One Arduino temperature MQTT sensor with more values

Arduino support via MQTT and autodiscovery to HA is great! But having Arduino UNO with a few HA switches and several HA temperature sensors with a short additional program code - it exceeds RAM limit. I have tested that 5 switches + 1-2 temp sensors are still OK (but with 8 sensors not).
The idea is to use just one HA sensor on Arduino side to send all the tempreature values, delimited by e.g. semicolon. But how to split the string of values, e.g. “12;25;33;25;33” into several individual sensors at HA side using scripts or templates?

Is it the fact that you use multiple “HA sensors” (whatever that is) that clogs your RAM?
If not, I don’t see the point of merging them on Arduino, then “unmerge” them on HA…

I believe the problem is that the discovery message doesn’t fit in the MCU’s SRAM. That should be easily solved by using PROGMEM. You’ll probably need to use publish_P.

Or just get rid of MQTT discovery altogether and define you MQTT sensors in configuration.yaml.

It is possible to extract your combined payload using value_template, but I don’t think it’s necessary. It makes much more sense to publish individual values in separate topics.

If it’s so, keep in mind you can use abbreviated command name in the payload as well

But yeah, there might be room for memory management improvement in the code.
Maybe the OP could post it…

Dawid Chyrzyński made good job with HA Arduino integration. It can be improved (e.g. above mentioned abbreviations etc.). But MQTT discovery is great feature saving time (having several config files, each hundreds of lines and have to pair them with Arduino code).
So for this moment I would stay with this concept. Could someone of you help me with a template/script to split the value of one sensor across more sensors in HA?

Sorry, but I don’t think this would help with SRAM usage. Your MQTT discovery message would have to contain the configuration and value templates for all of the sensors, and that’ll most likely take up more SRAM than the actual publishing of the values. So you wouldn’t save any.

It could help if you had the configuration of the sensors in configuration.yaml, but you don’t seem to want that.

The library already seems to be using the abbreviations: arduino-home-assistant/DeviceTypeSerializer.cpp at a4e50b7d048373d1254fef2e3e48f5e9a5fd51fc · dawidchyrzynski/arduino-home-assistant · GitHub
And a lot of stuff is PROGMEM already.
How much extra RAM usage per sensor are you seeing?

1 Like

The experience is that having 5 switches + 2 temp sensors is OK. Just declaration of additional sensors causes program failure. The RAM utilization after compilation is about 70% (Flash 92%).
I suppose, that using one sensor and merged payload I will have other sensor manually configured at HA side (but just on HA side :slight_smile: ) Therefore the saving of RAM is reasonable.

That would certainly work. However, at that point it might be easier to just configure everything manually in Home Assistant, get rid of arduino-home-assistant and handle everything just with pubsubclient. That would be the most memory-efficient approach.

If you insist on using one sensor with all of the temperatures combined, you’ll need to create a bunch of template sensors, and probably also exclude the combined sensor from recorder as it would be pretty much useless.

You can play with templates in developer tools:
Open your Home Assistant instance and show your template developer tools.

{% set combined = '12;25;33;25;33' %}
{{ combined.split(';')[0] }}

Example template sensor:

template:
  - sensor:
      - name: "First temperature"
        unit_of_measurement: "°C"
        state: >
          {{ states('sensor.combined').split(';')[0] }}
1 Like

“Krásná práce!” (Well done!) This is exactly what I need! Many thanks! Where we can have a beer on me?

Hi. I’m trying to do the same but its not working.
I receive on my MQTT Broker values like this: 1.00;0.30;26.74;48.53;15.16
On configuration.yaml I’ve created a mqtt sensor:

mqtt:
  sensor:
    - name: "abc_all"
      state_topic: "TABC"

I’ve added a new card to my Dashboard and selected the new Entity abc_all.
The values are shown and updated. Everything ok until now.

In @ondras12345 example the values are manually inserted:

{% set combined = '12;25;33;25;33' %}

I’ve changed it to:

{% set combined = sensor.abc_all %}

Then I get this error: UndefinedError: ‘sensor’ is undefined
How can I get the values, split them and create individual cards for each value?
Thank you for any help

Try

{% set combined = states('sensor.abc_all') %}
{{ combined.split(';')[0] }}

or just

{{ states('sensor.abc_all').split(';')[0] }}

Thanks, it works like that on Developer Tools → Template
But, then, on configuration.yaml, I’ve added:

template:
  - sensor:
      - name: "First temperature"
        unit_of_measurement: "°C"
        state: >
          {{ states('sensor.combined').split(';')[0] }}

It doesn’t work. The result is always 0ºC
Then I’ve tried:

template:
  - sensor:
      - name: "First temperature"
        unit_of_measurement: "°C"
        state: >
          {{ states('sensor.abc_all').split(';')[0] }}

It works like this, the value changes.
My question:
The Developer Tools → Template is just to try code and see the result and then copy that code to the right place or, the code should stay there and it will be called from other files, like in your example:

Developer Tools → Template

{% set combined = states('sensor.abc_all') %}

an then call from configuration.yaml:

{{ combined.split(';')[0] }}

Thank again :+1:

You’ll need to split() in every one of your template sensors.
Developer Tools → Template is just for development. Variables defined there cannot be used from template sensors.

This didn’t work because sensor.combined does not exist.

Hello,

Please let me know if it is possible to use the Arduino library done by Dawid Chyrzyński Home assistant integration and send the temperature like it was presented before by @Slavomir (“12;25;33;25;33”). In my case when I add the folowing command for the third sensor dht10.begin(); the sketch will not work. With 2 DHT11 sensors is working fine. So even if I want to use only one entity (HASensor temp1) to transmit all the temperature like it was presented by @Slavomir still is not working.
The used memory is:

Sketch uses 27482 bytes (85%) of program storage space. Maximum is 32256 bytes.
Global variables use 1008 bytes (49%) of dynamic memory, leaving 1040 bytes for local variables. Maximum is 2048 bytes.

You can see below the entire sketch:


#include <Arduino.h>
#include <Ethernet.h>
#include <ArduinoHA.h>
#include <DHT.h>
#include <DHT_U.h>
#define DHTPIN8 8
#define DHTPIN9 9
#define DHTPIN10 10
#define DHTTYPE DHT11
#define BROKER_ADDR         IPAddress(192,168,1,100)
#define BROKER_USERNAME     "mqtt-use" // replace with your credentials
#define BROKER_PASSWORD     "*****"
DHT dht8(DHTPIN8, DHTTYPE);
DHT dht9(DHTPIN9, DHTTYPE);
DHT dht10(DHTPIN10, DHTTYPE);
byte mac[] = {0x00, 0x10, 0xFA, 0x6E, 0x38, 0x4A};
unsigned long lastSentAt = millis();
String  allTemp="";
//double lastValue = 0;
EthernetClient client;
HADevice device(mac, sizeof(mac));
HAMqtt mqtt(client, device);
HASensor temp1("temp1Et1PD"); // "temp" is unique ID of the sensor. You should define your own ID.
void onBeforeSwitchStateChanged(bool state, HASwitch* s)
{
    // this callback will be called before publishing new state to HA
    // in some cases there may be delay before onStateChanged is called due to network latency
}

void setup() {
    // you don't need to verify return status
    Ethernet.begin(mac);
    dht8.begin();
    dht9.begin();
    dht10.begin();
    // set device's details (optional)
    device.setName("ArduinoUno1");
    device.setSoftwareVersion("1.0.0");
    device.setModel("ATmega2560");

    temp1.setName("Camera1 Temp");

    mqtt.begin(BROKER_ADDR, BROKER_USERNAME, BROKER_PASSWORD);
    
}
void loop() {
    Ethernet.maintain();
    mqtt.loop();
    if ((millis() - lastSentAt) >= 10000) {                           
        allTemp += dht8.readTemperature();
        allTemp += ";";
        allTemp += dht9.readTemperature();
        allTemp += ";";
        allTemp += dht10.readTemperature();
        const char *all_temp_test = allTemp.c_str();
        lastSentAt = millis();
        temp1.setValue(all_temp_test);
        allTemp = "";
        //temp2.setValue(dht9.readTemperature());
        //temp.setValue(lastValue);
        // Supported data types:
        // uint32_t (uint16_t, uint8_t)
        // int32_t (int16_t, int8_t)
        // double
        // float
        // const char*
    }
}

Please share with me your solution!

Thanks