Properly Create a Device Template from a Live Device in Azure IOT Central - azure-iot-central

I have LoRaWAN IoT devices from the TTN network, which I have brought to Azure IoT Central. I would like to get specific data inside the JSON in order to make alert rules. Here is a sample of the JSON I receive from a Milesight PIR & Light Sensor. Suppose I only want to get the "battery", "daylight" and "pir" values to make the alert, how do I go about that?
{
"end_device_ids": {
"device_id": "eui-24e124538c195063",
"application_ids": {
"application_id": "test-1117"
},
"dev_eui": "24E124538C195063",
"join_eui": "24E124C0002A0001",
"dev_addr": "260D82F3"
},
"received_at": "2023-02-01T13:52:47.892042526Z",
"uplink_message": {
"session_key_id": "AYYLj9wg6AeehHWwDLrzLg==",
"f_port": 85,
"f_cnt": 38,
"frm_payload": "AXVkAwAABAAA",
"decoded_payload": {
"battery": 100,
"daylight": "dark",
"pir": "normal"
},
"rx_metadata": [
{
"gateway_ids": {
"gateway_id": "eui-24e124fffef5531c",
"eui": "24E124FFFEF5531C"
},
"time": "2023-02-01T13:52:47.429725885Z",
"timestamp": 2696081442,
"rssi": -64,
"channel_rssi": -64,
"snr": 13,
"uplink_token": "CiIKIAoUZXVpLTI0ZTEyNGZmZmVmNTUzMWMSCCThJP/+9VMcEKLgy4UKGgwIr93pngYQ94rGxQIg0Ino17uJFw==",
"received_at": "2023-02-01T13:52:47.596682842Z"
}
],
"settings": {
"data_rate": {
"lora": {
"bandwidth": 125000,
"spreading_factor": 7,
"coding_rate": "4/5"
}
},
"frequency": "867700000",
"timestamp": 2696081442,
"time": "2023-02-01T13:52:47.429725885Z"
},
"received_at": "2023-02-01T13:52:47.683989041Z",
"confirmed": true,
"consumed_airtime": "0.061696s",
"network_ids": {
"net_id": "000013",
"tenant_id": "ttn",
"cluster_id": "au1",
"cluster_address": "au1.cloud.thethings.network"
}
},
"_eventtype": "Telemetry",
"_timestamp": "2023-02-01T13:52:49.35Z"
}

I was able to get the values by uploading my own DTDL.
Once the device sends data to Azure IOT Central from TTN, the device will have no template.
I first created a template from the raw telemetry sent.
I went to the new device template created, clicked EDIT DTDL, then placed the following JSON:
{
"#id": "dtmi:telavi:eui24e124538c195063;1",
"#type": "Interface",
"contents": [
{
"#type": [
"Telemetry",
"DateTimeValue"
],
"displayName": {
"en": "received_at"
},
"name": "received_at",
"schema": "dateTime"
},
{
"#type": [
"Telemetry",
"NumberValue"
],
"description": {
"en": "battery"
},
"displayName": {
"en": "battery"
},
"name": "battery",
"schema": "integer"
},
{
"#type": [
"Telemetry",
"StringValue"
],
"description": {
"en": "daylight"
},
"displayName": {
"en": "daylight"
},
"name": "daylight",
"schema": "string"
},
{
"#type": [
"Telemetry",
"StringValue"
],
"description": {
"en": "pir"
},
"displayName": {
"en": "pir"
},
"name": "pir",
"schema": "string"
}
],
"displayName": {
"en": "eui-24e124538c195063"
},
"#context": [
"dtmi:iotcentral:context;2",
"dtmi:dtdl:context;2"
]
}

Related

How set desired and reported properties for device twin in IoT Plug and Play DTDL model

I have this dtdl model I upload to local folder in IoT Plug and Play v0.15.4.0 (prior version behaviour is the same):
{
"#id": "dtmi:com:sergio:devkit;1",
"#type": "Interface",
"#context": [
"dtmi:dtdl:context;2"
],
"displayName": "Machine Part -v1",
"description": "Machine Part data",
"contents": [
{
"#type": "Property",
"name": "telemetryInterval",
"displayName": "telemetryInterval",
"description": "The time interval of this data",
"schema": "double",
"writable": true
},
{
"#type": "Property",
"name": "PartId",
"displayName": "PartId",
"description": "The unique id of the machine part",
"writable": true,
"schema": "string"
},
{
"#type": "Property",
"name": "Alert",
"displayName": "Alert",
"description": "whether or not this machine part needs maintenance",
"writable": true,
"schema": "boolean"
},
{
"#type": "Property",
"name": "ledState",
"displayName": "LED state",
"description": "Returns the current state of the onboard LED.",
"writable": true,
"schema": "boolean"
},
{
"#type": "Telemetry",
"name": "Description",
"schema": "string"
},
{
"#type": "Telemetry",
"name": "Code",
"schema": "integer"
},
{
"#type": "Telemetry",
"name": "Temperature",
"displayName": "Temperature",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "Humidity",
"displayName": "Humidity",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "pressure",
"displayName": "Pressure",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "magnetometerX",
"displayName": "Magnetometer X / mgauss",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "magnetometerY",
"displayName": "Magnetometer Y / mgauss",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "magnetometerZ",
"displayName": "Magnetometer Z / mgauss",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "accelerometerX",
"displayName": "Accelerometer X",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "accelerometerY",
"displayName": "Accelerometer Y",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "accelerometerZ",
"displayName": "Accelerometer Z",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "gyroscopeX",
"displayName": "Gyroscope X",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "gyroscopeY",
"displayName": "Gyroscope Y",
"schema": "double"
},
{
"#type": "Telemetry",
"name": "gyroscopeZ",
"displayName": "Gyroscope Z",
"schema": "double"
}
]
}
My expectation is that because properties ledState and Alert properties are writeable, these should be both reported and desired properties. However the IoT Hub Device in Azure portal (see below) shows them differently and I don't know why. How do I set the properties in the DTDL model I upload to IoT P&P to be reported or desired?
{
"deviceId": "mymxchip",
"etag": "AAAAAAAAAAk=",
"deviceEtag": "NDU1NDk0NDM4",
"status": "enabled",
"statusUpdateTime": "0001-01-01T00:00:00Z",
"connectionState": "Connected",
"lastActivityTime": "2023-01-09T07:26:48.611708Z",
"cloudToDeviceMessageCount": 0,
"authenticationType": "sas",
"x509Thumbprint": {
"primaryThumbprint": null,
"secondaryThumbprint": null
},
"modelId": "dtmi:com:sergio:devkit;1",
"version": 164,
"properties": {
"desired": {
"telemetryInterval": 5,
"Alert": true,
"$metadata": {
"$lastUpdated": "2023-01-08T07:27:01.9659284Z",
"$lastUpdatedVersion": 9,
"telemetryInterval": {
"$lastUpdated": "2023-01-08T06:54:11.9502921Z",
"$lastUpdatedVersion": 8
},
"Alert": {
"$lastUpdated": "2023-01-08T07:27:01.9659284Z",
"$lastUpdatedVersion": 9
}
},
"$version": 9
},
"reported": {
"deviceInformation": {
"__t": "c",
"manufacturer": "MXCHIP",
"model": "AZ3166",
"swVersion": "1.0.0",
"osName": "Azure RTOS",
"processorArchitecture": "Arm Cortex M4",
"processorManufacturer": "STMicroelectronics",
"totalStorage": 1024,
"totalMemory": 128
},
"ledState": false,
"telemetryInterval": {
"ac": 200,
"av": 1,
"value": 5
},
"$metadata": {
"$lastUpdated": "2023-01-09T07:28:26.0068306Z",
"deviceInformation": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z",
"__t": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"manufacturer": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"model": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"swVersion": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"osName": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"processorArchitecture": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"processorManufacturer": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"totalStorage": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
},
"totalMemory": {
"$lastUpdated": "2023-01-09T07:28:25.4599426Z"
}
},
"ledState": {
"$lastUpdated": "2023-01-09T07:28:25.7411971Z"
},
"telemetryInterval": {
"$lastUpdated": "2023-01-09T07:28:26.0068306Z",
"ac": {
"$lastUpdated": "2023-01-09T07:28:26.0068306Z"
},
"av": {
"$lastUpdated": "2023-01-09T07:28:26.0068306Z"
},
"value": {
"$lastUpdated": "2023-01-09T07:28:26.0068306Z"
}
}
},
"$version": 155
}
},
"capabilities": {
"iotEdge": false
}
}
You're correct that a DTDL writable property will appear as both a reported and desired property in the device twin. However, this is dependant and the behavior of the device.
If you set a desired property using a service API, that updates the desired property value in the device twin. The device should then send an Ack when it's received and processed the desired property - in your example above, it looks as if the device has done this for the telemetryInterval property. The device hasn't acknowledged the Alert desired property update.
When the device sends a reported property, the device twin is updated with the value sent by the device. In the example above, the device has sent deviceInformation, ledState, and telemetryInterval reported properties. The telemetryInterval was sent in response to a desired property.
You can find more details here:
https://learn.microsoft.com/en-us/azure/iot-develop/concepts-convention#writable-properties
https://learn.microsoft.com/en-us/azure/iot-develop/concepts-developer-guide-device#writable-properties (device code samples in multiple languages)
To following samples for a thermostat device all illustrate how to follow the PnP conventions for writable properties:
https://github.com/Azure/azure-iot-sdk-csharp/tree/main/iothub/device/samples/solutions/PnpDeviceSamples/Thermostat
https://github.com/Azure/azure-iot-sdk-java/tree/main/device/iot-device-samples/pnp-device-sample
https://github.com/Azure/azure-iot-sdk-node/tree/main/device/samples
https://github.com/Azure/azure-iot-sdk-python/tree/main/samples/pnp

Alexa CBT Test: Failed Test due to DeepQuery=True

My colleagues and I have been working to fix a reported issue on our Amazon Alexa CBT Test regarding the value “DeepQuery=true”.
Our code has been modified, so that every state change is reported automatically and all the used interfaces have the properties “proactivelyReported” and “retrievable” set to true.
As has been suggested by the WWA-Support we used the Smart Home Debugger of the Developer Console to validate the ReportEvents (e.g. Discovery or ChangeReport) and we checked the state of our device on the “View Device State” page (both pages are referenced on: https://developer.amazon.com/en-US/docs/alexa/smarthome/debug-your-smart-home-skill.html).
For debugging purposes we scaled our device capabilities down to just the PowerController. The AddOrUpdateReport of Alexa.Discovery looks to our eyes now exactly as expected/documented. Same goes for the ChangeReport, which we proactively send right after the AddOrUpdateReport (Two sample-Reports for both are provided at the end).
Unfortunately we are still faced with the issue, that “DeepQuery=true” on the “View Device State” page.
If we set the interface property “retrievable” to false, “DeepQuery=false”, but the Alexa-App does not retain the current state of the device. In this configuration the Alexa-App can only be used to send commands, which unfortunately will lead to other test cases to fail.
Does anyone know how to solve this issue?
How can we set “proactivelyReported” and “retrievable” to true and have “DeepQuery=false”?
Any help would be greatly appreciated and I will gladly provide more informations if needed.
Sample AddOrUpdateReport from Smart Home Debugger
{
"header": {
"namespace": "SkillDebugger",
"name": "CaptureDebuggingInfo",
"messageId": "05b030fb-6393-4ae0-80d0-47fc27876f0e"
},
"payload": {
"skillId": "amzn1.ask.skill.055ca62d-3cf8-4f51-a683-9a98b36f4637",
"timestamp": "2021-09-09T13:28:21.629Z",
"dialogRequestId": null,
"skillRequestId": null,
"type": "SmartHomeAddOrUpdateReportSuccess",
"content": {
"addOrUpdateReport": {
"event": {
"header": {
"namespace": "Alexa.Discovery",
"name": "AddOrUpdateReport",
"messageId": "2458b969-7c3e-47e2-ab0b-6e13a999be76",
"payloadVersion": "3"
},
"payload": {
"endpoints": [
{
"manufacturerName": "Our Company Name",
"description": "Our Product Name",
"endpointId": "device--cb12b420-1171-11ec-81f3-cb34e87ea438",
"friendlyName": "Lampe 1",
"capabilities": [
{
"type": "AlexaInterface",
"version": "3",
"interface": "Alexa.PowerController",
"properties": {
"supported": [
{
"name": "powerState"
}
],
"proactivelyReported": true,
"retrievable": true
}
},
{
"type": "AlexaInterface",
"interface": "Alexa",
"version": "3"
}
],
"displayCategories": [
"LIGHT"
],
"connections": [],
"relationships": {},
"cookie": {}
}
],
"scope": null
}
}
}
}
}
}
Sample ChangeReport from Smart Home Debugger
{
"header": {
"namespace": "SkillDebugger",
"name": "CaptureDebuggingInfo",
"messageId": "194a96a1-6747-46ba-8751-5c9ef715fd34"
},
"payload": {
"skillId": "amzn1.ask.skill.055ca62d-3cf8-4f51-a683-9a98b36f4637",
"timestamp": "2021-09-09T13:28:23.227Z",
"dialogRequestId": null,
"skillRequestId": null,
"type": "SmartHomeChangeReportSuccess",
"content": {
"changeReport": {
"event": {
"header": {
"namespace": "Alexa",
"name": "ChangeReport",
"messageId": "8972e386-9622-40e6-85e7-1a7d81c79c8a",
"payloadVersion": "3"
},
"endpoint": {
"scope": null,
"endpointId": "device--cb12b420-1171-11ec-81f3-cb34e87ea438"
},
"payload": {
"change": {
"cause": {
"type": "APP_INTERACTION"
},
"properties": [
{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": "ON",
"timeOfSample": "2021-09-09T13:28:18.088Z",
"uncertaintyInMilliseconds": 500
}
]
}
}
},
"context": {
"properties": []
}
}
}
}
}

Dialogflow textToSpeech fulfilment not reading aloud the text

I am providing users with a response on an audio only device (e.g. google home), when I respond with a textToSpeech field within a simpleResponse, the speech is not read out in the simulator.
Has anyone experienced this and know how to fix?
I've tried different response types but none of them read out the textToSpeech field.
Also tried ticking/unticking end conversation toggle in Dialogflow and expectUserInput true/false when responding with JSON to no avail.
The response is currently fulfilled by a webhook which responds with JSON v2 fulfilment blob and the simulator receives the response with no errors but does not read it out.
RESPONSE -
{
"payload": {
"google": {
"expectUserResponse": true,
"richResponse": {
"items": [
{
"simpleResponse": {
"textToSpeech": "Here are the 3 closest restaurants that match your criteria,"
}
}
]
}
}
}
}
REQUEST -
{
"responseId": "404f3b65-73a5-47db-9c17-0fc8b31560a5",
"queryResult": {
"queryText": "actions_intent_NEW_SURFACE",
"parameters": {},
"allRequiredParamsPresent": true,
"outputContexts": [
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/findrestaurantswithcuisineandlocation-followup",
"lifespanCount": 98,
"parameters": {
"location.original": "Shoreditch",
"cuisine.original": "international",
"cuisine": "International",
"location": {
"subadmin-area": "Shoreditch",
"subadmin-area.original": "Shoreditch",
"subadmin-area.object": {}
}
}
},
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/actions_capability_account_linking"
},
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/actions_capability_audio_output"
},
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/google_assistant_input_type_voice"
},
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/actions_capability_media_response_audio"
},
{
"name": "projects/my-project/agent/sessions/sessionId/contexts/actions_intent_new_surface",
"parameters": {
"text": "no",
"NEW_SURFACE": {
"#type": "type.googleapis.com/google.actions.v2.NewSurfaceValue",
"status": "CANCELLED"
}
}
}
],
"intent": {
"name": "projects/my-project/agent/intents/0baefc9d-689c-4c33-b2b8-4e130f626de1",
"displayName": "Send restaurants to mobile"
},
"intentDetectionConfidence": 1,
"languageCode": "en-us"
},
"originalDetectIntentRequest": {
"source": "google",
"version": "2",
"payload": {
"isInSandbox": true,
"surface": {
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.MEDIA_RESPONSE_AUDIO"
},
{
"name": "actions.capability.ACCOUNT_LINKING"
}
]
},
"requestType": "SIMULATOR",
"inputs": [
{
"rawInputs": [
{
"query": "no",
"inputType": "VOICE"
}
],
"arguments": [
{
"extension": {
"#type": "type.googleapis.com/google.actions.v2.NewSurfaceValue",
"status": "CANCELLED"
},
"name": "NEW_SURFACE"
},
{
"rawText": "no",
"textValue": "no",
"name": "text"
}
],
"intent": "actions.intent.NEW_SURFACE"
}
],
"user": {
"userStorage": "{\"data\":{}}",
"lastSeen": "2019-04-12T14:31:23Z",
"locale": "en-US",
"userId": "userID"
},
"conversation": {
"conversationId": "sessionId",
"type": "ACTIVE",
"conversationToken": "[\"defaultwelcomeintent-followup\",\"findrestaurantswithcuisineandlocation-followup\",\"findrestaurantswithcuisineandlocation-followup-2\"]"
},
"availableSurfaces": [
{
"capabilities": [
{
"name": "actions.capability.AUDIO_OUTPUT"
},
{
"name": "actions.capability.SCREEN_OUTPUT"
},
{
"name": "actions.capability.WEB_BROWSER"
}
]
}
]
}
},
"session": "projects/my-project/agent/sessions/sessionId"
}
I expect the simulator to read out the result of textToSpeech but currently does not.

How to fix "it doesn't support that" when I query Alexa retrievable property

I have this endpoint with powerState and connectivity properties both retrievable:
{
"endpointId": "123",
"manufacturerName": "abc",
"friendlyName": "lamp",
"description": "lamp",
"displayCategories": [
"LIGHT"
],
"capabilities": [
{
"type": "AlexaInterface",
"interface": "Alexa.PowerController",
"version": "3",
"properties": {
"supported": [{
"name": "powerState"
}],
"retrievable": true
}
},
{
"type": "AlexaInterface",
"interface": "Alexa.EndpointHealth",
"version": "3",
"properties": {
"supported": [{
"name": "connectivity"
}],
"retrievable": true
}
}
],
"cookie": {}
}
I respond to ReportState request by sending the state of both properties:
{
"context": {
"properties": [
{
"namespace": "Alexa.PowerController",
"name": "powerState",
"value": "ON",
"timeOfSample": "2019-01-10T10:17:19.99Z",
"uncertaintyInMilliseconds": 50
},
{
"namespace": "Alexa.EndpointHealth",
"name": "connectivity",
"value": {
"value": "OK"
},
"timeOfSample": "2019-01-10T10:17:19.90Z",
"uncertaintyInMilliseconds": 50
}
]
},
"event": {
"header": {
"namespace": "Alexa",
"name": "StateReport",
"payloadVersion": "3",
"messageId": "cde",
"correlationToken": "efg123"
},
"endpoint": {
"scope": {
"type": "BearerToken",
"token": "ab123"
},
"endpointId": "123",
"cookie": {}
},
"payload": {}
}
}
And I send the same context in the PowerController response.
In the Alexa app I can see my device, turn it on and off and view its state rightly. I can ask Alexa to turn on and off my device and the response in "OK", but if I try to ask:** "Is my device turned on?" ** Alexa answers that this device doesn't support that.
The skill language is Italian and PowerController documentation https://developer.amazon.com/it/docs/device-apis/alexa-powercontroller.html says that query is supported.
What am I missing?

ARM Template for Azure Custom Connector using On-Premises Data Gateway

I am trying to make an ARM Template for a Custom Connector which needs to have enabled the use of on-premises Data Gateway. I am getting everything right except this last requirement, since I create a fully configured Custom Connector, except for the fact that the check-mark for using the on-premises Data Gateway is not active.
Any idea which setting/element I need to add change to get this done?
This is my template up to now:
{
"type": "Microsoft.Web/customApis",
"name": "[parameters('Connection_Name')]",
"apiVersion": "2016-06-01",
"location": "centralus",
"scale": null,
"properties": {
"connectionParameters": {
"authType": {
"type": "string",
"allowedValues": [
{
"value": "none"
}
],
"uiDefinition": {
"displayName": "Authentication Type",
"description": "Authentication type to connect to your API",
"tooltip": "Authentication type to connect to your API",
"constraints": {
"tabIndex": 1,
"required": "true",
"allowedValues": [
{
"text": "none",
"value": "anonymous"
}
],
"capability": [
"gateway"
]
}
}
},
"gateway": {
"type": "gatewaySetting",
"gatewaySettings": {
"dataSourceType": "CustomConnector",
"connectionDetails": []
},
"uiDefinition": {
"constraints": {
"tabIndex": 4,
"required": "true",
"capability": [
"gateway"
]
}
}
}
},
"backendService": {
"serviceUrl": "[parameters('ServiceUrl')]"
},
"apiType": "Soap",
"wsdlDefinition": {
"importMethod": "SoapPassThrough"
},
"swagger": {
"swagger": "2.0",
"info": {
"title": "SOAP pass-through",
"description": "Custom Connector for SOAP Operation",
"version": "1.0"
},
"host": "xxxxxxxxxxxxx",
"basePath": "/xxxxxxxx/xxxxxxxxxx",
"consumes": [],
"produces": [],
"paths": {
"/": {
"post": {
"responses": {
"default": {
"description": "default",
"schema": {
"type": "string",
"title": "",
"x-ms-visibility": "important"
},
"headers": {
"Content-Type": {
"description": "Content-Type",
"type": "string"
}
}
}
},
"summary": "GetOrigins",
"description": "GetOrigins",
"operationId": "GetOrigins",
"parameters": [
{
"name": "Content-Type",
"in": "header",
"required": false,
"type": "string"
},
{
"name": "body",
"in": "body",
"required": false,
"schema": {
"type": "string"
}
}
]
}
}
},
"definitions": {},
"parameters": {},
"responses": {},
"securityDefinitions": {},
"security": [],
"tags": [],
"schemes": [
"http"
]
},
"description": "[concat('Custom Connector for SOAP', parameters('Connection_Name'),' Operation')]",
"displayName": "[parameters('Connection_Name')]",
"iconUri": "/Content/retail/assets/default-connection-icon.6296199fc1d74aa45ca68e1253762025.2.svg"
},
"dependsOn": []
}
To enable the 'On-Premises Data Gateway' option, you need to add gateway to the capabilities array like so:
"properties" {
"capabilities": [
"gateway"
],
}
the On-Premises Data Gateway option is not available from ARM templates, you must to install your template and manually add the check box from the Azure portal.
Thanks.

Resources