The use case is to receive device connected event as soon as the device is connected to the iothub.
There is a device connected/disconnected event that can be captured and routed to eventhub/servicebus/eventgrid, but, this event isn’t triggered in Amqp if the message is sent by .net program i.e it is inconsistent.
Is there any mechanism available to get the recent device connected event in Iothub! Or heartbeat pattern is the only mechanism available or is most efficient way?
Your understanding is correct. Suggestion is to use the Device heartbeat pattern.
The IoT Hub identity registry contains a field called connectionState. Only use the connectionState field during development and debugging. IoT solutions should not query the field at run time. For example, do not query the connectionState field to check if a device is connected before you send a cloud-to-device message or an SMS. We recommend subscribing to the device disconnected event on Event Grid to get alerts and monitor the device connection state. Use this tutorial to learn how to integrate Device Connected and Device Disconnected events from IoT Hub in your IoT solution.
If your IoT solution needs to know if a device is connected, you can implement the heartbeat pattern. In the heartbeat pattern, the device sends device-to-cloud messages at least once every fixed amount of time (for example, at least once every hour). Therefore, even if a device does not have any data to send, it still sends an empty device-to-cloud message (usually with a property that identifies it as a heartbeat). On the service side, the solution maintains a map with the last heartbeat received for each device. If the solution does not receive a heartbeat message within the expected time from the device, it assumes that there is a problem with the device.
Related
I did followings successfully:
Creating a hono tenant and registering a device for it.
Connecting a simple python based edge-device to hono.
Connecting hono to ditto.
Creating a twin for the above edge-device.
Sending telemtery data from the edge-device to ditto through hono works perfectly.
I also send a pseudo event every second form edge-device to ditto through hono as follows:
# sending an event from edge-device to ditto through hono-mqtt-adapter
correlation_id = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10))
data = {
"topic": "de.iot1/dev1/things/live/messages/fire",
"headers": {
"content-type": "text/plain",
"correlation-id": correlation_id
},
"path": "/outbox/messages/fire",
"value": "Fire detected"
}
payload = json.dumps(data)
mqtt_client.publish("event", payload=payload, qos=1)
On the other side I wrote a simple ditto-amqp-client which just receives all dittos incomming messages. I receive all incoming telemetry messages as their correct interval - i.e. every second. In the case of events messages they seems to be buffered by ditto and sent to amqp-client every couple of seconds and not at the time they are send from the device! Why?
As far as I understood from the ditto-doc, ditto offers two communication channels. twin-channel for communicating with the twin through commands and events and a live-channel to communicate with the device directly through messages. But in the section protocol-topics
the channel can be either twin or live also for events or commands, which is confusing.
I would like to know what is the recommended way to send an event form the device to ditto?
Should one send it through live channels using events or messages (outbox)?
Is it better to define the event as a feature in the twin and send normal command/modify to its value?
Thanks in advance for any suggestion!
I receive all incoming telemetry messages as their correct interval - i.e. every second. In the case of events messages they seems to be buffered by ditto and sent to amqp-client every couple of seconds and not at the time they are send from the device! Why?
As Ditto does not do a "store-and-forward", but publishes applied events immediately, I can't really explain from Ditto side. Maybe by sending events (which in Hono are persisted using an AMQP broker), those are consumed with some delay (after persisted by the broker), however I can't explain the "every couple of seconds".
You could enable DEBUG logging in Ditto's connectivity service by setting the environment variable LOG_LEVEL_APPLICATION to DEBUG - that way you'll see when the messages are received and when they are forwarded again to your AMQP endpoint.
I would like to know what is the recommended way to send an event form the device to ditto?
Should one send it through live channels using events or messages (outbox)?
When you talk about the "fire detected" event (containing a payload which shall not be stored in a twin managed by Ditto), I would send it as live message from the device (using Hono event channel with "QoS 1" - at least once - semantics).
However, an application connected to Ditto (e.g. via Websocket or via HTTP webhook) must be consuming the live message and acknowledging that it received the message.
Events in Ditto are the entity which is persisted as part of the CQRS architecture style. After persisting, interested parties can be notified about them.
So live events are meant to be in the same Ditto event format and must not be confused with Hono events.
Is it better to define the event as a feature in the twin and send normal command/modify to its value?
It depends on your requirements.
You could also make the "fireDetected" a boolean property in a feature and subscribe to changes of this property. But then this should be only settable via the device (using an appropriate Ditto Policy) - and the "QoS 1" guarantees you get by combining Hono and Ditto cannot be used any longer.
I am using the azure IOT sdk in an ESP32-based device to connect to the IOT hub using MQTT, sending messages with QOS 1. When the connection is good, all works exactly as intended. However, when we deploy to areas where the connectivity seems somewhat more spotty, the messages often time out (i.e. callback is called with the timeout error). The MQTT still thinks it has a connection (i.e. the disconnect callback has not been called), but all sends end up timing out. Interestingly, I see that when I send c2d messages, they do get picked up.
I have configured the firmware to tear down and rebuild the MQTT connection in these scenarios and that sometimes helps but not always.
Two questions:
Why does this seem to happen, and are there parameters that I can twiddle to prevent it. I have reduced the size of the packets but that did not seem to make a difference.
What is the appropriate way of handling this condition? I have seen scenarios where once the communication gets "stuck" like this, it can stay stuck for tens of minutes.
Hope there's someone from MSFT IOT group listening... :)
I'm coding a project which needs cloud control device operation, and want to keep information in sync.
The cloud needs to know the state of device, such as when the network is interrupted and when the network is restored.
When the network is restored, the modified information on the cloud is synchronized to device.
anyone got an idea of how my approach should be like? any tips?
I intend to add resident programs in the background at both ends to determine, but in fact, it is impossible for the cloud in the project to connect only one device, and multiple apps may run in one device, which is very tedious to do. Is there any simple component to realize this function?
I wish control information and data information to be synchronized on the cloud and device
Based on your tag, I'm assuming that you are using MQTT as a messaging protocol for your system. If so, to address your need for tracking the device-cloud connection state, MQTT specifies a feature called "Last Will and Testament".
From the MQTT 3.1.1 Standard Section 3.1.2.5:
If the Will Flag is set to 1 this indicates that, if the Connect request is accepted, a Will Message MUST be stored on the Server and associated with the Network Connection. The Will Message MUST be published when the Network Connection is subsequently closed unless the Will Message has been deleted by the Server on receipt of a DISCONNECT Packet [MQTT-3.1.2-8].
This can be leveraged to let the remote MQTT client on the cloud know when the device is connected and when it disconnects by publishing an online payload to a topic (for example) device/conn_status after a successful connection, and registering a Last Will offline message to the same topic. Now, whenever the device client goes offline, the broker will publish the offline payload on his behalf to the cloud client that can now act accordingly.
I have the following situation in Azure IOT Hub:
Script sends message to device queue. Listening with device explorer: Succes
Script listens for message to device queue. Sending with device explorer: Succes
This problem arises:
Script listens for message to device queue. Other script sends message to device queue: Listener does not receive the message.
So, it works well using the device explorer tool. But with the scripts only, the listener does not receive.
I hope someone might be able to help me with this issue.
There might be two possible problems on your side:
a) Device Explorer shows messages only from one device. If you have two separate device clients, you have to select another one.
b) But it's possible that you send and receive on two separate scripts with one deviceId (clientId) - it might be the problem.
Looking at various GATT-based profiles, it seems that services are always exposed in the GATT server rather than the GATT client. For instance, the Time Profile (TIP) has the server exposing the Current Time Service (CTS). So, if a phone is to update a heart rate monitor with the current time using TIP, the phone will be the server whereas the monitor will be the client. But, being a heart rate monitor, the Heart Rate Profile expects the monitor to be a GATT server.
So, for a monitor that takes the current time from a phone, should it be a GATT client or server? Should it be set as a client whilst time syncing with the phone and set as a server otherwise? Should a custom profile be implemented such that the CTS is exposed in the client instead?
Thanks
Generic Attribute Profile (GATT) defines how server and client communicate with
each other using Attribute Protocol for the purpose of transporting data. Client
and server roles are determined when a procedure is initiated and released when the procedure is ended. Hence, a device can act in both roles at the same time.
I would suggest you to read Bluetooth Spec. In Part G 2.2 it explains the roles and configurations.
Client—This is the device that initiates commands and requests towards the
server and can receive responses, indications and notifications sent by the
server.
Server—This is the device that accepts incoming commands and requests
from the client and sends responses, indications and notifications to a client.
Back to your question:
The Time profile enables the device to get the date, time, time zone,
and DST information and control the functions related the time.
In your case, the monitor will be the GATT client when it takes the time from a phone. However, it can be a server at the same time for another procedure (operation, request etc.) with the phone.
In short, client and server roles are not fixed to the devices. When your phone exposes the current time, it will be server. Similarly, when it gets the current time from the monitor, it will be client. no need to customize the profile. If you want your phone to get the current time from a device and expose it to another device, just implement the same profile for client and server roles to your phone.
EDIT:
According to TIP profile spec, to get the current time information, the GATT Read Characteristic Value sub-procedure shall be used with the handle of the Current Time Characteristic. Monitor as a client will read the Current Time Characteristic from the GATT Table of the server (in this case it is the phone). As soon as the monitor retrieves the value from phone, it can update its Current Time Characteristic Value, and expose it to its environment in three ways:
Notifying it to its subscribed clients (BLE notifications). If you do it in this way, you will customize the Bluetooth TIP profile since this procedure is not defined there (I had a quick look to the document and didn't see it).
Broadcasting it in the advertisement packet (Doesn't require BLE connection)
Another BLE device connects to the monitor and reads the Current Time Characteristic value. This is the recommended way if you want to use Bluetooth SIG defined TIP profile as a server.