def invoke_method_helper(method): direct_method = CloudToDeviceMethod(method_name=method.method_name, payload=method.serialize()) registry_manager = IoTHubRegistryManager(connection_string) payload = registry_manager.invoke_device_module_method(device_id, module_d, direct_method).payload if payload is not None and 'error' in payload: print(payload['error']) return None return payload
class GraphManager: def __init__(self, ioThubConnectionString, deviceId, moduleId, operationsApiVersion): self._iotHubConnStr = ioThubConnectionString self._deviceId = deviceId self._moduleId = moduleId self._apiVersion = operationsApiVersion self._registryManager = IoTHubRegistryManager(self._iotHubConnStr) def InvokeModuleMethod(self, methodName, payload): moduleMethod = CloudToDeviceMethod(method_name=methodName, payload=payload) return self._registryManager.invoke_device_module_method( self._deviceId, self._moduleId, moduleMethod) def GraphTopologySet(self, opParams): if opParams is None: logging.info('Operation parameters missing') raise Exception if opParams.get('topologyUrl') is not None: topologyJsonString = urlToText(opParams['topologyUrl']) elif opParams.get('topologyFile') is not None: from sys import platform if platform == "win32": #Windows fpath = 'file:///' + path.join( pathlib.Path(__file__).parent.absolute(), opParams['topologyFile']) else: #Linux or MacOS fpath = 'file://' + path.join( pathlib.Path(__file__).parent.absolute(), opParams['topologyFile']) topologyJsonString = urlToText(fpath) else: logging.info('Neither topologyUrl nor topologyFile specified') topologyJson = json.loads(topologyJsonString) return self.InvokeModuleMethod('GraphTopologySet', topologyJson) def GenericCall(self, methodName, opParams): if opParams is None: logging.info('Operation parameters missing') raise Exception opParams['@apiVersion'] = self._apiVersion return self.InvokeModuleMethod(methodName, opParams)
class IoTHubHandler: def __init__(self, iot_hub_connection_string): self.registry_manager = IoTHubRegistryManager(iot_hub_connection_string) async def send_message(self, message, device_id, module_id, method_name): payload = {"body": json.loads(message.data), "properties": message.custom_properties} module_method = CloudToDeviceMethod( method_name=method_name, payload=payload, response_timeout_in_seconds=30) print("Invoking message called") resp = self.registry_manager.invoke_device_module_method(device_id, module_id, module_method) if resp.payload is not None: print(json.dumps(resp.payload))
class ServiceHelperSync(object): def __init__(self): self._executor = ThreadPoolExecutor() self._registry_manager = IoTHubRegistryManager( iothub_connection_string) logger.info( "Creating EventHubConsumerClient with consumer_group = {}".format( eventhub_consumer_group)) self._eventhub_consumer_client = EventHubConsumerClient.from_connection_string( eventhub_connection_string, consumer_group=eventhub_consumer_group) self._eventhub_future = self._executor.submit(self._eventhub_thread) self.device_id = None self.module_id = None self.incoming_patch_queue = queue.Queue() self.cv = threading.Condition() self.incoming_eventhub_events = {} def set_identity(self, device_id, module_id): if device_id != self.device_id or module_id != self.module_id: self.device_id = device_id self.module_id = module_id self.incoming_patch_queue = queue.Queue() with self.cv: if self.incoming_eventhub_events: logger.warning( "Abandoning incoming events with IDs {}".format( str(list(self.incoming_eventhub_events.keys())))) self.incoming_eventhub_events = {} def set_desired_properties(self, desired_props): if self.module_id: self._registry_manager.update_module_twin( self.device_id, self.module_id, Twin(properties=TwinProperties(desired=desired_props)), "*", ) else: self._registry_manager.update_twin( self.device_id, Twin(properties=TwinProperties(desired=desired_props)), "*") def invoke_method( self, method_name, payload, connect_timeout_in_seconds=30, response_timeout_in_seconds=None, ): request = CloudToDeviceMethod( method_name=method_name, payload=payload, response_timeout_in_seconds=response_timeout_in_seconds, connect_timeout_in_seconds=connect_timeout_in_seconds, ) if self.module_id: response = self._registry_manager.invoke_device_module_method( self.device_id, self.module_id, request) else: response = self._registry_manager.invoke_device_method( self.device_id, request) return response def send_c2d(self, payload, properties): if self.module_id: raise TypeError("sending C2D to modules is not supported") self._registry_manager.send_c2d_message(self.device_id, payload, properties) def wait_for_eventhub_arrival(self, message_id, timeout=600): def get_event(inner_message_id): with self.cv: arrivals = self.incoming_eventhub_events # if message_id is not set, return any message if not inner_message_id and len(arrivals): id = list(arrivals.keys())[0] logger.info( "wait_for_eventhub_arrival(None) returning msgid={}". format(id)) else: id = inner_message_id if id and (id in arrivals): value = arrivals[id] del arrivals[id] return value else: return None if timeout: end_time = time.time() + timeout else: end_time = None with self.cv: while True: ev = get_event(message_id) if ev: return ev elif time.time() >= end_time: logger.warning( "timeout waiting for message with msgid={}".format( message_id)) return None elif end_time: self.cv.wait(timeout=end_time - time.time()) else: self.cv.wait() def get_next_reported_patch_arrival(self, block=True, timeout=20): try: return self.incoming_patch_queue.get(block=block, timeout=timeout) except queue.Empty: raise Exception( "reported patch did not arrive within {} seconds".format( timeout)) def shutdown(self): if self._eventhub_consumer_client: self._eventhub_consumer_client.close() def _convert_incoming_event(self, event): try: event_body = event.body_as_json() except TypeError: event_body = event.body_as_str() device_id = get_device_id_from_event(event) module_id = get_module_id_from_event(event) if get_message_source_from_event(event) == "twinChangeEvents": return copy.deepcopy(event_body.get("properties", {})) else: message = EventhubEvent() message.device_id = device_id message.module_id = module_id message.message_body = event_body if event.message.properties: message.properties = convert_binary_dict_to_string_dict( event.properties) message.content_type = event.message.properties.content_type.decode( "utf-8") message.system_properties = convert_binary_dict_to_string_dict( event.system_properties) return message def _store_eventhub_arrival(self, converted_event): message_id = converted_event.system_properties.get( "message-id", "no-message-id-{}".format(uuid.uuid4())) if message_id: with self.cv: self.incoming_eventhub_events[message_id] = converted_event self.cv.notify_all() def _store_patch_arrival(self, converted_event): self.incoming_patch_queue.put(converted_event) def _eventhub_thread(self): def on_error(partition_context, error): logger.error("EventHub on_error: {}".format( str(error) or type(error))) def on_partition_initialize(partition_context): logger.warning("EventHub on_partition_initialize") def on_partition_close(partition_context, reason): logger.warning("EventHub on_partition_close: {}".format(reason)) def on_event_batch(partition_context, events): try: for event in events: device_id = get_device_id_from_event(event) module_id = get_module_id_from_event(event) if device_id == self.device_id and module_id == self.module_id: converted_event = self._convert_incoming_event(event) if type(converted_event) == EventhubEvent: if "message-id" in converted_event.system_properties: logger.info( "Received event with msgid={}".format( converted_event. system_properties["message-id"])) else: logger.info( "Received event with no message id") else: logger.info( "Received {} for device {}, module {}".format( get_message_source_from_event(event), device_id, module_id, )) if isinstance(converted_event, EventhubEvent): self._store_eventhub_arrival(converted_event) else: self._store_patch_arrival(converted_event) except Exception: logger.error("Error on on_event_batch", exc_info=True) raise try: with self._eventhub_consumer_client: logger.info("Starting EventHub receive") self._eventhub_consumer_client.receive_batch( max_wait_time=2, on_event_batch=on_event_batch, on_error=on_error, on_partition_initialize=on_partition_initialize, on_partition_close=on_partition_close, ) except Exception: logger.error("_eventhub_thread exception", exc_info=True) raise
class ServiceHelperSync(object): def __init__(self): self._client_list = ClientList() self._executor = ThreadPoolExecutor() self._registry_manager = IoTHubRegistryManager( iothub_connection_string) self._digital_twin_client = DigitalTwinClient.from_connection_string( iothub_connection_string) self._eventhub_consumer_client = EventHubConsumerClient.from_connection_string( eventhub_connection_string, consumer_group=eventhub_consumer_group) self._eventhub_future = self._executor.submit(self._eventhub_thread) def start_watching(self, device_id, module_id): self._client_list.get_or_create(device_id, module_id) def stop_watching(self, device_id, module_id): self._client_list.remove(device_id, module_id) def get_next_incoming_event(self, device_id, module_id, block=True, timeout=None): return self._client_list.get_incoming_event_queue.get(block=block, timeout=timeout) def set_desired_properties(self, device_id, module_id, desired_props): if module_id: self._registry_manager.update_module_twin( device_id, module_id, Twin(properties=TwinProperties(desired=desired_props)), "*") else: self._registry_manager.update_twin( device_id, Twin(properties=TwinProperties(desired=desired_props)), "*") def invoke_method( self, device_id, module_id, method_name, payload, connect_timeout_in_seconds=None, response_timeout_in_seconds=None, ): request = CloudToDeviceMethod( method_name=method_name, payload=payload, response_timeout_in_seconds=response_timeout_in_seconds, connect_timeout_in_seconds=connect_timeout_in_seconds, ) if module_id: response = self._registry_manager.invoke_device_module_method( device_id, module_id, request) else: response = self._registry_manager.invoke_device_method( device_id, request) return response def invoke_pnp_command( self, device_id, module_id, component_name, command_name, payload, connect_timeout_in_seconds=None, response_timeout_in_seconds=None, ): assert not module_id # TODO if component_name: return self._digital_twin_client.invoke_component_command( device_id, component_name, command_name, payload, connect_timeout_in_seconds, response_timeout_in_seconds, ) else: return self._digital_twin_client.invoke_command( device_id, command_name, payload, connect_timeout_in_seconds, response_timeout_in_seconds, ) def get_pnp_properties(self, device_id, module_id): assert not module_id # TODO return self._digital_twin_client.get_digital_twin(device_id) def update_pnp_properties(self, device_id, module_id, properties): assert not module_id # TODO return self._digital_twin_client.update_digital_twin( device_id, properties) def send_c2d(self, device_id, module_id, payload, properties): assert not module_id # TODO self._registry_manager.send_c2d_message(device_id, payload, properties) def get_next_eventhub_arrival(self, device_id, module_id, block=True, timeout=None): return self._client_list.get_incoming_event_queue( device_id, module_id).get(block=block, timeout=timeout) def get_next_reported_patch_arrival(self, device_id, module_id, block=True, timeout=None): return self._client_list.get_incoming_patch_queue( device_id, module_id).get(block=block, timeout=timeout) def shutdown(self): if self._eventhub_consumer_client: self._eventhub_consumer_client.close() def _convert_incoming_event(self, event): event_body = event.body_as_json() device_id = get_device_id_from_event(event) module_id = None # TODO: extract module_id if get_message_source_from_event(event) == "twinChangeEvents": return copy.deepcopy(event_body.get("properties", {})) else: message = C2dMessage() message.device_id = device_id message.module_id = module_id message.message_body = event_body message.content_type = event.message.properties.content_type.decode( "utf-8") message.system_properties = convert_binary_dict_to_string_dict( event.system_properties) message.properties = convert_binary_dict_to_string_dict( event.properties) return message def _eventhub_thread(self): def on_error(partition_context, error): logger.error("EventHub on_error: {}".format( str(error) or type(error))) def on_partition_initialize(partition_context): logger.warning("EventHub on_partition_initialize") def on_partition_close(partition_context, reason): # commented out because it causes ugly warning spew on shutdown # logger.warning("EventHub on_partition_close: {}".format(reason)) pass def on_event(partition_context, event): if event: device_id = get_device_id_from_event(event) module_id = None # TODO: extract module_id if get_message_source_from_event(event) == "twinChangeEvents": queue = self._client_list.get_incoming_patch_queue( device_id, module_id) else: queue = self._client_list.get_incoming_event_queue( device_id, module_id) if queue: logger.info("Received {} for device {}, module {}".format( get_message_source_from_event(event), device_id, module_id)) queue.put(self._convert_incoming_event(event)) try: with self._eventhub_consumer_client: logger.info("Starting EventHub receive") self._eventhub_consumer_client.receive( on_event, on_error=on_error, on_partition_initialize=on_partition_initialize, on_partition_close=on_partition_close, max_wait_time=3600, ) except Exception: logger.error("_eventhub_thread exception", exc_info=True) raise
class GraphManager: def __init__(self): config_data = pathlib.Path('appsettings.json').read_text() config = json.loads(config_data) self.device_id = config['deviceId'] self.module_id = config['moduleId'] self.registry_manager = IoTHubRegistryManager(config['IoThubConnectionString']) self.rtsp_url = config['rtspUrl'] self.printColors = { 'yellow': '\033[93m {}\033[00m', 'green': '\033[92m {}\033[00m', 'red': '\033[91m {}\033[00m' } def invoke_wait_for_input(self, message): print(self.printColors['yellow'].format(message)) return input() """ Create and invoke the CloudToDeviceMethod to execute a Direct Method on the device. """ def invoke_module_method(self, method): # Get the name of the Direct Method method_name = method.method_name # Get the payload of the Direct Method payload = method.serialize() direct_method = CloudToDeviceMethod(method_name=method_name, payload=payload) print(self.printColors['green'].format("\n----------------------- Request: %s --------------------------------------------------\n" % method_name)) print(json.dumps(payload, indent=4)) # Invoke the Direct Method resp = self.registry_manager.invoke_device_module_method(self.device_id, self.module_id, direct_method) print(self.printColors['green'].format("\n--------------- Response: %s - Status: %s ---------------\n" % (method_name, resp.status))) # Check if the execution was successful and print out the payload (if available) if resp.payload is not None and 'error' in resp.payload: raise Exception(json.dumps(resp.payload['error'], indent=4)) elif resp.payload is not None: print(json.dumps(resp.payload, indent=4)) def graph_topology_set(self, graph_topology): self.invoke_module_method(MediaGraphTopologySetRequest(graph=graph_topology)) def graph_topology_list(self): self.invoke_module_method(MediaGraphTopologyListRequest()) def graph_topology_get(self, graph_topology_name): self.invoke_module_method(MediaGraphTopologyGetRequest(name=graph_topology_name)) def graph_topology_delete(self, graph_topology_name): self.invoke_module_method(MediaGraphTopologyDeleteRequest(name=graph_topology_name)) def graph_instance_set(self, graph_instance): self.invoke_module_method(MediaGraphInstanceSetRequest(instance=graph_instance)) def graph_instance_list(self): self.invoke_module_method(MediaGraphInstanceListRequest()) def graph_instance_activate(self, graph_instance_name): self.invoke_module_method(MediaGraphInstanceActivateRequest(name=graph_instance_name)) def graph_instance_deactivate(self, graph_instance_name): self.invoke_module_method(MediaGraphInstanceDeActivateRequest(name=graph_instance_name)) def graph_instance_delete(self, graph_instance_name): self.invoke_module_method(MediaGraphInstanceDeleteRequest(name=graph_instance_name)) """ Create an instance of a Graph Instance and set the required instance parameters """ def create_graph_instance(self, graph_topology, rtsp_url): graph_instance_name = "Sample-Graph-1" graph_instance_description = "Sample graph description" url_param = MediaGraphParameterDefinition(name="rtspUrl", value=rtsp_url) graph_instance_properties = MediaGraphInstanceProperties(description=graph_instance_description, topology_name=graph_topology.name, parameters=[url_param]) graph_instance = MediaGraphInstance(name=graph_instance_name, properties=graph_instance_properties) return graph_instance
iothub_connection_str = os.getenv("IOTHUB_CONNECTION_STRING") device_id = os.getenv("IOTHUB_DEVICE_ID") module_id = os.getenv("IOTHUB_MODULE_ID") method_name = "lockDoor" method_payload = "now" try: # RegistryManager iothub_registry_manager = IoTHubRegistryManager(iothub_connection_str) # Create Module primary_key = "aaabbbcccdddeeefffggghhhiiijjjkkklllmmmnnnoo" secondary_key = "111222333444555666777888999000aaabbbcccdddee" managed_by = "" new_module = iothub_registry_manager.create_module_with_sas( device_id, module_id, managed_by, primary_key, secondary_key) deviceMethod = CloudToDeviceMethod(method_name=method_name, payload=method_payload) iothub_registry_manager.invoke_device_module_method( device_id, module_id, deviceMethod) # Delete Module iothub_registry_manager.delete_module(device_id, module_id) print("Deleted Module {0}".format(module_id)) except Exception as ex: print("Unexpected error {0}".format(ex)) except KeyboardInterrupt: print("IoTHubRegistryManager sample stopped")
class GraphManager: def __init__(self): self.registry_manager = IoTHubRegistryManager(IOTHUB_CONNECTION_STRING) self.device_id = DEVICE_ID self.module_id = MODULE_ID def invoke_method2(self, method_name, payload): body = { "methodName": method_name, "responseTimeoutInSeconds": 10, "connectTimeoutInSeconds": 10, "payload": payload } url = 'https://main.iothub.ext.azure.com/api/dataPlane/post' data = { "apiVersion": "2018-06-30", "authorizationPolicyKey": "rDav1fU61BRTezz8NewMe/UNasZob1rQ8FowPqrbD28=", "authorizationPolicyName": "service", "hostName": "customvision.azure-devices.net", "requestPath": "/twins/testcam/modules/lvaEdge/methods", "requestBody": str(body) } header = {"Authorization": IOTHUB_CONNECTION_STRING} res = requests.post(url, headers=header, data=data) return res.json() def invoke_method(self, method_name, payload): mutex.acquire() try: module_method = CloudToDeviceMethod(method_name=method_name, payload=payload, response_timeout_in_seconds=30) res = self.registry_manager.invoke_device_module_method( self.device_id, self.module_id, module_method) mutex.release() return res.as_dict() except: mutex.release() print("[ERROR] Failed to invoke direct method:", sys.exc_info(), flush=True) return {'error': 'failed to invoke direct method'} def invoke_graph_topology_get(self, name): method = 'GraphTopologyGet' payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_topology_set(self, name, properties): method = 'GraphTopologySet' payload = { "@apiVersion": "1.0", 'name': name, 'properties': properties, } return self.invoke_method(method, payload) def invoke_graph_topology_list(self): method = 'GraphTopologyList' payload = { '@apiVersion': '1.0', } return self.invoke_method(method, payload) def invoke_graph_topology_delete(self, name): method = 'GraphTopologyDelete' payload = { '@apiVersion': '1.0', 'name': name, } return self.invoke_method(method, payload) def invoke_graph_instance_get(self, name): method = 'GraphInstanceGet' payload = { '@apiVersion': '1.0', 'name': name, } return self.invoke_method(method, payload) def invoke_graph_instance_set(self, name, properties): method = 'GraphInstanceSet' payload = { "@apiVersion": "1.0", 'name': name, 'properties': properties, } return self.invoke_method(method, payload) def invoke_graph_instance_delete(self, name): method = 'GraphInstanceDelete' payload = { '@apiVersion': '1.0', 'name': name, } return self.invoke_method(method, payload) def invoke_graph_instance_list(self): method = 'GraphInstanceList' payload = { '@apiVersion': '1.0', } return self.invoke_method(method, payload) def invoke_graph_instance_activate(self, name): method = 'GraphInstanceActivate' payload = { '@apiVersion': '1.0', 'name': name, } return self.invoke_method(method, payload) def invoke_graph_instance_deactivate(self, name): method = 'GraphInstanceDeactivate' payload = { '@apiVersion': '1.0', 'name': name, } return self.invoke_method(method, payload) # default grpc settings def invoke_graph_grpc_topology_set(self): method = 'GraphTopologySet' with open('grpc_topology.json') as f: payload = json.load(f) return self.invoke_method(method, payload) def invoke_graph_grpc_instance_set(self, name, rtspUrl, frameRate): properties = { "topologyName": "InferencingWithGrpcExtension", "description": "Sample graph description", "parameters": [ { "name": "rtspUrl", "value": rtspUrl }, { "name": "frameRate", "value": frameRate }, { "name": "grpcExtensionAddress", "value": "tcp://InferenceModule:44000" }, { "name": "frameHeight", "value": "540" }, { "name": "frameWidth", "value": "960" }, ] } return self.invoke_graph_instance_set(name, properties)
class GraphManager: def __init__(self): if is_edge(): try: self.registry_manager = IoTHubRegistryManager( IOTHUB_CONNECTION_STRING) except: logger.warning( 'IoTHub authentication failed. The server will terminate in 10 seconds.') time.sleep(10) sys.exit(-1) else: self.registry_manager = None self.device_id = DEVICE_ID self.module_id = MODULE_ID def invoke_method(self, method_name, payload): if not self.registry_manager: print( "[WARNING] Not int edge evironment, ignore direct message", flush=True ) mutex.acquire() try: module_method = CloudToDeviceMethod( method_name=method_name, payload=payload, response_timeout_in_seconds=30 ) res = self.registry_manager.invoke_device_module_method( self.device_id, self.module_id, module_method ) mutex.release() return res.as_dict() except: mutex.release() print("[ERROR] Failed to invoke direct method:", sys.exc_info(), flush=True) return {"error": "failed to invoke direct method"} def invoke_graph_topology_get(self, name): method = "GraphTopologyGet" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_topology_set(self, name, properties): method = "GraphTopologySet" payload = { "@apiVersion": "2.0", "name": name, "properties": properties, } return self.invoke_method(method, payload) def invoke_graph_topology_list(self): method = "GraphTopologyList" payload = { "@apiVersion": "2.0", } return self.invoke_method(method, payload) def invoke_graph_topology_delete(self, name): method = "GraphTopologyDelete" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_get(self, name): method = "GraphInstanceGet" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_set(self, name, properties): method = "GraphInstanceSet" payload = { "@apiVersion": "2.0", "name": name, "properties": properties, } return self.invoke_method(method, payload) def invoke_graph_instance_delete(self, name): method = "GraphInstanceDelete" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_list(self): method = "GraphInstanceList" payload = { "@apiVersion": "2.0", } return self.invoke_method(method, payload) def invoke_graph_instance_activate(self, name): method = "GraphInstanceActivate" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_deactivate(self, name): method = "GraphInstanceDeactivate" payload = { "@apiVersion": "2.0", "name": name, } return self.invoke_method(method, payload) # default grpc settings def invoke_graph_grpc_topology_set(self): method = "GraphTopologySet" with open("grpc_topology.json") as f: payload = json.load(f) return self.invoke_method(method, payload) def invoke_graph_grpc_instance_set(self, name, rtspUrl, frameRate, recording_duration): recordingDuration = "PT{}S".format(recording_duration) find_cred, username, password = self.parse_rtsp_credential(rtspUrl) properties = { "topologyName": "InferencingWithGrpcExtension", "description": "Sample graph description", "parameters": [ {"name": "rtspUrl", "value": rtspUrl}, {"name": "rtspUserName", "value": username}, {"name": "rtspPassword", "value": password}, {"name": "frameRate", "value": frameRate}, {"name": "instanceId", "value": name}, {"name": "recordingDuration", "value": recordingDuration}, { "name": "grpcExtensionAddress", "value": "tcp://*****:*****@' in rtspUrl: pattern = '\\:\\/\\/(?P<_0>.+)\\:(?P<_1>.+)\\@' out = re.findall(pattern, rtspUrl) if len(out) > 0: username = out[0][0] password = out[0][1] find_cred = True return(find_cred, username, password)
class GraphManager: def __init__(self): if is_edge(): self.registry_manager = IoTHubRegistryManager( IOTHUB_CONNECTION_STRING) else: self.registry_manager = None self.device_id = DEVICE_ID self.module_id = MODULE_ID def invoke_method(self, method_name, payload): if not self.registry_manager: print("[WARNING] Not int edge evironment, ignore direct message", flush=True) mutex.acquire() try: module_method = CloudToDeviceMethod(method_name=method_name, payload=payload, response_timeout_in_seconds=30) res = self.registry_manager.invoke_device_module_method( self.device_id, self.module_id, module_method) mutex.release() return res.as_dict() except: mutex.release() print("[ERROR] Failed to invoke direct method:", sys.exc_info(), flush=True) return {"error": "failed to invoke direct method"} def invoke_graph_topology_get(self, name): method = "GraphTopologyGet" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_topology_set(self, name, properties): method = "GraphTopologySet" payload = { "@apiVersion": "1.0", "name": name, "properties": properties, } return self.invoke_method(method, payload) def invoke_graph_topology_list(self): method = "GraphTopologyList" payload = { "@apiVersion": "1.0", } return self.invoke_method(method, payload) def invoke_graph_topology_delete(self, name): method = "GraphTopologyDelete" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_get(self, name): method = "GraphInstanceGet" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_set(self, name, properties): method = "GraphInstanceSet" payload = { "@apiVersion": "1.0", "name": name, "properties": properties, } return self.invoke_method(method, payload) def invoke_graph_instance_delete(self, name): method = "GraphInstanceDelete" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_list(self): method = "GraphInstanceList" payload = { "@apiVersion": "1.0", } return self.invoke_method(method, payload) def invoke_graph_instance_activate(self, name): method = "GraphInstanceActivate" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) def invoke_graph_instance_deactivate(self, name): method = "GraphInstanceDeactivate" payload = { "@apiVersion": "1.0", "name": name, } return self.invoke_method(method, payload) # default grpc settings def invoke_graph_grpc_topology_set(self): method = "GraphTopologySet" with open("grpc_topology.json") as f: payload = json.load(f) return self.invoke_method(method, payload) def invoke_graph_grpc_instance_set(self, name, rtspUrl, frameRate): properties = { "topologyName": "InferencingWithGrpcExtension", "description": "Sample graph description", "parameters": [ { "name": "rtspUrl", "value": rtspUrl }, { "name": "frameRate", "value": frameRate }, { "name": "instanceId", "value": name }, { "name": "grpcExtensionAddress", "value": "tcp://InferenceModule:44000", }, { "name": "frameHeight", "value": "540" }, { "name": "frameWidth", "value": "960" }, ], } return self.invoke_graph_instance_set(name, properties) # default http extension settings def invoke_graph_http_topology_set(self): method = "GraphTopologySet" with open("http_topology.json") as f: payload = json.load(f) return self.invoke_method(method, payload) def invoke_graph_http_instance_set(self, name, rtspUrl, frameRate): inferencingUrl = "http://InferenceModule:5000/predict?camera_id=" + str( name) properties = { "topologyName": "InferencingWithHttpExtension", "description": "Sample graph description", "parameters": [ { "name": "rtspUrl", "value": rtspUrl }, { "name": "frameRate", "value": frameRate }, { "name": "inferencingUrl", "value": inferencingUrl }, { "name": "frameHeight", "value": "540" }, { "name": "frameWidth", "value": "960" }, ], } return self.invoke_graph_instance_set(name, properties) def invoke_topology_set(self, mode): if mode == "grpc": return self.invoke_graph_grpc_topology_set() elif mode == "http": return self.invoke_graph_http_topology_set() else: return "LVA mode error" def invoke_instance_set(self, mode, name, rtspUrl, frameRate): if mode == "grpc": return self.invoke_graph_grpc_instance_set(name, rtspUrl, frameRate) elif mode == "http": return self.invoke_graph_http_instance_set(name, rtspUrl, frameRate) else: return "LVA mode error"
class GraphManager: def __init__(self): self.device_id = getenv(constants.device_id) self.device_tag = getenv(constants.device_tag) self.tag_value = getenv(constants.tag_value) self.module_id = getenv(constants.module_id) self.api_version = constants.topology_api_version self.registry_manager = IoTHubRegistryManager(getenv(constants.iot_connection_string)) if self.device_id is None: self.device_list = self.get_device_list() def get_device_list(self): query_string = f"SELECT * FROM devices WHERE tags.{self.device_tag} = '{self.tag_value}'" query_spec = QuerySpecification(query=query_string) response = self.registry_manager.query_iot_hub(query_spec, None, None) return response.items def invoke(self, method_name, payload): if method_name == 'GraphTopologySet': self.graph_topology_set(payload) return if method_name == 'WaitForInput': print(payload['message']) input() return self.invoke_module_method(method_name, payload) def invoke_module_method(self, method_name, payload): # make sure '@apiVersion' has been set payload['@apiVersion'] = self.api_version module_method = CloudToDeviceMethod( method_name=method_name, payload=payload, response_timeout_in_seconds=30) device_id = self.device_id try: if device_id is None: for device in self.device_list: device_id = device.device_id self.invoke_device_module_method(device_id, method_name, module_method, payload) else: self.invoke_device_module_method(device_id, method_name, module_method, payload) except Exception as ex: if ex.response.status_code == 404: print(">>>>>>>>>> Warning: device '%s' does not have the '%s' module deployed, or the module has not yet initalized <<<<<<<<<<" % (device_id, self.module_id)) def invoke_device_module_method(self, device_id, method_name, module_method, payload): print("\n----------------------- Device: %s - Request: %s --------------------------------------------------\n" % (device_id, method_name)) print(json.dumps(payload, indent=4)) resp = self.registry_manager.invoke_device_module_method(device_id, self.module_id, module_method) print("\n----------------------- Device: %s - Response: %s - Status: %s ------------------------------------\n" % (device_id, method_name, resp.status)) if resp.payload is not None: print(json.dumps(resp.payload, indent=4)) def graph_topology_set(self, op_parameters): if op_parameters is None: raise Exception('Operation parameters missing') if op_parameters.get('topologyUrl') is not None: topology_json = read_url(op_parameters['topologyUrl']) elif op_parameters.get('topologyFile') is not None: topology_path = Path(__file__).parent.joinpath(op_parameters['topologyFile']) topology_json = topology_path.read_text() else: raise Exception('Neither topologyUrl nor topologyFile is specified') topology = json.loads(topology_json) self.invoke_module_method('GraphTopologySet', topology)