#include <HardwareSerial.h>
#include <esp_now.h>
#include <WiFi.h>
#include <esp_wifi.h>
#define led1 25
#define WIFI_CHANNEL 11 //... wifi connect gatway
#define sw1 16
#define sw2 4
#define led_status 2
String led01,led02,dir00,pwm_duty,node_id;
String status_send; 
int led01x,led02x,dirx;
int pwm_dutyx;
int node_idx;
int myInt; //= textStr.toInt(); 
int status_loop=0;
//void send_data(int idx);

uint8_t Address_node1[] = {0x00,0x70,0x07,0xa3,0x78,0x78};
uint8_t Address_node2[] = {0x88,0x57,0x21,0xc2,0xc0,0xb4};
uint8_t Address_node3[] = {0x8c,0x94,0xdf,0x61,0xda,0x04};
uint8_t Address_node4[] = {0x88,0x57,0x21,0xb1,0x28,0x2c};
uint8_t Address_node5[] = {0x58,0x2a,0xbd,0x7d,0xbd,0xbc};


// 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.");
  if (status == ESP_NOW_SEND_SUCCESS)
  {
    status_send="Send successfully.";
  }
  else
  {
    status_send="Send failed.";
  }
  status_sender();
}

// 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));
  Serial.print("---I received the information: ");
  Serial.print(incomingData.text);
  
  Serial.print("pwm_duty: ");
  Serial.println(incomingData.pwm_duty);myData.pwm_duty=incomingData.pwm_duty;
  
  Serial.print(" id :");
  Serial.println(incomingData.id);
  
  Serial.print(" in1: ");
  Serial.print(incomingData.in1);myData.in1=incomingData.in1;
  Serial.print(" in2: ");
  Serial.print(incomingData.in2);myData.in2=incomingData.in2;

  Serial.print(" out1: ");
  Serial.print(incomingData.out1);myData.out1=incomingData.out1;
  Serial.print(" out2: ");
  Serial.print(incomingData.out2);myData.out2=incomingData.out2;


  send_data(incomingData.id); 
}
 
void setup() {
  WiFi.mode(WIFI_STA);
  esp_wifi_set_channel(WIFI_CHANNEL, WIFI_SECOND_CHAN_NONE);
  pinMode(led1, OUTPUT);
  pinMode(led_status, OUTPUT);
  pinMode(sw1, INPUT_PULLUP);
  pinMode(sw2, INPUT_PULLUP); 
  //------------------serial2 communication with nextion display-----
  Serial2.begin(9600, SERIAL_8N1, 19, 21);
  
  int a=0;
  while(a<10)
  {
     digitalWrite(led1, !digitalRead(led1));
     delay(1000);a++;
  }
digitalWrite(led1,LOW);
	
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);

  // Getting Started with ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW startup failed.");
    return;
  }
//-----------------------------------------------------------------
  //Register receiver 1.
  esp_now_peer_info_t peerInfo1 = {};
  memcpy(peerInfo1.peer_addr, Address_node1, 6);
  peerInfo1.channel = WIFI_CHANNEL;  
  peerInfo1.encrypt = false;
 

  if (esp_now_add_peer(&peerInfo1) != ESP_OK){
    Serial.println("Adding a peerInfo1 failed.");
    return;
  }
//----------------------------------------------------------
  //Register receiver 2.
  esp_now_peer_info_t peerInfo2 = {};
  memcpy(peerInfo2.peer_addr, Address_node2, 6);
  peerInfo2.channel = WIFI_CHANNEL;
  peerInfo2.encrypt = false;

  if (esp_now_add_peer(&peerInfo2) != ESP_OK){
    Serial.println("Adding a peerInfo2 failed.");
    return;
  }  
//----------------------------------------------------------
  //Register receiver 3.
  esp_now_peer_info_t peerInfo3 = {};
  memcpy(peerInfo3.peer_addr, Address_node3, 6);
  peerInfo3.channel = WIFI_CHANNEL;
  peerInfo3.encrypt = false;

  if (esp_now_add_peer(&peerInfo3) != ESP_OK){
    Serial.println("Adding a peerInfo3 failed.");
    return;
  }
 //------------------------------------------------------------
  //Register receiver 4.
  esp_now_peer_info_t peerInfo4 = {};
  memcpy(peerInfo4.peer_addr, Address_node4, 6);
  peerInfo4.channel = WIFI_CHANNEL;
  peerInfo4.encrypt = false;

  if (esp_now_add_peer(&peerInfo4) != ESP_OK){
    Serial.println("Adding a peerInfo4 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() {status_loop++;
	//----------------- command from nextion display-------------

  if (Serial2.available() > 0) {
    // Read the serial buffer up to our 0x0A (\n) newline delimiter
    String receivedString = Serial2.readStringUntil('\n');
    
    // Trim accidental carriage returns or whitespace
    receivedString.trim(); 
   
    // Print the message to the Arduino Serial Monitor
    Serial.print("Received from Nextion: "); 
    Serial.println(receivedString);
    
    led01 = receivedString.substring(3, 0); 
    led02 = receivedString.substring(6, 3);
    dir00 = receivedString.substring(9, 6);
    pwm_duty = receivedString.substring(12, 9);
    node_id = receivedString.substring(15, 12);

    led01x = led01.toInt(); 
    led02x = led02.toInt(); 
    dirx = dir00.toInt();
    pwm_dutyx = pwm_duty.toInt(); 
    node_idx = node_id.toInt(); 
//-------------------------------- DEBUG DATA RECEIVE -------------------------------
    Serial.print("led01x =    ");Serial.print(led01x);Serial.println();
    Serial.print("led02x =    ");Serial.print(led02x);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    =  led01x;
      myData.out2    =  led02x;   
      myData.in1     =  dirx;
      myData.pwm_duty=  pwm_dutyx; 
      myData.id      =  node_idx;  

      send_data(myData.id);
  }





    
if(status_loop>95000){digitalWrite(led_status, !digitalRead(led_status));status_loop=0;}	
}

void send_data(int idx)
{
    

//-------------------- select node send -------------

         if(idx==1)
         {
            esp_err_t result = esp_now_send(Address_node1, (uint8_t *) &myData, sizeof(myData));
            if (result != ESP_OK) {
            Serial.println("An error occurred during data transmission.");}     
         }
         else if(idx==2)  
         {
            esp_err_t result = esp_now_send(Address_node2, (uint8_t *) &myData, sizeof(myData));
            if (result != ESP_OK) {
            Serial.println("An error occurred during data transmission."); }   
         }
         else if(idx==3)  
         {
            esp_err_t result = esp_now_send(Address_node3, (uint8_t *) &myData, sizeof(myData));
            if (result != ESP_OK) {
            Serial.println("An error occurred during data transmission."); }   
         }
         else if(idx==4)  
         {
            esp_err_t result = esp_now_send(Address_node4, (uint8_t *) &myData, sizeof(myData));
            if (result != ESP_OK) {
            Serial.println("An error occurred during data transmission."); }   
         }
          else if(idx==5)  
         {
            esp_err_t result = esp_now_send(0, (uint8_t *) &myData, sizeof(myData));
            if (result != ESP_OK) {
            Serial.println("An error occurred during data transmission."); }   
         }                          
         else
         {
         }  


}

void status_sender(void)
{

  Serial2.print("t6.txt=\""); // เริ่มด้วยชื่อวัตถุ และเครื่องหมาย "
  Serial2.print(status_send);      // ใส่ตัวแปรข้อความ
  Serial2.print("\"");         
  //------------sendNextionEnd----------
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  Serial2.write(0xFF);
  
}
