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 @@
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/OpenDroneMap/WebODM.svg?branch=master)](https://travis-ci.org/OpenDroneMap/WebODM)
|
[![Build Status](https://travis-ci.org/OpenDroneMap/WebODM.svg?branch=master)](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.
|
||||||
|
|
||||||
![Alt text](/screenshots/ui-mockup.png?raw=true "WebODM")
|
![Alt text](/screenshots/ui-mockup.png?raw=true "WebODM")
|
||||||
|
|
||||||
|
![Alt text](/screenshots/dashboard.png?raw=true "Dashboard")
|
||||||
|
|
||||||
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.
|
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
|
## Getting Started
|
||||||
|
|
|
@ -11,7 +11,10 @@ from nodeodm import status_codes
|
||||||
import random
|
import random
|
||||||
|
|
||||||
logger = logging.getLogger('app.logger')
|
logger = logging.getLogger('app.logger')
|
||||||
scheduler = BackgroundScheduler()
|
scheduler = BackgroundScheduler({
|
||||||
|
'apscheduler.job_defaults.coalesce': 'false',
|
||||||
|
'apscheduler.job_defaults.max_instances': '3',
|
||||||
|
})
|
||||||
|
|
||||||
def background(func):
|
def background(func):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -8,6 +8,7 @@ import json
|
||||||
import os
|
import os
|
||||||
from urllib.parse import urlunparse
|
from urllib.parse import urlunparse
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
class ApiClient:
|
||||||
def __init__(self, host, port):
|
def __init__(self, host, port):
|
||||||
self.host = host
|
self.host = host
|
||||||
|
@ -55,7 +56,6 @@ class ApiClient:
|
||||||
:param options: options to be used for processing ([{'name': optionName, 'value': optionValue}, ...])
|
:param options: options to be used for processing ([{'name': optionName, 'value': optionValue}, ...])
|
||||||
:return: UUID or error
|
:return: UUID or error
|
||||||
"""
|
"""
|
||||||
|
|
||||||
files = [('images',
|
files = [('images',
|
||||||
(os.path.basename(image), open(image, 'rb'), (mimetypes.guess_type(image)[0] or "image/jpg"))
|
(os.path.basename(image), open(image, 'rb'), (mimetypes.guess_type(image)[0] or "image/jpg"))
|
||||||
) for image in images]
|
) for image in images]
|
||||||
|
|
|
@ -10,6 +10,19 @@ from django.db.models import signals
|
||||||
from requests.exceptions import ConnectionError
|
from requests.exceptions import ConnectionError
|
||||||
from .exceptions import ProcessingException
|
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):
|
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)")
|
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")
|
port = models.PositiveIntegerField(help_text="Port that connects to the node's API")
|
||||||
|
@ -21,6 +34,7 @@ class ProcessingNode(models.Model):
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return '{}:{}'.format(self.hostname, self.port)
|
return '{}:{}'.format(self.hostname, self.port)
|
||||||
|
|
||||||
|
@api
|
||||||
def update_node_info(self):
|
def update_node_info(self):
|
||||||
"""
|
"""
|
||||||
Retrieves information and options from the node API
|
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()
|
kwargs = dict(indent=4, separators=(',', ": ")) if pretty else dict()
|
||||||
return json.dumps(self.available_options, **kwargs)
|
return json.dumps(self.available_options, **kwargs)
|
||||||
|
|
||||||
|
@api
|
||||||
def process_new_task(self, images, name=None, options=[]):
|
def process_new_task(self, images, name=None, options=[]):
|
||||||
"""
|
"""
|
||||||
Sends a set of images (and optional GCP file) via the API
|
Sends a set of images (and optional GCP file) via the API
|
||||||
|
@ -72,6 +87,7 @@ class ProcessingNode(models.Model):
|
||||||
elif result['error']:
|
elif result['error']:
|
||||||
raise ProcessingException(result['error'])
|
raise ProcessingException(result['error'])
|
||||||
|
|
||||||
|
@api
|
||||||
def get_task_info(self, uuid):
|
def get_task_info(self, uuid):
|
||||||
"""
|
"""
|
||||||
Gets information about this task, such as name, creation date,
|
Gets information about this task, such as name, creation date,
|
||||||
|
@ -87,6 +103,7 @@ class ProcessingNode(models.Model):
|
||||||
else:
|
else:
|
||||||
raise ProcessingException("Unknown result from task info: {}".format(result))
|
raise ProcessingException("Unknown result from task info: {}".format(result))
|
||||||
|
|
||||||
|
@api
|
||||||
def get_task_console_output(self, uuid, line):
|
def get_task_console_output(self, uuid, line):
|
||||||
"""
|
"""
|
||||||
Retrieves the console output of the OpenDroneMap's process.
|
Retrieves the console output of the OpenDroneMap's process.
|
||||||
|
@ -101,6 +118,7 @@ class ProcessingNode(models.Model):
|
||||||
else:
|
else:
|
||||||
raise ProcessingException("Unknown response for console output: {}".format(result))
|
raise ProcessingException("Unknown response for console output: {}".format(result))
|
||||||
|
|
||||||
|
@api
|
||||||
def cancel_task(self, uuid):
|
def cancel_task(self, uuid):
|
||||||
"""
|
"""
|
||||||
Cancels a task (stops its execution, or prevents it from being executed)
|
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()
|
api_client = self.api_client()
|
||||||
return self.handle_generic_post_response(api_client.task_cancel(uuid))
|
return self.handle_generic_post_response(api_client.task_cancel(uuid))
|
||||||
|
|
||||||
|
@api
|
||||||
def remove_task(self, uuid):
|
def remove_task(self, uuid):
|
||||||
"""
|
"""
|
||||||
Removes a task and deletes all of its assets
|
Removes a task and deletes all of its assets
|
||||||
|
@ -115,6 +134,7 @@ class ProcessingNode(models.Model):
|
||||||
api_client = self.api_client()
|
api_client = self.api_client()
|
||||||
return self.handle_generic_post_response(api_client.task_remove(uuid))
|
return self.handle_generic_post_response(api_client.task_remove(uuid))
|
||||||
|
|
||||||
|
@api
|
||||||
def download_task_asset(self, uuid, asset):
|
def download_task_asset(self, uuid, asset):
|
||||||
"""
|
"""
|
||||||
Downloads a task asset
|
Downloads a task asset
|
||||||
|
@ -126,6 +146,7 @@ class ProcessingNode(models.Model):
|
||||||
else:
|
else:
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
@api
|
||||||
def restart_task(self, uuid):
|
def restart_task(self, uuid):
|
||||||
"""
|
"""
|
||||||
Restarts a task that was previously canceled or that had failed to process
|
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