Преобразование данных внутри приложения IoT Central для экспорта
Устройства Интернета вещей (IoT) отправляют данные в различных форматах. Чтобы использовать данные устройства в решении Интернета вещей, может потребоваться преобразовать данные устройства перед экспортом в другие службы.
В этой статье показано, как преобразовать данные устройства в рамках определения экспорта данных в приложении IoT Central.
Преобразования в определении экспорта данных IoT Central позволяют управлять форматом и структурой данных устройства перед экспортом в место назначения. Можно указать преобразование для каждого назначения в определении экспорта. Каждое сообщение проходит через преобразование, чтобы создать выходную запись для экспорта в место назначения.
Используйте преобразования для реорганизации полезных данных JSON, переименования полей, фильтрации полей и выполнения простых вычислений по значениям телеметрии. Например, используйте преобразование для конвертации сообщений в табличный формат, соответствующий схеме назначения, например таблице Azure Data Explorer.
В следующем видео представлено преобразование данных IoT Central:
Добавление преобразования
Чтобы добавить преобразование для назначения в определении экспорта данных, выберите +Преобразовать , как показано на следующем снимке экрана:
Панель преобразования данных позволяет указать преобразование. В 1. Добавьте раздел входного сообщения, можно ввести образец сообщения, который требуется передать через преобразование. Вы также можете создать образец сообщения, выбрав шаблон устройства. В 2. Раздел запроса преобразования сборки можно ввести запрос, который преобразует входное сообщение. 3. В разделе "Предварительный просмотр выходных сообщений" показан результат преобразования:
Совет
Если вы не знаете формат входного сообщения, используйте .
запрос для экспорта сообщения в качестве места назначения, например веб-перехватчика. Затем вставьте сообщение, полученное веб-перехватчиком, в 1. Добавьте входное сообщение. Затем создайте запрос преобразования для обработки этого сообщения в требуемый выходной формат.
Создание запроса преобразования
Модуль преобразования использует обработчик JQ JSON с открытым кодом для реструктуризации полезных данных JSON и форматирования полезных данных JSON. Чтобы указать преобразование, необходимо написать JQ-запрос, который может использовать встроенные фильтры, функции и функции JQ. Примеры запросов см. в разделе "Примеры запросов преобразования". Дополнительные сведения о написании запросов JQ см. в руководстве по JQ.
Структура сообщений перед преобразованием
Вы можете экспортировать следующие потоки данных из Интернета вещей: телеметрия, изменения свойств, события подключения устройств, события жизненного цикла устройства и события жизненного цикла шаблона устройства. Каждый тип данных имеет определенную структуру, содержащую такие сведения, как значения телеметрии, сведения о приложении, метаданные устройства и значения свойств.
В следующем примере показана форма сообщения телеметрии. Все эти данные доступны для преобразования. Структура сообщения аналогична другим типам сообщений, но существуют некоторые поля, относящиеся к типу. Вы можете использовать функцию добавления входного сообщения для создания примера сообщения на основе шаблона устройства в приложении.
{
"applicationId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"device": {
"id": "31edabe6-e0b9-4c83-b0df-d12e95745b9f",
"name": "Scripted Device - 31edabe6-e0b9-4c83-b0df-d12e95745b9f",
"cloudProperties": [],
"properties": {
"reported": [
{
"id": "urn:smartKneeBrace:Smart_Vitals_Patch_wr:FirmwareVersion:1",
"name": "FirmwareVersion",
"value": 1.0
}
]
},
"templateId": "urn:sbq3croo:modelDefinition:nf7st1wn3",
"templateName": "Smart Knee Brace"
},
"telemetry": [
{
"id": "urn:continuousPatientMonitoringTemplate:Smart_Knee_Brace_6wm:Acceleration:1",
"name": "Acceleration",
"value": {
"x": 19.212770659918583,
"y": 20.596296675217335,
"z": 54.04859440697045
}
},
{
"id": "urn:continuousPatientMonitoringTemplate:Smart_Knee_Brace_6wm:RangeOfMotion:1",
"name": "RangeOfMotion",
"value": 110
}
],
"enqueuedTime": "2021-03-23T19:55:56.971Z",
"enrichments": {
"your-enrichment-key": "enrichment-value"
},
"messageProperties": {
"prop1": "prop-value"
},
"messageSource": "telemetry"
}
Совет
Используйте функцию добавления входного сообщения в пользовательский интерфейс приложения IoT Central, чтобы просмотреть примеры структур сообщений для других типов экспорта данных, таких как изменения свойств.
Примеры запросов преобразования
В следующих примерах запросов используется сообщение телеметрии, показанное в предыдущем разделе.
Пример 1. Следующий запрос JQ выводит каждую часть телеметрии из входного сообщения в виде отдельного выходного сообщения:
.telemetry[]
Выходные данные JSON:
{
"id": "urn:continuousPatientMonitoringTemplate:Smart_Knee_Brace_6wm:Acceleration:1",
"name": "Acceleration",
"value": {
"x": 19.212770659918583,
"y": 20.596296675217335,
"z": 54.04859440697045
}
},
{
"id": "urn:continuousPatientMonitoringTemplate:Smart_Knee_Brace_6wm:RangeOfMotion:1",
"name": "RangeOfMotion",
"value": 110
}
Совет
Чтобы изменить выходные данные на одно сообщение с массивом типов телеметрии, используйте запрос .telemetry
.
Пример 2. Следующий запрос JQ преобразует входной массив телеметрии в объект с именами телеметрии в качестве ключей:
.telemetry | map({ key: .name, value: .value }) | from_entries
Выходные данные JSON:
{
"Acceleration": {
"x": 19.212770659918583,
"y": 20.596296675217335,
"z": 54.04859440697045
},
"RangeOfMotion": 110
}
Пример 3. Следующий запрос JQ находит значение телеметрии RangeOfMotion и преобразует его из градусов в радианы с помощью формулы rad = degree * pi / 180
. Этот запрос также показывает, как импортировать и использовать iotc
модуль:
import "iotc" as iotc;
{
rangeOfMotion: (
.telemetry
| iotc::find(.name == "RangeOfMotion").value
| . * 3.14159265358979323846 / 180
)
}
Выходные данные JSON:
{
"rangeOfMotion": 1.9198621771937625
}
Пример 4. Для управления входным сообщением в табличном формате можно сопоставить каждое экспортируемое сообщение с одной или несколькими строками. Выходные данные строк логически представлены в виде объекта JSON, где имя столбца является ключом, а значение столбца — значением:
{
"<column 1 name>": "<column 1 value>",
"<column 2 name>": "<column 2 value>",
...
}
Совет
При экспорте в Azure Data Explorer используйте табличный формат.
Следующий запрос JQ записывает строки в таблицу, в которой хранятся данные телеметрии rangeOfMotion на разных устройствах. Запрос сопоставляет идентификатор устройства, заложенное время и диапазон перемещения в таблицу с этими столбцами:
import "iotc" as iotc;
{
deviceId: .deviceId,
timestamp: .enqueuedTime,
rangeOfMotion: .telemetry | iotc::find(.name == "RangeOfMotion").value
}
Выходные данные в формате JSON:
{
"deviceId": "31edabe6-e0b9-4c83-b0df-d12e95745b9f",
"timestamp": "2021-03-23T19:55:56.971Z",
"rangeOfMotion": 110
}
Модуль IoT Central
Модуль JQ — это коллекция пользовательских функций. В рамках запроса преобразования можно импортировать встроенный модуль IoT Central, содержащий функции, чтобы упростить запись запросов. Чтобы импортировать модуль IoT Central, используйте следующую директиву:
import "iotc" as iotc;
Модуль IoT Central включает следующие функции:
find(expression)
: функция find
позволяет найти определенный элемент массива, например значение телеметрии или запись свойства в полезных данных. Входные данные функции — это массив, а параметр определяет фильтр JQ для запуска для каждого элемента в массиве. Функция возвращает каждый элемент массива, в котором фильтр оценивается как true:
Например, чтобы найти определенное значение телеметрии:RangeOfMotion
.telemetry | iotc::find(.name == "RangeOfMotion")
Сценарии
В следующих сценариях функция преобразования используется для настройки формата данных устройства для определенного назначения.
Сценарий 1. Экспорт данных устройства в Azure Data Explorer
В этом сценарии данные устройства преобразуются в соответствие с фиксированной схемой в Azure Data Explorer, где каждое значение телеметрии отображается как столбец в таблице, а каждая строка представляет одно сообщение. Например:
DeviceId | Метка времени | T1 | T2 | T3 |
---|---|---|---|---|
"31edabe6-e0b9-4c83-b0df-d12e95745b9f" | "2021-03-23T19:55:56.971Z | 1.18898 | 1.434709 | 2.97008 |
Чтобы экспортировать данные, совместимые с этой таблицей, каждое экспортируемое сообщение должно выглядеть как следующий объект. Объект представляет одну строку, в которой ключи являются именами столбцов, а значения — это значение, которое следует разместить в каждом столбце:
{
"Timestamp": <value-of-Timestamp>,
"DeviceId": <value-of-deviceId>,
"T1": <value-of-T1>,
"T2": <value-of-T2>,
"T3": <value-of-T3>,
}
В этом сценарии устройство отправляет t1
t2
значения телеметрии в t3
входном сообщении, которое выглядит следующим образом:
{
"applicationId": "11112222-bbbb-3333-cccc-4444dddd5555",
"enqueuedTime": "1933-01-26T03:10:44.480001324Z",
"messageSource": "telemetry",
"telemetry": [
{
"id": "dtmi:temperaturesensor288:sensors1lr:t1;1",
"name": "t1",
"value": 1.1889838348731093e+308
},
{
"id": "dtmi:temperaturesensor288:sensors1lr:t2;1",
"name": "t2",
"value": 1.4347093391531383e+308
},
{
"id": "dtmi:temperaturesensor288:sensors1lr:t3;1",
"name": "t3",
"value": 2.9700885230380616e+307
}
],
"device": {
"id": "oozrnl1zs857",
"name": "haptic alarm",
"templateId": "dtmi:modelDefinition:nhhbjotee:qytxnp8hi",
"templateName": "hapticsensors",
"properties": {
"reported": []
},
"cloudProperties": [],
"simulated": true,
"approved": false,
"blocked": false,
"provisioned": true
}
}
Следующий запрос JQ выводит T1
значения телеметрии T2
и T3
значения телеметрии, а также deviceId
сообщение с парами "ключ-значение", Timestamp
соответствующим схеме таблицы Azure Data Explorer:
import "iotc" as iotc;
{
deviceId: .device.id,
Timestamp: .enqueuedTime,
T1: .telemetry | iotc::find(.name == "t1").value,
T2: .telemetry | iotc::find(.name == "t2").value,
T3: .telemetry | iotc::find(.name == "t3").value,
}
Выходные данные JSON:
{
"T1": 1.1889838348731093e+308,
"T2": 1.4347093391531383e+308,
"T3": 2.9700885230380616e+307,
"Timestamp": "1933-01-26T03:10:44.480001324Z",
"deviceId": "oozrnl1zs857"
}
Дополнительные сведения о добавлении кластера и базы данных Azure Data Explorer в качестве назначения экспорта см. в статье "Создание назначения Azure Data Explorer".
Сценарий 2. Разрыв массива телеметрии
В этом сценарии устройство отправляет следующий массив телеметрии в одном сообщении:
{
"applicationId": "22223333-cccc-4444-dddd-5555eeee6666",
"enqueuedTime": "1909-10-10T07:11:56.078161042Z",
"messageSource": "telemetry",
"telemetry": [
{
"id": "dtmi:sample1:data;1",
"name": "data",
"value": [
{
"id": "subdevice1",
"values": {
"running": true,
"cycleCount": 2315
}
},
{
"id": "subdevice2",
"values": {
"running": false,
"cycleCount": 824567
}
}
]
},
{
"id": "dtmi:sample1:parentStatus;1",
"name": "parentStatus",
"value": "healthy"
}
],
"device": {
"id": "9xwhr7khkfri",
"name": "wireless port",
"templateId": "dtmi:hpzy1kfcbt2:umua7dplmbd",
"templateName": "Smart Vitals Patch",
"properties": {
"reported": [
{
"id": "dtmi:sample1:prop;1",
"name": "Connectivity",
"value": "Tenetur ut quasi minus ratione voluptatem."
}
]
},
"cloudProperties": [],
"simulated": true,
"approved": true,
"blocked": false,
"provisioned": false
}
}
Вы хотите преобразовать эти данные устройства в соответствии со следующей схемой таблицы:
cycleCount | deviceId | enqueuedTime | parentStatus | выполняется | subdeviceId |
---|---|---|---|---|---|
2315 | "9xwhr7khkfri" | "1909-10-10T07:11:56.078161042Z" | "здоровый" | true | Subdevice1 |
824567 | "9xwhr7khkfri" | "1909-10-10T07:11:56.078161042Z" | "здоровый" | false | Subdevice2 |
Следующий запрос JQ создает отдельное выходное сообщение для каждой записи subdevice в сообщении и содержит некоторые общие сведения из базового сообщения и родительского устройства. Этот запрос преобразует выходные данные и отделяет логические деления в данных, поступающих в виде одного сообщения:
import "iotc" as iotc;
{
enqueuedTime: .enqueuedTime,
deviceId: .device.id,
parentStatus: .telemetry | iotc::find(.name == "parentStatus").value
} + (
.telemetry
| iotc::find(.name == "data").value[]
| {
subdeviceId: .id,
running: .values.running,
cycleCount: .values.cycleCount
}
)
Выходные данные JSON:
{
"cycleCount": 2315,
"deviceId": "9xwhr7khkfri",
"enqueuedTime": "1909-10-10T07:11:56.078161042Z",
"parentStatus": "healthy",
"running": true,
"subdeviceId": "subdevice1"
},
{
"cycleCount": 824567,
"deviceId": "9xwhr7khkfri",
"enqueuedTime": "1909-10-10T07:11:56.078161042Z",
"parentStatus": "healthy",
"running": false,
"subdeviceId": "subdevice2"
}
Сценарий 3. Потоковая передача Power BI
Функция потоковой передачи Power BI в режиме реального времени позволяет просматривать данные на панели мониторинга, обновляющейся в режиме реального времени с низкой задержкой. Дополнительные сведения см. в статье "Потоковая передача в режиме реального времени" в Power BI.
Чтобы использовать IoT Central с потоковой передачей Power BI, настройте экспорт веб-перехватчика, который отправляет тела запросов в определенном формате. В этом примере предполагается, что у вас есть набор данных Потоковой передачи Power BI со следующей схемой:
{
"bloodPressureDiastolic": 161438124,
"bloodPressureSystolic": -966387879,
"deviceId": "9xwhr7khkfri",
"deviceName": "wireless port",
"heartRate": -633994413,
"heartRateVariability": -37514094,
"respiratoryRate": 1582211310,
"timestamp": "1909-10-10T07:11:56.078161042Z"
}
Чтобы создать назначение экспорта веб-перехватчика, вам потребуется конечная точка URL-адреса REST API для набора данных потоковой передачи Power BI.
В этом сценарии устройство отправляет сообщения телеметрии, которые выглядят следующим образом:
{
"applicationId": "22223333-cccc-4444-dddd-5555eeee6666",
"enqueuedTime": "1909-10-10T07:11:56.078161042Z",
"messageSource": "telemetry",
"telemetry": [
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:HeartRate;1",
"name": "HeartRate",
"value": -633994413
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:RespiratoryRate;1",
"name": "RespiratoryRate",
"value": 1582211310
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:HeartRateVariability;1",
"name": "HeartRateVariability",
"value": -37514094
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:BodyTemperature;1",
"name": "BodyTemperature",
"value": 5.323322666478241e+307
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:FallDetection;1",
"name": "FallDetection",
"value": "Earum est nobis at voluptas id qui."
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:BloodPressure;1",
"name": "BloodPressure",
"value": {
"Diastolic": 161438124,
"Systolic": -966387879
}
}
],
"device": {
"id": "9xwhr7khkfri",
"name": "wireless port",
"templateId": "dtmi:hpzy1kfcbt2:umua7dplmbd",
"templateName": "Smart Vitals Patch",
"properties": {
"reported": [
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_wr:DeviceStatus;1",
"name": "DeviceStatus",
"value": "Id optio iste vero et neque sit."
}
]
},
"cloudProperties": [],
"simulated": true,
"approved": true,
"blocked": false,
"provisioned": false
}
}
Следующий запрос JQ преобразует входное сообщение в формат, подходящий для отправки в набор данных потоковой передачи Power BI. В этом примере включается условие фильтра только для вывода сообщений для определенного шаблона устройства. Вы можете использовать функцию фильтра экспорта данных для фильтрации по шаблону устройства:
import "iotc" as iotc;
if .device.templateId == "dtmi:hpzy1kfcbt2:umua7dplmbd" then
{
deviceId: .device.id,
timestamp: .enqueuedTime,
deviceName: .device.name,
bloodPressureSystolic: .telemetry | iotc::find(.name == "BloodPressure").value.Systolic,
bloodPressureDiastolic: .telemetry | iotc::find(.name == "BloodPressure").value.Diastolic,
heartRate: .telemetry | iotc::find(.name == "HeartRate").value,
heartRateVariability: .telemetry | iotc::find(.name == "HeartRateVariability").value,
respiratoryRate: .telemetry | iotc::find(.name == "RespiratoryRate").value
}
else
empty
end
Выходные данные JSON:
{
"bloodPressureDiastolic": 161438124,
"bloodPressureSystolic": -966387879,
"deviceId": "9xwhr7khkfri",
"deviceName": "wireless port",
"heartRate": -633994413,
"heartRateVariability": -37514094,
"respiratoryRate": 1582211310,
"timestamp": "1909-10-10T07:11:56.078161042Z"
}
Сценарий 4. Экспорт данных в Azure Data Explorer и визуализация их в Power BI
В этом сценарии вы экспортируете данные в Azure Data Explorer, а затем используете соединитель для визуализации данных в Power BI. Дополнительные сведения о добавлении кластера и базы данных Azure Data Explorer в качестве назначения экспорта см. в статье "Создание назначения Azure Data Explorer".
В этом сценарии используется таблица Azure Data Explorer со следующей схемой:
.create table smartvitalspatch (
EnqueuedTime:datetime,
Message:string,
Application:string,
Device:string,
Simulated:boolean,
Template:string,
Module:string,
Component:string,
Capability:string,
Value:dynamic
)
В этом сценарии устройство отправляет сообщения телеметрии, которые выглядят следующим образом:
{
"applicationId": "22223333-cccc-4444-dddd-5555eeee6666",
"enqueuedTime": "1909-10-10T07:11:56.078161042Z",
"messageSource": "telemetry",
"telemetry": [
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:HeartRate;1",
"name": "HeartRate",
"value": -633994413
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:RespiratoryRate;1",
"name": "RespiratoryRate",
"value": 1582211310
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:HeartRateVariability;1",
"name": "HeartRateVariability",
"value": -37514094
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:BodyTemperature;1",
"name": "BodyTemperature",
"value": 5.323322666478241e+307
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:FallDetection;1",
"name": "FallDetection",
"value": "Earum est nobis at voluptas id qui."
},
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_37p:BloodPressure;1",
"name": "BloodPressure",
"value": {
"Diastolic": 161438124,
"Systolic": -966387879
}
}
],
"device": {
"id": "9xwhr7khkfri",
"name": "wireless port",
"templateId": "dtmi:hpzy1kfcbt2:umua7dplmbd",
"templateName": "Smart Vitals Patch",
"properties": {
"reported": [
{
"id": "dtmi:smartVitalsPatch:Smart_Vitals_Patch_wr:DeviceStatus;1",
"name": "DeviceStatus",
"value": "Id optio iste vero et neque sit."
}
]
},
"cloudProperties": [],
"simulated": true,
"approved": true,
"blocked": false,
"provisioned": false
}
}
Следующий запрос JQ преобразует входное сообщение в отдельное выходное сообщение для каждого значения телеметрии. Это преобразование создает выходные данные, соответствующие схеме таблицы Azure Data Explorer. Преобразование использует схему entity-attribute-value, где каждая строка содержит одно значение телеметрии, а имя телеметрии — это значение в отдельном столбце в одной строке:
. as $in | .telemetry[] | {
EnqueuedTime: $in.enqueuedTime,
Message: $in.messageId,
Application: $in.applicationId,
Device: $in.device.id,
Simulated: $in.device.simulated,
Template: ($in.device.templateName // ""),
Module: ($in.module // ""),
Component: ($in.component // ""),
Capability: .name,
Value: .value
}
Выходные данные JSON:
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "HeartRate",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": -633994413
},
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "RespiratoryRate",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": 1582211310
},
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "HeartRateVariability",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": -37514094
},
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "BodyTemperature",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": 5.323322666478241e+307
},
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "FallDetection",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": "Earum est nobis at voluptas id qui."
},
{
"Application": "22223333-cccc-4444-dddd-5555eeee6666",
"Capability": "BloodPressure",
"Component": "",
"Device": "9xwhr7khkfri",
"EnqueuedTime": "1909-10-10T07:11:56.078161042Z",
"Message": null,
"Module": "",
"Simulated": true,
"Template": "Smart Vitals Patch",
"Value": {
"Diastolic": 161438124,
"Systolic": -966387879
}
}
Выходные данные экспортируются в кластер Azure Data Explorer. Чтобы визуализировать экспортированные данные в Power BI, выполните следующие действия.
- Установите приложение Power BI. Вы можете скачать классическое приложение Power BI из Go из данных в аналитические сведения о действиях с Power BI Desktop.
- Скачайте файл Power BI desktop IoT Central ADX Connector.pbit из GitHub.
- Используйте приложение Power BI Desktop, чтобы открыть файл IoT Central ADX Connector.pbit , скачанный на предыдущем шаге. При появлении запроса введите кластер Azure Data Explorer, базу данных и сведения о таблице, которые вы записали ранее.
Теперь можно визуализировать данные в Power BI:
Следующие шаги
Теперь, когда вы знаете, как преобразовать данные в IoT Central, рекомендуемый следующий шаг — узнать , как использовать аналитику в IoT Central.