.. _dl_mech: Downlink Mechanisms ******************* When a :class:`.DownlinkMessage` conductor needs a *route* to send the message to. *Routes* consists of the recipient end-node address, appended by the :ref:`gateway` that the message will be sent to. The routes are saved in Conductor from the route that the class:`.UplinkMessage` takes when sending data to Conductor. These routes are persisted in conductor for some time and can be retrieved from both :class:`.Module` and :class:`.DownlinkMessage` objects :: my_mod = account.get_module("$301$0-0-0-03000XXXX") my_mod.get_routes() dl_msg = my_mod.send_message(b'Hello World') dl_msg.get_routes() Which, in both cases, returns :: [ '$301$0-0-0-03000XXXX!101!$101$0-0-0-dbYYYYYYY', '$301$0-0-0-03000XXXX!101!$101$0-0-0-dbZZZZZZZ' ] By default, Conductor will use all routes that the module has used in the *recent* past to send the message. This means that each gateway in that list will receive the :class:`.DownlinkMessage`. In cases where this is not the desired behavior, the *gateway* parameter can be used in the :meth:`Module.send_message` method to use only one route :: # Using the Gateay's Address dl_msg = my_mod.send_message(b'Hello World', gateway="$101$0-0-0-dbYYYYYYY") # Or a Gateway Object. my_gw = account.get_gateway("$101$0-0-0-dbYYYYYYY") dl_msg = my_mod.send_message(b'Hello World', gateway=my_gw) # Which only uses this route: "$301$0-0-0-03000XXXX!101!$101$0-0-0-dbYYYYYYY" When the :class:`.DownlinkMessage` is sent, you can check it's status by getting the Downlink Events for that downlink: :meth:`DownlinkMessage.get_events`. This returns an array of events, with their correlated timestamps, for each *route* utilized. :: dl_msg = my_mod.send_message(b'Hello World') dl_msg.get_events() { '$301$0-0-0-03000XXXX!101!$101$0-0-0-dbYYYYYYY': [ ('Issued', datetime.datetime(2016, 6, 9, 21, 45, 56, 585000)), ('Submitting', datetime.datetime(2016, 6, 9, 21, 45, 57, 158000)), ('Submitted', datetime.datetime(2016, 6, 9, 21, 45, 57, 349000)), ('Sending', datetime.datetime(2016, 6, 9, 21, 45, 57, 403000)), ('Sent', datetime.datetime(2016, 6, 9, 21, 45, 57, 945000)), ('Expired', datetime.datetime(2016, 6, 9, 21, 47, 36, 531000)) ], '$301$0-0-0-03000XXXX!101!$101$0-0-0-dbZZZZZZZ': [ ('Issued', datetime.datetime(2016, 6, 9, 21, 45, 56, 585000)), ('Expired', datetime.datetime(2016, 6, 9, 21, 47, 36, 531000)) ] } The possible Conductor Events, and their significance are as follows... ====================== ========================================================= Status Message Description ====================== ========================================================= Pending Has not yet expired and has not yet met its acknowledgement requirements. ---------------------- --------------------------------------------------------- Expired Has not met its acknowledgement requirements within the Time to Live expiration of the Command given its issuance time. ---------------------- --------------------------------------------------------- Failed Has either not been able to be propagated to its intended targets or the intended targets have not accepted it. ---------------------- --------------------------------------------------------- AcknowledgedSuccessful Has met its successful acknowledgement requirements. ---------------------- --------------------------------------------------------- Successful Has met its acknowledgement requirements of any type. ====================== ========================================================= The only way to be sure that a node received a :class:`.DownlinkMessage`, however, is to use the Acknowledgement Mechanism. This is enabled by default for standard *Unicast* messages (with one recipient). This can be explicitly set like this :: dl_msg = mod.send_message(b'Hello World', acked=True) This will then add the "AcknowledgedSuccessful" event to the Downlink Events. .. warning:: The Acknowledgement Mechanism only works for **Unicast** Downlink Messages; **Multicast** Downlink Messages are not Acknowledged. See :ref:`app-tok` for more information regarding **Multicast** Downlink. When a Downlink is sent, you can also wait for the message to be recieved using the blocking method :meth:`DownlinkMessage.wait_for_success` :: msg = module.send_message(b'hello') msg.wait_for_success()