From: Calin Crisan Date: Sun, 13 Dec 2015 17:49:34 +0000 (+0200) Subject: a few remote camera management fixes X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=d149f92ea0e0b2dcbfa92f3a596da1be86405597;p=motioneye-debian a few remote camera management fixes --- diff --git a/motioneye/handlers.py b/motioneye/handlers.py index f622f0a..d3763cd 100644 --- a/motioneye/handlers.py +++ b/motioneye/handlers.py @@ -1450,6 +1450,17 @@ class ActionHandler(BaseHandler): if camera_id not in config.get_camera_ids(): raise HTTPError(404, 'no such camera') + local_config = config.get_camera(camera_id) + if utils.remote_camera(local_config): + def on_response(error=None): + if error: + return self.finish_json({'error': 'Failed to execute action on remote camera at %(url)s: %(msg)s.' % { + 'url': remote.pretty_camera_url(local_config), 'msg': error}}) + + self.finish_json() + + return remote.exec_action(local_config, action, on_response) + if action == 'snapshot': logging.debug('executing snapshot action for camera with id %s' % camera_id) return self.snapshot() diff --git a/motioneye/remote.py b/motioneye/remote.py index d3831df..0749282 100644 --- a/motioneye/remote.py +++ b/motioneye/remote.py @@ -310,17 +310,11 @@ def get_current_picture(local_config, width, height, callback): query=query) def on_response(response): - motion_detected = False - - cookies = response.headers.get('Set-Cookie') - if cookies: - cookies = cookies.split(';') - cookies = [[i.strip() for i in c.split('=')] for c in cookies] - cookies = dict([c for c in cookies if len(c) == 2]) - motion_detected = cookies.get('motion_detected_' + str(camera_id)) == 'true' - fps = cookies.get('capture_fps_' + str(camera_id)) - fps = float(fps) if fps else 0 - + cookies = utils.parse_cookies(response.headers.get_list('Set-Cookie')) + motion_detected = cookies.get('motion_detected_' + str(camera_id)) == 'true' + fps = cookies.get('capture_fps_' + str(camera_id)) + fps = float(fps) if fps else 0 + if response.error: logging.error('failed to get current picture for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, @@ -708,3 +702,35 @@ def del_media_group(local_config, group, media_type, callback): http_client = AsyncHTTPClient() http_client.fetch(request, _callback_wrapper(on_response)) + + +def exec_action(local_config, action, callback): + scheme, host, port, username, password, path, camera_id = _remote_params(local_config) + + logging.debug('executing action "%(action)s" of remote camera %(id)s on %(url)s' % { + 'action': action, + 'id': camera_id, + 'url': pretty_camera_url(local_config)}) + + path += '/action/%(id)s/%(action)s/' % { + 'action': action, + 'id': camera_id} + + request = _make_request(scheme, host, port, username, password, path, + method='POST', data='{}', + timeout=settings.REMOTE_REQUEST_TIMEOUT, content_type='application/json') + + def on_response(response): + if response.error: + logging.error('failed to execute action "%(action)s" of remote camera %(id)s on %(url)s: %(msg)s' % { + 'action': action, + 'id': camera_id, + 'url': pretty_camera_url(local_config), + 'msg': utils.pretty_http_error(response)}) + + return callback(error=utils.pretty_http_error(response)) + + callback() + + http_client = AsyncHTTPClient() + http_client.fetch(request, _callback_wrapper(on_response)) diff --git a/motioneye/utils.py b/motioneye/utils.py index 27ae864..be7fd8f 100644 --- a/motioneye/utils.py +++ b/motioneye/utils.py @@ -41,6 +41,7 @@ except: _SIGNATURE_REGEX = re.compile('[^a-zA-Z0-9/?_.=&{}\[\]":, _-]') +_SPECIAL_COOKIE_NAMES = {'expires', 'domain', 'path', 'secure', 'httponly'} COMMON_RESOLUTIONS = [ @@ -585,6 +586,23 @@ def compute_signature(method, path, body, key): return hashlib.sha1('%s:%s:%s:%s' % (method, path, body or '', key)).hexdigest().lower() +def parse_cookies(cookies_headers): + parsed = {} + + for cookie in cookies_headers: + cookie = cookie.split(';') + for c in cookie: + (name, value) = c.split('=', 1) + name = name.strip() + value = value.strip() + + if name.lower() in _SPECIAL_COOKIE_NAMES: + continue + + parsed[name] = value + + return parsed + def build_basic_header(username, password): return 'Basic ' + base64.encodestring('%s:%s' % (username, password)).replace('\n', '')