433mhz Transciever

Hi together,
I’ve started with arduino last year and soon found my way to esp8266 and after that to home assistant and ESPHome. Currently I’m working on a project which is supposed to work as follows.

I have two Arduinos in my backyard, one should monitor the watering process in the garden and the second is supposed to open/close a chicken door. As I sadly do not have access to my WiFi in the backyard, I want to use a 433mhz transceiver to communicate with a esp8266 being connected to ESPHome and allowing control of watering my garden and opening/closing chiecken door via Home Assistant. By now, the 433mhz connection works, however, I’m stuck when it comes to sharing the data from the esp8266 with ESPHome and switching things which are not GPIOs.

What I was hoping to find is basically a arduino scetch running independent of the ESPHome PollingComponent so that the PollingComponent would just get values at defined timepoints whereas the arduino scetch runs as usual. Any advice about what to read or where I could find beginner friendly help for this problem?

Here’s the code, I roughly want to use on the esp and which works so far (also if you can see a huge error within this code which might cause problems, please let me know)

#include <Arduino.h>
#include <SPI.h>
#include <RH_ASK.h>
#include <ESP8266WiFi.h>
#include <ESP8266mDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>

#ifndef STASSID
#define STASSID ***
#define STAPSK  ***
#endif

const char* ssid = STASSID;
const char* password = STAPSK;

RH_ASK driver(500, 13, 5, 0);

#define SERIAL_BAUD 9600

const int led_pin=13;
const int transmit_pin = 2;
const int receive_pin = 3;
unsigned long startMillis = 0;
unsigned long currentMillis;
unsigned long lastTXMillis = 0;
uint8_t sender_number = 0;
unsigned long t_last_package = 10000;
uint8_t counter = 1;

struct package
{
  uint8_t sender_number;
  uint8_t send_sender_number;
  // you may add time as string
  uint16_t hum_beet1;
  uint16_t hum_beet2;
  uint16_t hum_beet3;
  uint16_t hum_beet4; 
  uint8_t temp;
  uint8_t hum;
};
typedef struct package Package;
Package data;

void requestData(){
  Serial.println("requesting data");
  digitalWrite(led_pin, HIGH);
  data.sender_number = sender_number;
  if(counter == 1 || data.send_sender_number == 1){
    Serial.println("data1");
    data.send_sender_number = 1;
    //counter++;
    data.hum_beet1;
    data.hum_beet2;
    data.hum_beet3;
    data.hum_beet4;
  }
  else if(counter == 2 || data.send_sender_number == 2){
    data.send_sender_number = 2;
    counter = 1;
  }
  else{
    counter = 1;
  }
  driver.send((uint8_t *)&data, sizeof(data));
  driver.waitPacketSent();
  digitalWrite(led_pin, LOW);
}

void readData(){
  uint8_t buf[sizeof(data)];
  uint8_t buflen = sizeof(data);
  if(driver.recv(buf, &buflen)){
    memcpy(&data, &buf, buflen);
    Serial.println("Got Data");
    Serial.print("Beet1: ");
    Serial.println(data.hum_beet1);
    Serial.print("Beet2: ");
    Serial.println(data.hum_beet2);
    Serial.print("Beet3: ");
    Serial.println(data.hum_beet3);
    Serial.print("Beet4: ");
    Serial.println(data.hum_beet4);
    Serial.print("Buf: ");
    Serial.write(buf, buflen);
  }
}

void setup() {
    Serial.begin(SERIAL_BAUD);
  Serial.println("Booting");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("Connection Failed! Rebooting...");
    delay(5000);
    ESP.restart();
  }

  ArduinoOTA.setPassword("***");

  ArduinoOTA.onStart([]() {
    String type;
    if (ArduinoOTA.getCommand() == U_FLASH) {
      type = "sketch";
    } else { // U_FS
      type = "filesystem";
    }

    Serial.println("Start updating " + type);
  });
  ArduinoOTA.onEnd([]() {
    Serial.println("\nEnd");
  });
  ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
    Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
  });
  ArduinoOTA.onError([](ota_error_t error) {
    Serial.printf("Error[%u]: ", error);
    if (error == OTA_AUTH_ERROR) {
      Serial.println("Auth Failed");
    } else if (error == OTA_BEGIN_ERROR) {
      Serial.println("Begin Failed");
    } else if (error == OTA_CONNECT_ERROR) {
      Serial.println("Connect Failed");
    } else if (error == OTA_RECEIVE_ERROR) {
      Serial.println("Receive Failed");
    } else if (error == OTA_END_ERROR) {
      Serial.println("End Failed");
    }
  });
  ArduinoOTA.setHostname("***");
  ArduinoOTA.setPassword("***");
  ArduinoOTA.begin();
  Serial.println("Ready");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  ESP.wdtEnable(5000);

  if(!driver.init())
  {
    Serial.println("init failied");
  }
}

void loop() {
  if(millis()<=600000)
  ArduinoOTA.handle();
  delay(10);
  if(t_last_package <= millis()-startMillis){
    startMillis = millis();
    requestData();
  }
  readData();
}

in case you do also need the code for the “executing” component, meaning the arduino nano which is going to be placed in the backyard:

#include <Arduino.h>
#include <SPI.h>
#include <RH_ASK.h>

RH_ASK driver(500, 11, 12, 0);


#define SERIAL_BAUD 9600

const int led_pin=13;
const int transmit_pin = 2;
const int receive_pin = 3;
unsigned long startMillis = 0;
unsigned long currentMillis;
unsigned long lastTXMillis = 0;
uint8_t sender_number = 1;
int t_last_package = 5000;
const uint8_t hum_sensor[] = {A0, A1, A2, A3};



struct package
{
  uint8_t sender_number;
  uint8_t send_sender_number;
  // you may add time as string
  uint16_t hum_beet1;
  uint16_t hum_beet2;
  uint16_t hum_beet3;
  uint16_t hum_beet4;
  uint8_t temp;
  uint8_t hum;
};

typedef struct package Package;
Package data;

void readSensor(){
  data.hum_beet1 = analogRead(hum_sensor[0]);
  data.hum_beet2 = analogRead(hum_sensor[1]);
  data.hum_beet3 = analogRead(hum_sensor[2]);
  data.hum_beet4 = analogRead(hum_sensor[3]);
}

void sendData(){
  Serial.println("Sending data");
  digitalWrite(led_pin, HIGH);
  data.sender_number = sender_number;
  data.send_sender_number = 0;
  driver.send((uint8_t *)&data, sizeof(data));
  driver.waitPacketSent();
  digitalWrite(led_pin, LOW);
}

void readData(){
  uint8_t buf[sizeof(data)];
  uint8_t buflen = sizeof(data);
  if(driver.recv(buf, &buflen)){
    startMillis = millis();
    memcpy(&data, &buf, buflen);
    Serial.print("Read data: ");
    Serial.println(data.send_sender_number);
    Serial.print("Beet1: ");
    Serial.println(data.hum_beet1);
    Serial.print("Beet2: ");
    Serial.println(data.hum_beet2);
    Serial.print("Beet3: ");
    Serial.println(data.hum_beet3);
    Serial.print("Beet4: ");
    Serial.println(data.hum_beet4);
    Serial.print("Buf: ");
    Serial.write(buf, buflen);
  }
}

void setup() {
  Serial.begin(SERIAL_BAUD);
  if(!driver.init())
  {
    Serial.println("init failied");
  }
}

void loop() {
  readData();
  delay(100);
  if(data.send_sender_number == 1){
    readSensor();
    for(int i=0; i<5; i++)
    sendData();
  }
}

And here my first attempt to hand the data to Home Assistant. I am able to hand over individual data following the guide given here https://esphome.io/components/sensor/custom.html, however implementing the 433mhz transceiver fails

#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <RH_ASK.h>


class MyCustomSensor: public PollingComponent, public Sensor {
    public:
    

    Sensor *beet1_sensor = new Sensor();
    Sensor *beet2_sensor = new Sensor();
    Sensor *beet3_sensor = new Sensor();
    Sensor *beet4_sensor = new Sensor();
    const int transmit_pin = 5;
    const int receive_pin = 13;
    unsigned long startMillis = 0;
    unsigned long currentMillis;
    unsigned long lastTXMillis = 0;
    uint8_t sender_number = 0;
    uint8_t send_sender_number;
    int t_last_package = 10000;
    uint8_t counter = 1;
    int humidity1;
    int humidity2;
    int humidity3;
    int humidity4;
    const uint16_t transmit_rate = 500;
    const uint8_t rx_pin = 13;
    const uint8_t tx_pin = 5;
    const bool push_to_talk = 0;
    RH_ASK driver;

struct package
{
  uint8_t sender_number;
  uint8_t send_sender_number;
  // you may add time as string
  int hum_beet1;
  int hum_beet2;
  int hum_beet3;
  int hum_beet4; 
  uint8_t temp;
  uint8_t hum;
};
typedef struct package Package;
Package data;

void requestData(){
    data.sender_number = sender_number;
    if(counter == 1 || data.send_sender_number == 1){
        Serial.println("data1");
        data.send_sender_number = 1;
        //counter++;
    }
    else if(counter == 2 || data.send_sender_number == 2){
        data.send_sender_number = 2;
        counter = 1;
    }
    else{
        counter = 1;
    }
    driver.send((uint8_t *)&data, sizeof(data));
    driver.waitPacketSent();
}

void readData(){
  uint8_t buf[sizeof(data)];
  uint8_t buflen = sizeof(data);
  if(driver.recv(buf, &buflen))
    memcpy(&data, &buf, buflen);
    humidity1 = data.hum_beet1;
    humidity2 = data.hum_beet2;
    humidity3 = data.hum_beet3;
    humidity4 = data.hum_beet4;
}

void publish(){
    beet1_sensor->publish_state(humidity1);
    beet2_sensor->publish_state(humidity2);
    beet3_sensor->publish_state(humidity3);
    beet4_sensor->publish_state(humidity4);
}

  // constructor
MyCustomSensor() : PollingComponent(60000) {}

    void setup() override {
        RH_ASK driver(transmit_rate, rx_pin, tx_pin, push_to_talk);
    }
    void update() override {
        requestData();
        startMillis = millis();
        while(10000>= millis()-startMillis){
            readData();
            delay(10);
        }
        publish();
    }
};

I’m very thankfull for any help and I’m also willing to do some readingt and to do some reading about how to hand data over from a method to Home Assistant. It might already help, if you could point out why my code works if I define const values for the humidities and it fails when I want to receive data via 433mhz and what I might use to solve this issue.

And if there is something I should do differently when asking for help, please also let me know, this is my first post ever, so there is probably still a lot I can do better. :slight_smile:

Best wishes

What do you mean with “however implementing the 433mhz transceiver fails” ? What does fail?

One think I noticed:

Your while loop seems wrong. It will always end immediately. In general your control flow doesn’t seem right?

If power is not an issue (it’s not running on battery?) the most simple solution would be something like this:

void setup() override {
        RH_ASK driver(transmit_rate, rx_pin, tx_pin, push_to_talk);
    }
    void update() override {
        requestData();
    }
    void loop() override {
          bool receivedData = readData();
          if (receivedData) { 
                   publish();
          }
    }

You have to change readData to return true or false depending if new data was received.

If don’t wont to read that often you can set a bool like “sendRequest” in the update method to true and then in loop only readData if sendRequest is true. And then set sendRequest to false after publish.

Remember: Don’t use delay (or only with very small delays) or other blocking code ESPHome custom components. You will block everything else.

Dear @danielw,

thank you very much for your answer.

I meant when I use the code with constants for humidity1, 2, 3, 4 and I remove all the parts which are intended to implement the 433mhz communication it works (I see the values being handed to Home Assistant), so the error must have to do something with requestData() or the while loop.

I’m using the while loop to have readData() running for 10 seconds, this is done by setting startMillis= millis() and then waiting, until millis()-startMillis gets bigger than 10 seconds, however, I think this part causes an error when it comes to handling the WiFi. I really like your suggestion for this part as it does not introduce a “break”, which might interfear e.g. with the WiFi handling. I’ll try to do this tomorrow and see if it helped :slight_smile:

One more question I have is about the void loop() override{}. As far as I understand the setup() override{} is like the setup function in Arduino and the void update() override{} is like the loop in simple Arduino scetches, but what does void loop() override{} do and whats the difference to update() override{}?

No it’s not going to run on battery, so power will not be a problem :slight_smile:

Is there a reason why you wouldnt determine the frequency of reding using the PollingGomponent()?

I’ve used the delay(10) to reset the wdt as I wasn’t able to completely disable it (and to be honest it is not a bad thing to have a watchdog running^^) but with your solution I may not need it anymore.

Thank you very much for your help!

I can’t help you much on this topic but I’m wondering if you have seen mysensors? Similar to esphome but centered around 433 instead of wifi. Their serial gateway has an integration for HA.

You are right I read it wrong. But: It still doesn’t make much sense to call readData() in an endless loop for 10 seconds. At least you should break out of the loop wen you received data ( the readData method should return true or false on success for that).

Well loop() and update() are similar. update gets called less often (depending on the number you use in the PollingComponent constructor call in ms) . Loop gets called for every global loop iteration of ESPHome. (I think it is 12 ms or 17ms or something in ESPHome by default).

My idea was: Use update to make a request for data every 60 seconds and use loop to check if you have received a response and if so publish that data. You can use a bool flag to only do the read if a new request was made since the last time.

I thought it works this way: You request the data. The other devices will get the request and answer it. That may take a few ms. If you do the read in the update (depending on the PollingComponent) you will either have to wait in the method for the answer (block ESPHome) or will only be able to read the result the next poll. (But: I do not even know if it is possible to read the data 60 seconds later. Does the driver buffer it?). To be safe if would also do a read in update. If the answer always comes in like 5 ms max it may be best to just do it in update only but you should not wait 10 seconds.

Yes your code should never block the execution for more then a few ms. (you have to return out of loop/setup/update in a few ms at max) . That way you should not get a problem with the watchdog.

Have you looked into these nice little transceivers ? I have very good experience using them on Arduinos and others. In fact, I build a whole DIY long range mesh protocol on top of them.

They operate in the 433MHz band (frequency and tx power are configurable) and they expose the air data stream over a simple serial interface. All the timing and modulation encoding is done by the hardware. You just push stuff in on one side, and get it out on the other. Over the normal Arduino HW serial or SoftwareSerial.

Should work fine on ESP too.

You’re absolutely right, this would for sure interfear with the WiFi handling (this is probably one reason why I never got a working connection with ESPHome when using this code)

Ah, now it’s clear, thanks for pinting this out. I find it quite difficult to find a proper introduction on how individual things work, it’s all about working sensors, but nobody ever really explains why they work ^^

Yes, that’s exactly what I want at the moment, so that I do at least get my data transferred to Home Assistant, however, later I would also want to integrate a switch which allows me to open/close the dor or to switch the water valves. I was thinking of using template switches, but therefore I would need a local push component. Is it possible to run both on the same node?

I’ve tried the code you suggested, however, I didn’t really get much further.
The first problem is, that the esp got stuck at driver.waitPacketSent(). I found that this might be due to not including the if(!driver.init()), so I inculded it, but it still doesn’t work :confused:

This is the used code:

#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <RH_ASK.h>


class MyCustomSensor: public PollingComponent, public Sensor {
    public:
    

    Sensor *beet1_sensor = new Sensor();
    Sensor *beet2_sensor = new Sensor();
    Sensor *beet3_sensor = new Sensor();
    Sensor *beet4_sensor = new Sensor();
    const int transmit_pin = 5;
    const int receive_pin = 13;
    unsigned long startMillis = 0;
    unsigned long currentMillis;
    unsigned long lastTXMillis = 0;
    uint8_t sender_number = 0;
    uint8_t send_sender_number;
    int t_last_package;
    uint8_t counter = 1;
    int humidity1;
    int humidity2;
    int humidity3;
    int humidity4;
    const uint16_t transmit_rate = 500;
    const uint8_t rx_pin = 4;
    const uint8_t tx_pin = 5;
    const bool push_to_talk = 0;
    RH_ASK driver;

struct package
{
  uint8_t sender_number;
  uint8_t send_sender_number;
  // you may add time as string
  int hum_beet1;
  int hum_beet2;
  int hum_beet3;
  int hum_beet4; 
  uint8_t temp;
  uint8_t hum;
};
typedef struct package Package;
Package data;

void requestData(){
    data.sender_number = sender_number;
    if(counter == 1 || data.send_sender_number == 1){
        Serial.println("data1");
        data.send_sender_number = 1;
        //counter++;
    }
    else if(counter == 2 || data.send_sender_number == 2){
        data.send_sender_number = 2;
        counter = 1;
    }
    else{
        counter = 1;
    }
    Serial.println("sending request");
    driver.send((uint8_t *)&data, sizeof(data));
    Serial.println("waiting for package sent");
    driver.waitPacketSent();
    Serial.println("request send");
}

int readData(){
  uint8_t buf[sizeof(data)];
  uint8_t buflen = sizeof(data);
  Serial.println("reading data");
  if(driver.recv(buf, &buflen)){
    memcpy(&data, &buf, buflen);
    humidity1 = data.hum_beet1;
    humidity2 = data.hum_beet2;
    humidity3 = data.hum_beet3;
    humidity4 = data.hum_beet4;
    return 1;
  }
  else
    return 0;
}

void publish(){
    Serial.println("publishing");
    beet1_sensor->publish_state(humidity1);
    beet2_sensor->publish_state(humidity2);
    beet3_sensor->publish_state(humidity3);
    beet3_sensor->publish_state(humidity4);
}

MyCustomSensor() : PollingComponent(10000){}

    void setup() override {
        RH_ASK driver(transmit_rate, rx_pin, tx_pin, push_to_talk);
        if(!driver.init())
        {
            Serial.println("init failied");
        }
    // This will be called by App.setup()
    }
    void update() override {
        requestData();  
    }

    // This will be called every "update_interval" milliseconds.
    void loop() override{
        bool receivedData = readData();
        if(receivedData){
            publish();
        }
    }
};

This is the log

Showing logs:
[11:36:24]sl[I][logger:166]: Log initialized
[11:36:24][C][ota:366]: There have been 2 suspected unsuccessful boot attempts.
[11:36:24][I][app:029]: Running through setup()…
[11:36:24][C][wifi:033]: Setting up WiFi…
[11:36:24][D][wifi:324]: Starting scan…
[11:36:24]data1
[11:36:24]sending request
[11:36:24]waiting for package sent

To circumvent this problem I commented the driver.waitPacketSent() out, just to see what happenes. What I see is a long output of reading data (as I would expect), but when it comes to requesting data, the esp gets stuck at sending request. I was thinking, that it might be a internal timer running out, so I varied the PollingComponent, but still it hang itself at this step.

    Serial.println("sending request");
    driver.send((uint8_t *)&data, sizeof(data));
    Serial.println("waiting for package sent");
    driver.waitPacketSent();
    Serial.println("request send");

do you possibly have any idea why? I might also ask this question in a radiohead related forum. As soon as I get a answer there, I’ll of course also share it here.

During my various tries some more questions rose. I had a look at the main code for ESPHome and I came across the following code:

  custom::CustomSensorConstructor custom_customsensorconstructor = custom::CustomSensorConstructor([=]() -> std::vector<sensor::Sensor *> {
      auto my_sensor = new MyCustomSensor();
      App.register_component(my_sensor);
      return {my_sensor->beet1_sensor, my_sensor->beet2_sensor, my_sensor->beet3_sensor, my_sensor->beet4_sensor};
  });
  sensor_sensor = custom_customsensorconstructor.get_sensor(0);
  App.register_sensor(sensor_sensor);
  sensor_sensor->set_name("Beet1");
  sensor_sensor->set_force_update(false);
  sensor_sensor_2 = custom_customsensorconstructor.get_sensor(1);
  App.register_sensor(sensor_sensor_2);
  sensor_sensor_2->set_name("Beet2");
  sensor_sensor_2->set_force_update(false);
  sensor_sensor_3 = custom_customsensorconstructor.get_sensor(2);
  App.register_sensor(sensor_sensor_3);
  sensor_sensor_3->set_name("Beet3");
  sensor_sensor_3->set_force_update(false);
  sensor_sensor_4 = custom_customsensorconstructor.get_sensor(3);
  App.register_sensor(sensor_sensor_4);
  sensor_sensor_4->set_name("Beet4");
  sensor_sensor_4->set_force_update(false);

I was wondering what it actually does. My main interest would be the first part with custom::CustomSensorConstructor, this is the bit I included as lambda in the yaml, but I don’t quite get what it does. And the other part I would like to understand is the
sensor_sensor = custom_customsensorconstructor.get_sensor(0)
bit. As far as I understand this is the line, that hands over the sensor value from my Sensor *beet1_sensor to Home Assistant, is this correct? If so, how can I access this part within the main code?

And one last question. All methods within my MyCustomSensor class are public right? So when writing something like

MyCustomSensor test;
test.requestData();

I should be able to access the method requestData() from the main code, right?

PS: I know, that it probably is not a good idea to mess around with the main code because of many reasons, one of which surely is the reusability of the individual code, but I would really like to understand what everything does and therefore I was playing around and wondering why things I expected to work did not.

Thank you very much for your help and time!! :blush:

Thanks a lot for this hint! I haven’t looked into MySensors before and it really sounds very interesting. Maybe I will make use of this in a future project, however, currently I try to not only realise my project but also to understand why things work or why they don’t and therefore I would really like to get my setup to work even if I might later realise that it just can’t work, or other solutions (e.g. using MySensors :slight_smile: ) are much more suitable for my use case.
Thanks again for the great hin :+1:
@HeyImAlex, thanks for your hint as well. This might acutally be able to solve my problem, but my plan B (aka surendering to find a solution which allows me to use ask) is to just install a powerline 450e from fritz in my backyard.

I don’t know exactly what you mean. But I think it should work.

I think I have an idea what the issue could be. It looks like you create a new different driver in setup() and are not using that later on. I think C++ should not allow to do that :frowning:

I would change to type of driver your your class to a pointer

RH_ASK* driver;

And in setup:

driver = new RH_ASK(transmit_rate, rx_pin, tx_pin, push_to_talk);

You have to use → insteand of just . when using driver. Like in: driver->send( …

Let’s hope that helps.

Well now it gets complicated. I am no ESPHome developer just learned by looking into the code when writing custom components and so on.

In general ESPHome is mainly a code generaten platform together with a c++ library with nice components for ESP devices. It parses your yaml with python code and use it to generate a PlatformIO project all in C++ that then gets compiled an pushed to the esp devices.

And the custom component constructor is like a bridge from the yaml world to custom c++ components without the python stuff. It has nothing to do with comunication with HA. It justs creates your sensor objects at the correc time and holds the references to it. The system or your code can then later access them using .get_sensor . The sensor objects hold the state of the sensors for internal uses and to send it to HA/MQTT.

With main code do you mean a lambda in the yaml file? Yes then sure you do that. But: Do not create new instances of the component. Your component holds state like the driver, the current sensor state (in the inherited class) and so on.

I would just store a pointer to the component in a global.

In yaml:

globals:
   - id: my_custom_sensor
     type: MyCustomSensor*
     restore_value: no

# in the lambda of the custom sensor
      auto my_sensor = new MyCustomSensor();
      App.register_component(my_sensor);
      id(my_custom_sensor)=my_sensor; 
      return {my_sensor->beet1_sensor, my_sensor->beet2_sensor, my_sensor->beet3_sensor, my_sensor->beet4_sensor};

# then in other lambdas
  id(my_custom_sensor)->callSomeMethod();

C++ allows pretty much anything, it just assumes that the programmer knows what he’s doing :wink:

@Niklas_Pallmann, have to admit I didn’t read everything, but it looks like you’re trying to fit your code into the pretty limited constraints imposed by ESPHome with a sledgehammer. At this point, is there any reason to even use ESPHome ? Why not just continue the path you already are on, write the entire firmware in C++ and interface it with HA over MQTT ?

What I meant is that I would have a local polling component, which would regularely request the sensor data, but I also want to use switches, which would then need to be local push as they should e.g. open the chicken door when the button is pressed and not when the next update cycle by local polling is run. I was just wondering if it’s possible to run both on the same node as they might interfear when I have a polling and a pushing command simultaneously, but I think this is something I’ll figgure out later.

thanks a lot for the hint, I’ll try this. :blush:

That totally makes sense. Maybe I should just play around with it to understand what it acutally does.

with main code I meant the c++ code that is generated when you create a new ESPHome component. You will have a esphome header and a main cpp file in the src folder. I was just trying to call methods from the MyCustomSensor in the main cpp and it didn’t work. (Just like if you would use the LiquidCrystal library and call LiquidCrystal.write())

Yep, I feel like it just stops running :smiley:

Actually I havent tried to use MQTT. I’ve read, that the API would run more stable than a Mosquitto and after that tried to avoid MQTT. Also I’ve seen my sonoff basic drop out from the network when using Tasmota, which got much better since I switched to ESPHome. But I will have a look at MQTT again and see how much freedom I could get this way. Maybe my bad experience was also due to it being the very first thing I did. ^^
Thanks for the hint!

MQTT is extremely stable. It’s an industry standard to connect sensor networks that’s massively scalable, with massively meaning in the millions of sensors. It’s widely used outside of home automation for things like monitoring power plants, oil pipelines, railway sensor networks, etc.

Mosquitto is also very stable, so your bad experiences were probably due to a local install or configuration problem. From all IoT stuff I have, the two most reliable network protocols are, by far, MQTT and zwave. Maybe give it another shot at some point !

1 Like

You should be able to do that. But other for some tests it is not a good idea to change the generated source files. ESPHome provides lots of triggers to add a lambda action to call whatever C++ code you want to call.

I’m back in the place where I study, so I can’t really try anything there. I’ll give a update as soon as I will have any updates, but this may take a while.
Thanks a lot for your great help and suggestions so far! :blush: