mirror of
https://codeberg.org/opentrafficmap/its-g5-receiver-firmware.git
synced 2026-07-30 20:45:39 +00:00
Add config system; auto-start/stop mqtt on eth up/down; first attempt of sending received packets over MQTT
This commit is contained in:
+22
-8
@@ -1,9 +1,23 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
"cmd_sniffer.c"
|
||||
"cmd_pcap.c"
|
||||
"ethernet.c"
|
||||
"sdcard.c"
|
||||
"spi.c"
|
||||
PRIV_REQUIRES console esp_wifi fatfs esp_eth app_trace nvs_flash
|
||||
INCLUDE_DIRS ".")
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
"cmd_sniffer.c"
|
||||
"cmd_pcap.c"
|
||||
"config.c"
|
||||
"ethernet.c"
|
||||
"events.c"
|
||||
"mqtt.c"
|
||||
"sdcard.c"
|
||||
"spi.c"
|
||||
PRIV_REQUIRES
|
||||
app_trace
|
||||
console
|
||||
esp_eth
|
||||
esp_netif
|
||||
esp_wifi
|
||||
fatfs
|
||||
nvs_flash
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
)
|
||||
|
||||
|
||||
+67
-51
@@ -1,20 +1,16 @@
|
||||
/* cmd_sniffer example.
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
#include "sdkconfig.h"
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
|
||||
#include "argtable3/argtable3.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include <sys/unistd.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_console.h"
|
||||
@@ -22,7 +18,8 @@
|
||||
#include "cmd_sniffer.h"
|
||||
#include "cmd_pcap.h"
|
||||
#include "esp_check.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "events.h"
|
||||
|
||||
#define SNIFFER_DEFAULT_CHANNEL (1)
|
||||
#define SNIFFER_PAYLOAD_FCS_LEN (4)
|
||||
@@ -32,7 +29,7 @@
|
||||
#define SNIFFER_DECIMAL_NUM (10)
|
||||
|
||||
|
||||
static const char *SNIFFER_TAG = "cmd_sniffer";
|
||||
static const char TAG[] = "SNIFFER";
|
||||
|
||||
typedef struct {
|
||||
char *filter_name;
|
||||
@@ -52,13 +49,6 @@ typedef struct {
|
||||
esp_eth_handle_t eth_handles[SNIFFER_MAX_ETH_INTFS];
|
||||
} sniffer_runtime_t;
|
||||
|
||||
typedef struct {
|
||||
void *payload;
|
||||
uint32_t length;
|
||||
uint32_t seconds;
|
||||
uint32_t microseconds;
|
||||
} sniffer_packet_info_t;
|
||||
|
||||
static sniffer_runtime_t snf_rt = {0};
|
||||
static wlan_filter_table_t wifi_filter_hash_table[SNIFFER_WLAN_FILTER_MAX] = {0};
|
||||
static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer);
|
||||
@@ -123,28 +113,51 @@ static void queue_packet(void *recv_packet, sniffer_packet_info_t *packet_info)
|
||||
if (snf_rt.work_queue) {
|
||||
/* send packet_info */
|
||||
if (xQueueSend(snf_rt.work_queue, packet_info, pdMS_TO_TICKS(SNIFFER_PROCESS_PACKET_TIMEOUT_MS)) != pdTRUE) {
|
||||
ESP_LOGE(SNIFFER_TAG, "sniffer work queue full");
|
||||
ESP_LOGE(TAG, "sniffer work queue full");
|
||||
free(packet_info->payload);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(SNIFFER_TAG, "No enough memory for promiscuous packet");
|
||||
ESP_LOGE(TAG, "No enough memory for promiscuous packet");
|
||||
}
|
||||
}
|
||||
|
||||
static void send_packet_event(void *recv_packet, sniffer_packet_info_t *packet_info)
|
||||
{
|
||||
/* Copy a packet from Link Layer driver and queue the copy to be processed by sniffer task */
|
||||
size_t combined_length = sizeof(sniffer_combined_info_t) + packet_info->length;
|
||||
sniffer_combined_info_t *info_to_queue = malloc(combined_length);
|
||||
if (info_to_queue) {
|
||||
info_to_queue->info = *packet_info;
|
||||
// TODO: This is one more copy than would be nice. Can we send shared_ptr over some sort of queue?
|
||||
memcpy(info_to_queue->payload, recv_packet, packet_info->length);
|
||||
info_to_queue->info.payload = NULL;
|
||||
|
||||
int result = esp_event_post(SNIFFER_EVENT_BASE, SNIFFER_GOT_FRAME, info_to_queue, combined_length, 0);
|
||||
if (result != ESP_OK)
|
||||
{
|
||||
ESP_LOGW(TAG, "Could not post event SNIFFER_GOT_FRAME: %s", esp_err_to_name(result));
|
||||
}
|
||||
free(info_to_queue);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "No enough memory for promiscuous packet");
|
||||
}
|
||||
}
|
||||
|
||||
static void wifi_sniffer_cb(void *recv_buf, wifi_promiscuous_pkt_type_t type)
|
||||
{
|
||||
sniffer_packet_info_t packet_info;
|
||||
wifi_promiscuous_pkt_t *sniffer = (wifi_promiscuous_pkt_t *)recv_buf;
|
||||
wifi_promiscuous_pkt_t *packet = (wifi_promiscuous_pkt_t *)recv_buf;
|
||||
/* prepare packet_info */
|
||||
packet_info.seconds = sniffer->rx_ctrl.timestamp / 1000000U;
|
||||
packet_info.microseconds = sniffer->rx_ctrl.timestamp % 1000000U;
|
||||
packet_info.length = sniffer->rx_ctrl.sig_len;
|
||||
packet_info.seconds = packet->rx_ctrl.timestamp / 1000000U;
|
||||
packet_info.microseconds = packet->rx_ctrl.timestamp % 1000000U;
|
||||
packet_info.length = packet->rx_ctrl.sig_len;
|
||||
|
||||
/* For now, the sniffer only dumps the length of the MISC type frame */
|
||||
if (type != WIFI_PKT_MISC && !sniffer->rx_ctrl.rx_state) {
|
||||
if (type != WIFI_PKT_MISC && !packet->rx_ctrl.rx_state) {
|
||||
packet_info.length -= SNIFFER_PAYLOAD_FCS_LEN;
|
||||
queue_packet(sniffer->payload, &packet_info);
|
||||
//queue_packet(sniffer->payload, &packet_info);
|
||||
send_packet_event(packet->payload, &packet_info);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,7 +197,7 @@ static void sniffer_task(void *parameters)
|
||||
}
|
||||
if (packet_capture(packet_info.payload, packet_info.length, packet_info.seconds,
|
||||
packet_info.microseconds) != ESP_OK) {
|
||||
ESP_LOGW(SNIFFER_TAG, "save captured packet failed");
|
||||
ESP_LOGW(TAG, "save captured packet failed");
|
||||
}
|
||||
free(packet_info.payload);
|
||||
if (sniffer->packets_to_sniff > 0) {
|
||||
@@ -204,25 +217,25 @@ static esp_err_t sniffer_stop(sniffer_runtime_t *sniffer)
|
||||
bool eth_set_promiscuous;
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
ESP_GOTO_ON_FALSE(sniffer->is_running, ESP_ERR_INVALID_STATE, err, SNIFFER_TAG, "sniffer is already stopped");
|
||||
ESP_GOTO_ON_FALSE(sniffer->is_running, ESP_ERR_INVALID_STATE, err, TAG, "sniffer is already stopped");
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
/* Disable wifi promiscuous mode */
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_promiscuous(false), err, SNIFFER_TAG, "stop wifi promiscuous failed");
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_promiscuous(false), err, TAG, "stop wifi promiscuous failed");
|
||||
break;
|
||||
case SNIFFER_INTF_ETH:
|
||||
/* Disable Ethernet Promiscuous Mode */
|
||||
eth_set_promiscuous = false;
|
||||
ESP_GOTO_ON_ERROR(esp_eth_ioctl(sniffer->eth_handles[sniffer->interf_num], ETH_CMD_S_PROMISCUOUS, ð_set_promiscuous),
|
||||
err, SNIFFER_TAG, "stop Ethernet promiscuous failed");
|
||||
err, TAG, "stop Ethernet promiscuous failed");
|
||||
esp_eth_update_input_path(sniffer->eth_handles[sniffer->interf_num], NULL, NULL);
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, SNIFFER_TAG, "unsupported interface");
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unsupported interface");
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(SNIFFER_TAG, "stop promiscuous ok");
|
||||
ESP_LOGI(TAG, "stop promiscuous ok");
|
||||
|
||||
/* stop sniffer local task */
|
||||
sniffer->is_running = false;
|
||||
@@ -260,7 +273,7 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
|
||||
wifi_promiscuous_filter_t wifi_filter;
|
||||
bool eth_set_promiscuous;
|
||||
|
||||
ESP_GOTO_ON_FALSE(!(sniffer->is_running), ESP_ERR_INVALID_STATE, err, SNIFFER_TAG, "sniffer is already running");
|
||||
ESP_GOTO_ON_FALSE(!(sniffer->is_running), ESP_ERR_INVALID_STATE, err, TAG, "sniffer is already running");
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
@@ -270,21 +283,21 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
|
||||
link_type = PCAP_LINK_TYPE_ETHERNET;
|
||||
break;
|
||||
default:
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, SNIFFER_TAG, "unsupported interface");
|
||||
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "unsupported interface");
|
||||
break;
|
||||
}
|
||||
|
||||
/* init a pcap session */
|
||||
ESP_GOTO_ON_ERROR(sniff_packet_start(link_type), err, SNIFFER_TAG, "init pcap session failed");
|
||||
ESP_GOTO_ON_ERROR(sniff_packet_start(link_type), err, TAG, "init pcap session failed");
|
||||
|
||||
sniffer->is_running = true;
|
||||
sniffer->work_queue = xQueueCreate(CONFIG_SNIFFER_WORK_QUEUE_LEN, sizeof(sniffer_packet_info_t));
|
||||
ESP_GOTO_ON_FALSE(sniffer->work_queue, ESP_FAIL, err_queue, SNIFFER_TAG, "create work queue failed");
|
||||
ESP_GOTO_ON_FALSE(sniffer->work_queue, ESP_FAIL, err_queue, TAG, "create work queue failed");
|
||||
sniffer->sem_task_over = xSemaphoreCreateBinary();
|
||||
ESP_GOTO_ON_FALSE(sniffer->sem_task_over, ESP_FAIL, err_sem, SNIFFER_TAG, "create work queue failed");
|
||||
ESP_GOTO_ON_FALSE(sniffer->sem_task_over, ESP_FAIL, err_sem, TAG, "create work queue failed");
|
||||
ESP_GOTO_ON_FALSE(xTaskCreate(sniffer_task, "snifferT", CONFIG_SNIFFER_TASK_STACK_SIZE,
|
||||
sniffer, CONFIG_SNIFFER_TASK_PRIORITY, &sniffer->task), ESP_FAIL,
|
||||
err_task, SNIFFER_TAG, "create task failed");
|
||||
err_task, TAG, "create task failed");
|
||||
|
||||
switch (sniffer->interf) {
|
||||
case SNIFFER_INTF_WLAN:
|
||||
@@ -292,20 +305,23 @@ static esp_err_t sniffer_start(sniffer_runtime_t *sniffer)
|
||||
wifi_filter.filter_mask = sniffer->filter;
|
||||
esp_wifi_set_promiscuous_filter(&wifi_filter);
|
||||
esp_wifi_set_promiscuous_rx_cb(wifi_sniffer_cb);
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_promiscuous(true), err_start, SNIFFER_TAG, "set promis failed");
|
||||
//ESP_GOTO_ON_ERROR(esp_wifi_set_channel(sniffer->channel, WIFI_SECOND_CHAN_NONE), err_start, SNIFFER_TAG, "set channel failed");
|
||||
phy_11p_set(1,0);
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_channel(140, WIFI_SECOND_CHAN_NONE), err_start, SNIFFER_TAG, "set channel failed");
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_promiscuous(true), err_start, TAG, "set promis failed");
|
||||
//ESP_GOTO_ON_ERROR(esp_wifi_set_channel(sniffer->channel, WIFI_SECOND_CHAN_NONE), err_start, TAG, "set channel failed");
|
||||
// enable 802.11p mode (enable, unknown (must be 0))
|
||||
phy_11p_set(1, 0);
|
||||
// set a channel with a frequency close to our desired frequency (not sure if strictly needed)
|
||||
ESP_GOTO_ON_ERROR(esp_wifi_set_channel(140, WIFI_SECOND_CHAN_NONE), err_start, TAG, "set channel failed");
|
||||
// switch channel (channel, ignored, ignored, ht_mode?)
|
||||
phy_change_channel(sniffer->channel, 1, 0, 0);
|
||||
ESP_LOGI(SNIFFER_TAG, "start WiFi promiscuous ok");
|
||||
ESP_LOGI(TAG, "start WiFi promiscuous ok");
|
||||
break;
|
||||
case SNIFFER_INTF_ETH:
|
||||
/* Start Ethernet Promiscuous Mode */
|
||||
eth_set_promiscuous = true;
|
||||
ESP_GOTO_ON_ERROR(esp_eth_ioctl(sniffer->eth_handles[sniffer->interf_num], ETH_CMD_S_PROMISCUOUS, ð_set_promiscuous),
|
||||
err_start, SNIFFER_TAG, "start Ethernet promiscuous failed");
|
||||
err_start, TAG, "start Ethernet promiscuous failed");
|
||||
esp_eth_update_input_path(sniffer->eth_handles[sniffer->interf_num], eth_sniffer_cb, NULL);
|
||||
ESP_LOGI(SNIFFER_TAG, "start Ethernet promiscuous ok");
|
||||
ESP_LOGI(TAG, "start Ethernet promiscuous ok");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -342,7 +358,7 @@ esp_err_t sniffer_reg_eth_intf(esp_eth_handle_t eth_handle)
|
||||
while ((snf_rt.eth_handles[i] != NULL) && (i < SNIFFER_MAX_ETH_INTFS)) {
|
||||
i++;
|
||||
}
|
||||
ESP_GOTO_ON_FALSE(i < SNIFFER_MAX_ETH_INTFS, ESP_FAIL, err, SNIFFER_TAG, "maximum num. of eth interfaces registered");
|
||||
ESP_GOTO_ON_FALSE(i < SNIFFER_MAX_ETH_INTFS, ESP_FAIL, err, TAG, "maximum num. of eth interfaces registered");
|
||||
snf_rt.eth_handles[i] = eth_handle;
|
||||
|
||||
err:
|
||||
@@ -380,16 +396,16 @@ static int do_sniffer_cmd(int argc, char **argv)
|
||||
snf_rt.interf = SNIFFER_INTF_ETH;
|
||||
snf_rt.interf_num = eth_intf_num;
|
||||
} else {
|
||||
ESP_LOGE(SNIFFER_TAG, "interface %s not found", sniffer_args.interface->sval[0]);
|
||||
ESP_LOGE(TAG, "interface %s not found", sniffer_args.interface->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(SNIFFER_TAG, "interface %s not found", sniffer_args.interface->sval[0]);
|
||||
ESP_LOGE(TAG, "interface %s not found", sniffer_args.interface->sval[0]);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
snf_rt.interf = SNIFFER_INTF_WLAN;
|
||||
ESP_LOGW(SNIFFER_TAG, "sniffing interface set to wlan by default");
|
||||
ESP_LOGW(TAG, "sniffing interface set to wlan by default");
|
||||
}
|
||||
|
||||
/* Check channel: "-c" option */
|
||||
@@ -402,7 +418,7 @@ static int do_sniffer_cmd(int argc, char **argv)
|
||||
break;
|
||||
case SNIFFER_INTF_ETH:
|
||||
if (sniffer_args.channel->count) {
|
||||
ESP_LOGW(SNIFFER_TAG, "'channel' option is not available for Ethernet");
|
||||
ESP_LOGW(TAG, "'channel' option is not available for Ethernet");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -427,7 +443,7 @@ static int do_sniffer_cmd(int argc, char **argv)
|
||||
break;
|
||||
case SNIFFER_INTF_ETH:
|
||||
if (sniffer_args.filter->count) {
|
||||
ESP_LOGW(SNIFFER_TAG, "'filter' option is not available for Ethernet");
|
||||
ESP_LOGW(TAG, "'filter' option is not available for Ethernet");
|
||||
}
|
||||
default:
|
||||
break;
|
||||
@@ -437,7 +453,7 @@ static int do_sniffer_cmd(int argc, char **argv)
|
||||
snf_rt.packets_to_sniff = -1;
|
||||
if (sniffer_args.number->count) {
|
||||
snf_rt.packets_to_sniff = sniffer_args.number->ival[0];
|
||||
ESP_LOGI(SNIFFER_TAG, "%" PRIi32 " packages will be captured", snf_rt.packets_to_sniff);
|
||||
ESP_LOGI(TAG, "%" PRIi32 " packages will be captured", snf_rt.packets_to_sniff);
|
||||
}
|
||||
|
||||
/* start sniffer */
|
||||
|
||||
@@ -14,6 +14,18 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
void *payload;
|
||||
uint32_t length;
|
||||
uint32_t seconds;
|
||||
uint32_t microseconds;
|
||||
} sniffer_packet_info_t;
|
||||
|
||||
typedef struct {
|
||||
sniffer_packet_info_t info;
|
||||
uint8_t payload[];
|
||||
} sniffer_combined_info_t;
|
||||
|
||||
/**
|
||||
* @brief Supported Sniffer Interface
|
||||
*
|
||||
@@ -42,6 +54,7 @@ typedef enum {
|
||||
void register_sniffer_cmd(void);
|
||||
esp_err_t sniffer_reg_eth_intf(esp_eth_handle_t eth_handle);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+596
@@ -0,0 +1,596 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "esp_console.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
#include "mbedtls/base64.h"
|
||||
#include "nvs.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "argtable3/argtable3.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
static const char TAG[] = "CONFIG";
|
||||
|
||||
static nvs_handle_t handle;
|
||||
|
||||
typedef esp_err_t (*config_u8_getter) (uint8_t *out);
|
||||
typedef esp_err_t (*config_u16_getter) (uint16_t *out);
|
||||
typedef esp_err_t (*config_u32_getter) (uint32_t *out);
|
||||
typedef esp_err_t (*config_u64_getter) (uint64_t *out);
|
||||
typedef esp_err_t (*config_i8_getter) (int8_t *out);
|
||||
typedef esp_err_t (*config_i16_getter) (int16_t *out);
|
||||
typedef esp_err_t (*config_i32_getter) (int32_t *out);
|
||||
typedef esp_err_t (*config_i64_getter) (int64_t *out);
|
||||
typedef esp_err_t (*config_str_getter) (char *out, size_t *size);
|
||||
typedef esp_err_t (*config_blob_getter)(uint8_t *out, size_t *size);
|
||||
|
||||
typedef esp_err_t (*config_u8_setter) (uint8_t val);
|
||||
typedef esp_err_t (*config_u16_setter) (uint16_t val);
|
||||
typedef esp_err_t (*config_u32_setter) (uint32_t val);
|
||||
typedef esp_err_t (*config_u64_setter) (uint64_t val);
|
||||
typedef esp_err_t (*config_i8_setter) (int8_t val);
|
||||
typedef esp_err_t (*config_i16_setter) (int16_t val);
|
||||
typedef esp_err_t (*config_i32_setter) (int32_t val);
|
||||
typedef esp_err_t (*config_i64_setter) (int64_t val);
|
||||
typedef esp_err_t (*config_str_setter) (const char *val);
|
||||
typedef esp_err_t (*config_blob_setter)(const uint8_t *val, size_t size);
|
||||
|
||||
typedef struct config_key {
|
||||
char name[NVS_KEY_NAME_MAX_SIZE];
|
||||
nvs_type_t type;
|
||||
size_t buffer_size;
|
||||
void *getter;
|
||||
void *setter;
|
||||
} config_key_t;
|
||||
|
||||
static esp_err_t config_get_node_id(char *out, size_t *size);
|
||||
|
||||
static const config_key_t config_keys[] = {
|
||||
[CONFIG_INDEX_NODEID] = { "nodeid", NVS_TYPE_STR, CONFIG_NODEID_BUFFER_SIZE, config_get_node_id, NULL },
|
||||
[CONFIG_INDEX_MQTT_URI] = { "mqtturi", NVS_TYPE_STR, CONFIG_MQTT_URI_BUFFER_SIZE, NULL, NULL },
|
||||
};
|
||||
#define CONFIG_KEYS_END (&config_keys[sizeof(config_keys)/sizeof(*config_keys)])
|
||||
|
||||
|
||||
void config_init(void)
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
|
||||
ESP_ERROR_CHECK(nvs_open("its", NVS_READWRITE, &handle));
|
||||
}
|
||||
|
||||
esp_err_t config_get_node_id(char *out, size_t *size)
|
||||
{
|
||||
size_t size_copy = *size;
|
||||
|
||||
esp_err_t res = nvs_get_str(handle, "nodeid", out, &size_copy);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
if (res != ESP_ERR_NVS_NOT_FOUND)
|
||||
ESP_LOGW(TAG, "nvs_get_str failed: %s", esp_err_to_name(res));
|
||||
|
||||
uint8_t base_mac[6];
|
||||
ESP_ERROR_CHECK(esp_base_mac_addr_get(base_mac));
|
||||
|
||||
int print_res = snprintf(out, *size, "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
|
||||
base_mac[0], base_mac[1], base_mac[2], base_mac[3], base_mac[4], base_mac[5]);
|
||||
|
||||
if (print_res > *size - 1)
|
||||
{
|
||||
ESP_LOGE(TAG, "buffer too small to print");
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
|
||||
if (print_res < 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "snprintf failed");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
size_copy = print_res + 1;
|
||||
}
|
||||
|
||||
*size = size_copy;
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t config_get_str(config_index_t index, char *out, size_t *size)
|
||||
{
|
||||
const config_key_t *key = &config_keys[index];
|
||||
|
||||
if (key->type != NVS_TYPE_STR)
|
||||
{
|
||||
ESP_LOGE(TAG, "Attempt to get key %s with wrong type str", key->name);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (key->getter)
|
||||
return ((config_str_getter)key->getter)(out, size);
|
||||
else
|
||||
return nvs_get_str(handle, key->name, out, size);
|
||||
}
|
||||
|
||||
esp_err_t config_set_str(config_index_t index, const char *value)
|
||||
{
|
||||
const config_key_t *key = &config_keys[index];
|
||||
|
||||
if (key->type != NVS_TYPE_STR)
|
||||
{
|
||||
ESP_LOGE(TAG, "Attempt to set key %s with wrong type str", key->name);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (strlen(value) >= key->buffer_size)
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
|
||||
if (key->setter)
|
||||
return ((config_str_setter)key->setter)(value);
|
||||
else
|
||||
return nvs_set_str(handle, key->name, value);
|
||||
}
|
||||
|
||||
static const config_key_t *config_key_find(const char *name)
|
||||
{
|
||||
for (const config_key_t *it = config_keys; it != CONFIG_KEYS_END; it++)
|
||||
{
|
||||
if (strcmp(name, it->name))
|
||||
continue;
|
||||
|
||||
return it;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct {
|
||||
arg_lit_t *raw;
|
||||
arg_str_t *key;
|
||||
arg_str_t *value;
|
||||
arg_end_t *end;
|
||||
} config_set_args;
|
||||
|
||||
static int cmd_config_set(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&config_set_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, config_set_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *key_str = config_set_args.key->sval[0];
|
||||
const char *value_str = config_set_args.value->sval[0];
|
||||
|
||||
const config_key_t *key = config_key_find(key_str);
|
||||
if (key == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "No such config key: %s", key_str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
esp_err_t res;
|
||||
switch (key->type)
|
||||
{
|
||||
case NVS_TYPE_U8:
|
||||
case NVS_TYPE_U16:
|
||||
case NVS_TYPE_U32:
|
||||
case NVS_TYPE_U64:
|
||||
{
|
||||
char *end;
|
||||
uint64_t parsed = strtoull(value_str, &end, 0);
|
||||
if (*end != '\0')
|
||||
{
|
||||
ESP_LOGE(TAG, "Invalid unsigned integer");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((key->type == NVS_TYPE_U8 && parsed > UINT8_MAX) ||
|
||||
(key->type == NVS_TYPE_U16 && parsed > UINT16_MAX) ||
|
||||
(key->type == NVS_TYPE_U32 && parsed > UINT32_MAX))
|
||||
{
|
||||
ESP_LOGE(TAG, "Value out of range for type");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key->setter == NULL || config_set_args.raw->count)
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = nvs_set_u8(handle, key_str, (uint8_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = nvs_set_u16(handle, key_str, (uint16_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = nvs_set_u32(handle, key_str, (uint32_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = nvs_set_u64(handle, key_str, parsed);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = ((config_u8_setter)key->setter)((uint8_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = ((config_u16_setter)key->setter)((uint16_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = ((config_u32_setter)key->setter)((uint32_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = ((config_u64_setter)key->setter)(parsed);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case NVS_TYPE_I8:
|
||||
case NVS_TYPE_I16:
|
||||
case NVS_TYPE_I32:
|
||||
case NVS_TYPE_I64:
|
||||
{
|
||||
char *end;
|
||||
int64_t parsed = strtoll(value_str, &end, 0);
|
||||
if (*end != '\0')
|
||||
{
|
||||
ESP_LOGE(TAG, "Invalid signed integer");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((key->type == NVS_TYPE_I8 && (parsed < INT8_MIN || parsed > INT8_MAX)) ||
|
||||
(key->type == NVS_TYPE_I16 && (parsed < INT16_MIN || parsed > INT16_MAX)) ||
|
||||
(key->type == NVS_TYPE_I32 && (parsed < INT32_MIN || parsed > INT32_MAX)))
|
||||
{
|
||||
ESP_LOGE(TAG, "Value out of range for type");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key->setter == NULL || config_set_args.raw->count)
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = nvs_set_i8(handle, key_str, (int8_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = nvs_set_i16(handle, key_str, (int16_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = nvs_set_i32(handle, key_str, (int32_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = nvs_set_i64(handle, key_str, parsed);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = ((config_i8_setter)key->setter)((int8_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = ((config_i16_setter)key->setter)((int16_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = ((config_i32_setter)key->setter)((int32_t)parsed);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = ((config_i64_setter)key->setter)(parsed);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case NVS_TYPE_STR:
|
||||
if (strlen(value_str) >= key->buffer_size)
|
||||
{
|
||||
ESP_LOGE(TAG, "Value too long");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key->setter == NULL || config_set_args.raw->count)
|
||||
res = nvs_set_str(handle, key_str, value_str);
|
||||
else
|
||||
res = ((config_str_setter)key->setter)(value_str);
|
||||
break;
|
||||
case NVS_TYPE_BLOB:
|
||||
{
|
||||
unsigned char *buf = malloc(key->buffer_size);
|
||||
size_t olen;
|
||||
int result = mbedtls_base64_decode(buf, key->buffer_size, &olen, (const uint8_t *)value_str, strlen(value_str));
|
||||
if (result != 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "mbedtls_base64_decode failed: %#x", result);
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (olen > key->buffer_size)
|
||||
{
|
||||
ESP_LOGE(TAG, "Value too long");
|
||||
free(buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (key->setter == NULL || config_set_args.raw->count)
|
||||
res = nvs_set_blob(handle, key_str, buf, olen);
|
||||
else
|
||||
res = ((config_blob_setter)key->setter)(buf, olen);
|
||||
free(buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
// avoid compiler warning
|
||||
res = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "set failed: %s", esp_err_to_name(res));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void register_config_set(void)
|
||||
{
|
||||
config_set_args.raw = arg_lit0("R", NULL, "skip setter functions, directly write NVS");
|
||||
config_set_args.key = arg_str1(NULL, NULL, "key", "the key");
|
||||
config_set_args.value = arg_str1(NULL, NULL, "value", "the value to set");
|
||||
config_set_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "config_set",
|
||||
.help = "set a config key",
|
||||
.hint = NULL,
|
||||
.func = &cmd_config_set,
|
||||
.argtable = &config_set_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
static struct {
|
||||
arg_lit_t *raw;
|
||||
arg_str_t *key;
|
||||
arg_end_t *end;
|
||||
} config_get_args;
|
||||
|
||||
static int cmd_config_get(int argc, char **argv)
|
||||
{
|
||||
int nerrors = arg_parse(argc, argv, (void **)&config_get_args);
|
||||
if (nerrors != 0) {
|
||||
arg_print_errors(stderr, config_get_args.end, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *key_str = config_get_args.key->sval[0];
|
||||
|
||||
const config_key_t *key = config_key_find(key_str);
|
||||
if (key == NULL)
|
||||
{
|
||||
ESP_LOGE(TAG, "No such config key: %s", key_str);
|
||||
return 1;
|
||||
}
|
||||
|
||||
esp_err_t res;
|
||||
|
||||
switch (key->type)
|
||||
{
|
||||
case NVS_TYPE_U8:
|
||||
case NVS_TYPE_U16:
|
||||
case NVS_TYPE_U32:
|
||||
case NVS_TYPE_U64:
|
||||
{
|
||||
uint64_t value = 0;
|
||||
|
||||
if (key->getter == NULL || config_get_args.raw->count)
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = nvs_get_u8(handle, key_str, (uint8_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = nvs_get_u16(handle, key_str, (uint16_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = nvs_get_u32(handle, key_str, (uint32_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = nvs_get_u64(handle, key_str, &value);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_U8:
|
||||
res = ((config_u8_getter)key->getter)((uint8_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U16:
|
||||
res = ((config_u16_getter)key->getter)((uint16_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U32:
|
||||
res = ((config_u32_getter)key->getter)((uint32_t *)&value);
|
||||
break;
|
||||
case NVS_TYPE_U64:
|
||||
res = ((config_u64_getter)key->getter)(&value);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
if (res == ESP_OK)
|
||||
printf("%"PRIu64 "\n", value);
|
||||
}
|
||||
|
||||
break;
|
||||
case NVS_TYPE_I8:
|
||||
case NVS_TYPE_I16:
|
||||
case NVS_TYPE_I32:
|
||||
case NVS_TYPE_I64:
|
||||
{
|
||||
int64_t value = 0;
|
||||
|
||||
if (key->getter == NULL || config_get_args.raw->count)
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_I8:
|
||||
res = nvs_get_i8(handle, key_str, (int8_t *)&value);
|
||||
value = (int64_t)(int8_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I16:
|
||||
res = nvs_get_i16(handle, key_str, (int16_t *)&value);
|
||||
value = (int64_t)(int16_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I32:
|
||||
res = nvs_get_i32(handle, key_str, (int32_t *)&value);
|
||||
value = (int64_t)(int32_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I64:
|
||||
res = nvs_get_i64(handle, key_str, &value);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (key->type) {
|
||||
case NVS_TYPE_I8:
|
||||
res = ((config_i8_getter)key->getter)((int8_t *)&value);
|
||||
value = (int64_t)(int8_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I16:
|
||||
res = ((config_i16_getter)key->getter)((int16_t *)&value);
|
||||
value = (int64_t)(int16_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I32:
|
||||
res = ((config_i32_getter)key->getter)((int32_t *)&value);
|
||||
value = (int64_t)(int32_t)value;
|
||||
break;
|
||||
case NVS_TYPE_I64:
|
||||
res = ((config_i64_getter)key->getter)(&value);
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
if (res == ESP_OK)
|
||||
printf("%"PRIi64 "\n", value);
|
||||
}
|
||||
|
||||
break;
|
||||
case NVS_TYPE_STR:
|
||||
char *value = malloc(key->buffer_size);
|
||||
size_t size = key->buffer_size;
|
||||
|
||||
if (key->getter == NULL || config_get_args.raw->count)
|
||||
res = nvs_get_str(handle, key_str, value, &size);
|
||||
else
|
||||
res = ((config_str_getter)key->getter)(value, &size);
|
||||
|
||||
if (res == ESP_OK)
|
||||
printf("%s\n", value);
|
||||
|
||||
free(value);
|
||||
break;
|
||||
case NVS_TYPE_BLOB:
|
||||
{
|
||||
unsigned char *buf = malloc(key->buffer_size);
|
||||
size_t actual_size;
|
||||
|
||||
if (key->getter == NULL || config_get_args.raw->count)
|
||||
res = nvs_get_blob(handle, key_str, buf, &actual_size);
|
||||
else
|
||||
res = ((config_blob_getter)key->getter)(buf, &actual_size);
|
||||
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
free(buf);
|
||||
break;
|
||||
}
|
||||
|
||||
const size_t base64_buffer_size = (((4 * key->buffer_size / 3) + 3) & ~3) + 1;
|
||||
unsigned char *base64_buf = malloc(base64_buffer_size);
|
||||
size_t olen;
|
||||
int result = mbedtls_base64_encode(base64_buf, base64_buffer_size, &olen, (const uint8_t *)buf, actual_size);
|
||||
if (result != 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "mbedtls_base64_encode failed: %#x", result);
|
||||
free(buf);
|
||||
free(base64_buf);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s\n", base64_buf);
|
||||
free(buf);
|
||||
free(base64_buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
__builtin_unreachable();
|
||||
// avoid compiler warning
|
||||
res = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "get failed: %s", esp_err_to_name(res));
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void register_config_get(void)
|
||||
{
|
||||
config_get_args.raw = arg_lit0("R", NULL, "skip getter functions, directly read NVS");
|
||||
config_get_args.key = arg_str1(NULL, NULL, "key", "the key");
|
||||
config_get_args.end = arg_end(1);
|
||||
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "config_get",
|
||||
.help = "get a config key",
|
||||
.hint = NULL,
|
||||
.func = &cmd_config_get,
|
||||
.argtable = &config_get_args
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void config_register_commands(void)
|
||||
{
|
||||
register_config_set();
|
||||
register_config_get();
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#define CONFIG_NODEID_BUFFER_SIZE 64
|
||||
#define CONFIG_MQTT_URI_BUFFER_SIZE 256
|
||||
|
||||
void config_init(void);
|
||||
|
||||
typedef enum {
|
||||
CONFIG_INDEX_NODEID,
|
||||
CONFIG_INDEX_MQTT_URI,
|
||||
} config_index_t;
|
||||
|
||||
esp_err_t config_get_str(config_index_t index, char *out, size_t *size);
|
||||
esp_err_t config_set_str(config_index_t index, const char *value);
|
||||
|
||||
|
||||
void config_register_commands(void);
|
||||
+50
-13
@@ -10,6 +10,7 @@
|
||||
#include "lwip/netif.h"
|
||||
|
||||
#include "cmd_sniffer.h"
|
||||
#include "events.h"
|
||||
|
||||
#include "ethernet.h"
|
||||
|
||||
@@ -18,6 +19,9 @@
|
||||
|
||||
static const char TAG[] = "ETHERNET";
|
||||
|
||||
static esp_netif_t *mgmt_netif;
|
||||
static esp_eth_handle_t mgmt_eth;
|
||||
|
||||
/** Event handler for Ethernet events */
|
||||
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
@@ -33,15 +37,20 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
|
||||
break;
|
||||
case ETHERNET_EVENT_DISCONNECTED:
|
||||
printf("\n");
|
||||
ESP_LOGI(TAG, "Ethernet link down");
|
||||
if (eth_handle == mgmt_eth)
|
||||
{
|
||||
esp_err_t post_res = esp_event_post(APP_EVENT_BASE, APP_ETHERNET_MGMT_INTERFACE_DISCONNECTED, NULL, 0, 0);
|
||||
if (post_res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_event_post failed: %s", esp_err_to_name(post_res));
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETHERNET_EVENT_START:
|
||||
printf("\n");
|
||||
ESP_LOGI(TAG, "Ethernet started");
|
||||
break;
|
||||
case ETHERNET_EVENT_STOP:
|
||||
printf("\n");
|
||||
ESP_LOGI(TAG, "Ethernet stopped");
|
||||
break;
|
||||
default:
|
||||
@@ -53,23 +62,48 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
static void ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data)
|
||||
{
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||
|
||||
char ifname[NETIF_NAMESIZE] = {0};
|
||||
esp_err_t res = esp_netif_get_netif_impl_name(event->esp_netif, ifname);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to get netif name: %s", esp_err_to_name(res));
|
||||
strcpy(ifname, "unk");
|
||||
}
|
||||
|
||||
switch (event_id) {
|
||||
case IP_EVENT_ETH_GOT_IP:
|
||||
{
|
||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||
|
||||
char ifname[NETIF_NAMESIZE] = {0};
|
||||
esp_err_t res = esp_netif_get_netif_impl_name(event->esp_netif, ifname);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Failed to get netif name: %s", esp_err_to_name(res));
|
||||
strcpy(ifname, "unk");
|
||||
}
|
||||
|
||||
const esp_netif_ip_info_t *ip_info = &event->ip_info;
|
||||
ESP_LOGI(TAG, "Ethernet %s got IP: " IPSTR " netmask: " IPSTR " gw: " IPSTR, ifname, IP2STR(&ip_info->ip), IP2STR(&ip_info->netmask), IP2STR(&ip_info->gw));
|
||||
|
||||
// If this is the management netif, post an event to start MQTT etc.
|
||||
if (event->esp_netif == mgmt_netif)
|
||||
{
|
||||
esp_err_t post_res = esp_event_post(APP_EVENT_BASE, APP_ETHERNET_MGMT_INTERFACE_CONNECTED, NULL, 0, 0);
|
||||
if (post_res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_event_post failed: %s", esp_err_to_name(post_res));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IP_EVENT_ETH_LOST_IP:
|
||||
{
|
||||
ESP_LOGI(TAG, "Ethernet %s lost IP", ifname);
|
||||
|
||||
// If this is the management netif, post an event to start MQTT etc.
|
||||
if (event->esp_netif == mgmt_netif)
|
||||
{
|
||||
esp_err_t post_res = esp_event_post(APP_EVENT_BASE, APP_ETHERNET_MGMT_INTERFACE_DISCONNECTED, NULL, 0, 0);
|
||||
if (post_res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_event_post failed: %s", esp_err_to_name(post_res));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -109,6 +143,9 @@ void initialize_ethernet(void)
|
||||
cfg.base = &esp_netif_config;
|
||||
esp_netif_t *eth_netif = esp_netif_new(&cfg);
|
||||
|
||||
mgmt_netif = eth_netif;
|
||||
mgmt_eth = eth_handles[i];
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i])));
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_event.h"
|
||||
|
||||
#include "events.h"
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(APP_EVENT_BASE);
|
||||
|
||||
ESP_EVENT_DEFINE_BASE(SNIFFER_EVENT_BASE);
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "esp_event.h"
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(APP_EVENT_BASE);
|
||||
|
||||
enum AppEvent
|
||||
{
|
||||
APP_ETHERNET_MGMT_INTERFACE_CONNECTED,
|
||||
APP_ETHERNET_MGMT_INTERFACE_DISCONNECTED
|
||||
};
|
||||
|
||||
|
||||
ESP_EVENT_DECLARE_BASE(SNIFFER_EVENT_BASE);
|
||||
|
||||
enum SnifferEvent
|
||||
{
|
||||
SNIFFER_GOT_FRAME
|
||||
};
|
||||
@@ -2,3 +2,5 @@ dependencies:
|
||||
pcap: "^1.0.0"
|
||||
espressif/ethernet_init:
|
||||
version: "~1.3.0"
|
||||
espressif/mqtt:
|
||||
version: "~1.0.0"
|
||||
|
||||
+63
-25
@@ -14,7 +14,9 @@
|
||||
|
||||
#include "cmd_sniffer.h"
|
||||
#include "cmd_pcap.h"
|
||||
#include "config.h"
|
||||
#include "ethernet.h"
|
||||
#include "mqtt.h"
|
||||
#include "sdcard.h"
|
||||
#include "spi.h"
|
||||
|
||||
@@ -40,16 +42,6 @@ static void initialize_filesystem(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void initialize_nvs(void)
|
||||
{
|
||||
esp_err_t err = nvs_flash_init();
|
||||
if (err == ESP_ERR_NVS_NO_FREE_PAGES || err == ESP_ERR_NVS_NEW_VERSION_FOUND) {
|
||||
ESP_ERROR_CHECK(nvs_flash_erase());
|
||||
err = nvs_flash_init();
|
||||
}
|
||||
ESP_ERROR_CHECK(err);
|
||||
}
|
||||
|
||||
/* Initialize wifi with tcp/ip adapter */
|
||||
static void initialize_wifi(void)
|
||||
{
|
||||
@@ -59,27 +51,26 @@ static void initialize_wifi(void)
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_NULL));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
static esp_console_repl_t *repl;
|
||||
static void console_init(void)
|
||||
{
|
||||
initialize_nvs();
|
||||
initialize_filesystem();
|
||||
// 31 buffer size - length of colors and 1 space after prompt - 1 closing angle bracket - 1 null byte
|
||||
const size_t max_nodeid_length = 31 - (sizeof(LOG_COLOR_I " " LOG_RESET_COLOR) - 1) - 1 - 1;
|
||||
|
||||
initialize_spi();
|
||||
char prompt[CONFIG_NODEID_BUFFER_SIZE];
|
||||
size_t size = sizeof(prompt);
|
||||
ESP_ERROR_CHECK(config_get_str(CONFIG_INDEX_NODEID, prompt, &size));
|
||||
|
||||
/*--- Initialize Network ---*/
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
/* Initialize WiFi */
|
||||
initialize_wifi();
|
||||
/* Initialize Ethernet */
|
||||
initialize_ethernet();
|
||||
if (size - 1 > max_nodeid_length)
|
||||
strcpy(&prompt[max_nodeid_length - 3], "...");
|
||||
|
||||
strcat(prompt, ">");
|
||||
|
||||
/*--- Initialize Console ---*/
|
||||
esp_console_repl_t *repl = NULL;
|
||||
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
|
||||
#if CONFIG_SNIFFER_STORE_HISTORY
|
||||
repl_config.history_save_path = HISTORY_FILE_PATH;
|
||||
#endif
|
||||
repl_config.prompt = "cli>";
|
||||
repl_config.prompt = prompt;
|
||||
|
||||
// install console REPL environment
|
||||
#if CONFIG_ESP_CONSOLE_UART
|
||||
@@ -92,15 +83,62 @@ void app_main(void)
|
||||
esp_console_dev_usb_serial_jtag_config_t usbjtag_config = ESP_CONSOLE_DEV_USB_SERIAL_JTAG_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_console_new_repl_usb_serial_jtag(&usbjtag_config, &repl_config, &repl));
|
||||
#endif
|
||||
}
|
||||
|
||||
int cmd_reboot(int argc, char **argv)
|
||||
{
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
esp_restart();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void register_reboot(void)
|
||||
{
|
||||
const esp_console_cmd_t cmd = {
|
||||
.command = "reboot",
|
||||
.help = "reboot the device",
|
||||
.hint = NULL,
|
||||
.func = &cmd_reboot,
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
config_init();
|
||||
|
||||
initialize_filesystem();
|
||||
|
||||
initialize_spi();
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
// Make sure MQTT has registered its event handlers before Ethernet goes up
|
||||
mqtt_init();
|
||||
|
||||
/*--- Initialize Network ---*/
|
||||
/* Initialize WiFi */
|
||||
initialize_wifi();
|
||||
/* Initialize Ethernet */
|
||||
initialize_ethernet();
|
||||
|
||||
/*--- Initialize Console ---*/
|
||||
console_init();
|
||||
|
||||
/* Register commands */
|
||||
#if CONFIG_ENABLE_SD
|
||||
register_mount();
|
||||
register_unmount();
|
||||
sdcard_register_commands();
|
||||
#endif
|
||||
register_sniffer_cmd();
|
||||
register_pcap_cmd();
|
||||
|
||||
config_register_commands();
|
||||
|
||||
register_reboot();
|
||||
|
||||
// start console REPL
|
||||
ESP_ERROR_CHECK(esp_console_start_repl(repl));
|
||||
}
|
||||
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
|
||||
#include "cmd_sniffer.h"
|
||||
#include "config.h"
|
||||
#include "events.h"
|
||||
|
||||
#include "mqtt.h"
|
||||
|
||||
static const char TAG[] = "MQTT";
|
||||
|
||||
static esp_mqtt_client_handle_t client;
|
||||
|
||||
static char topic_prefix[96];
|
||||
static char command_topic[128];
|
||||
static char packet_topic[128];
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
|
||||
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||||
|
||||
esp_mqtt_event_handle_t event = event_data;
|
||||
esp_mqtt_client_handle_t client = event->client;
|
||||
int msg_id;
|
||||
// your_context_t *context = event->context;
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
|
||||
msg_id = esp_mqtt_client_subscribe(client, command_topic, 0);
|
||||
ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
break;
|
||||
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_DATA");
|
||||
printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
printf("DATA=%.*s\r\n", event->data_len, event->data);
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
|
||||
if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
|
||||
ESP_LOGI(TAG, "Last error code reported from esp-tls: 0x%x", event->error_handle->esp_tls_last_esp_err);
|
||||
ESP_LOGI(TAG, "Last tls stack error number: 0x%x", event->error_handle->esp_tls_stack_err);
|
||||
ESP_LOGI(TAG, "Last captured errno : %d (%s)", event->error_handle->esp_transport_sock_errno,
|
||||
strerror(event->error_handle->esp_transport_sock_errno));
|
||||
} else if (event->error_handle->error_type == MQTT_ERROR_TYPE_CONNECTION_REFUSED) {
|
||||
ESP_LOGI(TAG, "Connection refused error: 0x%x", event->error_handle->connect_return_code);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Unknown error type: 0x%x", event->error_handle->error_type);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static int make_topic_prefix()
|
||||
{
|
||||
size_t size = sizeof(topic_prefix);
|
||||
strcpy(topic_prefix, "its/");
|
||||
size -= 4;
|
||||
|
||||
esp_err_t res = config_get_str(CONFIG_INDEX_NODEID, topic_prefix + 4, &size);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Could not get node ID from config: %s", esp_err_to_name(res));
|
||||
return res;
|
||||
}
|
||||
|
||||
topic_prefix[4 + size - 1] = '/';
|
||||
topic_prefix[4 + size] = '\0';
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void mqtt_start(void)
|
||||
{
|
||||
if (client)
|
||||
{
|
||||
ESP_LOGW(TAG, "MQTT already started");
|
||||
return;
|
||||
}
|
||||
|
||||
make_topic_prefix();
|
||||
|
||||
strcpy(command_topic, topic_prefix);
|
||||
strcat(command_topic, "command");
|
||||
|
||||
strcpy(packet_topic, topic_prefix);
|
||||
strcat(packet_topic, "packet");
|
||||
|
||||
esp_mqtt_client_config_t mqtt_cfg = {0};
|
||||
|
||||
char mqtt_uri[CONFIG_MQTT_URI_BUFFER_SIZE];
|
||||
size_t size = sizeof(mqtt_uri);
|
||||
esp_err_t res = config_get_str(CONFIG_INDEX_MQTT_URI, mqtt_uri, &size);
|
||||
if (res != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "Could not get MQTT URI from config: %s", esp_err_to_name(res));
|
||||
return;
|
||||
}
|
||||
|
||||
mqtt_cfg.broker.address.uri = mqtt_uri;
|
||||
|
||||
esp_mqtt_client_handle_t client_ = esp_mqtt_client_init(&mqtt_cfg);
|
||||
esp_mqtt_client_register_event(client_, ESP_EVENT_ANY_ID, mqtt_event_handler, client_);
|
||||
esp_mqtt_client_start(client_);
|
||||
|
||||
client = client_;
|
||||
ESP_LOGI(TAG, "MQTT started");
|
||||
}
|
||||
|
||||
void mqtt_stop(void)
|
||||
{
|
||||
if (!client)
|
||||
{
|
||||
ESP_LOGW(TAG, "Attempted to stop MQTT while not running");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_mqtt_client_stop(client);
|
||||
|
||||
esp_mqtt_client_handle_t client_ = client;
|
||||
client = NULL;
|
||||
esp_mqtt_client_destroy(client_);
|
||||
ESP_LOGI(TAG, "MQTT stopped");
|
||||
}
|
||||
|
||||
static void app_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
switch (event_id)
|
||||
{
|
||||
case APP_ETHERNET_MGMT_INTERFACE_CONNECTED:
|
||||
mqtt_start();
|
||||
break;
|
||||
case APP_ETHERNET_MGMT_INTERFACE_DISCONNECTED:
|
||||
mqtt_stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void sniffer_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||
{
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
switch (event_id)
|
||||
{
|
||||
case SNIFFER_GOT_FRAME:
|
||||
sniffer_combined_info_t *info = event_data;
|
||||
esp_mqtt_client_publish(client, packet_topic, (const char *)info->payload, info->info.length, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void mqtt_init(void)
|
||||
{
|
||||
esp_event_handler_register(APP_EVENT_BASE, ESP_EVENT_ANY_ID, app_event_handler, NULL);
|
||||
esp_event_handler_register(SNIFFER_EVENT_BASE, ESP_EVENT_ANY_ID, sniffer_event_handler, NULL);
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void mqtt_init(void);
|
||||
@@ -139,4 +139,11 @@ void register_unmount(void)
|
||||
};
|
||||
ESP_ERROR_CHECK(esp_console_cmd_register(&cmd));
|
||||
}
|
||||
|
||||
void sdcard_register_commands(void)
|
||||
{
|
||||
register_mount();
|
||||
register_unmount();
|
||||
}
|
||||
|
||||
#endif // CONFIG_ENABLE_SD
|
||||
|
||||
+1
-2
@@ -1,4 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
void register_mount(void);
|
||||
void register_unmount(void);
|
||||
void sdcard_register_commands(void);
|
||||
|
||||
@@ -2404,7 +2404,9 @@ CONFIG_ESP_TIMER_IMPL_SYSTIMER=y
|
||||
#
|
||||
# ESP Trace Configuration
|
||||
#
|
||||
# default:
|
||||
# CONFIG_ESP_TRACE_LIB_EXTERNAL is not set
|
||||
# default:
|
||||
CONFIG_ESP_TRACE_LIB_NONE=y
|
||||
# default:
|
||||
CONFIG_ESP_TRACE_LIB_NAME="none"
|
||||
@@ -3986,6 +3988,33 @@ CONFIG_WL_SECTOR_SIZE_4096=y
|
||||
# default:
|
||||
CONFIG_WL_SECTOR_SIZE=4096
|
||||
# end of Wear Levelling
|
||||
|
||||
#
|
||||
# ESP-MQTT Configurations
|
||||
#
|
||||
# default:
|
||||
CONFIG_MQTT_PROTOCOL_311=y
|
||||
# default:
|
||||
# CONFIG_MQTT_PROTOCOL_5 is not set
|
||||
# default:
|
||||
CONFIG_MQTT_TRANSPORT_SSL=y
|
||||
# default:
|
||||
CONFIG_MQTT_TRANSPORT_WEBSOCKET=y
|
||||
# default:
|
||||
CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y
|
||||
# default:
|
||||
# CONFIG_MQTT_MSG_ID_INCREMENTAL is not set
|
||||
# default:
|
||||
# CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED is not set
|
||||
# default:
|
||||
# CONFIG_MQTT_REPORT_DELETED_MESSAGES is not set
|
||||
# default:
|
||||
# CONFIG_MQTT_USE_CUSTOM_CONFIG is not set
|
||||
# default:
|
||||
# CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED is not set
|
||||
# default:
|
||||
# CONFIG_MQTT_CUSTOM_OUTBOX is not set
|
||||
# end of ESP-MQTT Configurations
|
||||
# end of Component config
|
||||
|
||||
# default:
|
||||
|
||||
Reference in New Issue
Block a user