|
|
|
@ -3,12 +3,27 @@ |
|
|
|
#include <WiFi.h> |
|
|
|
#include <esp_wifi.h> |
|
|
|
|
|
|
|
static constexpr uint16_t BRIDGE_PACKET_MAGIC = 0xC03E; |
|
|
|
static const size_t MAX_ESPNOW_PACKET_SIZE = 250; |
|
|
|
/**
|
|
|
|
* @brief Common field sizes used by bridge implementations |
|
|
|
* |
|
|
|
* These constants define the size of common packet fields used across bridges. |
|
|
|
* BRIDGE_MAGIC_SIZE is used by all bridges for packet identification. |
|
|
|
* BRIDGE_LENGTH_SIZE is used by bridges that need explicit length fields (like RS232). |
|
|
|
* BRIDGE_CHECKSUM_SIZE is used by all bridges for Fletcher-16 checksums. |
|
|
|
*/ |
|
|
|
static constexpr uint16_t BRIDGE_MAGIC_SIZE = sizeof(BRIDGE_PACKET_MAGIC); |
|
|
|
static constexpr uint16_t BRIDGE_LENGTH_SIZE = sizeof(uint16_t); |
|
|
|
static constexpr uint16_t BRIDGE_CHECKSUM_SIZE = sizeof(uint16_t); |
|
|
|
|
|
|
|
static uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; |
|
|
|
static esp_now_peer_info_t peerInfo; |
|
|
|
static volatile 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; |
|
|
|
static char bridge_secret[16]; |
|
|
|
|
|
|
|
// callback when data is sent
|
|
|
|
static void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { |
|
|
|
@ -16,15 +31,56 @@ static void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { |
|
|
|
ESPNOW_DEBUG_PRINTLN("Send Status: %d", (int)status); |
|
|
|
} |
|
|
|
|
|
|
|
static void xorCrypt(uint8_t *data, size_t len) { |
|
|
|
size_t keyLen = strlen(bridge_secret); |
|
|
|
for (size_t i = 0; i < len; i++) { |
|
|
|
data[i] ^= bridge_secret[i % keyLen]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
static uint16_t fletcher16(const uint8_t *data, size_t len) { |
|
|
|
uint8_t sum1 = 0, sum2 = 0; |
|
|
|
|
|
|
|
for (size_t i = 0; i < len; i++) { |
|
|
|
sum1 = (sum1 + data[i]) % 255; |
|
|
|
sum2 = (sum2 + sum1) % 255; |
|
|
|
} |
|
|
|
|
|
|
|
return (sum2 << 8) | sum1; |
|
|
|
} |
|
|
|
|
|
|
|
static bool validateChecksum(const uint8_t *data, size_t len, uint16_t received_checksum) { |
|
|
|
uint16_t calculated_checksum = fletcher16(data, len); |
|
|
|
return received_checksum == calculated_checksum; |
|
|
|
} |
|
|
|
|
|
|
|
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; |
|
|
|
|
|
|
|
if (len < 4) return; |
|
|
|
|
|
|
|
uint16_t magic = (data[0] << 8) | data[1]; |
|
|
|
if (magic != BRIDGE_PACKET_MAGIC) return; |
|
|
|
|
|
|
|
uint8_t decrypted[MAX_ESPNOW_PACKET_SIZE]; |
|
|
|
int encLen = len - 2; // everything except magic
|
|
|
|
memcpy(decrypted, data + 2, encLen); |
|
|
|
xorCrypt(decrypted, encLen); |
|
|
|
|
|
|
|
uint16_t rx_cksum = (decrypted[0] << 8) | decrypted[1]; |
|
|
|
uint8_t* meshPayload = decrypted + 2; |
|
|
|
int meshLen = encLen - 2; |
|
|
|
|
|
|
|
if (!validateChecksum(meshPayload, meshLen, rx_cksum)) return; |
|
|
|
|
|
|
|
memcpy(rx_buf, meshPayload, meshLen); |
|
|
|
last_rx_len = meshLen; |
|
|
|
} |
|
|
|
|
|
|
|
void ESPNOWRadio::init() { |
|
|
|
// Set device as a Wi-Fi Station
|
|
|
|
WiFi.mode(WIFI_STA); |
|
|
|
strncpy(bridge_secret, "LVSITANOS", sizeof(bridge_secret)); |
|
|
|
// Long Range mode
|
|
|
|
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_LR); |
|
|
|
|
|
|
|
@ -72,7 +128,36 @@ uint32_t ESPNOWRadio::intID() { |
|
|
|
bool 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 (!bytes || len <= 0) { |
|
|
|
Serial.println("Invalid raw mesh packet"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if (len > (MAX_ESPNOW_PACKET_SIZE - 4)) { |
|
|
|
Serial.println("Mesh packet too large for ESP-NOW"); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
uint8_t out[MAX_ESPNOW_PACKET_SIZE]; |
|
|
|
|
|
|
|
// 1) magic
|
|
|
|
out[0] = (BRIDGE_PACKET_MAGIC >> 8) & 0xFF; |
|
|
|
out[1] = BRIDGE_PACKET_MAGIC & 0xFF; |
|
|
|
|
|
|
|
// 2) checksum (πάνω στο raw mesh packet)
|
|
|
|
uint16_t cksum = fletcher16(bytes, len); |
|
|
|
out[2] = (cksum >> 8) & 0xFF; |
|
|
|
out[3] = cksum & 0xFF; |
|
|
|
|
|
|
|
// 3) payload = raw mesh packet
|
|
|
|
memcpy(out + 4, bytes, len); |
|
|
|
|
|
|
|
// 4) encrypt checksum + payload
|
|
|
|
xorCrypt(out + 2, len + 2); |
|
|
|
|
|
|
|
// 5) send via ESP-NOW
|
|
|
|
esp_err_t result = esp_now_send(broadcastAddress, out, len + 4); |
|
|
|
|
|
|
|
if (result == ESP_OK) { |
|
|
|
n_sent++; |
|
|
|
ESPNOW_DEBUG_PRINTLN("Send success"); |
|
|
|
|