From 5a6b2d4e0e34cb6d3969549c86645c19095bd729 Mon Sep 17 00:00:00 2001 From: simon Date: Sat, 28 Dec 2024 19:52:54 +0100 Subject: [PATCH] Added Reconnecting ability --- Makefile | 10 +++- main/main.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 137 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index b26cb23..21d6c39 100644 --- a/Makefile +++ b/Makefile @@ -15,10 +15,18 @@ flash1: sudo chmod o+rw /dev/ttyUSB1 idf.py flash -p /dev/ttyUSB1 +flash2: + sudo chmod o+rw /dev/ttyUSB2 + idf.py flash -p /dev/ttyUSB2 + monitor0: sudo chmod o+rw /dev/ttyUSB0 idf.py monitor -p /dev/ttyUSB0 monitor1: - sudo chmod o+rw /dev/ttyUSB0 + sudo chmod o+rw /dev/ttyUSB1 idf.py monitor -p /dev/ttyUSB1 + +monitor2: + sudo chmod o+rw /dev/ttyUSB2 + idf.py monitor -p /dev/ttyUSB2 diff --git a/main/main.c b/main/main.c index 69858bc..cb70224 100644 --- a/main/main.c +++ b/main/main.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include "main.h" @@ -28,6 +29,9 @@ #define TXD_PIN (GPIO_NUM_17) #define RXD_PIN (GPIO_NUM_16) +#define CLIENT_TIMEOUT_MS 5000 // 5 Sekunden Timeout +#define CHECK_INTERVAL_MS 1000 // Jede Sekunde überprüfen + uint8_t broadcast_address[ESP_NOW_ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; #define IS_BROADCAST_ADDR(addr) \ @@ -37,6 +41,7 @@ typedef enum { BroadCastPage, StatusPage, PingPage, + RegisterPage, } CommandPages; typedef struct { @@ -51,10 +56,15 @@ typedef struct { typedef struct { } BroadCastPayload; +typedef struct { + bool familierClient; +} RegisterPayload; + typedef union { StatusPayload status_payload; PingPayload ping_payload; BroadCastPayload broadcast_payload; + RegisterPayload register_payload; } PayloadUnion; typedef struct { @@ -74,12 +84,25 @@ typedef struct { uint8_t macAddr[ESP_NOW_ETH_ALEN]; int rssi; bool isAvailable; + TickType_t lastSuccessfullPing; } ClientInfo; -ClientInfo clients[19]; +#define MAX_CLIENTS 19 +ClientInfo clients[MAX_CLIENTS]; size_t numClients = 0; +size_t activeClients = 0; bool hasMaster = false; +// return any inactive client field for new usage +int getNextFreeClientId() { + for (int i = 0; i < numClients; i++) { + if (!clients[i].isAvailable) { + return i; + } + } + return 0; +} + void add_peer(uint8_t *macAddr) { esp_now_peer_info_t peerInfo = { .channel = @@ -93,15 +116,44 @@ void add_peer(uint8_t *macAddr) { if (result == ESP_OK) { ESP_LOGI(TAG, "Peer added: %02X:%02X:%02X:%02X:%02X:%02X", macAddr[0], macAddr[1], macAddr[2], macAddr[3], macAddr[4], macAddr[5]); - ClientInfo newClient = {}; - memcpy(newClient.macAddr, macAddr, ESP_NOW_ETH_ALEN); - newClient.isAvailable = true; - clients[numClients++] = newClient; + + if (!IS_BROADCAST_ADDR(macAddr)) { + + if (numClients >= MAX_CLIENTS) { + ESP_LOGW(TAG, "Cannot add more clients, maximum reached."); + return; + } + + ClientInfo newClient = {}; + memcpy(newClient.macAddr, macAddr, ESP_NOW_ETH_ALEN); + newClient.isAvailable = true; + newClient.lastSuccessfullPing = xTaskGetTickCount(); + clients[getNextFreeClientId()] = newClient; + ESP_LOGI(TAG, "New client added."); + } + } else if (result == ESP_ERR_ESPNOW_EXIST) { + ESP_LOGW(TAG, "Peer already exists."); + // Überprüfen, ob der Client bereits existiert + for (int i = 0; i < numClients; i++) { + if (memcmp(clients[i].macAddr, macAddr, ESP_NOW_ETH_ALEN) == 0) { + ESP_LOGI(TAG, "Client found again, welcome back!"); + clients[i].isAvailable = true; // Reaktiviere den Client + break; + } + } } else { ESP_LOGE(TAG, "Failed to add peer: %s", esp_err_to_name(result)); } } +// UNSAFE ACCROSS THREADS BUT EZ TO USE +const char *MACtoString(uint8_t *macAddr) { + static char output[18]; // 17 Zeichen + 1 für Nullterminierung + sprintf(output, "%02X:%02X:%02X:%02X:%02X:%02X", macAddr[0], macAddr[1], + macAddr[2], macAddr[3], macAddr[4], macAddr[5]); + return output; +} + BaseMessage MessageBuilder(CommandPages commandPage, PayloadUnion payload, size_t payload_size) { BaseMessage message; @@ -134,7 +186,7 @@ void master_broadcast_task(void *param) { void master_ping_task(void *param) { while (1) { - for (size_t i = 0; i < numClients; ++i) { + for (size_t i = 0; i < MAX_CLIENTS; ++i) { if (clients[i].isAvailable) { PingPayload payload = {}; payload.timestamp = esp_timer_get_time(); @@ -167,15 +219,43 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info, ESP_LOGI(TAG, "Start: %lu, End: %lu, Diff: %lu, Ping: %lu", message->payload.ping_payload.timestamp, currentTime, diff, diff / 1000); // ping in ms + + for (int i = 0; i < 20; i++) { + // Überprüfen, ob der Client existiert und die MAC-Adresse übereinstimmt + if (clients[i].isAvailable && + memcmp(clients[i].macAddr, esp_now_info->src_addr, + ESP_NOW_ETH_ALEN) == 0) { + clients[i].lastSuccessfullPing = xTaskGetTickCount(); + ESP_LOGI(TAG, "Updated client %d last ping time to %lu", i, + clients[i].lastSuccessfullPing); + break; + } + } break; case BroadCastPage: - ESP_LOGI(TAG, "WILL REGISTER NEW DEVICE"); + ESP_LOGI(TAG, "MASTER SHOULD NOT GET BROADCAST MESSAGE, is there another " + "master calling?"); + break; + case RegisterPage: + ESP_LOGI(TAG, "WILL REGISTER DEVICE"); esp_now_peer_info_t checkPeerInfo; esp_err_t checkPeer = esp_now_get_peer(esp_now_info->src_addr, &checkPeerInfo); switch (checkPeer) { case (ESP_OK): ESP_LOGI(TAG, "CLIENT BEKANNT"); + for (int i = 0; i < 20; i++) { + // client in liste wiederfinden + if (!clients[i].isAvailable && + memcmp(clients[i].macAddr, esp_now_info->src_addr, + ESP_NOW_ETH_ALEN) == 0) { + clients[i].isAvailable = true; + clients[i].lastSuccessfullPing = xTaskGetTickCount(); + ESP_LOGI(TAG, "Updated client %d last ping time to %lu", i, + clients[i].lastSuccessfullPing); + break; + } + } break; case (ESP_ERR_ESPNOW_NOT_INIT): ESP_LOGI(TAG, "Not initalised"); @@ -190,6 +270,7 @@ void master_receive_callback(const esp_now_recv_info_t *esp_now_info, default: ESP_LOGI(TAG, "Unknown Message %i", checkPeer); } + break; default: break; @@ -226,12 +307,18 @@ void client_receive_callback(const esp_now_recv_info_t *esp_now_info, ESP_LOGI(TAG, "GOT BROADCAST MESSAGE ATTEMPTING TO REGISTER TO MASTER!"); add_peer(esp_now_info->src_addr); - uint8_t data[] = "REGISTER ME DADDY"; - esp_now_send(esp_now_info->src_addr, data, strlen((const char *)data)); + replyMessage = + MessageBuilder(RegisterPage, *(PayloadUnion *)&message->payload, + sizeof(message->payload)); + ESP_ERROR_CHECK(esp_now_send(esp_now_info->src_addr, + (uint8_t *)&replyMessage, + sizeof(BaseMessage))); hasMaster = true; } } break; + case RegisterPage: + break; default: ESP_LOGI(TAG, "GOT UNKONW MESSAGE"); break; @@ -248,6 +335,37 @@ void client_data_sending_task(void *param) { } } +void client_monitor_task(void *pvParameters) { + TickType_t timeout_ticks = + pdMS_TO_TICKS(CLIENT_TIMEOUT_MS); // Timeout in Ticks + TickType_t interval_ticks = + pdMS_TO_TICKS(CHECK_INTERVAL_MS); // Prüfintervall in Ticks + + while (1) { + TickType_t now = xTaskGetTickCount(); // Aktuelle Zeit in Ticks + + for (int i = 0; i < 20; i++) { + if (clients[i].isAvailable) { + TickType_t time_diff = now - clients[i].lastSuccessfullPing; + + // Prüfen, ob der Client als "nicht verfügbar" markiert werden soll + if (time_diff > timeout_ticks) { + clients[i].isAvailable = false; + ESP_LOGW( + TAG, + "Client %d (MAC: %02X:%02X:%02X:%02X:%02X:%02X) is unavailable", + i, clients[i].macAddr[0], clients[i].macAddr[1], + clients[i].macAddr[2], clients[i].macAddr[3], + clients[i].macAddr[4], clients[i].macAddr[5]); + } + } + } + + // Task für das Prüfintervall anhalten + vTaskDelay(interval_ticks); + } +} + void uart_read_task(void *param) { uint8_t *data = (uint8_t *)malloc(BUF_SIZE); int len = 0; @@ -323,6 +441,7 @@ void app_main(void) { add_peer(broadcast_address); xTaskCreate(master_broadcast_task, "MasterBroadcast", 4096, NULL, 1, NULL); xTaskCreate(master_ping_task, "MasterPing", 4096, NULL, 1, NULL); + xTaskCreate(client_monitor_task, "MonitorClientTask", 4096, NULL, 1, NULL); init_uart(); } else { ESP_LOGI(TAG, "Started in Slavemode");