потоковая аналитика - преобразование входящего JSON в набор потоковых данных PowerBI - PullRequest
0 голосов
/ 15 мая 2018

У меня есть датчик, который передает данные в IoTHub в следующем формате (через сервер Modbus):

15/05/2018 14:56:56> Device: [dev], Data:[[{"DisplayName":"Temperature","HwId":"PI-1","Address":"400002","Value":"192","SourceTimestamp":"2018-05-15 13:56:52"},{"DisplayName":"Humidity","HwId":"PI-1","Address":"400001","Value":"397","SourceTimestamp":"2018-05-15 13:56:52"}]]Properties:
'content-type': 'application/edge-modbus-json'

15/05/2018 14:57:00> Device: [dev], Data:[[{"DisplayName":"Temperature","HwId":"PI-1","Address":"400002","Value":"201","SourceTimestamp":"2018-05-15 13:56:57"},{"DisplayName":"Humidity","HwId":"PI-1","Address":"400001","Value":"397","SourceTimestamp":"2018-05-15 13:56:57"}]]Properties:
'content-type': 'application/edge-modbus-json'

15/05/2018 14:57:06> Device: [dev], Data:[[{"DisplayName":"Temperature","HwId":"PI-1","Address":"400002","Value":"201","SourceTimestamp":"2018-05-15 13:57:02"},{"DisplayName":"Humidity","HwId":"PI-1","Address":"400001","Value":"397","SourceTimestamp":"2018-05-15 13:57:02"}]]Properties:
'content-type': 'application/edge-modbus-json'

15/05/2018 14:57:10> Device: [dev], Data:[[{"DisplayName":"Temperature","HwId":"PI-1","Address":"400002","Value":"195","SourceTimestamp":"2018-05-15 13:57:07"},{"DisplayName":"Humidity","HwId":"PI-1","Address":"400001","Value":"397","SourceTimestamp":"2018-05-15 13:57:07"}]]Properties:
'content-type': 'application/edge-modbus-json'

Каждый датчик сообщается в отдельной записи массива, а также разделяется между отображаемым именем датчика и значением.

Мне нужна полезная нагрузка JSON, которую я могу передавать в PowerBI, поэтому она должна быть в следующем порядке:

метка времени: Время, влажность: humidity_value, температура: temperature_value

Как мне создать подходящий запрос потоковой аналитики для этого? Этот формат ввода типичен для устройств типа Modbus или OPC-UA, поэтому, скорее всего, столкнется с этим несколько раз.

Я пытался использовать GetArrayElement / s, но у массива нет имени в JSON, поэтому ссылаться на него нечем.

Ответы [ 2 ]

0 голосов
/ 17 мая 2018

На самом деле нашел гораздо более простой способ справиться с этим напрямую без функций. Использование оператора CASE в сочетании с LAST.

SELECT System.Timestamp as timestamp,

    CASE Address
        WHEN '400001' THEN cast(Value as float)/10 ELSE last(cast(Value as float)/10) over (partition by HwId limit duration(day,1) when Value is not null and Address like '400001')
    END
    AS Humidity,
    CASE Address
        WHEN '400002' THEN cast(Value as float)/10 ELSE last(cast(Value as float)/10) over (partition by HwId limit duration(day,1) when Value is not null and Address like '400002')
    END
    AS Temperature,
    CASE Address
        WHEN '400003' THEN cast(Value as float)/10 ELSE last(cast(Value as float)/10) over (partition by HwId limit duration(day,1) when Value is not null and Address like '400003')
    END
    AS Pressure    
INTO PowerBI
FROM IoTHub as event 
0 голосов
/ 16 мая 2018

Насколько я понимаю, вы можете использовать пользовательские функции JavaScript Azure Stream Analytics для выравнивания ваших данных.

Предполагая, что ваши данные выглядят так:

{
    Device:"dev01", 
    Data:[
    [
      {"DisplayName":"Temperature","HwId":"PI-1","Address":"400002","Value":"192","SourceTimestamp":"2018-05-15 13:56:52"}
      ,{"DisplayName":"Humidity","HwId":"PI-1","Address":"400001","Value":"397","SourceTimestamp":"2018-05-15 13:56:52"}
     ]
    ]
}   

Вы можете создать следующие пользовательские функции:

GetValueByPropertyName:

function main(arrs,propertyname) {
    for(var i=0;i<arrs.length;i++){
       var item=arrs[i];
       if(item.hasOwnProperty(propertyname)){
           return item[propertyname];
       }
    }
    return '';
}

GetValueByDisplayName:

function main(dataArr,displayname) {
    if(dataArr){
      for(var j=0;j<dataArr.length;j++)
      {
        var subArr=dataArr[j];
        for(var i=0;i<subArr.length;i++){
          var obj=subArr[i];
          if(obj.DisplayName.toLowerCase()==displayname.toLowerCase())
              return obj.Value;
        }
      }
    }
    return '';
}

Пример запроса:

select 
input.device as DeviceName,
UDF.GetValueByDisplayName(input.Data,'Temperature') as Temperature,
UDF.GetValueByDisplayName(input.Data,'Humidity') as Humidity,
UDF.GetValueByPropertyName(GetArrayElement(input.Data,0),'SourceTimestamp') as [Timestamp]
from input

ТЕСТ:

enter image description here

...