testot connects with MQTT directly over an IP, and just sends uptime
authorjweigele <jweigele@local>
Mon, 4 Sep 2023 17:48:51 +0000 (10:48 -0700)
committerjweigele <jweigele@local>
Mon, 4 Sep 2023 17:48:51 +0000 (10:48 -0700)
testot/main/Kconfig [new file with mode: 0644]
testot/main/esp_ot_sleepy_device.c
testot/main/esp_ot_sleepy_device_config.h
testot/sdkconfig

diff --git a/testot/main/Kconfig b/testot/main/Kconfig
new file mode 100644 (file)
index 0000000..4ab293c
--- /dev/null
@@ -0,0 +1,12 @@
+menu "AQI Program Configuration"
+config BROKER_URL
+    string "Set this to connect mqtt and report back data"
+    default "mqtts://esp32:sensorauth@rabbitmq.hexthepla.net"
+    help
+      Gets used downstream
+config LOCATION
+    string "Set this to whatever you'd like reported as location"
+    default "ESP32 babyyy"
+    help
+      Gets used when sending off sensor data
+endmenu
index d0cd8adb326710da26606f6430038842cef1de88..cd7126dc991ad54d24ee616f044c17bcf5a14a4b 100644 (file)
 
 #define TAG "ot_esp_power_save"
 
+static bool ot_connected = false;
+static bool mqtt_connected = false;
+static QueueHandle_t event_queue;
+
+// for tracking and reporting device uptime
+static uint32_t device_uptime_seconds = 0;
+
+
+
+static void log_error_if_nonzero(const char *message, int error_code)
+{
+    if (error_code != 0) {
+        ESP_LOGE(TAG, "Last error %s: 0x%x", message, error_code);
+    }
+}
+
+static void mqtt_reinit(esp_mqtt_client_handle_t client){
+        ESP_LOGW(TAG, "trying to shutdown old mqtt client here");
+        // get rid of previous handle
+        // the auto reconnect should handle everything else
+        ESP_ERROR_CHECK(esp_mqtt_client_stop(client));
+}
+
+
+/*
+ * @brief Event handler registered to receive MQTT events
+ *
+ *  This function is called by the MQTT client event loop.
+ *
+ * @param handler_args user data registered to the event.
+ * @param base Event base for the handler(always MQTT Base in this example).
+ * @param event_id The id for the received event.
+ * @param event_data The data for the event, esp_mqtt_event_handle_t.
+ */
+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=%" PRIi32 "", base, event_id);
+    esp_mqtt_event_handle_t event = event_data;
+    switch ((esp_mqtt_event_id_t)event_id) {
+    case MQTT_EVENT_CONNECTED:
+        mqtt_client = event->client;
+        mqtt_connected = true;
+        ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
+        break;
+    case MQTT_EVENT_DISCONNECTED:
+        if ( event->client != mqtt_client ){
+            ESP_LOGI(TAG, "disco old mqtt client, staying connected on this one");
+        } else {
+            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
+            mqtt_connected = false;
+        }
+        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:
+        if ( mqtt_client != NULL && event->client != mqtt_client ){
+            ESP_LOGI(TAG, "old mqtt client, staying connected on this one and shutting down old");
+            esp_mqtt_client_handle_t send_item  = event->client;
+            xQueueSend(event_queue, &send_item, portMAX_DELAY);
+        } else {
+            mqtt_connected = false;
+            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
+        }
+        if (event->error_handle->error_type == MQTT_ERROR_TYPE_TCP_TRANSPORT) {
+            log_error_if_nonzero("reported from esp-tls", event->error_handle->esp_tls_last_esp_err);
+            log_error_if_nonzero("reported from tls stack", event->error_handle->esp_tls_stack_err);
+            log_error_if_nonzero("captured as transport's socket errno",  event->error_handle->esp_transport_sock_errno);
+            ESP_LOGI(TAG, "Last errno string (%s)", strerror(event->error_handle->esp_transport_sock_errno));
+
+        }
+
+        //ESP_ERROR_CHECK(esp_mqtt_client_reconnect(mqtt_client));
+        break;
+    default:
+        ESP_LOGI(TAG, "Other event id:%d", event->event_id);
+        break;
+    }
+}
+
+static void send_report_wifi(){
+    ESP_LOGI(TAG, "send_report_wifi was called!");
+    cJSON *root;
+    root = cJSON_CreateObject();
+    cJSON_AddStringToObject(root, "location", CONFIG_LOCATION);
+    cJSON_AddNumberToObject(root, "uptime", device_uptime_seconds);
+
+    //const char *my_json_string = cJSON_Print(root);
+    char *mqtt_string = cJSON_Print(root);
+    ESP_LOGI(TAG, "sending mqtt_string:\n%s",mqtt_string);
+    if (mqtt_connected == true){
+        int msg_id = esp_mqtt_client_publish(mqtt_client, "esp32/sensor_info", mqtt_string, 0, 1, 0);
+        ESP_LOGI(TAG, "sent publish successful, msg_id=%d", msg_id);
+    } else {
+        ESP_LOGW(TAG, "well, not quite yet (not connected)");
+    }
+    free(mqtt_string);
+    cJSON_Delete(root);
+}
+
+
+void init_mqtt(){
+    ESP_LOGI(TAG, "attempting to connect to MQTT");
+    mqtt_client = NULL;
+    esp_mqtt_client_config_t mqtt_cfg = {
+        .broker = {
+            .address.uri  = CONFIG_BROKER_URL,
+            .verification.certificate = NULL,
+            //.verification.use_global_ca_store = true,
+            //.verification.crt_bundle_attach = esp_crt_bundle_attach,
+        },
+        .session.keepalive = 10,
+        //.cacert_buf = ca_cert,
+        //.cacert_bytes = strlen(ca_cert)+1,
+    };
+    esp_mqtt_client_handle_t client = esp_mqtt_client_init(&mqtt_cfg);
+    /* The last argument may be used to pass data to the event handler, in this example mqtt_event_handler */
+    esp_mqtt_client_register_event(client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
+    esp_mqtt_client_start(client);
+}
+
+static void monitoring_task(void* discard)
+{
+    int64_t cur_uptime = 0;
+    int64_t next_sleep_uptime = 0;
+    int64_t remaining_time = 0;
+    esp_mqtt_client_handle_t queue_item;
+    for(;;){
+
+        // receive an event we need to deal with from elsewhere, right now just reconnect related
+        if (xQueueReceive(event_queue, &queue_item, 0 )){
+            ESP_LOGW(TAG, "received a queue event in main monitoring loop! %p", queue_item);
+            mqtt_reinit(queue_item);
+        }
+        ESP_LOGI(TAG, "free heap: %"PRIu32, esp_get_free_heap_size());
+        cur_uptime = esp_timer_get_time();
+        // we'll use this to calc our sleeps later
+        next_sleep_uptime = cur_uptime + SLEEP_MS*1000;
+        // first things first (function gives microseconds, just convert to seconds)
+        // 32 bits is enough for >50 years and zigbee stack gets mad if we use more bits
+        device_uptime_seconds = (uint32_t)(cur_uptime/1000000);
+        // one BIG report for wifi
+        send_report_wifi();
+        cur_uptime = esp_timer_get_time();
+        remaining_time = next_sleep_uptime - cur_uptime;
+        ESP_LOGI(TAG, "next sleep uptime %lld cur_uptime %lld remaining time %lld", next_sleep_uptime, cur_uptime, remaining_time);
+        // sleep for 10 seconds before measuring again
+        ESP_LOGI(TAG, "sleeping for %lld ms", remaining_time/1000);
+        vTaskDelay( pdMS_TO_TICKS(remaining_time/1000) );
+    }
+}
+
+
+
+void handleNetifStateChanged(uint32_t aFlags, void *aContext)
+{
+   if ((aFlags & OT_CHANGED_THREAD_ROLE) != 0)
+   {
+       otDeviceRole changedRole = otThreadGetDeviceRole(aContext);
+
+       switch (changedRole)
+       {
+       case OT_DEVICE_ROLE_LEADER:
+       case OT_DEVICE_ROLE_ROUTER:
+       case OT_DEVICE_ROLE_CHILD:
+           ot_connected = true;
+           ESP_LOGI(TAG, "is_connected = true");
+           init_mqtt();
+           break;
+
+       case OT_DEVICE_ROLE_DETACHED:
+       case OT_DEVICE_ROLE_DISABLED:
+           ot_connected = false;
+           ESP_LOGI(TAG, "is_connected = false");
+           break;
+        }
+    }
+}
+
 /**
  * Override default network settings, such as panid, so the devices can join a
  network
@@ -103,6 +294,10 @@ static void create_config_network(otInstance *instance)
         ESP_LOGE(TAG, "Failed to set OpenThread linkmode.");
         abort();
     }
+
+    /* Register Thread state change handler */
+    otSetStateChangedCallback(instance, handleNetifStateChanged, instance);
+
     ESP_ERROR_CHECK(esp_openthread_auto_start(NULL));
 
     /* Override default network credentials */
@@ -192,6 +387,9 @@ void app_main(void)
     ESP_ERROR_CHECK(esp_netif_init());
     ESP_ERROR_CHECK(esp_vfs_eventfd_register(&eventfd_config));
     ESP_ERROR_CHECK(ot_power_save_init());
+    event_queue = xQueueCreate(5, sizeof(esp_mqtt_client_handle_t));
+
 
     xTaskCreate(ot_task_worker, "ot_power_save_main", 4096, NULL, 5, NULL);
+    xTaskCreate(monitoring_task, "monitoring_task", 4096, NULL, 1, NULL);
 }
index d5b9383c06fa5665e80ff7bc318bf49202e5986e..b1125de72e90841837a82402e461920806baece3 100644 (file)
  * CONDITIONS OF ANY KIND, either express or implied.
  */
 
+#include "esp_timer.h"
+#include <lwip/ip4_addr.h>
+#include <esp_netif.h>
+#include <esp_tls.h>
+#include "mqtt_client.h"
+#include "esp_crt_bundle.h"
+#include "esp_netif_sntp.h"
+#include "cJSON.h"
+static esp_mqtt_client_handle_t mqtt_client;
+void init_mqtt();
+
+static void mqtt_reinit();
+// ten second loop
+#define SLEEP_MS 10000
+
+
+
 #pragma once
 
 #include "esp_openthread_types.h"
index fc61f17a1c8bd068aae41e26802f29409907b96b..2ccf5bf71013cd9bf73d222394133c40873056b5 100644 (file)
@@ -624,7 +624,8 @@ CONFIG_ESP_TLS_USE_DS_PERIPHERAL=y
 # CONFIG_ESP_TLS_CLIENT_SESSION_TICKETS is not set
 # CONFIG_ESP_TLS_SERVER is not set
 # CONFIG_ESP_TLS_PSK_VERIFICATION is not set
-# CONFIG_ESP_TLS_INSECURE is not set
+CONFIG_ESP_TLS_INSECURE=y
+CONFIG_ESP_TLS_SKIP_SERVER_CERT_VERIFY=y
 # end of ESP-TLS
 
 #
@@ -1701,6 +1702,13 @@ CONFIG_WIFI_PROV_AUTOSTOP_TIMEOUT=30
 CONFIG_WIFI_PROV_STA_ALL_CHANNEL_SCAN=y
 # CONFIG_WIFI_PROV_STA_FAST_SCAN is not set
 # end of Wi-Fi Provisioning Manager
+
+#
+# AQI Program Configuration
+#
+CONFIG_BROKER_URL="mqtts://esp32:sensorauth@10.246.1.110"
+CONFIG_LOCATION="OT Test"
+# end of AQI Program Configuration
 # end of Component config
 
 # CONFIG_IDF_EXPERIMENTAL_FEATURES is not set