Files
cits-sniffer/block3_csv_writer.c

163 lines
3.7 KiB
C

/**
* Block 3: CSV Writer für C-ITS Sniffer
*
* Erstellt CSV-Dateien mit empfangenen C-ITS Nachrichten
* Neue Datei alle 10 Minuten
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_vfs_fat.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
static const char *TAG = "CSV_WRITER";
// CSV Datei Handle
static FILE *csv_file = NULL;
static char current_filename[64];
static time_t last_write_time = 0;
#define CSV_WRITE_INTERVAL_SEC (600) // 10 Minuten
/**
* C-ITS Message Header (BSI Format)
*/
typedef struct {
uint32_t timestamp_sec;
uint32_t timestamp_usec;
uint16_t length;
uint8_t sender_id[6]; // MAC Address
uint8_t message_type; // BSI Message Type
uint8_t channel; // Kanal
int16_t rssi; // Signal Stärke
} cits_message_t;
/**
* CSV Header schreiben
*/
static void write_csv_header(FILE *fp)
{
fprintf(fp, "timestamp_sec,timestamp_usec,length,sender_mac,message_type,channel,rssi\n");
}
/**
* CSV Zeile schreiben
*/
static void write_csv_row(FILE *fp, cits_message_t *msg)
{
char mac_str[18];
snprintf(mac_str, sizeof(mac_str), "%02x:%02x:%02x:%02x:%02x:%02x",
msg->sender_id[0], msg->sender_id[1], msg->sender_id[2],
msg->sender_id[3], msg->sender_id[4], msg->sender_id[5]);
fprintf(fp, "%u,%u,%u,%s,%u,%u,%d\n",
msg->timestamp_sec, msg->timestamp_usec, msg->length,
mac_str, msg->message_type, msg->channel, msg->rssi);
}
/**
* Neue CSV-Datei erstellen
*/
static esp_err_t create_new_csv_file(void)
{
time_t now;
struct tm *tm_info;
time(&now);
tm_info = localtime(&now);
// Dateinamen mit Zeitstempel
snprintf(current_filename, sizeof(current_filename),
"/data/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_hour, tm_info->tm_min, tm_info->tm_sec);
if (csv_file != NULL) {
fclose(csv_file);
}
csv_file = fopen(current_filename, "w");
if (csv_file == NULL) {
ESP_LOGE(TAG, "Failed to create CSV file: %s", current_filename);
return ESP_FAIL;
}
write_csv_header(csv_file);
fflush(csv_file);
ESP_LOGI(TAG, "Created new CSV file: %s", current_filename);
return ESP_OK;
}
/**
* Prüfen ob neue Datei nötig (10 Minuten Intervall)
*/
static void check_new_csv_file(void)
{
time_t now;
time(&now);
if (difftime(now, last_write_time) >= CSV_WRITE_INTERVAL_SEC) {
create_new_csv_file();
last_write_time = now;
}
}
/**
* C-ITS Nachricht speichern
*
* @param msg Nachricht Daten
*/
void csv_store_cits_message(cits_message_t *msg)
{
if (csv_file == NULL) {
create_new_csv_file();
if (csv_file == NULL) {
return;
}
}
check_new_csv_file();
write_csv_row(csv_file, msg);
fflush(csv_file);
}
/**
* CSV System initialisieren
*/
esp_err_t csv_writer_init(void)
{
// SPI Flash Filesystem mounten
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) {
ESP_LOGE(TAG, "Failed to mount FATFS (%s)", esp_err_to_name(ret));
return ret;
}
// Erste CSV Datei erstellen
return create_new_csv_file();
}
/**
* CSV System beenden
*/
void csv_writer_deinit(void)
{
if (csv_file != NULL) {
fclose(csv_file);
csv_file = NULL;
}
}