Page 1 of 1

espNOW changing peer mac address.

Posted: Tue Feb 16, 2021 4:37 pm
by sebasdt
hi all!

I have been searching for a while for an answer to my question.
so my question is:
is there a way to change the MAC address of the peer the sender is sending to?
let me explain why I want this and maybe this will clarify my question.

I have code that reads a string (in mine case a mac address) from serial monitor and copies that into EEPROM.
when the esp32 reboots retrieve this mac address from EEPROM and store it in broadcastAddress. so the esp32 could later send to that mac address. this and all works without any issue.

i use esp_now_add_peer() to add the peer when a New MAC address is received and verified.
here is the real question does the old MAC address get replaced? or is it still stored?
is there a function like: esp_now_change_peer_mac()?


Code: Select all

#include <esp_now.h>
#include <WiFi.h>
#include <EEPROM.h>

const byte numChars = 32;
char receivedChars[numChars];
boolean newData = false;

esp_now_peer_info_t peerInfo;
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};//<B4:E6:2D:FB:21:31> an example Mac address for testing.

void sendData(uint8_t data);

// callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.print("Last Packet Send Status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}

void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
  delay(3000); // wait for a bit

  if (!EEPROM.begin(18)) {
    Serial.println("failed to initialise EEPROM");
    delay(1000000);
  }

  Serial.print("updated broadcastAddress from EEPROM: ");
  EEPROM.get(0, broadcastAddress);//Update the mac address from EEPROM
  for (byte cnt = 0; cnt < sizeof(broadcastAddress); cnt++)
  {
    Serial.print(broadcastAddress[cnt], HEX);
    Serial.print(" ");
  }
  Serial.println();


  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  } else Serial.println("Succesfully initializing ESP-NOW");

  // Once ESPNow is successfully Init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);

  // Register peer
  memcpy(peerInfo.peer_addr, broadcastAddress, 6);
  peerInfo.channel = 0;
  peerInfo.encrypt = true;

  // Add peer and test if the peer is active if so WE ARE IN BUSINESS
  if (esp_now_add_peer(&peerInfo) != ESP_OK) {
    Serial.println("Failed to add peer");
    return;
  }
   Serial.print("Sending a test... ");
   sendData(random(0,255));
}

void loop() {
  
  recvWithStartEndMarkers(); //look for when a new message is recieved
  if (newData == true){
    bool rv = newMacToBroadcastAddress();// is the newly received message a MAC address? if so do some tests to see if the Recieved mac is valid. if so store it in eeprom and add a new peer.
    if (rv == false){
      Serial.println("An error occured while processing the received MAC address");
    }
    else{
      Serial.print("updated broadcastAddress from EEPROM: ");
      EEPROM.get(0, broadcastAddress);
      for (byte cnt = 0; cnt < sizeof(broadcastAddress); cnt++){
        Serial.print(broadcastAddress[cnt], HEX);
        Serial.print(" ");
      }
      Serial.println();

      memcpy(peerInfo.peer_addr, broadcastAddress, 6);
      // // Add peer and test if the peer is active if so WE ARE IN BUSINESS
      if (esp_now_add_peer(&peerInfo) != ESP_OK) {
        Serial.println("Failed to add peer");return;
      } else{ Serial.println("Added a ESPNow peer"); sendData(random(0,255));}
    }
  }
}


void sendData(uint8_t data) {
  esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &data, sizeof(data));
  if (result == ESP_OK) {
    Serial.println("Sent with success");
  }
  else {
    Serial.println("Error sending the data");
  }
}


void recvWithStartEndMarkers()
{
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (Serial.available() > 0 && newData == false) {
    rc = Serial.read();
    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars) {
          ndx = numChars - 1;
        }
      }
      else {
        receivedChars[ndx] = '\0'; // terminate the string
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

/*
  function: Process received mac address and store in EEPROM
  Returns: true on success else false
*/
bool newMacToBroadcastAddress()
{
  // array to store received and converted MAC address before saving to EEPROM
  byte eepromMac[sizeof(broadcastAddress)];
  // index where to write next byte in eepromMac array
  byte idx = 0;

  // tokeniser and converter
  char *token;
  char *ptr;
  const char s[2] = ":";

  if (newData == true) {
    newData = false;

    Serial.print("I received this: '");
    Serial.print(receivedChars);
    Serial.println("'");

    // check the length
    if (strlen(receivedChars) != 17) {
      Serial.println("Expected 17 characters for MAC address");
      return false;
    }

    /* parse data */
    token = strtok(receivedChars, s);
    while ( token != NULL ){
      Serial.print("Token: '");
      Serial.print(token);
      Serial.println("'");

      // check if there were more MAC bytes than needed; basically redundant
      if (idx >= sizeof(broadcastAddress)) {
        Serial.println("Too many tokens");
        return false;
      }

      // token should be 2 bytes
      if (strlen(token) != 2) {
        Serial.println("Expected 2 characters for Mac byte, are there '-' or ' ' placed? instead please use ':'");
        return false;
      }

      // check if values in token are hexadecimal
      for (byte cnt = 0; cnt < strlen(token); cnt++) {
        if (isHexadecimalDigit(token[cnt]) == false) {
          Serial.println("Expected a hexadecimal Mac byte");
          return false;
        }
      }

      // convert token
      byte b = strtoul(token, &ptr, 16);

      // the two tests below are basically redundant but demonstrate how ptr can be used to check the result of the conversion
      if (ptr == token) {
        Serial.println("Expected a hexadecimal Mac byte");
        return false;
      }
      if (*ptr != '\0') {
        Serial.println("Still characters available");
        return false;
      }

      eepromMac[idx] = b;
      Serial.print(idx); Serial.print(" > ");
      Serial.println(b, HEX);
      idx++;

      token = strtok(NULL, s);
    }

    Serial.println("writing to EEPROM ");
    EEPROM.put(0, eepromMac);
    EEPROM.commit();
    delay(100);

  }

  return true;
}