Page 1 of 1

Using ESP-NOW for bi-directional communication between esp32's

Posted: Mon Jan 29, 2024 9:23 pm
by keshavshankar
I am trying to make a smart home system where I use 1 esp32 as a hub module and many other esp32s as end devices that connect to the hub. I also want to use ESP-NOW for low-power bi-directional communication, since many end devices will be low-power sensors that should last up to a few months on a battery.

The functionality I'm looking for on startup is that when my hub is powered on, it handles existing connected device signals, but also scans for new devices trying to pair. Once an end device is turned on, it goes into pairing mode if a button is long pressed, but if it is paired already and not pressed, it will just wait for directions from the hub. In this pairing mode, the end device should send a signal with its MAC address to the hub, and the hub should read and save this end device into its memory using its MAC address. From there, the hub should send acknowledgment back to the end device with its MAC address, which is then stored in the end device's memory. This acts as a handshake connection.

The issue I am having with this process is that to do the peer connection process, the end device is required to know the hub's MAC address, but I want this process to be dynamic, since in a large-scale setting, I want to be able to get any manufactured end device and any hub and pair them together. I'm also unsure exactly how the peer connection and using channels works in ESP-NOW.

Below are the code files for the Hub and End device I have right now which only seems to send the signal from the end-device to the hub, but the hub does not respond back). Any help or resources you can point me to would be greatly appreciated!

Hub.ino
  1. #include <esp_now.h>
  2. #include <WiFi.h>
  3.  
  4. // Device data object
  5. typedef struct {
  6.   uint8_t device_mac_address[6]; // mac address of device
  7.   int device_type; // 0 = smart flusher, etc.
  8. } device_data;
  9. device_data device_info; // local storage of paired device
  10.  
  11. // Hub data object
  12. typedef struct {
  13.   uint8_t hub_mac_address[6]; // mac address of hub
  14. } hub_data;
  15. hub_data hub_info; // local storage of hub data
  16.  
  17. // Device pairing flags
  18. bool pairedFlag = false;
  19. bool sentAck = false;
  20.  
  21. // Handler for when data received using esp-now
  22. void on_data_received(const uint8_t * mac, const uint8_t *incomingData, int len) {
  23.   if(pairedFlag == false){
  24.     // copy received device data to local
  25.     memcpy(&device_info, incomingData, sizeof(device_info));
  26.  
  27.     // set as paired
  28.     pairedFlag = true;
  29.     Serial.println("Paired device " + String(device_info.device_type) + " with ");
  30.     for(int i = 0; i < 6; i++){
  31.       Serial.print(device_info.device_mac_address[i], HEX);
  32.     }
  33.     Serial.println();
  34.  
  35.     // get hub mac address
  36.     esp_read_mac(hub_info.hub_mac_address, ESP_MAC_WIFI_STA);
  37.    
  38.     // send paired acknowledgement back to device
  39.     if(pairedFlag == true  && sentAck == false){
  40.       esp_now_send(device_info.device_mac_address, (uint8_t *) &hub_info, sizeof(hub_info));
  41.       sentAck = true;
  42.     }
  43.   }
  44. }
  45.  
  46. // Handler for when data sent using esp-now
  47. void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  48.   Serial.print("\r\nLast Packet Send Status:\t");
  49.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  50. }
  51.  
  52. void setup() {
  53.   Serial.begin(115200);
  54.   WiFi.mode(WIFI_STA);
  55.  
  56.   if (esp_now_init() != ESP_OK) {
  57.     Serial.println("Error initializing ESP-NOW");
  58.     return;
  59.   }
  60.  
  61.   // call handler when data received
  62.   esp_now_register_recv_cb(on_data_received);
  63.  
  64.   // call handler when data sent
  65.   esp_now_register_send_cb(on_data_sent);
  66.  
  67.   Serial.println(WiFi.macAddress());
  68. }
  69.  
  70. void loop() {
  71. }
  72. [/code]
  73.  
  74. [b]EndDevice.ino[/b]
  75. [Codebox=cpp file=Untitled.cpp]
  76. #include <esp_now.h>
  77. #include <WiFi.h>
  78.  
  79. // Device data object
  80. typedef struct {
  81.   uint8_t device_mac_address[6]; // mac address of device
  82.   int device_type; // 0 = smart flusher, etc.
  83. } device_data;
  84. device_data device_info; // local storage of paired device
  85.  
  86. // Hub data object
  87. typedef struct {
  88.   uint8_t hub_mac_address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};; // mac address of hub
  89. } hub_data;
  90. hub_data hub_info; // local storage of hub data
  91.  
  92. // Device pairing flags
  93. bool pairedFlag = false;
  94.  
  95. esp_now_peer_info_t peerInfo;
  96.  
  97. // Handler for when data sent using esp-now
  98. void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  99.   Serial.print("\r\nLast Packet Send Status:\t");
  100.   Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
  101. }
  102.  
  103. // Handler for when data received using esp-now
  104. void on_data_received(const uint8_t * mac, const uint8_t *incomingData, int len) {
  105.   if(pairedFlag == false){
  106.     // copy received device data to local
  107.     memcpy(&hub_info, incomingData, sizeof(hub_info));
  108.    
  109.     // set as paired
  110.     pairedFlag = true;
  111.     Serial.println("Paired to hub");
  112.   }
  113. }
  114.  
  115. void setup() {
  116.   Serial.begin(115200);
  117.   WiFi.mode(WIFI_STA);
  118.  
  119.   if (esp_now_init() != ESP_OK) {
  120.     Serial.println("Error initializing ESP-NOW");
  121.     return;
  122.   }
  123.  
  124.   // register peer
  125.   memcpy(peerInfo.peer_addr, hub_info.hub_mac_address, 6);
  126.   peerInfo.channel = 0;  
  127.   peerInfo.encrypt = false;
  128.  
  129.   // add peer        
  130.   if (esp_now_add_peer(&peerInfo) != ESP_OK){
  131.     Serial.println("Failed to add peer");
  132.     return;
  133.   }
  134.  
  135.   // set device mac address and type
  136.   esp_read_mac(device_info.device_mac_address, ESP_MAC_WIFI_STA);
  137.   device_info.device_type = 0;
  138.  
  139.   // call function on data send
  140.   esp_now_register_send_cb(on_data_sent);
  141.  
  142.   // call function on data receive
  143.   esp_now_register_recv_cb(on_data_received);
  144.  
  145.   Serial.println(WiFi.macAddress());
  146. }
  147.  
  148. void loop() {
  149.   // run pair sequence if not paired
  150.   if(pairedFlag == false){
  151.     // send data to pair to hub
  152.     esp_now_send(hub_info.hub_mac_address, (uint8_t *) &device_info, sizeof(device_info));
  153.   }
  154. }

Re: Using ESP-NOW for bi-directional communication between esp32's

Posted: Tue Jan 30, 2024 1:10 pm
by MicroController
The issue I am having with this process is that to do the peer connection process, the end device is required to know the hub's MAC address
ESP-NOW supports sending+receiving broadcast messages, see the example.

Re: Using ESP-NOW for bi-directional communication between esp32's

Posted: Sun Feb 11, 2024 3:18 pm
by keshavshankar
From what I read, this method uses WiFi. Only my hub esp32 can access wifi, whereas I want my end device esp32 to not be connected, as this will be a low power device. I believe you should still be able to broadcast without initiating wifi on the esp32, so I will try a system where the hold of a button emits the pairing signal.