Added Reconnecting ability

This commit is contained in:
simon 2024-12-28 19:52:54 +01:00
parent 10d6898e43
commit 5a6b2d4e0e
2 changed files with 137 additions and 10 deletions

View File

@ -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

View File

@ -17,6 +17,7 @@
#include <freertos/task.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#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]);
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;
clients[numClients++] = newClient;
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");