cits-sniffer: IEEE 802.15.4 Promiscuous Mode Sniffer mit Ringpuffer und JTAG-Konsolencommands
- Ringpuffer (128 Pakete) für JTAG-Auslesung implementiert - Konsolencommands: status, read_pkts [n], chan <ch>, packets <n> - USB-Serial/JTAG als Primary Console aktiviert - esp_log_set_vprintf für JTAG-Log-Ausgabe - Block4-Integration entfernt, alles in app_main.c - CMakeLists.txt angepasst - partitions_8M.csv und sdkconfig aktualisiert
This commit is contained in:
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS "app_main.c"
|
SRCS "app_main.c"
|
||||||
INCLUDE_DIRS "."
|
INCLUDE_DIRS "."
|
||||||
REQUIRES esp_wifi esp_timer nvs_flash fatfs
|
PRIV_REQUIRES esp_timer nvs_flash driver ieee802154 console fatfs wear_levelling esp_driver_usb_serial_jtag
|
||||||
PRIV_REQUIRES wear_levelling
|
|
||||||
)
|
)
|
||||||
|
|||||||
+342
-133
@@ -1,7 +1,9 @@
|
|||||||
/**
|
/**
|
||||||
* app_main.c - C-ITS Sniffer für ESP32-C5 (LilyGO T-Dongle-C5)
|
* app_main.c - C-ITS Sniffer ESP32-C5
|
||||||
*
|
*
|
||||||
* Kombiniert alle Blöcke zu einer lauffähigen ESP-IDF Anwendung
|
* IEEE 802.15.4 Promiscuous Mode Sniffer
|
||||||
|
* Ringpuffer für JTAG-Auslesung von rohen Paketen
|
||||||
|
* Konsolencommands: status, read_pkts [n], chan <ch>, packets <n>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -11,205 +13,412 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_log_write.h"
|
||||||
#include "esp_timer.h"
|
#include "esp_timer.h"
|
||||||
|
#include "esp_console.h"
|
||||||
|
#include "esp_vfs.h"
|
||||||
|
#include "driver/usb_serial_jtag.h"
|
||||||
|
#include "driver/usb_serial_jtag_vfs.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_vfs_fat.h"
|
#include "esp_vfs_fat.h"
|
||||||
#include "esp_vfs.h"
|
|
||||||
#include "wear_levelling.h"
|
#include "wear_levelling.h"
|
||||||
|
#include "esp_ieee802154.h"
|
||||||
|
#include "esp_ieee802154_types.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
|
||||||
// ==================== Typedefs ====================
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
uint32_t timestamp_sec;
|
|
||||||
uint32_t timestamp_usec;
|
|
||||||
uint16_t length;
|
|
||||||
uint8_t sender_id[6];
|
|
||||||
uint8_t message_type;
|
|
||||||
uint8_t channel;
|
|
||||||
int16_t rssi;
|
|
||||||
} cits_message_t;
|
|
||||||
|
|
||||||
// ==================== Constants ====================
|
|
||||||
|
|
||||||
static const char *TAG = "CITS_SNIFFER";
|
static const char *TAG = "CITS_SNIFFER";
|
||||||
#define CITS_CHANNEL_0_MHZ 5900
|
static const char *TAG_CMD = "CMD";
|
||||||
#define CSV_WRITE_INTERVAL_SEC (600)
|
#define LED_PIN GPIO_NUM_28
|
||||||
|
#define SNIFFER_CHANNEL 11
|
||||||
|
#define CSV_INTERVAL_SEC 3600
|
||||||
|
|
||||||
// ==================== CSV State ====================
|
// Ringpuffer für rohe Pakete (für JTAG-Direct-Access)
|
||||||
|
#define PKT_RING_BUF_SIZE 128
|
||||||
|
#define PKT_MAX_SIZE 160
|
||||||
|
typedef struct {
|
||||||
|
uint8_t data[PKT_MAX_SIZE];
|
||||||
|
uint16_t len;
|
||||||
|
int8_t rssi;
|
||||||
|
uint8_t lqi;
|
||||||
|
uint32_t ts_sec;
|
||||||
|
uint32_t ts_usec;
|
||||||
|
} raw_pkt_t;
|
||||||
|
|
||||||
|
static raw_pkt_t pkt_ring[PKT_RING_BUF_SIZE];
|
||||||
|
static volatile uint32_t pkt_ring_write = 0;
|
||||||
|
static volatile uint32_t pkt_ring_total = 0;
|
||||||
|
static bool pkt_ring_full = false;
|
||||||
|
|
||||||
static FILE *csv_file = NULL;
|
static FILE *csv_file = NULL;
|
||||||
static char current_filename[64];
|
static char csv_filename[64];
|
||||||
static time_t last_write_time = 0;
|
static time_t last_csv_time = 0;
|
||||||
|
static uint32_t packet_count = 0;
|
||||||
|
static wl_handle_t wl_handle = WL_INVALID_HANDLE;
|
||||||
|
|
||||||
|
static volatile bool sniffer_active = false;
|
||||||
|
static volatile int8_t last_rssi = -127;
|
||||||
|
|
||||||
|
// === CSV / Storage ===
|
||||||
|
|
||||||
static void write_csv_header(FILE *fp)
|
static void write_csv_header(FILE *fp)
|
||||||
{
|
{
|
||||||
fprintf(fp, "timestamp_sec,timestamp_usec,length,sender_mac,message_type,channel,rssi\n");
|
fprintf(fp, "timestamp_sec,timestamp_usec,length,sender_mac,frame_type,channel,rssi,lqi\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_csv_row(FILE *fp, cits_message_t *msg)
|
static void write_csv_row(FILE *fp, uint32_t ts_sec, uint32_t ts_usec, uint16_t len,
|
||||||
|
uint8_t *src_mac, uint8_t ftype, uint8_t ch, int16_t rssi, uint8_t lqi)
|
||||||
{
|
{
|
||||||
char mac_str[18];
|
char mac_str[24];
|
||||||
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
msg->sender_id[0], msg->sender_id[1], msg->sender_id[2],
|
src_mac[7], src_mac[6], src_mac[5], src_mac[4], src_mac[3], src_mac[2], src_mac[1], src_mac[0]);
|
||||||
msg->sender_id[3], msg->sender_id[4], msg->sender_id[5]);
|
fprintf(fp, "%" PRIu32 ",%" PRIu32 ",%" PRIu16 ",%s,%u,%u,%d,%u\n",
|
||||||
fprintf(fp, "%" PRIu32 ",%" PRIu32 ",%" PRIu16 ",%s,%" PRIu8 ",%" PRIu8 ",%d\n",
|
ts_sec, ts_usec, len, mac_str, ftype, ch, rssi, lqi);
|
||||||
msg->timestamp_sec, msg->timestamp_usec, msg->length,
|
|
||||||
mac_str, msg->message_type, msg->channel, msg->rssi);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t create_new_csv_file(void)
|
static esp_err_t create_csv_file(void)
|
||||||
{
|
{
|
||||||
time_t now;
|
time_t now;
|
||||||
struct tm *tm_info;
|
struct tm *tm_info;
|
||||||
time(&now);
|
time(&now);
|
||||||
tm_info = localtime(&now);
|
tm_info = localtime(&now);
|
||||||
snprintf(current_filename, sizeof(current_filename),
|
snprintf(csv_filename, sizeof(csv_filename),
|
||||||
"/data/cits_%04d%02d%02d_%02d%02d%02d.csv",
|
"/storage/cits_%04d%02d%02d_%02d%02d%02d.csv",
|
||||||
tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
|
tm_info->tm_year + 1900, tm_info->tm_mon + 1, tm_info->tm_mday,
|
||||||
tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
|
tm_info->tm_hour, tm_info->tm_min, tm_info->tm_sec);
|
||||||
if (csv_file != NULL) fclose(csv_file);
|
if (csv_file != NULL) fclose(csv_file);
|
||||||
csv_file = fopen(current_filename, "w");
|
csv_file = fopen(csv_filename, "w");
|
||||||
if (csv_file == NULL) {
|
if (csv_file == NULL) {
|
||||||
ESP_LOGE(TAG, "CSV file erstellen fehlgeschlagen: %s", current_filename);
|
ESP_LOGE(TAG, "CSV create failed: %s", csv_filename);
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
write_csv_header(csv_file);
|
write_csv_header(csv_file);
|
||||||
fflush(csv_file);
|
fflush(csv_file);
|
||||||
ESP_LOGI(TAG, "Neue CSV-Datei: %s", current_filename);
|
ESP_LOGI(TAG, "CSV: %s", csv_filename);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void csv_store_cits_message(cits_message_t *msg)
|
static void store_pkt_raw(const uint8_t *data, uint16_t len, int8_t rssi, uint8_t lqi,
|
||||||
|
uint32_t ts_sec, uint32_t ts_usec)
|
||||||
{
|
{
|
||||||
if (csv_file != NULL) {
|
uint32_t idx = pkt_ring_write;
|
||||||
write_csv_row(csv_file, msg);
|
pkt_ring[idx].len = (len > PKT_MAX_SIZE) ? PKT_MAX_SIZE : len;
|
||||||
|
memcpy(pkt_ring[idx].data, data, pkt_ring[idx].len);
|
||||||
|
pkt_ring[idx].rssi = rssi;
|
||||||
|
pkt_ring[idx].lqi = lqi;
|
||||||
|
pkt_ring[idx].ts_sec = ts_sec;
|
||||||
|
pkt_ring[idx].ts_usec = ts_usec;
|
||||||
|
pkt_ring_write = (pkt_ring_write + 1) % PKT_RING_BUF_SIZE;
|
||||||
|
pkt_ring_total++;
|
||||||
|
if (pkt_ring_total > PKT_RING_BUF_SIZE) pkt_ring_full = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === 802.15.4 Sniffer Callback ===
|
||||||
|
|
||||||
|
static void sniffer_rx_cb(uint8_t *data, esp_ieee802154_frame_info_t *info)
|
||||||
|
{
|
||||||
|
if (!data || !info) return;
|
||||||
|
if (info->rssi < -100) return;
|
||||||
|
if (!sniffer_active) return;
|
||||||
|
|
||||||
|
packet_count++;
|
||||||
|
last_rssi = info->rssi;
|
||||||
|
|
||||||
|
uint16_t frame_ctrl = data[0] | (data[1] << 8);
|
||||||
|
uint8_t ftype = frame_ctrl & 0x07;
|
||||||
|
uint8_t addr_mode_src = (frame_ctrl >> 12) & 0x03;
|
||||||
|
|
||||||
|
uint8_t src_mac[8] = {0};
|
||||||
|
if (addr_mode_src == 1) {
|
||||||
|
src_mac[7] = data[2]; src_mac[6] = data[3];
|
||||||
|
} else if (addr_mode_src == 2) {
|
||||||
|
memcpy(src_mac, &data[2], 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ts_sec = (uint32_t)(info->timestamp / 1000000);
|
||||||
|
uint32_t ts_usec = (uint32_t)(info->timestamp / 1000) % 1000000;
|
||||||
|
|
||||||
|
// Raw-Paket im Ringpuffer speichern
|
||||||
|
store_pkt_raw(data, (uint16_t)(info->timestamp >> 8), info->rssi, info->lqi, ts_sec, ts_usec);
|
||||||
|
|
||||||
|
if (csv_file) {
|
||||||
|
write_csv_row(csv_file, ts_sec, ts_usec, 0, src_mac, ftype,
|
||||||
|
info->channel, info->rssi, info->lqi);
|
||||||
fflush(csv_file);
|
fflush(csv_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (packet_count % 5 == 0) {
|
||||||
|
char mac_str[32];
|
||||||
|
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
src_mac[7], src_mac[6], src_mac[5], src_mac[4], src_mac[3], src_mac[2],
|
||||||
|
src_mac[1], src_mac[0]);
|
||||||
|
ESP_LOGI(TAG, "[Pkt %lu] RSSI=%d | LQI=%u | Ch=%u | Src=%s",
|
||||||
|
(unsigned long)packet_count, info->rssi, info->lqi,
|
||||||
|
info->channel, mac_str);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== Promiscuous Callback ====================
|
static esp_err_t init_sniffer(void)
|
||||||
|
|
||||||
static void sniffer_callback(void *buf, wifi_promiscuous_pkt_type_t type)
|
|
||||||
{
|
{
|
||||||
wifi_promiscuous_pkt_t *pkt = (wifi_promiscuous_pkt_t *)buf;
|
ESP_LOGI(TAG, "Starte 802.15.4 Stack...");
|
||||||
|
esp_err_t ret = esp_ieee802154_enable();
|
||||||
if (type != WIFI_PKT_MISC) return;
|
|
||||||
if (pkt->rx_ctrl.rssi < -100) return; // Rauschen filtern
|
|
||||||
|
|
||||||
uint32_t timestamp_us = pkt->rx_ctrl.timestamp;
|
|
||||||
uint32_t sec = timestamp_us / 1000000U;
|
|
||||||
uint32_t usec = timestamp_us % 1000000U;
|
|
||||||
|
|
||||||
// Logge Paket-Metadaten
|
|
||||||
ESP_LOGI(TAG, "[Paket] RSSI=%d dBm | CH=%u MHz | Len=%" PRIu16 " | TS=%" PRIu32 ".%06" PRIu32 "",
|
|
||||||
pkt->rx_ctrl.rssi, CITS_CHANNEL_0_MHZ,
|
|
||||||
pkt->rx_ctrl.sig_len, sec, usec);
|
|
||||||
|
|
||||||
// Speichere in CSV (nur Header-Daten, kein Parser)
|
|
||||||
cits_message_t msg = {
|
|
||||||
.timestamp_sec = sec,
|
|
||||||
.timestamp_usec = usec,
|
|
||||||
.length = (pkt->rx_ctrl.sig_len > 65535) ? 65535 : pkt->rx_ctrl.sig_len,
|
|
||||||
.channel = (uint8_t)(CITS_CHANNEL_0_MHZ % 256),
|
|
||||||
.rssi = pkt->rx_ctrl.rssi,
|
|
||||||
};
|
|
||||||
csv_store_cits_message(&msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== Flash Storage ====================
|
|
||||||
|
|
||||||
static esp_err_t setup_flash_storage(void)
|
|
||||||
{
|
|
||||||
static wl_handle_t wl_handle;
|
|
||||||
const esp_vfs_fat_mount_config_t mount_config = {
|
|
||||||
.max_files = 4,
|
|
||||||
.format_if_mount_failed = true,
|
|
||||||
};
|
|
||||||
esp_err_t ret = esp_vfs_fat_spiflash_mount_rw_wl("/data", "storage", &mount_config, &wl_handle);
|
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "FATFS Mount fehlgeschlagen: %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "esp_ieee802154_enable failed: %s", esp_err_to_name(ret));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "FATFS storage gemountet");
|
ESP_LOGI(TAG, "802.15.4 stack enabled");
|
||||||
|
|
||||||
|
ret = esp_ieee802154_set_channel(SNIFFER_CHANNEL);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "channel set failed: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Channel: %d", SNIFFER_CHANNEL);
|
||||||
|
|
||||||
|
ret = esp_ieee802154_set_promiscuous(true);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "promiscuous failed: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Promiscuous mode enabled");
|
||||||
|
|
||||||
|
esp_ieee802154_event_cb_list_t cb_list = { .rx_done_cb = sniffer_rx_cb };
|
||||||
|
ret = esp_ieee802154_event_callback_list_register(cb_list);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "callback register failed: %s", esp_err_to_name(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG, "Rx callback registered");
|
||||||
|
|
||||||
|
sniffer_active = true;
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==================== WiFi Init (inline Block 1) ====================
|
static esp_err_t init_storage(void)
|
||||||
|
|
||||||
static esp_err_t initialize_wifi(void)
|
|
||||||
{
|
{
|
||||||
|
static wl_handle_t wl;
|
||||||
|
const esp_vfs_fat_mount_config_t mcfg = {
|
||||||
|
.max_files = 4, .format_if_mount_failed = true, .allocation_unit_size = 16 * 1024,
|
||||||
|
};
|
||||||
|
esp_err_t ret = esp_vfs_fat_spiflash_mount_rw_wl("/storage", "storage", &mcfg, &wl);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
wl_handle = wl;
|
||||||
|
ESP_LOGI(TAG, "FATFS storage mounted");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Konsolencommands ===
|
||||||
|
|
||||||
|
static int cmd_status(int argc, char **argv)
|
||||||
|
{
|
||||||
|
(void)argc; (void)argv;
|
||||||
|
ESP_LOGI(TAG_CMD, "== Status ==");
|
||||||
|
ESP_LOGI(TAG_CMD, "Packets: %lu", (unsigned long)packet_count);
|
||||||
|
ESP_LOGI(TAG_CMD, "CSV: %s", csv_filename);
|
||||||
|
ESP_LOGI(TAG_CMD, "Channel: %d", SNIFFER_CHANNEL);
|
||||||
|
ESP_LOGI(TAG_CMD, "Ring buffer: %lu/%d total, write_idx=%lu",
|
||||||
|
(unsigned long)pkt_ring_total, PKT_RING_BUF_SIZE,
|
||||||
|
(unsigned long)pkt_ring_write);
|
||||||
|
ESP_LOGI(TAG_CMD, "Last RSSI: %d", last_rssi);
|
||||||
|
ESP_LOGI(TAG_CMD, "Sniffer active: %s", sniffer_active ? "YES" : "NO");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_packets(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2) { ESP_LOGW(TAG_CMD, "Usage: packets <count>"); return 1; }
|
||||||
|
int count = atoi(argv[1]);
|
||||||
|
ESP_LOGI(TAG_CMD, "Warte auf %d Pakete...", count);
|
||||||
|
uint32_t start = packet_count;
|
||||||
|
while (packet_count - start < count) vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
ESP_LOGI(TAG_CMD, "%d Pakete empfangen!", count);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_read_pkts(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int count = 10;
|
||||||
|
if (argc > 0) {
|
||||||
|
count = atoi(argv[0]);
|
||||||
|
if (count < 1) count = 1;
|
||||||
|
if (count > PKT_RING_BUF_SIZE) count = PKT_RING_BUF_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t total = pkt_ring_total;
|
||||||
|
if (total == 0) {
|
||||||
|
ESP_LOGI(TAG_CMD, "Keine Pakete empfangen.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG_CMD, "=== Ring Buffer Read (%d von %lu) ===", count, (unsigned long)total);
|
||||||
|
uint32_t idx = (pkt_ring_write == 0) ? PKT_RING_BUF_SIZE - 1 : pkt_ring_write - 1;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
uint32_t read_total = pkt_ring_total;
|
||||||
|
if (pkt_ring_full && (read_total - (pkt_ring_write == 0 ? PKT_RING_BUF_SIZE : pkt_ring_write)) <= i) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!pkt_ring_full && i >= pkt_ring_total) break;
|
||||||
|
|
||||||
|
raw_pkt_t *pkt = &pkt_ring[idx];
|
||||||
|
char hex_str[72];
|
||||||
|
hex_str[0] = 0;
|
||||||
|
for (int j = 0; j < pkt->len && j < 36; j++) {
|
||||||
|
snprintf(hex_str + strlen(hex_str), sizeof(hex_str) - strlen(hex_str),
|
||||||
|
"%02x ", pkt->data[j]);
|
||||||
|
}
|
||||||
|
ESP_LOGI(TAG_CMD, " [%d] len=%u RSSI=%d LQI=%u | %s",
|
||||||
|
i, pkt->len, pkt->rssi, pkt->lqi, hex_str);
|
||||||
|
idx = (idx == 0) ? PKT_RING_BUF_SIZE - 1 : idx - 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_chan(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
ESP_LOGW(TAG_CMD, "Usage: chan <channel>");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
int ch = atoi(argv[0]);
|
||||||
|
if (ch < 11 || ch > 26) {
|
||||||
|
ESP_LOGW(TAG_CMD, "Channel muss 11-26 sein");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
esp_err_t ret = esp_ieee802154_set_channel(ch);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ESP_LOGI(TAG_CMD, "Channel auf %d geändert", ch);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG_CMD, "Channel change failed: %s", esp_err_to_name(ret));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void register_console_commands(void)
|
||||||
|
{
|
||||||
|
esp_console_cmd_t cmd_status_def = { .command = "status", .help = "Show sniffer status", .func = cmd_status };
|
||||||
|
esp_console_cmd_t cmd_packets_def = { .command = "packets", .help = "Wait for N packets", .func = cmd_packets };
|
||||||
|
esp_console_cmd_t cmd_read_def = { .command = "read_pkts", .help = "Read raw packets from ring buffer", .func = cmd_read_pkts };
|
||||||
|
esp_console_cmd_t cmd_ch_def = { .command = "chan", .help = "Change 802.15.4 channel", .func = cmd_chan };
|
||||||
|
esp_console_register_help_command();
|
||||||
|
esp_console_cmd_register(&cmd_status_def);
|
||||||
|
esp_console_cmd_register(&cmd_packets_def);
|
||||||
|
esp_console_cmd_register(&cmd_read_def);
|
||||||
|
esp_console_cmd_register(&cmd_ch_def);
|
||||||
|
ESP_LOGI(TAG, "Console commands registriert");
|
||||||
|
}
|
||||||
|
|
||||||
|
// === JTAG vprintf-Wrapper ===
|
||||||
|
// Sendet Logs über JTAG-Verbindung zum Host
|
||||||
|
static volatile int jtag_connected = 0;
|
||||||
|
static TickType_t jtag_last_connect_tick = 0;
|
||||||
|
|
||||||
|
static int jtag_vprintf(const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
char buf[256];
|
||||||
|
int len = vsnprintf(buf, sizeof(buf), fmt, args);
|
||||||
|
if (len > 0 && len < 256) {
|
||||||
|
// Versuche non-blocking JTAG write
|
||||||
|
TickType_t now = xTaskGetTickCount();
|
||||||
|
if (now - jtag_last_connect_tick < pdMS_TO_TICKS(1000)) {
|
||||||
|
// JTAG write with short timeout (100ms)
|
||||||
|
int wrote = usb_serial_jtag_write_bytes(buf, len, pdMS_TO_TICKS(100));
|
||||||
|
if (wrote <= 0) {
|
||||||
|
jtag_connected = 0;
|
||||||
|
jtag_last_connect_tick = now;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void app_main(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "== C-ITS SNIFFER ESP32-C5 ==");
|
||||||
|
ESP_LOGI(TAG, "Build: %s %s", __DATE__, __TIME__);
|
||||||
|
|
||||||
|
// LED initialisieren
|
||||||
|
gpio_reset_pin(LED_PIN);
|
||||||
|
gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
|
||||||
|
gpio_set_level(LED_PIN, 0);
|
||||||
|
|
||||||
|
// NVS initialisieren
|
||||||
esp_err_t ret = nvs_flash_init();
|
esp_err_t ret = nvs_flash_init();
|
||||||
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||||
nvs_flash_erase();
|
nvs_flash_erase();
|
||||||
ret = nvs_flash_init();
|
ret = nvs_flash_init();
|
||||||
}
|
}
|
||||||
|
ESP_ERROR_CHECK(ret);
|
||||||
|
|
||||||
|
// === USB-Serial/JTAG initialisieren ===
|
||||||
|
ESP_LOGI(TAG, "Init USB-Serial/JTAG...");
|
||||||
|
usb_serial_jtag_driver_config_t jtag_config = {0};
|
||||||
|
ret = usb_serial_jtag_driver_install(&jtag_config);
|
||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
ESP_LOGE(TAG, "NVS Flash init fehlgeschlagen: %s", esp_err_to_name(ret));
|
ESP_LOGE(TAG, "usb_serial_jtag_driver_install failed: %s", esp_err_to_name(ret));
|
||||||
return ret;
|
return;
|
||||||
|
}
|
||||||
|
ret = usb_serial_jtag_vfs_register();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "usb_serial_jtag_vfs_register failed: %s", esp_err_to_name(ret));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "NVS Flash OK");
|
|
||||||
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_storage(WIFI_STORAGE_RAM));
|
// Non-blocking JTAG write aktivieren
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
|
usb_serial_jtag_vfs_use_nonblocking();
|
||||||
ESP_ERROR_CHECK(esp_wifi_start());
|
ESP_LOGI(TAG, "Non-blocking JTAG aktiv");
|
||||||
|
|
||||||
ESP_LOGI(TAG, "WiFi initialisiert");
|
// Log-Ausgabe auf JTAG umleiten
|
||||||
return ESP_OK;
|
esp_log_set_vprintf((vprintf_like_t)jtag_vprintf);
|
||||||
}
|
|
||||||
|
|
||||||
static esp_err_t init_promiscuous(void)
|
ESP_LOGI(TAG, "USB-Serial/JTAG initialisiert");
|
||||||
{
|
|
||||||
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));
|
|
||||||
|
|
||||||
wifi_promiscuous_filter_t filter = {
|
// Storage initialisieren
|
||||||
.filter_mask = WIFI_PROMIS_FILTER_MASK_ALL
|
ESP_LOGI(TAG, "Init storage...");
|
||||||
};
|
ESP_ERROR_CHECK(init_storage());
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_filter(&filter));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous_rx_cb(sniffer_callback));
|
|
||||||
ESP_ERROR_CHECK(esp_wifi_set_promiscuous(true));
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Promiscuous Mode aktiv auf %u MHz", CITS_CHANNEL_0_MHZ);
|
// Console commands registrieren
|
||||||
return ESP_OK;
|
register_console_commands();
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== Main ====================
|
// 802.15.4 Sniffer starten
|
||||||
|
ret = init_sniffer();
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "802.15.4 init fehlgeschlagen: %s", esp_err_to_name(ret));
|
||||||
|
ESP_LOGI(TAG, "Sniffer deaktiviert - nur Console verfügbar");
|
||||||
|
}
|
||||||
|
|
||||||
void app_main(void)
|
// CSV-Datei erstellen
|
||||||
{
|
if (ret == ESP_OK) {
|
||||||
ESP_LOGI(TAG, "=== C-ITS SNIFFER FÜR ESP32-C5 ===");
|
ESP_ERROR_CHECK(create_csv_file());
|
||||||
ESP_LOGI(TAG, "Starte...");
|
last_csv_time = time(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
// WiFi Setup
|
ESP_LOGI(TAG, "== SNIFFER LÄUFT ==");
|
||||||
ESP_ERROR_CHECK(initialize_wifi());
|
ESP_LOGI(TAG, "Channel %d | Warte auf Pakete...", SNIFFER_CHANNEL);
|
||||||
ESP_ERROR_CHECK(init_promiscuous());
|
ESP_LOGI(TAG, "Console: sende 'status', 'read_pkts [n]', 'chan <ch>', 'packets <n>'");
|
||||||
|
|
||||||
// Flash Storage
|
// === Main Loop ===
|
||||||
ESP_ERROR_CHECK(setup_flash_storage());
|
uint32_t tick = 0;
|
||||||
ESP_ERROR_CHECK(create_new_csv_file());
|
|
||||||
last_write_time = time(NULL);
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "=== C-ITS SNIFFER LÄUFT ===");
|
|
||||||
ESP_LOGI(TAG, "Erwarte C-ITS/DSRC Pakete auf %u MHz...", CITS_CHANNEL_0_MHZ);
|
|
||||||
|
|
||||||
uint32_t last_report = 0;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(60000));
|
tick++;
|
||||||
last_report++;
|
gpio_set_level(LED_PIN, (tick % 2) ? 1 : 0);
|
||||||
time_t now;
|
if (tick % 100 == 0) {
|
||||||
time(&now);
|
ESP_LOGI(TAG, "tick=%lu | pkts=%lu | LED=%d",
|
||||||
if (difftime(now, last_write_time) >= CSV_WRITE_INTERVAL_SEC) {
|
(unsigned long)tick, (unsigned long)packet_count, (int)(tick%2));
|
||||||
create_new_csv_file();
|
}
|
||||||
last_write_time = now;
|
vTaskDelay(pdMS_TO_TICKS(1000));
|
||||||
|
|
||||||
|
if (sniffer_active && difftime(time(NULL), last_csv_time) >= CSV_INTERVAL_SEC) {
|
||||||
|
create_csv_file();
|
||||||
|
last_csv_time = time(NULL);
|
||||||
}
|
}
|
||||||
ESP_LOGI(TAG, "Laufzeit: %lu Min. | Warte auf C-ITS Pakete...", (unsigned long)last_report);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+259
-5
@@ -18,6 +18,11 @@
|
|||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
|
#include "esp_console.h"
|
||||||
|
#include "esp_vfs_dev_usb_serial_jtag.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "arg_table3/arg_table3.h"
|
||||||
|
#include "driver/usb_serial_jtag.h"
|
||||||
|
|
||||||
#include "block1_hardware_init.h"
|
#include "block1_hardware_init.h"
|
||||||
#include "block2_cits_parser.h"
|
#include "block2_cits_parser.h"
|
||||||
@@ -25,9 +30,51 @@
|
|||||||
|
|
||||||
static const char *TAG = "CITS_SNIFFER";
|
static const char *TAG = "CITS_SNIFFER";
|
||||||
|
|
||||||
|
// Globale Puffer für JTAG-Direct-Auslesung
|
||||||
|
#define MAX_STORED_PACKETS 64
|
||||||
|
#define MAX_PACKET_SIZE 2000
|
||||||
|
typedef struct {
|
||||||
|
wifi_promiscuous_pkt_t pkt;
|
||||||
|
uint32_t timestamp;
|
||||||
|
} stored_packet_t;
|
||||||
|
|
||||||
|
static stored_packet_t stored_packets[MAX_STORED_PACKETS];
|
||||||
|
static volatile uint32_t packet_write_idx = 0;
|
||||||
|
static volatile uint32_t packet_count_total = 0;
|
||||||
|
static bool packets_available = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hilfsfunktion: HEX-Daten auf Console (JTAG) ausgeben
|
||||||
|
*/
|
||||||
|
static void hex_dump(const char *prefix, const uint8_t *data, int len)
|
||||||
|
{
|
||||||
|
if (!prefix || !data || len <= 0) return;
|
||||||
|
|
||||||
|
// Print header with prefix
|
||||||
|
char line[128];
|
||||||
|
int offset = 0;
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "%s [Len=%d]:", prefix, len);
|
||||||
|
|
||||||
|
// First line: raw hex dump
|
||||||
|
for (int i = 0; i < len && i < 64; i++) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
if (i > 0) {
|
||||||
|
ESP_LOGI(TAG, " %s", line);
|
||||||
|
}
|
||||||
|
offset = 0;
|
||||||
|
snprintf(line, sizeof(line), " %04x: ", i);
|
||||||
|
}
|
||||||
|
offset += snprintf(line + strlen(line), sizeof(line) - strlen(line), "%02x ", data[i]);
|
||||||
|
}
|
||||||
|
if (len > 0) {
|
||||||
|
ESP_LOGI(TAG, "%s", line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sniffer Callback - Wird vom WiFi Promiscuous Mode aufgerufen
|
* Sniffer Callback - Wird vom WiFi Promiscuous Mode aufgerufen
|
||||||
* Jede empfangene 802.11p Nachricht wird hier geloggt
|
* Jede empfangene 802.11p Nachricht wird hier geloggt UND gespeichert für JTAG-Auslesung
|
||||||
*/
|
*/
|
||||||
static void sniffer_callback(void *recv_buf, wifi_promiscuous_pkt_type_t type)
|
static void sniffer_callback(void *recv_buf, wifi_promiscuous_pkt_type_t type)
|
||||||
{
|
{
|
||||||
@@ -44,9 +91,61 @@ static void sniffer_callback(void *recv_buf, wifi_promiscuous_pkt_type_t type)
|
|||||||
|
|
||||||
// RSSI aus dem Paket
|
// RSSI aus dem Paket
|
||||||
int8_t rssi = packet->rx_ctrl.rssi;
|
int8_t rssi = packet->rx_ctrl.rssi;
|
||||||
|
uint32_t ts = packet->rx_ctrl.timestamp;
|
||||||
|
uint16_t pkt_len = packet->rx_ctrl.sig_len;
|
||||||
|
|
||||||
ESP_LOGI(TAG, "[SNIFFER] 802.11p Paket empfangen: %d Bytes | RSSI: %d dBm",
|
// Detailiertes Paket-Logging auf JTAG Console
|
||||||
packet->rx_ctrl.sig_len, rssi);
|
ESP_LOGI(TAG, "[SNIFFER] === Paket #%lu ===", (unsigned long)packet_count_total);
|
||||||
|
ESP_LOGI(TAG, " Länge: %d Bytes | RSSI: %d dBm | Typ: %d | Chan: %d | Rate: %d",
|
||||||
|
pkt_len, rssi, type,
|
||||||
|
packet->rx_ctrl.channel,
|
||||||
|
packet->rx_ctrl.rate);
|
||||||
|
|
||||||
|
// MAC Header Bytes ausgeben
|
||||||
|
ESP_LOGI(TAG, " MAC Header: %02x %02x %02x %02x %02x %02x %02x %02x",
|
||||||
|
packet->payload[0], packet->payload[1],
|
||||||
|
packet->payload[2], packet->payload[3],
|
||||||
|
packet->payload[4], packet->payload[5],
|
||||||
|
packet->payload[6], packet->payload[7]);
|
||||||
|
|
||||||
|
// WAVE Header parsen
|
||||||
|
if (pkt_len >= 15) {
|
||||||
|
uint32_t pdu_len = packet->payload[0] | (packet->payload[1] << 8) | (packet->payload[2] << 16);
|
||||||
|
uint8_t sender_mac[6];
|
||||||
|
memcpy(sender_mac, packet->payload + 3, 6);
|
||||||
|
uint32_t ts_field;
|
||||||
|
memcpy(&ts_field, packet->payload + 9, 4);
|
||||||
|
uint8_t priority = packet->payload[13];
|
||||||
|
uint8_t pdu_type = packet->payload[14];
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, " WAVE PDU Length: %u | Sender: %02X:%02X:%02X:%02X:%02X:%02X",
|
||||||
|
pdu_len, sender_mac[0], sender_mac[1], sender_mac[2],
|
||||||
|
sender_mac[3], sender_mac[4], sender_mac[5]);
|
||||||
|
ESP_LOGI(TAG, " WAVE Timestamp: %u | Priority: %u | PDU Type: %02X",
|
||||||
|
ts_field, priority, pdu_type);
|
||||||
|
|
||||||
|
// C-ITS Payload wenn vorhanden
|
||||||
|
if (pkt_len > 15) {
|
||||||
|
ESP_LOGI(TAG, " C-ITS Payload (%d Bytes):", pkt_len - 15);
|
||||||
|
for (int i = 15; i < pkt_len && i < 47; i++) {
|
||||||
|
if ((i - 15) % 16 == 0) {
|
||||||
|
char hex_line[128];
|
||||||
|
snprintf(hex_line, sizeof(hex_line), " %04x: ", i);
|
||||||
|
ESP_LOGI(TAG, "%s", hex_line);
|
||||||
|
}
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL(TAG, packet->payload + i, 1, ESP_LOG_INFO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Paket zum JTAG-Direct-Zugang speichern
|
||||||
|
if (packet_count_total < MAX_STORED_PACKETS) {
|
||||||
|
memcpy(&stored_packets[packet_write_idx].pkt, packet, sizeof(wifi_promiscuous_pkt_t));
|
||||||
|
stored_packets[packet_write_idx].timestamp = ts;
|
||||||
|
packet_write_idx = (packet_write_idx + 1) % MAX_STORED_PACKETS;
|
||||||
|
}
|
||||||
|
packet_count_total++;
|
||||||
|
packets_available = true;
|
||||||
|
|
||||||
// Verarbeite C-ITS Nachricht
|
// Verarbeite C-ITS Nachricht
|
||||||
cits_process_packet(packet->payload, packet->rx_ctrl.sig_len,
|
cits_process_packet(packet->payload, packet->rx_ctrl.sig_len,
|
||||||
@@ -84,12 +183,131 @@ static esp_err_t setup_cits_sniffer(void)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JTAG Direct Read - Gepackete Pakete auf Console (JTAG) ausgeben
|
||||||
|
*/
|
||||||
|
static int cmd_jtag_read(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int count = 10; // Default 10 Pakete
|
||||||
|
|
||||||
|
if (argc > 0) {
|
||||||
|
count = atoi(argv[0]);
|
||||||
|
if (count < 1) count = 1;
|
||||||
|
if (count > MAX_STORED_PACKETS) count = MAX_STORED_PACKETS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packets_available) {
|
||||||
|
ESP_LOGI(TAG, "Keine Pakete empfangen. Warte auf C-ITS Nachrichten...");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "[JTAG-READ] Empfangene Pakete (%d vom %lu insgesamt):", count, (unsigned long)packet_count_total);
|
||||||
|
|
||||||
|
uint32_t idx = (packet_write_idx - 1 + MAX_STORED_PACKETS) % MAX_STORED_PACKETS;
|
||||||
|
int printed = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (printed >= packet_count_total) break;
|
||||||
|
|
||||||
|
stored_packet_t *p = &stored_packets[idx];
|
||||||
|
if (p->pkt.payload == NULL) {
|
||||||
|
idx = (idx - 1 + MAX_STORED_PACKETS) % MAX_STORED_PACKETS;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t pkt_len = p->pkt.rx_ctrl.sig_len;
|
||||||
|
int8_t rssi = p->pkt.rx_ctrl.rssi;
|
||||||
|
|
||||||
|
char mac_str[20];
|
||||||
|
if (pkt_len >= 12) {
|
||||||
|
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
p->pkt.payload[0], p->pkt.payload[1],
|
||||||
|
p->pkt.payload[2], p->pkt.payload[3],
|
||||||
|
p->pkt.payload[4], p->pkt.payload[5]);
|
||||||
|
} else {
|
||||||
|
strcpy(mac_str, "N/A");
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "[Paket %d] L=%d RSSI=%d MAC=%s",
|
||||||
|
i + 1, pkt_len, rssi, mac_str);
|
||||||
|
ESP_LOGI(TAG, "[Paket %d] Raw: ", i + 1);
|
||||||
|
ESP_LOG_BUFFER_HEX_LEVEL(TAG, p->pkt.payload, pkt_len < 64 ? pkt_len : 64, ESP_LOG_INFO);
|
||||||
|
|
||||||
|
printed++;
|
||||||
|
idx = (idx - 1 + MAX_STORED_PACKETS) % MAX_STORED_PACKETS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sniffer Status - Aktuelle Statistik ausgeben
|
||||||
|
*/
|
||||||
|
static int cmd_sniffer_status(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "[Status] Gesamt empfangene Pakete: %lu",
|
||||||
|
(unsigned long)packet_count_total);
|
||||||
|
ESP_LOGI(TAG, "[Status] Gespeichert: %d / %d",
|
||||||
|
(packet_write_idx < MAX_STORED_PACKETS) ?
|
||||||
|
(MAX_STORED_PACKETS - packet_write_idx) : packet_write_idx,
|
||||||
|
MAX_STORED_PACKETS);
|
||||||
|
ESP_LOGI(TAG, "[Status] Pakete verfügbar: %s", packets_available ? "JA" : "NEIN");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kanal wechseln
|
||||||
|
*/
|
||||||
|
static int cmd_change_channel(int argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 1) {
|
||||||
|
ESP_LOGI(TAG, "Nutzung: change_channel <freq_mhz>");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t freq = atoi(argv[0]);
|
||||||
|
if (freq < 5800 || freq > 5900) {
|
||||||
|
ESP_LOGE(TAG, "Frequenz muss zwischen 5800 und 5900 MHz liegen");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_11p_set(1, 0);
|
||||||
|
phy_change_channel(freq, 1, 0, 0);
|
||||||
|
ESP_LOGI(TAG, "Kanal auf %u MHz geändert", freq);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sniffer starten (neu)
|
||||||
|
*/
|
||||||
|
static int cmd_start_sniffer(int argc, char **argv)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "Sniffer wird neu gestartet...");
|
||||||
|
packets_available = false;
|
||||||
|
packet_write_idx = 0;
|
||||||
|
packet_count_total = 0;
|
||||||
|
|
||||||
|
esp_err_t ret = start_promiscuous_mode(CITS_CHANNEL_0_MHZ);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Sniffer Start fehlgeschlagen");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "Sniffer läuft auf %u MHz", CITS_CHANNEL_0_MHZ);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hauptfunktion
|
* Hauptfunktion
|
||||||
*/
|
*/
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "C-ITS Sniffer für ESP32-C5 startet...");
|
// USB-Serial/JTAG Console initialisieren
|
||||||
|
usb_serial_jtag_driver_install(0, 0, 0);
|
||||||
|
esp_vfs_dev_usb_serial_jtag_set_console();
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "=== C-ITS Sniffer für ESP32-C5 startet ===");
|
||||||
|
ESP_LOGI(TAG, "Console: USB-Serial/JTAG (115200 bps)");
|
||||||
|
|
||||||
// NVS initialisieren
|
// NVS initialisieren
|
||||||
esp_err_t ret = init_nvs_flash();
|
esp_err_t ret = init_nvs_flash();
|
||||||
@@ -112,10 +330,46 @@ void app_main(void)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Console Commands registrieren
|
||||||
|
const esp_console_cmd_t cmd_jtag_read_cmd = {
|
||||||
|
.command = "jtag_read",
|
||||||
|
.help = "Read captured packets via JTAG (optional count)",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_jtag_read,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&cmd_jtag_read_cmd);
|
||||||
|
|
||||||
|
const esp_console_cmd_t cmd_status_cmd = {
|
||||||
|
.command = "sniffer_status",
|
||||||
|
.help = "Show sniffer statistics",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_sniffer_status,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&cmd_status_cmd);
|
||||||
|
|
||||||
|
const esp_console_cmd_t cmd_chan_cmd = {
|
||||||
|
.command = "chan",
|
||||||
|
.help = "Change C-ITS channel (5800-5900 MHz)",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_change_channel,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&cmd_chan_cmd);
|
||||||
|
|
||||||
|
const esp_console_cmd_t cmd_start_cmd = {
|
||||||
|
.command = "start_sniffer",
|
||||||
|
.help = "Restart sniffer",
|
||||||
|
.hint = NULL,
|
||||||
|
.func = &cmd_start_sniffer,
|
||||||
|
};
|
||||||
|
esp_console_cmd_register(&cmd_start_cmd);
|
||||||
|
|
||||||
|
register_cits_commands();
|
||||||
|
|
||||||
// Hauptschleife - C-ITS Nachrichten werden im Callback verarbeitet
|
// Hauptschleife - C-ITS Nachrichten werden im Callback verarbeitet
|
||||||
ESP_LOGI(TAG, "C-ITS Sniffer läuft - Empfange DSRC/C-ITS Nachrichten auf %u MHz...",
|
ESP_LOGI(TAG, "C-ITS Sniffer läuft - Empfange DSRC/C-ITS Nachrichten auf %u MHz...",
|
||||||
CITS_CHANNEL_0_MHZ);
|
CITS_CHANNEL_0_MHZ);
|
||||||
ESP_LOGI(TAG, "Jede empfangene Nachricht wird geloggt und in CSV gespeichert");
|
ESP_LOGI(TAG, "Verwende USB-Serial/JTAG für Console/Ausgabe");
|
||||||
|
ESP_LOGI(TAG, "Commands: jtag_read [count], sniffer_status, chan <freq>, start_sniffer");
|
||||||
|
|
||||||
// Zähler für Statistik
|
// Zähler für Statistik
|
||||||
uint32_t packet_count = 0;
|
uint32_t packet_count = 0;
|
||||||
|
|||||||
+2
-4
@@ -2,7 +2,5 @@
|
|||||||
nvs, data, nvs, , 0x4000,
|
nvs, data, nvs, , 0x4000,
|
||||||
otadata, data, ota, , 0x2000,
|
otadata, data, ota, , 0x2000,
|
||||||
phy_init, data, phy, , 0x1000,
|
phy_init, data, phy, , 0x1000,
|
||||||
factory, app, factory, , 0x3E0000,
|
factory, app, factory, , 0x3C0000,
|
||||||
ota_0, app, ota_0, , 0x3E0000,
|
storage, data, fat, , 0x400000,
|
||||||
ota_1, app, ota_1, , 0x3E0000,
|
|
||||||
storage, data, fat, , 0x200000,
|
|
||||||
|
|||||||
|
@@ -645,14 +645,14 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
|
|||||||
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
# CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
|
CONFIG_ESPTOOLPY_FLASHFREQ="80m"
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y
|
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
|
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_32MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_64MB is not set
|
||||||
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
# CONFIG_ESPTOOLPY_FLASHSIZE_128MB is not set
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE="2MB"
|
CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
|
||||||
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
# CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE is not set
|
||||||
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
CONFIG_ESPTOOLPY_BEFORE_RESET=y
|
||||||
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
|
||||||
@@ -666,13 +666,13 @@ CONFIG_ESPTOOLPY_MONITOR_BAUD=115200
|
|||||||
#
|
#
|
||||||
# Partition Table
|
# Partition Table
|
||||||
#
|
#
|
||||||
CONFIG_PARTITION_TABLE_SINGLE_APP=y
|
# CONFIG_PARTITION_TABLE_SINGLE_APP is not set
|
||||||
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
|
# CONFIG_PARTITION_TABLE_SINGLE_APP_LARGE is not set
|
||||||
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
# CONFIG_PARTITION_TABLE_TWO_OTA is not set
|
||||||
# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set
|
# CONFIG_PARTITION_TABLE_TWO_OTA_LARGE is not set
|
||||||
# CONFIG_PARTITION_TABLE_CUSTOM is not set
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
|
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions_8M.csv"
|
||||||
CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv"
|
CONFIG_PARTITION_TABLE_FILENAME="partitions_8M.csv"
|
||||||
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
CONFIG_PARTITION_TABLE_OFFSET=0x8000
|
||||||
CONFIG_PARTITION_TABLE_MD5=y
|
CONFIG_PARTITION_TABLE_MD5=y
|
||||||
# end of Partition Table
|
# end of Partition Table
|
||||||
@@ -723,6 +723,7 @@ CONFIG_COMPILER_ORPHAN_SECTIONS_WARNING=y
|
|||||||
#
|
#
|
||||||
# CONFIG_APPTRACE_DEST_JTAG is not set
|
# CONFIG_APPTRACE_DEST_JTAG is not set
|
||||||
CONFIG_APPTRACE_DEST_NONE=y
|
CONFIG_APPTRACE_DEST_NONE=y
|
||||||
|
# CONFIG_APPTRACE_DEST_UART0 is not set
|
||||||
# CONFIG_APPTRACE_DEST_UART1 is not set
|
# CONFIG_APPTRACE_DEST_UART1 is not set
|
||||||
# CONFIG_APPTRACE_DEST_UART2 is not set
|
# CONFIG_APPTRACE_DEST_UART2 is not set
|
||||||
CONFIG_APPTRACE_DEST_UART_NONE=y
|
CONFIG_APPTRACE_DEST_UART_NONE=y
|
||||||
@@ -1358,17 +1359,14 @@ CONFIG_ESP_MAIN_TASK_AFFINITY_CPU0=y
|
|||||||
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
|
# CONFIG_ESP_MAIN_TASK_AFFINITY_NO_AFFINITY is not set
|
||||||
CONFIG_ESP_MAIN_TASK_AFFINITY=0x0
|
CONFIG_ESP_MAIN_TASK_AFFINITY=0x0
|
||||||
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
|
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
|
||||||
CONFIG_ESP_CONSOLE_UART_DEFAULT=y
|
# CONFIG_ESP_CONSOLE_UART_DEFAULT is not set
|
||||||
# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG is not set
|
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
|
||||||
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
|
# CONFIG_ESP_CONSOLE_UART_CUSTOM is not set
|
||||||
# CONFIG_ESP_CONSOLE_NONE is not set
|
# CONFIG_ESP_CONSOLE_NONE is not set
|
||||||
# CONFIG_ESP_CONSOLE_SECONDARY_NONE is not set
|
CONFIG_ESP_CONSOLE_SECONDARY_NONE=y
|
||||||
CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG=y
|
|
||||||
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y
|
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG_ENABLED=y
|
||||||
CONFIG_ESP_CONSOLE_UART=y
|
CONFIG_ESP_CONSOLE_UART_NUM=-1
|
||||||
CONFIG_ESP_CONSOLE_UART_NUM=0
|
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=3
|
||||||
CONFIG_ESP_CONSOLE_ROM_SERIAL_PORT_NUM=0
|
|
||||||
CONFIG_ESP_CONSOLE_UART_BAUDRATE=115200
|
|
||||||
CONFIG_ESP_INT_WDT=y
|
CONFIG_ESP_INT_WDT=y
|
||||||
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
|
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
|
||||||
CONFIG_ESP_TASK_WDT_EN=y
|
CONFIG_ESP_TASK_WDT_EN=y
|
||||||
@@ -2370,13 +2368,11 @@ CONFIG_ESP_SYSTEM_PM_POWER_DOWN_CPU=y
|
|||||||
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
|
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
|
||||||
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
|
||||||
CONFIG_MAIN_TASK_STACK_SIZE=3584
|
CONFIG_MAIN_TASK_STACK_SIZE=3584
|
||||||
CONFIG_CONSOLE_UART_DEFAULT=y
|
# CONFIG_CONSOLE_UART_DEFAULT is not set
|
||||||
# CONFIG_CONSOLE_UART_CUSTOM is not set
|
# CONFIG_CONSOLE_UART_CUSTOM is not set
|
||||||
# CONFIG_CONSOLE_UART_NONE is not set
|
# CONFIG_CONSOLE_UART_NONE is not set
|
||||||
# CONFIG_ESP_CONSOLE_UART_NONE is not set
|
# CONFIG_ESP_CONSOLE_UART_NONE is not set
|
||||||
CONFIG_CONSOLE_UART=y
|
CONFIG_CONSOLE_UART_NUM=-1
|
||||||
CONFIG_CONSOLE_UART_NUM=0
|
|
||||||
CONFIG_CONSOLE_UART_BAUDRATE=115200
|
|
||||||
CONFIG_INT_WDT=y
|
CONFIG_INT_WDT=y
|
||||||
CONFIG_INT_WDT_TIMEOUT_MS=300
|
CONFIG_INT_WDT_TIMEOUT_MS=300
|
||||||
CONFIG_TASK_WDT=y
|
CONFIG_TASK_WDT=y
|
||||||
|
|||||||
Reference in New Issue
Block a user