229 lines
6.8 KiB
C
229 lines
6.8 KiB
C
/**
|
|
* Block 4: Integration - C-ITS Sniffer für ESP32-C5
|
|
*
|
|
* Hauptprogramm:
|
|
* - NVS + WiFi + 802.11p PHY + Promiscuous Mode
|
|
* - CSV Writer auf SD-Karte
|
|
* - USB-Serial/JTAG Console für Live-Ansicht der C-ITS Nachrichten
|
|
* - CLI Commands: status, chan <freq>, set_channel <freq>, stop_sniffer
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#include <inttypes.h>
|
|
|
|
#include "sdkconfig.h"
|
|
#include "esp_err.h"
|
|
#include "esp_log.h"
|
|
#include "esp_wifi.h"
|
|
#include "esp_timer.h"
|
|
#include "esp_console.h"
|
|
#include "driver/gpio.h"
|
|
#include "nvs_flash.h"
|
|
#include "freertos/FreeRTOS.h"
|
|
#include "freertos/task.h"
|
|
#include "driver/usb_serial_jtag_vfs.h"
|
|
#include "driver/usb_serial_jtag.h"
|
|
|
|
#include "block1_hardware_init.h"
|
|
#include "block2_cits_parser.h"
|
|
#include "block3_csv_writer.h"
|
|
|
|
static const char *TAG = "CITS_SNIFFER";
|
|
|
|
#define LED_PIN GPIO_NUM_28
|
|
#define STATS_INTERVAL_TICKS (pdMS_TO_TICKS(60000))
|
|
#define BUILTIN_LED_ON 0
|
|
#define BUILTIN_LED_OFF 1
|
|
|
|
/* ---------- Sniffer-Zustand ---------- */
|
|
static volatile bool g_sniffer_active = false;
|
|
static volatile uint32_t g_total_packets = 0;
|
|
|
|
/* ---------- Promiscuous RX Callback ---------- */
|
|
void sniffer_on_raw_packet(void *buf, wifi_promiscuous_pkt_type_t type)
|
|
{
|
|
(void)type;
|
|
if (!g_sniffer_active) return;
|
|
|
|
wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)buf;
|
|
if (!pkt || pkt->rx_ctrl.sig_len < 14) return;
|
|
|
|
int8_t rssi = pkt->rx_ctrl.rssi;
|
|
uint16_t data_len = pkt->rx_ctrl.sig_len;
|
|
uint32_t channel_mhz = pkt->rx_ctrl.channel;
|
|
uint32_t ts_us = pkt->rx_ctrl.timestamp;
|
|
|
|
g_total_packets++;
|
|
|
|
// LED blink
|
|
gpio_set_level(LED_PIN, (g_total_packets % 10 < 1) ? BUILTIN_LED_ON : BUILTIN_LED_OFF);
|
|
|
|
// C-ITS Parser aufrufen
|
|
cits_process_packet(pkt->payload, data_len, rssi, channel_mhz,
|
|
ts_us / 1000000, ts_us % 1000000);
|
|
}
|
|
|
|
/* ---------- Console Commands ---------- */
|
|
|
|
static int cmd_status(int argc, char **argv)
|
|
{
|
|
(void)argc; (void)argv;
|
|
ESP_LOGI(TAG, "== STATUS ==");
|
|
ESP_LOGI(TAG, "Sniffer aktiv: %s", g_sniffer_active ? "JA" : "NEIN");
|
|
ESP_LOGI(TAG, "Gesamt Pakete: %" PRIu32, g_total_packets);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_chan(int argc, char **argv)
|
|
{
|
|
if (argc < 1) {
|
|
printf("Nutzung: chan <5900|5890|5880|5870>\n");
|
|
return 0;
|
|
}
|
|
uint32_t freq = atoi(argv[0]);
|
|
if (freq != 5900 && freq != 5890 && freq != 5880 && freq != 5870) {
|
|
printf("Ungültiger Kanal. Gültig: 5900, 5890, 5880, 5870\n");
|
|
return 1;
|
|
}
|
|
set_cits_channel(freq);
|
|
ESP_LOGI(TAG, "Kanal auf %d MHz ge\303\244ndert", freq);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_packets(int argc, char **argv)
|
|
{
|
|
if (argc < 1) {
|
|
printf("Nutzung: packets <anzahl>\n");
|
|
return 0;
|
|
}
|
|
int target = atoi(argv[0]);
|
|
uint32_t start = g_total_packets;
|
|
printf("Warte auf %d Pakete... ", target);
|
|
fflush(stdout);
|
|
while (g_total_packets - start < (uint32_t)target) {
|
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
|
}
|
|
printf("OK! %" PRIu32 " Pakete empfangen.\n", g_total_packets);
|
|
return 0;
|
|
}
|
|
|
|
static int cmd_restart(int argc, char **argv)
|
|
{
|
|
(void)argc; (void)argv;
|
|
printf("Sniffer wird neu gestartet...\n");
|
|
stop_promiscuous_mode();
|
|
g_sniffer_active = false;
|
|
vTaskDelay(pdMS_TO_TICKS(500));
|
|
g_total_packets = 0;
|
|
esp_err_t ret = start_promiscuous_mode(CITS_CHANNEL_0_MHZ);
|
|
if (ret == ESP_OK) {
|
|
g_sniffer_active = true;
|
|
ESP_LOGI(TAG, "Sniffer l\303\274uft auf %d MHz", CITS_CHANNEL_0_MHZ);
|
|
}
|
|
return (ret == ESP_OK) ? 0 : 1;
|
|
}
|
|
|
|
/* ---------- Hauptfunktion ---------- */
|
|
void app_main(void)
|
|
{
|
|
ESP_LOGI(TAG, "====== C-ITS SNIFFER ESP32-C5 ======");
|
|
ESP_LOGI(TAG, " Release v2.0.0 — C-ITS Live + SD-Card");
|
|
ESP_LOGI(TAG, " Build: %s %s", __DATE__, __TIME__);
|
|
ESP_LOGI(TAG, "======================================");
|
|
|
|
// LED
|
|
gpio_reset_pin(LED_PIN);
|
|
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
|
|
gpio_set_level(LED_PIN, BUILTIN_LED_OFF);
|
|
|
|
// NVS
|
|
esp_err_t ret = nvs_flash_init();
|
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
|
nvs_flash_erase();
|
|
ret = nvs_flash_init();
|
|
}
|
|
ESP_ERROR_CHECK(ret);
|
|
|
|
// WiFi
|
|
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
|
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
|
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
|
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
|
|
ESP_ERROR_CHECK(esp_wifi_start());
|
|
ESP_LOGI(TAG, "WiFi initialisiert (NULL-Mode / Promiscuous)");
|
|
|
|
// CSV Writer (SD-Karte)
|
|
ret = csv_writer_init();
|
|
if (ret != ESP_OK) {
|
|
ESP_LOGE(TAG, "CSV Writer init failed: %s", esp_err_to_name(ret));
|
|
}
|
|
|
|
// C-ITS Parser
|
|
cits_parser_init();
|
|
|
|
// USB-Serial/JTAG Console
|
|
#ifdef CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
|
usb_serial_jtag_driver_config_t jtag_cfg = USB_SERIAL_JTAG_DRIVER_CONFIG_DEFAULT();
|
|
usb_serial_jtag_driver_install(&jtag_cfg);
|
|
usb_serial_jtag_vfs_register();
|
|
usb_serial_jtag_vfs_use_nonblocking();
|
|
usb_serial_jtag_vfs_use_driver();
|
|
ESP_LOGI(TAG, "Console: USB-Serial/JTAG @ 115200 bps");
|
|
#else
|
|
ESP_LOGI(TAG, "Console: UART default");
|
|
#endif
|
|
|
|
// Promiscuous Mode starten
|
|
start_promiscuous_mode(CITS_CHANNEL_0_MHZ);
|
|
g_sniffer_active = true;
|
|
|
|
// CLI Commands
|
|
esp_console_register_help_command();
|
|
|
|
const esp_console_cmd_t cmd_status_def = {
|
|
.command = "status", .help = "Show sniffer status", .func = cmd_status,
|
|
};
|
|
esp_console_cmd_register(&cmd_status_def);
|
|
|
|
const esp_console_cmd_t cmd_chan_def = {
|
|
.command = "chan", .help = "Change C-ITS channel (5900|5890|5880|5870)", .func = cmd_chan,
|
|
};
|
|
esp_console_cmd_register(&cmd_chan_def);
|
|
|
|
const esp_console_cmd_t cmd_pkts_def = {
|
|
.command = "packets", .help = "Wait for N packets", .func = cmd_packets,
|
|
};
|
|
esp_console_cmd_register(&cmd_pkts_def);
|
|
|
|
const esp_console_cmd_t cmd_restart_def = {
|
|
.command = "restart", .help = "Restart sniffer", .func = cmd_restart,
|
|
};
|
|
esp_console_cmd_register(&cmd_restart_def);
|
|
|
|
// register_cits_commands() aus block1
|
|
register_cits_commands();
|
|
|
|
// Hauptschleife
|
|
ESP_LOGI(TAG, ">>> C-ITS SNIFFER LAUFT <<<");
|
|
ESP_LOGI(TAG, "Kanal: %d MHz | SD-Karte: /storage/ | Console: USB-JTAG", CITS_CHANNEL_0_MHZ);
|
|
ESP_LOGI(TAG, "Commands: status, chan <freq>, set_channel <freq>, packets <n>, restart");
|
|
ESP_LOGI(TAG, "Live-Ansicht: Alle Pakete erscheinen als [PKT#...] auf Console");
|
|
|
|
uint32_t tick = 0;
|
|
while (1) {
|
|
tick++;
|
|
gpio_set_level(LED_PIN, (tick % 2) ? BUILTIN_LED_ON : BUILTIN_LED_OFF);
|
|
|
|
if (tick % 60 == 0) {
|
|
ESP_LOGI(TAG, "[STAT] Uptime=%" PRIu32 " min | Total pkts=%" PRIu32,
|
|
tick / 60, g_total_packets);
|
|
}
|
|
|
|
vTaskDelay(1);
|
|
}
|
|
}
|