def api_to_master_topic_mapper(api: str, body: dict = None, http_method: HttpMethod = HttpMethod.GET, headers: dict = None, timeout: int = 10): mrb: MqttRestBridge = MqttRestBridge() api: str = api.strip("/") session_uuid: str = __create_uuid() topic: str = "/".join([ 'master', 'unicast', mrb.global_uuid, session_uuid, MessageType.REQUEST.value ]) publish_request(api, body, headers, http_method, topic) start_time: float = time.time() while True: if time.time() - start_time <= timeout: sleep(0.01) response: Response = Store().get(session_uuid) if response: return response else: return Response( error=True, error_message= f'Master request timeout, exceed the time {timeout} secs', status_code=408)
def run(): setting: AppSetting = current_app.config[AppSetting.FLASK_KEY] create_internal_token(setting) if setting.mqtt_rest_bridge_setting.enabled: MqttRestBridge(port=setting.port, mqtt_setting=setting.mqtt_rest_bridge_setting, callback=Background.sync_on_start).start() if setting.mqtt_rest_bridge_setting.master: from src.discover.remote_device_registry import RemoteDeviceRegistry gevent.spawn(RemoteDeviceRegistry().register, setting) from src.system.services.restart_job import RestartJob FlaskThread(target=RestartJob().setup, daemon=True).start()
def request(self): from mrb.brige import MqttRestBridge bridge: MqttRestBridge = MqttRestBridge() request_url: str = 'http://0.0.0.0:{}/{}'.format(bridge.port, self.api) try: content_type: str = self.headers.get('Content-Type', '') if self.headers else "" if 'multipart/form-data' in content_type: return Response( error=True, status_code=501, error_message=str( "We don't have the multipart/form-data support yet!")) else: resp = requests.request(self.http_method, request_url, json=self.body, headers=self.headers, params={'bridge': True}) status_code: int = resp.status_code if resp.headers['Content-Type'] == "application/json": content = resp.json() if resp.text else {} else: content = resp.text error: bool = False error_message: str = '' if status_code not in range(200, 300): error = True error_message = content.get('message', '') if isinstance( content, dict) else content headers = resp.raw.headers.items() headers.append(["Content-Type", "application/json"]) return Response(status_code=status_code, headers=headers, error=error, error_message=error_message) else: headers = resp.raw.headers.items() return Response(content, status_code, headers, resp.headers.get('content-type'), error, error_message) except Exception as e: return Response(error=True, error_message=str(e))
def get(self): up_time = _get_up_time() up_min = up_time / 60 up_min = "{:.2f}".format(up_min) up_hour = up_time / 3600 up_hour = "{:.2f}".format(up_hour) setting: AppSetting = current_app.config[AppSetting.FLASK_KEY] deployment_mode = 'production' if setting.prod else 'development' return { 'version': get_version(), 'up_time_date': up_time_date, 'up_min': up_min, 'up_hour': up_hour, 'deployment_mode': deployment_mode, 'public_ip': _get_public_ip(), 'mqtt_rest_bridge_listener': { 'enabled': setting.mqtt_rest_bridge_setting.enabled, 'master': setting.mqtt_rest_bridge_setting.master, 'status': MqttRestBridge.status() } }
def slave_proxy_handler(_): url_parts = request.full_path.split("/") if len(url_parts) <= 2: abort(404) del url_parts[0] del url_parts[0] url: str = "/".join(url_parts) timeout: str = request.args.get('timeout') numeric_timeout: int = int(timeout) if timeout and timeout.isnumeric( ) else MqttRestBridge().mqtt_setting.timeout response: MessageResponse = api_to_master_topic_mapper( api=url, body=request.get_json(), http_method=HttpMethod[request.method.upper()], timeout=numeric_timeout) if response.error: return Response(json.dumps({'message': response.error_message}), response.status_code, response.headers) else: return Response( json.dumps(response.content).encode('utf-8'), response.status_code, response.headers)
def slaves_proxy_handler(_): url_parts = request.full_path.split("/") del url_parts[0] del url_parts[0] del url_parts[0] url = "/".join(url_parts) timeout: str = request.args.get('timeout') numeric_timeout: int = int(timeout) if timeout and timeout.isnumeric( ) else MqttRestBridge().mqtt_setting.timeout RemoteDeviceRegistry().sem.acquire() response: MessageResponse = api_to_slaves_broadcast_topic_mapper( api=url, body=request.get_json(), http_method=HttpMethod[request.method.upper()], timeout=numeric_timeout) RemoteDeviceRegistry().sem.release() if response.error: return Response(json.dumps({'message': response.error_message}), response.status_code, response.headers) else: return Response( json.dumps(response.content).encode('utf-8'), response.status_code, response.headers)
def slave_proxy_handler(_): url_parts = request.full_path.split("/") if len(url_parts) <= 3: abort(404) del url_parts[0] del url_parts[0] slave_global_uuid: str = url_parts[0] del url_parts[0] url: str = "/".join(url_parts) if slave_global_uuid not in RemoteDeviceRegistry().devices: return { "message": f"Slave with global_uuid {slave_global_uuid} is not active!" }, 404 timeout: str = request.args.get('timeout') numeric_timeout: int = int(timeout) if timeout and timeout.isnumeric( ) else MqttRestBridge().mqtt_setting.timeout response: MessageResponse = api_to_slave_topic_mapper( slave_global_uuid=slave_global_uuid, api=url, body=request.get_json(), http_method=HttpMethod[request.method.upper()], timeout=numeric_timeout, headers={k: v for k, v in request.headers.items()}, ) if response.error: return Response(json.dumps({'message': response.error_message}), response.status_code, response.headers) elif 'application/zip' in response.content_type: return Response(str.encode(response.content), response.status_code, response.headers) else: return Response( json.dumps(response.content).encode('utf-8'), response.status_code, response.headers)
def slaves_proxy_handler(_): url_parts = request.full_path.split("/") del url_parts[0] del url_parts[0] del url_parts[0] url = "/".join(url_parts) if request.args.get("slave_devices", None): available_inserted_devices_global_uuids: List[str] = request.args[ 'slave_devices'].split(",") else: available_inserted_devices_global_uuids: List[ str] = RemoteDeviceRegistry( ).available_inserted_devices_global_uuids timeout: str = request.args.get('timeout') numeric_timeout: int = int(timeout) if timeout and timeout.isnumeric( ) else MqttRestBridge().mqtt_setting.timeout if available_inserted_devices_global_uuids: RemoteDeviceRegistry().sem.acquire() response: MessageResponse = api_to_slaves_multicast_topic_mapper( slaves_global_uuids=available_inserted_devices_global_uuids, api=url, body=request.get_json(), http_method=HttpMethod[request.method.upper()], timeout=numeric_timeout) RemoteDeviceRegistry().sem.release() if response.error: return Response(json.dumps({'message': response.error_message}), response.status_code, response.headers) else: return Response( json.dumps(response.content).encode('utf-8'), response.status_code, response.headers) return { "message": "Registered devices are not available or haven't registered yet!" }, 404
def _mqtt_to_rest_mapper_process(message): master: bool = False topic = message.topic.split('/') if topic[0] == 'master': master = True if topic[1] == 'broadcast': slave_global_uuid: str = topic[2] session_uuid: str = topic[3] response: Response = Response().reload(json.loads(message.payload)) StoreBroadcast().append(slave_global_uuid, session_uuid, response) return else: slave_global_uuid: str = topic[2] session_uuid: str = topic[3] response: Response = Response().reload(json.loads(message.payload)) if topic[1] == 'multicast': StoreMulticast().append(slave_global_uuid, session_uuid, response) return message_type: str = topic[4] else: if topic[0] == 'broadcast': session_uuid: str = topic[1] serialize_response: str = request_api(message) reply_topic: str = '/'.join([ 'master', 'broadcast', MqttRestBridge().global_uuid, session_uuid ]) from mrb.mqtt import MqttClient MqttClient().publish_value(reply_topic, serialize_response) return else: slave_global_uuid: str = topic[1] session_uuid: str = topic[2] if topic[0] == 'multicast': serialize_response: str = request_api(message) reply_topic: str = "/".join( ['master', 'multicast', slave_global_uuid, session_uuid]) logger.debug(f'Reply topic: {reply_topic}') from mrb.mqtt import MqttClient MqttClient().publish_value(reply_topic, serialize_response) return message_type: str = topic[3] if message_type == MessageType.REQUEST.value: serialize_response: str = request_api(message) if master: reply_topic: str = "/".join([ 'unicast', slave_global_uuid, session_uuid, MessageType.RESPONSE.value ]) else: reply_topic: str = "/".join([ 'master', 'unicast', slave_global_uuid, session_uuid, MessageType.RESPONSE.value ]) logger.debug(f'Reply topic: {reply_topic}') from mrb.mqtt import MqttClient MqttClient().publish_value(reply_topic, serialize_response) if message_type == MessageType.RESPONSE.value: logger.debug(f'Response payload: {message.payload}') response: Response = Response().reload(json.loads(message.payload)) Store().add(session_uuid, response)
from mrb.brige import MqttRestBridge from mrb.setting import MqttSetting def callback(): print('callback...') if __name__ == '__main__': bridge = MqttRestBridge(port=8080, identifier=f'identifier', prod=True, mqtt_setting=MqttSetting(), callback=callback) bridge.start(False)