class HubManager(object): def __init__(self, connection_string, protocol=IoTHubTransportProvider.MQTT): self.client_protocol = protocol self.client = IoTHubClient(connection_string, protocol) if protocol == IoTHubTransportProvider.HTTP: self.client.set_option("timeout", TIMEOUT) self.client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME) # set the time until a message times out self.client.set_option("messageTimeout", 100000) def send_event(self, event, properties, send_context): if not isinstance(event, IoTHubMessage): event = IoTHubMessage(bytearray(event, 'utf8')) event.set_content_encoding_system_property('utf-8') event.set_content_type_system_property('application/json') event.properties().add('deviceId', 'RaspberryPi3') if len(properties) > 0: prop_map = event.properties() for key in properties: prop_map.add_or_update(key, properties[key]) self.client.send_event_async(event, send_confirmation_callback, send_context) def send_reported_state(self, reported_state, size, user_context): self.client.send_reported_state(reported_state, size, send_reported_state_callback, user_context)
class IoTHubDevice: def __init__(self, iothub_name, device_id, device_key, suffix='.azure-devices.net'): self.device_id = device_id device_connection_string = 'HostName={0}{1};DeviceId={2};SharedAccessKey={3}'.format( iothub_name, suffix, device_id, device_key ) self.client = IoTHubClient(device_connection_string, IoTHubTransportProvider.MQTT) # HTTP, AMQP, MQTT ? def send_message(self, message): m = IoTHubMessage(message) # string or bytearray self.client.send_event_async(m, IoTHubDevice.__dummy_send_confirmation_callback, 0) def send_reported_state(self, state, send_reported_state_callback = None, user_context = None): if send_reported_state_callback is None: send_reported_state_callback = IoTHubDevice.__dummy_send_reported_state_callback state_json = json.dumps(state) self.client.send_reported_state(state_json, len(state_json), send_reported_state_callback, user_context) @staticmethod def __dummy_send_confirmation_callback(message, result, user_context): pass #print(result) @staticmethod def __dummy_send_reported_state_callback(status_code, user_context): pass
class IoTHubDevice: def __init__(self, iothub_name, device_id, device_key, suffix='.azure-devices.net'): self.iothub_name = iothub_name self.device_id = device_id self.device_key = device_key self.policy_name = 'device' self.suffix = suffix device_connection_string = self.__get_device_connection_string() self.client = IoTHubClient( device_connection_string, IoTHubTransportProvider.MQTT) # HTTP, AMQP, MQTT ? def send_message(self, message): m = IoTHubMessage(message) # string or bytearray self.client.send_event_async( m, IoTHubDevice.__dummy_send_confirmation_callback, 0) def send_reported_state(self, state): state_json = json.dumps(state) self.client.send_reported_state( state_json, len(state_json), IoTHubDevice.__dummy_send_reported_state_callback, 0) def __get_device_connection_string(self, expiry=3600): ttl = time() + expiry uri = '{0}{1}/devices/{2}'.format(self.iothub_name, self.suffix, self.device_id) sign_key = "%s\n%d" % ((quote_plus(uri)), int(ttl)) signature = b64encode( HMAC(b64decode(self.device_key), sign_key.encode('utf-8'), sha256).digest()) rawtoken = {'sr': uri, 'sig': signature, 'se': str(int(ttl))} if self.policy_name is not None: rawtoken['skn'] = self.policy_name sas = 'SharedAccessSignature ' + urlencode(rawtoken) return 'HostName={0}{1};DeviceId={2};SharedAccessSignature={3}'.format( self.iothub_name, self.suffix, self.device_id, sas) @staticmethod def __dummy_send_confirmation_callback(message, result, user_context): pass # print(result) @staticmethod def __dummy_send_reported_state_callback(status_code, user_context): pass
class HubManager(object): def __init__( self, connection_string, protocol=IoTHubTransportProvider.MQTT): self.client_protocol = protocol self.client = IoTHubClient(connection_string, protocol) if protocol == IoTHubTransportProvider.HTTP: self.client.set_option("timeout", TIMEOUT) self.client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME) # set the time until a message times out self.client.set_option("messageTimeout", MESSAGE_TIMEOUT) # some embedded platforms need certificate information # self.set_certificates() self.client.set_message_callback(receive_message_callback, RECEIVE_CONTEXT) self.client.set_device_twin_callback(device_twin_callback, TWIN_CONTEXT) self.client.set_device_method_callback(device_method_callback, METHOD_CONTEXT) def set_certificates(self): from iothub_client_cert import CERTIFICATES try: self.client.set_option("TrustedCerts", CERTIFICATES) print ( "set_option TrustedCerts successful" ) except IoTHubClientError as iothub_client_error: print ( "set_option TrustedCerts failed (%s)" % iothub_client_error ) def send_event(self, event, properties, send_context): if not isinstance(event, IoTHubMessage): event = IoTHubMessage(bytearray(event, 'utf8')) if len(properties) > 0: prop_map = event.properties() for key in properties: prop_map.add_or_update(key, properties[key]) self.client.send_event_async( event, send_confirmation_callback, send_context) def send_reported_state(self, reported_state, size, user_context): self.client.send_reported_state( reported_state, size, send_reported_state_callback, user_context) def upload_to_blob(self, destinationfilename, source, size, usercontext): self.client.upload_blob_async( destinationfilename, source, size, blob_upload_conf_callback, usercontext)
class HubManager(object): def __init__( self, connection_string, protocol=IoTHubTransportProvider.MQTT): self.client_protocol = protocol self.client = IoTHubClient(connection_string, protocol) if protocol == IoTHubTransportProvider.HTTP: self.client.set_option("timeout", TIMEOUT) self.client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME) # set the time until a message times out self.client.set_option("messageTimeout", MESSAGE_TIMEOUT) # some embedded platforms need certificate information # self.set_certificates() self.client.set_message_callback(receive_message_callback, RECEIVE_CONTEXT) self.client.set_device_twin_callback(device_twin_callback, TWIN_CONTEXT) self.client.set_device_method_callback(device_method_callback, METHOD_CONTEXT) def set_certificates(self): from iothub_client_cert import CERTIFICATES try: self.client.set_option("TrustedCerts", CERTIFICATES) print ( "set_option TrustedCerts successful" ) except IoTHubClientError as iothub_client_error: print ( "set_option TrustedCerts failed (%s)" % iothub_client_error ) def send_event(self, event, properties, send_context): if not isinstance(event, IoTHubMessage): event = IoTHubMessage(bytearray(event, 'utf8')) if len(properties) > 0: prop_map = event.properties() for key in properties: prop_map.add_or_update(key, properties[key]) self.client.send_event_async( event, send_confirmation_callback, send_context) def send_reported_state(self, reported_state, size, user_context): self.client.send_reported_state( reported_state, size, send_reported_state_callback, user_context) def upload_to_blob(self, destinationfilename, source, size, usercontext): self.client.upload_blob_async( destinationfilename, source, size, blob_upload_conf_callback, usercontext)
class HubManager(object): def __init__(self, connection_string): self.client_protocol = PROTOCOL self.client = IoTHubClient(connection_string, PROTOCOL) # set the time until a message times out self.client.set_option("messageTimeout", MESSAGE_TIMEOUT) # some embedded platforms need certificate information self.set_certificates() # sets the callback when a message arrives on "input1" queue. Messages sent to # other inputs or to the default will be silently discarded. self.client.set_device_twin_callback(device_twin_callback, self) def set_certificates(self): isWindows = sys.platform.lower() in ['windows', 'win32'] if not isWindows: CERT_FILE = os.environ['EdgeModuleCACertificateFile'] print("Adding TrustedCerts from: {0}".format(CERT_FILE)) # this brings in x509 privateKey and certificate file = open(CERT_FILE) try: self.client.set_option("TrustedCerts", file.read()) print("set_option TrustedCerts successful") except IoTHubClientError as iothub_client_error: print("set_option TrustedCerts failed (%s)" % iothub_client_error) file.close() # Forwards the message received onto the next stage in the process. def forward_event_to_output(self, outputQueueName, event, send_context): self.client.send_event_async(outputQueueName, event, send_confirmation_callback, send_context) def send_reported_state(self, reported_state, size, send_context): self.client.send_reported_state(reported_state, size, send_reported_state_callback, send_context)
def run_e2e_device_client(iothub_service_client_messaging, iothub_device_method, iothub_device_twin, device_id, device_connection_string, protocol, authMethod): ########################################################################### # IoTHubClient # prepare # act device_client = IoTHubClient(device_connection_string, protocol) # verify assert isinstance(device_client, IoTHubClient), 'Error: Invalid type returned!' assert device_client != None, "Error: device_client is NULL" ########################################################################### ########################################################################### # set_option # prepare # act device_client.set_option("messageTimeout", DEVICE_MESSAGE_TIMEOUT) if authMethod == IoTHubRegistryManagerAuthMethod.X509_THUMBPRINT: device_client.set_option("x509certificate", IOTHUB_E2E_X509_CERT) device_client.set_option("x509privatekey", IOTHUB_E2E_X509_THUMBPRINT) if device_client.protocol == IoTHubTransportProvider.HTTP: device_client.set_option("timeout", HTTP_TIMEOUT) device_client.set_option("MinimumPollingTime", HTTP_MINIMUM_POLLING_TIME) if protocol == IoTHubTransportProvider.MQTT_WS or protocol == IoTHubTransportProvider.AMQP_WS: device_client.set_option("TrustedCerts", CERTIFICATES) # verify ########################################################################### ########################################################################### # set_message_callback # prepare # act device_client.set_message_callback(receive_message_callback, MESSAGING_CONTEXT) # verify ########################################################################### if protocol == IoTHubTransportProvider.MQTT or protocol == IoTHubTransportProvider.MQTT_WS: ########################################################################### # set_device_twin_callback # prepare # act device_client.set_device_twin_callback(device_twin_callback, MESSAGING_CONTEXT) # verify ########################################################################### ########################################################################### # set_device_method_callback # prepare # act device_client.set_device_method_callback(device_method_callback, MESSAGING_CONTEXT) # verify ########################################################################### ########################################################################### # update device twin # prepare global TWIN_CALLBACK_EVENT global TWIN_CALLBACK_COUNTER TWIN_CALLBACK_EVENT.clear() TWIN_CALLBACK_COUNTER = 0 # act sc_update_twin(iothub_device_twin, device_id) TWIN_CALLBACK_EVENT.wait(CALLBACK_TIMEOUT) # verify assert TWIN_CALLBACK_COUNTER == 1, "Error: device_twin_callback callback has not been called" ########################################################################### ########################################################################### # call device method # prepare global DEVICE_METHOD_EVENT global DEVICE_METHOD_CALLBACK_COUNTER DEVICE_METHOD_EVENT.clear() DEVICE_METHOD_CALLBACK_COUNTER = 0 method_name = "E2EMethodName" payload_json = "{\"method_number\":\"42\"}" # act sc_invoke_device_method(iothub_device_method, device_id, method_name, payload_json) DEVICE_METHOD_EVENT.wait(CALLBACK_TIMEOUT) # verify assert DEVICE_METHOD_CALLBACK_COUNTER == 1, "Error: device_twin_callback callback has not been called" ########################################################################### if protocol != IoTHubTransportProvider.AMQP \ and protocol != IoTHubTransportProvider.AMQP_WS \ and protocol != IoTHubTransportProvider.HTTP: ########################################################################### # send_reported_state # prepare global REPORTED_STATE_EVENT global REPORTED_STATE_CALLBACK_COUNTER reported_state = "{\"newState\":\"standBy\"}" REPORTED_STATE_EVENT.clear() REPORTED_STATE_CALLBACK_COUNTER = 0 # act device_client.send_reported_state(reported_state, len(reported_state), send_reported_state_callback, REPORTED_STATE_CONTEXT) REPORTED_STATE_EVENT.wait(CALLBACK_TIMEOUT) # verify assert REPORTED_STATE_CALLBACK_COUNTER == 1, "Error: send_reported_state_callback has not been called" ########################################################################### ########################################################################### # send_event_async # prepare global MESSAGING_MESSAGE global MESSAGE_RECEIVE_EVENT global MESSAGE_RECEIVE_CALLBACK_COUNTER MESSAGING_MESSAGE = ''.join([random.choice(string.ascii_letters) for n in range(12)]) message = IoTHubMessage(bytearray(MESSAGING_MESSAGE, 'utf8')) MESSAGE_RECEIVE_EVENT.clear() MESSAGE_RECEIVE_CALLBACK_COUNTER = 0 # act sc_send_message(iothub_service_client_messaging, device_id, message) MESSAGE_RECEIVE_EVENT.wait(CALLBACK_TIMEOUT) # verify assert MESSAGE_RECEIVE_CALLBACK_COUNTER == 1, "Error: message has not been received" ########################################################################### ########################################################################### # get_send_status # prepare status_counter = 0 status = -1; # act while status_counter < 1: status = device_client.get_send_status() print ( "Send status: {0}".format(status) ) # verify assert status == 0, "get_send_status reported status is not IDLE" status_counter += 1 ########################################################################### if protocol != IoTHubTransportProvider.AMQP \ and protocol != IoTHubTransportProvider.AMQP_WS: ########################################################################### # get_last_message_receive_time # prepare last_receive_time = -1 # act last_receive_time = device_client.get_last_message_receive_time() # verify assert last_receive_time > 0, "Error: get_last_message_receive_time failed" ########################################################################### ########################################################################### # upload_blob_async # prepare global BLOB_UPLOAD_CONTEXT global BLOB_UPLOAD_EVENT global BLOB_UPLOAD_CALLBACK_COUNTER destination_file_name = ''.join([random.choice(string.ascii_letters) for n in range(12)]) source = "Blob content for file upload test!" size = 34 BLOB_UPLOAD_EVENT.clear() BLOB_UPLOAD_CALLBACK_COUNTER = 0 # act device_client.upload_blob_async(destination_file_name, source, size, blob_upload_conf_callback, BLOB_UPLOAD_CONTEXT) BLOB_UPLOAD_EVENT.wait(CALLBACK_TIMEOUT) # verify assert BLOB_UPLOAD_CALLBACK_COUNTER == 1, "Error: blob_upload_conf_callback callback has not been called" ########################################################################### print ("run_e2e_device_client with protocol: {0}, and authMethod: {1} finished".format(protocol, authMethod))
def run_e2e_device_client(iothub_service_client_messaging, iothub_device_method, iothub_device_twin, device_id, device_connection_string, protocol, authMethod): global IOTHUB_E2E_X509_CERT global IOTHUB_E2E_X509_THUMBPRINT global IOTHUB_E2E_X509_PRIVATE_KEY global CERTIFICATES global MESSAGING_CONTEXT ########################################################################### # IoTHubClient # prepare # act device_client = IoTHubClient(device_connection_string, protocol) # verify assert isinstance(device_client, IoTHubClient), 'Error: Invalid type returned!' assert device_client != None, "Error: device_client is NULL" ########################################################################### ########################################################################### # set_option # prepare # act device_client.set_option("messageTimeout", DEVICE_MESSAGE_TIMEOUT) if authMethod == IoTHubRegistryManagerAuthMethod.X509_THUMBPRINT: device_client.set_option("x509certificate", IOTHUB_E2E_X509_CERT) device_client.set_option("x509privatekey", IOTHUB_E2E_X509_PRIVATE_KEY) if device_client.protocol == IoTHubTransportProvider.HTTP: device_client.set_option("timeout", HTTP_TIMEOUT) device_client.set_option("MinimumPollingTime", HTTP_MINIMUM_POLLING_TIME) device_client.set_option("TrustedCerts", CERTIFICATES) device_client.set_option("logtrace", True) # verify ########################################################################### ########################################################################### # set_message_callback # prepare # act device_client.set_message_callback(receive_message_callback, MESSAGING_CONTEXT) ########################################################################### ########################################################################### # set_connection_status_callback # prepare # act device_client.set_connection_status_callback(connection_status_callback, CONNECTION_STATUS_CONTEXT) ########################################################################### # verify ########################################################################### if protocol == IoTHubTransportProvider.MQTT or protocol == IoTHubTransportProvider.MQTT_WS: ########################################################################### # set_device_twin_callback # prepare # act device_client.set_device_twin_callback(device_twin_callback, MESSAGING_CONTEXT) # verify ########################################################################### ########################################################################### # set_device_method_callback # prepare # act device_client.set_device_method_callback(device_method_callback, MESSAGING_CONTEXT) # verify ########################################################################### ########################################################################### # update device twin # prepare global TWIN_CALLBACK_EVENT global TWIN_CALLBACK_COUNTER TWIN_CALLBACK_EVENT.clear() TWIN_CALLBACK_COUNTER = 0 # act sc_update_twin(iothub_device_twin, device_id) TWIN_CALLBACK_EVENT.wait(CALLBACK_TIMEOUT) # verify assert TWIN_CALLBACK_COUNTER > 0, "Error: device_twin_callback callback has not been called" ########################################################################### ########################################################################### # call device method # prepare global DEVICE_METHOD_EVENT global DEVICE_METHOD_CALLBACK_COUNTER DEVICE_METHOD_EVENT.clear() DEVICE_METHOD_CALLBACK_COUNTER = 0 method_name = "E2EMethodName" payload_json = "{\"method_number\":\"42\"}" # act sc_invoke_device_method(iothub_device_method, device_id, method_name, payload_json) DEVICE_METHOD_EVENT.wait(CALLBACK_TIMEOUT) # verify assert DEVICE_METHOD_CALLBACK_COUNTER > 0, "Error: device_twin_callback callback has not been called" ########################################################################### if protocol == IoTHubTransportProvider.AMQP \ or protocol == IoTHubTransportProvider.AMQP_WS \ or protocol == IoTHubTransportProvider.MQTT \ or protocol == IoTHubTransportProvider.MQTT_WS: ########################################################################### # send_reported_state # prepare global REPORTED_STATE_EVENT global REPORTED_STATE_CALLBACK_COUNTER reported_state = "{\"newState\":\"standBy\"}" REPORTED_STATE_EVENT.clear() REPORTED_STATE_CALLBACK_COUNTER = 0 # act device_client.send_reported_state(reported_state, len(reported_state), send_reported_state_callback, REPORTED_STATE_CONTEXT) REPORTED_STATE_EVENT.wait(CALLBACK_TIMEOUT) # verify assert REPORTED_STATE_CALLBACK_COUNTER > 0, "Error: send_reported_state_callback has not been called" ########################################################################### ########################################################################### # set_retry_policy # get_retry_policy # prepare # act retryPolicy = IoTHubClientRetryPolicy.RETRY_INTERVAL retryInterval = 100 device_client.set_retry_policy(retryPolicy, retryInterval) print ( "SetRetryPolicy to: retryPolicy = %d" % retryPolicy) print ( "SetRetryPolicy to: retryTimeoutLimitInSeconds = %d" % retryInterval) # verify retryPolicyReturn = device_client.get_retry_policy() assert retryPolicyReturn.retryPolicy == IoTHubClientRetryPolicy.RETRY_INTERVAL, "Error: set_retry_policy/get_retry_policy failed" assert retryPolicyReturn.retryTimeoutLimitInSeconds == 100, "Error: set_retry_policy/get_retry_policy failed" print ( "GetRetryPolicy returned: retryPolicy = %d" % retryPolicyReturn.retryPolicy) print ( "GetRetryPolicy returned: retryTimeoutLimitInSeconds = %d" % retryPolicyReturn.retryTimeoutLimitInSeconds) ########################################################################### # send_event_async # prepare global MESSAGING_MESSAGE global MESSAGE_RECEIVE_EVENT global MESSAGE_RECEIVE_CALLBACK_COUNTER MESSAGING_MESSAGE = ''.join([random.choice(string.ascii_letters) for n in range(12)]) message = IoTHubMessage(bytearray(MESSAGING_MESSAGE, 'utf8')) MESSAGE_RECEIVE_EVENT.clear() MESSAGE_RECEIVE_CALLBACK_COUNTER = 0 # act sc_send_message(iothub_service_client_messaging, device_id, message) MESSAGE_RECEIVE_EVENT.wait(CALLBACK_TIMEOUT) # verify assert MESSAGE_RECEIVE_CALLBACK_COUNTER > 0, "Error: message has not been received" ########################################################################### ########################################################################### # get_send_status # prepare status_counter = 0 status = -1; # act while status_counter < 1: status = device_client.get_send_status() print ( "Send status: {0}".format(status) ) # verify assert status == 0, "get_send_status reported status is not IDLE" status_counter += 1 ########################################################################### if protocol != IoTHubTransportProvider.AMQP \ and protocol != IoTHubTransportProvider.AMQP_WS: ########################################################################### # get_last_message_receive_time # prepare last_receive_time = -1 # act last_receive_time = device_client.get_last_message_receive_time() # verify assert last_receive_time > 0, "Error: get_last_message_receive_time failed" ########################################################################### ########################################################################### # upload_blob_async # prepare global BLOB_UPLOAD_CONTEXT global BLOB_UPLOAD_EVENT global BLOB_UPLOAD_CALLBACK_COUNTER destination_file_name = ''.join([random.choice(string.ascii_letters) for n in range(12)]) source = "Blob content for file upload test!" size = 34 BLOB_UPLOAD_EVENT.clear() BLOB_UPLOAD_CALLBACK_COUNTER = 0 # act device_client.upload_blob_async(destination_file_name, source, size, blob_upload_conf_callback, BLOB_UPLOAD_CONTEXT) BLOB_UPLOAD_EVENT.wait(CALLBACK_TIMEOUT) # verify assert BLOB_UPLOAD_CALLBACK_COUNTER > 0, "Error: blob_upload_conf_callback callback has not been called"
class AzureIoTClient(object): def __init__( self, connection_string, logger, protocol=IoTHubTransportProvider.MQTT, message_timeout=10000, # Callback handlers receive_message_callback=noop, send_event_callback=noop, reported_state_callback=noop): self._connection_string = connection_string self._logger = logger self._protocol = protocol self._message_timeout = message_timeout self.receive_message_callback = receive_message_callback self.send_event_callback = send_event_callback self.reported_state_callback = reported_state_callback self.client = None self._send_context = 0 self._reported_state_context = 0 def connect(self): self._logger.info("Connecting") self.client = IoTHubClient(self._connection_string, self._protocol) # set the time until a message times out self.client.set_option("messageTimeout", self._message_timeout) self.client.set_message_callback(self._receive_message_callback, RECEIVE_CONTEXT) def disconnect(self): self._logger.info("Disconnecting") self.client = None def _receive_message_callback(self, message, context): message_buffer = message.get_bytearray() size = len(message_buffer) body = message_buffer[:size].decode('utf-8') self._logger.debug("Data: {}, Size={}, counter".format( body, size, context)) map_properties = message.properties() properties = map_properties.get_internals() self._logger.debug(" Properties: {}".format(properties)) if self.receive_message_callback: try: body = json.loads(body) except (json_decode_error, ValueError): # ignore if no json, pass it to callback as decoded body pass try: self.receive_message_callback(body, properties) except ValueError: return IoTHubMessageDispositionResult.REJECTED return IoTHubMessageDispositionResult.ACCEPTED def send_event(self, event, properties=None): """ Sends an event Args: event (dict): event values properties (dict): values to send as properties """ if not isinstance(event, IoTHubMessage): event = json.dumps(event) event = IoTHubMessage(bytearray(event, 'utf8')) if properties and len(properties) > 0: prop_map = event.properties() for key in properties: prop_map.add_or_update(key, properties[key]) self.client.send_event_async(event, self._send_event_callback, self._send_context) self._send_context += 1 def _send_event_callback(self, message, result, user_context): self._logger.debug( "Confirmation[{}] received for send event message, result: {}". format(user_context, result)) map_properties = message.properties() key_value_pair = map_properties.get_internals() self._logger.debug("Properties: {}".format(key_value_pair)) # notify block is requested if self.send_event_callback: self.send_event_callback(result, key_value_pair) def send_reported_state(self, reported_state): """ Sends a reported state Args: reported_state (dict): state to report """ reported_state = json.dumps(reported_state) self.client.send_reported_state(reported_state, len(reported_state), self._send_reported_state_callback, self._reported_state_context) self._reported_state_context += 1 def _send_reported_state_callback(self, result, user_context): self._logger.debug("Confirmation for reported state received with:" "\nresult = {}\ncontext = {}".format( result, user_context)) # notify block is requested if self.reported_state_callback: self.reported_state_callback(result)
class Azure: def __init__(self, application, device_config): global azure_singelton if azure_singelton is None: azure_singelton = self else: raise Exception("AZURE: AzureIot instance already created") with open('azure.json') as f: self.config = json.load(f) if self.config['connection_string'].find(device_config.deviceid) == -1: raise Exception( "Azure connection string does not match configured device id") self.application = application self.hubClient = IoTHubClient(self.config['connection_string'], PROTOCOL) if self.hubClient.protocol == IoTHubTransportProvider.MQTT or self.hubClient.protocol == IoTHubTransportProvider.MQTT_WS: self.hubClient.set_device_twin_callback(device_twin_callback, TWIN_CONTEXT) # Report current state to cloud def update_reported_state(self, reported): try: # Report new state to HUB reported_state = json.dumps(reported) self.hubClient.send_reported_state(reported_state, len(reported_state), send_reported_state_callback, SEND_REPORTED_STATE_CONTEXT) return True except IoTHubError as iothub_error: print( "AZURE: Unexpected error from IoTHub when reporting state: %s" % iothub_error) return False # Post telemetry to cloud def post_telemetry(self, telemetry): try: message = IoTHubMessage(json.dumps(telemetry)) self.hubClient.send_event_async(message, send_confirmation_callback, None) return True except IoTHubError as iothub_error: print( "AZURE: Unexpected error from IoTHub when posting telemetry: %s" % iothub_error) return False # Keep cloud connection open (not needed for azure) def kick(self): pass # Local callbacks from iot_client def device_twin_callback(self, update_state, payload, user_context): print("AZURE: Twin callback called with updateStatus: '%s'" % update_state) payload_json = json.loads(payload) if update_state == iothub_client.iothub_client.IoTHubTwinUpdateState.COMPLETE: desired_state = payload_json["desired"].copy() else: desired_state = payload_json.copy() self.application.device_twin_update(desired_state) def send_confirmation_callback(self, message, result, user_context): print("AZURE: IoT Hub responded to message with status: %s" % (result)) def send_reported_state_callback(self, status_code, user_context): print( "AZURE: Confirmation for reported state called with status_code: %d" % status_code)
class DeviceClient(object): def __init__(self, connection_string, protocol=IoTHubTransportProvider.MQTT): print("Device Client __init__ ....creating IoTHubClient connection!") print("Connection String = %s" % connection_string) self.client_protocol = protocol self.client = IoTHubClient(connection_string, protocol) if protocol == IoTHubTransportProvider.HTTP: self.client.set_option("timeout", TIMEOUT) self.client.set_option("MinimumPollingTime", MINIMUM_POLLING_TIME) # set the time until a message times out self.client.set_option("messageTimeout", MESSAGE_TIMEOUT) # some embedded platforms need certificate information # self.set_certificates() self.client.set_message_callback(self.receive_message_callback, RECEIVE_CONTEXT) self.client.set_device_twin_callback(self.device_twin_callback, TWIN_CONTEXT) self.client.set_device_method_callback(self.device_method_callback, METHOD_CONTEXT) def set_certificates(self, client): from iothub_client_cert import CERTIFICATES try: self.client.set_option("TrustedCerts", CERTIFICATES) print("set_option TrustedCerts successful") except IoTHubClientError as iothub_client_error: print("set_option TrustedCerts failed (%s)" % iothub_client_error) def send_event(self, event, properties, send_context): if not isinstance(event, IoTHubMessage): event = IoTHubMessage(bytearray(event, 'utf8')) # if len(properties) > 0: # prop_map = event.properties() # for key in properties: # prop_map.add_or_update(key, properties[key]) self.client.send_event_async(event, self.send_confirmation_callback, send_context) def send_reported_state(self, reported_state, size, user_context): self.client.send_reported_state(reported_state, size, self.send_reported_state_callback, user_context) def upload_to_blob(self, destinationfilename, source, size, usercontext): self.client.upload_blob_async(destinationfilename, source, size, self.blob_upload_conf_callback, usercontext) def send_confirmation_callback(self, message, result, user_context): global SEND_CALLBACKS print("Confirmation[%d] received for message with result = %s" % (user_context, result)) map_properties = message.properties() key_value_pair = map_properties.get_internals() print(" Properties: %s" % key_value_pair) SEND_CALLBACKS += 1 print(" Total calls confirmed: %d" % SEND_CALLBACKS) def receive_message_callback(self, message, counter): global RECEIVE_CALLBACKS message_buffer = message.get_bytearray() size = len(message_buffer) print("<SimDevice> Received Message [%d]:" % counter) print(" Data: <<<%s>>> & Size=%d" % (message_buffer[:size].decode('utf-8'), size)) map_properties = message.properties() key_value_pair = map_properties.get_internals() print(" Properties: %s" % key_value_pair) counter += 1 RECEIVE_CALLBACKS += 1 print(" Total calls received: %d" % RECEIVE_CALLBACKS) return IoTHubMessageDispositionResult.ACCEPTED def device_twin_callback(self, update_state, payload, user_context): global TWIN_CALLBACKS print( "\nTwin callback called with:\nupdateStatus = %s\npayload = %s\ncontext = %s" % (update_state, payload, user_context)) TWIN_CALLBACKS += 1 print("Total calls confirmed: %d\n" % TWIN_CALLBACKS) def send_reported_state_callback(self, status_code, user_context): global SEND_REPORTED_STATE_CALLBACKS print( "Confirmation for reported state received with:\nstatus_code = [%d]\ncontext = %s" % (status_code, user_context)) SEND_REPORTED_STATE_CALLBACKS += 1 print(" Total calls confirmed: %d" % SEND_REPORTED_STATE_CALLBACKS) def device_method_callback(self, method_name, payload, user_context): global METHOD_CALLBACKS print( "\nMethod callback called with:\nmethodName = %s\npayload = %s\ncontext = %s" % (method_name, payload, user_context)) METHOD_CALLBACKS += 1 print("Total calls confirmed: %d\n" % METHOD_CALLBACKS) device_method_return_value = DeviceMethodReturnValue() device_method_return_value.response = "{ \"Response\": \"This is the response from the device\" }" device_method_return_value.status = 200 return device_method_return_value def blob_upload_conf_callback(self, result, user_context): global BLOB_CALLBACKS print( "Blob upload confirmation[%d] received for message with result = %s" % (user_context, result)) BLOB_CALLBACKS += 1 print(" Total calls confirmed: %d" % BLOB_CALLBACKS) def connection_status_callback(self, result, reason, user_context): global CONNECTION_STATUS_CALLBACKS print("Connection status changed[%d] with:" % (user_context)) print(" reason: %d" % reason) print(" result: %s" % result) CONNECTION_STATUS_CALLBACKS += 1 print(" Total calls confirmed: %d" % CONNECTION_STATUS_CALLBACKS)