Browse Source

Works with WiFi and MQTT. Done

Thomas Chef 4 months ago
parent
commit
52488da35a
12 changed files with 514 additions and 90 deletions
  1. 1 1
      main/CMakeLists.txt
  2. 25 19
      main/Kconfig.projbuild
  3. 23 0
      main/config.h
  4. 84 0
      main/fridgeDoor.c
  5. 9 0
      main/fridgeDoor.h
  6. 7 69
      main/main.c
  7. 134 0
      main/mqtt.c
  8. 9 0
      main/mqtt.h
  9. 16 0
      main/sound.c
  10. 6 1
      main/sound.h
  11. 185 0
      main/wifi.c
  12. 15 0
      main/wifi.h

+ 1 - 1
main/CMakeLists.txt

@@ -1,4 +1,4 @@
-idf_component_register(SRCS "sound.c" "main.c"
+idf_component_register(SRCS "mqtt.c" "fridgeDoor.c" "sound.c" "main.c" "wifi.c"
                     INCLUDE_DIRS "."
                     )
 

+ 25 - 19
main/Kconfig.projbuild

@@ -1,4 +1,28 @@
-menu "Example Configuration"
+menu "Fridge Sensor Application Configuration"
+
+    config ESP_WIFI_SSID
+        string "WiFi SSID"
+        default "Hemnet3"
+        help
+            SSID (network name) to connect to.
+
+    config ESP_WIFI_PASSWORD
+        string "WiFi Password"
+        default "mypassword"
+        help
+            WiFi password (WPA or WPA2) to use.
+
+    config ESP_MQTT_PASSWORD
+        string "MQTT Password"
+        default "mypassword"
+        help
+            MQTT password
+
+    config ESP_MQTT_UNAME
+        string "MQTT User"
+        default "myuser"
+        help
+            MQTT Username
 
     choice BLINK_LED
         prompt "Blink LED type"
@@ -13,18 +37,6 @@ menu "Example Configuration"
             bool "RMT - Addressable LED"
     endchoice
 
-    config BLINK_LED_RMT_CHANNEL
-        depends on BLINK_LED_RMT
-        int "RMT Channel"
-        range 0 7
-        default 0
-        help
-            Set the RMT peripheral channel.
-            ESP32 RMT channel from 0 to 7
-            ESP32-S2 RMT channel from 0 to 3
-            ESP32-S3 RMT channel from 0 to 3
-            ESP32-C3 RMT channel from 0 to 1
-
     config BLINK_GPIO
         int "Blink GPIO number"
         range 0 48
@@ -36,11 +48,5 @@ menu "Example Configuration"
             GPIO number (IOxx) to blink on and off or the RMT signal for the addressable LED.
             Some GPIOs are used for other purposes (flash connections, etc.) and cannot be used to blink.
 
-    config BLINK_PERIOD
-        int "Blink period in ms"
-        range 10 3600000
-        default 1000
-        help
-            Define the blinking period in milliseconds.
 
 endmenu

+ 23 - 0
main/config.h

@@ -0,0 +1,23 @@
+#ifndef __CONFIG_H__
+#define __CONFIG_H__
+
+#include "driver/gpio.h"
+
+
+#define SW_VERSION "1.0"
+
+
+#define ACTIVE_THRESHOLD_MS 60000  // 60 seconds in milliseconds
+
+#define PHOTO_SENSOR_PIN GPIO_NUM_18
+#define BLINK_GPIO CONFIG_BLINK_GPIO
+
+#define SOUND_ENABLED
+#define DOOR_SENSOR_ENABLED
+
+
+#define WIFI_ENABLED
+#define MQTT_ENABLED
+
+
+#endif

+ 84 - 0
main/fridgeDoor.c

@@ -0,0 +1,84 @@
+#include <stdio.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "driver/gpio.h"
+#include "esp_log.h"
+#include <stdbool.h>
+#include "sdkconfig.h"
+#include "fridgeDoor.h"
+#include "config.h"
+#include "sound.h"
+#include "mqtt.h"
+
+#ifdef DOOR_SENSOR_ENABLED
+
+static void check_sensor_active_time(bool fridgeDoorClosed) {
+
+    static int64_t activeStartTime = 0;
+
+    //ESP_EARLY_LOGI("CHECK", "State: %s", fridgeDoorClosed == true ? "CLOSED" : "OPEN");
+
+    if (fridgeDoorClosed == false) {
+        if (activeStartTime == 0) {
+            activeStartTime = esp_timer_get_time() / 1000; // Convert to milliseconds
+            ESP_LOGI("CHECK", "Door timer start time: %lld", activeStartTime);
+        } else {
+            int64_t elapsedTime = (esp_timer_get_time() / 1000) - activeStartTime;
+            //ESP_LOGI("CHECK", "Elapsed time: %lld", elapsedTime);
+            if (elapsedTime > ACTIVE_THRESHOLD_MS) {
+                enableNotificationSound(true);
+            }
+        }
+    } else {
+        activeStartTime = 0;
+        enableNotificationSound(false);
+    }
+}
+
+static void read_photo_sensor_task(void *pvParameters) {
+    static bool prevState = false;
+    while (1) {
+        bool fridgeDoorClosed = gpio_get_level(PHOTO_SENSOR_PIN) == 0 ? false : true;
+        if (fridgeDoorClosed != prevState) {
+            prevState = fridgeDoorClosed;
+            ESP_EARLY_LOGI("PHOTO", "Triggered! State: %s", fridgeDoorClosed == true ? "CLOSED" : "OPEN");
+            if( fridgeDoorClosed == false ) {
+                gpio_set_level(BLINK_GPIO, 1);
+            }
+            else {
+                gpio_set_level(BLINK_GPIO, 0);
+            }
+
+            char mqtt_s[50];
+            char value_s[10];
+
+            sprintf(mqtt_s,"kitchen/fridge/doorState");
+            sprintf(value_s,"%s",fridgeDoorClosed ? "closed" : "open");
+            sendMQTTMessage(mqtt_s, value_s);
+        }
+
+        check_sensor_active_time(fridgeDoorClosed);
+
+        vTaskDelay(pdMS_TO_TICKS(50)); // Delay 50ms (20 times per second)
+
+    }
+}
+
+void setup_photo_sensor() {
+    gpio_config_t io_conf = {
+        .intr_type = GPIO_INTR_ANYEDGE,  // Trigger on both rising & falling edges
+        .pin_bit_mask = (1ULL << PHOTO_SENSOR_PIN),
+        .mode = GPIO_MODE_INPUT,
+        .pull_up_en = GPIO_PULLUP_DISABLE,  
+        .pull_down_en = GPIO_PULLDOWN_DISABLE
+    };
+    gpio_config(&io_conf);
+
+    xTaskCreate(read_photo_sensor_task, "read_sensor_task", 2048, NULL, 10, NULL);
+
+    ESP_LOGI("PHOTO", "Photomicrosensor configured on GPIO %d", PHOTO_SENSOR_PIN);
+}
+
+#else
+void setup_photo_sensor() {};
+#endif

+ 9 - 0
main/fridgeDoor.h

@@ -0,0 +1,9 @@
+#ifndef __FRIDGE_H__
+#define __FRIDGE_H__
+
+#include <stdbool.h>
+
+
+void setup_photo_sensor();
+
+#endif

+ 7 - 69
main/main.c

@@ -6,14 +6,10 @@
 #include <stdbool.h>
 #include "sdkconfig.h"
 #include "sound.h"
-
-/* Use project configuration menu (idf.py menuconfig) to choose the GPIO to blink,
-   or you can edit the following line and set a number here.
-*/
-#define BLINK_GPIO CONFIG_BLINK_GPIO
-#define PHOTO_SENSOR_PIN GPIO_NUM_18
-
-#define ACTIVE_THRESHOLD_MS 5000  // 60 seconds in milliseconds
+#include "config.h"
+#include "fridgeDoor.h"
+#include "wifi.h"
+#include "mqtt.h"
 
 static void configure_led(void)
 {
@@ -23,73 +19,15 @@ static void configure_led(void)
     gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
 }
 
-// GPIO setup
-void setup_photo_sensor() {
-    gpio_config_t io_conf = {
-        .intr_type = GPIO_INTR_ANYEDGE,  // Trigger on both rising & falling edges
-        .pin_bit_mask = (1ULL << PHOTO_SENSOR_PIN),
-        .mode = GPIO_MODE_INPUT,
-        .pull_up_en = GPIO_PULLUP_DISABLE,  
-        .pull_down_en = GPIO_PULLDOWN_DISABLE
-    };
-    gpio_config(&io_conf);
-
-    ESP_LOGI("PHOTO", "Photomicrosensor configured on GPIO %d", PHOTO_SENSOR_PIN);
-}
-
-void check_sensor_active_time(bool fridgeDoorClosed) {
-
-    static int64_t activeStartTime = 0;
-
-    //ESP_EARLY_LOGI("CHECK", "State: %s", fridgeDoorClosed == true ? "CLOSED" : "OPEN");
-
-    if (fridgeDoorClosed == false) {
-        if (activeStartTime == 0) {
-            activeStartTime = esp_timer_get_time() / 1000; // Convert to milliseconds
-            ESP_LOGI("CHECK", "Door timer start time: %lld", activeStartTime);
-        } else {
-            int64_t elapsedTime = (esp_timer_get_time() / 1000) - activeStartTime;
-            //ESP_LOGI("CHECK", "Elapsed time: %lld", elapsedTime);
-            if (elapsedTime > ACTIVE_THRESHOLD_MS) {
-                enableNotificationSound(true);
-            }
-        }
-    } else {
-        activeStartTime = 0;
-        enableNotificationSound(false);
-    }
-}
-
-void read_photo_sensor_task(void *pvParameters) {
-    static bool prevState = false;
-    while (1) {
-        bool fridgeDoorClosed = gpio_get_level(PHOTO_SENSOR_PIN) == 0 ? false : true;
-        if (fridgeDoorClosed != prevState) {
-            prevState = fridgeDoorClosed;
-            ESP_EARLY_LOGI("PHOTO", "Triggered! State: %s", fridgeDoorClosed == true ? "CLOSED" : "OPEN");
-            if( fridgeDoorClosed == false ) {
-                gpio_set_level(BLINK_GPIO, 1);
-            }
-            else {
-                gpio_set_level(BLINK_GPIO, 0);
-            }
-        }
-
-        check_sensor_active_time(fridgeDoorClosed);
-
-        vTaskDelay(pdMS_TO_TICKS(50)); // Delay 50ms (20 times per second)
-
-    }
-}
-
 void app_main(void)
 {
 
+    initWifi();             // Init WIFI
+    mqtt_init();
+
     /* Configure the peripheral according to the LED type */
     configure_led();
     setup_photo_sensor();
     initSound();
 
-    xTaskCreate(read_photo_sensor_task, "read_sensor_task", 2048, NULL, 10, NULL);
-
 }

+ 134 - 0
main/mqtt.c

@@ -0,0 +1,134 @@
+/* MQTT (over TCP) Example
+
+   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 <stdio.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <string.h>
+#include "esp_wifi.h"
+#include "esp_system.h"
+#include "nvs_flash.h"
+#include "esp_event.h"
+#include "esp_netif.h"
+//#include "protocol_examples_common.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+
+#include "lwip/sockets.h"
+#include "lwip/dns.h"
+#include "lwip/netdb.h"
+
+#include "esp_log.h"
+#include "mqtt_client.h"
+
+#include "wifi.h"
+
+static const char *TAG = "MQTT";
+
+#ifdef MQTT_ENABLED
+
+
+static esp_mqtt_client_handle_t client;
+static bool connected = false;
+
+
+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:
+            connected = true;
+            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
+            esp_mqtt_client_publish(client, "kitchen/fridge/available", "online", 0, 1, true);
+            break;
+        case MQTT_EVENT_DISCONNECTED:
+            connected = false;
+            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
+            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 mqttTask(void *pvParameters) {
+
+    ESP_LOGI("MQTT", "mqttTask starting. Core:%d\n",xPortGetCoreID());
+
+#ifdef WIFI_ENABLED
+    // Wait for tcpip-comm
+    while( commIsUpAndRunning == false ) vTaskDelay(10000 / portTICK_PERIOD_MS);
+#endif
+
+    esp_mqtt_client_config_t mqtt_cfg = {
+        .uri = "mqtt://192.168.1.110:1883",
+        .password = CONFIG_ESP_MQTT_PASSWORD,
+        .username = CONFIG_ESP_MQTT_UNAME
+    };
+
+    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);
+
+    vTaskDelete(NULL);
+}
+
+
+
+void mqtt_init(void)
+{
+    xTaskCreatePinnedToCore(mqttTask, "MQTT-Task", 1024*10, NULL, 2, NULL,0);
+
+}
+
+void sendMQTTMessage(const char * topic, const char * data) {
+    if( connected ) {
+
+        int msg_id;
+        
+        msg_id = esp_mqtt_client_publish(client, topic, data, 0, 1, 0);
+
+        ESP_LOGI(TAG, "sent publish successful, msg_id=%d   %s   %s", msg_id, topic, data);
+    }
+    else {
+        ESP_LOGI(TAG, "Not connected to MQTT");
+    }
+}
+
+#else
+
+void sendMQTTMessage(const char * topic, const char * data) {
+        ESP_LOGI(TAG, "sent publish FAKE, msg_id=-   %s   %s", topic, data);
+}
+
+void mqtt_init(void) {};
+#endif

+ 9 - 0
main/mqtt.h

@@ -0,0 +1,9 @@
+#ifndef __MQTT_H__
+#define __MQTT_H__
+
+void mqtt_init(void);
+void sendMQTTMessage(const char * topic, const char * data);
+
+
+
+#endif

+ 16 - 0
main/sound.c

@@ -7,6 +7,10 @@
 #include "sdkconfig.h"
 #include "driver/dac.h"
 #include "math.h"
+#include "config.h"
+#include "mqtt.h"
+
+#ifdef SOUND_ENABLED
 
 #define DAC_CHANNEL       1
 #define DAC_PIN           GPIO_NUM_25   // GPIO pin for DAC output GPIO25=Channel 1
@@ -79,6 +83,18 @@ void enableNotificationSound(bool enable)
 {
     if (soundEnabled != enable) {
         ESP_LOGI("SOUND", "Notification sound %s", enable ? "enabled" : "disabled");
+        char mqtt_s[50];
+        char value_s[10];
+
+        sprintf(mqtt_s,"kitchen/fridge/doorAlarm");
+        sprintf(value_s,"%s",enable ? "active" : "inactive");
+        sendMQTTMessage(mqtt_s, value_s);
     }
     soundEnabled = enable;
 }
+
+#else
+void initSound() {};
+void enableNotificationSound(bool enable) {};
+#endif
+

+ 6 - 1
main/sound.h

@@ -1,6 +1,11 @@
+#ifndef __SOUND_H__
+#define __SOUND_H__
 
 #include <stdbool.h>
 
 void initSound();
 
-void enableNotificationSound(bool enable);
+void enableNotificationSound(bool enable);
+
+
+#endif

+ 185 - 0
main/wifi.c

@@ -0,0 +1,185 @@
+/* WiFi station Example
+
+   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 <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/event_groups.h"
+#include "esp_system.h"
+#include "esp_log.h"
+#include "driver/gpio.h"
+
+#include "wifi.h"
+
+
+#ifdef WIFI_ENABLED
+
+#include "nvs_flash.h"
+#include "esp_wifi.h"
+#include "esp_event.h"
+#include "lwip/err.h"
+#include "lwip/sys.h"
+
+
+// These are configured in idf.py menuconfig
+#define DEFAULT_SSID CONFIG_ESP_WIFI_SSID
+#define DEFAULT_PWD CONFIG_ESP_WIFI_PASSWORD
+
+
+static const char *TAG = "wifi";
+
+
+int latestRSSIValue = 0;
+int latestWiFiChannel = -1;
+
+/*******
+ * 0: Not initialized
+ * 5: Waiting for a connection, or other event
+ * 10: WIFI_EVENT_STA_START
+ * 15: Waiting for a connection
+ * 20: WIFI_EVENT_STA_DISCONNECTED
+ * 30: IP_EVENT_STA_GOT_IP
+ * 35: All is up and running
+ */
+
+static int wifiState = 0; // Local wifi-state
+
+int commIsUpAndRunning = 0; // Global info
+
+static void event_handler(void* arg, esp_event_base_t event_base,int32_t event_id, void* event_data)
+{
+    ESP_LOGI(TAG, "Got event: %s ID:%d",event_base, event_id);
+    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
+        wifiState = 10;
+    }
+    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
+        wifiState = 20;
+
+    }
+    else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
+        wifiState = 30;
+    }
+}
+
+static void setupAndConfigureWiFi(void)
+{
+    ESP_ERROR_CHECK(esp_netif_init());
+    ESP_ERROR_CHECK(esp_event_loop_create_default());
+
+    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
+    ESP_ERROR_CHECK(esp_wifi_init(&cfg));
+
+    ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL));
+    ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL));
+
+    // Initialize default station as network interface instance (esp-netif)
+    esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
+    assert(sta_netif);
+
+    // Initialize and start WiFi
+    wifi_config_t wifi_config = {
+        .sta = {
+            .ssid = DEFAULT_SSID,
+            .password = DEFAULT_PWD,
+            .scan_method = WIFI_ALL_CHANNEL_SCAN,
+            .sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
+            .threshold.rssi = -127,
+            .threshold.authmode = WIFI_AUTH_OPEN,
+        },
+    };
+    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
+    ESP_ERROR_CHECK(esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config));
+    ESP_ERROR_CHECK(esp_wifi_start());
+}
+
+void wifiTask(void *pvParameters)
+{
+    ESP_LOGI("WIFI", "wifiTask starting. Core:%d\n",xPortGetCoreID());
+    //Initialize NVS
+    esp_err_t ret = nvs_flash_init();
+    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
+        ESP_ERROR_CHECK(nvs_flash_erase());
+        ret = nvs_flash_init();
+    }
+    ESP_ERROR_CHECK(ret);
+
+    static TickType_t lastLogTime = 0;
+
+    while(1) {
+
+        switch (wifiState)
+        {
+        case 0:
+            // Time to setup everything
+            ESP_LOGI(TAG, "wifiTask state 0. Init-phase");
+            wifiState = 5;
+            setupAndConfigureWiFi();
+            break;
+        
+        case 10:
+            // Try to connect
+            ESP_LOGI(TAG, "wifiTask state 10: Try to scan and connect");
+            wifiState = 15;
+            esp_wifi_connect();
+            break;          
+        
+        case 20:
+            // We got disconnected ??
+            commIsUpAndRunning = 0;
+            ESP_LOGI(TAG, "wifiTask state 20: Disconnected");
+            wifiState = 15;
+            esp_wifi_connect();
+            break;          
+       
+        case 30:
+            // We got IP
+            commIsUpAndRunning = 1;
+            wifiState = 35;
+            ESP_LOGI(TAG, "wifiTask state 30. We got IP");
+            break;
+        
+        case 35:
+            // Everything is fine !
+
+            if( (xTaskGetTickCount()*portTICK_PERIOD_MS) > (lastLogTime + 500) ) {
+                static int logCounter = 5;
+                lastLogTime = xTaskGetTickCount() * portTICK_PERIOD_MS;
+                wifi_ap_record_t wifidata;
+                if (esp_wifi_sta_get_ap_info(&wifidata)==0){
+                    if( --logCounter == 0 ) {
+                        //ESP_LOGI(TAG, "WiFi RSSI:%d  Ch:%d",wifidata.rssi, wifidata.primary);
+                        logCounter=60;
+                    }
+                    latestRSSIValue = wifidata.rssi;
+                    latestWiFiChannel = wifidata.primary;
+                }
+            }
+            break;
+
+        case 5:
+        case 15:
+        default:
+            break;
+        }
+
+        vTaskDelay(250 / portTICK_PERIOD_MS);
+    }
+
+    vTaskDelete(NULL);
+}
+
+void initWifi(void)
+{
+    xTaskCreatePinnedToCore(wifiTask, "WiFi-Task", 1024*10, NULL, 2, NULL,0);
+}
+
+#else
+void initWifi(void) {};
+#endif

+ 15 - 0
main/wifi.h

@@ -0,0 +1,15 @@
+#ifndef __WIFI__
+#define __WIFI__
+
+#include "config.h"
+
+void initWifi(void);
+
+extern int latestRSSIValue;
+extern int commIsUpAndRunning; // Global info
+extern int latestWiFiChannel;
+
+
+
+
+#endif