Problems parsing JSONPATH expressions from LoRaWAN sensor via MQTT

Hello,
after updating my OH installation to the recent 3.2 version I am currently in progress of integrating a pump control using 2 LoRaWAN sensors for measuring the current water level in two wells.
I’m using TTN at the moment with their MQTT server service, did all the MQTT stuff in OH and so far I can see the messages coming in, that worked more or less out of the box.
However, the most simple task I’m struggling with (n German we say “Brett vor dem Kopf”…) is parsing the results via JSONPATHS into a number of channels:

  • I added a thing that gets a JSON message via MQTT from TTN for every reading of exactly one sensor.
  • I want to add channels which extract a couple of values from the reading and make them then availble inside OH.
  • In the “advanced settings” of a channel under “Incoming Value Transformations” I put “JSONPATH:$.uplink_message.decoded_payload.dis1” to extract the first distance reading from the sensor (which is labeled “dis1”), the expression anyhow is super simple.

The “funny” thing is now that the channel publishes the whole message, so the parsing expressions seems to be completely ignored - why? I tried http://jsonpath.com/ to validate the expression, no surprise, it yields the correct result. Not sure if something special for OH is missing here, but the expression should be really straight-forward working…?

One example message below

{
   "end_device_ids":{
      "device_id":"water-sensor-p1",
      "application_ids":{
         "application_id":"XXX"
      },
      "dev_eui":"XXX",
      "join_eui":"XXX",
      "dev_addr":"XXX"
   },
   "correlation_ids":[
      "as:up:01G467N09BBRCNZHA56AD5V4FS",
      "gs:conn:01G3R43YH2HGBVTC75WY6JKZAY",
      "gs:up:host:01G3R4401RNYBPK7G1MR4K6F61",
      "gs:uplink:01G467N02M6AV2TRTYSRTQJTC5",
      "ns:uplink:01G467N02QZB5NYA6XR68A1QG9",
      "rpc:/ttn.lorawan.v3.GsNs/HandleUplink:01G467N02QJKYC7M8TJ457D607",
      "rpc:/ttn.lorawan.v3.NsAs/HandleUplink:01G467N09APHH9294WQSHJBDT4"
   ],
   "received_at":"2022-05-28T21:02:44.011415449Z",
   "uplink_message":{
      "session_key_id":"AYDoNsgjB6aWY/UQeI7M5g==",
      "f_port":2,
      "f_cnt":337,
      "frm_payload":"DSIAmgEMAA==",
      "decoded_payload":{
         "Bat":3.362,
         "DALARM_count":0,
         "Distance_alarm":0,
         "Interrupt_alarm":0,
         "dis1":154,
         "dis2":268
      },
      "rx_metadata":[
         {
            "gateway_ids":{
               "gateway_id":"cancasas-gw1",
               "eui":"A84041FFFF1EF99C"
            },
            "time":"2022-05-28T21:02:43.772986Z",
            "timestamp":2972375931,
            "rssi":-77,
            "channel_rssi":-77,
            "snr":10,
            "location":{
               "latitude":41.623433,
               "longitude":2.575709,
               "altitude":145,
               "source":"SOURCE_REGISTRY"
            },
            "uplink_token":"ChoKGAoMY2FuY2FzYXMtZ3cxEgioQEH//x75nBD7tquJCxoMCPObypQGENzi8/sCIPiwpfvAjGwqDAjzm8qUBhCQqcvwAg=="
         }
      ],
      "settings":{
         "data_rate":{
            "lora":{
               "bandwidth":125000,
               "spreading_factor":7
            }
         },
         "coding_rate":"4/5",
         "frequency":"868100000",
         "timestamp":2972375931,
         "time":"2022-05-28T21:02:43.772986Z"
      },
      "received_at":"2022-05-28T21:02:43.799563295Z",
      "consumed_airtime":"0.056576s",
      "locations":{
         "user":{
            "latitude":41.622746706484016,
            "longitude":2.576688480926399,
            "altitude":100,
            "source":"SOURCE_REGISTRY"
         }
      },
      "network_ids":{
         "net_id":"000013",
         "tenant_id":"ttn",
         "cluster_id":"eu1",
         "cluster_address":"eu1.cloud.thethings.network"
      }
   }
}

What do the openHAB logs say? Do you have the JSONPATH Transformation Service installed?

I had trouble integrating my Dragino LHT65 sensor too.
Here is how I got it to work (some id’s are blurred/X-ed):

Create a MQTT broker to TTN:

Create a things file with channel transformations:

Thing mqtt:topic:ttn:lht65 “TTN Dragino LHT65” (mqtt:broker:bae01d4af3) @ “Locker” {
Channels:

Type string : full_message  "full TTN message"                 [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up" ]
Type datetime : time  "time of event"                       [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.rx_metadata[0].time" ]
Type number : rssi  "rssi value "                           [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.rx_metadata[0].rssi" ]
Type number : snr  "signal noise ratio"                     [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.rx_metadata[0].snr" ]
Type string : gateway_id  "receiving gw id"                 [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.rx_metadata[0].gateway_ids.gateway_id" ]
Type number : battery  "battery level device"               [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.decoded_payload.BatV" ]
Type number : humidity  "event type "                          [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.decoded_payload.Hum_SHT" ]
Type number : temp_intern      "illumination in environment"      [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.decoded_payload.TempC_DS" ]
Type number : temp_extern      "temperature in environment" [ stateTopic="v3/veve-lora-app@ttn/devices/eui-a840XXXXXXX2a0da/up", transformationPattern="JSONPATH:$.uplink_message.decoded_payload.TempC_SHT" ]

}

Define the items in items file:

//LoraWAN Meta Data
DateTime  ELT2_meta_time         "Metadata Time: [%s]"  (gLoRa)  { channel="mqtt:topic:ttn:lht65:time" } 
Number    ELT2_meta_battery       "Metadata Time: [%s]"  (gLoRa)  { channel="mqtt:topic:ttn:lht65:battery" } 
Number    ELT2_meta_humidity         "Metadata Time: [%s]"  (gLoRa)  { channel="mqtt:topic:ttn:lht65:humidity" } 
Number    ELT2_meta_temperature_intern         "Metadata Time: [%s]"  (gLoRa)  { channel="mqtt:topic:ttn:lht65:temp_intern" } 
Number    ELT2_meta_temperature_extern   "Metadata Time: [%s]"  (gLoRa)  { channel="mqtt:topic:ttn:lht65:temp_extern" }

I hope this helps

Homer says “d’ooooh!”. Mentioning the “JSONPATH Transformation Service” resolved the problem. Thanks @hafniumzinc! Have to say I wasn’t even aware something like that would be required.
Maybe a hint to the documentation team that the MQTT documentation could be improved just reminding about that once JSONPATH service would be used, the respective service must be installed as well to have it working. But all good now ,-)

Just to give some more informations:

There are two ways to tinker with a JSON Object through JSONPATH.

The obvious solution is to use incomming value transformation directly in the binding. (can be done in every binding which provides such a parameter for the channel).
You will have to build as many channels as you want values to be extracted from the JSON Object. The channel can be set to the type which fits best for the extracted value.

The not so obvious solution is to use only one(!) channel per JSON Object but link many Items to this channel. You can use the Profile parameter within the link to the Item to set the JSONPATH. You have to use a String Channel, because the Channel will store the whole JSON Object.
However, the Items can be of the type that fits best to the value.

The Channel has to be used read only, for obvious reasons (well… in fact, you could even provide a string Item to write a JSON Object to the same Channel… But you will need a rule to create the JSON Object)
At least, you can save some data transfer, as the JSON Object is received only once and not n times (where n is number of Items used).

Okay, interesting to know these details @Udo_Hartmann :+1: However, for my use case I’ll stick to the more “obvious” setup, i.e. I will modell “1 sensor == 1 thing” and “1 sensor value == 1 channel”. In fact this requires more JSON transofrmations, but I have currently 4 sensors only, each sending every 30 minutes a small message with 4 or 5 values to transform. I agree with the solution for a more high-frequency sender, but in my case the result seems more natural and system load is not an issue. THanks!

Well, both options are valid :slight_smile: But it’s better to have a choice and know about…

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.