.. module:: iot ******************************* Microsoft Azure Iot Hub Library ******************************* The Zerynth Microsoft Azure Iot Hub Library can be used to ease the connection to `Microsoft Azure Iot Hub `_. It allows to make your device act as a Microsoft Azure Iot Hub Device which can be registered through Azure command line tools or Azure web dashboard. ================ The Device class ================ .. class:: Device(hub_id, device_id, api_version, key, timestamp_fn, token_lifetime=60) Create a Device instance representing a Microsoft Azure Iot Hub Device. The Device object will contain an mqtt client instance pointing to Microsoft Azure Iot Hub MQTT broker located at :samp:`hub_id.azure-devices.net`. The client is configured with :samp:`device_id` as MQTT id and is able to connect securely through TLS and authenticate through a `SAS `_ token with a :samp:`token_lifetime` minutes lifespan. Valid tokens generation process needs current timestamp which will be obtained calling passed :samp:`timestamp_fn`. :samp:`timestamp_fn` has to be a Python function returning an integer timestamp. A valid base64-encoded primary or secondary key :samp:`key` is also needed. The :samp:`api_version` string is mandatory to enable some responses from Azure MQTT broker on specific topics. The client is accessible through :samp:`mqtt` instance attribute and exposes all :ref:`Zerynth MQTT Client methods ` so that it is possible, for example, to setup custom callbacks on MQTT commands (though the Device class already exposes high-level methods to setup Azure specific callbacks). The only difference concerns :code:`mqtt.connect` method which does not require broker url and ssl context, taking them from Device configuration:: def timestamp_fn(): valid_timestamp = 1509001724 return valid_timestamp key = "ZhmdoNjyBccLrTnku0JxxVTTg8e94kleWTz9M+FJ9dk=" my_device = iot.Device('my-hub-id', 'my-device-id', '2017-06-30', key, timestamp_fn) my_device.mqtt.connect() ... my_device.mqtt.loop() .. method:: on_bound(bound_cbk) Set a callback to be called on cloud to device messages. :samp:`bound_cbk` callback will be called passing a string containing sent message and a dictionary containing sent properties:: def bound_callback(msg, properties): print('c2d msg:', msg) print('with properties:', properties) my_device.on_bound(bound_callback) .. method:: on_method(method_name, method_cbk) Set a callback to respond to a direct method call. :samp:`method_cbk` callback will be called in response to :samp:`method_name` method, passing a dictionary containing method payload (should be a valid JSON):: def send_something(method_payload): if method_payload['type'] == 'random': return (0, {'something': random(0,10)}) deterministic = 5 return (0, {'something': deterministic}) my_device.on_method('get', send_something) :samp:`method_cbk` callback must return a tuple containing response status and a dictionary or None as response payload. .. method:: on_twin_update(twin_cbk) Set a callback to respond to cloud twin updates. :samp:`twin_cbk` callback will be called when a twin update is notified by the cloud, passing a dictionary containing desired twin and an integer representing current twin version:: def twin_callback(twin, version): print('new twin version:', version) print(twin) my_device.on_twin_update(twin_callback) It is possible for :samp:`twin_cbk` to return a dictionary which will be immediately sent as reported twin. .. method:: report_twin(reported, wait_confirm=True, timeout=1000) Report :samp:`reported` twin. :samp:`reported` twin must be a dictionary and will be sent as JSON string. It is possible to not wait for cloud confirmation setting :samp:`wait_confirm` to false or to set a custom :samp:`timeout` (:code:`-1` to wait forever) for the confirmation process which could lead to :code:`TimeoutException`. An integer status code is returned after cloud confirmation. .. method:: get_twin(timeout=1000) Get current twin containing desired and reported fields. It is possible set a custom :samp:`timeout` (:code:`-1` to wait forever) for the process which could lead to :code:`TimeoutException`. An integer status code is returned after cloud response along with received :samp:`twin` JSON-parsed dictionary. .. method:: publish_event(event, properties) Publish a new event :samp:`event` with custom :samp:`properties`. :samp:`event` must be a dictionary and will be sent as json string. :samp:`properties` must be a dictionary and will be sent as an url-encoded property bag.