Nodemcu, Mqtt, relay status

I am using mqtt broker (adafruit) to send command to nodemcu (esp8266) to turn on/off relays ..it works nice when i am home and see that relay is turned on/off, but how to be sure that relay is turned on/off when i am not at home.
What code should i upload to nodemcu to get status of the relay, or to get info that nodemcu turned relay on/off.

Have the Nodemcu send a message back via MQTT confirming the change of relay status

@UKHeliBob thanks for reply, but how to do that? i am using Adafruit mqtt broker
what is the code that sends the message to mqtt as a confirmation of relay status change

What is sending the command to the broker to turn the relay on and off ?

I am using

https://play.google.com/store/apps/details?id=snr.lab.iotmqttpanel.prod.pro&hl=en_US&gl=US&pli=1

for Android or i can go online on website adafruit.io and from there send command to nodemcu to turn on relay on off

Presumably that app can see messages received by the broker. If so it will see a message such as "relay closed" or "relay open" if you send it from the Nodemcu

how to see that?

I don't know as I don't have the app, but it would be a pretty poor MQTT dashboard if it could not see the messages sent to your topics on the broker

what MQTT dashboard do you suggest?

I have had a look at the app you are using. You can set up a Text Log panel, associate it with a topic and any messages sent to that topic, such as "Relay on", "Relay off" etc will be displayed in that panel

yes you are right but i have no problem with mqtt because mqtt broker sends command with no problem, i have problem with nodemcu because i have no information from nodemcu that it executed the command

on the other hand, when i get message on IoT app in text log that Relay is ON, that doesnt mean that nodemcu has really turned on the relay, because maybe nodemcu is offline lack of wifi

The idea is that you send a message from the dashboard to the NodeMCU telling it to turn on the relay and that the NodeMCU then sends back a message telling you that it received your message and that it has turned on the relay

If the NodeMCU does not receive your message then it will not reply and you will know that your message has not been acted upon

Please post the full sketch that you have running on the NodeMCU, using code tags when you do

yes thats the point....to get nodemcu to send back a message telling me that it has received my command and executed it by turning relay on/off
please find code below

 /***************************************************
  Adafruit MQTT Library ESP8266 Example
  Must use ESP8266 Arduino from:
    https://github.com/esp8266/Arduino
  Works great with Adafruit's Huzzah ESP board & Feather
  ----> https://www.adafruit.com/product/2471
  ----> https://www.adafruit.com/products/2821
  Adafruit invests time and resources providing this open source code,
  please support Adafruit and open-source hardware by purchasing
  products from Adafruit!
  Written by Tony DiCola for Adafruit Industries.
  MIT license, all text above must be included in any redistribution
  Code is edited by Sachin Soni for it's project called
  Ultimate Home Automation
  For Project video, visit his YouTube channel named "CreativeDesk"
 
  
 
 ****************************************************/
//for esp32 use <wifi.h> ,for esp8266 use <esp8266wifi.h>
// this code is for esp32 for using esp8266 you just need to change <wifi.h> into <esp8266wifi.h> and also change the relay pin 
#include <ESP8266WiFi.h>
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"


/************************* Pin Definition *********************************/

//Relays for switching appliances
#define relay1            D0  //GPIO 16
#define relay2            D1  //GPIO 5
#define relay3            D2  //GPIO 4
#define relay4            D3  //GPIO 0
#define buzzer            26  

//buzzer to know the status of MQTT connections and can be used for any other purpose according to your project need.


byte relayPins [] = { relay1, relay2, relay3, relay4 };
#define N_RELAY_PINS sizeof(relayPins);

  
/************************* WiFi Access Point *********************************/

#define WLAN_SSID       "12345"
#define WLAN_PASS       "54321"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER      "io.adafruit.com"
#define AIO_SERVERPORT  1883                   // use 8883 for SSL
#define AIO_USERNAME    "xxxxxxx"   //Your Username
#define AIO_KEY         "xxxxxxx" // Your API Key

/************ Global State (you don't need to change this!) ******************/

// Create an ESP8266 WiFiClient class to connect to the MQTT server.
WiFiClient client;
// or... use WiFiFlientSecure for SSL
//WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);

/****************************** Feeds ***************************************/

// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>

Adafruit_MQTT_Publish Light = Adafruit_MQTT_Publish(&mqtt, AIO_USERNAME "/feeds/light");


// Setup a feed called 'onoff' for subscribing to changes.
Adafruit_MQTT_Subscribe Light1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/faza1");
Adafruit_MQTT_Subscribe Fan1 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/faza2");
Adafruit_MQTT_Subscribe Light2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/relay3");
Adafruit_MQTT_Subscribe Fan2 = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/relay4");




/*************************** Sketch Code ************************************/

// Bug workaround for Arduino 1.6.6, it seems to need a function declaration
// for some reason (only affects ESP8266, likely an arduino-builder bug).
void MQTT_connect();

void setup() {
  Serial.begin(115200);

  delay(10);

  pinMode(relay1, OUTPUT);
  digitalWrite (relay1, HIGH);
  pinMode(relay2, OUTPUT);
  digitalWrite (relay2, HIGH); 
  pinMode(relay3, OUTPUT);
  digitalWrite (relay3, HIGH); 
  pinMode(relay4, OUTPUT);
  digitalWrite (relay4, HIGH);


 
  Serial.println(F("Adafruit MQTT demo"));

  // Connect to WiFi access point.
  Serial.println(); Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: "); 
  Serial.println(WiFi.localIP());
  
  // Setup MQTT subscription for onoff feed.
  mqtt.subscribe(&Light1);
  mqtt.subscribe(&Fan1);
  mqtt.subscribe(&Light2);
  mqtt.subscribe(&Fan2);
}

uint32_t x=0;

void loop() {
  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

  
  // this is our 'wait for incoming subscription packets' busy subloop
  // try to spend your time here

  Adafruit_MQTT_Subscribe *subscription;
  while ((subscription = mqtt.readSubscription(5000))) {
    if (subscription == &Light1) {
      Serial.print(F("Got: "));
      Serial.println((char *)Light1.lastread);
      int Light1_State = atoi((char *)Light1.lastread);
      digitalWrite(relay1, !Light1_State);
      
    }
    if (subscription == &Light2) {
      Serial.print(F("Got: "));
      Serial.println((char *)Light2.lastread);
      int Light2_State = atoi((char *)Light2.lastread);
      digitalWrite(relay2, !Light2_State);
    }
    if (subscription == &Fan1) {
      Serial.print(F("Got: "));
      Serial.println((char *)Fan1.lastread);
      int Fan1_State = atoi((char *)Fan1.lastread);
      digitalWrite(relay3, !Fan1_State);
    }
    if (subscription == &Fan2) {
      Serial.print(F("Got: "));
      Serial.println((char *)Fan2.lastread);
      int Fan2_State = atoi((char *)Fan2.lastread);
      digitalWrite(relay4, !Fan2_State);
      
    }
  }

 
  // ping the server to keep the mqtt connection alive
  // NOT required if you are publishing once every KEEPALIVE seconds
  /*
    if(! mqtt.ping()) {
    mqtt.disconnect();
    }
  */
}

// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;

  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }

  Serial.print("Connecting to MQTT... ");

  uint8_t retries = 3;
  digitalWrite(buzzer, HIGH);
  delay(200);
  digitalWrite(buzzer, LOW);
  delay(200);
  digitalWrite(buzzer, HIGH);
  delay(200);
  digitalWrite(buzzer, LOW);
  delay(200);
  while ((ret = mqtt.connect()) != 0) { // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);  // wait 5 seconds
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1);
    }
  }
  Serial.println("MQTT Connected!");
  digitalWrite(buzzer, HIGH);
  delay(2000);
  digitalWrite(buzzer, LOW);
}

Does the Adafruit library support QoS1 or QoS2?

I think yes

The code looks for incoming messages by doing this

  while ((subscription = mqtt.readSubscription(5000)))
  {
    if (subscription == &Light1)
    {
      Serial.print(F("Got: "));
      Serial.println((char *)Light1.lastread);
      int Light1_State = atoi((char *)Light1.lastread);
      digitalWrite(relay1, !Light1_State);
    }

So, you need to send a message back immediately after the digitalWrite(). I am not familiar with the Adafruit MQTT library having used PubSubClient for my MQTT projects, but the library has examples of how to publish a message to an MQTT topic

I have read that pubsubclient works great with adafruit
so please write the code with pubsubclient

I don't have time to write your code for you, but take a look at the Adafruit MQTT example named mqtt_esp8266. It sends a message to a topic named photocell every 5 seconds using the command

photocell.publish(x++);

Look at the code to see how it subscribes to the topic and add a topic of your own called feedback. Then you could do this when the ESP8266 receives a command to change the relay state

feedback.publish("Relay state changed");

If you subscribe to that topic using your app then you should see the message in the Text Log panel that you have defined to be subscribed to that topic

Sorry for asking
i will try of course, thanks for your time

Can I just check some things with you ?

If I understand things correctly you are using this MQTT control panel https://play.google.com/store/apps/details?id=snr.lab.iotmqttpanel.prod.pro&hl=en_US&gl=US&pli=1 to send commands to your NodeMCU via the Adafruit MQTT broker

If that is the case then how do you enter your Adafruit key into the control panel app ?