kopia lustrzana https://github.com/OpenDroneMap/WebODM
Added ability to handle non-json erroneous responses from API calls, modified readme, new screenshot
rodzic
37b54e634d
commit
1b13fdccef
|
@ -2,10 +2,12 @@
|
|||
|
||||
[](https://travis-ci.org/OpenDroneMap/WebODM)
|
||||
|
||||
A free, user-friendly application and API for drone image processing.
|
||||
A free, user-friendly, extendable application and API for drone image processing.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
If you know Python, web technologies (JS, HTML, CSS, etc.) or both, make a fork, contribute something that interests you, and make a pull request! All ideas are considered and people of all skill levels are welcome.
|
||||
|
||||
## Getting Started
|
||||
|
|
|
@ -11,7 +11,10 @@ from nodeodm import status_codes
|
|||
import random
|
||||
|
||||
logger = logging.getLogger('app.logger')
|
||||
scheduler = BackgroundScheduler()
|
||||
scheduler = BackgroundScheduler({
|
||||
'apscheduler.job_defaults.coalesce': 'false',
|
||||
'apscheduler.job_defaults.max_instances': '3',
|
||||
})
|
||||
|
||||
def background(func):
|
||||
"""
|
||||
|
|
|
@ -8,6 +8,7 @@ import json
|
|||
import os
|
||||
from urllib.parse import urlunparse
|
||||
|
||||
|
||||
class ApiClient:
|
||||
def __init__(self, host, port):
|
||||
self.host = host
|
||||
|
@ -55,10 +56,9 @@ class ApiClient:
|
|||
:param options: options to be used for processing ([{'name': optionName, 'value': optionValue}, ...])
|
||||
:return: UUID or error
|
||||
"""
|
||||
|
||||
files = [('images',
|
||||
(os.path.basename(image), open(image, 'rb'), (mimetypes.guess_type(image)[0] or "image/jpg"))
|
||||
) for image in images]
|
||||
return requests.post(self.url("/task/new"),
|
||||
files=files,
|
||||
data={'name': name, 'options': json.dumps(options)}).json()
|
||||
data={'name': name, 'options': json.dumps(options)}).json()
|
||||
|
|
|
@ -10,6 +10,19 @@ from django.db.models import signals
|
|||
from requests.exceptions import ConnectionError
|
||||
from .exceptions import ProcessingException
|
||||
|
||||
def api(func):
|
||||
"""
|
||||
Catches JSON decoding errors that might happen when the server
|
||||
answers unexpectedly
|
||||
"""
|
||||
def wrapper(*args,**kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except json.decoder.JSONDecodeError as e:
|
||||
raise ProcessingException(str(e))
|
||||
|
||||
return wrapper
|
||||
|
||||
class ProcessingNode(models.Model):
|
||||
hostname = models.CharField(max_length=255, help_text="Hostname where the node is located (can be an internal hostname as well)")
|
||||
port = models.PositiveIntegerField(help_text="Port that connects to the node's API")
|
||||
|
@ -21,6 +34,7 @@ class ProcessingNode(models.Model):
|
|||
def __str__(self):
|
||||
return '{}:{}'.format(self.hostname, self.port)
|
||||
|
||||
@api
|
||||
def update_node_info(self):
|
||||
"""
|
||||
Retrieves information and options from the node API
|
||||
|
@ -52,6 +66,7 @@ class ProcessingNode(models.Model):
|
|||
kwargs = dict(indent=4, separators=(',', ": ")) if pretty else dict()
|
||||
return json.dumps(self.available_options, **kwargs)
|
||||
|
||||
@api
|
||||
def process_new_task(self, images, name=None, options=[]):
|
||||
"""
|
||||
Sends a set of images (and optional GCP file) via the API
|
||||
|
@ -72,6 +87,7 @@ class ProcessingNode(models.Model):
|
|||
elif result['error']:
|
||||
raise ProcessingException(result['error'])
|
||||
|
||||
@api
|
||||
def get_task_info(self, uuid):
|
||||
"""
|
||||
Gets information about this task, such as name, creation date,
|
||||
|
@ -87,6 +103,7 @@ class ProcessingNode(models.Model):
|
|||
else:
|
||||
raise ProcessingException("Unknown result from task info: {}".format(result))
|
||||
|
||||
@api
|
||||
def get_task_console_output(self, uuid, line):
|
||||
"""
|
||||
Retrieves the console output of the OpenDroneMap's process.
|
||||
|
@ -101,6 +118,7 @@ class ProcessingNode(models.Model):
|
|||
else:
|
||||
raise ProcessingException("Unknown response for console output: {}".format(result))
|
||||
|
||||
@api
|
||||
def cancel_task(self, uuid):
|
||||
"""
|
||||
Cancels a task (stops its execution, or prevents it from being executed)
|
||||
|
@ -108,6 +126,7 @@ class ProcessingNode(models.Model):
|
|||
api_client = self.api_client()
|
||||
return self.handle_generic_post_response(api_client.task_cancel(uuid))
|
||||
|
||||
@api
|
||||
def remove_task(self, uuid):
|
||||
"""
|
||||
Removes a task and deletes all of its assets
|
||||
|
@ -115,6 +134,7 @@ class ProcessingNode(models.Model):
|
|||
api_client = self.api_client()
|
||||
return self.handle_generic_post_response(api_client.task_remove(uuid))
|
||||
|
||||
@api
|
||||
def download_task_asset(self, uuid, asset):
|
||||
"""
|
||||
Downloads a task asset
|
||||
|
@ -126,6 +146,7 @@ class ProcessingNode(models.Model):
|
|||
else:
|
||||
return res
|
||||
|
||||
@api
|
||||
def restart_task(self, uuid):
|
||||
"""
|
||||
Restarts a task that was previously canceled or that had failed to process
|
||||
|
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 104 KiB |
Ładowanie…
Reference in New Issue