#include "protocol.h" #include "uart_handler.h" #include "event_reporter.h" #include "cmd_dispatcher.h" #include "nvs_flash.h" #include "esp_system.h" #include "esp_chip_info.h" #include "esp_timer.h" #include "esp_log.h" #include "esp_mac.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "cJSON.h" #include #include #define FW_VERSION "0.1.0" static const char *TAG = "main"; static void send_boot_event(void) { esp_chip_info_t chip; esp_chip_info(&chip); const char *model; switch (chip.model) { case CHIP_ESP32: model = "ESP32"; break; case CHIP_ESP32S2: model = "ESP32-S2"; break; case CHIP_ESP32S3: model = "ESP32-S3"; break; case CHIP_ESP32C3: model = "ESP32-C3"; break; case CHIP_ESP32H2: model = "ESP32-H2"; break; default: model = "unknown"; break; } cJSON *data = cJSON_CreateObject(); cJSON_AddStringToObject(data, "fw_version", FW_VERSION); cJSON_AddStringToObject(data, "chip_model", model); cJSON_AddNumberToObject(data, "cores", chip.cores); cJSON_AddNumberToObject(data, "revision", chip.revision); cJSON_AddNumberToObject(data, "free_heap", (double)esp_get_free_heap_size()); uart_send_event(EVT_BOOT, data); } void app_main(void) { /* NVS -- needed for Bluetooth bonding storage */ esp_err_t ret = nvs_flash_init(); if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) { ESP_LOGW(TAG, "NVS partition issue, erasing and re-initializing"); ESP_ERROR_CHECK(nvs_flash_erase()); ESP_ERROR_CHECK(nvs_flash_init()); } else { ESP_ERROR_CHECK(ret); } uart_handler_init(); event_reporter_init(); send_boot_event(); cmd_dispatcher_init(); ESP_LOGI(TAG, "mcbluetooth-esp32 v%s ready", FW_VERSION); /* Main command loop */ for (;;) { char *line = uart_read_line(); if (!line) { continue; } cJSON *root = cJSON_Parse(line); if (!root) { ESP_LOGE(TAG, "bad JSON: %.64s", line); /* best-effort error -- no id available */ uart_send_response("?", STATUS_ERROR, cJSON_CreateString("invalid JSON")); free(line); continue; } const cJSON *j_id = cJSON_GetObjectItem(root, "id"); const cJSON *j_cmd = cJSON_GetObjectItem(root, "cmd"); cJSON *j_params = cJSON_GetObjectItem(root, "params"); const char *id = cJSON_IsString(j_id) ? j_id->valuestring : "?"; const char *cmd = cJSON_IsString(j_cmd) ? j_cmd->valuestring : NULL; if (!cmd) { ESP_LOGE(TAG, "missing 'cmd' field"); uart_send_response(id, STATUS_ERROR, cJSON_CreateString("missing 'cmd' field")); } else { cmd_dispatch(id, cmd, j_params); } cJSON_Delete(root); free(line); } }