async def make_timelapse_movie(local_config, framerate, interval, group) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) msg = 'making timelapse movie for group "%(group)s" of remote camera %(id)s ' \ 'with rate %(framerate)s/%(int)s on %(url)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'framerate': framerate, 'int': interval, 'url': pretty_camera_url(local_config)} logging.debug(msg) path += '/picture/%(id)s/timelapse/%(group)s/?interval=%(int)s&framerate=%(framerate)s' % { 'id': camera_id, 'int': interval, 'framerate': framerate, 'group': group } request = _make_request(scheme, host, port, username, password, path, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT) response = await _send_request(request) if response.error: msg = 'failed to make timelapse movie for group "%(group)s" of remote camera %(id)s ' \ 'with rate %(framerate)s/%(int)s on %(url)s: %(msg)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'url': pretty_camera_url(local_config), 'int': interval, 'framerate': framerate, 'msg': utils.pretty_http_error(response)} logging.error(msg) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) try: response = json.loads(response.body) except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config), 'msg': str(e) }) return utils.CommonExternalResponse(error=str(e)) else: return utils.CommonExternalResponse(result=response)
async def get_current_picture(local_config, width, height) -> utils.GetCurrentPictureResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'getting current picture for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) query = {} if width: query['width'] = str(width) if height: query['height'] = str(height) p = path + '/picture/%(id)s/current/' % {'id': camera_id} request = _make_request(scheme, host, port, username, password, p, query=query) response = await _send_request(request) cookies = utils.parse_cookies(response.headers.get_list('Set-Cookie')) motion_detected = cookies.get('motion_detected_' + str(camera_id)) == 'true' capture_fps = cookies.get('capture_fps_' + str(camera_id)) capture_fps = float(capture_fps) if capture_fps else 0 monitor_info = cookies.get('monitor_info_' + str(camera_id)) if response.error: logging.error( 'failed to get current picture for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.GetCurrentPictureResponse( error=utils.pretty_http_error(response)) return utils.GetCurrentPictureResponse(motion_detected=motion_detected, capture_fps=capture_fps, monitor_info=monitor_info, picture=response.body)
async def make_zipped_content(local_config, media_type, group) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'preparing zip file for group "%(group)s" of remote camera %(id)s on %(url)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'url': pretty_camera_url(local_config) }) prepare_path = path + '/%(media_type)s/%(id)s/zipped/%(group)s/' % { 'media_type': media_type, 'id': camera_id, 'group': group } # timeout here is 100 times larger than usual - we expect a big delay request = _make_request(scheme, host, port, username, password, prepare_path, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT) response = await _send_request(request) if response.error: msg = 'failed to prepare zip file for group "%(group)s" ' \ 'of remote camera %(id)s on %(url)s: %(msg)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response)} logging.error(msg) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) try: key = json.loads(response.body)['key'] except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config), 'msg': str(e) }) return utils.CommonExternalResponse(error=str(e)) else: return utils.CommonExternalResponse(result={'key': key})
async def list_media(local_config, media_type, prefix) -> utils.ListMediaResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug('getting media list for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) query = {} if prefix is not None: query['prefix'] = prefix # timeout here is 10 times larger than usual - we expect a big delay when fetching the media list p = path + '/%(media_type)s/%(id)s/list/' % { 'id': camera_id, 'media_type': media_type } request = _make_request(scheme, host, port, username, password, p, query=query, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT) response = await _send_request(request) if response.error: logging.error( 'failed to get media list for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.ListMediaResponse(error=utils.pretty_http_error(response)) try: response = json.loads(response.body) except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config), 'msg': str(e) }) return utils.ListMediaResponse(error=str(e)) return utils.ListMediaResponse(media_list=response)
async def get_media_preview(local_config, filename, media_type, width, height) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'getting file preview for %(filename)s of remote camera %(id)s on %(url)s' % { 'filename': filename, 'id': camera_id, 'url': pretty_camera_url(local_config) }) path += '/%(media_type)s/%(id)s/preview/%(filename)s' % { 'media_type': media_type, 'id': camera_id, 'filename': filename } query = {} if width: query['width'] = str(width) if height: query['height'] = str(height) request = _make_request(scheme, host, port, username, password, path, query=query) response = await _send_request(request) if response.error: logging.error( 'failed to get file preview for %(filename)s of remote camera %(id)s on %(url)s: %(msg)s' % { 'filename': filename, 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) return utils.CommonExternalResponse(result=response.body)
async def get_motion_detection(camera_id) -> utils.GetMotionDetectionResult: motion_camera_id = camera_id_to_motion_camera_id(camera_id) if motion_camera_id is None: error = 'could not find motion camera id for camera with id %s' % camera_id logging.error(error) return utils.GetMotionDetectionResult(None, error=error) url = 'http://127.0.0.1:%(port)s/%(id)s/detection/status' % { 'port': settings.MOTION_CONTROL_PORT, 'id': motion_camera_id } request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT) resp = await AsyncHTTPClient().fetch(request) if resp.error: return utils.GetMotionDetectionResult( None, error=utils.pretty_http_error(resp)) resp_body = resp.body.decode('utf-8') enabled = bool(resp_body.count('active')) logging.debug('motion detection is %(what)s for camera with id %(id)s' % { 'what': ['disabled', 'enabled'][enabled], 'id': camera_id }) return utils.GetMotionDetectionResult(enabled, None)
async def take_snapshot(camera_id): motion_camera_id = camera_id_to_motion_camera_id(camera_id) if motion_camera_id is None: return logging.error( 'could not find motion camera id for camera with id %s' % camera_id) logging.debug('taking snapshot for camera with id %(id)s' % {'id': camera_id}) url = 'http://127.0.0.1:%(port)s/%(id)s/action/snapshot' % { 'port': settings.MOTION_CONTROL_PORT, 'id': motion_camera_id } request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT) resp = await AsyncHTTPClient().fetch(request) if resp.error: logging.error( 'failed to take snapshot for camera with id %(id)s: %(msg)s' % { 'id': camera_id, 'msg': utils.pretty_http_error(resp) }) else: logging.debug('successfully took snapshot for camera with id %(id)s' % {'id': camera_id})
async def get_zipped_content(local_config, media_type, key, group) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug('downloading zip file for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) p = path + '/%(media_type)s/%(id)s/zipped/%(group)s/?key=%(key)s' % { 'media_type': media_type, 'group': group, 'id': camera_id, 'key': key } request = _make_request(scheme, host, port, username, password, p, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT) response = await _send_request(request) if response.error: logging.error( 'failed to download zip file for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) return utils.CommonExternalResponse( result={ 'data': response.body, 'content_type': response.headers.get('Content-Type'), 'content_disposition': response.headers.get('Content-Disposition') })
async def check_timelapse_movie(local_config, group) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'checking timelapse movie status for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) p = path + '/picture/%(id)s/timelapse/%(group)s/?check=true' % { 'id': camera_id, 'group': group } request = _make_request(scheme, host, port, username, password, p) response = await _send_request(request) if response.error: logging.error( 'failed to check timelapse movie status for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) try: response = json.loads(response.body) except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config), 'msg': str(e) }) return utils.CommonExternalResponse(error=str(e)) else: return utils.CommonExternalResponse(result=response)
async def list_cameras(local_config) -> utils.GetCamerasResponse: scheme, host, port, username, password, path, _ = _remote_params( local_config) logging.debug('listing remote cameras on %(url)s' % {'url': pretty_camera_url(local_config, camera=False)}) request = _make_request(scheme, host, port, username, password, path + '/config/list/') response = await _send_request(request) if response.error: logging.error( 'failed to list remote cameras on %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config, camera=False), 'msg': utils.pretty_http_error(response) }) return utils.GetCamerasResponse(None, utils.pretty_http_error(response)) try: response = json.loads(response.body) except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config, camera=False), 'msg': str(e) }) return utils.GetCamerasResponse(None, str(e)) else: cameras = response['cameras'] # filter out simple mjpeg cameras cameras = [ make_camera_response(c) for c in cameras if c['proto'] != 'mjpeg' and c.get('enabled') ] return utils.GetCamerasResponse(cameras, None)
async def del_media_group(local_config, group, media_type) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'deleting group "%(group)s" of remote camera %(id)s on %(url)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'url': pretty_camera_url(local_config) }) path += '/%(media_type)s/%(id)s/delete_all/%(group)s/' % { 'media_type': media_type, 'id': camera_id, 'group': group } request = _make_request(scheme, host, port, username, password, path, method='POST', data='{}', timeout=settings.REMOTE_REQUEST_TIMEOUT, content_type='application/json') response = await _send_request(request) if response.error: logging.error( 'failed to delete group "%(group)s" of remote camera %(id)s on %(url)s: %(msg)s' % { 'group': group or 'ungrouped', 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) return utils.CommonExternalResponse()
async def set_config(local_config, ui_config) -> Union[str, None]: scheme = local_config.get('@scheme', local_config.get('scheme')) host = local_config.get('@host', local_config.get('host')) port = local_config.get('@port', local_config.get('port')) username = local_config.get('@username', local_config.get('username')) password = local_config.get('@password', local_config.get('password')) path = local_config.get('@path', local_config.get('path')) or '' camera_id = local_config.get('@remote_camera_id', local_config.get('remote_camera_id')) logging.debug('setting config for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) ui_config = json.dumps(ui_config) p = path + '/config/%(id)s/set/' % {'id': camera_id} request = _make_request(scheme, host, port, username, password, p, method='POST', data=ui_config, content_type='application/json') response = await _send_request(request) result = None if response.error: logging.error( 'failed to set config for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) result = utils.pretty_http_error(response) return result
async def get_config(local_config) -> utils.GetConfigResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug('getting config for remote camera %(id)s on %(url)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config) }) request = _make_request(scheme, host, port, username, password, path + '/config/%(id)s/get/' % {'id': camera_id}) response = await _send_request(request) if response.error: logging.error( 'failed to get config for remote camera %(id)s on %(url)s: %(msg)s' % { 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.GetConfigResponse(None, error=utils.pretty_http_error(response)) try: response = json.loads(response.body) except Exception as e: logging.error('failed to decode json answer from %(url)s: %(msg)s' % { 'url': pretty_camera_url(local_config), 'msg': str(e) }) return utils.GetConfigResponse(None, error=str(e)) else: response['host'] = host response['port'] = port return utils.GetConfigResponse(remote_ui_config=response, error=None)
async def get_media_content(local_config, filename, media_type) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) logging.debug( 'downloading file %(filename)s of remote camera %(id)s on %(url)s' % { 'filename': filename, 'id': camera_id, 'url': pretty_camera_url(local_config) }) path += '/%(media_type)s/%(id)s/download/%(filename)s' % { 'media_type': media_type, 'id': camera_id, 'filename': filename } # timeout here is 10 times larger than usual - we expect a big delay when fetching the media list request = _make_request(scheme, host, port, username, password, path, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT) response = await _send_request(request) if response.error: logging.error( 'failed to download file %(filename)s of remote camera %(id)s on %(url)s: %(msg)s' % { 'filename': filename, 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( error=utils.pretty_http_error(response)) return utils.CommonExternalResponse(result=response.body)
def on_response(response: HTTPResponse): if not called[0]: if response.code == 401 and auth_modes and url_obj.username: status_2xx[0] = False do_request() else: called[0] = True error = pretty_http_error( response ) if response.error else 'not a supported network camera' future.set_result(GetCamerasResponse(None, error=error))
async def exec_action(local_config, action) -> utils.CommonExternalResponse: 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') response = await _send_request(request) 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 utils.CommonExternalResponse( error=utils.pretty_http_error(response)) return utils.CommonExternalResponse()
async def test(local_config, data) -> utils.CommonExternalResponse: scheme, host, port, username, password, path, camera_id = _remote_params( local_config) what = data['what'] logging.debug('testing %(what)s on remote camera %(id)s, on %(url)s' % { 'what': what, 'id': camera_id, 'url': pretty_camera_url(local_config) }) data = json.dumps(data) p = path + '/config/%(id)s/test/' % {'id': camera_id} request = _make_request(scheme, host, port, username, password, p, method='POST', data=data, content_type='application/json') response = await _send_request(request) if response.error: logging.error( 'failed to test %(what)s on remote camera %(id)s, on %(url)s: %(msg)s' % { 'what': what, 'id': camera_id, 'url': pretty_camera_url(local_config), 'msg': utils.pretty_http_error(response) }) return utils.CommonExternalResponse( None, error=utils.pretty_http_error(response)) return utils.CommonExternalResponse( None, None) # it will never return result = True, what the point?
async def set_motion_detection(camera_id, enabled): motion_camera_id = camera_id_to_motion_camera_id(camera_id) if motion_camera_id is None: return logging.error( 'could not find motion camera id for camera with id %s' % camera_id) if not enabled: _motion_detected[camera_id] = False logging.debug('%(what)s motion detection for camera with id %(id)s' % { 'what': ['disabling', 'enabling'][enabled], 'id': camera_id }) url = 'http://127.0.0.1:%(port)s/%(id)s/detection/%(enabled)s' % { 'port': settings.MOTION_CONTROL_PORT, 'id': motion_camera_id, 'enabled': ['pause', 'start'][enabled] } request = HTTPRequest(url, connect_timeout=_MOTION_CONTROL_TIMEOUT, request_timeout=_MOTION_CONTROL_TIMEOUT) resp = await AsyncHTTPClient().fetch(request) if resp.error: logging.error( 'failed to %(what)s motion detection for camera with id %(id)s: %(msg)s' % { 'what': ['disable', 'enable'][enabled], 'id': camera_id, 'msg': utils.pretty_http_error(resp) }) else: logging.debug( 'successfully %(what)s motion detection for camera with id %(id)s' % { 'what': ['disabled', 'enabled'][enabled], 'id': camera_id })