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)
Example #2
0
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)
Example #6
0
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"
Example #9
0
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)
Example #10
0
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)
Example #11
0
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)