

#include <WiFi.h>
#include <PubSubClient.h>
#include <esp_now.h>
#include <esp_wifi.h>
#define sw1 34
#define sw2 4
#define led 2
#define WIFI_CHANNEL 11
int channel;
uint8_t Address_node5[] = {0x58,0x2a,0xbd,0x7d,0xbd,0xbc};
int duty;
char msg[20];
String data ;
int chk_status_connect=0;
bool dir,led1,led2;
//----------------------get data from mqtt ------------------
String led01,led02,dir00,pwm_duty,node_id;
//int led01x,led02x,dirx;
bool led1x;
bool led2x;
bool dirx;
int pwm_dutyx;
int node_idx;
//------------------------------------------------------
//const char* ssid = "Hut_Temram 2.4 G";
//const char* password = "0868321536";
const char* ssid = "samtech";
const char* password = "samraeng";
bool toggle_sw1=0;
bool toggle_sw2=0;
String message;
int s01;
int sw_on=0;
#define vtopic "esp_now_2569"
const char* mqtt_server = "mqttgo.io";

WiFiClient espClient;
PubSubClient client(espClient);

// Data structure for receiving and sending.
typedef struct struct_message {
    char text[32];
    int pwm_duty;
    int id;
    bool in1;
    bool in2;
    bool out1;
    bool out2;
} struct_message;

struct_message myData;       // Information to send
struct_message incomingData; // Received information

//The function is called when data is sent.
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("\r\nLatest delivery status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Sent successfully." : "Send failed.");
}

// The function is called when data is submitted.
void OnDataRecv(const esp_now_recv_info *info, const uint8_t *incomingDataRaw, int len) {

const uint8_t *mac = info->src_addr;
//------------------------------------- check data incomming -------------
    Serial.println("\n=== [Received a new data frame.] ===");
    
    // Displays the sender's MAC address.
    Serial.printf("from MAC Address: %02X:%02X:%02X:%02X:%02X:%02X\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
    
    // Check the frame size (Frame Length Verification)
    Serial.printf("Size of data received. (Bytes): %d\n", len);
    Serial.printf("Expected structure dimensions(Bytes): %d\n", sizeof(struct_message));

    if (len != sizeof(struct_message)) {
        Serial.println("ÃƒÆ’Ã‚Â¢Ãƒâ€šÃ‚ÂÃƒâ€¦Ã¢â‚¬â„¢ [Error] Frame Format Incorrect! The data size does not match the structure");
        return;
    }
//-----------------------------------------------------------------------     
  
  
  memcpy(&incomingData, incomingDataRaw, sizeof(incomingData));
//-------------------- text data ---------------  
  Serial.print("---I received the information: ");
  Serial.print(incomingData.text);
//--------------- interger  data--------------  
  Serial.print(" |number: ");
  Serial.print(incomingData.pwm_duty);
  duty=incomingData.pwm_duty;
//-------------bool data-------------------
  Serial.print(" in1: ");
  Serial.print(incomingData.in1);dir=incomingData.in1;
  Serial.print(" in2: ");
  Serial.print(incomingData.in2);

  Serial.print(" out1: ");
  Serial.print(incomingData.out1);digitalWrite(led1, incomingData.out1);
  Serial.print(" out2: ");
  Serial.print(incomingData.out2);digitalWrite(led2, incomingData.out2);


}


void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  message = "";
  for (int i = 0; i < length; i++) {

    message = message + (char)payload[i];
  }
  Serial.print("message=");
  Serial.println(message);

    led01 = message.substring(3, 0); 
    led02 = message.substring(6, 3);
    dir00 = message.substring(9, 6);
    pwm_duty = message.substring(12, 9);
    node_id = message.substring(15, 12);

    led1x = led01.toInt(); 
    led2x = led02.toInt(); 
    dirx = dir00.toInt();
    pwm_dutyx = pwm_duty.toInt(); 
    node_idx = node_id.toInt(); 

    Serial.print("led01x =    ");Serial.print(led1x);Serial.println();
    Serial.print("led02x =    ");Serial.print(led2x);Serial.println();
    Serial.print("dirx   =    ");Serial.print(dirx);Serial.println();
    Serial.print("pwm_dutyx =  ");Serial.print(pwm_dutyx);Serial.println(); 
    Serial.print("node_idx =  ");Serial.print(node_idx);Serial.println();  
    
      myData.out1    =  led1x;
      myData.out2    =  led2x;   
      myData.in1     =  dirx;
      myData.pwm_duty=  pwm_dutyx; 
      myData.id      =  node_idx;
      //=========================== esp now send data to node 5======================
      strcpy(myData.text, "Greetings from mqtt .");  
      esp_err_t result = esp_now_send(Address_node5, (uint8_t *) &myData, sizeof(myData));
      if (result != ESP_OK) 
      {
        Serial.println("An error occurred during data transmission.");
      }     
}

void reconnect() {

  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // Create a random client ID
    String clientId = "ESP8266Client-";
    clientId += String(random(0xffff), HEX);
    // Attempt to connect
    if (client.connect(clientId.c_str())) {
      Serial.println("connected");

      client.subscribe(vtopic);
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}
void setup() {
  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);   
  
  pinMode(led, OUTPUT);    
  pinMode(sw1, INPUT_PULLUP); 
   pinMode(sw2, INPUT_PULLUP); 
   
  Serial.begin(115200);
  Serial.println("Starting...");
  
chk_status_connect=0;
 while(chk_status_connect < 10)
 {
   digitalWrite(led, HIGH);delay(500);digitalWrite(led, LOW);delay(500);
   chk_status_connect++;
 }
chk_status_connect=0;

  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
    channel = WiFi.channel();
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  Serial.print("Wi-Fi Channel: ");
  Serial.println(channel);
  
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);


   if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW startup failed.");
    return;
  }

  //Register receiver 5.
  esp_now_peer_info_t peerInfo5 = {};
  memcpy(peerInfo5.peer_addr, Address_node5, 6);
  peerInfo5.channel = WIFI_CHANNEL;
  peerInfo5.encrypt = false;

  if (esp_now_add_peer(&peerInfo5) != ESP_OK){
    Serial.println("Adding a peerInfo5 failed.");
    return;
  }
    // Register the Callback function for both incoming and outgoing calls.

esp_now_register_send_cb((esp_now_send_cb_t)OnDataSent);
 
esp_now_register_recv_cb((esp_now_recv_cb_t)OnDataRecv);   
   
}

void loop() {
  
  if (!client.connected()) {
    reconnect();
  }
  else{chk_status_connect++;
   if(chk_status_connect>20000){digitalWrite(led, !digitalRead(led));chk_status_connect=0;
      Serial.print("Wi-Fi Channel: ");
      Serial.println(channel);   
   }
  
  }
 
  
  client.loop();
  //---------------------- local control-----------------  

           if(digitalRead(sw1)==0)
           { delay(100);
               if(digitalRead(sw1)==0)
               {toggle_sw1 = !toggle_sw1;
                 if(toggle_sw1)data = "sw1on";else data = "sw1off";
                 data.toCharArray(msg, (data.length() + 1));
                 client.publish(vtopic, msg);
                 while(digitalRead(sw1)==0);
               }
           }

 //----------------------------------------------------


           if(digitalRead(sw2)==0)
           { delay(100);
               if(digitalRead(sw2)==0)
               {toggle_sw2 = !toggle_sw2;
                 if(toggle_sw2)data = "sw2on";else data = "sw2off";
                 data.toCharArray(msg, (data.length() + 1));
                 client.publish(vtopic, msg);
                 while(digitalRead(sw2)==0);
               }
           }
   

   
  
      
    }

  
