Просмотр исходного кода

work on GPIO handler
bigfix: memory leak in GetJPGStream

Zwer2k 4 лет назад
Родитель
Сommit
7b8f10a14e
29 измененных файлов с 357 добавлено и 172 удалено
  1. 2 0
      code/components/jomjol_configfile/configFile.cpp
  2. 0 3
      code/components/jomjol_configfile/configFile.h
  3. 1 1
      code/components/jomjol_controlGPIO/CMakeLists.txt
  4. 106 35
      code/components/jomjol_controlGPIO/server_GPIO.cpp
  5. 15 5
      code/components/jomjol_controlGPIO/server_GPIO.h
  6. 1 1
      code/components/jomjol_controlcamera/ClassControllCamera.cpp
  7. 0 3
      code/components/jomjol_controlcamera/ClassControllCamera.h
  8. 5 2
      code/components/jomjol_controlcamera/server_camera.cpp
  9. 0 2
      code/components/jomjol_controlcamera/server_camera.h
  10. 1 1
      code/components/jomjol_fileserver_ota/CMakeLists.txt
  11. 57 45
      code/components/jomjol_fileserver_ota/server_file.cpp
  12. 1 0
      code/components/jomjol_fileserver_ota/server_ota.cpp
  13. 0 2
      code/components/jomjol_fileserver_ota/server_ota.h
  14. 1 1
      code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
  15. 93 10
      code/components/jomjol_mqtt/interface_mqtt.cpp
  16. 15 1
      code/components/jomjol_mqtt/interface_mqtt.h
  17. 1 1
      code/components/jomjol_tfliteclass/CMakeLists.txt
  18. 13 9
      code/components/jomjol_tfliteclass/server_tflite.cpp
  19. 0 2
      code/components/jomjol_tfliteclass/server_tflite.h
  20. 6 10
      code/main/main.cpp
  21. 8 7
      code/main/server_main.cpp
  22. 4 4
      code/main/server_main.h
  23. 4 4
      code/main/version.cpp
  24. 4 4
      code/version.cpp
  25. BIN
      firmware/bootloader.bin
  26. BIN
      firmware/firmware.bin
  27. BIN
      firmware/html.zip
  28. 18 18
      sd-card/html/edit_config_param.html
  29. 1 1
      sd-card/html/readconfigparam.js

+ 2 - 0
code/components/jomjol_configfile/configFile.cpp

@@ -5,6 +5,8 @@
 #include "Helper.h"
 #include "configFile.h"
 
+//static const char *TAGCONFIGFILE = "configFile";
+
 ConfigFile::ConfigFile(std::string filePath)
 {
     std::string config = FormatFileName(filePath);

+ 0 - 3
code/components/jomjol_configfile/configFile.h

@@ -1,9 +1,6 @@
 #include <string>
 #include <vector>
 
-static const char *TAGCONFIGFILE = "configFile";
-
-
 class ConfigFile {
 public:
     ConfigFile(std::string filePath);

+ 1 - 1
code/components/jomjol_controlGPIO/CMakeLists.txt

@@ -4,6 +4,6 @@ list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/proto
 
 idf_component_register(SRCS ${app_sources}
                     INCLUDE_DIRS "."
-                    REQUIRES esp_http_server jomjol_logfile jomjol_configfile)
+                    REQUIRES esp_http_server jomjol_logfile jomjol_configfile jomjol_mqtt)
 
 

+ 106 - 35
code/components/jomjol_controlGPIO/server_GPIO.cpp

@@ -1,4 +1,5 @@
 #include <string>
+#include <functional>
 #include "string.h"
 
 #include <string.h>
@@ -7,7 +8,6 @@
 #include "esp_system.h"
 #include "esp_event.h"
 #include "esp_log.h"
-#include "driver/gpio.h"
 //#include "errno.h"
 
 #include <sys/stat.h>
@@ -19,40 +19,70 @@
 #include "ClassLogFile.h"
 #include "configFile.h"
 #include "Helper.h"
+#include "interface_mqtt.h"
+
+static const char *TAG_SERVERGPIO = "server_GPIO";
 
 // #define DEBUG_DETAIL_ON 
 
-GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, bool mqttEnable, bool httpEnable) 
+GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable) 
 {
     _gpio = gpio;
     _name = name; 
     _mode = mode;
     _interruptType = interruptType;    
+    _mqttTopic = mqttTopic;
 
     //initGPIO();
 }
 
 GpioPin::~GpioPin()
 {
-    printf("reset GPIO pin %d", _gpio);
+    ESP_LOGI(TAG_SERVERGPIO,"reset GPIO pin %d", _gpio);
+    if (_interruptType != GPIO_INTR_DISABLE) {
+        //hook isr handler for specific gpio pin
+        gpio_isr_handler_remove(_gpio);
+    }
     gpio_reset_pin(_gpio);
 }
 
+static void IRAM_ATTR gpio_isr_handler(void* arg)
+{
+    GpioPin* gpioPin = (GpioPin*) arg;
+    gpioPin->gpioInterrupt();
+}
+
+void GpioPin::gpioInterrupt () {
+    if (_mqttTopic != "") {
+        MQTTPublish(_mqttTopic, (gpio_get_level(_gpio) == 1) ? "true" : "false");
+    }
+}
+
 void GpioPin::init()
 {
     gpio_config_t io_conf;
     //set interrupt
     io_conf.intr_type = _interruptType;
     //set as output mode
-    io_conf.mode = _mode == gpio_pin_mode_t::GPIO_PIN_MODE_OUTPUT ? gpio_mode_t::GPIO_MODE_OUTPUT : gpio_mode_t::GPIO_MODE_INPUT;
+    io_conf.mode = _mode == GPIO_PIN_MODE_OUTPUT ? gpio_mode_t::GPIO_MODE_OUTPUT : gpio_mode_t::GPIO_MODE_INPUT;
     //bit mask of the pins that you want to set,e.g.GPIO18/19
     io_conf.pin_bit_mask = (1ULL << _gpio);
     //set pull-down mode
-    io_conf.pull_down_en = _mode == gpio_pin_mode_t::GPIO_PIN_MODE_INPUT_PULLDOWN ? gpio_pulldown_t::GPIO_PULLDOWN_ENABLE : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE;
+    io_conf.pull_down_en = _mode == GPIO_PIN_MODE_INPUT_PULLDOWN ? gpio_pulldown_t::GPIO_PULLDOWN_ENABLE : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE;
     //set pull-up mode
-    io_conf.pull_up_en = _mode == gpio_pin_mode_t::GPIO_PIN_MODE_INPUT_PULLDOWN ? gpio_pullup_t::GPIO_PULLUP_ENABLE : gpio_pullup_t::GPIO_PULLUP_DISABLE;
+    io_conf.pull_up_en = _mode == GPIO_PIN_MODE_INPUT_PULLDOWN ? gpio_pullup_t::GPIO_PULLUP_ENABLE : gpio_pullup_t::GPIO_PULLUP_DISABLE;
     //configure GPIO with the given settings
     gpio_config(&io_conf);
+
+    if (_interruptType != GPIO_INTR_DISABLE) {
+        //hook isr handler for specific gpio pin
+        gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*) this);
+    }
+
+    if ((_mqttTopic != "") && ((_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_OUTPUT_PWM))) {
+        std::function<bool(std::string, char*, int)> f = std::bind(&GpioPin::handleMQTT, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
+        MQTTregisterSubscribeFunction(_mqttTopic, f);
+    }
 }
 
 bool GpioPin::getValue(std::string* errorText)
@@ -65,37 +95,59 @@ bool GpioPin::getValue(std::string* errorText)
 }
 
 void GpioPin::setValue(bool value, std::string* errorText)
-{   
+{
+    printf("setValue %d\r\n", value);
+   
     if ((_mode != GPIO_PIN_MODE_OUTPUT) && (_mode != GPIO_PIN_MODE_OUTPUT_PWM)) {
         (*errorText) = "GPIO is not in output mode";
+    } else {
+        gpio_set_level(_gpio, value);
+    }
+}
+
+bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
+    printf("handleMQTT data %.*s\r\n", data_len, data);
+    
+    std::string dataStr(data, data_len);
+    dataStr = toLower(dataStr);
+    std::string errorText = "";
+    if ((dataStr == "true") || (dataStr == "1")) {
+        setValue(true, &errorText);
+    } else if ((dataStr == "false") || (dataStr == "0")) {
+        setValue(false, &errorText);    
+    } else {
+        errorText = "wrong value ";
+        errorText.append(data, data_len);
+    }
+
+    if (errorText != "") {
+        printf(errorText.c_str());
     }
 
-    gpio_set_level(_gpio, value);
+    return (errorText == "");
 }
 
 
 esp_err_t callHandleHttpRequest(httpd_req_t *req)
 {
-    printf("callHandleHttpRequest\n");
+    ESP_LOGI(TAG_SERVERGPIO,"callHandleHttpRequest");
     GpioHandler *gpioHandler = (GpioHandler*)req->user_ctx;
     return gpioHandler->handleHttpRequest(req);
 }
 
 void taskGpioHandler(void *pvParameter)
 {
-    printf("taskGpioHandler\n");
+    ESP_LOGI(TAG_SERVERGPIO,"taskGpioHandler");
     ((GpioHandler*)pvParameter)->init();
 }
 
 GpioHandler::GpioHandler(std::string configFile, httpd_handle_t httpServer) 
 {
-    printf("---- start GpioHandler ----\n");
+    ESP_LOGI(TAG_SERVERGPIO,"start GpioHandler");
     _configFile = configFile;
-    printf("-1-\n");
     _httpServer = httpServer;
-    printf("-2-\n");
 
-    printf("register GPIO Uri\n");
+    ESP_LOGI(TAG_SERVERGPIO, "register GPIO Uri");
     registerGpioUri();
 
     //xTaskCreate((TaskFunction_t)&taskGpioHandler, "taskGpioHandler", configMINIMAL_STACK_SIZE * 64, this, tskIDLE_PRIORITY+1, &xHandletaskGpioHandler);
@@ -110,9 +162,8 @@ GpioHandler::~GpioHandler()  {
 
 void GpioHandler::init()
 {
-    printf("freemem -3.1-: %u\n", esp_get_free_heap_size());
     // TickType_t xDelay = 60000 / portTICK_PERIOD_MS;
-    // printf("wait before start %ldms\n", (long) xDelay);
+    // printf("wait before start %ldms\r\n", (long) xDelay);
     // vTaskDelay( xDelay );
 
     if (gpioMap == NULL) {
@@ -121,17 +172,18 @@ void GpioHandler::init()
         clear();
     }
     
-    printf("read GPIO config and init GPIO\n");
-    printf("freemem -3.2-: %u\n", esp_get_free_heap_size());
+    ESP_LOGI(TAG_SERVERGPIO, "read GPIO config and init GPIO");
     readConfig();
-    printf("freemem -3.3-: %u\n", esp_get_free_heap_size());
 
     for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
         it->second->init();
     }
-    printf("freemem -3.4-: %u\n", esp_get_free_heap_size());
 
-    printf("GPIO init comleted\n");
+    ESP_LOGI(TAG_SERVERGPIO, "GPIO init comleted");
+}
+
+void GpioHandler::destroy() {
+    clear();
 }
 
 bool GpioHandler::readConfig() 
@@ -150,6 +202,8 @@ bool GpioHandler::readConfig()
     if (eof)
         return false;
 
+    std::string mainTopicMQTT = "";
+    bool registerISR = false;
     while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line))
     {
         zerlegt = configFile.ZerlegeZeile(line);
@@ -158,9 +212,13 @@ bool GpioHandler::readConfig()
         // if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
         // {
         //     std::string gpioStr = pieces_match[1];
-        if (zerlegt[0].rfind("IO", 0) == 0)
+        printf("conf param %s\r\n", toUpper(zerlegt[0]).c_str());
+        if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") {
+            printf("MAINTOPICMQTT found\r\n");
+            mainTopicMQTT = zerlegt[1];
+        } else if (zerlegt[0].rfind("IO", 0) == 0)
         {
-            printf("Enable GP%s in %s mode\n", zerlegt[0].c_str(), zerlegt[1].c_str());
+            ESP_LOGI(TAG_SERVERGPIO,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str());
             std::string gpioStr = zerlegt[0].substr(2, 2);
             gpio_num_t gpioNr = (gpio_num_t)atoi(gpioStr.c_str());
             gpio_pin_mode_t pinMode = resolvePinMode(toLower(zerlegt[1]));
@@ -168,10 +226,21 @@ bool GpioHandler::readConfig()
             uint16_t dutyResolution = (uint8_t)atoi(zerlegt[3].c_str());
             bool mqttEnabled = toLower(zerlegt[4]) == "true";
             bool httpEnabled = toLower(zerlegt[5]) == "true";
-            (*gpioMap)[gpioNr] = new GpioPin(gpioNr, zerlegt[6].c_str(), pinMode, intType,dutyResolution, mqttEnabled, httpEnabled);
+            std::string mqttTopic = mqttEnabled ? (mainTopicMQTT + "/" + zerlegt[6]) : "";
+            GpioPin* gpioPin = new GpioPin(gpioNr, zerlegt[6].c_str(), pinMode, intType,dutyResolution, mqttTopic, httpEnabled);
+            (*gpioMap)[gpioNr] = gpioPin;
+
+            if (intType != GPIO_INTR_DISABLE) {
+                registerISR = true;
+            }
         }
     }
 
+    if (registerISR) {
+        //install gpio isr service
+        gpio_install_isr_service(ESP_INTR_FLAG_LOWMED | ESP_INTR_FLAG_IRAM);
+    }
+
     return true;
 }
 
@@ -181,11 +250,13 @@ void GpioHandler::clear()
         delete it->second;
     }
     gpioMap->clear();
+
+    // gpio_uninstall_isr_service(); can't uninstall, isr service is used by camera
 }
  
 void GpioHandler::registerGpioUri() 
 {
-    ESP_LOGI(TAGPARTGPIO, "server_GPIO - Registering URI handlers");
+    ESP_LOGI(TAG_SERVERGPIO, "server_GPIO - Registering URI handlers");
     
     httpd_uri_t camuri = { };
     camuri.method    = HTTP_GET;
@@ -197,7 +268,7 @@ void GpioHandler::registerGpioUri()
 
 esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
 {
-    printf("handleHttpRequest\n");
+    ESP_LOGI(TAG_SERVERGPIO, "handleHttpRequest");
 
 #ifdef DEBUG_DETAIL_ON 
     LogFile.WriteHeapInfo("handler_switch_GPIO - Start");    
@@ -208,14 +279,14 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
     char _valueGPIO[30];    
     char _valueStatus[30];    
     std::string gpio, status;
-    printf("-1-\n");
+    printf("-1-\r\n");
 
     if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) {
-        printf("Query: "); printf(_query); printf("\n");
+        printf("Query: "); printf(_query); printf("\r\n");
         
         if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK)
         {
-            printf("GPIO is found "); printf(_valueGPIO); printf("\n"); 
+            printf("GPIO is found "); printf(_valueGPIO); printf("\r\n"); 
             gpio = std::string(_valueGPIO);
         } else {
             std::string resp_str = "GPIO No is not defined";
@@ -224,15 +295,15 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
         }
         if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK)
         {
-            printf("Status is found "); printf(_valueStatus); printf("\n"); 
+            printf("Status is found "); printf(_valueStatus); printf("\r\n"); 
             status = std::string(_valueStatus);
         }
     } else {
-        char* resp_str = "Error in call. Use /GPIO?GPIO=12&Status=high";
+        const char* resp_str = "Error in call. Use /GPIO?GPIO=12&Status=high";
         httpd_resp_send(req, resp_str, strlen(resp_str));    
         return ESP_OK;
     }
-    printf("-2-\n");
+    printf("-2-\r\n");
 
     status = toUpper(status);
     if ((status != "HIGH") && (status != "LOW") && (status != "TRUE") && (status != "FALSE") && (status != "0") && (status != "1") && (status != ""))
@@ -242,7 +313,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
         httpd_resp_sendstr_chunk(req, NULL);          
         return ESP_OK;    
     }
-    printf("-3-\n");
+    printf("-3-\r\n");
 
     int gpionum = stoi(gpio);
 
@@ -263,7 +334,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
         return ESP_OK;     
     }
     
-    printf("-4-\n");
+    printf("-4-\r\n");
 
     if (status == "") 
     {
@@ -285,7 +356,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
         httpd_resp_sendstr_chunk(req, resp_str.c_str());
         httpd_resp_sendstr_chunk(req, NULL);
     }
-    printf("-5-\n");
+    printf("-5-\r\n");
           
     return ESP_OK;    
 };

+ 15 - 5
code/components/jomjol_controlGPIO/server_GPIO.h

@@ -1,12 +1,14 @@
+#ifndef SERVER_GPIO_H
+#define SERVER_GPIO_H
+
 #include <esp_log.h>
 
 #include <esp_http_server.h>
 #include <map>
+#include "driver/gpio.h"
 
 //#include "ClassControllCamera.h"
 
-static const char *TAGPARTGPIO = "server_GPIO";
-
 typedef enum {
     GPIO_PIN_MODE_DISABLED              = 0x0,
     GPIO_PIN_MODE_INPUT                 = 0x1,
@@ -18,20 +20,24 @@ typedef enum {
     GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X = 0x5,
 } gpio_pin_mode_t;
 
+
 class GpioPin {
 public:
-    GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, bool mqttEnable, bool httpEnable);
+    GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable);
     ~GpioPin();
 
     bool getValue(std::string* errorText);
     void setValue(bool value, std::string* errorText);
     void init();
+    bool handleMQTT(std::string, char* data, int data_len);
+    void gpioInterrupt();
 
 private:
     gpio_num_t _gpio;
     const char* _name;
     gpio_pin_mode_t _mode;
     gpio_int_type_t _interruptType;
+    std::string _mqttTopic;
 };
 
 esp_err_t callHandleHttpRequest(httpd_req_t *req);
@@ -43,7 +49,7 @@ public:
     ~GpioHandler();
     
     void init();
-    void clear();
+    void destroy();
     void registerGpioUri();
     esp_err_t handleHttpRequest(httpd_req_t *req);  
 
@@ -54,9 +60,13 @@ private:
     TaskHandle_t xHandletaskGpioHandler = NULL;
 
     bool readConfig();
+    void clear();
+    
     gpio_num_t resolvePinNr(uint8_t pinNr);
     gpio_pin_mode_t resolvePinMode(std::string input);
     gpio_int_type_t resolveIntType(std::string input);
 };
 
-void GpioHandlerStart();
+void GpioHandlerStart();
+
+#endif //SERVER_GPIO_H

+ 1 - 1
code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -50,7 +50,7 @@
 #define CAM_PIN_HREF 23
 #define CAM_PIN_PCLK 22
 
-static const char *TAG = "example:take_picture";
+static const char *TAGCAMERACLASS = "server_part_camera"; 
 
 static camera_config_t camera_config = {
     .pin_pwdn = CAM_PIN_PWDN,

+ 0 - 3
code/components/jomjol_controlcamera/ClassControllCamera.h

@@ -16,9 +16,6 @@
 #define CAMERA_MODEL_AI_THINKER
 
 
-static const char *TAGCAMERACLASS = "server_part_camera"; 
-
-
 class CCamera {
     protected:
         int ActualQuality;

+ 5 - 2
code/components/jomjol_controlcamera/server_camera.cpp

@@ -12,14 +12,17 @@
 char scratch2[SCRATCH_BUFSIZE2];
 
 //#define DEBUG_DETAIL_ON   
-
+static const char *TAGPARTCAMERA = "server_camera";
 
 
 void PowerResetCamera(){
         ESP_LOGD(TAGPARTCAMERA, "Resetting camera by power down line");
-        gpio_config_t conf = { 0 };
+        gpio_config_t conf;
+        conf.intr_type = GPIO_INTR_DISABLE;
         conf.pin_bit_mask = 1LL << GPIO_NUM_32;
         conf.mode = GPIO_MODE_OUTPUT;
+        conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
+        conf.pull_up_en = GPIO_PULLUP_DISABLE;
         gpio_config(&conf);
 
         // carefull, logic is inverted compared to reset pin

+ 0 - 2
code/components/jomjol_controlcamera/server_camera.h

@@ -7,8 +7,6 @@
 
 //#include "ClassControllCamera.h"
 
-static const char *TAGPARTCAMERA = "server_camera";
-
 void register_server_camera_uri(httpd_handle_t server);
 
 void PowerResetCamera();

+ 1 - 1
code/components/jomjol_fileserver_ota/CMakeLists.txt

@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 
 idf_component_register(SRCS ${app_sources}
                     INCLUDE_DIRS "."
-                    REQUIRES tfmicro esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper)
+                    REQUIRES main tfmicro esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper)
 
 

+ 57 - 45
code/components/jomjol_fileserver_ota/server_file.cpp

@@ -26,9 +26,12 @@
 #include <esp_spiffs.h>
 #include "esp_http_server.h"
 
+#include "defines.h"
 #include "ClassLogFile.h"
 
 #include "server_help.h"
+#include "interface_mqtt.h"
+#include "server_main.h"
 
 #include "Helper.h"
 #include "miniz.h"
@@ -53,17 +56,17 @@ struct file_server_data {
     char scratch[SCRATCH_BUFSIZE];
 };
 
-static const char *TAG = "file_server";
+static const char *TAG_FILESERVER = "file_server";
 
 /* Handler to redirect incoming GET request for /index.html to /
  * This can be overridden by uploading file with same name */
-static esp_err_t index_html_get_handler(httpd_req_t *req)
-{
-    httpd_resp_set_status(req, "307 Temporary Redirect");
-    httpd_resp_set_hdr(req, "Location", "/");
-    httpd_resp_send(req, NULL, 0);  // Response body can be empty
-    return ESP_OK;
-}
+// static esp_err_t index_html_get_handler(httpd_req_t *req)
+// {
+//     httpd_resp_set_status(req, "307 Temporary Redirect");
+//     httpd_resp_set_hdr(req, "Location", "/");
+//     httpd_resp_send(req, NULL, 0);  // Response body can be empty
+//     return ESP_OK;
+// }
 
 /* Send HTTP response with a run-time generated html consisting of
  * a list of all files and folders under the requested path.
@@ -95,7 +98,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
     printf("entrypath: <%s>\n", entrypath);    
 
     if (!dir) {
-        ESP_LOGE(TAG, "Failed to stat dir : %s", dirpath);
+        ESP_LOGE(TAG_FILESERVER, "Failed to stat dir : %s", dirpath);
         /* Respond with 404 Not Found */
         httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
         return ESP_FAIL;
@@ -115,7 +118,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
             if (chunksize > 0){
                 if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
                 fclose(fd);
-                ESP_LOGE(TAG, "File sending failed!");
+                ESP_LOGE(TAG_FILESERVER, "File sending failed!");
                 return ESP_FAIL;
                 }
             }
@@ -154,11 +157,11 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
             strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
             printf("Entrypath: %s\n", entrypath);
             if (stat(entrypath, &entry_stat) == -1) {
-                ESP_LOGE(TAG, "Failed to stat %s : %s", entrytype, entry->d_name);
+                ESP_LOGE(TAG_FILESERVER, "Failed to stat %s : %s", entrytype, entry->d_name);
                 continue;
             }
             sprintf(entrysize, "%ld", entry_stat.st_size);
-            ESP_LOGI(TAG, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
+            ESP_LOGI(TAG_FILESERVER, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
 
             /* Send chunk of HTML file containing table entries with file name and size */
             httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
@@ -206,19 +209,19 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
     LogFile.WriteToFile("logfileact_get_handler");
     char filepath[FILE_PATH_MAX];
     FILE *fd = NULL;
-    struct stat file_stat;
+    //struct stat file_stat;
     printf("uri: %s\n", req->uri);
 
-    const char filename = 'log_current.txt'; 
+    const char* filename = "log_current.txt"; 
 
-    printf("uri: %s, filename: %s, filepath: %s\n", req->uri, &filename, filepath);
+    printf("uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
 
     std::string currentfilename = LogFile.GetCurrentFileName();
 
 
     fd = OpenFileAndWait(currentfilename.c_str(), "r");
     if (!fd) {
-        ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
+        ESP_LOGE(TAG_FILESERVER, "Failed to read existing file : %s", filepath);
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
         return ESP_FAIL;
@@ -226,8 +229,8 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
 
     httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
 
-//    ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
-    set_content_type_from_file(req, &filename);
+//    ESP_LOGI(TAG_FILESERVER, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
+    set_content_type_from_file(req, filename);
 
     /* Retrieve the pointer to scratch buffer for temporary storage */
     char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
@@ -239,7 +242,7 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
         /* Send the buffer contents as HTTP response chunk */
         if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
             fclose(fd);
-            ESP_LOGE(TAG, "File sending failed!");
+            ESP_LOGE(TAG_FILESERVER, "File sending failed!");
             /* Abort sending file */
             httpd_resp_sendstr_chunk(req, NULL);
             /* Respond with 500 Internal Server Error */
@@ -252,7 +255,7 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
 
     /* Close file after sending complete */
     fclose(fd);
-    ESP_LOGI(TAG, "File sending complete");
+    ESP_LOGI(TAG_FILESERVER, "File sending complete");
 
     /* Respond with an empty chunk to signal HTTP response completion */
     httpd_resp_send_chunk(req, NULL, 0);
@@ -284,7 +287,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
 
 
     if (!filename) {
-        ESP_LOGE(TAG, "Filename is too long");
+        ESP_LOGE(TAG_FILESERVER, "Filename is too long");
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
         return ESP_FAIL;
@@ -297,11 +300,11 @@ static esp_err_t download_get_handler(httpd_req_t *req)
         if (buf_len > 1) {
             char buf[buf_len];
             if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
-                ESP_LOGI(TAG, "Found URL query => %s", buf);
+                ESP_LOGI(TAG_FILESERVER, "Found URL query => %s", buf);
                 char param[32];
                 /* Get value of expected key from query string */
                 if (httpd_query_key_value(buf, "readonly", param, sizeof(param)) == ESP_OK) {
-                    ESP_LOGI(TAG, "Found URL query parameter => readonly=%s", param);
+                    ESP_LOGI(TAG_FILESERVER, "Found URL query parameter => readonly=%s", param);
                     readonly = param && strcmp(param,"true")==0;
                 }
             }
@@ -316,7 +319,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
 
         /* If file not present on SPIFFS check if URI
          * corresponds to one of the hardcoded paths */
-        ESP_LOGE(TAG, "Failed to stat file : %s", filepath);
+        ESP_LOGE(TAG_FILESERVER, "Failed to stat file : %s", filepath);
         /* Respond with 404 Not Found */
         httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
         return ESP_FAIL;
@@ -324,7 +327,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
 
     fd = OpenFileAndWait(filepath, "r");
     if (!fd) {
-        ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
+        ESP_LOGE(TAG_FILESERVER, "Failed to read existing file : %s", filepath);
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
         return ESP_FAIL;
@@ -332,7 +335,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
 
     httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
 
-    ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
+    ESP_LOGI(TAG_FILESERVER, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
     set_content_type_from_file(req, filename);
 
     /* Retrieve the pointer to scratch buffer for temporary storage */
@@ -345,7 +348,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
         /* Send the buffer contents as HTTP response chunk */
         if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
             fclose(fd);
-            ESP_LOGE(TAG, "File sending failed!");
+            ESP_LOGE(TAG_FILESERVER, "File sending failed!");
             /* Abort sending file */
             httpd_resp_sendstr_chunk(req, NULL);
             /* Respond with 500 Internal Server Error */
@@ -358,7 +361,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
 
     /* Close file after sending complete */
     fclose(fd);
-    ESP_LOGI(TAG, "File sending complete");
+    ESP_LOGI(TAG_FILESERVER, "File sending complete");
 
     /* Respond with an empty chunk to signal HTTP response completion */
     httpd_resp_send_chunk(req, NULL, 0);
@@ -385,13 +388,13 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
 
     /* Filename cannot have a trailing '/' */
     if (filename[strlen(filename) - 1] == '/') {
-        ESP_LOGE(TAG, "Invalid filename : %s", filename);
+        ESP_LOGE(TAG_FILESERVER, "Invalid filename : %s", filename);
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
         return ESP_FAIL;
     }
 
     if (stat(filepath, &file_stat) == 0) {
-        ESP_LOGE(TAG, "File already exists : %s", filepath);
+        ESP_LOGE(TAG_FILESERVER, "File already exists : %s", filepath);
         /* Respond with 400 Bad Request */
         httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File already exists");
         return ESP_FAIL;
@@ -399,7 +402,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
 
     /* File cannot be larger than a limit */
     if (req->content_len > MAX_FILE_SIZE) {
-        ESP_LOGE(TAG, "File too large : %d bytes", req->content_len);
+        ESP_LOGE(TAG_FILESERVER, "File too large : %d bytes", req->content_len);
         /* Respond with 400 Bad Request */
         httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
                             "File size must be less than "
@@ -411,13 +414,13 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
 
     fd = OpenFileAndWait(filepath, "w");
     if (!fd) {
-        ESP_LOGE(TAG, "Failed to create file : %s", filepath);
+        ESP_LOGE(TAG_FILESERVER, "Failed to create file : %s", filepath);
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
         return ESP_FAIL;
     }
 
-    ESP_LOGI(TAG, "Receiving file : %s...", filename);
+    ESP_LOGI(TAG_FILESERVER, "Receiving file : %s...", filename);
 
     /* Retrieve the pointer to scratch buffer for temporary storage */
     char *buf = ((struct file_server_data *)req->user_ctx)->scratch;
@@ -429,7 +432,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
 
     while (remaining > 0) {
 
-        ESP_LOGI(TAG, "Remaining size : %d", remaining);
+        ESP_LOGI(TAG_FILESERVER, "Remaining size : %d", remaining);
         /* Receive the file part by part into a buffer */
         if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) {
             if (received == HTTPD_SOCK_ERR_TIMEOUT) {
@@ -442,7 +445,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
             fclose(fd);
             unlink(filepath);
 
-            ESP_LOGE(TAG, "File reception failed!");
+            ESP_LOGE(TAG_FILESERVER, "File reception failed!");
             /* Respond with 500 Internal Server Error */
             httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
             return ESP_FAIL;
@@ -455,7 +458,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
             fclose(fd);
             unlink(filepath);
 
-            ESP_LOGE(TAG, "File write failed!");
+            ESP_LOGE(TAG_FILESERVER, "File write failed!");
             /* Respond with 500 Internal Server Error */
             httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
             return ESP_FAIL;
@@ -468,7 +471,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
 
     /* Close file upon upload completion */
     fclose(fd);
-    ESP_LOGI(TAG, "File reception complete");
+    ESP_LOGI(TAG_FILESERVER, "File reception complete");
 
     std::string directory = std::string(filepath);
 	size_t zw = directory.find("/");
@@ -496,6 +499,15 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
     httpd_resp_set_status(req, "303 See Other");
     httpd_resp_set_hdr(req, "Location", directory.c_str());
     httpd_resp_sendstr(req, "File uploaded successfully");
+
+    if (strcmp(filepath, CONFIG_FILE) == 0) {
+        printf("New config foung. Reload handler.");
+        MQTTdestroy();
+        if (gpioHandler != NULL) {
+            gpioHandler->destroy();
+        }
+    }
+
     return ESP_OK;
 }
 
@@ -567,19 +579,19 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
 
         /* Filename cannot have a trailing '/' */
         if (filename[strlen(filename) - 1] == '/') {
-            ESP_LOGE(TAG, "Invalid filename : %s", filename);
+            ESP_LOGE(TAG_FILESERVER, "Invalid filename : %s", filename);
             httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
             return ESP_FAIL;
         }
 
         if (stat(filepath, &file_stat) == -1) {
-            ESP_LOGE(TAG, "File does not exist : %s", filename);
+            ESP_LOGE(TAG_FILESERVER, "File does not exist : %s", filename);
             /* Respond with 400 Bad Request */
             httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File does not exist");
             return ESP_FAIL;
         }
 
-        ESP_LOGI(TAG, "Deleting file : %s", filename);
+        ESP_LOGI(TAG_FILESERVER, "Deleting file : %s", filename);
         /* Delete file */
         unlink(filepath);
 
@@ -623,7 +635,7 @@ void delete_all_in_directory(std::string _directory)
     std::string filename;
 
     if (!dir) {
-        ESP_LOGE(TAG, "Failed to stat dir : %s", _directory.c_str());
+        ESP_LOGE(TAG_FILESERVER, "Failed to stat dir : %s", _directory.c_str());
         return;
     }
 
@@ -632,7 +644,7 @@ void delete_all_in_directory(std::string _directory)
         if (!(entry->d_type == DT_DIR)){
             if (strcmp("wlan.ini", entry->d_name) != 0){                    // auf wlan.ini soll nicht zugegriffen werden !!!
                 filename = _directory + "/" + std::string(entry->d_name);
-                ESP_LOGI(TAG, "Deleting file : %s", filename.c_str());
+                ESP_LOGI(TAG_FILESERVER, "Deleting file : %s", filename.c_str());
                 /* Delete file */
                 unlink(filename.c_str());    
             }
@@ -722,19 +734,19 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
     /* Validate file storage base path */
     if (!base_path) {
 //    if (!base_path || strcmp(base_path, "/spiffs") != 0) {
-        ESP_LOGE(TAG, "File server base_path not set");
+        ESP_LOGE(TAG_FILESERVER, "File server base_path not set");
 //        return ESP_ERR_INVALID_ARG;
     }
 
     if (server_data) {
-        ESP_LOGE(TAG, "File server already started");
+        ESP_LOGE(TAG_FILESERVER, "File server already started");
 //        return ESP_ERR_INVALID_STATE;
     }
 
     /* Allocate memory for server data */
     server_data = (file_server_data *) calloc(1, sizeof(struct file_server_data));
     if (!server_data) {
-        ESP_LOGE(TAG, "Failed to allocate memory for server data");
+        ESP_LOGE(TAG_FILESERVER, "Failed to allocate memory for server data");
 //        return ESP_ERR_NO_MEM;
     }
     strlcpy(server_data->base_path, base_path,

+ 1 - 0
code/components/jomjol_fileserver_ota/server_ota.cpp

@@ -46,6 +46,7 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
 
 
 #define OTA_URL_SIZE 256
+static const char *TAGPARTOTA = "server_ota";
 
 
 static void infinite_loop(void)

+ 0 - 2
code/components/jomjol_fileserver_ota/server_ota.h

@@ -4,8 +4,6 @@
 
 //#include "ClassControllCamera.h"
 
-static const char *TAGPARTOTA = "server_ota";
-
 void register_server_ota_sdcard_uri(httpd_handle_t server);
 void CheckOTAUpdate();
 void doReboot();

+ 1 - 1
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp

@@ -112,7 +112,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
 
     }
 
-    if ((uri.length() > 0) && (topic.length() > 0)) 
+    if (!MQTTisConnected() && (uri.length() > 0) && (topic.length() > 0)) 
     {
         MQTTInit(uri, clientname, user, password, topicError, 60);
     }

+ 93 - 10
code/components/jomjol_mqtt/interface_mqtt.cpp

@@ -5,8 +5,9 @@
 #include "mqtt_client.h"
 #include "ClassLogFile.h"
 
-static const char *TAG = "interface_mqtt";
+static const char *TAG_INTERFACEMQTT = "interface_mqtt";
 
+std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;  
 bool debugdetail = true;
 
 // #define CONFIG_BROKER_URL "mqtt://192.168.178.43:1883"
@@ -23,44 +24,70 @@ void MQTTPublish(std::string _key, std::string _content, int retained_flag){
         msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
         zw = "sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
         if (debugdetail) LogFile.WriteToFile(zw);
-        ESP_LOGI(TAG, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
+        ESP_LOGI(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
     }
     else {
-        ESP_LOGI(TAG, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
+        ESP_LOGI(TAG_INTERFACEMQTT, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
     }
 }
 
 
 static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
 {
+    int msg_id;
+    std::string topic = "";
     switch (event->event_id) {
+        case MQTT_EVENT_BEFORE_CONNECT:
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_CONNECTED");
+            break;
         case MQTT_EVENT_CONNECTED:
-            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_CONNECTED");
             mqtt_connected = true;
+            MQTTsubscribeFunctions();
             break;
         case MQTT_EVENT_DISCONNECTED:
-            ESP_LOGI(TAG, "MQTT_EVENT_DISCONNECTED");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_DISCONNECTED");
+            break;
+        case MQTT_EVENT_SUBSCRIBED:
+            ESP_LOGI(TAG_INTERFACEMQTT, "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_INTERFACEMQTT, "sent publish successful, msg_id=%d", msg_id);
+            break;
+        case MQTT_EVENT_UNSUBSCRIBED:
+            ESP_LOGI(TAG_INTERFACEMQTT, "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);
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
             break;
         case MQTT_EVENT_DATA:
-            ESP_LOGI(TAG, "MQTT_EVENT_DATA");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_DATA");
             printf("TOPIC=%.*s\r\n", event->topic_len, event->topic);
             printf("DATA=%.*s\r\n", event->data_len, event->data);
+            topic.assign(event->topic, event->topic_len);
+            if (subscribeFunktionMap != NULL) {
+                for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
+                    printf("compare %s %s\r\n", it->first.c_str(), topic.c_str());
+                }
+                if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
+                    printf("call handler function\r\n");
+                    (*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
+                }
+            } else {
+                printf("no handler available\r\n");
+            }
             break;
         case MQTT_EVENT_ERROR:
-            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_ERROR");
             break;
         default:
-            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
+            ESP_LOGI(TAG_INTERFACEMQTT, "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);
+    ESP_LOGD(TAG_INTERFACEMQTT, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
     mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
 }
 
@@ -91,3 +118,59 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
 
     MQTTPublish(_LWTContext, "", 1);
 }
+
+void MQTTdestroy() {
+    if (client != NULL) {
+        esp_mqtt_client_stop(client);
+        esp_mqtt_client_destroy(client);
+    }
+}
+
+bool MQTTisConnected() {
+    return mqtt_connected;
+}
+
+void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
+    printf("MQTTregisterSubscribeFunction %s\r\n", topic.c_str());
+    if (subscribeFunktionMap == NULL) {
+        subscribeFunktionMap = new std::map<std::string, std::function<bool(std::string, char*, int)>>();
+    }
+
+    if ((*subscribeFunktionMap)[topic] != NULL) {
+        ESP_LOGW(TAG_INTERFACEMQTT, "topic %s already registred for subscription", topic.c_str());
+        return;
+    }
+
+    (*subscribeFunktionMap)[topic] = func;
+
+    if (mqtt_connected) {
+        int msg_id = esp_mqtt_client_subscribe(client, topic.c_str(), 0);
+        ESP_LOGI(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
+    }
+}
+
+void MQTTsubscribeFunctions(){
+    if (subscribeFunktionMap != NULL) {
+        if (mqtt_connected) {
+            for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
+                int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
+                ESP_LOGI(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", it->first.c_str(), msg_id);
+            }
+        }
+    }
+}
+
+void MQTTdestroySubscribeFunction(){
+    if (subscribeFunktionMap != NULL) {
+        if (mqtt_connected) {
+            for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
+                int msg_id = esp_mqtt_client_unsubscribe(client, it->first.c_str());
+                ESP_LOGI(TAG_INTERFACEMQTT, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
+            }
+        }
+
+        subscribeFunktionMap->clear();
+        delete subscribeFunktionMap;
+        subscribeFunktionMap = NULL;
+    }
+}

+ 15 - 1
code/components/jomjol_mqtt/interface_mqtt.h

@@ -1,7 +1,21 @@
+#ifndef INTERFACE_MQTT_H
+#define INTERFACE_MQTT_H
+
 #include <string>
+#include <map>
+#include <functional>
 
 void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive);
+void MQTTdestroy();
 
 //void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user = "", std::string _password = "");
 
-void MQTTPublish(std::string _key, std::string _content, int retained_flag = 0);
+void MQTTPublish(std::string _key, std::string _content, int retained_flag = 0);
+
+bool MQTTisConnected();
+
+void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func);
+void MQTTdestroySubscribeFunction();
+void MQTTsubscribeFunctions();
+
+#endif //INTERFACE_MQTT_H

+ 1 - 1
code/components/jomjol_tfliteclass/CMakeLists.txt

@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 
 idf_component_register(SRCS ${app_sources}
                     INCLUDE_DIRS "."
-                    REQUIRES jomjol_image_proc jomjol_logfile esp_http_server esp32-camera-master jomjol_controlcamera jomjol_flowcontroll jomjol_helper)
+                    REQUIRES main jomjol_image_proc jomjol_logfile esp_http_server esp32-camera-master jomjol_controlcamera jomjol_flowcontroll jomjol_helper)
 
 

+ 13 - 9
code/components/jomjol_tfliteclass/server_tflite.cpp

@@ -8,7 +8,7 @@
 #include <iomanip>
 #include <sstream>
 
-#include "../../main/defines.h"
+#include "defines.h"
 #include "Helper.h"
 
 #include "esp_camera.h"
@@ -38,6 +38,9 @@ bool auto_isrunning = false;
 
 int countRounds = 0;
 
+static const char *TAGTFLITE = "server_tflite";
+
+
 int getCountFlowRounds() {
     return countRounds;
 }
@@ -136,7 +139,7 @@ esp_err_t handler_init(httpd_req_t *req)
     printf("handler_doinit uri:\n"); printf(req->uri); printf("\n");
 #endif
 
-    char* resp_str = "Init started<br>";
+    const char* resp_str = "Init started<br>";
     httpd_resp_send(req, resp_str, strlen(resp_str));     
 
     doInit();
@@ -159,8 +162,6 @@ esp_err_t handler_doflow(httpd_req_t *req)
     LogFile.WriteHeapInfo("handler_doflow - Start");       
 #endif
 
-    char* resp_str;
-
     printf("handler_doFlow uri: "); printf(req->uri); printf("\n");
 
     if (flowisrunning)
@@ -173,7 +174,7 @@ esp_err_t handler_doflow(httpd_req_t *req)
     {
         xTaskCreate(&blink_task_doFlow, "blink_doFlow", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, &xHandleblink_task_doFlow);
     }
-    resp_str = "doFlow gestartet - dauert ca. 60 Sekunden";
+    const char* resp_str = "doFlow gestartet - dauert ca. 60 Sekunden";
     httpd_resp_send(req, resp_str, strlen(resp_str));  
     /* Respond with an empty chunk to signal HTTP response completion */
     httpd_resp_send_chunk(req, NULL, 0);       
@@ -429,7 +430,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
 
 //        printf("Parameter host: "); printf(_host.c_str()); printf("\n"); 
 //        string zwzw = "Do " + _task + " start\n"; printf(zwzw.c_str());
-        bool changed = Camera.SetBrightnessContrastSaturation(bri, con, sat);
+        Camera.SetBrightnessContrastSaturation(bri, con, sat);
         std::string zw = tfliteflow.doSingleStep("[MakeImage]", _host);
         httpd_resp_sendstr_chunk(req, zw.c_str()); 
     } 
@@ -535,17 +536,18 @@ void task_autodoFlow(void *pvParameter)
 {
     int64_t fr_start, fr_delta_ms;
 
+    printf("task_autodoFlow: start\r\n");
     doInit();
-    
+    printf("-a-\r\n");
     auto_isrunning = tfliteflow.isAutoStart(auto_intervall);
-
+    printf("-b-\r\n");
     if (isSetupModusActive()) {
         auto_isrunning = false;
         std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
         tfliteflow.doFlowMakeImageOnly(zw_time);
 
     }
-
+    printf("-c-\r\n");
     while (auto_isrunning)
     {
         std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds);
@@ -588,8 +590,10 @@ void task_autodoFlow(void *pvParameter)
             vTaskDelay( xDelay );        
         }
     }
+    printf("-d-\r\n");
     vTaskDelete(NULL); //Delete this task if it exits from the loop above
     xHandletask_autodoFlow = NULL;
+    printf("task_autodoFlow: end\r\n");
 }
 
 void TFliteDoAutoStart()

+ 0 - 2
code/components/jomjol_tfliteclass/server_tflite.h

@@ -5,8 +5,6 @@
 
 //#include "ClassControllCamera.h"
 
-static const char *TAGTFLITE = "server_tflite";
-
 void register_server_tflite_uri(httpd_handle_t server);
 
 void KillTFliteTasks();

+ 6 - 10
code/main/main.cpp

@@ -31,19 +31,15 @@
 
 #define __SD_USE_ONE_LINE_MODE__
 
-#ifdef __SD_USE_ONE_LINE_MODE__
 #include "server_GPIO.h"
-#endif
 
 
 #define BLINK_GPIO GPIO_NUM_33
 
-static const char *TAGMAIN = "connect_wlan_main";
+static const char *TAGMAIN = "main";
 
 #define FLASH_GPIO GPIO_NUM_4
 
-GpioHandler *gpioHandler = NULL;
-
 bool Init_NVS_SDCard()
 {
     esp_err_t ret = nvs_flash_init();
@@ -53,7 +49,7 @@ bool Init_NVS_SDCard()
     }
 ////////////////////////////////////////////////
 
-    ESP_LOGI(TAG, "Using SDMMC peripheral");
+    ESP_LOGI(TAGMAIN, "Using SDMMC peripheral");
     sdmmc_host_t host = SDMMC_HOST_DEFAULT();
 
     // This initializes the slot without card detect (CD) and write protect (WP) signals.
@@ -95,10 +91,10 @@ bool Init_NVS_SDCard()
 
     if (ret != ESP_OK) {
         if (ret == ESP_FAIL) {
-            ESP_LOGE(TAG, "Failed to mount filesystem. "
+            ESP_LOGE(TAGMAIN, "Failed to mount filesystem. "
                 "If you want the card to be formatted, set format_if_mount_failed = true.");
         } else {
-            ESP_LOGE(TAG, "Failed to initialize the card (%s). "
+            ESP_LOGE(TAGMAIN, "Failed to initialize the card (%s). "
                 "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
         }
         return false;
@@ -190,7 +186,7 @@ extern "C" void app_main(void)
     
     TickType_t xDelay;
     xDelay = 2000 / portTICK_PERIOD_MS;
-    printf("Autoflow: sleep for : %ldms\n", (long) xDelay);
+    printf("main: sleep for : %ldms\n", (long) xDelay);
 //    LogFile.WriteToFile("Startsequence 06");      
     vTaskDelay( xDelay );   
 //    LogFile.WriteToFile("Startsequence 07");  
@@ -207,7 +203,7 @@ extern "C" void app_main(void)
 //    Camera.InitCam();
 //    Camera.LightOnOff(false); 
     xDelay = 2000 / portTICK_PERIOD_MS;
-    printf("Autoflow: sleep for : %ldms\n", (long) xDelay);
+    printf("main: sleep for : %ldms\n", (long) xDelay);
     vTaskDelay( xDelay ); 
 
     server = start_webserver();   

+ 8 - 7
code/main/server_main.cpp

@@ -20,9 +20,10 @@
 
 
 httpd_handle_t server = NULL;   
-
 std::string starttime = "";
 
+static const char *TAG_SERVERMAIN = "server-main";
+
 
 /* An HTTP GET handler */
 esp_err_t info_get_handler(httpd_req_t *req)
@@ -198,7 +199,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
     printf("File requested: %s\n", filetosend.c_str());    
 
     if (!filename) {
-        ESP_LOGE(TAG, "Filename is too long");
+        ESP_LOGE(TAG_SERVERMAIN, "Filename is too long");
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
         return ESP_FAIL;
@@ -410,14 +411,14 @@ httpd_handle_t start_webserver(void)
     starttime = gettimestring("%Y%m%d-%H%M%S");
 
     // Start the httpd server
-    ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
+    ESP_LOGI(TAG_SERVERMAIN, "Starting server on port: '%d'", config.server_port);
     if (httpd_start(&server, &config) == ESP_OK) {
         // Set URI handlers
-        ESP_LOGI(TAG, "Registering URI handlers");
+        ESP_LOGI(TAG_SERVERMAIN, "Registering URI handlers");
         return server;
     }
 
-    ESP_LOGI(TAG, "Error starting server!");
+    ESP_LOGI(TAG_SERVERMAIN, "Error starting server!");
     return NULL;
 }
 
@@ -432,7 +433,7 @@ void disconnect_handler(void* arg, esp_event_base_t event_base,
 {
     httpd_handle_t* server = (httpd_handle_t*) arg;
     if (*server) {
-        ESP_LOGI(TAG, "Stopping webserver");
+        ESP_LOGI(TAG_SERVERMAIN, "Stopping webserver");
         stop_webserver(*server);
         *server = NULL;
     }
@@ -443,7 +444,7 @@ void connect_handler(void* arg, esp_event_base_t event_base,
 {
     httpd_handle_t* server = (httpd_handle_t*) arg;
     if (*server == NULL) {
-        ESP_LOGI(TAG, "Starting webserver");
+        ESP_LOGI(TAG_SERVERMAIN, "Starting webserver");
         *server = start_webserver();
     }
 }

+ 4 - 4
code/main/server_main.h

@@ -8,16 +8,16 @@
 #include <nvs_flash.h>
 #include <sys/param.h>
 #include "nvs_flash.h"
-#include "tcpip_adapter.h"
+#include "esp_netif.h"
 #include "esp_eth.h"
-
+#include "server_GPIO.h"
 
 #include <esp_http_server.h>
 
-static const char *TAG = "server-main";
-
 extern httpd_handle_t server;
 
+static GpioHandler *gpioHandler = NULL;
+
 httpd_handle_t start_webserver(void);
 
 void register_server_main_uri(httpd_handle_t server, const char *base_path);

+ 4 - 4
code/main/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="6cefc44";
-const char* GIT_TAG="v7.1.0";
-const char* GIT_BRANCH="master";
-const char* BUILD_TIME="2021-05-30 21:47";
+const char* GIT_REV="d995c31";
+const char* GIT_TAG="";
+const char* GIT_BRANCH="gpio-handler";
+const char* BUILD_TIME="2021-06-21 23:55";

+ 4 - 4
code/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="6cefc44";
-const char* GIT_TAG="v7.1.0";
-const char* GIT_BRANCH="master";
-const char* BUILD_TIME="2021-05-30 21:47";
+const char* GIT_REV="d995c31";
+const char* GIT_TAG="";
+const char* GIT_BRANCH="gpio-handler";
+const char* BUILD_TIME="2021-06-21 23:55";

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin


BIN
firmware/html.zip


+ 18 - 18
sd-card/html/edit_config_param.html

@@ -577,20 +577,6 @@ textarea {
 				MQTT topic, ESP uptime of last flow
 			</td>
 		</tr>
-		<tr>
-			<td width="20px"  style="padding-left: 40px;">
-				<input type="checkbox" id="MQTT_MainTopicGPIO_enabled" value="1"  onclick = 'InvertEnableItem("MQTT", "MainTopicGPIO")' unchecked >
-			</td>
-			<td  width="200px">
-				<class id="MQTT_MainTopicGPIO_text" style="color:black;">MainTopicGPIO</class>
-			</td>
-			<td>
-				<input type="text" id="MQTT_MainTopicGPIO_value1">
-			</td>
-			<td style="font-size: 80%;">
-				MQTT main topic for GPIO
-			</td>
-		</tr>
 		<tr>
 			<td width="20px"  style="padding-left: 40px;">
 				<input type="checkbox" id="MQTT_ClientID_enabled" value="1"  onclick = 'InvertEnableItem("MQTT", "ClientID")' unchecked >
@@ -671,6 +657,20 @@ textarea {
 			<td colspan="4" style="padding-left: 20px;"><h4><input type="checkbox" id="Category_GPIO_enabled" value="1"  onclick='UpdateAfterCategoryCheck()' unchecked > GPIO Settings</h4></td>
 		</tr> 	
 		
+		<tr>
+			<td width="20px"  style="padding-left: 40px;">
+				<input type="checkbox" id="GPIO_MainTopicMQTT_enabled" value="1"  onclick = 'InvertEnableItem("GPIO", "MainTopicMQTT")' unchecked >
+			</td>
+			<td  width="200px">
+				<class id="GPIO_MainTopicMQTT_text" style="color:black;">MainTopicMQTT</class>
+			</td>
+			<td>
+				<input type="text" id="GPIO_MainTopicMQTT_value1">
+			</td>
+			<td style="font-size: 80%;">
+				MQTT main topic for GPIO
+			</td>
+		</tr>
 		<tr class="GPIO_IO12">
 			<td width="20px"  style="padding-left: 40px;">
 				<input type="checkbox" id="GPIO_IO12_enabled" value="1"  onclick = 'InvertEnableItem("GPIO", "IO12")' unchecked>
@@ -704,8 +704,8 @@ textarea {
 				<td">
 					<select id="GPIO_IO12_value2">
 						<option value="disabled">disabled</option>
-						<option value="rising-edge" disabled>rising edge (not implemented)</option>
-						<option value="falling-edge" disabled>falling edge (not implemented)</option>
+						<option value="rising-edge">rising edge</option>
+						<option value="falling-edge">falling edge</option>
 					</select>	
 				</td>
 			</td>
@@ -1204,11 +1204,11 @@ function UpdateInput() {
 	WriteParameter(param, category, "MQTT", "TopicRate", true);	
 	WriteParameter(param, category, "MQTT", "TopicTimeStamp", true);
 	WriteParameter(param, category, "MQTT", "TopicUptime", true);	
-	WriteParameter(param, category, "MQTT", "MainTopicGPIO", true);
 	WriteParameter(param, category, "MQTT", "ClientID", true);	
 	WriteParameter(param, category, "MQTT", "user", true);	
 	WriteParameter(param, category, "MQTT", "password", true);
 	
+	WriteParameter(param, category, "GPIO", "MainTopicMQTT", true);
 	WriteParameter(param, category, "GPIO", "IO12", true);
 	WriteParameter(param, category, "GPIO", "IO13", true);
 
@@ -1269,11 +1269,11 @@ function ReadParameterAll()
 	ReadParameter(param, "MQTT", "TopicRate", true);
 	ReadParameter(param, "MQTT", "TopicTimeStamp", true);
 	ReadParameter(param, "MQTT", "TopicUptime", true);
-	ReadParameter(param, "MQTT", "MainTopicGPIO", true);
 	ReadParameter(param, "MQTT", "ClientID", true);	
 	ReadParameter(param, "MQTT", "user", true);	
 	ReadParameter(param, "MQTT", "password", true);	
 
+	ReadParameter(param, "GPIO", "MainTopicMQTT", true);
 	ReadParameter(param, "GPIO", "IO12", true);
 	ReadParameter(param, "GPIO", "IO13", true);
 

+ 1 - 1
sd-card/html/readconfigparam.js

@@ -87,7 +87,6 @@ function ParseConfig() {
      ParamAddValue(param, catname, "TopicRate");
      ParamAddValue(param, catname, "TopicTimeStamp");
      ParamAddValue(param, catname, "TopicUptime", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]);
-     ParamAddValue(param, catname, "MainTopicGPIO", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]);
      ParamAddValue(param, catname, "ClientID");
      ParamAddValue(param, catname, "user");
      ParamAddValue(param, catname, "password");
@@ -97,6 +96,7 @@ function ParseConfig() {
      category[catname]["enabled"] = false;
      category[catname]["found"] = false;
      param[catname] = new Object();
+     ParamAddValue(param, catname, "MainTopicMQTT", 1, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]);
      ParamAddValue(param, catname, "IO12", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
      ParamAddValue(param, catname, "IO13", 6, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);