Using ESP-NOW for bi-directional communication between esp32's
Posted: Mon Jan 29, 2024 9:23 pm
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
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
- #include <esp_now.h>
- #include <WiFi.h>
- // Device data object
- typedef struct {
- uint8_t device_mac_address[6]; // mac address of device
- int device_type; // 0 = smart flusher, etc.
- } device_data;
- device_data device_info; // local storage of paired device
- // Hub data object
- typedef struct {
- uint8_t hub_mac_address[6]; // mac address of hub
- } hub_data;
- hub_data hub_info; // local storage of hub data
- // Device pairing flags
- bool pairedFlag = false;
- bool sentAck = false;
- // Handler for when data received using esp-now
- void on_data_received(const uint8_t * mac, const uint8_t *incomingData, int len) {
- if(pairedFlag == false){
- // copy received device data to local
- memcpy(&device_info, incomingData, sizeof(device_info));
- // set as paired
- pairedFlag = true;
- Serial.println("Paired device " + String(device_info.device_type) + " with ");
- for(int i = 0; i < 6; i++){
- Serial.print(device_info.device_mac_address[i], HEX);
- }
- Serial.println();
- // get hub mac address
- esp_read_mac(hub_info.hub_mac_address, ESP_MAC_WIFI_STA);
- // send paired acknowledgement back to device
- if(pairedFlag == true && sentAck == false){
- esp_now_send(device_info.device_mac_address, (uint8_t *) &hub_info, sizeof(hub_info));
- sentAck = true;
- }
- }
- }
- // Handler for when data sent using esp-now
- void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
- Serial.print("\r\nLast Packet Send Status:\t");
- Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
- }
- void setup() {
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
- if (esp_now_init() != ESP_OK) {
- Serial.println("Error initializing ESP-NOW");
- return;
- }
- // call handler when data received
- esp_now_register_recv_cb(on_data_received);
- // call handler when data sent
- esp_now_register_send_cb(on_data_sent);
- Serial.println(WiFi.macAddress());
- }
- void loop() {
- }
- [/code]
- [b]EndDevice.ino[/b]
- [Codebox=cpp file=Untitled.cpp]
- #include <esp_now.h>
- #include <WiFi.h>
- // Device data object
- typedef struct {
- uint8_t device_mac_address[6]; // mac address of device
- int device_type; // 0 = smart flusher, etc.
- } device_data;
- device_data device_info; // local storage of paired device
- // Hub data object
- typedef struct {
- uint8_t hub_mac_address[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};; // mac address of hub
- } hub_data;
- hub_data hub_info; // local storage of hub data
- // Device pairing flags
- bool pairedFlag = false;
- esp_now_peer_info_t peerInfo;
- // Handler for when data sent using esp-now
- void on_data_sent(const uint8_t *mac_addr, esp_now_send_status_t status) {
- Serial.print("\r\nLast Packet Send Status:\t");
- Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
- }
- // Handler for when data received using esp-now
- void on_data_received(const uint8_t * mac, const uint8_t *incomingData, int len) {
- if(pairedFlag == false){
- // copy received device data to local
- memcpy(&hub_info, incomingData, sizeof(hub_info));
- // set as paired
- pairedFlag = true;
- Serial.println("Paired to hub");
- }
- }
- void setup() {
- Serial.begin(115200);
- WiFi.mode(WIFI_STA);
- if (esp_now_init() != ESP_OK) {
- Serial.println("Error initializing ESP-NOW");
- return;
- }
- // register peer
- memcpy(peerInfo.peer_addr, hub_info.hub_mac_address, 6);
- peerInfo.channel = 0;
- peerInfo.encrypt = false;
- // add peer
- if (esp_now_add_peer(&peerInfo) != ESP_OK){
- Serial.println("Failed to add peer");
- return;
- }
- // set device mac address and type
- esp_read_mac(device_info.device_mac_address, ESP_MAC_WIFI_STA);
- device_info.device_type = 0;
- // call function on data send
- esp_now_register_send_cb(on_data_sent);
- // call function on data receive
- esp_now_register_recv_cb(on_data_received);
- Serial.println(WiFi.macAddress());
- }
- void loop() {
- // run pair sequence if not paired
- if(pairedFlag == false){
- // send data to pair to hub
- esp_now_send(hub_info.hub_mac_address, (uint8_t *) &device_info, sizeof(device_info));
- }
- }