IoT Hub message payload - how to define Application Properties and Body? - azure-iot-hub

What is needed to define / create Application Properties in a message sent to the IoT hub?
I have one demo device, where I create the message using the C client SDK and everything works fine. Those incoming messages can be routed based on Application Property values and the EventData parameter is set correctly in an Azure Function that listens on the IoT Hub.
Another device is also sending data to the same IoT hub. Code running on this device is developed directly by my customer, but I doubt that they used the SDK. Instead I assume they create the whole payload themselves.
To me the incoming JSON looks basically the same, like the one built with the SDK. It contains a section for applicationProperties and one for the body.
{
"applicationProperties": {
"type": "telemetry",
"version": "1.0"
},
"body": {
"device_id": "sensor1",
"datetime": "2019-05-09T10:44:04Z",
"channels": {
"T": 24.42,
"H": 44.87,
"C": 1234
}
}
}
But it turns out, that the message as a whole is treated as the body.
So why does this message behave different? What needs to be done, to tell IoT Hub what are application properties and what is the real body when not using the SDK?

In the case of using the MQTT protocol directly, the application and system properties are part of the topic, see the following example:
devices/Device1/messages/events/location=abcd&$.to=deviceABC
the output telemetry message received by Visual Studio 2019 Cloud Explorer:
[Monitor D2C Message] [5/9/2019 7:54:40 AM] Message received on partition 2:{"counter":17,"time":"2019-05-09T14:54:40.1984163Z","deviceId":"Device1","windSpeed":9.1991,"temperature":14.88,"humidity":81.66}
Application properties:
location: abcd
System properties:
iothub-connection-device-id: Device1
iothub-connection-auth-method: {"scope":"device","type":"sas","issuer":"iothub","acceptingIpFilterRule":null}
iothub-connection-auth-generation-id: 636550937738557556
iothub-enqueuedtime: 5/9/2019 2:54:38 PM
iothub-message-source: Telemetry
x-opt-sequence-number: 13069
x-opt-offset: 5989280
x-opt-enqueued-time: 5/9/2019 2:54:38 PM
EnqueuedTimeUtc: 5/9/2019 2:54:38 PM
SequenceNumber: 13069
Offset: 5989280
to: deviceABC
In the case of using the connection less protocol such as Https, the application and system properties are part of the headers. The following example shows the above properties from the MQTT protocol:
iothub-app-location:abcd
iothub-to:deviceABC

Related

Messages Patterns - RabbitMQ/NestJS

I'm trying to integrate to a project done using NestJS, a simple api where you can publish messages with a name (or pattern) and send it to that system that has implemented a handler that matches the name.
The system I'm building is really small, it wouldn't make much of a sense using NestJS for that.
The problem I'm having is the following:
I'm creating a simple api that triggers the publish of the message onto a queue.
The consumer is on a system using NestJS.
I can't figure out how to give that messages a pattern that is recognized by that system.
For example:
Let's say I want to publish a message that has a name of "CreateRecord" with a payload to be processed from the other system that has a handler with the same name with an implementation.
Using amqplib how do I give messages a name or pattern?
You can provide a pattern in the content object when you are publishing a message.
publish(
'my_exchange',
'routing_key',
{ pattern: 'CreateRecord', data: 'Record' },
);

Call web service at alerting in grafana

I'm using Grafana and set an alert in a graph, How can I call an external API or web service when alert fired? thanks.
So the goal is to get information into an external service. I am making the assumption that your particular external api / web service is not in the list of supported notification channels.
Personally in this case, I would suggest using the webhook notification channel option, as it gives a TON of information to work through / interact with:
{
"dashboardId":1,
"evalMatches":[
{
"value":1,
"metric":"Count",
"tags":{
}
}
],
"imageUrl":"https://grafana.com/assets/img/blog/mixed_styles.png",
"message":"Notification Message",
"orgId":1,
"panelId":2,
"ruleId":1,
"ruleName":"Panel Title alert",
"ruleUrl":"http://localhost:3000/d/hZ7BuVbWz/test-dashboard?fullscreen\u0026edit\u0026tab=alert\u0026panelId=2\u0026orgId=1",
"state":"alerting",
"tags":{
"tag name":"tag value"
},
"title":"[Alerting] Panel Title alert"
}
This can be sent to any service that is capable of receiving webhooks and translating them into whatever you need for your external API endpoint, I might suggest the following:
integromat.com (Free account gives 1000 operations / month)
n8n.io (OSS and self-hosted but limited direct integration... does have HTTP, so you can use that to interact with whatever (including internal stuff)
Once in either of these tools, you build a webhook receiver and then a workflow that will translate the action into the formats needed by your external API / service.

How to include information about iotEdge capability in device created event in IoT Hub?

I am wondering if it is possible to include information if device is an edge device in Microsoft.Devices.DeviceCreated event data? I receive those events for both type of devices but I am not able to distinguish them and say oh yeah this one is an edge device.
I can see that device twin which I receive is a little bit different than the one I can see in portal. In portal twin contains information about capabilities which say iotEdge: true for edge and false for directly connected devices.
Basically, there are two ways to handle this issue:
The subscriber event handler (EventGridTrigger function) will pull up the full device twins info like you can see on the portal.
Using the Bulk Create or Update REST API call for creating devices with an additional information in the tags. I do recommend this way and based on my answer here, the following is an example of the payload POST:
[
{
"id":"TD_0001",
"importMode":"create",
"status":"enabled",
"tags":{
"capabilities":{
"iotEdge":false
}
}
},
{
"id":"TD_0002",
"importMode":"create",
"status":"enabled",
"tags":{
"capabilities":{
"iotEdge":true
}
},
"capabilities":{
"iotEdge":true
}
}
]
As you can see, the capabilities property has been added in the tags. Basically, you can initialized any device twins properties included a reported property.
The Azure IoT Hub Notification to the AEG is almost immediately and the following screen snippet shows an example of the event message:
and the azure portal screen:

Openfire send message using rest api in php

I am using openfire. I am able to add users and groups. But now stuck at send message from one user to another. I was going through libraries but not found any suitable. I tried xmpp bosh library but getting error:
"message": "Declaration of XMPPHP_BOSH::connect($server, $wait = '1', $session = false) should be compatible with XMPPHP_XMLStream::connect($timeout = 30, $persistent = false, $sendinit = true)",
"exception": "ErrorException",
The REST API Plugin does not provide the feature you are looking fore (1:1 messaging). The REST API Plugin is made to manage the Openfire Instance (Users, Groups, Channels etc.)
To send one to one messages, you could use the openfire chat plugin. (https://github.com/igniterealtime/openfire-chat)
Example:
POST /restapi/v1/chat/{streamid}/messages/{destination}
{
"body" : "desired message"
}

IoT Hub route query does not match on message body

I'm facing some issues with filtering on message body in the Azure IoT Hub. Is this still not supported? The tests go through, but when I try real messages from the device everything is hitting the fallback and not the intended route.ยจ
In other words:
//this is working when adding property to message in the device code
temperature > 30
//this is not working when message contains json object without using any properties
$body.temperature > 30
Do we still need to use the message properties?
This feature (such as a filtering on the $body) requires setup the following message system properties:
message.ContentType = "application/json";
message.ContentEncoding = "utf-8";
See more details here.