I found a code online to control a LED using ESP8266 so I modified that code to control two LEDs and that’s it. The purpose of this project was to test the connection stability and so far the system is not stable at all, so before we go further let me describe the system components first:
-
HA (installed in a VM) to control the LEDs.
-
I’m using a TPLINK mesh router, so the esps and the HA are connected to that router.
-
ESP8266 - D1 - mini.
On the HA side, the configuration.yaml file as following:
# Light
light:
- platform: mqtt
name: 'Office lamp'
state_topic: 'home/office/light1/status'
command_topic: 'home/office/light1/switch'
optimistic: false
qos: 1
retain: true
- platform: mqtt
name: 'Office main'
state_topic: 'home/office/light2/status'
command_topic: 'home/office/light2/switch'
optimistic: false
qos: 1
retain: true
Since the connection wasn’t stable, I tried to change the QoS and the problem still there. At the beginning I did a couple of tests to test the stability, and one of these tests was:
“press the reset button on the esp to reboot and while you pressing change the led state by clicking on it once”.
Sometime the esp after reboot is not reachable (from the dashboard I mean, if you tried to change the led state it’s not responding). At the beginning I thought my shitty code was the problem so I decided to test the previous code again (the online code) and I got the same results.
The next thing came to me was “BECAUSE OF THE ROUTER” so I decided to build a local network and it was not the problem.
“Maybe because of the library” so I tried to use a different library and it gave me the same result. When you check the MQTT logs you will see the esp is connected, so why I can’t control it?
Suddenly I decided to open wireshark to see what is going on, for some reason you will see that the HA tried to ‘re transmit’ the packet again and again (something related to the SYN) and you will see also the HA (or the broker) ping the esp and the esp send the response back, hah??
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#define MQTT_VERSION MQTT_VERSION_3_1_1
const PROGMEM uint8_t LED_PIN = D1;
const PROGMEM uint8_t LED2_PIN = D2;
// Wifi: SSID and password
const char* WIFI_SSID = "xxxxxxxx";
const char* WIFI_PASSWORD = "xxxxxxxx";
// MQTT: ID, server IP, port, username and password
const PROGMEM char* MQTT_CLIENT_ID = "office_light1";
const PROGMEM char* MQTT_CLIENT2_ID = "office_light2";
const PROGMEM char* MQTT_SERVER_IP = "192.168.68.143";
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
// MQTT: topics
const char* MQTT_LIGHT_STATE_TOPIC = "office/light1/status";
const char* MQTT_LIGHT_COMMAND_TOPIC = "office/light1/switch";
const char* MQTT_LIGHT2_STATE_TOPIC = "office/light2/status";
const char* MQTT_LIGHT2_COMMAND_TOPIC = "office/light2/switch";
// payloads by default (on/off)
const char* LIGHT_ON = "ON";
const char* LIGHT_OFF = "OFF";
boolean m_light_state = false; // light is turned off by default
boolean m_light2_state = false; // light is turned off by default
WiFiClient wifiClient;
PubSubClient client(wifiClient);
//Function to publish Office light state
void publishLightState(uint8_t TopicCase) {
switch(TopicCase) {
case 1:
if(m_light_state)
client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_ON, true);
else
client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_OFF, true);
break;
case 2:
if(m_light2_state)
client.publish(MQTT_LIGHT2_STATE_TOPIC, LIGHT_ON, true);
else
client.publish(MQTT_LIGHT2_STATE_TOPIC, LIGHT_OFF, true);
break;
default:
break;
}
}
void setLightState(uint8_t SwitchCase) {
switch(SwitchCase) {
case 1:
if(m_light_state) {
digitalWrite(LED_PIN, HIGH);
Serial.println("INFO: Desk light is ......... ON"); }
else {
digitalWrite(LED_PIN, LOW);
Serial.println("INFO: Desk light is ......... OFF"); }
break;
case 2:
if(m_light2_state) {
digitalWrite(LED2_PIN, HIGH);
Serial.println("INFO: Main light is ......... ON"); }
else {
digitalWrite(LED2_PIN, LOW);
Serial.println("INFO: Main light is ......... OFF"); }
break;
default:
break;
}
}
// function called when a MQTT message arrived
void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
// concat the payload into a string
String payload;
for (uint8_t i = 0; i < p_length; i++) {
payload.concat((char)p_payload[i]);
}
//Serial.print("CallBack function: payload is ............. ");
//Serial.println(payload);
// handle message topic
if (String(MQTT_LIGHT_COMMAND_TOPIC).equals(p_topic)) {
// test if the payload is equal to "ON" or "OFF"
if (payload.equals(String(LIGHT_ON))) {
if (m_light_state != true) {
m_light_state = true;
setLightState(1);
publishLightState(1);
}
} else if (payload.equals(String(LIGHT_OFF))) {
if (m_light_state != false) {
m_light_state = false;
setLightState(1);
publishLightState(1);
}
}
}
else if (String(MQTT_LIGHT2_COMMAND_TOPIC).equals(p_topic)) {
// test if the payload is equal to "ON" or "OFF"
if (payload.equals(String(LIGHT_ON))) {
if (m_light2_state != true) {
m_light2_state = true;
setLightState(2);
publishLightState(2);
}
} else if (payload.equals(String(LIGHT_OFF))) {
if (m_light2_state != false) {
m_light2_state = false;
setLightState(2);
publishLightState(2);
}
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("INFO: Attempting MQTT connection...");
// Attempt to connect
if (client.connect(MQTT_CLIENT_ID)) {
Serial.println("INFO: connected");
// Once connected, publish an announcement...
publishLightState(1);
// ... and resubscribe
client.subscribe(MQTT_LIGHT_COMMAND_TOPIC, 1);
} else {
Serial.print("ERROR: failed, rc=");
Serial.print(client.state());
Serial.println("DEBUG: try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
if (client.connect(MQTT_CLIENT2_ID)) {
Serial.println("INFO: connected");
// Once connected, publish an announcement...
publishLightState(2);
// ... and resubscribe
client.subscribe(MQTT_LIGHT2_COMMAND_TOPIC, 1);
} else {
Serial.print("ERROR: failed, rc=");
Serial.print(client.state());
Serial.println("DEBUG: try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void setup() {
// init the serial
Serial.begin(115200);
// init the led
pinMode(LED_PIN, OUTPUT);
pinMode(LED2_PIN, OUTPUT);
analogWriteRange(255);
setLightState(1);
setLightState(2);
// init the WiFi connection
Serial.println();
Serial.println();
Serial.print("INFO: Connecting to ");
WiFi.mode(WIFI_STA);
Serial.println(WIFI_SSID);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("INFO: WiFi connected");
Serial.print("INFO: IP address: ");
Serial.println(WiFi.localIP());
// init the MQTT connection
client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
client.setCallback(callback);
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
}
This is the code for the esp and below you will find a snapshot for the wireshark. As you can see (packet #8188) after many trails I was able to control the LEDs, and below you will see (packet #8758, the selected) the publish message (the esp respond), unfortunately it’s not possible to upload the PCAP file here.
Appreciate your help guys.