memomem

備忘録・メモ置き場

ESP-now

lang-ship.com

101010.fun

shinshu-makers.net

qiita.com

// https://lang-ship.com/blog/work/m5stickc-esp-now-1/
// https://101010.fun/iot/esp32-m5stickc-plus-esp-now.html
// https://shinshu-makers.net/shinshu_makers/2020/05/01/%E3%80%90powermeter2020%E3%80%91esp-now%E3%81%AE%E9%80%9A%E4%BF%A1%E9%80%9F%E5%BA%A6%E9%80%9F%E3%81%844msecok%E3%81%A0%E3%81%A3%E3%81%9F%EF%BC%9Cbt%E3%82%84xbee%E3%82%88%E3%82%8A%E8%89%AF%E3%81%84/
// https://qiita.com/yoroyasu/items/05aa1135c2c830708e20

/*
起動時にM5_Slaveと名前の着いたアクセスポイントを検索
見つかったデバイスへ接続し、データの送信を行う。
ボタン押しでデータ送信
ボタン長押しでアクセスポイント再スキャン
*/
#include <M5StickC.h>

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

#define CHANNEL 1

// 送信コールバック
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  char macStr[18];
  snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.print("Sent to: ");
  Serial.println(macStr);
  Serial.print("Status: ");
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");

  // 画面にも描画
  // M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 25);
  M5.Lcd.print("Sent:");
  M5.Lcd.println(macStr);
  M5.Lcd.print("Status:");
  M5.Lcd.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
// 受信コールバック
void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) {
  char macStr[18];
  snprintf(macStr, sizeof(macStr), "%02X:%02X:%02X:%02X:%02X:%02X",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.printf("Recv from: %s", macStr);
  Serial.printf("/Data(%d): ", data_len);
  for ( int i = 0 ; i < data_len ; i++ ) {
    Serial.print(data[i]);
    Serial.print(" ");
  }
  Serial.println("");
  // 画面にも描画
  // M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setCursor(0, 55);
  M5.Lcd.print("Recv from: ");
  M5.Lcd.print(macStr);
  M5.Lcd.printf("/Data(%d): ", data_len);
  for ( int i = 0 ; i < data_len ; i++ ) {
    M5.Lcd.print(data[i]);
    M5.Lcd.print(" ");
  }
}


String Prefix = "M5_Slave:";

void configDeviceAP() {
  String Mac = WiFi.macAddress();
  String SSID = Prefix + Mac;
  String Password = "123456789";
  bool result = WiFi.softAP(SSID.c_str(), Password.c_str(), CHANNEL, 0);
  if (!result) {
    Serial.println("AP Config failed.");
  } else {
    Serial.println("AP Config Success. Broadcasting with AP: " + String(SSID));
  }
}

// Global copy of slave
#define NUMSLAVES 20
esp_now_peer_info_t slaves[NUMSLAVES] = {};
int SlaveCnt = 0;
#define PRINTSCANRESULTS 1

// Scan for slaves in AP mode
// 処理に時間がかかる
void ScanForSlave() {
  int8_t scanResults = WiFi.scanNetworks();
  //reset slaves
  memset(slaves, 0, sizeof(slaves));
  SlaveCnt = 0;
  Serial.println("");
  if (scanResults == 0) {
    Serial.println("No WiFi devices in AP Mode found");
  } else {
    Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices ");
    for (int i = 0; i < scanResults; ++i) {
      // Print SSID and RSSI for each device found
      String SSID = WiFi.SSID(i);
      int32_t RSSI = WiFi.RSSI(i);
      String BSSIDstr = WiFi.BSSIDstr(i);

      if (PRINTSCANRESULTS) {
        Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
      }
      delay(10);
      // Check if the current device starts with `Slave`
      if (SSID.indexOf(Prefix) == 0) {
        // SSID of interest
        Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println("");
        // Get BSSID => Mac Address of the Slave
        int mac[6];

        if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x",  &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) {
          for (int ii = 0; ii < 6; ++ii ) {
            slaves[SlaveCnt].peer_addr[ii] = (uint8_t) mac[ii];
          }
        }
        slaves[SlaveCnt].channel = CHANNEL; // pick a channel
        slaves[SlaveCnt].encrypt = 0; // no encryption
        SlaveCnt++;
      }
    }
  }

  if (SlaveCnt > 0) {
    Serial.print(SlaveCnt); Serial.println(" Slave(s) found, processing..");
  } else {
    Serial.println("No Slave Found, trying again.");
  }

  // clean up ram
  WiFi.scanDelete();
}

// Check if the slave is already paired with the master.
// If not, pair the slave with master
void manageSlave() {
  if (SlaveCnt > 0) {
    for (int i = 0; i < SlaveCnt; i++) {
      Serial.print("Processing: ");
      for (int ii = 0; ii < 6; ++ii ) {
        Serial.print((uint8_t) slaves[i].peer_addr[ii], HEX);
        if (ii != 5) Serial.print(":");
      }
      Serial.print(" Status: ");
      // check if the peer exists
      bool exists = esp_now_is_peer_exist(slaves[i].peer_addr);
      if (exists) {
        // Slave already paired.
        // 既に接続済み
        Serial.println("Already Paired");
      } else {
        // Slave not paired, attempt pair
        // pairリングされていない時は接続を行う
        esp_err_t addStatus = esp_now_add_peer(&slaves[i]);
        if (addStatus == ESP_OK) {
          // Pair success
          Serial.println("Pair success");
        } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
          // How did we get so far!!
          Serial.println("ESPNOW Not Init");
        } else if (addStatus == ESP_ERR_ESPNOW_ARG) {
          Serial.println("Add Peer - Invalid Argument");
        } else if (addStatus == ESP_ERR_ESPNOW_FULL) {
          Serial.println("Peer list full");
        } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
          Serial.println("Out of memory");
        } else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
          Serial.println("Peer Exists");
        } else {
          Serial.println("Not sure what happened");
        }
        // delay(100);
      }
    }
  } else {
    // No slave found to process
    Serial.println("No Slave found to process");
  }
}


// 
uint8_t slaveAddress[2][6] = {{ 0xDC,0x54,0x75,0xC8,0x97,0x00 }, { 0xDA,0x52,0x75,0xC8,0x97,0x00 }};

void setup() {
  M5.begin();
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setRotation(3);
  M5.Lcd.print("ESP-NOW");

  // ESP-NOW初期化
  WiFi.mode(WIFI_STA);

  configDeviceAP();

  Serial.println(WiFi.macAddress());
  M5.Lcd.print(WiFi.macAddress());

  WiFi.disconnect();
  if (esp_now_init() == ESP_OK) {
    Serial.print(">Success");
    M5.Lcd.print(">Success");
  } else {
    Serial.print(">Failed");
    M5.Lcd.print(">Failed");
    ESP.restart();
  }

  // # Slaveをスキャンして送信
  ScanForSlave();
  manageSlave();

  // # slaveAddressで指定したデバイスへ送信
  // SlaveCnt = 0;
  // memcpy(slaves[SlaveCnt].peer_addr, slaveAddress[SlaveCnt], 6);
  // slaves[SlaveCnt].channel = CHANNEL; // pick a channel
  // slaves[SlaveCnt].encrypt = 0; // no encryption
  // SlaveCnt = 1;
  // manageSlave();

  // # broadcastまたは任意のslaveAddressへ送信
  // uint8_t slaveAddress[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };//broadcast
  // esp_now_peer_info_t slave;
  // memcpy(slave.peer_addr, slaveAddress, 6);
  // slave.channel = CHANNEL;
  // slave.encrypt = 0;
  // esp_err_t addStatus = esp_now_add_peer(&slave);
  // if (addStatus == ESP_OK) {
  //   // Pair success
  //   Serial.println(">Pair");
  //   M5.Lcd.println(">Pair");
  // }
  
  // ESP-NOWコールバック登録
  esp_now_register_send_cb(OnDataSent);
  esp_now_register_recv_cb(OnDataRecv);
}

uint8_t count = 0;

void loop() {

  M5.update();

  // ボタンを押したら送信
  if (M5.BtnA.wasPressed()) {

    if (SlaveCnt > 0) {
      // Send data to device
      sendData();
    }
  }

  if (M5.BtnA.pressedFor(1000)) {
    Serial.print("Rescan");

    ScanForSlave();
    manageSlave();
  }
  delay(1);
}

void sendData() {
  count ++;
  uint8_t data[2] = {count, 234};//送信データ

  M5.Lcd.setCursor(0, 15);
  M5.Lcd.print("Send Status: ");

  // const uint8_t *peer_addr = slave.peer_addr;

  for (int i = 0; i < SlaveCnt; i++) {
    const uint8_t *peer_addr = slaves[i].peer_addr;

    esp_err_t result = esp_now_send(peer_addr, data, sizeof(data));

    if (result == ESP_OK) {
      Serial.println("Success");
      M5.Lcd.println("Success");
    } else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
      Serial.println("ESPNOW not Init.");
      M5.Lcd.println("ESPNOW not Init.");
    } else if (result == ESP_ERR_ESPNOW_ARG) {
      Serial.println("Invalid Argument");
      M5.Lcd.println("Invalid Argument");
    } else if (result == ESP_ERR_ESPNOW_INTERNAL) {
      Serial.println("Internal Error");
      M5.Lcd.println("Internal Error");
    } else if (result == ESP_ERR_ESPNOW_NO_MEM) {
      Serial.println("ESP_ERR_ESPNOW_NO_MEM");
      M5.Lcd.println("ESP_ERR_ESPNOW_NO_MEM");
    } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
      Serial.println("Peer not found.");
      M5.Lcd.println("Peer not found.");
    } else {
      Serial.println("Not sure what happened");
      M5.Lcd.println("Not sure what happened");
    }
  }
}