Json question for new sensor

Hi folks,
I found these LoRa soil sensors and they’re exactly what i’ve been looking for for!

I think i’ve gotten the code to format a proper json message:

#include <avr/wdt.h>
#include <avr/sleep.h>
//#include <RadioLib.h>
#include "I2C_AHT10.h"
#include <Wire.h>
#include <SPI.h>
#include <LoRa.h>
#include <ArduinoJson.h>

#define NODENAME "Soil_1"

#define DIO0 2
#define DIO1 6
#define DIO2 7
#define DIO5 8

#define LORA_RST 4
#define LORA_CS 10

#define SS      10   // GPIO18 -- SX1278's CS
#define RST     4   // GPIO14 -- SX1278's RESET
#define DI0     2   // GPIO26 -- SX1278's IRQ(Interrupt Request)
#define BAND  915E6

//#define SPI_MOSI 11
//#define SPI_MISO 12
//#define SPI_SCK 13

#define SPI_MOSI 11
#define SPI_MISO 12
#define SPI_SCK 13
//#define SPI_SS 10

int ledPin = 13;
int shu = 0;
int sensorPin = A2; // select the input pin for the potentiometer
int sensorPowerCtrlPin = 5;

int sensorValue = 0;     // variable to store the value coming from the sensor
int16_t packetnum = 0;   // packet counter, we increment per xmission
float temperature = 0.0; //
float humidity = 0.0;
//float dewpoint = 0.0;
String errcode = "";


// SX1278 radio = new Module(LORA_CS, DIO0, LORA_RST, DIO1, SPI, SPISettings());
AHT10 humiditySensor;

ISR(WDT_vect)
{
    Serial.print("[Watch dog]");
    Serial.println(shu);
    delay(100);
    shu++;
    wdt_reset();
}

void setup()
{
    wdt_disable();
    pinMode(ledPin, OUTPUT);
    Serial.begin(115200);
    Serial.println("[Start]");
    delay(100);
    SPI.begin();

    //setup start
    Serial.println("[Setup]");
    delay(100);

    // initialize SX1278 with default settings
    Serial.println(String("Sensor name is :") + String(NODENAME));
    Serial.print(F("Initializing ... "));
    SPI.begin();
    LoRa.setPins(SS,RST,DI0);
    if (!LoRa.begin(915E6)) {
      Serial.println("Starting LoRa failed!");
      while (1);
    }
//    else
//    {
//        Serial.print(Success!));
//        Serial.println("LoRa ok");
//        while (0)
//            ;
//    }
    LoRa.sleep();

    //AHT10
    pinMode(sensorPowerCtrlPin, OUTPUT);
    digitalWrite(sensorPowerCtrlPin, HIGH); //Sensor power on

    Wire.begin();
    if (humiditySensor.begin() == false)
    {
        Serial.println("AHT10 not detected. Please check wiring. Freezing.");
    }
    else
        Serial.println("AHT10 acknowledged.");

    read_sensor();
    //setup over

    low_power_set();
}

void loop()
{
    wdt_disable();

    if (shu > 7) //(7+1) x 8S
    {
        //code start
        Serial.println("Code start*************************************");

        read_sensor();
        //code end
        Serial.println("Code end*************************************");

        //count init
        shu = 0;
    }

    watchdog_init();
    delay(10);
    sleep_cpu();
}

//Set low power mode and into sleep
void low_power_set()
{
    Serial.println("[Set]Sleep Mode Set");
    delay(100);
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);
    sleep_enable();
    watchdog_init();
    delay(10);
    sleep_cpu();
}

//Enable watch dog
void watchdog_init()
{
    MCUSR &= ~(1 << WDRF);
    WDTCSR |= (1 << WDCE) | (1 << WDE);

    //WDTCSR = 1 << WDP1 | 1 << WDP2; //1S
    WDTCSR = 1 << WDP0 | 1 << WDP3; //8S

    WDTCSR |= _BV(WDIE); //not rst, inter interrutp
    wdt_reset();
}

void read_sensor()
{
    digitalWrite(sensorPowerCtrlPin, HIGH); //Sensor power on
    for (int i = 0; i < 3; i++)
    {
        sensorValue = analogRead(sensorPin);
        delay(200);
        if (humiditySensor.available() == true)
        {
            temperature = humiditySensor.getTemperature();
            humidity = humiditySensor.getHumidity();
        }
        if (isnan(humidity) || isnan(temperature))
        {
            Serial.println(F("Failed to read from AHT sensor!"));
        }
    }
    digitalWrite(sensorPowerCtrlPin, LOW); //Sensor power on

    String lora_msg = "#" + (String)packetnum +" NAME:" + (String)NODENAME + " H:" + (String)humidity + "% T:" + (String)temperature + " C" + " ADC:" + (String)sensorValue;

StaticJsonBuffer<200> jsonBuffer;

JsonObject& root = jsonBuffer.createObject();
root["id"] = "LoRaADC";
root["name"] = NODENAME;
root["model"] = "LSMS092D";
root["tempc"] = temperature;
root["hum"] = humidity;
//root[" Dew Point"] = dewpoint;
root["adc"] = sensorValue;
//root["topic"] = home/OMG_01/LORAtoMQTT;

//JsonArray& data = root.createNestedArray("data");
//data.add(temperature,6);  // 6 is the number of decimals to print
//data.add(humidity);   // if not specified, 2 digits are printed

//root.printTo(Serial);
//root.printTo(LoRa);
// This prints:
// {"sensor":"gps","time":1351824120,"data":[48.756080,2.302038]}
    
    Serial.println(lora_msg);
    packetnum++;
    LoRa.beginPacket();
//    LoRa.print("test");
    root.printTo(LoRa);
//    LoRa.print(temperature);
//    LoRa.print(humidity);
//    LoRa.print((String)sensorValue);
    LoRa.endPacket();
//    radio.transmit(lora_msg);
    delay(1000);
    LoRa.sleep();
}

but I don’t know much about code… i just cobbled this together from examples I found… so maybe my json isn’t correct?

It looks like this when sent over LoRa to OpenMqttGateway:

{“id”:“LoRaADC”,“name”:“Soil_1”,“model”:“LSMS092D”,“tempc”:23.01273,“hum”:47.26543,“adc”:879}

i’m trying to get the values to show up as usable data that I can plot on a graph as opposed to a string of characters…

I’ve tried this:

- platform: mqtt
  state_topic: 'home/OMG_01/LORAtoMQTT' # MQTT topic, check MQTT messages; replace AA... with id (BLE MAC) of your device
  name: "Soil_1_ADC"
  unit_of_measurement: 'µS/cm'
  value_template: '{{ value_json.adc.value"] }}'
  expire_after: 21600 # 6 hours

and this:

  value_template: '{{ value_json.adc }}'

and this

  value_template: '{{ value_json["adc"] }}'

can anyone help me figure out how to derive the values form my json string? (Is my json correct)?

and finally I see this in the MQTT debug info of the OMG device:

Subscribed topics:
home/OMG_01/LORAtoMQTT
1 most recently received message(s)
Received 7:12:48 PM
QoS: 0
Payload: rssi: -35
snr: 10.25
pferror: 12608
packetSize: 93
message: >-
  {"id":"LoRaADC","name":"Soil_1","model":"LSMS092D","tempc":23.01273,"hum":47.26543,"adc":879}

Thanks in advance!!

Not sure why but this json validator doesn’t like it: https://jsonformatter.curiousconcept.com/# bit it looks o to me…

I use this to read in json and attributes from mqtt

  - platform: mqtt
    name: "Coffee Maker Firmware"
    state_topic: "stat/sonoff1/STATUS2"
    value_template: 'v{{ value_json.StatusFWR.Version | replace("(tasmota)", "") | replace("(release-tasmota)", "") }}'
    json_attributes_topic: "stat/sonoff1/STATUS2"
    json_attributes_template: "{{ value_json.StatusFWR | tojson }}"

Thank you for responding!
so something like this maybe?

- platform: mqtt
  name: "davesexample"
  state_topic: "home/OMG_01/LORAtoMQTT"
  value_template: 'v{{ value_json.adc | replace("(adc)", "") }}'
  json_attributes_topic: "home/OMG_01/LORAtoMQTT"
  json_attributes_template: "{{ value_json.adc | tojson }}"

Thank you!

Edit:

if i copy paste the json from the logs, it is valid in the validator…

well probably just “{{ value_json }}” unless you only want everything configured by the adc key.
Best thing is just to try it and see the difference. In my case the root key was called StatusFWR and I wanted everything under that as an attribute.
From what you showed, you probably want everything under the root but want the state to be adc

for that bit, you just want “{{ value_json.adc }}”
I was adding the v and replacing the tasmota in mine.
Maybe this makes it easier to see
image
See the top line says v9.4.0 - that is what stripping the Tasmota and adding the V does. The state is v9.4.0 in my case but then you can also see the firmware version as an attribute without the v and unstripped…I hope that makes sense

Thank you for your help!

I don’t really know what all the code actually means, i’m just trying to figure this out as I go … So thank you for taking the time.

What you’re showing me is actually exactly what I would like it to show up as in home assistant. Where the Soil_1 is the “coffee maker” and the different sensors show up as part of it.

So if i am understanding this correctly I need a root key and attributes?
How are those distinguished?

Thanks

There’s nothing wrong with the json you are using…
This first one

"{{ value_json.adc | tojson }}"

Will read the value of adc into the state of the sensor you are creating. In this case sensor.soil_1_adc

Then this:

"{{ value_json | tojson }}"

for all the attributes

So maybe you would get the result you want with this:

- platform: mqtt
  name: "Soil_1_ADC"
  state_topic: "home/OMG_01/LORAtoMQTT"
  value_template: 'v{{ value_json.adc }}'
  json_attributes_topic: "home/OMG_01/LORAtoMQTT"
  json_attributes_template: "{{ value_json.adc | tojson }}"

Thank you!

I tried what you showed me and in the home assistant logs i get this:

Logger: homeassistant.helpers.template
Source: helpers/template.py:1335
First occurred: 9:35:14 PM (6 occurrences)
Last logged: 9:36:23 PM

Template variable warning: 'dict object' has no attribute 'adc' when rendering '{{ value_json.adc | replace("(adc)", "") }}'
Template variable warning: 'dict object' has no attribute 'adc' when rendering '{{ value_json.adc }}'

maybe value_json.0.adc or value_json[0].adc
This isn’t my strong suit…
If you read that json into a variable in the template editor you can work it out… I will give that a go,

Pasting this in the template editor seems to work ok

{% set val = {“id”:“LoRaADC”,“name”:“Soil_1”,“model”:“LSMS092D”,“tempc”:23.01273,“hum”:47.26543,“adc”:879} %}
{{ val }}
{{ val.adc }}

OK this is looking better than anything i’ve done so far!!!

Still the data is a sting for some reason ( i tried both of the example)
Getting there it looks like

If i paste that into my template editor i get:

TemplateSyntaxError: unexpected char '“' at 14

Edit:
Oh wow.
I replaced all the quotes, that got copy pasta’d and now it works in the template editor!

So how can I make that work in the yaml?

Thank you!!

It should just work in the yaml if it works in the editor. If the data is a string, use | float filter to convert it

So this is why i was thinking maybe my json isn’t right… It has the curly brackets…

The Rssi and all the other attributes are how i’d like to have the data that appears in the “message”, show up.
(I love having the rssi also that’s a cool add)

Instead it shows up as a string:

edit:
that’s using this:

- platform: mqtt
  name: "Soil_1_ADC"
  state_topic: "home/OMG_01/LORAtoMQTT"
  value_template: '{{ value_json[0].adc }}'
  json_attributes_topic: "home/OMG_01/LORAtoMQTT"
  json_attributes_template: "{{ value_json[0].adc }}"

Thank you!

The json you are showing in first post seems different to that sensor…

I have replaced the yaml with what you have been suggesting.
So far this seems to be the closest i have gotten to what i’m looking for.

What I started off with was a string of characters, here i still have a string of characters, but now the added: Rssi, snr, pfrror, packetsize

the logs show also show the curly brackets instead of the same as rssi, snr etc…


Subscribed topics:
home/OMG_01/LORAtoMQTT
1 most recently received message(s)
Received 7:12:48 PM
QoS: 0
Payload: rssi: -35
snr: 10.25
pferror: 12608
packetSize: 93
message: >-
  {"id":"LoRaADC","name":"Soil_1","model":"LSMS092D","tempc":23.01273,"hum":47.26543,"adc":879}

And in the home assistant logs i get:

Logger: homeassistant.helpers.template
Source: helpers/template.py:1346
First occurred: 10:17:07 PM (46 occurrences)
Last logged: 11:06:37 PM

Template variable error: dict object has no element 0 when rendering '{{ value_json[0].adc }}'

Does that make sense?

How do you mean?

Also, i’ve tried:


- platform: mqtt
  name: "Soil_1_ADC"
  state_topic: "home/OMG_01/LORAtoMQTT"
  value_template: '{{ value_json[0].adc }}'
  json_attributes_topic: "home/OMG_01/LORAtoMQTT"
  json_attributes_template: "{{ value_json[0].adc | tojson }}"

Which in the logs gives me:

Error parsing value: dict object has no element 0 (value: {"rssi":-36,"snr":9.75,"pferror":12322,"packetSize":93,"message":"{\"id\":\"LoRaADC\",\"name\":\"Soil_1\",\"model\":\"LSMS092D\",\"tempc\":21.56868,\"hum\":47.57414,\"adc\":878}"}, template: {{ value_json[0].adc | tojson }})

and

Template variable warning: 'dict object' has no attribute 'adc' when rendering '{{ value_json.adc }}'

Any pointers would be greatly appreciated.
Thanks in advance!

try value_json.message

The problem is your mqtt screenshot and the json you keep showing me is different…

Thanks again for helping me!

So replacing the value template and the json attributes template to value_json.message

gave me this:
Screen Shot 2021-04-29 at 7.46.54 PM

and the logs show this:

Logger: homeassistant.components.mqtt.mixins
Source: components/mqtt/mixins.py:212
Integration: MQTT (documentation, issues)
First occurred: 7:46:44 PM (2 occurrences)
Last logged: 7:47:54 PM

JSON result was not a dictionary

When you say different i’m not sure i understand how. If you mean the numbers changed, that’s because those are the sensor values that change with the environment so each reading will potentially change. Those are at least tempc, hum, and adc

Is that what you meant?

Thanks!

No - you never had a message key in the original json you posted.

What does this give you?

- platform: mqtt
  name: "Soil_1_ADC"
  state_topic: "home/OMG_01/LORAtoMQTT"
  value_template: '{{ value_json }}'
  json_attributes_topic: "home/OMG_01/LORAtoMQTT"
  json_attributes_template: "{{ value_json | tojson }}"

Show me the state for that (from dev-tools)

With that configuration i get: