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.
Related
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.
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 currently trying to implement some processing of C2D messages. So far sending a C2D message from an IoT Hub Function works like a charm and I'm receiving and processing the payload without any problems.
My problem however is, that on the initiating side I always get a positive ACK, even if I kill the IoT device while processing the command. It seems all documentation starts becoming a little vague as soon as it comes to responses to C2D messages. And I did read the related documents of the IoT Hub functionality multiple times ... Hope I didn't miss an essential part, but I doubt it.
So how can I explicitly send a response back to the initiator which also contains a payload?
I'm currently on the free demo-subscription as I'm doing my first steps with IoT Hub.
Help greatly appreciated.
A good place to start for any communication from cloud to the device is this page. From what I can tell, in your situation, you might want to use a Direct Method rather than a C2D message. A C2D message is great for notifying the device, but as you experienced, there are no built-in features for responding to the message.
A direct method allows to send a request to a device, and for that device to respond to it. Both the request and response are allowed a 128 KB JSON payload, so you can use that on the device-side to send something back.
Update:
Like mentioned in the comments, you don't have a lot of influence on how to handle C2D messages from the device, other than accepting/rejecting it. Here's how you would reject a message using the C# Device SDK.
private async Task RejectSample()
{
var deviceClient = DeviceClient.CreateFromConnectionString("muchconnectionstring");
var message = await deviceClient.ReceiveAsync();
// await deviceClient.CompleteAsync(message);
await deviceClient.RejectAsync(message);
}
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.