def stdin_listener(): iothub_registry_manager = IoTHubRegistryManager( IOTHUB_CONNECTION_STRING) twin = iothub_registry_manager.get_twin(DEVICE_ID) while True: selection = input("Q: quit, F: forward, S: stop/free\n") if selection == "Q" or selection == "q": print("Quitting...") break elif selection == "F" or selection == "f": twin_patch = Twin(properties=TwinProperties( desired={'command': 'forward'})) twin = iothub_registry_manager.update_twin( DEVICE_ID, twin_patch, twin.etag) elif selection == "S" or selection == "s": twin_patch = Twin(properties=TwinProperties( desired={'command': 'stop'})) twin = iothub_registry_manager.update_twin( DEVICE_ID, twin_patch, twin.etag)
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
# # Replace twin new_twin = Twin() new_twin = twin new_twin.properties = TwinProperties(desired={"telemetryInterval": 9000}) print(new_twin) print("") replaced_twin = iothub_registry_manager.replace_twin(device_id, new_twin) print(replaced_twin) print("") # Update twin twin_patch = Twin() twin_patch.properties = TwinProperties(desired={"telemetryInterval": 3000}) updated_twin = iothub_registry_manager.update_twin(device_id, twin_patch, twin.etag) print(updated_twin) print("The twin patch has been successfully applied") # Get devices max_number_of_devices = 10 devices = iothub_registry_manager.get_devices(max_number_of_devices) if devices: x = 0 for d in devices: print_device_info("Get devices {0}".format(x), d) x += 1 else: print("No device found") # Delete the device
import sys from time import sleep from azure.iot.hub import IoTHubRegistryManager from azure.iot.hub.models import Twin, TwinProperties, QuerySpecification, QueryResult iothub_registry_manager = IoTHubRegistryManager("Service Connection String") twin = iothub_registry_manager.get_twin("Device_id") twin_patch = Twin(properties=TwinProperties( desired={'Vision_Model_Version': 1.2})) twin = iothub_registry_manager.update_twin(DEVICE_ID, twin_patch, twin.etag) query_spec = QuerySpecification( query= "SELECT * FROM devices WHERE properties.reported.Vision_Model_Version <> 1.2" ) query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100) print("Devices that did not update: {}".format(', '.join( [twin.device_id for twin in query_result.items]))) print() query_spec = QuerySpecification( query= "SELECT * FROM devices WHERE tags.location.plant = 'Redmond43' AND properties.reported.connectivity = 'cellular'" ) query_result = iothub_registry_manager.query_iot_hub(query_spec, None, 100) print("Devices in Redmond43 plant using cellular network: {}".format(', '.join( [twin.device_id for twin in query_result.items])))