From 51877aa7410daa5c0d346c00f3399b06e577c74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 15 Jan 2023 20:28:47 +0100 Subject: [PATCH] refactoring and add mqtt --- Makefile | 2 +- main/CMakeLists.txt | 4 ++ main/NVS.txt | 9 ++++ main/cmd_decl.h | 2 + main/cmd_ip.c | 127 +++++++++++++++++++++++++++++++++++++++++++ main/cmd_ip.h | 12 +++++ main/cmd_mqtt.c | 70 ++++++++++++++++++++++++ main/cmd_mqtt.h | 12 +++++ main/cmd_wifi.c | 122 ++++++++++------------------------------- main/cmd_wifi.h | 8 --- main/meteo_main.c | 38 ++++++------- main/meteo_task.c | 67 ++++++++++++++++++++--- main/mqttpub.c | 128 ++++++++++++++++++++++++++++++++++++++++++++ main/mqttpub.h | 9 ++++ main/nvsconfig.c | 125 ++++++++++++++++++++++++++++++++++++++++++ main/nvsconfig.h | 7 +++ sdkconfig | 8 +-- sdkconfig.old | 14 ++--- 18 files changed, 620 insertions(+), 144 deletions(-) create mode 100644 main/NVS.txt create mode 100644 main/cmd_ip.c create mode 100644 main/cmd_ip.h create mode 100644 main/cmd_mqtt.c create mode 100644 main/cmd_mqtt.h create mode 100644 main/mqttpub.c create mode 100644 main/mqttpub.h create mode 100644 main/nvsconfig.c create mode 100644 main/nvsconfig.h diff --git a/Makefile b/Makefile index 03826de..6dacfb4 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ # project subdirectory. # -DUMMY_VAR = 1 +DUMMY_VAR = 2 PROJECT_NAME := meteo include $(IDF_PATH)/make/project.mk diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index a2fc61a..288cc5e 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -1,4 +1,8 @@ set(COMPONENT_SRCS "cmd_wifi.c" + "cmd_ip.c" + "cmd_mqtt.c" + "mqttpub.c" + "nvsconfig.c" "meteo_task.c" "meteo_main.c") set(COMPONENT_ADD_INCLUDEDIRS ".") diff --git a/main/NVS.txt b/main/NVS.txt new file mode 100644 index 0000000..15a24c7 --- /dev/null +++ b/main/NVS.txt @@ -0,0 +1,9 @@ +wifi.use_dhcpc - int 0/1 - use dynamic IP +wifi.static_ip - str +wifi.static_gw - str +wifi.static_mask - str + +mqtt.topic - str, base topic, ends with slash +mqtt.broker - str, mqtt broker + +/* wifi ssid/pw are stored in system nvs */ diff --git a/main/cmd_decl.h b/main/cmd_decl.h index efdda4e..618f693 100644 --- a/main/cmd_decl.h +++ b/main/cmd_decl.h @@ -14,6 +14,8 @@ extern "C" { #include "cmd_system.h" #include "cmd_wifi.h" +#include "cmd_ip.h" +#include "cmd_mqtt.h" #ifdef __cplusplus } diff --git a/main/cmd_ip.c b/main/cmd_ip.c new file mode 100644 index 0000000..afdc43c --- /dev/null +++ b/main/cmd_ip.c @@ -0,0 +1,127 @@ +/* Console example — WiFi commands + + This example code is in the Public Domain (or CC0 licensed, at your option.) + + 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 +#include +#include "esp_log.h" +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "esp_event_loop.h" +#include "cmd_ip.h" + +#include "nvs.h" + +/** Arguments used by 'join' function */ +static struct { + struct arg_lit *dhcp_on; + struct arg_lit *dhcp_off; + struct arg_str *static_ip; + struct arg_str *static_gw; + struct arg_str *static_mask; + struct arg_str *static_dns1; + struct arg_str *static_dns2; + struct arg_end *end; +} ip_args; + +static int ipcmd(int argc, char** argv) +{ + esp_err_t rv; + + int nerrors = arg_parse(argc, argv, (void**) &ip_args); + if (nerrors != 0) { + arg_print_errors(stderr, ip_args.end, argv[0]); + return 1; + } + + nvs_handle_t hnvs; + ESP_ERROR_CHECK( nvs_open("wifi", NVS_READWRITE, &hnvs) ); + + if (ip_args.dhcp_on->count) { + nvs_set_u8(hnvs, "use_dhcpc", 1); + } else if (ip_args.dhcp_off->count) { + nvs_set_u8(hnvs, "use_dhcpc", 0); + } + + if (ip_args.static_ip->count) { + nvs_set_str(hnvs, "static_ip", ip_args.static_ip->sval[0]); + } + + if (ip_args.static_gw->count) { + nvs_set_str(hnvs, "static_gw", ip_args.static_gw->sval[0]); + } + + if (ip_args.static_mask->count) { + nvs_set_str(hnvs, "static_mask", ip_args.static_mask->sval[0]); + } + + if (ip_args.static_dns1->count) { + nvs_set_str(hnvs, "static_dns1", ip_args.static_dns1->sval[0]); + } + + if (ip_args.static_dns2->count) { + nvs_set_str(hnvs, "static_dns2", ip_args.static_dns2->sval[0]); + } + + // read current config + + uint8_t use_dhcpc; + rv = nvs_get_u8(hnvs, "use_dhcpc", &use_dhcpc); + if (rv != ESP_OK) { + use_dhcpc = 1; + } + + char ip[16], gw[16], mask[16], dns1[16], dns2[16]; + size_t iplen = 16; + size_t gwlen = 16; + size_t masklen = 16; + size_t dns1len = 16; + size_t dns2len = 16; + ip[0] = gw[0] = mask[0] = dns1[0] = dns2[0] = 0; + + nvs_get_str(hnvs, "static_ip", ip, &iplen); + nvs_get_str(hnvs, "static_gw", gw, &gwlen); + nvs_get_str(hnvs, "static_mask", mask, &masklen); + nvs_get_str(hnvs, "static_dns1", dns1, &dns1len); + nvs_get_str(hnvs, "static_dns2", dns2, &dns2len); + + printf("DHCP = %s\n", use_dhcpc ? "Yes (dynamic IP)" : "No (static IP)"); + printf("Saved static IP = %s\n", ip); + printf("Saved static GW = %s\n", gw); + printf("Saved static MASK = %s\n", mask); + printf("Saved static DNS1 = %s\n", dns1); + printf("Saved static DNS2 = %s\n", dns2); + + nvs_close(hnvs); + + printf("Any changes are applied after restart.\n"); + + return 0; +} + +void console_register_ip() +{ + ip_args.dhcp_on = arg_lit0("d", "dynamic", "Enable DHCP"); + ip_args.dhcp_off = arg_lit0("s", "static", "Disable DHCP (use static)"); + ip_args.static_ip = arg_str0("a", "ip", "", "Set static IP"); + ip_args.static_gw = arg_str0("g", "gw", "", "Set static GW"); + ip_args.static_mask = arg_str0("m", "mask", "", "Set static MASK (e.g. 255.255.255.0)"); + ip_args.static_dns1 = arg_str0("n", "dns1", "", "Set static nameserver1 (e.g. 8.8.8.8)"); + ip_args.static_dns2 = arg_str0("N", "dns2", "", "Set static nameserver2 (e.g. 8.8.4.4)"); + ip_args.end = arg_end(5); + + const esp_console_cmd_t ip_cmd = { + .command = "ip", + .help = "Configure TCP/IP", + .hint = NULL, + .func = &ipcmd, + .argtable = &ip_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&ip_cmd) ); +} diff --git a/main/cmd_ip.h b/main/cmd_ip.h new file mode 100644 index 0000000..bd814f6 --- /dev/null +++ b/main/cmd_ip.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void console_register_ip(); + +#ifdef __cplusplus +} +#endif + diff --git a/main/cmd_mqtt.c b/main/cmd_mqtt.c new file mode 100644 index 0000000..7b3b9e6 --- /dev/null +++ b/main/cmd_mqtt.c @@ -0,0 +1,70 @@ +#include +#include +#include "esp_log.h" +#include "esp_console.h" +#include "argtable3/argtable3.h" +#include "esp_event_loop.h" +#include "cmd_mqtt.h" + +#include "nvs.h" + +/** Arguments used by 'join' function */ +static struct { + struct arg_str *broker; + struct arg_str *topic; + struct arg_end *end; +} mqtt_args; + +static int mqttcmd(int argc, char** argv) +{ + int nerrors = arg_parse(argc, argv, (void**) &mqtt_args); + if (nerrors != 0) { + arg_print_errors(stderr, mqtt_args.end, argv[0]); + return 1; + } + + nvs_handle_t hnvs; + ESP_ERROR_CHECK( nvs_open("mqtt", NVS_READWRITE, &hnvs) ); + + if (mqtt_args.broker->count) { + nvs_set_str(hnvs, "broker", mqtt_args.broker->sval[0]); + } + if (mqtt_args.topic->count) { + nvs_set_str(hnvs, "topic", mqtt_args.topic->sval[0]); + } + + // read current config + + size_t topic_len = 128; + char topic[128] = ""; + nvs_get_str(hnvs, "topic", topic, &topic_len); + + size_t broker_len = 128; + char broker[128] = ""; + nvs_get_str(hnvs, "broker", broker, &broker_len); + + printf("Topic = %s\n", topic); + printf("Broker = %s\n", broker); + + nvs_close(hnvs); + + printf("Any changes are applied after restart.\n"); + return 0; +} + +void console_register_mqtt() +{ + mqtt_args.topic = arg_str0("t", "topic", "", "Set base of the MQTT topic (including slash)"); + mqtt_args.broker = arg_str0("b", "broker", "", "Set MQTT broker IP addr"); + mqtt_args.end = arg_end(2); + + const esp_console_cmd_t mqtt_cmd = { + .command = "mqtt", + .help = "Configure MQTT", + .hint = NULL, + .func = &mqttcmd, + .argtable = &mqtt_args + }; + + ESP_ERROR_CHECK( esp_console_cmd_register(&mqtt_cmd) ); +} diff --git a/main/cmd_mqtt.h b/main/cmd_mqtt.h new file mode 100644 index 0000000..8830a57 --- /dev/null +++ b/main/cmd_mqtt.h @@ -0,0 +1,12 @@ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void console_register_mqtt(); + +#ifdef __cplusplus +} +#endif + diff --git a/main/cmd_wifi.c b/main/cmd_wifi.c index 56ca129..7858b56 100644 --- a/main/cmd_wifi.c +++ b/main/cmd_wifi.c @@ -77,10 +77,12 @@ void initialise_wifi(void) } if (!use_dhcpc) { - char ip[16], gw[16], mask[16]; + char ip[16], gw[16], mask[16], dns1[16], dns2[16]; size_t iplen = 16; size_t gwlen = 16; size_t masklen = 16; + size_t dns1len = 16; + size_t dns2len = 16; rv = nvs_get_str(hnvs, "static_ip", ip, &iplen); if (rv != ESP_OK) { @@ -100,14 +102,33 @@ void initialise_wifi(void) ESP_LOGW(__func__, "Fail to load 'static_mask'"); } - printf("Static IP config: IP: %s, GW: %s, Mask: %s\n", ip, gw, mask); + rv = nvs_get_str(hnvs, "static_dns1", dns1, &dns1len); + if (rv != ESP_OK) { + ESP_LOGW(__func__, "Fail to load 'static_dns1'"); + } + + rv = nvs_get_str(hnvs, "static_dns2", dns2, &dns2len); // can be empty + if (rv != ESP_OK) { + ESP_LOGW(__func__, "Fail to load 'static_dns2'"); + } + + printf("Static IP config: IP: %s, GW: %s, Mask: %s, DNS1: %s, DNS2: %s\n", ip, gw, mask, dns1, dns2); tcpip_adapter_ip_info_t ip_info; + tcpip_adapter_dns_info_t dns1_info; + tcpip_adapter_dns_info_t dns2_info; if (!use_dhcpc) { ip_info.ip.addr = ipaddr_addr(ip); ip_info.gw.addr = ipaddr_addr(gw); ip_info.netmask.addr = ipaddr_addr(mask); + dns1_info.ip.addr = ipaddr_addr(dns1); + if (dns2[0] != 0) { + dns2_info.ip.addr = ipaddr_addr(dns2); + } else { + dns2_info.ip.addr = IPADDR_NONE; + } + if (ip_info.ip.addr == IPADDR_NONE || ip_info.gw.addr == IPADDR_NONE || ip_info.netmask.addr == IPADDR_NONE) { use_dhcpc = 1; ESP_LOGW(__func__, "Fail to parse static IP config"); @@ -117,6 +138,12 @@ void initialise_wifi(void) if (!use_dhcpc) { tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA); tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info); + if (dns1_info.ip.addr != IPADDR_NONE) { + tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_DNS_MAIN, &dns1_info); + } + if (dns2_info.ip.addr != IPADDR_NONE) { + tcpip_adapter_set_dns_info(TCPIP_ADAPTER_IF_STA, TCPIP_ADAPTER_DNS_FALLBACK, &dns2_info); + } } } nvs_commit(hnvs); @@ -192,94 +219,3 @@ void console_register_wifi() ESP_ERROR_CHECK( esp_console_cmd_register(&join_cmd) ); } - -/** Arguments used by 'join' function */ -static struct { - struct arg_lit *dhcp_on; - struct arg_lit *dhcp_off; - struct arg_str *static_ip; - struct arg_str *static_gw; - struct arg_str *static_mask; - struct arg_end *end; -} ip_args; - -static int ipcmd(int argc, char** argv) -{ - esp_err_t rv; - - int nerrors = arg_parse(argc, argv, (void**) &ip_args); - if (nerrors != 0) { - arg_print_errors(stderr, ip_args.end, argv[0]); - return 1; - } - - nvs_handle_t hnvs; - ESP_ERROR_CHECK( nvs_open("wifi", NVS_READWRITE, &hnvs) ); - - if (ip_args.dhcp_on->count) { - nvs_set_u8(hnvs, "use_dhcpc", 1); - } else if (ip_args.dhcp_off->count) { - nvs_set_u8(hnvs, "use_dhcpc", 0); - } - - if (ip_args.static_ip->count) { - nvs_set_str(hnvs, "static_ip", ip_args.static_ip->sval[0]); - } - - if (ip_args.static_gw->count) { - nvs_set_str(hnvs, "static_gw", ip_args.static_gw->sval[0]); - } - - if (ip_args.static_mask->count) { - nvs_set_str(hnvs, "static_mask", ip_args.static_mask->sval[0]); - } - - // read current config - - uint8_t use_dhcpc; - rv = nvs_get_u8(hnvs, "use_dhcpc", &use_dhcpc); - if (rv != ESP_OK) { - use_dhcpc = 1; - } - - char ip[16], gw[16], mask[16]; - size_t iplen = 16; - size_t gwlen = 16; - size_t masklen = 16; - ip[0] = gw[0] = mask[0] = 0; - - nvs_get_str(hnvs, "static_ip", ip, &iplen); - nvs_get_str(hnvs, "static_gw", gw, &gwlen); - nvs_get_str(hnvs, "static_mask", mask, &masklen); - - printf("DHCP = %s\n", use_dhcpc ? "Yes (dynamic IP)" : "No (static IP)"); - printf("Saved static IP = %s\n", ip); - printf("Saved static GW = %s\n", gw); - printf("Saved static MASK = %s\n", mask); - - nvs_close(hnvs); - - printf("Any changes are applied after restart.\n"); - - return 0; -} - -void console_register_ip() -{ - ip_args.dhcp_on = arg_lit0("d", "dhcp", "Enable DHCP"); - ip_args.dhcp_off = arg_lit0("s", "no-dhcp", "Disable DHCP (use static)"); - ip_args.static_ip = arg_str0("a", NULL, "", "Set static IP"); - ip_args.static_gw = arg_str0("g", NULL, "", "Set static GW"); - ip_args.static_mask = arg_str0("m", NULL, "", "Set static MASK (e.g. 255.255.255.0)"); - ip_args.end = arg_end(5); - - const esp_console_cmd_t ip_cmd = { - .command = "ip", - .help = "Configure TCP/IP", - .hint = NULL, - .func = &ipcmd, - .argtable = &ip_args - }; - - ESP_ERROR_CHECK( esp_console_cmd_register(&ip_cmd) ); -} diff --git a/main/cmd_wifi.h b/main/cmd_wifi.h index 145c313..7baec01 100644 --- a/main/cmd_wifi.h +++ b/main/cmd_wifi.h @@ -1,11 +1,3 @@ -/* Console example — declarations of command registration functions. - - This example code is in the Public Domain (or CC0 licensed, at your option.) - - 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. -*/ #pragma once #ifdef __cplusplus diff --git a/main/meteo_main.c b/main/meteo_main.c index 97f2562..943ddb8 100644 --- a/main/meteo_main.c +++ b/main/meteo_main.c @@ -1,5 +1,6 @@ #include #include +#include #include "esp_system.h" #include "esp_log.h" #include "esp_console.h" @@ -13,24 +14,11 @@ #include "nvs.h" #include "nvs_flash.h" #include "meteo_task.h" +#include "mqttpub.h" +#include "nvsconfig.h" #define TAG "example" -static void initialize_nvs() -{ - esp_err_t err = nvs_flash_init(); - if (err == ESP_ERR_NVS_NO_FREE_PAGES) { - ESP_ERROR_CHECK( nvs_flash_erase() ); - err = nvs_flash_init(); - } - ESP_ERROR_CHECK(err); - - // ensure the namespaces we need exist - nvs_handle_t hnvs; - ESP_ERROR_CHECK( nvs_open("wifi", NVS_READWRITE, &hnvs) ); - nvs_close(hnvs); -} - static void initialize_console() { /* Disable buffering on stdin */ @@ -81,18 +69,28 @@ static void initialize_console() /* Set command history size */ linenoiseHistorySetMaxLen(100); + + + /* Register commands */ + esp_console_register_help_command(); + console_register_system(); + console_register_wifi(); + console_register_ip(); + console_register_mqtt(); } + void app_main() { initialize_nvs(); + initialise_wifi(); initialize_console(); - initialise_wifi(); - console_register_ip(); + initialize_mqttpub(); xTaskCreate(meteo_task, "meteo_task", 2048, NULL, 10, NULL); + /* Print chip information */ esp_chip_info_t chip_info; esp_chip_info(&chip_info); @@ -105,12 +103,6 @@ void app_main() (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); - - /* Register commands */ - esp_console_register_help_command(); - console_register_system(); - console_register_wifi(); - /* Prompt to be printed before each line. * This can be customized, made dynamic, etc. */ diff --git a/main/meteo_task.c b/main/meteo_task.c index 3c5709b..dfbdf31 100644 --- a/main/meteo_task.c +++ b/main/meteo_task.c @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include "meteo_task.h" #include "ds18b20.h" #include "dht.h" @@ -14,18 +16,26 @@ #include "driver/i2c.h" #include "circbuf.h" #include "bmp280.h" +#include "mqttpub.h" +#include "esp_wifi.h" static volatile uint32_t timestamp = 0; +static volatile uint32_t last_telemetry_ts = 0; #define RPS_BUFFER_LEN (60*10) static volatile uint16_t history[RPS_BUFFER_LEN] = {}; static CircBuf rps_cb; static volatile float rpm_average = 0; +static volatile float rpm_inst = 0; static volatile float rpm_gust = 0; +#define MAGNET_COUNT 3 + static volatile uint16_t cycle_count = 0; +#define TAG "meteo" + void calculate_wind(); static void gpio_isr_handler(void *arg) @@ -57,9 +67,10 @@ void calculate_wind() float max_gust = 0; uint32_t tenmin_sum = 0; - uint32_t numsecs = cbuf_count(&rps_cb); + int numsecs = (int) cbuf_count(&rps_cb); uint16_t threesec1 = 0, threesec2 = 0; - for (size_t i = 0; i < numsecs; i++) { + uint32_t tensec_sum = 0, tensec_cnt = 0; + for (int i = 0; i < numsecs; i++) { uint16_t *slot = cbuf_ptr_nth(&rps_cb, i); if (!slot) { continue; @@ -68,6 +79,11 @@ void calculate_wind() uint16_t slotval = *slot; tenmin_sum += (uint32_t) slotval; + if (i >= numsecs - 10) { + tensec_sum += slotval; + tensec_cnt++; + } + // gust is max avg from 3 seconds within the 10 minutes uint32_t gust_sum = (uint32_t) threesec1 + (uint32_t) threesec2 + (uint32_t) slotval; threesec1 = threesec2; @@ -80,11 +96,24 @@ void calculate_wind() } rpm_gust = max_gust; rpm_average = ((float) tenmin_sum / (float) numsecs) * 60.0f; + rpm_inst = ((float) tensec_sum / (float) tensec_cnt) * 60.0f; } +bool is_nan(float f) { + return f != f; +} + +float nan_fallback(float f, float fallback) { + if (is_nan(f)) { + return fallback; + } + return f; +} void meteo_task(void *pvParameters) { + static char pldbuf[512]; + cbuf_init(&rps_cb, (void *) history, RPS_BUFFER_LEN, 2); // uint16 fields // Try to unfuck GPIOs @@ -131,7 +160,8 @@ void meteo_task(void *pvParameters) }; bmp280_init(&bmp_dev, &bmp_conf); - vTaskDelay(pdMS_TO_TICKS(500)); + + vTaskDelay(pdMS_TO_TICKS(5000)); float dht_hum, dht_temp, ds_temp, bmp_temp, bmp_hum, bmp_press; while (1) { @@ -144,24 +174,45 @@ void meteo_task(void *pvParameters) // this works ... ds_temp = ds18b20_measure_and_read(0, DS18B20_ANY); if (ds_temp != ds_temp) { - printf("DS failed\n"); + ESP_LOGE(TAG, "DS failed"); } if (!dht_read_float_data(DHT_TYPE_DHT22, 12, &dht_hum, &dht_temp)) { dht_hum = dht_temp = NAN; - printf("DHT failed\n"); + ESP_LOGE(TAG, "DHT failed"); } if(!bmp280_read_float(&bmp_dev, &bmp_temp, &bmp_press, &bmp_hum)) { - printf("BMP failed\n"); + ESP_LOGE(TAG, "BMP failed"); } - printf("Dallas: %.2f °C, ** DHT %.2f °C, %.1f %%r.H, ** WIND avg %.1f, gust %.1f RPM, ** BMP %.2f °C, %f Pa \n", + /* + {"uptime":125,"heap_free":44472,"heap_lwm":44028,"wifi_rssi":-48} + {"ds18b20":21.500000,"dht22_t":22.000000,"dht22_h":42.500000,"wind_avg":0.000000,"wind_inst":0.000000,"wind_gust":0.000000,"bmp280_t":22.540001,"bmp280_p":97578.734375} + */ + + ESP_LOGI(TAG, "Dallas: %.2f °C, ** DHT %.2f °C, %.1f %%r.H, ** WIND avg %.1f, gust %.1f RPM, ** BMP %.2f °C, %f Pa", ds_temp, dht_temp, dht_hum, rpm_average, rpm_gust, bmp_temp, bmp_press); - vTaskDelay(pdMS_TO_TICKS(500)); + snprintf(pldbuf, 512, "{\"ds18b20\":%.2f,\"dht22_t\":%.1f,\"dht22_h\":%.1f,\"wind_avg\":%.1f,\"wind_inst\":%.0f,\"wind_gust\":%.0f,\"bmp280_t\":%.2f,\"bmp280_p\":%.1f}", + nan_fallback(ds_temp, -300), nan_fallback(dht_temp, -300), nan_fallback(dht_hum, -1), + nan_fallback(rpm_average, 0)/MAGNET_COUNT, nan_fallback(rpm_inst, 0)/MAGNET_COUNT, nan_fallback(rpm_gust, 0)/MAGNET_COUNT, + nan_fallback(bmp_temp, -300), nan_fallback(bmp_press, -1)); + + mqtt_publish("measurement", pldbuf); + + if (timestamp - last_telemetry_ts >= 5*60 || last_telemetry_ts == 0) { + wifi_ap_record_t ap_info = {}; + esp_wifi_sta_get_ap_info(&ap_info); + snprintf(pldbuf, 512, "{\"uptime\":%"PRIu32",\"heap_free\":%d,\"heap_lwm\":%d,\"wifi_rssi\":%d}", + timestamp, heap_caps_get_free_size(0), heap_caps_get_minimum_free_size(0), ap_info.rssi); + mqtt_publish("telemetry", pldbuf); + last_telemetry_ts = timestamp; + } + + vTaskDelay(pdMS_TO_TICKS(15000)); } vTaskDelete(NULL); diff --git a/main/mqttpub.c b/main/mqttpub.c new file mode 100644 index 0000000..d6fad67 --- /dev/null +++ b/main/mqttpub.c @@ -0,0 +1,128 @@ +/** + * TODO file description + */ + +#include +#include +#include +#include "mqttpub.h" + +#define TAG "mq" + +static bool mqtt_inited = false; + +esp_mqtt_client_handle_t s_client; +static char s_basetopic[128]; +static char s_topicbuf[256]; + +static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) +{ + 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_publish(client, "/topic/qos1", "data_3", 0, 1, 0); + +// ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id); +// +// msg_id = esp_mqtt_client_subscribe(client, "/topic/qos0", 0); +// ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); +// +// msg_id = esp_mqtt_client_subscribe(client, "/topic/qos1", 1); +// ESP_LOGI(TAG, "sent subscribe successful, msg_id=%d", msg_id); +// +// msg_id = esp_mqtt_client_unsubscribe(client, "/topic/qos1"); +// ESP_LOGI(TAG, "sent unsubscribe 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); +// msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0); +// ESP_LOGI(TAG, "sent publish successful, msg_id=%d", 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"); + break; + default: + ESP_LOGI(TAG, "Other event id:%d", event->event_id); + break; + } + return ESP_OK; +} + + +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); + mqtt_event_handler_cb(event_data); +} + +void initialize_mqttpub() +{ + char brokerurl[128]; + size_t len; + esp_err_t rv; + nvs_handle_t hnvs; + + ESP_ERROR_CHECK( nvs_open("mqtt", NVS_READWRITE, &hnvs) ); + + len = 128; + brokerurl[0] = 0; + rv = nvs_get_str(hnvs, "broker", brokerurl, &len); + if (rv != ESP_OK || brokerurl[0] == 0) { + ESP_LOGW(TAG, "Missing MQTT broker!"); + return; + } + + len = 128; + s_basetopic[0] = 0; + rv = nvs_get_str(hnvs, "topic", s_basetopic, &len); + if (rv != ESP_OK) { + ESP_LOGW(TAG, "Bad MQTT topic!"); + return; + } + ESP_LOGI(TAG, "mqtt.topic = %s", s_basetopic); + + nvs_close(hnvs); + + esp_mqtt_client_config_t mqtt_cfg = { + .uri = brokerurl, + }; + + s_client = esp_mqtt_client_init(&mqtt_cfg); + ESP_ERROR_CHECK(esp_mqtt_client_register_event(s_client, ESP_EVENT_ANY_ID, mqtt_event_handler, s_client)); + ESP_ERROR_CHECK(esp_mqtt_client_start(s_client)); + + mqtt_inited = true; +} + +void mqtt_publish(const char *topic, const char *payload) +{ + if (!mqtt_inited) { + ESP_LOGE(TAG, "MQTT not inited"); + return; + } + + snprintf(s_topicbuf, 256, "%s%s", s_basetopic, topic); + + ESP_LOGI(TAG, "MQTT pub to %s: %s", s_topicbuf, payload); + + + esp_mqtt_client_publish(s_client, s_topicbuf, payload, (int) strlen(payload), 1, 0); +} diff --git a/main/mqttpub.h b/main/mqttpub.h new file mode 100644 index 0000000..dcdb929 --- /dev/null +++ b/main/mqttpub.h @@ -0,0 +1,9 @@ +/** + * TODO file description + */ + +#pragma once + +void initialize_mqttpub(); + +void mqtt_publish(const char *topic, const char *payload); diff --git a/main/nvsconfig.c b/main/nvsconfig.c new file mode 100644 index 0000000..84aa878 --- /dev/null +++ b/main/nvsconfig.c @@ -0,0 +1,125 @@ +/** + * TODO file description + */ + +#include +#include +#include +#include +#include +#include +#include "nvsconfig.h" + +#define TAG_CONFIG "config" + +void initialize_nvs() +{ + esp_err_t rv; + nvs_handle_t hnvs; + + char tmps[128]; + size_t len; + uint8_t u8val; + + + esp_err_t err = nvs_flash_init(); + if (err == ESP_ERR_NVS_NO_FREE_PAGES) { + ESP_ERROR_CHECK( nvs_flash_erase() ); + err = nvs_flash_init(); + } + ESP_ERROR_CHECK(err); + + + + /* Wifi namespace */ + + ESP_ERROR_CHECK( nvs_open("wifi", NVS_READWRITE, &hnvs) ); + + u8val = 99; + rv = nvs_get_u8(hnvs, "use_dhcpc", &u8val); + if (rv != ESP_OK || (u8val != 0 && u8val != 1)) { + ESP_LOGW(TAG_CONFIG, "Invalid dhcp option - set to default"); + u8val = 1; + nvs_set_u8(hnvs, "use_dhcpc", u8val); + } + ESP_LOGI(TAG_CONFIG, "wifi.use_dhcpc = %d", u8val); + + len = 16; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "static_ip", tmps, &len); + if (rv != ESP_OK || IPADDR_NONE == ipaddr_addr(tmps)) { + strcpy(tmps, "192.168.56.2"); + ESP_LOGW(TAG_CONFIG, "Invalid static ip - set to default"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "static_ip", tmps)); + } + ESP_LOGI(TAG_CONFIG, "wifi.static_ip = %s", tmps); + + len = 16; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "static_gw", tmps, &len); + if (rv != ESP_OK || IPADDR_NONE == ipaddr_addr(tmps)) { + strcpy(tmps, "192.168.0.1"); + ESP_LOGW(TAG_CONFIG, "Invalid static gw - set to default"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "static_gw", tmps)); + } + ESP_LOGI(TAG_CONFIG, "wifi.static_gw = %s", tmps); + + len = 16; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "static_mask", tmps, &len); + if (rv != ESP_OK || IPADDR_NONE == ipaddr_addr(tmps)) { + strcpy(tmps, "255.255.255.0"); + ESP_LOGW(TAG_CONFIG, "Invalid static mask - set to default"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "static_mask", tmps)); + } + ESP_LOGI(TAG_CONFIG, "wifi.static_mask = %s", tmps); + + len = 16; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "static_dns1", tmps, &len); + if (rv != ESP_OK || IPADDR_NONE == ipaddr_addr(tmps)) { + strcpy(tmps, "8.8.8.8"); + ESP_LOGW(TAG_CONFIG, "Invalid static DNS1 - set to default"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "static_dns1", tmps)); + } + ESP_LOGI(TAG_CONFIG, "wifi.static_dns1 = %s", tmps); + + len = 16; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "static_dns2", tmps, &len); + if (rv != ESP_OK) { + strcpy(tmps, ""); + ESP_LOGW(TAG_CONFIG, "Invalid static DNS2 - set to empty"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "static_dns2", tmps)); + } + ESP_LOGI(TAG_CONFIG, "wifi.static_dns2 = %s", tmps); + + nvs_close(hnvs); + + + /* MQTT namespace */ + + ESP_ERROR_CHECK( nvs_open("mqtt", NVS_READWRITE, &hnvs) ); + + len = 128; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "broker", tmps, &len); + if (rv != ESP_OK) { + strcpy(tmps, ""); + ESP_LOGW(TAG_CONFIG, "Invalid broker addr - set to empty"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "broker", tmps)); + } + ESP_LOGI(TAG_CONFIG, "mqtt.broker = %s", tmps); + + len = 128; + tmps[0] = 0; + rv = nvs_get_str(hnvs, "topic", tmps, &len); + if (rv != ESP_OK || tmps[0] == 0) { + strcpy(tmps, "/meteo/"); + ESP_LOGW(TAG_CONFIG, "Invalid mqtt topic - set to default"); + ESP_ERROR_CHECK(nvs_set_str(hnvs, "topic", tmps)); // default + } + ESP_LOGI(TAG_CONFIG, "mqtt.topic = %s", tmps); + + nvs_close(hnvs); +} diff --git a/main/nvsconfig.h b/main/nvsconfig.h new file mode 100644 index 0000000..8843f59 --- /dev/null +++ b/main/nvsconfig.h @@ -0,0 +1,7 @@ +/** + * TODO file description + */ + +#pragma once + +void initialize_nvs(); diff --git a/sdkconfig b/sdkconfig index cefc2cb..a77d5c8 100644 --- a/sdkconfig +++ b/sdkconfig @@ -76,8 +76,8 @@ CONFIG_PARTITION_TABLE_SINGLE_APP=y CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_OFFSET=0x8000 CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" -CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG is not set +CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set @@ -463,8 +463,8 @@ CONFIG_MONITOR_BAUD_74880B=y # CONFIG_MONITOR_BAUD_OTHER is not set CONFIG_MONITOR_BAUD_OTHER_VAL=74880 CONFIG_MONITOR_BAUD=74880 -CONFIG_OPTIMIZATION_LEVEL_DEBUG=y -# CONFIG_OPTIMIZATION_LEVEL_RELEASE is not set +# CONFIG_OPTIMIZATION_LEVEL_DEBUG is not set +CONFIG_OPTIMIZATION_LEVEL_RELEASE=y CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set # CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set diff --git a/sdkconfig.old b/sdkconfig.old index d948584..cefc2cb 100644 --- a/sdkconfig.old +++ b/sdkconfig.old @@ -82,11 +82,11 @@ CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set # CONFIG_COMPILER_CXX_EXCEPTIONS is not set -CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y -# CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set +# CONFIG_COMPILER_STACK_CHECK_MODE_NONE is not set +CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y # CONFIG_COMPILER_STACK_CHECK_MODE_STRONG is not set # CONFIG_COMPILER_STACK_CHECK_MODE_ALL is not set -# CONFIG_COMPILER_STACK_CHECK is not set +CONFIG_COMPILER_STACK_CHECK=y # CONFIG_COMPILER_WARN_WRITE_STRINGS is not set CONFIG_APP_UPDATE_CHECK_APP_SUM=y # CONFIG_APP_UPDATE_CHECK_APP_HASH is not set @@ -401,7 +401,7 @@ CONFIG_MQTT_TRANSPORT_WEBSOCKET_SECURE=y CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y # CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF is not set # CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR is not set -CONFIG_NEWLIB_NANO_FORMAT=y +# CONFIG_NEWLIB_NANO_FORMAT is not set # CONFIG_OPENSSL_DEBUG is not set CONFIG_OPENSSL_ASSERT_DO_NOTHING=y # CONFIG_OPENSSL_ASSERT_EXIT is not set @@ -469,11 +469,11 @@ CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set # CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set # CONFIG_CXX_EXCEPTIONS is not set -CONFIG_STACK_CHECK_NONE=y -# CONFIG_STACK_CHECK_NORM is not set +# CONFIG_STACK_CHECK_NONE is not set +CONFIG_STACK_CHECK_NORM=y # CONFIG_STACK_CHECK_STRONG is not set # CONFIG_STACK_CHECK_ALL is not set -# CONFIG_STACK_CHECK is not set +CONFIG_STACK_CHECK=y # CONFIG_WARN_WRITE_STRINGS is not set CONFIG_MAIN_TASK_STACK_SIZE=3584 CONFIG_CONSOLE_UART_DEFAULT=y