Как достать json‐данные из топика mqtt - d51x/openhab-docs-russian GitHub Wiki

Это требуется в том случае, если в топике mqtt данные передаются в формате json.

Например

{
  "battery": 40,
  "batteryLow": false,
  "contact": false,
  "linkQuality": 248,
  "tamper": false
}

Нам нужно достать определенный параметр contact

Для этого используется транформация JSONPATH

Строка для трансофрмации выглядит следующим образом JSONPATH:$.contact

Есть более сложны случай, когда в json лежит целый объект, а нам из объекта АМ2301 надо достать свойство Humidity

{
  "Time": "2024-01-16T13:07:03",
  "Switch1": "ON",
  "Switch2": "OFF",
  "ANALOG": {
    "A0": 373
  },
  "AM2301": {
    "Temperature": 22.1,
    "Humidity": 56.6,
    "DewPoint": 13.1
  },
  "PCF8574-1": {
    "D0": 1,
    "D1": 1,
    "D2": 1,
    "D3": 1,
    "D4": 1,
    "D5": 1,
    "D6": 1,
    "D7": 1
  },
  "TempUnit": "C"
}

Строка для трансофрмации выглядит следующим образом JSONPATH:$.AM2301.Humidity

Есть еще более сложные случаи, когда в json передам массив объектов и нам надо достать определенный объект из массива по какому-то атрибуту объекта. Например, name = WallSwitchCorridor,

{
    "devices": [
        {
            "active": true,
            "description": "Heiman Smoke Detector HS1SA",
            "firmware": "1.1.1",
            "ieeeAddress": "00:0d:6f:00:0e:f3:e2:38",
            "interviewFinished": true,
            "lastSeen": 1704869813,
            "linkQuality": 40,
            "logicalType": 2,
            "manufacturerCode": 4619,
            "manufacturerName": "HEIMAN",
            "modelName": "SmokeSensor-EM",
            "networkAddress": 1146,
            "powerSource": 3,
            "supported": true,
            "version": 18
        },
        {
            "active": true,
            "description": "Heiman Smoke Detector HS1SA",
            "firmware": "1.1.1",
            "ieeeAddress": "00:0d:6f:00:12:24:ce:64",
            "interviewFinished": true,
            "lastSeen": 1705396491,
            "linkQuality": 140,
            "logicalType": 2,
            "manufacturerCode": 4619,
            "manufacturerName": "HEIMAN",
            "modelName": "SmokeSensor-EM",
            "name": "SmokeSensor_Room_Banya",
            "networkAddress": 34050,
            "powerSource": 3,
            "supported": true,
            "version": 18
        },
        {
            "ieeeAddress": "00:12:4b:00:09:fe:24:da",
            "name": "Socket Plug 1 Life Control",
            "networkAddress": 51771,
            "removed": true
        },
        {
            "active": true,
            "description": "Sonoff 1-Channel Relay ZBMINI",
            "ieeeAddress": "00:12:4b:00:24:c0:2a:d7",
            "interviewFinished": true,
            "lastSeen": 1705398144,
            "linkQuality": 72,
            "logicalType": 1,
            "manufacturerCode": 4742,
            "manufacturerName": "SONOFF",
            "modelName": "01MINIZB",
            "name": "WallSwitchCorridor",
            "networkAddress": 20309,
            "powerSource": 1,
            "supported": true
        }
    ]
}

Строка для трансофрмации вернет целый объект из массива JSONPATH:$.devices.[?(@.name=="WallSwitchCorridor")]

А следующая строка трансформации уже вернет конкретный атрибут powerSource JSONPATH:$.devices.[?(@.name=="WallSwitchCorridor")].powerSource

Может оказаться так, что мы пытаемся обратиться к атрибуту, которого нет в json.

В этом случае в логах будут сыпаться ошибки.

Чтобы их не было, можно использовать цепочку трансформаций, используя знак связывания

REGEX:(.*WallSwitchRoom.*)∩JSONPATH:$.devices.[?(@.name=="WallSwitchRoom")].lastSeen

В данном примере мы проверяем, есть ли вообще в json WallSwitchRoom. Делается это первой трансформацией REGEX.

Так мы достанем атрибут lastSeen из объекта массива.

Но опять же может получиться так, что объект в массиве будет, но у него не будет атрибута lastSeen, поэтому усложним конструкцию, чтобы не было warnings в логах.

REGEX:(.*WallSwitchRoom.*)∩JSONPATH:$.devices.[?(@.name=="WallSwitchRoom")]∩REGEX:(.*lastSeen.*)∩JSONPATH:$.lastSeen

В данном примере используется цепочка из 4-х трансофрмаций:

  1. проверяет наличие WallSwitchRoom
  2. достает из массива объект по атрибуту
  3. проверяет в полученном объекте наличие атрибута lastSeen
  4. достает из объекта п.2 (не из всего массива) атрибут