* ESP-NOW experiment with terminal-chat

This commit is contained in:
Scott Powell 2025-03-24 21:16:00 +11:00
parent f33e1b22b3
commit 7bd7bfb14a
6 changed files with 182 additions and 0 deletions

View file

@ -7,9 +7,12 @@
#include <SPIFFS.h>
#endif
#ifdef WRAPPER_CLASS
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <helpers/RadioLibWrappers.h>
#endif
#include <helpers/ArduinoHelpers.h>
#include <helpers/StaticPoolPacketManager.h>
#include <helpers/SimpleMeshTables.h>
@ -263,7 +266,11 @@ protected:
public:
#ifdef WRAPPER_CLASS
MyMesh(RadioLibWrapper& radio, mesh::RNG& rng, mesh::RTCClock& rtc, SimpleMeshTables& tables)
#else
MyMesh(mesh::Radio& radio, mesh::RNG& rng, mesh::RTCClock& rtc, SimpleMeshTables& tables)
#endif
: BaseChatMesh(radio, *new ArduinoMillis(), rng, rtc, *new StaticPoolPacketManager(16), tables)
{
// defaults
@ -325,6 +332,8 @@ public:
Serial.println("===== MeshCore Chat Terminal =====");
Serial.println();
Serial.printf("WELCOME %s\n", _prefs.node_name);
mesh::Utils::printHex(Serial, self_id.pub_key, PUB_KEY_SIZE);
Serial.println();
Serial.println(" (enter 'help' for basic commands)");
Serial.println();
}
@ -513,7 +522,12 @@ public:
StdRNG fast_rng;
SimpleMeshTables tables;
#ifdef WRAPPER_CLASS
MyMesh the_mesh(*new WRAPPER_CLASS(radio, board), fast_rng, *new VolatileRTCClock(), tables);
#else
MyMesh the_mesh(radio, fast_rng, *new VolatileRTCClock(), tables);
#endif
void halt() {
while (1) ;
@ -526,7 +540,11 @@ void setup() {
if (!radio_init()) { halt(); }
#ifdef WRAPPER_CLASS
fast_rng.begin(radio.random(0x7FFFFFFF));
#else
fast_rng.begin(rand());
#endif
#if defined(NRF52_PLATFORM)
InternalFS.begin();
@ -538,12 +556,14 @@ void setup() {
#error "need to define filesystem"
#endif
#ifdef WRAPPER_CLASS
if (LORA_FREQ != the_mesh.getFreqPref()) {
radio.setFrequency(the_mesh.getFreqPref());
}
if (LORA_TX_POWER != the_mesh.getTxPowerPref()) {
radio.setOutputPower(the_mesh.getTxPowerPref());
}
#endif
the_mesh.showWelcome();

View file

@ -0,0 +1,83 @@
#include "ESPNOWRadio.h"
#include <esp_now.h>
#include <WiFi.h>
static uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
static esp_now_peer_info_t peerInfo;
static bool is_send_complete = false;
static esp_err_t last_send_result;
static uint8_t rx_buf[256];
static uint8_t last_rx_len = 0;
// callback when data is sent
static void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
is_send_complete = true;
ESPNOW_DEBUG_PRINTLN("Send Status: %d", (int)status);
}
static void OnDataRecv(const uint8_t *mac, const uint8_t *data, int len) {
ESPNOW_DEBUG_PRINTLN("Recv: len = %d", len);
memcpy(rx_buf, data, len);
last_rx_len = len;
}
void ESPNOWRadio::begin() {
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
ESPNOW_DEBUG_PRINTLN("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
esp_now_register_recv_cb(OnDataRecv);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) == ESP_OK) {
ESPNOW_DEBUG_PRINTLN("init success");
} else {
// ESPNOW_DEBUG_PRINTLN("Failed to add peer");
}
}
void ESPNOWRadio::startSendRaw(const uint8_t* bytes, int len) {
// Send message via ESP-NOW
is_send_complete = false;
esp_err_t result = esp_now_send(broadcastAddress, bytes, len);
if (result == ESP_OK) {
ESPNOW_DEBUG_PRINTLN("Send success");
} else {
last_send_result = result;
is_send_complete = true;
ESPNOW_DEBUG_PRINTLN("Send failed: %d", result);
}
}
bool ESPNOWRadio::isSendComplete() {
return is_send_complete;
}
void ESPNOWRadio::onSendFinished() {
}
float ESPNOWRadio::getLastRSSI() const { return 0; }
float ESPNOWRadio::getLastSNR() const { return 0; }
int ESPNOWRadio::recvRaw(uint8_t* bytes, int sz) {
int len = last_rx_len;
if (last_rx_len > 0) {
memcpy(bytes, rx_buf, last_rx_len);
last_rx_len = 0;
}
return len;
}
uint32_t ESPNOWRadio::getEstAirtimeFor(int len_bytes) {
return 100; // TODO
}

View file

@ -0,0 +1,34 @@
#pragma once
#include <Mesh.h>
class ESPNOWRadio : public mesh::Radio {
protected:
uint32_t n_recv, n_sent;
public:
ESPNOWRadio() { n_recv = n_sent = 0; }
void begin() override;
int recvRaw(uint8_t* bytes, int sz) override;
uint32_t getEstAirtimeFor(int len_bytes) override;
void startSendRaw(const uint8_t* bytes, int len) override;
bool isSendComplete() override;
void onSendFinished() override;
uint32_t getPacketsRecv() const { return n_recv; }
uint32_t getPacketsSent() const { return n_sent; }
virtual float getLastRSSI() const override;
virtual float getLastSNR() const override;
float packetScore(float snr, int packet_len) override { return 0; }
};
#if ESPNOW_DEBUG_LOGGING && ARDUINO
#include <Arduino.h>
#define ESPNOW_DEBUG_PRINT(F, ...) Serial.printf("ESP-Now: " F, ##__VA_ARGS__)
#define ESPNOW_DEBUG_PRINTLN(F, ...) Serial.printf("ESP-Now: " F "\n", ##__VA_ARGS__)
#else
#define ESPNOW_DEBUG_PRINT(...) {}
#define ESPNOW_DEBUG_PRINTLN(...) {}
#endif

View file

@ -0,0 +1,25 @@
; ----------- Generic ESP32-C3 ------------
[env:Generic_C3_ESPNOW_terminal_chat]
extends = esp32_base
;board = esp32-c3-devkitm-1
board = esp32-s3-devkitc-1
build_flags =
${esp32_base.build_flags}
-I variants/espnow_c3
-D MAX_CONTACTS=100
-D MAX_GROUP_CHANNELS=1
-D ESPNOW_DEBUG_LOGGING=1
; -D P_LORA_TX_LED=8
-D P_LORA_TX_LED=35
-D PIN_USER_BTN=0
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${esp32_base.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
+<helpers/esp32/ESPNowRadio.cpp>
+<../variants/espnow_c3>
lib_deps =
${esp32_base.lib_deps}
densaugeo/base64 @ ~1.4.0

View file

@ -0,0 +1,11 @@
#include <Arduino.h>
#include "target.h"
ESP32Board board;
ESPNOWRadio radio;
bool radio_init() {
radio.begin();
return true; // success
}

View file

@ -0,0 +1,9 @@
#pragma once
#include <helpers/ESP32Board.h>
#include <helpers/esp32/ESPNOWRadio.h>
extern ESP32Board board;
extern ESPNOWRadio radio;
bool radio_init();