Code executed at startup - MQTT

Hello, everybody!

I'm starting in this Arduino world with a small project to control my air conditioning.

First I got the infrared signal and once I got the commands, I proceeded to write this code to control my air via MQTT, but I have a working problem and I needed some advice too.

The problem is that when I load my code, or when I reset the ESP8266 module or if there is a loss of connection, in any of those circumstances, the air turns on without me giving any command. It only happens the first time, then the operation is correct. Could someone tell me what's wrong with my code?

#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRsend.h>
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char* ssid = "San Blas";
const char* password = "seba2703";
const char* mqtt_server = "192.168.0.15";
const uint16_t kIrLed = 4;

IRsend irsend(kIrLed);
WiFiClient espClient;
PubSubClient client(espClient);

uint16_t TEMP17[199] = {4269, 4497, 433, 1732, 433, 654, 433, 1732, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433, 5298, 4269, 4497, 433, 1732, 433, 654, 433, 1732, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 654, 433, 654, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433, 1732, 433, 654, 433, 1732, 433, 1732, 433, 1732, 433};
///Delete a long part//
uint16_t Off[199] = {4269, 0xxxx, 0000};
uint16_t On[199] = {4269,00};
 
void setup() {
  pinMode(BUILTIN_LED, OUTPUT);
 // digitalWrite(BUILTIN_LED, HIGH);
  irsend.begin();
//#if ESP8266
 // Serial.begin(115200, SERIAL_8N1, SERIAL_TX_ONLY);
//#else  // ESP8266
  //Serial.begin(115200, SERIAL_8N1);
//#endif  // ESP8266
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  }

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("WiFi connected - ESP IP address: ");
  Serial.println(WiFi.localIP());
}

void callback(String topic, byte* message, unsigned int length) {
  Serial.print("Message arrived on topic: ");
  Serial.print(topic);
  Serial.print(". Message: ");
  String messageTemp;
  int i=0;
  for (i = 0; i < length; i++) {
    Serial.print((char)message[i]);
    messageTemp += (char)message[i];
  }
  Serial.println();
  
  if(topic=="esp1/habitacion/aire"){
      Serial.print("Estado del aire: ");
      if(messageTemp == "1"){
        irsend.sendRaw(On, 199, 38);
        Serial.print("Encendido");
        client.publish("esp1/habitacion/aire/state","ON");
      }
      else if(messageTemp == "0"){
        irsend.sendRaw(Off, 199, 38);
        Serial.print("Apagado");
        client.publish("esp1/habitacion/aire/state","OFF");
      }
  }

  if(topic=="esp1/habitacion/aire/temperatura"){
      Serial.print("Temperatura del aire: ");
      if(messageTemp == "17"){
        irsend.sendRaw(TEMP17, 199, 38);
        Serial.print("17º C");
        client.publish("esp1/habitacion/aire/temperatura/state","17");
      }
      else if(messageTemp == "18"){
        irsend.sendRaw(TEMP18, 199, 38);
        Serial.print("18º C");
        client.publish("esp1/habitacion/aire/temperatura/state","18");
      }
      else if(messageTemp == "19"){
        irsend.sendRaw(TEMP19, 199, 38);
        Serial.print("19º C");
        client.publish("esp1/habitacion/aire/temperatura/state","19");
      }
      else if(messageTemp == "20"){
        irsend.sendRaw(TEMP20, 199, 38);
        Serial.print("20º C");
        client.publish("esp1/habitacion/aire/temperatura/state","20");
      }
      else if(messageTemp == "21"){
        irsend.sendRaw(TEMP21, 199, 38);
        Serial.print("21º C");
        client.publish("esp1/habitacion/aire/temperatura/state","21");
      }
      else if(messageTemp == "22"){
        irsend.sendRaw(TEMP22, 199, 38);
        Serial.print("22º C");
        client.publish("esp1/habitacion/aire/temperatura/state","22");
      }
      else if(messageTemp == "23"){
        irsend.sendRaw(TEMP23, 199, 38);
        Serial.print("23º C");
        client.publish("esp1/habitacion/aire/temperatura/state","23");
      }
      else if(messageTemp == "24"){
        irsend.sendRaw(TEMP24, 199, 38);
        Serial.print("24º C");
        client.publish("esp1/habitacion/aire/temperatura/state","24");
      }
      else if(messageTemp == "25"){
        irsend.sendRaw(TEMP25, 199, 38);
        Serial.print("25º C");
        client.publish("esp1/habitacion/aire/temperatura/state","25");
      }
      else if(messageTemp == "26"){
        irsend.sendRaw(TEMP26, 199, 38);
        Serial.print("26º C");
        client.publish("esp1/habitacion/aire/temperatura/state","26");
      }
      else if(messageTemp == "27"){
        irsend.sendRaw(TEMP27, 199, 38);
        Serial.print("27º C");
        client.publish("esp1/habitacion/aire/temperatura/state","27");
      }
      else if(messageTemp == "28"){
        irsend.sendRaw(TEMP28, 199, 38);
        Serial.print("28º C");
        client.publish("esp1/habitacion/aire/temperatura/state","28");
      }
      else if(messageTemp == "29"){
        irsend.sendRaw(TEMP29, 199, 38);
        Serial.print("29º C");
        client.publish("esp1/habitacion/aire/temperatura/state","29");
      }
      else if(messageTemp == "30"){
        irsend.sendRaw(TEMP30, 199, 38);
        Serial.print("30º C");
        client.publish("esp1/habitacion/aire/temperatura/state","30");
      }
  } 
  
  Serial.println();
}

void reconnect() {
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    if (client.connect("ESP8266Client")) {
      Serial.println("connected");  
      client.subscribe("esp1/habitacion/aire");
      client.subscribe("esp1/habitacion/aire/temperatura");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}


void loop() {
    if (!client.connected()) {
    reconnect();
  }
  if(!client.loop())
    client.connect("ESP8266Client");
}

Second I wanted to ask your advice about the same code because the second part (where I control the temperature) I am seeing that it is a too long code and I think I could shrink it a bit, any recommendation?

Thank you very much!

the air turns on without me giving any command.

what does "turns on" mean? did you receive a message? what?

instead having a separate case for each temperature, why not have a sub-function that processes the message as an argument

void
temp (
    const char *messageTemp)
{
    irsend.sendRaw(atoi (messageTemp), 199, 38);
    Serial.print(messageTemp);
    Serial.println("º C");
    client.publish("esp1/habitacion/aire/temperatura/state", messageTemp);
}

gcjr:
did you receive a message?

Yeah, after reset the ESP, I obtened this

Captura de Pantalla 2020-03-04 a la(s) 12.31.44.png

and obviously my air is turn on

Captura de Pantalla 2020-03-04 a la(s) 12.31.44.png

Is the sender that turns the air on setting the MQTT retain flag?

wildbill:
Is the sender that turns the air on setting the MQTT retain flag?

Well, I'm using OpenHAB but I disable all the parameters, so it does not have a flag.

When I run on my console mosquitto_sub -h localhost -t esp1/habitacion/aire
I always get 1 before I start the ESP.

If I then connect, the air is turned on, I turn it off by sending mosquitto_pub -h localhost -t esp1/habitacion/aire -m 0
but if I close the console and re-run the command to publish I get 1 again.

Sound like your issue is MQTT, not Arduino.

it seems like the message must be old and coming from some buffer. (i've seen this with test equipment)

could you try unpowering your arduino long enough to make sure memory is clean and power up and see if the unsolicited message appears.

even if it doesn't appear, do a hot reset is see what happens

IRsend irsend(kIrLed);
WiFiClient espClient;
PubSubClient client(espClient);

These three are suspect to me. You are creating objects -before- setup. IF they have any code in their constructors that depends on anything else. You have no way of knowing if what they "need" exists yet or not. And horrible things can happen.

Better..

IRsend* irsend;
WiFiClient* espClient;
PubSubClient* client;


void setup(void) {

   irsend  = new IRsend(kIrLed);
   espClient  = new WiFiClient;
   client  = new PubSubClient(espClient);

Then treat them as global pointers to objects as opposed to the actual objects themselves.
This way you can be sure everything is as it should be when they are constructed.

Hope this helps!

-jim lee

You are creating objects -before- setup.

isn't that the fundamental concept of class object constructors?

Sure you can do it. But those classes have to be written so that they don't "expect" anything to be already created in their universe during their constructor. As a user of these classes, unless you go look at their source code, you don't know what they are expecting on creation. So its best to just make sure they are created when you know its ok.

Even if what they rely on are are all globals, you have no way of knowing the order of their creation. Unless you create them your self and that starts in setup().

Been there, hit that wall, thought I was nuts. 'Till I realized some object's constructor was expecting another object to be ready for use. Messy messy in your memory!

Most won't have this issue because a lot of people are carful of this when they design their code. But, how well do you know the source of everything you use?

-jim lee

Well investigating a little, I realized that I had left the option of retained message activated in OpenHAB and when I restarted I took that value and executed it. I simply fixed it by sending an empty message to the topic and removing the retention.