Răsfoiți Sursa

Merge branch 'rolling'

jomjol 4 ani în urmă
părinte
comite
03b5e36114
80 a modificat fișierele cu 4181 adăugiri și 1568 ștergeri
  1. 16 0
      FeatureRequest.md
  2. 15 2
      README.md
  3. 3 3
      code/.helper/copy.bat
  4. 1 1
      code/.helper/makezip.bat
  5. BIN
      code/components/connect_wlan.zip
  6. 1 1
      code/components/esp32-camera-master/examples/take_picture.c
  7. 7 0
      code/components/jomjol_configfile/CMakeLists.txt
  8. 96 0
      code/components/jomjol_configfile/configFile.cpp
  9. 16 0
      code/components/jomjol_configfile/configFile.h
  10. 2 2
      code/components/jomjol_controlGPIO/CMakeLists.txt
  11. 513 62
      code/components/jomjol_controlGPIO/server_GPIO.cpp
  12. 91 2
      code/components/jomjol_controlGPIO/server_GPIO.h
  13. 1 1
      code/components/jomjol_controlcamera/CMakeLists.txt
  14. 18 13
      code/components/jomjol_controlcamera/ClassControllCamera.cpp
  15. 0 3
      code/components/jomjol_controlcamera/ClassControllCamera.h
  16. 5 2
      code/components/jomjol_controlcamera/server_camera.cpp
  17. 0 2
      code/components/jomjol_controlcamera/server_camera.h
  18. 2 2
      code/components/jomjol_fileserver_ota/CMakeLists.txt
  19. 55 45
      code/components/jomjol_fileserver_ota/server_file.cpp
  20. 13 9
      code/components/jomjol_fileserver_ota/server_ota.cpp
  21. 0 2
      code/components/jomjol_fileserver_ota/server_ota.h
  22. 22 6
      code/components/jomjol_flowcontroll/ClassFlow.cpp
  23. 2 0
      code/components/jomjol_flowcontroll/ClassFlow.h
  24. 205 67
      code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp
  25. 21 4
      code/components/jomjol_flowcontroll/ClassFlowAnalog.h
  26. 50 7
      code/components/jomjol_flowcontroll/ClassFlowControll.cpp
  27. 9 2
      code/components/jomjol_flowcontroll/ClassFlowControll.h
  28. 181 52
      code/components/jomjol_flowcontroll/ClassFlowDigit.cpp
  29. 20 2
      code/components/jomjol_flowcontroll/ClassFlowDigit.h
  30. 72 40
      code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp
  31. 5 2
      code/components/jomjol_flowcontroll/ClassFlowMQTT.h
  32. 435 244
      code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp
  33. 60 24
      code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h
  34. 38 1
      code/components/jomjol_helper/Helper.cpp
  35. 5 1
      code/components/jomjol_helper/Helper.h
  36. 1 1
      code/components/jomjol_logfile/ClassLogFile.cpp
  37. 127 14
      code/components/jomjol_mqtt/interface_mqtt.cpp
  38. 17 1
      code/components/jomjol_mqtt/interface_mqtt.h
  39. 8 2
      code/components/jomjol_tfliteclass/CTfLiteClass.cpp
  40. 1 1
      code/components/jomjol_tfliteclass/CTfLiteClass.h
  41. 75 17
      code/components/jomjol_tfliteclass/server_tflite.cpp
  42. 0 2
      code/components/jomjol_tfliteclass/server_tflite.h
  43. 14 0
      code/components/jomjol_time_sntp/time_sntp.cpp
  44. 4 1
      code/components/jomjol_time_sntp/time_sntp.h
  45. 6 0
      code/include/defines.h
  46. 15 16
      code/main/main.cpp
  47. 16 14
      code/main/server_main.cpp
  48. 3 4
      code/main/server_main.h
  49. 4 4
      code/main/version.cpp
  50. 5 1
      code/platformio.ini
  51. 4 2
      code/sdkconfig
  52. 2 3
      code/sdkconfig.old
  53. 4 4
      code/version.cpp
  54. BIN
      firmware/bootloader.bin
  55. BIN
      firmware/firmware.bin
  56. BIN
      firmware/html.zip
  57. 35 28
      sd-card/config/config.ini
  58. BIN
      sd-card/config/dig0870s3q.tflite
  59. BIN
      sd-card/config/dig1100s2q.tflite
  60. 14 16
      sd-card/html/edit_alignment.html
  61. 188 53
      sd-card/html/edit_analog.html
  62. 0 1
      sd-card/html/edit_config.html
  63. 692 93
      sd-card/html/edit_config_param.html
  64. 188 55
      sd-card/html/edit_digits.html
  65. 4 4
      sd-card/html/edit_explain_6.html
  66. 7 5
      sd-card/html/edit_reference.html
  67. 1 1
      sd-card/html/explain_3.html
  68. 1 1
      sd-card/html/explain_4.html
  69. 4 3
      sd-card/html/gethost.js
  70. 17 0
      sd-card/html/info.html
  71. 0 1
      sd-card/html/jquery-3.5.1.min.js
  72. 1 0
      sd-card/html/jquery-3.6.0.min.js
  73. 103 23
      sd-card/html/prevalue_set.html
  74. 0 427
      sd-card/html/readconfig.js
  75. 58 61
      sd-card/html/readconfigcommon.js
  76. 442 47
      sd-card/html/readconfigparam.js
  77. BIN
      sd-card/html/sd-card - Verknüpfung.lnk
  78. 32 0
      sd-card/html/test.html
  79. 1 1
      sd-card/html/version.txt
  80. 107 57
      sd-card/html/wasserzaehler_roi.html

+ 16 - 0
FeatureRequest.md

@@ -11,6 +11,22 @@
 
 
 ____
 ____
 
 
+#### #8 MQTT configurable readout intervall
+
+Make the readout intervall configurable via MQTT.
+
+* Change the mqtt part to receive and process input and not only sending
+
+#### #7 Extended Error Handling
+
+Check different types of error (e.g. tflite not availabe) and generate an error on the html page.
+
+To do:
+
+* Make a list of "important" errors
+* Implement a checking algo
+* Extend the firmware and html page for the error handling
+
 #### #6 Check for double ROI names
 #### #6 Check for double ROI names
 
 
 Check during configuration, that ROI names are unique.
 Check during configuration, that ROI names are unique.

+ 15 - 2
README.md

@@ -12,6 +12,8 @@ respectively ESP32-Cam housing only: https://www.thingiverse.com/thing:4571627
 
 
 <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter.jpg" width="600"> 
 <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter.jpg" width="600"> 
 
 
+<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/powermeter.jpg" width="600"> 
+
 
 
 
 
 
 
@@ -45,16 +47,27 @@ In other cases you can contact the developer via email: <img src="https://raw.gi
 
 
 
 
 
 
+##### 8.0.0 - Multi Meter Support (2021-07-14)
+
+* Dual / multi meter support (more than 1 number to be recognized)
+  This is implemented with the feature "number" on the ROI definition as well as selected options
+* MQTT: standardization of the naming - including new topics (`json`,  `freeMem `, `uptime`)c
+* Preparation for extended GPIO support (thanks to Zwerk2k) - not tested and fully functional yet
+* Bug fixing: html server, memory leak, MQTT connect, hostname, turn of flash LED
+
+<span style="color: red;">**ATTENTION: the configuration and prevalue files are modified automatically and will not be backward compatible!**</span> 
+
+
 
 
 ##### 7.1.2 MQTT-Update - (2021-06-17)
 ##### 7.1.2 MQTT-Update - (2021-06-17)
 
 
-* NEW: 7.1.2: bug fix setting hostname, Flash-LED not off during reboot
-* NEW: 7.1.1: bug fix wlan password with "="  (again)
+* NEW: 7.1.2: bug fix setting hostname, Flash-LED not off during rebootNEW: 7.1.1: bug fix wlan password with "="  (again)
 * MQTT error message: changes "no error", send retain flag
 * MQTT error message: changes "no error", send retain flag
 * Update wlan handling to esp-idf 4.1
 * Update wlan handling to esp-idf 4.1
 * Upgrade digital CNN to v8.7.0  (added new images)
 * Upgrade digital CNN to v8.7.0  (added new images)
 * Bug fix: MQTT, WLAN, LED-Controll, GPIO usage, fixed IP, calculation flow rate
 * Bug fix: MQTT, WLAN, LED-Controll, GPIO usage, fixed IP, calculation flow rate
 
 
+  
 
 
 ##### 7.0.1 MQTT-Update - (2021-05-13)
 ##### 7.0.1 MQTT-Update - (2021-05-13)
 
 

+ 3 - 3
code/.helper/copy.bat

@@ -1,3 +1,3 @@
-copy "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\code\.pio\build\esp32cam\firmware.bin" "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\firmware\firmware.bin"
-copy "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\code\.pio\build\esp32cam\bootloader.bin" "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\firmware\bootloader.bin"
-copy "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\code\.pio\build\esp32cam\partitions.bin" "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\firmware\partitions.bin"
+copy "..\..\code\.pio\build\esp32cam\firmware.bin" "..\..\firmware\firmware.bin"
+copy "..\..\code\.pio\build\esp32cam\bootloader.bin" "..\..\firmware\bootloader.bin"
+copy "..\..\code\.pio\build\esp32cam\partitions.bin" "..\..\firmware\partitions.bin"

+ 1 - 1
code/.helper/makezip.bat

@@ -1 +1 @@
-powershell Compress-Archive "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\sd-card\html\*.*" "C:\Users\Muell\Documents\Programmieren\GitHub\AI-on-the-edge-device\firmware\html.zip"
+powershell Compress-Archive "..\..\sd-card\html\*.*" "..\..\firmware\html.zip"

BIN
code/components/connect_wlan.zip


+ 1 - 1
code/components/esp32-camera-master/examples/take_picture.c

@@ -29,7 +29,7 @@
 
 
 // ================================ CODE ======================================
 // ================================ CODE ======================================
 
 
-#include <esp_event_loop.h>
+#include <esp_event.h>
 #include <esp_log.h>
 #include <esp_log.h>
 #include <esp_system.h>
 #include <esp_system.h>
 #include <nvs_flash.h>
 #include <nvs_flash.h>

+ 7 - 0
code/components/jomjol_configfile/CMakeLists.txt

@@ -0,0 +1,7 @@
+FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
+
+idf_component_register(SRCS ${app_sources}
+                    INCLUDE_DIRS "."
+                    REQUIRES jomjol_logfile)
+
+

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

@@ -0,0 +1,96 @@
+#include <string.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "Helper.h"
+#include "configFile.h"
+
+//static const char *TAGCONFIGFILE = "configFile";
+
+ConfigFile::ConfigFile(std::string filePath)
+{
+    std::string config = FormatFileName(filePath);
+    pFile = OpenFileAndWait(config.c_str(), "r");
+}
+
+ConfigFile::~ConfigFile()
+{
+    fclose(pFile);
+}
+
+bool ConfigFile::isNewParagraph(std::string input)
+{
+	if ((input[0] == '[') || ((input[0] == ';') && (input[1] == '[')))
+	{
+		return true;
+	}
+	return false;
+}
+
+bool ConfigFile::GetNextParagraph(std::string& aktparamgraph, bool &disabled, bool &eof)
+{
+	while (getNextLine(&aktparamgraph, disabled, eof) && !isNewParagraph(aktparamgraph));
+
+	if (isNewParagraph(aktparamgraph))
+		return true;
+	return false;
+}
+
+bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
+{
+    eof = false;
+	char zw[1024];
+	if (pFile == NULL)
+	{
+		*rt = "";
+		return false;
+	}
+	fgets(zw, 1024, pFile);
+	printf("%s", zw);
+	if ((strlen(zw) == 0) && feof(pFile))
+	{
+		*rt = "";
+        eof = true;
+		return false;
+	}
+	*rt = zw;
+	*rt = trim(*rt);
+	while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))			// Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
+	{
+		fgets(zw, 1024, pFile);
+		printf("%s", zw);		
+		if (feof(pFile))
+		{
+			*rt = "";
+            eof = true;
+			return false;
+		}
+		*rt = zw;
+		*rt = trim(*rt);
+	}
+
+    disabled = ((*rt)[0] == ';');
+	return true;
+}
+
+std::vector<string> ConfigFile::ZerlegeZeile(std::string input, std::string delimiter)
+{
+	std::vector<string> Output;
+//	std::string delimiter = " =,";
+
+	input = trim(input, delimiter);
+	size_t pos = findDelimiterPos(input, delimiter);
+	std::string token;
+	while (pos != std::string::npos) {
+		token = input.substr(0, pos);
+		token = trim(token, delimiter);
+		Output.push_back(token);
+		input.erase(0, pos + 1);
+		input = trim(input, delimiter);
+		pos = findDelimiterPos(input, delimiter);
+	}
+	Output.push_back(input);
+
+	return Output;
+
+}

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

@@ -0,0 +1,16 @@
+#include <string>
+#include <vector>
+
+class ConfigFile {
+public:
+    ConfigFile(std::string filePath);
+    ~ConfigFile();
+
+    bool isNewParagraph(std::string input);
+    bool GetNextParagraph(std::string& aktparamgraph, bool &disabled, bool &eof);
+	bool getNextLine(std::string* rt, bool &disabled, bool &eof);
+    std::vector<std::string> ZerlegeZeile(std::string input, std::string delimiter = " =, \t");
+    
+private:
+    FILE* pFile;
+};

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

@@ -3,7 +3,7 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
 
 
 idf_component_register(SRCS ${app_sources}
 idf_component_register(SRCS ${app_sources}
-                    INCLUDE_DIRS "."
-                    REQUIRES esp_http_server jomjol_logfile)
+                    INCLUDE_DIRS "." "../../include"
+                    REQUIRES esp_http_server jomjol_logfile jomjol_configfile jomjol_mqtt jomjol_flowcontroll)
 
 
 
 

+ 513 - 62
code/components/jomjol_controlGPIO/server_GPIO.cpp

@@ -1,4 +1,5 @@
 #include <string>
 #include <string>
+#include <functional>
 #include "string.h"
 #include "string.h"
 
 
 #include <string.h>
 #include <string.h>
@@ -6,22 +7,384 @@
 #include "freertos/task.h"
 #include "freertos/task.h"
 #include "esp_system.h"
 #include "esp_system.h"
 #include "esp_event.h"
 #include "esp_event.h"
+
+//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
 #include "esp_log.h"
 #include "esp_log.h"
-#include "driver/gpio.h"
 //#include "errno.h"
 //#include "errno.h"
 
 
 #include <sys/stat.h>
 #include <sys/stat.h>
+#include <vector>
+//#include <regex>
+
+#include "defines.h"
 
 
 #include "server_GPIO.h"
 #include "server_GPIO.h"
 
 
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
-
+#include "configFile.h"
 #include "Helper.h"
 #include "Helper.h"
+#include "interface_mqtt.h"
+
+static const char *TAG_SERVERGPIO = "server_GPIO";
+QueueHandle_t gpio_queue_handle = NULL;
+
+#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, std::string mqttTopic, bool httpEnable) 
+{
+    _gpio = gpio;
+    _name = name; 
+    _mode = mode;
+    _interruptType = interruptType;    
+    _mqttTopic = mqttTopic;
+}
+
+GpioPin::~GpioPin()
+{
+    ESP_LOGD(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)
+{
+    GpioResult gpioResult;
+    gpioResult.gpio = *(gpio_num_t*) arg;
+    gpioResult.value = gpio_get_level(gpioResult.gpio);
+    BaseType_t ContextSwitchRequest = pdFALSE;
+ 
+    xQueueSendToBackFromISR(gpio_queue_handle,(void*)&gpioResult,&ContextSwitchRequest);
+   
+    if(ContextSwitchRequest){
+        taskYIELD();
+    }
+}
+
+static void gpioHandlerTask(void *arg) {
+    ESP_LOGD(TAG_SERVERGPIO,"start interrupt task");
+    while(1){
+        if(uxQueueMessagesWaiting(gpio_queue_handle)){
+            while(uxQueueMessagesWaiting(gpio_queue_handle)){
+                GpioResult gpioResult;
+                xQueueReceive(gpio_queue_handle,(void*)&gpioResult,10);
+                ESP_LOGD(TAG_SERVERGPIO,"gpio: %d state: %d", gpioResult.gpio, gpioResult.value);
+                ((GpioHandler*)arg)->gpioInterrupt(&gpioResult);
+            }  
+        }
+
+        ((GpioHandler*)arg)->taskHandler();
+        vTaskDelay(pdMS_TO_TICKS(1000));
+    }
+}
+
+void GpioPin::gpioInterrupt(int value) {
+    if (_mqttTopic != "") {
+        ESP_LOGD(TAG_SERVERGPIO, "gpioInterrupt %s %d", _mqttTopic.c_str(), value);
+
+        MQTTPublish(_mqttTopic, value ? "true" : "false");
+        currentState = value;
+    }
+}
+
+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_OUTPUT) || (_mode == GPIO_PIN_MODE_BUILT_IN_FLASH_LED) ? 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_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_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
+        ESP_LOGD(TAG_SERVERGPIO, "GpioPin::init add isr handler for GPIO %d\r\n", _gpio);
+        gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*)&_gpio);
+    }
+
+    if ((_mqttTopic != "") && ((_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_OUTPUT_PWM) || (_mode == GPIO_PIN_MODE_BUILT_IN_FLASH_LED))) {
+        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)
+{   
+    if ((_mode != GPIO_PIN_MODE_INPUT) && (_mode != GPIO_PIN_MODE_INPUT_PULLUP) && (_mode != GPIO_PIN_MODE_INPUT_PULLDOWN)) {
+        (*errorText) = "GPIO is not in input mode";
+    }
+
+    return gpio_get_level(_gpio) == 1;
+}
+
+void GpioPin::setValue(bool value, gpio_set_source setSource, std::string* errorText)
+{
+    ESP_LOGD(TAG_SERVERGPIO, "GpioPin::setValue %d\r\n", value);
+
+    if ((_mode != GPIO_PIN_MODE_OUTPUT) && (_mode != GPIO_PIN_MODE_OUTPUT_PWM) && (_mode != GPIO_PIN_MODE_BUILT_IN_FLASH_LED)) {
+        (*errorText) = "GPIO is not in output mode";
+    } else {
+        gpio_set_level(_gpio, value);
+
+        if ((_mqttTopic != "") && (setSource != GPIO_SET_SOURCE_MQTT)) {
+            MQTTPublish(_mqttTopic, value ? "true" : "false");
+        }
+    }
+}
+
+void GpioPin::publishState() {
+    int newState = gpio_get_level(_gpio);
+    if (newState != currentState) {
+        ESP_LOGD(TAG_SERVERGPIO,"publish state of GPIO %d new state %d", _gpio, newState);
+        MQTTPublish(_mqttTopic, newState ? "true" : "false");
+        currentState = newState;
+    }
+}
+
+bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
+    ESP_LOGD(TAG_SERVERGPIO, "GpioPin::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, GPIO_SET_SOURCE_MQTT, &errorText);
+    } else if ((dataStr == "false") || (dataStr == "0")) {
+        setValue(false, GPIO_SET_SOURCE_MQTT, &errorText);    
+    } else {
+        errorText = "wrong value ";
+        errorText.append(data, data_len);
+    }
+
+    if (errorText != "") {
+        ESP_LOGE(TAG_SERVERGPIO, "%s", errorText.c_str());
+    }
+
+    return (errorText == "");
+}
+
+
+esp_err_t callHandleHttpRequest(httpd_req_t *req)
+{
+    ESP_LOGD(TAG_SERVERGPIO,"callHandleHttpRequest");
+
+    GpioHandler *gpioHandler = (GpioHandler*)req->user_ctx;
+    return gpioHandler->handleHttpRequest(req);
+}
+
+void taskGpioHandler(void *pvParameter)
+{
+    ESP_LOGD(TAG_SERVERGPIO,"taskGpioHandler");
+    ((GpioHandler*)pvParameter)->init();
+}
+
+GpioHandler::GpioHandler(std::string configFile, httpd_handle_t httpServer) 
+{
+    ESP_LOGI(TAG_SERVERGPIO,"start GpioHandler");
+    _configFile = configFile;
+    _httpServer = httpServer;
+
+    ESP_LOGI(TAG_SERVERGPIO, "register GPIO Uri");
+    registerGpioUri();
+}
+
+GpioHandler::~GpioHandler()  {
+    if (gpioMap != NULL) {
+        clear();
+        delete gpioMap;
+    }
+}
+
+void GpioHandler::init()
+{
+    // TickType_t xDelay = 60000 / portTICK_PERIOD_MS;
+    // printf("wait before start %ldms\r\n", (long) xDelay);
+    // vTaskDelay( xDelay );
+
+    if (gpioMap == NULL) {
+        gpioMap = new std::map<gpio_num_t, GpioPin*>();
+    } else {
+        clear();
+    }
+    
+    ESP_LOGI(TAG_SERVERGPIO, "read GPIO config and init GPIO");
+    if (!readConfig()) {
+        clear();
+        delete gpioMap;
+        gpioMap = NULL;
+        ESP_LOGI(TAG_SERVERGPIO, "GPIO init comleted, handler is disabled");
+        return;
+    }
+
+    for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
+        it->second->init();
+    }
+
+    std::function<void()> f = std::bind(&GpioHandler::handleMQTTconnect, this);
+    MQTTregisterConnectFunction("gpio-handler", f);
+
+    if (xHandleTaskGpio == NULL) {
+        gpio_queue_handle = xQueueCreate(10,sizeof(GpioResult));
+        BaseType_t  xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", configMINIMAL_STACK_SIZE * 8, (void *)this, tskIDLE_PRIORITY + 2, &xHandleTaskGpio);
+        if(xReturned == pdPASS ) {
+            ESP_LOGD(TAG_SERVERGPIO, "xHandletaskGpioHandler started");
+        } else {
+            ESP_LOGD(TAG_SERVERGPIO, "xHandletaskGpioHandler not started %d ", (int)xHandleTaskGpio);
+        }
+    }
+
+    ESP_LOGI(TAG_SERVERGPIO, "GPIO init comleted, is enabled");
+}
+
+void GpioHandler::taskHandler() {
+    if (gpioMap != NULL) {
+        for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
+            if ((it->second->getInterruptType() == GPIO_INTR_DISABLE))
+                it->second->publishState();
+        }
+    }
+}
+
+
+void GpioHandler::handleMQTTconnect()
+{
+    if (gpioMap != NULL) {
+        for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
+            if ((it->second->getMode() == GPIO_PIN_MODE_INPUT) || (it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN) || (it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLUP))
+                it->second->publishState();
+        }
+    }
+}
+
+void GpioHandler::deinit() {
+    MQTTunregisterConnectFunction("gpio-handler");
+    clear();
+    if (xHandleTaskGpio != NULL) {
+        vTaskDelete(xHandleTaskGpio);
+        xHandleTaskGpio = NULL;
+    }
+}
+
+void GpioHandler::gpioInterrupt(GpioResult* gpioResult) {
+    if ((gpioMap != NULL) && (gpioMap->find(gpioResult->gpio) != gpioMap->end())) {
+        (*gpioMap)[gpioResult->gpio]->gpioInterrupt(gpioResult->value);
+    }
+}
+
+bool GpioHandler::readConfig() 
+{
+    if (!gpioMap->empty())
+        clear();
+
+    ConfigFile configFile = ConfigFile(_configFile); 
+
+    std::vector<std::string> zerlegt;
+    std::string line = "";
+    bool disabledLine = false;
+    bool eof = false;
+        
+    while ((!configFile.GetNextParagraph(line, disabledLine, eof) || (line.compare("[GPIO]") != 0)) && !disabledLine && !eof) {}
+    if (eof)
+        return false;
+    
+    _isEnabled = !disabledLine;
+
+    if (!_isEnabled)
+        return false;
+
+    std::string mainTopicMQTT = "";
+    bool registerISR = false;
+    while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line))
+    {
+        zerlegt = configFile.ZerlegeZeile(line);
+        // const std::regex pieces_regex("IO([0-9]{1,2})");
+        // std::smatch pieces_match;
+        // if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
+        // {
+        //     std::string gpioStr = pieces_match[1];
+        ESP_LOGD(TAG_SERVERGPIO, "conf param %s\r\n", toUpper(zerlegt[0]).c_str());
+        if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") {
+            ESP_LOGD(TAG_SERVERGPIO, "MAINTOPICMQTT found\r\n");
+            mainTopicMQTT = zerlegt[1];
+        } else if ((zerlegt[0].rfind("IO", 0) == 0) && (zerlegt.size() >= 6))
+        {
+            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]));
+            gpio_int_type_t intType = resolveIntType(toLower(zerlegt[2]));
+            uint16_t dutyResolution = (uint8_t)atoi(zerlegt[3].c_str());
+            bool mqttEnabled = toLower(zerlegt[4]) == "true";
+            bool httpEnabled = toLower(zerlegt[5]) == "true";
+            char gpioName[100];
+            if (zerlegt.size() >= 7) {
+                strcpy(gpioName, trim(zerlegt[6]).c_str());
+            } else {
+                sprintf(gpioName, "GPIO%d", gpioNr);
+            }
+            std::string mqttTopic = mqttEnabled ? (mainTopicMQTT + "/" + gpioName) : "";
+            GpioPin* gpioPin = new GpioPin(gpioNr, gpioName, 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;
+}
 
 
-// #define DEBUG_DETAIL_ON 
+void GpioHandler::clear() 
+{
+    ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::clear\r\n");
+
+    if (gpioMap != NULL) {
+        for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
+            delete it->second;
+        }
+        gpioMap->clear();
+    }
+
+    // gpio_uninstall_isr_service(); can't uninstall, isr service is used by camera
+}
+ 
+void GpioHandler::registerGpioUri() 
+{
+    ESP_LOGI(TAG_SERVERGPIO, "server_GPIO - Registering URI handlers");
+    
+    httpd_uri_t camuri = { };
+    camuri.method    = HTTP_GET;
+    camuri.uri       = "/GPIO";
+    camuri.handler   = callHandleHttpRequest;
+    camuri.user_ctx  = (void*)this;    
+    httpd_register_uri_handler(_httpServer, &camuri);
+}
 
 
-esp_err_t handler_switch_GPIO(httpd_req_t *req)
+esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
 {
 {
+    ESP_LOGD(TAG_SERVERGPIO, "handleHttpRequest");
+
+    if (gpioMap == NULL) {
+        std::string resp_str = "GPIO handler not initialized";
+        httpd_resp_send(req, resp_str.c_str(), resp_str.length());    
+        return ESP_OK;
+    }
+
 #ifdef DEBUG_DETAIL_ON 
 #ifdef DEBUG_DETAIL_ON 
     LogFile.WriteHeapInfo("handler_switch_GPIO - Start");    
     LogFile.WriteHeapInfo("handler_switch_GPIO - Start");    
 #endif
 #endif
@@ -30,95 +393,183 @@ esp_err_t handler_switch_GPIO(httpd_req_t *req)
     char _query[200];
     char _query[200];
     char _valueGPIO[30];    
     char _valueGPIO[30];    
     char _valueStatus[30];    
     char _valueStatus[30];    
-    std::string gpio, status, zw;
-    int gpionum = 0;
-    gpio_num_t gpio_num;
+    std::string gpio, status;
 
 
-    if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
-    {
-        printf("Query: "); printf(_query); printf("\n");
+    if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) {
+        ESP_LOGD(TAG_SERVERGPIO, "Query: %s", _query);
         
         
         if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK)
         if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK)
         {
         {
-            printf("GPIO is found"); printf(_valueGPIO); printf("\n"); 
+            ESP_LOGD(TAG_SERVERGPIO, "GPIO is found %s", _valueGPIO); 
             gpio = std::string(_valueGPIO);
             gpio = std::string(_valueGPIO);
+        } else {
+            std::string resp_str = "GPIO No is not defined";
+            httpd_resp_send(req, resp_str.c_str(), resp_str.length());    
+            return ESP_OK;
         }
         }
         if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK)
         if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK)
         {
         {
-            printf("Status is found"); printf(_valueStatus); printf("\n"); 
+            ESP_LOGD(TAG_SERVERGPIO, "Status is found %s", _valueStatus); 
             status = std::string(_valueStatus);
             status = std::string(_valueStatus);
         }
         }
-    };
+    } else {
+        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;
+    }
 
 
     status = toUpper(status);
     status = toUpper(status);
-    if (!(status == "HIGH") && !(status == "LOW"))
+    if ((status != "HIGH") && (status != "LOW") && (status != "TRUE") && (status != "FALSE") && (status != "0") && (status != "1") && (status != ""))
     {
     {
-        zw = "Status not valid: " + status;;
+        std::string zw = "Status not valid: " + status;
         httpd_resp_sendstr_chunk(req, zw.c_str());
         httpd_resp_sendstr_chunk(req, zw.c_str());
         httpd_resp_sendstr_chunk(req, NULL);          
         httpd_resp_sendstr_chunk(req, NULL);          
         return ESP_OK;    
         return ESP_OK;    
     }
     }
 
 
-    gpionum = stoi(gpio);
-    
-    // frei: 16; 12-15; 2; 4  // nur 12 und 13 funktionieren 2: reboot, 4: BlitzLED, 14/15: DMA für SDKarte ???
+    int gpionum = stoi(gpio);
 
 
-    switch (gpionum) {
-        case 12:
-            gpio_num = GPIO_NUM_12;
-            break;
-        case 13:
-            gpio_num = GPIO_NUM_13;
-            break;
-        default:
-            zw = "GPIO" + std::to_string(gpionum) + " not support - only 12 & 13 free";
+    // frei: 16; 12-15; 2; 4  // nur 12 und 13 funktionieren 2: reboot, 4: BlitzLED, 15: PSRAM, 14/15: DMA für SDKarte ???
+    gpio_num_t gpio_num = resolvePinNr(gpionum);
+    if (gpio_num == GPIO_NUM_NC)
+    {
+        std::string zw = "GPIO" + std::to_string(gpionum) + " not support - only 12 & 13 free";
             httpd_resp_sendstr_chunk(req, zw.c_str());
             httpd_resp_sendstr_chunk(req, zw.c_str());
             httpd_resp_sendstr_chunk(req, NULL);          
             httpd_resp_sendstr_chunk(req, NULL);          
-            return ESP_OK;    
+            return ESP_OK;
     }
     }
 
 
-    if (status == "HIGH")  
-        gpio_set_level(gpio_num, 1);
+    if (gpioMap->count(gpio_num) == 0) {
+        char resp_str [30];
+        sprintf(resp_str, "GPIO%d is not registred", gpio_num);
+        httpd_resp_send(req, resp_str, strlen(resp_str));  
+        return ESP_OK;     
+    }
+    
+    if (status == "") 
+    {
+        std::string resp_str = "";
+        status = (*gpioMap)[gpio_num]->getValue(&resp_str) ? "HIGH" : "LOW";
+        if (resp_str == "") {
+            resp_str = status;
+        }
+        httpd_resp_sendstr_chunk(req, resp_str.c_str());
+        httpd_resp_sendstr_chunk(req, NULL);
+    }
     else
     else
-        gpio_set_level(gpio_num, 0); 
-
-
-    zw = "GPIO" + std::to_string(gpionum) + " switched to " + status;
-    httpd_resp_sendstr_chunk(req, zw.c_str());
-    httpd_resp_sendstr_chunk(req, NULL);          
+    {
+        std::string resp_str = "";
+        (*gpioMap)[gpio_num]->setValue((status == "HIGH") || (status == "TRUE") || (status == "1"), GPIO_SET_SOURCE_HTTP, &resp_str);
+        if (resp_str == "") {
+            resp_str = "GPIO" + std::to_string(gpionum) + " switched to " + status;
+        }
+        httpd_resp_sendstr_chunk(req, resp_str.c_str());
+        httpd_resp_sendstr_chunk(req, NULL);
+    }
+          
     return ESP_OK;    
     return ESP_OK;    
 };
 };
 
 
-void initGPIO()
+void GpioHandler::flashLightEnable(bool value) 
 {
 {
-    gpio_config_t io_conf;
-    //disable interrupt
-    io_conf.intr_type = GPIO_INTR_DISABLE;
-    //set as output mode
-    io_conf.mode = GPIO_MODE_OUTPUT;
-    //bit mask of the pins that you want to set,e.g.GPIO18/19
-//    io_conf.pin_bit_mask = ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1));
-//    io_conf.pin_bit_mask = ((1ULL << GPIO_NUM_12) | (1ULL << GPIO_NUM_2) | (1ULL << GPIO_NUM_4) | (1ULL << GPIO_NUM_12) | (1ULL << GPIO_NUM_13) | (1ULL << GPIO_NUM_14) | (1ULL << GPIO_NUM_15));
-    io_conf.pin_bit_mask = ((1ULL << GPIO_NUM_12) | (1ULL << GPIO_NUM_13));
-    //disable pull-down mode
-    io_conf.pull_down_en = (gpio_pulldown_t) 0;
-    //disable pull-up mode
-    io_conf.pull_up_en = (gpio_pullup_t) 0;
-    //configure GPIO with the given settings
-    gpio_config(&io_conf);
+    ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::flashLightEnable %s\r\n", value ? "true" : "false");
+
+    if (gpioMap != NULL) {
+        for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) 
+        {
+            if (it->second->getMode() == GPIO_PIN_MODE_BUILT_IN_FLASH_LED) //|| (it->second->getMode() == GPIO_PIN_MODE_EXTERNAL_FLASH_PWM) || (it->second->getMode() == GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X))
+            {
+                std::string resp_str = "";
+                it->second->setValue(value, GPIO_SET_SOURCE_INTERNAL, &resp_str);
+
+                if (resp_str == "") {
+                    ESP_LOGD(TAG_SERVERGPIO, "Flash light pin GPIO %d switched to %s\r\n", (int)it->first, (value ? "on" : "off"));
+                } else {
+                    ESP_LOGE(TAG_SERVERGPIO, "Can't set flash light pin GPIO %d.  Error: %s\r\n", (int)it->first, resp_str.c_str());
+                }
+            }
+        }
+    }
 }
 }
 
 
+gpio_num_t GpioHandler::resolvePinNr(uint8_t pinNr) 
+{
+    switch(pinNr)  {
+        case 0:
+            return GPIO_NUM_0;
+        case 1:
+            return GPIO_NUM_1;
+        case 3:
+            return GPIO_NUM_3;
+        case 4:
+            return GPIO_NUM_4;
+        case 12:
+            return GPIO_NUM_12;
+        case 13:
+            return GPIO_NUM_13;
+        default: 
+            return GPIO_NUM_NC;   
+    }
+}
 
 
-void register_server_GPIO_uri(httpd_handle_t server)
+gpio_pin_mode_t GpioHandler::resolvePinMode(std::string input) 
 {
 {
-    ESP_LOGI(TAGPARTGPIO, "server_GPIO - Registering URI handlers");
-    
-    httpd_uri_t camuri = { };
-    camuri.method    = HTTP_GET;
-    camuri.uri       = "/GPIO";
-    camuri.handler   = handler_switch_GPIO;
-    camuri.user_ctx  = (void*) "switch GPIO";    
-    httpd_register_uri_handler(server, &camuri);
+    if( input == "disabled" ) return GPIO_PIN_MODE_DISABLED;
+    if( input == "input" ) return GPIO_PIN_MODE_INPUT;
+    if( input == "input-pullup" ) return GPIO_PIN_MODE_INPUT_PULLUP;
+    if( input == "input-pulldown" ) return GPIO_PIN_MODE_INPUT_PULLDOWN;
+    if( input == "output" ) return GPIO_PIN_MODE_OUTPUT;
+    if( input == "built-in-led" ) return GPIO_PIN_MODE_BUILT_IN_FLASH_LED;
+    if( input == "output-pwm" ) return GPIO_PIN_MODE_OUTPUT_PWM;
+    if( input == "external-flash-pwm" ) return GPIO_PIN_MODE_EXTERNAL_FLASH_PWM;
+    if( input == "external-flash-ws281x" ) return GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X;
+
+    return GPIO_PIN_MODE_DISABLED;
+}
+
+gpio_int_type_t GpioHandler::resolveIntType(std::string input) 
+{
+    if( input == "disabled" ) return GPIO_INTR_DISABLE;
+    if( input == "rising-edge" ) return GPIO_INTR_POSEDGE;
+    if( input == "falling-edge" ) return GPIO_INTR_NEGEDGE;
+    if( input == "rising-and-falling" ) return GPIO_INTR_ANYEDGE ;
+    if( input == "low-level-trigger" ) return GPIO_INTR_LOW_LEVEL;
+    if( input == "high-level-trigger" ) return GPIO_INTR_HIGH_LEVEL;
+
+
+    return GPIO_INTR_DISABLE;
+}
+
+static GpioHandler *gpioHandler = NULL;
+
+void gpio_handler_create(httpd_handle_t server) 
+{
+    if (gpioHandler == NULL)
+        gpioHandler = new GpioHandler(CONFIG_FILE, server);
+}
+
+void gpio_handler_init() 
+{
+    if (gpioHandler != NULL) {
+        gpioHandler->init();
+    }
+}
+
+void gpio_handler_deinit() {
+    if (gpioHandler != NULL) {
+        gpioHandler->deinit();
+   }
+}
+
+void gpio_handler_destroy()
+{
+    if (gpioHandler != NULL) {
+        delete gpioHandler;
+        gpioHandler = NULL;
+    }
+}
 
 
-    initGPIO();
+GpioHandler* gpio_handler_get()
+{
+    return gpioHandler;
 }
 }

+ 91 - 2
code/components/jomjol_controlGPIO/server_GPIO.h

@@ -1,10 +1,99 @@
+#ifndef SERVER_GPIO_H
+#define SERVER_GPIO_H
+
 #include <esp_log.h>
 #include <esp_log.h>
 
 
 #include <esp_http_server.h>
 #include <esp_http_server.h>
+#include <map>
+#include "driver/gpio.h"
 
 
 //#include "ClassControllCamera.h"
 //#include "ClassControllCamera.h"
 
 
-static const char *TAGPARTGPIO = "server_GPIO";
+typedef enum {
+    GPIO_PIN_MODE_DISABLED              = 0x0,
+    GPIO_PIN_MODE_INPUT                 = 0x1,
+    GPIO_PIN_MODE_INPUT_PULLUP          = 0x2,
+    GPIO_PIN_MODE_INPUT_PULLDOWN        = 0x3,
+    GPIO_PIN_MODE_OUTPUT                = 0x4,
+    GPIO_PIN_MODE_BUILT_IN_FLASH_LED    = 0x5,
+    GPIO_PIN_MODE_OUTPUT_PWM            = 0x6,
+    GPIO_PIN_MODE_EXTERNAL_FLASH_PWM    = 0x7,
+    GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X = 0x8,
+} gpio_pin_mode_t;
+
+struct GpioResult {
+    gpio_num_t gpio;
+    int value;
+};
+
+typedef enum {
+    GPIO_SET_SOURCE_INTERNAL  = 0,
+    GPIO_SET_SOURCE_MQTT  = 1,
+    GPIO_SET_SOURCE_HTTP  = 2,
+} gpio_set_source;
+
+class GpioPin {
+public:
+    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();
+
+    void init();
+    bool getValue(std::string* errorText);
+    void setValue(bool value, gpio_set_source setSource, std::string* errorText);
+    bool handleMQTT(std::string, char* data, int data_len);
+    void publishState();
+    void gpioInterrupt(int value);
+    gpio_int_type_t getInterruptType() { return _interruptType; }
+    gpio_pin_mode_t getMode() { return _mode; }
+
+private:
+    gpio_num_t _gpio;
+    const char* _name;
+    gpio_pin_mode_t _mode;
+    gpio_int_type_t _interruptType;
+    std::string _mqttTopic;
+    int currentState = -1;
+};
+
+esp_err_t callHandleHttpRequest(httpd_req_t *req);
+void taskGpioHandler(void *pvParameter);
+
+class GpioHandler {
+public:
+    GpioHandler(std::string configFile, httpd_handle_t httpServer);
+    ~GpioHandler();
+    
+    void init();
+    void deinit();
+    void registerGpioUri();
+    esp_err_t handleHttpRequest(httpd_req_t *req);
+    void taskHandler();
+    void gpioInterrupt(GpioResult* gpioResult);  
+    void flashLightEnable(bool value);
+    bool isEnabled() { return _isEnabled; }
+    void handleMQTTconnect();
+
+private:
+    std::string _configFile;
+    httpd_handle_t _httpServer;
+    std::map<gpio_num_t, GpioPin*> *gpioMap = NULL;
+    TaskHandle_t xHandleTaskGpio = NULL;
+    bool _isEnabled = false;
+
+    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 gpio_handler_create(httpd_handle_t server);
+void gpio_handler_init();
+void gpio_handler_deinit();
+void gpio_handler_destroy();
+GpioHandler* gpio_handler_get();
+
 
 
-void register_server_GPIO_uri(httpd_handle_t server);
 
 
+#endif //SERVER_GPIO_H

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

@@ -4,6 +4,6 @@ list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/proto
 
 
 idf_component_register(SRCS ${app_sources}
 idf_component_register(SRCS ${app_sources}
                     INCLUDE_DIRS "."
                     INCLUDE_DIRS "."
-                    REQUIRES esp32-camera-master esp_http_server jomjol_logfile jomjol_image_proc nvs_flash jomjol_fileserver_ota)
+                    REQUIRES esp32-camera-master esp_http_server jomjol_logfile jomjol_image_proc nvs_flash jomjol_fileserver_ota jomjol_controlGPIO)
 
 
 
 

+ 18 - 13
code/components/jomjol_controlcamera/ClassControllCamera.cpp

@@ -10,12 +10,13 @@
 #include "CImageBasis.h"
 #include "CImageBasis.h"
 
 
 #include "server_ota.h"
 #include "server_ota.h"
+#include "server_GPIO.h"
 
 
 
 
 #define BOARD_ESP32CAM_AITHINKER
 #define BOARD_ESP32CAM_AITHINKER
 
 
 
 
-#include <esp_event_loop.h>
+#include <esp_event.h>
 #include <esp_log.h>
 #include <esp_log.h>
 #include <esp_system.h>
 #include <esp_system.h>
 #include <nvs_flash.h>
 #include <nvs_flash.h>
@@ -50,7 +51,7 @@
 #define CAM_PIN_HREF 23
 #define CAM_PIN_HREF 23
 #define CAM_PIN_PCLK 22
 #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 = {
 static camera_config_t camera_config = {
     .pin_pwdn = CAM_PIN_PWDN,
     .pin_pwdn = CAM_PIN_PWDN,
@@ -275,7 +276,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
 
 
     camera_fb_t * fb = esp_camera_fb_get();
     camera_fb_t * fb = esp_camera_fb_get();
     if (!fb) {
     if (!fb) {
-        ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
+        ESP_LOGE(TAGCAMERACLASS, "CaptureToBasisImage: Camera Capture Failed");
         LEDOnOff(false);
         LEDOnOff(false);
         LightOnOff(false);
         LightOnOff(false);
         doReboot();
         doReboot();
@@ -362,8 +363,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
 
 
     camera_fb_t * fb = esp_camera_fb_get();
     camera_fb_t * fb = esp_camera_fb_get();
     if (!fb) {
     if (!fb) {
-        ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
-        ESP_LOGE(TAGCAMERACLASS, "Reboot ?????");
+        ESP_LOGE(TAGCAMERACLASS, "CaptureToFile: Camera Capture Failed");
         LEDOnOff(false);
         LEDOnOff(false);
         LightOnOff(false);
         LightOnOff(false);
         doReboot();
         doReboot();
@@ -497,15 +497,20 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
 
 
 void CCamera::LightOnOff(bool status)
 void CCamera::LightOnOff(bool status)
 {
 {
-	// Init the GPIO
-    gpio_pad_select_gpio(FLASH_GPIO);
-    /* Set the GPIO as a push/pull output */
-    gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT);  
+    GpioHandler* gpioHandler = gpio_handler_get();
+    if ((gpioHandler != NULL) && (gpioHandler->isEnabled())) {
+        gpioHandler->flashLightEnable(status);
+    }  else {
+        // Init the GPIO
+        gpio_pad_select_gpio(FLASH_GPIO);
+        /* Set the GPIO as a push/pull output */
+        gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT);  
 
 
-    if (status)  
-        gpio_set_level(FLASH_GPIO, 1);
-    else
-        gpio_set_level(FLASH_GPIO, 0);      
+        if (status)  
+            gpio_set_level(FLASH_GPIO, 1);
+        else
+            gpio_set_level(FLASH_GPIO, 0);
+    }
 }
 }
 
 
 void CCamera::LEDOnOff(bool status)
 void CCamera::LEDOnOff(bool status)

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

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

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

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

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

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

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

@@ -1,7 +1,7 @@
 FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
 
 
 idf_component_register(SRCS ${app_sources}
 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)
+                    INCLUDE_DIRS "." "../../include"
+                    REQUIRES tfmicro esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper jomjol_controlGPIO)
 
 
 
 

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

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

+ 13 - 9
code/components/jomjol_fileserver_ota/server_ota.cpp

@@ -12,7 +12,7 @@
 #include "freertos/task.h"
 #include "freertos/task.h"
 #include "esp_system.h"
 #include "esp_system.h"
 #include "esp_event.h"
 #include "esp_event.h"
-#include "esp_event_loop.h"
+#include "esp_event.h"
 #include "esp_log.h"
 #include "esp_log.h"
 #include <esp_ota_ops.h>
 #include <esp_ota_ops.h>
 #include "esp_http_client.h"
 #include "esp_http_client.h"
@@ -28,6 +28,7 @@
 
 
 #include "server_tflite.h"
 #include "server_tflite.h"
 #include "server_file.h"
 #include "server_file.h"
+#include "server_GPIO.h"
 
 
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 
 
@@ -46,6 +47,7 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
 
 
 
 
 #define OTA_URL_SIZE 256
 #define OTA_URL_SIZE 256
+static const char *TAGPARTOTA = "server_ota";
 
 
 
 
 static void infinite_loop(void)
 static void infinite_loop(void)
@@ -60,14 +62,14 @@ static void infinite_loop(void)
 
 
 
 
 
 
-static bool ota_example_task(std::string fn)
+static bool ota_update_task(std::string fn)
 {
 {
     esp_err_t err;
     esp_err_t err;
     /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
     /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */
     esp_ota_handle_t update_handle = 0 ;
     esp_ota_handle_t update_handle = 0 ;
     const esp_partition_t *update_partition = NULL;
     const esp_partition_t *update_partition = NULL;
 
 
-    ESP_LOGI(TAGPARTOTA, "Starting OTA example");
+    ESP_LOGI(TAGPARTOTA, "Starting OTA update");
 
 
     const esp_partition_t *configured = esp_ota_get_boot_partition();
     const esp_partition_t *configured = esp_ota_get_boot_partition();
     const esp_partition_t *running = esp_ota_get_running_partition();
     const esp_partition_t *running = esp_ota_get_running_partition();
@@ -374,7 +376,9 @@ esp_err_t handler_ota_update(httpd_req_t *req)
 
 
     const char* resp_str;    
     const char* resp_str;    
 
 
-    if (ota_example_task(fn))
+    KillTFliteTasks();
+    gpio_handler_deinit();
+    if (ota_update_task(fn))
     {
     {
         resp_str = "Firmware Update Successfull!<br><br>You can restart now.";
         resp_str = "Firmware Update Successfull!<br><br>You can restart now.";
     }
     }
@@ -400,8 +404,6 @@ void hard_restart() {
 
 
 void task_reboot(void *pvParameter)
 void task_reboot(void *pvParameter)
 {
 {
-
-
     while(1)
     while(1)
     {
     {
         vTaskDelay(5000 / portTICK_PERIOD_MS);
         vTaskDelay(5000 / portTICK_PERIOD_MS);
@@ -413,12 +415,14 @@ void task_reboot(void *pvParameter)
 }
 }
 
 
 void doReboot(){
 void doReboot(){
-    LogFile.WriteToFile("Reboot - now");
-    KillTFliteTasks();
+    ESP_LOGI(TAGPARTOTA, "Reboot in 5sec");
+    LogFile.WriteToFile("Reboot in 5sec");
     xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
     xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
+    // KillTFliteTasks(); // kills itself 
+    gpio_handler_destroy();
     vTaskDelay(5000 / portTICK_PERIOD_MS);
     vTaskDelay(5000 / portTICK_PERIOD_MS);
     esp_restart();
     esp_restart();
-    hard_restart();    
+    hard_restart();
 }
 }
 
 
 
 

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

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

+ 22 - 6
code/components/jomjol_flowcontroll/ClassFlow.cpp

@@ -94,6 +94,23 @@ string ClassFlow::getReadout()
 	return string();
 	return string();
 }
 }
 
 
+std::string ClassFlow::GetParameterName(std::string _input)
+{
+    string _param;
+    int _pospunkt = _input.find_first_of(".");
+    if (_pospunkt > -1)
+    {
+        _param = _input.substr(_pospunkt+1, _input.length() - _pospunkt - 1);
+    }
+    else
+    {
+        _param = _input;
+    }
+//    printf("Parameter: %s, Pospunkt: %d\n", _param.c_str(), _pospunkt);
+	return _param;
+}
+
+
 bool ClassFlow::getNextLine(FILE* pfile, string *rt)
 bool ClassFlow::getNextLine(FILE* pfile, string *rt)
 {
 {
 	char zw[1024];
 	char zw[1024];
@@ -102,24 +119,23 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
 		*rt = "";
 		*rt = "";
 		return false;
 		return false;
 	}
 	}
-	fgets(zw, 1024, pfile);
-	printf("%s", zw);
-	if ((strlen(zw) == 0) && feof(pfile))
+	if (!fgets(zw, 1024, pfile))
 	{
 	{
 		*rt = "";
 		*rt = "";
+		printf("END OF FILE\n");
 		return false;
 		return false;
 	}
 	}
+	printf("%s", zw);
 	*rt = zw;
 	*rt = zw;
 	*rt = trim(*rt);
 	*rt = trim(*rt);
 	while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))			// Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
 	while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))			// Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
 	{
 	{
-		fgets(zw, 1024, pfile);
-		printf("%s", zw);		
-		if (feof(pfile))
+		if (!fgets(zw, 1024, pfile))
 		{
 		{
 			*rt = "";
 			*rt = "";
 			return false;
 			return false;
 		}
 		}
+		printf("%s", zw);		
 		*rt = zw;
 		*rt = zw;
 		*rt = trim(*rt);
 		*rt = trim(*rt);
 	}
 	}

+ 2 - 0
code/components/jomjol_flowcontroll/ClassFlow.h

@@ -37,6 +37,8 @@ protected:
 
 
 	virtual void SetInitialParameter(void);
 	virtual void SetInitialParameter(void);
 
 
+	std::string GetParameterName(std::string _input);
+
 	bool disabled;
 	bool disabled;
 
 
 public:
 public:

+ 205 - 67
code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp

@@ -1,7 +1,7 @@
 #include "ClassFlowAnalog.h"
 #include "ClassFlowAnalog.h"
 
 
 #include <math.h>
 #include <math.h>
-#include <iomanip>
+#include <iomanip> 
 #include <sys/types.h>
 #include <sys/types.h>
 #include <sstream>      // std::stringstream
 #include <sstream>      // std::stringstream
 
 
@@ -46,9 +46,9 @@ ClassFlowAnalog::ClassFlowAnalog(std::vector<ClassFlow*>* lfc) : ClassFlowImage(
 }
 }
 
 
 
 
-int ClassFlowAnalog::AnzahlROIs()
+int ClassFlowAnalog::AnzahlROIs(int _analog = 0)
 {
 {
-    int zw = ROI.size();
+    int zw = ANALOG[_analog]->ROI.size();
     if (extendedResolution)
     if (extendedResolution)
         zw++;
         zw++;
     
     
@@ -56,27 +56,27 @@ int ClassFlowAnalog::AnzahlROIs()
 } 
 } 
 
 
 
 
-string ClassFlowAnalog::getReadout()
+string ClassFlowAnalog::getReadout(int _analog = 0)
 {
 {
     string result = "";    
     string result = "";    
-    if (ROI.size() == 0)
+    if (ANALOG[_analog]->ROI.size() == 0)
         return result;
         return result;
 
 
 
 
-    float zahl = ROI[ROI.size() - 1]->result;
+    float zahl = ANALOG[_analog]->ROI[ANALOG[_analog]->ROI.size() - 1]->result;
     int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
     int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
 
 
     int prev = -1;
     int prev = -1;
 
 
-    prev = ZeigerEval(ROI[ROI.size() - 1]->result, prev);
+    prev = ZeigerEval(ANALOG[_analog]->ROI[ANALOG[_analog]->ROI.size() - 1]->result, prev);
     result = std::to_string(prev);
     result = std::to_string(prev);
 
 
     if (extendedResolution)
     if (extendedResolution)
         result = result + std::to_string(ergebnis_nachkomma);
         result = result + std::to_string(ergebnis_nachkomma);
 
 
-    for (int i = ROI.size() - 2; i >= 0; --i)
+    for (int i = ANALOG[_analog]->ROI.size() - 2; i >= 0; --i)
     {
     {
-        prev = ZeigerEval(ROI[i]->result, prev);
+        prev = ZeigerEval(ANALOG[_analog]->ROI[i]->result, prev);
         result = std::to_string(prev) + result;
         result = std::to_string(prev) + result;
     }
     }
 
 
@@ -153,8 +153,8 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
         }
         }
         if (zerlegt.size() >= 5)
         if (zerlegt.size() >= 5)
         {
         {
-            roianalog* neuroi = new roianalog;
-            neuroi->name = zerlegt[0];
+            analog* _analog = GetANALOG(zerlegt[0], true);
+            roianalog* neuroi = _analog->ROI[_analog->ROI.size()-1];
             neuroi->posx = std::stoi(zerlegt[1]);
             neuroi->posx = std::stoi(zerlegt[1]);
             neuroi->posy = std::stoi(zerlegt[2]);
             neuroi->posy = std::stoi(zerlegt[2]);
             neuroi->deltax = std::stoi(zerlegt[3]);
             neuroi->deltax = std::stoi(zerlegt[3]);
@@ -162,7 +162,7 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
             neuroi->result = -1;
             neuroi->result = -1;
             neuroi->image = NULL;
             neuroi->image = NULL;
             neuroi->image_org = NULL;
             neuroi->image_org = NULL;
-            ROI.push_back(neuroi);
+//            ROI.push_back(neuroi);
         }
         }
 
 
         if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
         if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
@@ -178,16 +178,77 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph)
         }
         }
     }
     }
 
 
-    for (int i = 0; i < ROI.size(); ++i)
+   for (int _ana = 0; _ana < ANALOG.size(); ++_ana)
+        for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i)
+        {
+            ANALOG[_ana]->ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
+            ANALOG[_ana]->ROI[i]->image_org = new CImageBasis(ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, 3);
+        }
+
+    return true;
+}
+
+analog* ClassFlowAnalog::FindANALOG(string _name_number)
+{
+    analog *_ret = NULL;
+
+    for (int i = 0; i < ANALOG.size(); ++i)
     {
     {
-        ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
-        ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3);
+        if (ANALOG[i]->name == _name_number)
+            return ANALOG[i];
     }
     }
 
 
-    return true;
+    return NULL;
 }
 }
 
 
 
 
+
+analog* ClassFlowAnalog::GetANALOG(string _name, bool _create = true)
+{
+    string _analog, _roi;
+    int _pospunkt = _name.find_first_of(".");
+//    printf("Name: %s, Pospunkt: %d\n", _name.c_str(), _pospunkt);
+    if (_pospunkt > -1)
+    {
+        _analog = _name.substr(0, _pospunkt);
+        _roi = _name.substr(_pospunkt+1, _name.length() - _pospunkt - 1);
+    }
+    else
+    {
+        _analog = "default";
+        _roi = _name;
+    }
+
+    analog *_ret = NULL;
+
+    for (int i = 0; i < ANALOG.size(); ++i)
+    {
+        if (ANALOG[i]->name == _analog)
+            _ret = ANALOG[i];
+    }
+
+    if (!_create)         // nicht gefunden und soll auch nicht erzeugt werden
+        return _ret;
+
+
+    if (_ret == NULL)
+    {
+        _ret = new analog;
+        _ret->name = _analog;
+        ANALOG.push_back(_ret);
+    }
+
+    roianalog* neuroi = new roianalog;
+    neuroi->name = _roi;
+    _ret->ROI.push_back(neuroi);
+
+    printf("GetANALOG - ANALOG %s - roi %s\n", _analog.c_str(), _roi.c_str());
+
+    return _ret;
+}
+
+
+
 string ClassFlowAnalog::getHTMLSingleStep(string host)
 string ClassFlowAnalog::getHTMLSingleStep(string host)
 {
 {
     string result, zw;
     string result, zw;
@@ -238,16 +299,29 @@ bool ClassFlowAnalog::doAlignAndCut(string time)
 
 
     CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();    
     CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();    
 
 
-    for (int i = 0; i < ROI.size(); ++i)
-    {
-        printf("Analog %d - Align&Cut\n", i);
-        
-        caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org);
-        if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
-
-        ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image);
-        if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
-    }
+    for (int _ana = 0; _ana < ANALOG.size(); ++_ana)
+        for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i)
+        {
+            printf("Analog %d - Align&Cut\n", i);
+            
+            caic->CutAndSave(ANALOG[_ana]->ROI[i]->posx, ANALOG[_ana]->ROI[i]->posy, ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, ANALOG[_ana]->ROI[i]->image_org);
+            if (SaveAllFiles)
+            {
+                if (ANALOG[_ana]->name == "default")
+                    ANALOG[_ana]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".jpg"));
+                else
+                    ANALOG[_ana]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".jpg"));
+            } 
+
+            ANALOG[_ana]->ROI[i]->image_org->Resize(modelxsize, modelysize, ANALOG[_ana]->ROI[i]->image);
+            if (SaveAllFiles)
+            {
+                if (ANALOG[_ana]->name == "default")
+                    ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".bmp"));
+                else
+                    ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp"));
+            } 
+        }
 
 
     return true;
     return true;
 } 
 } 
@@ -258,13 +332,14 @@ void ClassFlowAnalog::DrawROI(CImageBasis *_zw)
     int g = 255;
     int g = 255;
     int b = 0;
     int b = 0;
 
 
-    for (int i = 0; i < ROI.size(); ++i)
-    {
-        _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1);
-        _zw->drawCircle((int) (ROI[i]->posx + ROI[i]->deltax/2), (int)  (ROI[i]->posy + ROI[i]->deltay/2), (int) (ROI[i]->deltax/2), r, g, b, 2);
-        _zw->drawLine((int) (ROI[i]->posx + ROI[i]->deltax/2), (int) ROI[i]->posy, (int) (ROI[i]->posx + ROI[i]->deltax/2), (int) (ROI[i]->posy + ROI[i]->deltay), r, g, b, 2);
-        _zw->drawLine((int) ROI[i]->posx, (int) (ROI[i]->posy + ROI[i]->deltay/2), (int) ROI[i]->posx + ROI[i]->deltax, (int) (ROI[i]->posy + ROI[i]->deltay/2), r, g, b, 2);
-    }
+    for (int _ana = 0; _ana < ANALOG.size(); ++_ana)
+        for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i)
+        {
+            _zw->drawRect(ANALOG[_ana]->ROI[i]->posx, ANALOG[_ana]->ROI[i]->posy, ANALOG[_ana]->ROI[i]->deltax, ANALOG[_ana]->ROI[i]->deltay, r, g, b, 1);
+            _zw->drawCircle((int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int)  (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), (int) (ANALOG[_ana]->ROI[i]->deltax/2), r, g, b, 2);
+            _zw->drawLine((int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int) ANALOG[_ana]->ROI[i]->posy, (int) (ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax/2), (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay), r, g, b, 2);
+            _zw->drawLine((int) ANALOG[_ana]->ROI[i]->posx, (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), (int) ANALOG[_ana]->ROI[i]->posx + ANALOG[_ana]->ROI[i]->deltax, (int) (ANALOG[_ana]->ROI[i]->posy + ANALOG[_ana]->ROI[i]->deltay/2), r, g, b, 2);
+        }
 } 
 } 
 
 
 bool ClassFlowAnalog::doNeuralNetwork(string time)
 bool ClassFlowAnalog::doNeuralNetwork(string time)
@@ -284,43 +359,46 @@ bool ClassFlowAnalog::doNeuralNetwork(string time)
     string zwcnn = "/sdcard" + cnnmodelfile;
     string zwcnn = "/sdcard" + cnnmodelfile;
     zwcnn = FormatFileName(zwcnn);
     zwcnn = FormatFileName(zwcnn);
     printf(zwcnn.c_str());printf("\n");
     printf(zwcnn.c_str());printf("\n");
-    tflite->LoadModel(zwcnn); 
+    if (!tflite->LoadModel(zwcnn)) {
+        printf("Can't read model file /sdcard%s\n", cnnmodelfile.c_str());
+        delete tflite;
+        return false;
+    } 
     tflite->MakeAllocate();
     tflite->MakeAllocate();
 #endif
 #endif
 
 
-    for (int i = 0; i < ROI.size(); ++i)
+    for (int _ana = 0; _ana < ANALOG.size(); ++_ana)
     {
     {
-        printf("Analog %d - TfLite\n", i);
-        ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp";
-        ioresize = FormatFileName(ioresize);
-
+        for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i)
+        {
+            printf("Analog %d - TfLite\n", i);
 
 
-        float f1, f2;
-        f1 = 0; f2 = 0;
+            float f1, f2;
+            f1 = 0; f2 = 0;
 
 
-#ifndef OHNETFLITE
-//        LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)");
-//        tflite->LoadInputImage(ioresize);
-        tflite->LoadInputImageBasis(ROI[i]->image);        
-        tflite->Invoke();
-        if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke");
+    #ifndef OHNETFLITE
+            tflite->LoadInputImageBasis(ANALOG[_ana]->ROI[i]->image);        
+            tflite->Invoke();
+            if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke");
 
 
 
 
-        f1 = tflite->GetOutputValue(0);
-        f2 = tflite->GetOutputValue(1);
-#endif
+            f1 = tflite->GetOutputValue(0);
+            f2 = tflite->GetOutputValue(1);
+    #endif
 
 
-        float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
-//        printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result);  
-        ROI[i]->result = result * 10;
+            float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
+    //        printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result);  
+            ANALOG[_ana]->ROI[i]->result = result * 10;
 
 
-        printf("Result Analog%i: %f\n", i, ROI[i]->result); 
+            printf("Result Analog%i: %f\n", i, ANALOG[_ana]->ROI[i]->result); 
 
 
-        if (isLogImage)
-        {
-            LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org);
+            if (isLogImage)
+            {
+                LogImage(logPath, ANALOG[_ana]->ROI[i]->name, &ANALOG[_ana]->ROI[i]->result, NULL, time, ANALOG[_ana]->ROI[i]->image_org);
+            }
         }
         }
     }
     }
+
 #ifndef OHNETFLITE
 #ifndef OHNETFLITE
         delete tflite;
         delete tflite;
 #endif    
 #endif    
@@ -333,18 +411,78 @@ std::vector<HTMLInfo*> ClassFlowAnalog::GetHTMLInfo()
 {
 {
     std::vector<HTMLInfo*> result;
     std::vector<HTMLInfo*> result;
 
 
-    for (int i = 0; i < ROI.size(); ++i)
-    {
-        HTMLInfo *zw = new HTMLInfo;
-        zw->filename = ROI[i]->name + ".bmp";
-        zw->filename_org = ROI[i]->name + ".jpg";
-        zw->val = ROI[i]->result;
-        zw->image = ROI[i]->image;
-        zw->image_org = ROI[i]->image_org;
-        result.push_back(zw);
-    }
+    for (int _ana = 0; _ana < ANALOG.size(); ++_ana)
+        for (int i = 0; i < ANALOG[_ana]->ROI.size(); ++i)
+        {
+                if (ANALOG[_ana]->name == "default")
+                    ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->ROI[i]->name + ".bmp"));
+                else
+                    ANALOG[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp"));
+
+
+            HTMLInfo *zw = new HTMLInfo;
+            if (ANALOG[_ana]->name == "default")
+            {
+                zw->filename = ANALOG[_ana]->ROI[i]->name + ".bmp";
+                zw->filename_org = ANALOG[_ana]->ROI[i]->name + ".jpg";
+            }
+            else
+            {
+                zw->filename = ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".bmp";
+                zw->filename_org = ANALOG[_ana]->name + "_" + ANALOG[_ana]->ROI[i]->name + ".jpg";
+            }
+
+            zw->val = ANALOG[_ana]->ROI[i]->result;
+            zw->image = ANALOG[_ana]->ROI[i]->image;
+            zw->image_org = ANALOG[_ana]->ROI[i]->image_org;
+
+            result.push_back(zw);
+        }
 
 
     return result;
     return result;
 }
 }
 
 
 
 
+
+int ClassFlowAnalog::getAnzahlANALOG()
+{
+    return ANALOG.size();
+}
+
+string ClassFlowAnalog::getNameANALOG(int _analog)
+{
+    if (_analog < ANALOG.size())
+        return ANALOG[_analog]->name;
+
+    return "ANALOG DOES NOT EXIST";
+}
+
+analog* ClassFlowAnalog::GetANALOG(int _analog)
+{
+    if (_analog < ANALOG.size())
+        return ANALOG[_analog];
+
+    return NULL;
+}
+
+
+
+void ClassFlowAnalog::UpdateNameNumbers(std::vector<std::string> *_name_numbers)
+{
+    for (int _dig = 0; _dig < ANALOG.size(); _dig++)
+    {
+        std::string _name = ANALOG[_dig]->name;
+        bool found = false;
+        for (int i = 0; i < (*_name_numbers).size(); ++i)
+        {
+            if ((*_name_numbers)[i] == _name)
+                found = true;
+        }
+        if (!found)
+            (*_name_numbers).push_back(_name);
+    }
+}
+
+
+
+

+ 21 - 4
code/components/jomjol_flowcontroll/ClassFlowAnalog.h

@@ -10,12 +10,19 @@ struct roianalog {
     string name;
     string name;
 };
 };
 
 
+struct analog {
+    string name;
+    std::vector<roianalog*> ROI;
+};
+
 
 
 class ClassFlowAnalog :
 class ClassFlowAnalog :
     public ClassFlowImage
     public ClassFlowImage
 {
 {
 protected:
 protected:
-    std::vector<roianalog*> ROI;
+//    std::vector<roianalog*> ROI;
+    std::vector<analog*> ANALOG;
+
     string cnnmodelfile;
     string cnnmodelfile;
     int modelxsize, modelysize;
     int modelxsize, modelysize;
     int ZeigerEval(float zahl, int ziffer_vorgaenger);
     int ZeigerEval(float zahl, int ziffer_vorgaenger);
@@ -24,7 +31,8 @@ protected:
 
 
     ClassFlowAlignment* flowpostalignment;
     ClassFlowAlignment* flowpostalignment;
 
 
-	void SetInitialParameter(void);        
+	void SetInitialParameter(void);   
+
 
 
 public:
 public:
     bool extendedResolution;
     bool extendedResolution;
@@ -34,14 +42,23 @@ public:
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     bool doFlow(string time);
     string getHTMLSingleStep(string host);
     string getHTMLSingleStep(string host);
-    string getReadout();   
+    string getReadout(int _analog);   
 
 
     void DrawROI(CImageBasis *_zw); 
     void DrawROI(CImageBasis *_zw); 
 
 
     bool doNeuralNetwork(string time); 
     bool doNeuralNetwork(string time); 
     bool doAlignAndCut(string time);
     bool doAlignAndCut(string time);
    	std::vector<HTMLInfo*> GetHTMLInfo();   
    	std::vector<HTMLInfo*> GetHTMLInfo();   
-    int AnzahlROIs(); 
+    int AnzahlROIs(int _analog);
+
+    int getAnzahlANALOG();
+    analog* GetANALOG(int _analog);
+    analog* GetANALOG(string _name, bool _create);
+    analog* FindANALOG(string _name_number);    
+    string getNameANALOG(int _analog);     
+
+    void UpdateNameNumbers(std::vector<std::string> *_name_numbers);
+
 
 
     string name(){return "ClassFlowAnalog";}; 
     string name(){return "ClassFlowAnalog";}; 
 };
 };

+ 50 - 7
code/components/jomjol_flowcontroll/ClassFlowControll.cpp

@@ -120,6 +120,7 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
     }
     }
     if (toUpper(_type).compare("[MQTT]") == 0)
     if (toUpper(_type).compare("[MQTT]") == 0)
         cfc = new ClassFlowMQTT(&FlowControll);
         cfc = new ClassFlowMQTT(&FlowControll);
+        
     if (toUpper(_type).compare("[POSTPROCESSING]") == 0)
     if (toUpper(_type).compare("[POSTPROCESSING]") == 0)
     {
     {
         cfc = new ClassFlowPostProcessing(&FlowControll); 
         cfc = new ClassFlowPostProcessing(&FlowControll); 
@@ -209,7 +210,7 @@ bool ClassFlowControll::doFlow(string time)
     int repeat = 0;
     int repeat = 0;
 
 
 #ifdef DEBUG_DETAIL_ON 
 #ifdef DEBUG_DETAIL_ON 
-    LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow - Start");
+    LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
 #endif
 #endif
 
 
     for (int i = 0; i < FlowControll.size(); ++i)
     for (int i = 0; i < FlowControll.size(); ++i)
@@ -238,7 +239,7 @@ bool ClassFlowControll::doFlow(string time)
         }
         }
         
         
 #ifdef DEBUG_DETAIL_ON  
 #ifdef DEBUG_DETAIL_ON  
-        LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow");
+        LogFile.WriteHeapInfo("ClassFlowControll::doFlow");
 #endif
 #endif
 
 
     }
     }
@@ -262,6 +263,38 @@ void ClassFlowControll::UpdateAktStatus(std::string _flow)
 }
 }
 
 
 
 
+string ClassFlowControll::getReadoutAll(int _type)
+{
+    std::vector<NumberPost*> numbers = flowpostprocessing->GetNumbers();
+    std::string out = "";
+
+    for (int i = 0; i < numbers.size(); ++i)
+    {
+        out = out + numbers[i]->name + "\t";
+        switch (_type) {
+            case READOUT_TYPE_VALUE:
+                out = out + numbers[i]->ReturnValue;
+                break;
+            case READOUT_TYPE_PREVALUE:
+                out = out + numbers[i]->ReturnPreValue;
+                break;
+            case READOUT_TYPE_RAWVALUE:
+                out = out + numbers[i]->ReturnRawValue;
+                break;
+            case READOUT_TYPE_ERROR:
+                out = out + numbers[i]->ErrorMessageText;
+                break;
+        }
+        if (i < numbers.size()-1)
+            out = out + "\r\n";
+    }
+
+//    printf("OUT: %s", out.c_str());
+
+    return out;
+}	
+
+
 string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false)
 string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = false)
 {
 {
     if (flowpostprocessing)
     if (flowpostprocessing)
@@ -285,17 +318,17 @@ string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = fal
     return result;
     return result;
 }
 }
 
 
-string ClassFlowControll::GetPrevalue()	
+string ClassFlowControll::GetPrevalue(std::string _number)	
 {
 {
     if (flowpostprocessing)
     if (flowpostprocessing)
     {
     {
-        return flowpostprocessing->GetPreValue();   
+        return flowpostprocessing->GetPreValue(_number);   
     }
     }
 
 
     return std::string();    
     return std::string();    
 }
 }
 
 
-std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue)
+std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers)
 {
 {
     float zw;
     float zw;
     char* p;
     char* p;
@@ -317,7 +350,7 @@ std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue)
 
 
     if (flowpostprocessing)
     if (flowpostprocessing)
     {
     {
-        flowpostprocessing->SavePreValue(zw);
+        flowpostprocessing->SetPreValue(zw, _numbers);
         return _newvalue;    
         return _newvalue;    
     }
     }
 
 
@@ -442,7 +475,7 @@ int ClassFlowControll::CleanTempFolder() {
 
 
 esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req)
 esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req)
 {
 {
-    return flowmakeimage->SendRawJPG(req);
+    return flowmakeimage != NULL ? flowmakeimage->SendRawJPG(req) : ESP_FAIL;
 }
 }
 
 
 
 
@@ -454,6 +487,12 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
     esp_err_t result = ESP_FAIL;
     esp_err_t result = ESP_FAIL;
     bool Dodelete = false;    
     bool Dodelete = false;    
 
 
+    if (flowalignment == NULL)
+    {
+        printf("Can't continue, flowalignment is NULL\n");
+        return ESP_FAIL;
+    }
+
     if (_fn == "alg.jpg")
     if (_fn == "alg.jpg")
     {
     {
         _send = flowalignment->ImageBasis;  
         _send = flowalignment->ImageBasis;  
@@ -485,7 +524,9 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
             if (htmlinfo[i]->image_org)
             if (htmlinfo[i]->image_org)
                 _send = htmlinfo[i]->image_org;        
                 _send = htmlinfo[i]->image_org;        
         }
         }
+        delete htmlinfo[i];
     }
     }
+    htmlinfo.clear();
 
 
     htmlinfo = GetAllAnalog();
     htmlinfo = GetAllAnalog();
     for (int i = 0; i < htmlinfo.size(); ++i)
     for (int i = 0; i < htmlinfo.size(); ++i)
@@ -500,7 +541,9 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
             if (htmlinfo[i]->image_org)
             if (htmlinfo[i]->image_org)
                 _send = htmlinfo[i]->image_org;        
                 _send = htmlinfo[i]->image_org;        
         }
         }
+        delete htmlinfo[i];
     }
     }
+    htmlinfo.clear();
 
 
     if (_send)
     if (_send)
     {
     {

+ 9 - 2
code/components/jomjol_flowcontroll/ClassFlowControll.h

@@ -11,6 +11,12 @@
 #include "ClassFlowMQTT.h"
 #include "ClassFlowMQTT.h"
 
 
 
 
+#define READOUT_TYPE_VALUE 0
+#define READOUT_TYPE_PREVALUE 1
+#define READOUT_TYPE_RAWVALUE 2
+#define READOUT_TYPE_ERROR 3
+
+
 class ClassFlowControll :
 class ClassFlowControll :
     public ClassFlow
     public ClassFlow
 {
 {
@@ -38,8 +44,9 @@ public:
 	void doFlowMakeImageOnly(string time);
 	void doFlowMakeImageOnly(string time);
 	bool getStatusSetupModus(){return SetupModeActive;};
 	bool getStatusSetupModus(){return SetupModeActive;};
 	string getReadout(bool _rawvalue, bool _noerror);
 	string getReadout(bool _rawvalue, bool _noerror);
-	string UpdatePrevalue(std::string _newvalue);
-	string GetPrevalue();	
+	string getReadoutAll(int _type);	
+	string UpdatePrevalue(std::string _newvalue, std::string _numbers);
+	string GetPrevalue(std::string _number = "");	
 	bool ReadParameter(FILE* pfile, string& aktparamgraph);	
 	bool ReadParameter(FILE* pfile, string& aktparamgraph);	
 
 
 	esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req);
 	esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req);

+ 181 - 52
code/components/jomjol_flowcontroll/ClassFlowDigit.cpp

@@ -64,16 +64,16 @@ ClassFlowDigit::ClassFlowDigit(std::vector<ClassFlow*>* lfc, ClassFlow *_prev) :
     }    
     }    
 }
 }
 
 
-string ClassFlowDigit::getReadout()
+string ClassFlowDigit::getReadout(int _digit = 0)
 {
 {
     string rst = "";
     string rst = "";
 
 
-    for (int i = 0; i < ROI.size(); ++i)
+    for (int i = 0; i < DIGIT[_digit]->ROI.size(); ++i)
     {
     {
-        if (ROI[i]->resultklasse == 10)
+        if (DIGIT[_digit]->ROI[i]->resultklasse == 10)
             rst = rst + "N";
             rst = rst + "N";
         else
         else
-            rst = rst + std::to_string(ROI[i]->resultklasse);
+            rst = rst + std::to_string(DIGIT[_digit]->ROI[i]->resultklasse);
     }
     }
 
 
     return rst;
     return rst;
@@ -91,18 +91,11 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
 
 
     printf("aktparamgraph: %s\n", aktparamgraph.c_str());
     printf("aktparamgraph: %s\n", aktparamgraph.c_str());
 
 
-
-/*
-    if ((aktparamgraph.compare("[Digits]") != 0) && (aktparamgraph.compare(";[Digits]") != 0))       // Paragraph passt nich zu MakeImage
-        return false;
-*/
-
     if ((aktparamgraph.compare(0, 7, "[Digits") != 0) && (aktparamgraph.compare(0, 8, ";[Digits") != 0))       // Paragraph passt nich zu MakeImage
     if ((aktparamgraph.compare(0, 7, "[Digits") != 0) && (aktparamgraph.compare(0, 8, ";[Digits") != 0))       // Paragraph passt nich zu MakeImage
         return false;
         return false;
 
 
     int _pospkt = aktparamgraph.find_first_of(".");
     int _pospkt = aktparamgraph.find_first_of(".");
     int _posklammerzu = aktparamgraph.find_first_of("]");
     int _posklammerzu = aktparamgraph.find_first_of("]");
-//    printf("Pos: %d, %d\n", _pospkt, _posklammerzu);
     if (_pospkt > -1)
     if (_pospkt > -1)
         NameDigit = aktparamgraph.substr(_pospkt+1, _posklammerzu - _pospkt-1);
         NameDigit = aktparamgraph.substr(_pospkt+1, _posklammerzu - _pospkt-1);
     else
     else
@@ -137,8 +130,8 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
         }
         }
         if (zerlegt.size() >= 5)
         if (zerlegt.size() >= 5)
         {
         {
-            roi* neuroi = new roi;
-            neuroi->name = zerlegt[0];
+            digit* _digit = GetDIGIT(zerlegt[0], true);
+            roi* neuroi = _digit->ROI[_digit->ROI.size()-1];
             neuroi->posx = std::stoi(zerlegt[1]);
             neuroi->posx = std::stoi(zerlegt[1]);
             neuroi->posy = std::stoi(zerlegt[2]);
             neuroi->posy = std::stoi(zerlegt[2]);
             neuroi->deltax = std::stoi(zerlegt[3]);
             neuroi->deltax = std::stoi(zerlegt[3]);
@@ -146,7 +139,6 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
             neuroi->resultklasse = -1;
             neuroi->resultklasse = -1;
             neuroi->image = NULL;
             neuroi->image = NULL;
             neuroi->image_org = NULL;            
             neuroi->image_org = NULL;            
-            ROI.push_back(neuroi);
         }
         }
 
 
         if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
         if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
@@ -157,16 +149,75 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph)
 
 
     }
     }
 
 
-    for (int i = 0; i < ROI.size(); ++i)
+   for (int _dig = 0; _dig < DIGIT.size(); ++_dig)
+        for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i)
+        {
+            DIGIT[_dig]->ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
+            DIGIT[_dig]->ROI[i]->image_org = new CImageBasis(DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, 3);
+        }
+
+    return true;
+}
+
+digit* ClassFlowDigit::FindDIGIT(string _name_number)
+{
+    digit *_ret = NULL;
+
+    for (int i = 0; i < DIGIT.size(); ++i)
     {
     {
-        ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3);
-        ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3);
+        if (DIGIT[i]->name == _name_number)
+            return DIGIT[i];
     }
     }
 
 
-    return true;
+    return NULL;
 }
 }
 
 
 
 
+digit* ClassFlowDigit::GetDIGIT(string _name, bool _create = true)
+{
+    string _digit, _roi;
+    int _pospunkt = _name.find_first_of(".");
+//    printf("Name: %s, Pospunkt: %d\n", _name.c_str(), _pospunkt);
+    if (_pospunkt > -1)
+    {
+        _digit = _name.substr(0, _pospunkt);
+        _roi = _name.substr(_pospunkt+1, _name.length() - _pospunkt - 1);
+    }
+    else
+    {
+        _digit = "default";
+        _roi = _name;
+    }
+
+    digit *_ret = NULL;
+
+    for (int i = 0; i < DIGIT.size(); ++i)
+    {
+        if (DIGIT[i]->name == _digit)
+            _ret = DIGIT[i];
+    }
+
+    if (!_create)         // nicht gefunden und soll auch nicht erzeugt werden, ggf. geht eine NULL zurück
+        return _ret;
+
+    if (_ret == NULL)
+    {
+        _ret = new digit;
+        _ret->name = _digit;
+        DIGIT.push_back(_ret);
+    }
+
+    roi* neuroi = new roi;
+    neuroi->name = _roi;
+    _ret->ROI.push_back(neuroi);
+
+    printf("GetDIGIT - digit %s - roi %s\n", _digit.c_str(), _roi.c_str());
+
+    return _ret;
+}
+
+
+
 string ClassFlowDigit::getHTMLSingleStep(string host)
 string ClassFlowDigit::getHTMLSingleStep(string host)
 {
 {
     string result, zw;
     string result, zw;
@@ -216,17 +267,32 @@ bool ClassFlowDigit::doAlignAndCut(string time)
 
 
     CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
     CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage();
 
 
-    for (int i = 0; i < ROI.size(); ++i)
+    for (int _dig = 0; _dig < DIGIT.size(); ++_dig)
     {
     {
-        printf("DigitalDigit %d - Align&Cut\n", i);
-        
-        caic->CutAndSave(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, ROI[i]->image_org);
-        if (SaveAllFiles) ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".jpg"));
-
-        ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image);
-        if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp"));
+        printf("DIGIT[_dig]->ROI.size() %d\n", DIGIT[_dig]->ROI.size());
+        for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i)
+        {
+            printf("DigitalDigit %d - Align&Cut\n", i);
+            
+            caic->CutAndSave(DIGIT[_dig]->ROI[i]->posx, DIGIT[_dig]->ROI[i]->posy, DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, DIGIT[_dig]->ROI[i]->image_org);
+            if (SaveAllFiles)
+            {
+                if (DIGIT[_dig]->name == "default")
+                    DIGIT[_dig]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".jpg"));
+                else
+                    DIGIT[_dig]->ROI[i]->image_org->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".jpg"));
+            } 
+
+            DIGIT[_dig]->ROI[i]->image_org->Resize(modelxsize, modelysize, DIGIT[_dig]->ROI[i]->image);
+            if (SaveAllFiles)
+            {
+                if (DIGIT[_dig]->name == "default")
+                    DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".bmp"));
+                else
+                    DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp"));
+            } 
+        }
     }
     }
-
     return true;
     return true;
 } 
 } 
 
 
@@ -241,26 +307,32 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
     CTfLiteClass *tflite = new CTfLiteClass;  
     CTfLiteClass *tflite = new CTfLiteClass;  
     string zwcnn =  FormatFileName("/sdcard" + cnnmodelfile);
     string zwcnn =  FormatFileName("/sdcard" + cnnmodelfile);
     printf(zwcnn.c_str());printf("\n");
     printf(zwcnn.c_str());printf("\n");
-    tflite->LoadModel(zwcnn); 
+    if (!tflite->LoadModel(zwcnn)) {
+        printf("Can't read model file /sdcard%s\n", cnnmodelfile.c_str());
+        delete tflite;
+        return false;
+    } 
+
     tflite->MakeAllocate();
     tflite->MakeAllocate();
 #endif
 #endif
 
 
-    for (int i = 0; i < ROI.size(); ++i)
-    {
-        printf("DigitalDigit %d - TfLite\n", i);
+    for (int _dig = 0; _dig < DIGIT.size(); ++_dig)
+        for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i)
+        {
+            printf("DigitalDigit %d - TfLite\n", i);
 
 
-        ROI[i]->resultklasse = 0;
-#ifndef OHNETFLITE
-        ROI[i]->resultklasse = tflite->GetClassFromImageBasis(ROI[i]->image);
+            DIGIT[_dig]->ROI[i]->resultklasse = 0;
+    #ifndef OHNETFLITE
+            DIGIT[_dig]->ROI[i]->resultklasse = tflite->GetClassFromImageBasis(DIGIT[_dig]->ROI[i]->image);
 
 
-#endif
-        printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse);
+    #endif
+            printf("Result Digit%i: %d\n", i, DIGIT[_dig]->ROI[i]->resultklasse);
 
 
-        if (isLogImage)
-        {
-            LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time, ROI[i]->image_org);
+            if (isLogImage)
+            {
+                LogImage(logPath, DIGIT[_dig]->ROI[i]->name, NULL, &DIGIT[_dig]->ROI[i]->resultklasse, time, DIGIT[_dig]->ROI[i]->image_org);
+            }
         }
         }
-    }
 #ifndef OHNETFLITE
 #ifndef OHNETFLITE
         delete tflite;
         delete tflite;
 #endif
 #endif
@@ -269,25 +341,82 @@ bool ClassFlowDigit::doNeuralNetwork(string time)
 
 
 void ClassFlowDigit::DrawROI(CImageBasis *_zw)
 void ClassFlowDigit::DrawROI(CImageBasis *_zw)
 {
 {
-    for (int i = 0; i < ROI.size(); ++i)
-        _zw->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2);
+    for (int _dig = 0; _dig < DIGIT.size(); ++_dig)
+        for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i)
+            _zw->drawRect(DIGIT[_dig]->ROI[i]->posx, DIGIT[_dig]->ROI[i]->posy, DIGIT[_dig]->ROI[i]->deltax, DIGIT[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2);
 }     
 }     
 
 
 std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
 std::vector<HTMLInfo*> ClassFlowDigit::GetHTMLInfo()
 {
 {
     std::vector<HTMLInfo*> result;
     std::vector<HTMLInfo*> result;
 
 
-    for (int i = 0; i < ROI.size(); ++i)
-    {
-        HTMLInfo *zw = new HTMLInfo;
-        zw->filename = ROI[i]->name + ".bmp";
-        zw->filename_org = ROI[i]->name + ".jpg";
-        zw->val = ROI[i]->resultklasse;
-        zw->image = ROI[i]->image;
-        zw->image_org = ROI[i]->image_org;
-        result.push_back(zw);
-    }
+    for (int _dig = 0; _dig < DIGIT.size(); ++_dig)
+        for (int i = 0; i < DIGIT[_dig]->ROI.size(); ++i)
+        {
+                if (DIGIT[_dig]->name == "default")
+                    DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->ROI[i]->name + ".bmp"));
+                else
+                    DIGIT[_dig]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp"));
+
+
+            HTMLInfo *zw = new HTMLInfo;
+            if (DIGIT[_dig]->name == "default")
+            {
+                zw->filename = DIGIT[_dig]->ROI[i]->name + ".bmp";
+                zw->filename_org = DIGIT[_dig]->ROI[i]->name + ".jpg";
+            }
+            else
+            {
+                zw->filename = DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".bmp";
+                zw->filename_org = DIGIT[_dig]->name + "_" + DIGIT[_dig]->ROI[i]->name + ".jpg";
+            }
+
+            zw->val = DIGIT[_dig]->ROI[i]->resultklasse;
+            zw->image = DIGIT[_dig]->ROI[i]->image;
+            zw->image_org = DIGIT[_dig]->ROI[i]->image_org;
+            result.push_back(zw);
+        }
 
 
     return result;
     return result;
 }
 }
 
 
+int ClassFlowDigit::getAnzahlDIGIT()
+{
+    return DIGIT.size();
+}
+
+string ClassFlowDigit::getNameDIGIT(int _digit)
+{
+    if (_digit < DIGIT.size())
+        return DIGIT[_digit]->name;
+
+    return "DIGIT DOES NOT EXIST";
+}
+
+digit* ClassFlowDigit::GetDIGIT(int _digit)
+{
+    if (_digit < DIGIT.size())
+        return DIGIT[_digit];
+
+    return NULL;
+}
+
+void ClassFlowDigit::UpdateNameNumbers(std::vector<std::string> *_name_numbers)
+{
+    for (int _dig = 0; _dig < DIGIT.size(); _dig++)
+    {
+        std::string _name = DIGIT[_dig]->name;
+        bool found = false;
+        for (int i = 0; i < (*_name_numbers).size(); ++i)
+        {
+            if ((*_name_numbers)[i] == _name)
+                found = true;
+        }
+        if (!found)
+            (*_name_numbers).push_back(_name);
+    }
+}
+
+
+
+

+ 20 - 2
code/components/jomjol_flowcontroll/ClassFlowDigit.h

@@ -5,6 +5,8 @@
 
 
 #include <string>
 #include <string>
 
 
+
+
 struct roi {
 struct roi {
     int posx, posy, deltax, deltay;
     int posx, posy, deltax, deltay;
     int resultklasse;
     int resultklasse;
@@ -13,11 +15,17 @@ struct roi {
     roi* next;
     roi* next;
 };
 };
 
 
+struct digit {
+    string name;
+    std::vector<roi*> ROI;
+};
+
 class ClassFlowDigit :
 class ClassFlowDigit :
     public ClassFlowImage
     public ClassFlowImage
 {
 {
 protected:
 protected:
-    std::vector<roi*> ROI;
+//    std::vector<roi*> ROI;
+    std::vector<digit*> DIGIT;
     string cnnmodelfile;
     string cnnmodelfile;
     int modelxsize, modelysize;
     int modelxsize, modelysize;
     bool SaveAllFiles;
     bool SaveAllFiles;
@@ -31,6 +39,7 @@ protected:
     bool doNeuralNetwork(string time); 
     bool doNeuralNetwork(string time); 
     bool doAlignAndCut(string time); 
     bool doAlignAndCut(string time); 
 
 
+
 	void SetInitialParameter(void);    
 	void SetInitialParameter(void);    
 
 
 public:
 public:
@@ -40,9 +49,18 @@ public:
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     bool doFlow(string time);
     string getHTMLSingleStep(string host); 
     string getHTMLSingleStep(string host); 
-    string getReadout();
+    string getReadout(int _digit);
    	std::vector<HTMLInfo*> GetHTMLInfo();
    	std::vector<HTMLInfo*> GetHTMLInfo();
 
 
+    int getAnzahlDIGIT();
+    digit* GetDIGIT(int _digit);
+    digit* GetDIGIT(string _name, bool _create);
+    digit* FindDIGIT(string _name_number);
+
+    string getNameDIGIT(int _digit);
+
+    void UpdateNameNumbers(std::vector<std::string> *_name_numbers);
+
     void DrawROI(CImageBasis *_zw);        
     void DrawROI(CImageBasis *_zw);        
 
 
     string name(){return "ClassFlowDigit";};
     string name(){return "ClassFlowDigit";};

+ 72 - 40
code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp

@@ -1,6 +1,8 @@
+#include <sstream>
 #include "ClassFlowMQTT.h"
 #include "ClassFlowMQTT.h"
 #include "Helper.h"
 #include "Helper.h"
 
 
+#include "time_sntp.h"
 #include "interface_mqtt.h"
 #include "interface_mqtt.h"
 #include "ClassFlowPostProcessing.h"
 #include "ClassFlowPostProcessing.h"
 
 
@@ -13,6 +15,11 @@ void ClassFlowMQTT::SetInitialParameter(void)
     topicError = "";
     topicError = "";
     topicRate = "";
     topicRate = "";
     topicTimeStamp = "";
     topicTimeStamp = "";
+    maintopic = "";
+    mainerrortopic = ""; 
+
+    topicUptime = "";
+    topicFreeMem = "";
     clientname = "watermeter";
     clientname = "watermeter";
     OldValue = "";
     OldValue = "";
     flowpostprocessing = NULL;  
     flowpostprocessing = NULL;  
@@ -21,6 +28,9 @@ void ClassFlowMQTT::SetInitialParameter(void)
     previousElement = NULL;
     previousElement = NULL;
     ListFlowControll = NULL; 
     ListFlowControll = NULL; 
     disabled = false;
     disabled = false;
+    MQTTenable = false;
+    
+    
 
 
 }       
 }       
 
 
@@ -88,33 +98,24 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
         {
         {
             this->uri = zerlegt[1];
             this->uri = zerlegt[1];
         }
         }
-        if ((toUpper(zerlegt[0]) == "TOPIC") && (zerlegt.size() > 1))
-        {
-            this->topic = zerlegt[1];
-        }
-        if ((toUpper(zerlegt[0]) == "TOPICERROR") && (zerlegt.size() > 1))
-        {
-            this->topicError = zerlegt[1];
-        }
-        if ((toUpper(zerlegt[0]) == "TOPICRATE") && (zerlegt.size() > 1))
-        {
-            this->topicRate  = zerlegt[1];
-        }
-        if ((toUpper(zerlegt[0]) == "TOPICTIMESTAMP") && (zerlegt.size() > 1))
-        {
-            this->topicTimeStamp  = zerlegt[1];
-        }
 
 
         if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
         if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
         {
         {
             this->clientname = zerlegt[1];
             this->clientname = zerlegt[1];
         }
         }
 
 
+        if (((toUpper(zerlegt[0]) == "TOPIC") || (toUpper(zerlegt[0]) == "MAINTOPIC")) && (zerlegt.size() > 1))
+        {
+            maintopic = zerlegt[1];
+        }
     }
     }
 
 
-    if ((uri.length() > 0) && (topic.length() > 0)) 
+    if (!MQTTisConnected() && (uri.length() > 0) && (maintopic.length() > 0)) 
     {
     {
-        MQTTInit(uri, clientname, user, password, topicError, 60);
+        mainerrortopic = maintopic + "/connection";
+        MQTTInit(uri, clientname, user, password, mainerrortopic, 60); 
+        MQTTPublish(mainerrortopic, "connected");
+        MQTTenable = true;
     }
     }
    
    
     return true;
     return true;
@@ -123,18 +124,66 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
 
 
 bool ClassFlowMQTT::doFlow(string zwtime)
 bool ClassFlowMQTT::doFlow(string zwtime)
 {
 {
+    if (!MQTTenable)
+        return true;
+
     std::string result;
     std::string result;
     std::string resulterror = "";
     std::string resulterror = "";
     std::string resultrate = "";
     std::string resultrate = "";
     std::string resulttimestamp = "";
     std::string resulttimestamp = "";
     string zw = "";
     string zw = "";
+    string namenumber = "";
+
+    MQTTPublish(mainerrortopic, "connected");
     
     
+    zw = maintopic + "/" + "uptime";
+    char uptimeStr[11];
+    sprintf(uptimeStr, "%ld", (long)getUpTime());
+    MQTTPublish(zw, uptimeStr);
+
+    zw = maintopic + "/" + "freeMem";
+    char freeheapmem[11];
+    sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
+    MQTTPublish(zw, freeheapmem);
+
     if (flowpostprocessing)
     if (flowpostprocessing)
     {
     {
-        result =  flowpostprocessing->getReadoutParam(false, true);
-        resulterror = flowpostprocessing->getReadoutError();
-        resultrate = flowpostprocessing->getReadoutRate();
-        resulttimestamp = flowpostprocessing->getReadoutTimeStamp();
+        std::vector<NumberPost*> NUMBERS = flowpostprocessing->GetNumbers();
+
+        for (int i = 0; i < NUMBERS.size(); ++i)
+        {
+            result =  NUMBERS[i]->ReturnValueNoError;
+            resulterror = NUMBERS[i]->ErrorMessageText;
+            resultrate = std::to_string(NUMBERS[i]->FlowRateAct);
+            resulttimestamp = NUMBERS[i]->timeStamp;
+
+            namenumber = NUMBERS[i]->name;
+            if (namenumber == "default")
+                namenumber = maintopic + "/";
+            else
+                namenumber = maintopic + "/" + namenumber + "/";
+
+            zw = namenumber + "value";    
+            MQTTPublish(zw, result);
+
+            zw = namenumber + "error";    
+            MQTTPublish(zw, resulterror, 1);
+
+            zw = namenumber + "rate";    
+            MQTTPublish(zw, resultrate);
+
+            zw = namenumber + "timestamp";
+            MQTTPublish(zw, resulttimestamp);
+
+
+            std::string json="{\"value\":"+result;
+            json += ",\"error\":\""+resulterror;
+            json += "\",\"rate\":"+resultrate;
+            json += ",\"timestamp\":\""+resulttimestamp+"\"}";
+
+            zw = namenumber + "json";
+            MQTTPublish(zw, json);
+        }
     }
     }
     else
     else
     {
     {
@@ -149,26 +198,9 @@ bool ClassFlowMQTT::doFlow(string zwtime)
                     result = result + "\t" + zw;
                     result = result + "\t" + zw;
             }
             }
         }
         }
+        MQTTPublish(topic, result);
     }
     }
     
     
-    MQTTPublish(topic, result);
-
-    if (topicError.length() > 0) {
-        if (resulterror.length() == 0)
-        {
-            resulterror = " ";
-        }
-        MQTTPublish(topicError, resulterror, 1);
-    }
-
-    if (topicRate.length() > 0) {
-        MQTTPublish(topicRate, resultrate);
-    }
-
-    if (topicTimeStamp.length() > 0) {
-        MQTTPublish(topicTimeStamp, resulttimestamp);
-    }
-
     OldValue = result;
     OldValue = result;
     
     
     return true;
     return true;

+ 5 - 2
code/components/jomjol_flowcontroll/ClassFlowMQTT.h

@@ -9,10 +9,13 @@ class ClassFlowMQTT :
     public ClassFlow
     public ClassFlow
 {
 {
 protected:
 protected:
-    std::string uri, topic, topicError, clientname, topicRate, topicTimeStamp;
+    std::string uri, topic, topicError, clientname, topicRate, topicTimeStamp, topicUptime, topicFreeMem;
     std::string OldValue;
     std::string OldValue;
 	ClassFlowPostProcessing* flowpostprocessing;  
 	ClassFlowPostProcessing* flowpostprocessing;  
-    std::string user, password;  
+    std::string user, password; 
+    bool MQTTenable;
+
+    std::string maintopic, mainerrortopic; 
 	void SetInitialParameter(void);        
 	void SetInitialParameter(void);        
 
 
 public:
 public:

+ 435 - 244
code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp

@@ -1,8 +1,6 @@
 #include "ClassFlowPostProcessing.h"
 #include "ClassFlowPostProcessing.h"
 
 
 #include "Helper.h"
 #include "Helper.h"
-#include "ClassFlowAnalog.h"
-#include "ClassFlowDigit.h"
 #include "ClassFlowMakeImage.h"
 #include "ClassFlowMakeImage.h"
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 
 
@@ -18,130 +16,205 @@
 #define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
 #define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
 
 
 
 
-string ClassFlowPostProcessing::GetPreValue()
+string ClassFlowPostProcessing::GetPreValue(std::string _number)
 {
 {
     std::string result;
     std::string result;
-    bool isAnalog = false;
-    bool isDigit = false;
+    int index = -1;
 
 
-    int AnzahlAnalog = 0;
-    result = RundeOutput(PreValue, -DecimalShift);
+    if (_number == "")
+        _number = "default";
 
 
-    for (int i = 0; i < ListFlowControll->size(); ++i)
-    {
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
-        {
-            isAnalog = true;
-            AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs();
-        }
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0)
-        {
-            isDigit = true;
-        }
-    }
+    for (int i = 0; i < NUMBERS.size(); ++i)
+        if (NUMBERS[i]->name == _number)
+            index = i;
 
 
-    if (isDigit && isAnalog)
-        result = RundeOutput(PreValue, AnzahlAnalog - DecimalShift);
+//    result = RundeOutput(NUMBERS[index]->PreValue, -NUMBERS[index]->DecimalShift);
+    result = RundeOutput(NUMBERS[index]->PreValue, NUMBERS[index]->Nachkomma);
+
+//    if (NUMBERS[index]->digit_roi && NUMBERS[index]->analog_roi)
+//        result = RundeOutput(NUMBERS[index]->PreValue, NUMBERS[index]->AnzahlAnalog - NUMBERS[index]->DecimalShift);
 
 
     return result;
     return result;
 }
 }
 
 
+void ClassFlowPostProcessing::SetPreValue(float zw, string _numbers)
+{
+    for (int j = 0; j < NUMBERS.size(); ++j)
+    {
+        if (NUMBERS[j]->name == _numbers)
+            NUMBERS[j]->PreValue = zw;
+    }
+    UpdatePreValueINI = true;
+    SavePreValue();
+}
+
+
 bool ClassFlowPostProcessing::LoadPreValue(void)
 bool ClassFlowPostProcessing::LoadPreValue(void)
 {
 {
+    std::vector<string> zerlegt;
     FILE* pFile;
     FILE* pFile;
     char zw[1024];
     char zw[1024];
-    string zwtime, zwvalue;
+    string zwtime, zwvalue, name;
+    bool _done = false;
+
+    UpdatePreValueINI = false;       // Konvertierung ins neue Format
+
 
 
     pFile = fopen(FilePreValue.c_str(), "r");
     pFile = fopen(FilePreValue.c_str(), "r");
     if (pFile == NULL)
     if (pFile == NULL)
         return false;
         return false;
 
 
     fgets(zw, 1024, pFile);
     fgets(zw, 1024, pFile);
-    printf("%s", zw);
+    printf("Read Zeile Prevalue.ini: %s", zw);
     zwtime = trim(std::string(zw));
     zwtime = trim(std::string(zw));
-
-    fgets(zw, 1024, pFile);
-    fclose(pFile);
-    printf("%s", zw);
-    zwvalue = trim(std::string(zw));
-    PreValue = stof(zwvalue.c_str());
-
-    time_t tStart;
-    int yy, month, dd, hh, mm, ss;
-    struct tm whenStart;
-
-    sscanf(zwtime.c_str(), PREVALUE_TIME_FORMAT_INPUT, &yy, &month, &dd, &hh, &mm, &ss);
-    whenStart.tm_year = yy - 1900;
-    whenStart.tm_mon = month - 1;
-    whenStart.tm_mday = dd;
-    whenStart.tm_hour = hh;
-    whenStart.tm_min = mm;
-    whenStart.tm_sec = ss;
-    whenStart.tm_isdst = -1;
-
-    lastvalue = mktime(&whenStart);
-
-    time(&tStart);
-    localtime(&tStart);
-    double difference = difftime(tStart, lastvalue);
-    difference /= 60;
-    if (difference > PreValueAgeStartup)
+    if (zwtime.length() == 0)
         return false;
         return false;
 
 
-    Value = PreValue;
-    ReturnValue = to_string(Value);
-    ReturnValueNoError = ReturnValue; 
+    zerlegt = HelperZerlegeZeile(zwtime, "\t");
+    if (zerlegt.size() > 1)     // neues Format
+    {
+        while ((zerlegt.size() > 1) && !_done)
+        {
+            name = trim(zerlegt[0]);
+            zwtime = trim(zerlegt[1]);
+            zwvalue = trim(zerlegt[2]);
 
 
-    bool isAnalog = false;
-    bool isDigit = false;
-    int AnzahlAnalog = 0;
+            for (int j = 0; j < NUMBERS.size(); ++j)
+            {
+                if (NUMBERS[j]->name == name)
+                {
+                    NUMBERS[j]->PreValue = stof(zwvalue.c_str());
+                    NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
+
+                    time_t tStart;
+                    int yy, month, dd, hh, mm, ss;
+                    struct tm whenStart;
+
+                    sscanf(zwtime.c_str(), PREVALUE_TIME_FORMAT_INPUT, &yy, &month, &dd, &hh, &mm, &ss);
+                    whenStart.tm_year = yy - 1900;
+                    whenStart.tm_mon = month - 1;
+                    whenStart.tm_mday = dd;
+                    whenStart.tm_hour = hh;
+                    whenStart.tm_min = mm;
+                    whenStart.tm_sec = ss;
+                    whenStart.tm_isdst = -1;
+
+                    NUMBERS[j]->lastvalue = mktime(&whenStart);
+
+                    time(&tStart);
+                    localtime(&tStart);
+                    double difference = difftime(tStart, NUMBERS[j]->lastvalue);
+                    difference /= 60;
+                    if (difference > PreValueAgeStartup)
+                    {
+                        NUMBERS[j]->PreValueOkay = false;
+                    }
+                    else
+                    {
+                        NUMBERS[j]->PreValueOkay = true;
+                        NUMBERS[j]->Value = NUMBERS[j]->PreValue;
+                        NUMBERS[j]->ReturnValue = to_string(NUMBERS[j]->Value);
+                        NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue; 
+
+                        if (NUMBERS[j]->digit_roi || NUMBERS[j]->analog_roi)
+                        {
+                            NUMBERS[j]->ReturnValue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift);
+                            NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue;
+                        }
+                    }
+
+                }
+            }
 
 
-    for (int i = 0; i < ListFlowControll->size(); ++i)
+            if (!fgets(zw, 1024, pFile))
+                _done = true;
+            else
+            {
+                printf("Read Zeile Prevalue.ini: %s", zw);
+                zerlegt = HelperZerlegeZeile(trim(std::string(zw)), "\t");
+                if (zerlegt.size() > 1)
+                {
+                    name = trim(zerlegt[0]);
+                    zwtime = trim(zerlegt[1]);
+                    zwvalue = trim(zerlegt[2]);
+                }
+            }
+        }
+        fclose(pFile);
+    }   
+    else        // altes Format
     {
     {
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
-            isAnalog = true;
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0)
-            isDigit = true;
-    }
+        fgets(zw, 1024, pFile);
+        fclose(pFile);
+        printf("%s", zw);
+        zwvalue = trim(std::string(zw));
+        NUMBERS[0]->PreValue = stof(zwvalue.c_str());
+
+        time_t tStart;
+        int yy, month, dd, hh, mm, ss;
+        struct tm whenStart;
+
+        sscanf(zwtime.c_str(), PREVALUE_TIME_FORMAT_INPUT, &yy, &month, &dd, &hh, &mm, &ss);
+        whenStart.tm_year = yy - 1900;
+        whenStart.tm_mon = month - 1;
+        whenStart.tm_mday = dd;
+        whenStart.tm_hour = hh;
+        whenStart.tm_min = mm;
+        whenStart.tm_sec = ss;
+        whenStart.tm_isdst = -1;
+
+        printf("TIME: %d, %d, %d, %d, %d, %d\n", whenStart.tm_year, whenStart.tm_mon, whenStart.tm_wday, whenStart.tm_hour, whenStart.tm_min, whenStart.tm_sec);
+
+        NUMBERS[0]->lastvalue = mktime(&whenStart);
+
+        time(&tStart);
+        localtime(&tStart);
+        double difference = difftime(tStart, NUMBERS[0]->lastvalue);
+        difference /= 60;
+        if (difference > PreValueAgeStartup)
+            return false;
+
+        NUMBERS[0]->Value = NUMBERS[0]->PreValue;
+        NUMBERS[0]->ReturnValue = to_string(NUMBERS[0]->Value);
+        NUMBERS[0]->ReturnValueNoError = NUMBERS[0]->ReturnValue; 
+
+        if (NUMBERS[0]->digit_roi || NUMBERS[0]->analog_roi)
+        {
+            NUMBERS[0]->ReturnValue = RundeOutput(NUMBERS[0]->Value, NUMBERS[0]->AnzahlAnalog - NUMBERS[0]->DecimalShift);
+            NUMBERS[0]->ReturnValueNoError = NUMBERS[0]->ReturnValue;
+        }
+
+        UpdatePreValueINI = true;       // Konvertierung ins neue Format
+        SavePreValue();
+    } 
 
 
-    if (isDigit || isAnalog)
-    {
-        ReturnValue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
-        ReturnValueNoError = ReturnValue;
-    }
-   
     return true;
     return true;
 }
 }
 
 
-void ClassFlowPostProcessing::SavePreValue(float value, string zwtime)
+void ClassFlowPostProcessing::SavePreValue()
 {
 {
     FILE* pFile;
     FILE* pFile;
+    string _zw;
+
+    if (!UpdatePreValueINI)         // PreValues unverändert --> File muss nicht neu geschrieben werden
+        return;
 
 
     pFile = fopen(FilePreValue.c_str(), "w");
     pFile = fopen(FilePreValue.c_str(), "w");
 
 
-    if (strlen(zwtime.c_str()) == 0)
+    for (int j = 0; j < NUMBERS.size(); ++j)
     {
     {
-        time_t rawtime;
-        struct tm* timeinfo;
         char buffer[80];
         char buffer[80];
+        struct tm* timeinfo = localtime(&NUMBERS[j]->lastvalue);
+        strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo);
+        NUMBERS[j]->timeStamp = std::string(buffer);
 
 
-        time(&rawtime);
-        timeinfo = localtime(&rawtime);
+        _zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + to_string(NUMBERS[j]->PreValue) + "\n";
+        printf("Write PreValue Zeile: %s\n", _zw.c_str());
 
 
-        strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo);
-        timeStamp = std::string(buffer);
-    }
-    else
-    {
-        timeStamp = zwtime;
+        fputs(_zw.c_str(), pFile);
     }
     }
 
 
-    PreValue = value;
-
-    fputs(timeStamp.c_str(), pFile);
-    fputs("\n", pFile);
-    fputs(to_string(value).c_str(), pFile);
-    fputs("\n", pFile);
+    UpdatePreValueINI = false;
 
 
     fclose(pFile);
     fclose(pFile);
 }
 }
@@ -149,22 +222,19 @@ void ClassFlowPostProcessing::SavePreValue(float value, string zwtime)
 
 
 ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc)
 ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc)
 {
 {
-    FlowRateAct = 0;
+//    FlowRateAct = 0;
     PreValueUse = false;
     PreValueUse = false;
     PreValueAgeStartup = 30;
     PreValueAgeStartup = 30;
-    AllowNegativeRates = false;
-    MaxRateValue = 0.1;
     ErrorMessage = false;
     ErrorMessage = false;
     ListFlowControll = NULL;
     ListFlowControll = NULL;
-    PreValueOkay = false;
-    useMaxRateValue = false;
-    checkDigitIncreaseConsistency = false;
-    DecimalShift = 0;    
-    ErrorMessageText = "";
-    timeStamp = "";
+//    PreValueOkay = false;
+//    DecimalShift = 0;    
+//    ErrorMessageText = "";
+//    timeStamp = "";
     FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
     FilePreValue = FormatFileName("/sdcard/config/prevalue.ini");
     ListFlowControll = lfc;
     ListFlowControll = lfc;
     flowMakeImage = NULL;
     flowMakeImage = NULL;
+    UpdatePreValueINI = false;
 
 
     for (int i = 0; i < ListFlowControll->size(); ++i)
     for (int i = 0; i < ListFlowControll->size(); ++i)
     {
     {
@@ -175,10 +245,82 @@ ClassFlowPostProcessing::ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc)
     }
     }
 }
 }
 
 
+void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _value)
+{
+    string _digit, _decpos;
+    int _pospunkt = _decsep.find_first_of(".");
+//    printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
+    if (_pospunkt > -1)
+        _digit = _decsep.substr(0, _pospunkt);
+    else
+        _digit = "default";
+
+    for (int j = 0; j < NUMBERS.size(); ++j)
+    {
+        int _zwdc = 0;
+
+        try
+        {
+            _zwdc = stoi(_value);
+        }
+        catch(const std::exception& e)
+        {
+            printf("ERROR - Decimalshift is not a number: %s\n", _value.c_str());
+        }
+        
+        if (_digit == "default")                        // erstmal auf default setzen (falls sonst nichts gesetzt)
+            NUMBERS[j]->DecimalShift = _zwdc;
+
+        if (NUMBERS[j]->name == _digit)
+            NUMBERS[j]->DecimalShift = _zwdc;
+
+        NUMBERS[j]->Nachkomma = NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift;
+    }
+}
+
+void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
+{
+    string _digit, _decpos;
+    int _pospunkt = _decsep.find_first_of(".");
+//    printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
+    if (_pospunkt > -1)
+        _digit = _decsep.substr(0, _pospunkt);
+    else
+        _digit = "default";
+
+    for (int j = 0; j < NUMBERS.size(); ++j)
+    {
+        float _zwdc = 1;
+
+        try
+        {
+            _zwdc = stof(_value);
+        }
+        catch(const std::exception& e)
+        {
+            printf("ERROR - MaxRateValue is not a number: %s\n", _value.c_str());
+        }
+
+
+        if (_digit == "default")                        // erstmal auf default setzen (falls sonst nichts gesetzt)
+        {
+            NUMBERS[j]->useMaxRateValue = true;
+            NUMBERS[j]->MaxRateValue = _zwdc;
+        }
+
+        if (NUMBERS[j]->name == _digit)
+        {
+            NUMBERS[j]->useMaxRateValue = true;
+            NUMBERS[j]->MaxRateValue = _zwdc;
+        }
+    }
+}
+
 
 
 bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
 bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
 {
 {
     std::vector<string> zerlegt;
     std::vector<string> zerlegt;
+    int _n;
 
 
     aktparamgraph = trim(aktparamgraph);
     aktparamgraph = trim(aktparamgraph);
 
 
@@ -190,53 +332,148 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
     if (aktparamgraph.compare("[PostProcessing]") != 0)       // Paragraph passt nich zu MakeImage
     if (aktparamgraph.compare("[PostProcessing]") != 0)       // Paragraph passt nich zu MakeImage
         return false;
         return false;
 
 
+    InitNUMBERS();
+
+
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
     {
     {
         zerlegt = this->ZerlegeZeile(aktparamgraph);
         zerlegt = this->ZerlegeZeile(aktparamgraph);
-        if ((toUpper(zerlegt[0]) == "DECIMALSHIFT") && (zerlegt.size() > 1))
+        std::string _param = GetParameterName(zerlegt[0]);
+
+        if ((toUpper(_param) == "DECIMALSHIFT") && (zerlegt.size() > 1))
+        {
+            handleDecimalSeparator(zerlegt[0], zerlegt[1]);
+        }
+        if ((toUpper(_param) == "MAXRATEVALUE") && (zerlegt.size() > 1))
         {
         {
-            DecimalShift = stoi(zerlegt[1]);
+            handleMaxRateValue(zerlegt[0], zerlegt[1]);
         }
         }
 
 
-        if ((toUpper(zerlegt[0]) == "PREVALUEUSE") && (zerlegt.size() > 1))
+        if ((toUpper(_param) == "PREVALUEUSE") && (zerlegt.size() > 1))
         {
         {
             if (toUpper(zerlegt[1]) == "TRUE")
             if (toUpper(zerlegt[1]) == "TRUE")
             {
             {
                 PreValueUse = true;
                 PreValueUse = true;
             }
             }
         }
         }
-        if ((toUpper(zerlegt[0]) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1))
+        if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1))
         {
         {
             if (toUpper(zerlegt[1]) == "TRUE")
             if (toUpper(zerlegt[1]) == "TRUE")
-                checkDigitIncreaseConsistency = true;
+                for (_n = 0; _n < NUMBERS.size(); ++_n)
+                    NUMBERS[_n]->checkDigitIncreaseConsistency = true;
         }        
         }        
-        if ((toUpper(zerlegt[0]) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1))
+        if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1))
         {
         {
             if (toUpper(zerlegt[1]) == "TRUE")
             if (toUpper(zerlegt[1]) == "TRUE")
-                AllowNegativeRates = true;
+                for (_n = 0; _n < NUMBERS.size(); ++_n)
+                    NUMBERS[_n]->AllowNegativeRates = true;
         }
         }
-        if ((toUpper(zerlegt[0]) == "ERRORMESSAGE") && (zerlegt.size() > 1))
+        if ((toUpper(_param) == "ERRORMESSAGE") && (zerlegt.size() > 1))
         {
         {
             if (toUpper(zerlegt[1]) == "TRUE")
             if (toUpper(zerlegt[1]) == "TRUE")
                 ErrorMessage = true;
                 ErrorMessage = true;
         }
         }
-        if ((toUpper(zerlegt[0]) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1))
+        if ((toUpper(_param) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1))
         {
         {
             PreValueAgeStartup = std::stoi(zerlegt[1]);
             PreValueAgeStartup = std::stoi(zerlegt[1]);
         }
         }
-        if ((toUpper(zerlegt[0]) == "MAXRATEVALUE") && (zerlegt.size() > 1))
-        {
-            useMaxRateValue = true;
-            MaxRateValue = std::stof(zerlegt[1]);
-        }
     }
     }
 
 
     if (PreValueUse) {
     if (PreValueUse) {
-        PreValueOkay = LoadPreValue();
+        LoadPreValue();
     }
     }
+
     return true;
     return true;
 }
 }
 
 
+void ClassFlowPostProcessing::InitNUMBERS()
+{
+//    ClassFlowDigit* _cdigit = NULL;
+//    ClassFlowAnalog* _canalog = NULL;
+    int anzDIGIT = 0;
+    int anzANALOG = 0;
+    std::vector<std::string> name_numbers;
+
+    flowAnalog = NULL;
+    flowDigit = NULL;
+
+    for (int i = 0; i < ListFlowControll->size(); ++i)
+    {
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0)
+        {
+            flowDigit = (ClassFlowDigit*) (*ListFlowControll)[i];
+            anzDIGIT = flowDigit->getAnzahlDIGIT();
+        }
+        if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
+        {
+            flowAnalog = (ClassFlowAnalog*)(*ListFlowControll)[i];
+            anzANALOG = flowAnalog->getAnzahlANALOG();
+        }
+    }
+
+    if (flowDigit)
+        flowDigit->UpdateNameNumbers(&name_numbers);
+    if (flowAnalog)
+        flowAnalog->UpdateNameNumbers(&name_numbers);
+
+    printf("Anzahl NUMBERS: %d - DIGITS: %d, ANALOG: %d\n", name_numbers.size(), anzDIGIT, anzANALOG);
+
+    for (int _num = 0; _num < name_numbers.size(); ++_num)
+    {
+        NumberPost *_number = new NumberPost;
+
+        _number->name = name_numbers[_num];
+        
+        _number->digit_roi = NULL;
+        if (flowDigit)
+            _number->digit_roi = flowDigit->FindDIGIT(name_numbers[_num]);
+        
+        if (_number->digit_roi)
+            _number->AnzahlDigital = _number->digit_roi->ROI.size();
+        else
+            _number->AnzahlDigital = 0;
+
+        _number->analog_roi = NULL;
+        if (flowAnalog)
+            _number->analog_roi = flowAnalog->FindANALOG(name_numbers[_num]);
+
+
+        if (_number->analog_roi)
+            _number->AnzahlAnalog = _number->analog_roi->ROI.size();
+        else
+            _number->AnzahlAnalog = 0;
+
+        _number->ReturnRawValue = "";      // Rohwert (mit N & führenden 0)    
+        _number->ReturnValue = "";         // korrigierter Rückgabewert, ggf. mit Fehlermeldung
+        _number->ReturnValueNoError = "";  // korrigierter Rückgabewert ohne Fehlermeldung
+        _number->ErrorMessageText = "";        // Fehlermeldung bei Consistency Check
+        _number->ReturnPreValue = "";
+        _number->PreValueOkay = false;
+        _number->AllowNegativeRates = false;
+        _number->MaxRateValue = 0.1;
+        _number->useMaxRateValue = false;
+        _number->checkDigitIncreaseConsistency = false;
+        _number->PreValueOkay = false;
+        _number->useMaxRateValue = false;
+        _number->DecimalShift = 0;
+
+        _number->FlowRateAct = 0;          // m3 / min
+        _number->PreValue = 0;             // letzter Wert, der gut ausgelesen wurde
+        _number->Value = 0;                // letzer ausgelesener Wert, inkl. Korrekturen
+        _number->ReturnRawValue = "";      // Rohwert (mit N & führenden 0)    
+        _number->ReturnValue = "";         // korrigierter Rückgabewert, ggf. mit Fehlermeldung
+        _number->ReturnValueNoError = "";  // korrigierter Rückgabewert ohne Fehlermeldung
+        _number->ErrorMessageText = "";        // Fehlermeldung bei Consistency Check
+
+        _number->Nachkomma = _number->AnzahlAnalog;
+
+        NUMBERS.push_back(_number);
+    }
+
+    for (int i = 0; i < NUMBERS.size(); ++i)
+        printf("Number %s, Anz DIG: %d, Anz ANA %d\n", NUMBERS[i]->name.c_str(), NUMBERS[i]->AnzahlDigital, NUMBERS[i]->AnzahlAnalog);
+}
+
 string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
 string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
 
 
     if (_decShift == 0){
     if (_decShift == 0){
@@ -285,173 +522,127 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
     string digit = "";
     string digit = "";
     string analog = "";
     string analog = "";
     string zwvalue;
     string zwvalue;
-    bool isdigit = false;
-    bool isanalog = false;
-    int AnzahlAnalog = 0;
     string zw;
     string zw;
     time_t imagetime = 0;
     time_t imagetime = 0;
     string rohwert;
     string rohwert;
 
 
-    ErrorMessageText = "";
-
-
-    for (int i = 0; i < ListFlowControll->size(); ++i)
-    {
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0)
-        {
-            imagetime = ((ClassFlowMakeImage*)(*ListFlowControll)[i])->getTimeImageTaken();
-        }
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowDigit") == 0)
-        {
-            isdigit = true;
-            digit = (*ListFlowControll)[i]->getReadout();
-        }
-        if (((*ListFlowControll)[i])->name().compare("ClassFlowAnalog") == 0)
-        {
-            isanalog = true;
-            analog = (*ListFlowControll)[i]->getReadout();
-            AnzahlAnalog = ((ClassFlowAnalog*)(*ListFlowControll)[i])->AnzahlROIs();
-        }
-    }
+//    ErrorMessageText = "";
 
 
+    imagetime = flowMakeImage->getTimeImageTaken();
     if (imagetime == 0)
     if (imagetime == 0)
         time(&imagetime);
         time(&imagetime);
 
 
     struct tm* timeinfo;
     struct tm* timeinfo;
     timeinfo = localtime(&imagetime);
     timeinfo = localtime(&imagetime);
-
     char strftime_buf[64];
     char strftime_buf[64];
     strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo);
     strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo);
     zwtime = std::string(strftime_buf);
     zwtime = std::string(strftime_buf);
 
 
+    printf("Anzahl NUMBERS: %d\n", NUMBERS.size());
 
 
-    //    // TESTING ONLY////////////////////
-    //    isdigit = true; digit = "12N";
-    //    isanalog = true; analog = "456";
-
-    ReturnRawValue = "";
-
-    if (isdigit)
-        ReturnRawValue = digit;
-    if (isdigit && isanalog)
-        ReturnRawValue = ReturnRawValue + ".";
-    if (isanalog)
-        ReturnRawValue = ReturnRawValue + analog; 
-
-
-    if (!isdigit)
+    for (int j = 0; j < NUMBERS.size(); ++j)
     {
     {
-        AnzahlAnalog = 0;
-    }
+        NUMBERS[j]->ReturnRawValue = "";
+        NUMBERS[j]->ErrorMessageText = "";
 
 
-    ReturnRawValue = ShiftDecimal(ReturnRawValue, DecimalShift);   
+        if (NUMBERS[j]->digit_roi)
+            NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j);
+        if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
+            NUMBERS[j]->ReturnRawValue = NUMBERS[j]->ReturnRawValue + ".";
+        if (NUMBERS[j]->analog_roi)
+            NUMBERS[j]->ReturnRawValue = NUMBERS[j]->ReturnRawValue + flowAnalog->getReadout(j); 
 
 
-    rohwert = ReturnRawValue;
+        NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift);   
 
 
-    if (!PreValueUse || !PreValueOkay)
-    {
-        ReturnValue = ReturnRawValue;
-        ReturnValueNoError = ReturnRawValue;
+        rohwert = NUMBERS[j]->ReturnRawValue;
 
 
-        if ((findDelimiterPos(ReturnValue, "N") == std::string::npos) && (ReturnValue.length() > 0))
+        if (!PreValueUse || !NUMBERS[j]->PreValueOkay)
         {
         {
-            while ((ReturnValue.length() > 1) && (ReturnValue[0] == '0'))
-            {
-                ReturnValue.erase(0, 1);
-            }
-            Value = std::stof(ReturnValue);
-            ReturnValueNoError = ReturnValue;
+            NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnRawValue;
+            NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnRawValue;
 
 
-            PreValueOkay = true;
-            PreValue = Value;
-            if (flowMakeImage) 
+            if ((findDelimiterPos(NUMBERS[j]->ReturnValue, "N") == std::string::npos) && (NUMBERS[j]->ReturnValue.length() > 0))
             {
             {
-                lastvalue = flowMakeImage->getTimeImageTaken();
-                zwtime = ConvertTimeToString(lastvalue, PREVALUE_TIME_FORMAT_OUTPUT);
+                while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0'))
+                {
+                    NUMBERS[j]->ReturnValue.erase(0, 1);
+                }
+                NUMBERS[j]->Value = std::stof(NUMBERS[j]->ReturnValue);
+                NUMBERS[j]->ReturnValueNoError = NUMBERS[j]->ReturnValue;
+
+                NUMBERS[j]->PreValueOkay = true;
+                NUMBERS[j]->PreValue = NUMBERS[j]->Value;
+                NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
+                NUMBERS[j]->lastvalue = flowMakeImage->getTimeImageTaken();
+                zwtime = ConvertTimeToString(NUMBERS[j]->lastvalue, PREVALUE_TIME_FORMAT_OUTPUT);
+
+                UpdatePreValueINI = true;
+                SavePreValue();
             }
             }
-            else
-            {
-                time(&lastvalue);
-                localtime(&lastvalue);
-            }
-
-            SavePreValue(Value, zwtime);
         }
         }
-        return true;
-    }
-
+        else
+        {
+            zw = ErsetzteN(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->PreValue); 
 
 
-    zw = ErsetzteN(ReturnRawValue); 
+            NUMBERS[j]->Value = std::stof(zw);
+            if (NUMBERS[j]->checkDigitIncreaseConsistency)
+            {
+                NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
+            }
 
 
-    Value = std::stof(zw);
-    if (checkDigitIncreaseConsistency)
-    {
-        Value = checkDigitConsistency(Value, DecimalShift, isanalog);
-    }
+            zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift);
 
 
-    zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
+            if ((!NUMBERS[j]->AllowNegativeRates) && (NUMBERS[j]->Value < NUMBERS[j]->PreValue))
+            {
+                NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + std::to_string(NUMBERS[j]->Value) + " "; 
+                NUMBERS[j]->Value = NUMBERS[j]->PreValue;
+                zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->AnzahlAnalog - NUMBERS[j]->DecimalShift);
+            }
 
 
-    if ((!AllowNegativeRates) && (Value < PreValue))
-    {
-        ErrorMessageText = ErrorMessageText + "Negative Rate - Returned old value - read value: " + zwvalue + " - raw value: " + ReturnRawValue + " - checked value: " + std::to_string(Value) + " "; 
-        Value = PreValue;
-        zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
-    }
+            if (NUMBERS[j]->useMaxRateValue && (abs(NUMBERS[j]->Value - NUMBERS[j]->PreValue) > NUMBERS[j]->MaxRateValue))
+            {
+                NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
+                NUMBERS[j]->Value = NUMBERS[j]->PreValue;
+                zwvalue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma);
+            }
 
 
-    if (useMaxRateValue && (abs(Value - PreValue) > MaxRateValue))
-    {
-        ErrorMessageText = ErrorMessageText + "Rate too high - Returned old value - read value: " + zwvalue + " - checked value: " + RundeOutput(Value, AnzahlAnalog - DecimalShift) + " ";
-        Value = PreValue;
-        zwvalue = RundeOutput(Value, AnzahlAnalog - DecimalShift);
-    }
+            NUMBERS[j]->ReturnValueNoError = zwvalue;
+            NUMBERS[j]->ReturnValue = zwvalue;
+            if (NUMBERS[j]->ErrorMessage && (NUMBERS[j]->ErrorMessageText.length() > 0))
+                NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnValue + "\t" + NUMBERS[j]->ErrorMessageText;
 
 
 
 
-    ReturnValueNoError = zwvalue;
-    ReturnValue = zwvalue;
-    if (ErrorMessage && (ErrorMessageText.length() > 0))
-        ReturnValue = ReturnValue + "\t" + ErrorMessageText;
+            double difference = difftime(imagetime, NUMBERS[j]->lastvalue);      // in Sekunden
+            difference /= 60;                                          // in Minuten
+            NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference;
+            NUMBERS[j]->lastvalue = imagetime;
 
 
-    time_t currenttime;
-    if (flowMakeImage) 
-    {
-        currenttime = flowMakeImage->getTimeImageTaken();
-        zwtime = ConvertTimeToString(currenttime, PREVALUE_TIME_FORMAT_OUTPUT);
-    }
-    else
-    {
-        time(&currenttime);
-        localtime(&currenttime);
+            if (NUMBERS[j]->ErrorMessageText.length() == 0)
+            {
+                NUMBERS[j]->PreValue = NUMBERS[j]->Value;
+                NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
+                NUMBERS[j]->ErrorMessageText = "no error";
+                UpdatePreValueINI = true;
+            }
+        }
     }
     }
 
 
-    double difference = difftime(currenttime, lastvalue);      // in Sekunden
-    difference /= 60;                                          // in Minuten
-    FlowRateAct = (Value - PreValue) / difference;
-    lastvalue = currenttime;
-//    std::string _zw = "CalcRate: " + std::to_string(FlowRateAct) + " TimeDifference[min]: " +  std::to_string(difference);
-//    _zw = _zw  + " Value: " +  std::to_string(Value) + " PreValue: " +  std::to_string(PreValue);
-//    LogFile.WriteToFile(_zw);
-
-    if (ErrorMessageText.length() == 0)
-    {
-        PreValue = Value;
-        ErrorMessageText = "no error";
-        SavePreValue(Value, zwtime);
-    }
+    SavePreValue();
     return true;
     return true;
 }
 }
 
 
-string ClassFlowPostProcessing::getReadout()
+string ClassFlowPostProcessing::getReadout(int _number)
 {
 {
-    return ReturnValue;
+    return NUMBERS[_number]->ReturnValue;
 }
 }
 
 
-string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror)
+string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror, int _number)
 {
 {
     if (_rawValue)
     if (_rawValue)
-        return ReturnRawValue;
+        return NUMBERS[_number]->ReturnRawValue;
     if (_noerror)
     if (_noerror)
-        return ReturnValueNoError;
-    return ReturnValue;
+        return NUMBERS[_number]->ReturnValueNoError;
+    return NUMBERS[_number]->ReturnValue;
 }
 }
 
 
 string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
 string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
@@ -478,7 +669,7 @@ string ClassFlowPostProcessing::RundeOutput(float _in, int _anzNachkomma){
 }
 }
 
 
 
 
-string ClassFlowPostProcessing::ErsetzteN(string input)
+string ClassFlowPostProcessing::ErsetzteN(string input, float _prevalue)
 {
 {
     int posN, posPunkt;
     int posN, posPunkt;
     int pot, ziffer;
     int pot, ziffer;
@@ -499,7 +690,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input)
             pot = posPunkt - posN;
             pot = posPunkt - posN;
         }
         }
 
 
-        zw = PreValue / pow(10, pot);
+        zw =_prevalue / pow(10, pot);
         ziffer = ((int) zw) % 10;
         ziffer = ((int) zw) % 10;
         input[posN] = ziffer + 48;
         input[posN] = ziffer + 48;
 
 
@@ -509,7 +700,7 @@ string ClassFlowPostProcessing::ErsetzteN(string input)
     return input;
     return input;
 }
 }
 
 
-float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog){
+float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue){
     int aktdigit, olddigit;
     int aktdigit, olddigit;
     int aktdigit_before, olddigit_before;
     int aktdigit_before, olddigit_before;
     int pot, pot_max;
     int pot, pot_max;
@@ -527,12 +718,12 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
     {
     {
         zw = input / pow(10, pot-1);
         zw = input / pow(10, pot-1);
         aktdigit_before = ((int) zw) % 10;
         aktdigit_before = ((int) zw) % 10;
-        zw = PreValue / pow(10, pot-1);
+        zw = _preValue / pow(10, pot-1);
         olddigit_before = ((int) zw) % 10;
         olddigit_before = ((int) zw) % 10;
 
 
         zw = input / pow(10, pot);
         zw = input / pow(10, pot);
         aktdigit = ((int) zw) % 10;
         aktdigit = ((int) zw) % 10;
-        zw = PreValue / pow(10, pot);
+        zw = _preValue / pow(10, pot);
         olddigit = ((int) zw) % 10;
         olddigit = ((int) zw) % 10;
 
 
         no_nulldurchgang = (olddigit_before <= aktdigit_before);
         no_nulldurchgang = (olddigit_before <= aktdigit_before);
@@ -558,18 +749,18 @@ float ClassFlowPostProcessing::checkDigitConsistency(float input, int _decilamsh
     return input;
     return input;
 }
 }
 
 
-string ClassFlowPostProcessing::getReadoutRate()
+string ClassFlowPostProcessing::getReadoutRate(int _number)
 {
 {
-    return std::to_string(FlowRateAct);
+    return std::to_string(NUMBERS[_number]->FlowRateAct);
 }
 }
 
 
-string ClassFlowPostProcessing::getReadoutTimeStamp()
+string ClassFlowPostProcessing::getReadoutTimeStamp(int _number)
 {
 {
-   return timeStamp; 
+   return NUMBERS[_number]->timeStamp; 
 }
 }
 
 
 
 
-string ClassFlowPostProcessing::getReadoutError() 
+string ClassFlowPostProcessing::getReadoutError(int _number) 
 {
 {
-    return ErrorMessageText;
+    return NUMBERS[_number]->ErrorMessageText;
 }
 }

+ 60 - 24
code/components/jomjol_flowcontroll/ClassFlowPostProcessing.h

@@ -1,58 +1,94 @@
 #pragma once
 #pragma once
 #include "ClassFlow.h"
 #include "ClassFlow.h"
 #include "ClassFlowMakeImage.h"
 #include "ClassFlowMakeImage.h"
-
-#include <string>
+#include "ClassFlowAnalog.h"
+#include "ClassFlowDigit.h"
 
 
 
 
+#include <string>
 
 
 
 
-class ClassFlowPostProcessing :
-    public ClassFlow
-{
-protected:
-    bool PreValueUse;
-    int PreValueAgeStartup; 
-    bool AllowNegativeRates;
+struct NumberPost {
+//    int PreValueAgeStartup; 
     float MaxRateValue;
     float MaxRateValue;
     bool useMaxRateValue;
     bool useMaxRateValue;
     bool ErrorMessage;
     bool ErrorMessage;
     bool PreValueOkay;
     bool PreValueOkay;
+    bool AllowNegativeRates;
     bool checkDigitIncreaseConsistency;
     bool checkDigitIncreaseConsistency;
-    int DecimalShift;
     time_t lastvalue;
     time_t lastvalue;
+    string timeStamp;
     float FlowRateAct;          // m3 / min
     float FlowRateAct;          // m3 / min
-
-
-    string FilePreValue;
     float PreValue;             // letzter Wert, der gut ausgelesen wurde
     float PreValue;             // letzter Wert, der gut ausgelesen wurde
     float Value;                // letzer ausgelesener Wert, inkl. Korrekturen
     float Value;                // letzer ausgelesener Wert, inkl. Korrekturen
     string ReturnRawValue;      // Rohwert (mit N & führenden 0)    
     string ReturnRawValue;      // Rohwert (mit N & führenden 0)    
     string ReturnValue;         // korrigierter Rückgabewert, ggf. mit Fehlermeldung
     string ReturnValue;         // korrigierter Rückgabewert, ggf. mit Fehlermeldung
-    string ReturnValueNoError;  // korrigierter Rückgabewert ohne Fehlermeldung
+    string ReturnPreValue;  // korrigierter Rückgabewert ohne Fehlermeldung
+    string ReturnValueNoError;
     string ErrorMessageText;        // Fehlermeldung bei Consistency Check
     string ErrorMessageText;        // Fehlermeldung bei Consistency Check
-    string timeStamp;
+    int AnzahlAnalog;
+    int AnzahlDigital;
+    int DecimalShift;
+    int Nachkomma;
+//    ClassFlowAnalog* ANALOG;
+//    ClassFlowDigit* DIGIT;
+
+    digit *digit_roi;
+    analog *analog_roi;
+
+
+
+    string name;
+};
+
+
+
+
+class ClassFlowPostProcessing :
+    public ClassFlow
+{
+protected:
+    std::vector<NumberPost*> NUMBERS;
+    bool UpdatePreValueINI;
+
+    bool PreValueUse;
+    int PreValueAgeStartup; 
+    bool ErrorMessage;
+
+
+    ClassFlowAnalog* flowAnalog;
+    ClassFlowDigit* flowDigit;    
+
+
+    string FilePreValue;
 
 
     ClassFlowMakeImage *flowMakeImage;
     ClassFlowMakeImage *flowMakeImage;
 
 
     bool LoadPreValue(void);
     bool LoadPreValue(void);
     string ShiftDecimal(string in, int _decShift);
     string ShiftDecimal(string in, int _decShift);
 
 
-    string ErsetzteN(string);
-    float checkDigitConsistency(float input, int _decilamshift, bool _isanalog);
+    string ErsetzteN(string, float _prevalue);
+    float checkDigitConsistency(float input, int _decilamshift, bool _isanalog, float _preValue);
     string RundeOutput(float _in, int _anzNachkomma);
     string RundeOutput(float _in, int _anzNachkomma);
 
 
+    void InitNUMBERS();
+    void handleDecimalSeparator(string _decsep, string _value);
+    void handleMaxRateValue(string _decsep, string _value);
+
+
 public:
 public:
     ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc);
     ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc);
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool ReadParameter(FILE* pfile, string& aktparamgraph);
     bool doFlow(string time);
     bool doFlow(string time);
-    string getReadout();
-    string getReadoutParam(bool _rawValue, bool _noerror);
-    string getReadoutError();
-    string getReadoutRate();
-    string getReadoutTimeStamp();
-    void SavePreValue(float value, string time = "");
-    string GetPreValue();
+    string getReadout(int _number);
+    string getReadoutParam(bool _rawValue, bool _noerror, int _number = 0);
+    string getReadoutError(int _number = 0);
+    string getReadoutRate(int _number = 0);
+    string getReadoutTimeStamp(int _number = 0);
+    void SavePreValue();
+    string GetPreValue(std::string _number = "");
+    void SetPreValue(float zw, string _numbers);
+    std::vector<NumberPost*> GetNumbers(){return NUMBERS;};
 
 
     string name(){return "ClassFlowPostProcessing";};
     string name(){return "ClassFlowPostProcessing";};
 };
 };

+ 38 - 1
code/components/jomjol_helper/Helper.cpp

@@ -10,6 +10,7 @@
 #include <string.h>
 #include <string.h>
 #include <esp_log.h>
 #include <esp_log.h>
 
 
+
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 //#include "ClassLogFile.h"
 //#include "ClassLogFile.h"
 
 
@@ -77,8 +78,9 @@ void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
 
 
 
 
 
 
-FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec)
+FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec)
 {
 {
+	printf("open config file %s in mode %s\n", nm, _mode);
 	FILE *pfile = fopen(nm, _mode);
 	FILE *pfile = fopen(nm, _mode);
 
 
 	if (pfile == NULL)
 	if (pfile == NULL)
@@ -313,6 +315,14 @@ string toUpper(string in)
 	return in;
 	return in;
 }
 }
 
 
+string toLower(string in)
+{
+	for (int i = 0; i < in.length(); ++i)
+		in[i] = tolower(in[i]);
+	
+	return in;
+}
+
 // CPU Temp
 // CPU Temp
 extern "C" uint8_t temprature_sens_read();
 extern "C" uint8_t temprature_sens_read();
 float temperatureRead()
 float temperatureRead()
@@ -358,3 +368,30 @@ int removeFolder(const char* folderPath, const char* logTag) {
 
 
 	return deleted;
 	return deleted;
 }
 }
+
+
+
+std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter = "")
+{
+	std::vector<string> Output;
+	std::string delimiter = " =,";
+    if (_delimiter.length() > 0){
+        delimiter = _delimiter;
+    }
+
+	input = trim(input, delimiter);
+	size_t pos = findDelimiterPos(input, delimiter);
+	std::string token;
+	while (pos != std::string::npos) {
+		token = input.substr(0, pos);
+		token = trim(token, delimiter);
+		Output.push_back(token);
+		input.erase(0, pos + 1);
+		input = trim(input, delimiter);
+		pos = findDelimiterPos(input, delimiter);
+	}
+	Output.push_back(input);
+
+	return Output;
+}
+

+ 5 - 1
code/components/jomjol_helper/Helper.h

@@ -1,6 +1,7 @@
 #pragma once
 #pragma once
 #include <string>
 #include <string>
 #include <fstream>
 #include <fstream>
+#include <vector>
 
 
 
 
 using namespace std;
 using namespace std;
@@ -10,7 +11,7 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
 
 
 void CopyFile(string input, string output);
 void CopyFile(string input, string output);
 
 
-FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 1);
+FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1);
 
 
 size_t findDelimiterPos(string input, string delimiter);
 size_t findDelimiterPos(string input, string delimiter);
 //string trim(string istring);
 //string trim(string istring);
@@ -22,6 +23,7 @@ string getFileType(string filename);
 int mkdir_r(const char *dir, const mode_t mode);
 int mkdir_r(const char *dir, const mode_t mode);
 int removeFolder(const char* folderPath, const char* logTag);
 int removeFolder(const char* folderPath, const char* logTag);
 
 
+string toLower(string in);
 string toUpper(string in);
 string toUpper(string in);
 
 
 float temperatureRead();
 float temperatureRead();
@@ -30,6 +32,8 @@ time_t addDays(time_t startTime, int days);
 
 
 void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);
 void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);
 
 
+std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter);
+
 ///////////////////////////
 ///////////////////////////
 size_t getInternalESPHeapSize();
 size_t getInternalESPHeapSize();
 size_t getESPHeapSize();
 size_t getESPHeapSize();

+ 1 - 1
code/components/jomjol_logfile/ClassLogFile.cpp

@@ -12,7 +12,7 @@ ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt");
 
 
 void ClassLogFile::WriteHeapInfo(std::string _id)
 void ClassLogFile::WriteHeapInfo(std::string _id)
 {
 {
-std::string _zw = "\t" + _id;
+    std::string _zw = "\t" + _id;
     if (loglevel > 0)
     if (loglevel > 0)
         _zw =  _zw + "\t" + getESPHeapInfo();
         _zw =  _zw + "\t" + getESPHeapInfo();
 
 

+ 127 - 14
code/components/jomjol_mqtt/interface_mqtt.cpp

@@ -1,12 +1,14 @@
 #include "interface_mqtt.h"
 #include "interface_mqtt.h"
 
 
-
+//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
 #include "esp_log.h"
 #include "esp_log.h"
 #include "mqtt_client.h"
 #include "mqtt_client.h"
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
 
 
-static const char *TAG = "interface_mqtt";
+static const char *TAG_INTERFACEMQTT = "interface_mqtt";
 
 
+std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;  
+std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;  
 bool debugdetail = true;
 bool debugdetail = true;
 
 
 // #define CONFIG_BROKER_URL "mqtt://192.168.178.43:1883"
 // #define CONFIG_BROKER_URL "mqtt://192.168.178.43:1883"
@@ -23,44 +25,67 @@ 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);
         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;
         zw = "sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
         if (debugdetail) LogFile.WriteToFile(zw);
         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_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
     }
     }
     else {
     else {
-        ESP_LOGI(TAG, "Problem with Publish, client=%d, mqtt_connected %d", (int) client, (int) mqtt_connected);
+        ESP_LOGW(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)
 static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
 {
 {
+    int msg_id;
+    std::string topic = "";
     switch (event->event_id) {
     switch (event->event_id) {
+        case MQTT_EVENT_BEFORE_CONNECT:
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_BEFORE_CONNECT");
+            break;
         case MQTT_EVENT_CONNECTED:
         case MQTT_EVENT_CONNECTED:
-            ESP_LOGI(TAG, "MQTT_EVENT_CONNECTED");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_CONNECTED");
             mqtt_connected = true;
             mqtt_connected = true;
+            MQTTconnected();
             break;
             break;
         case MQTT_EVENT_DISCONNECTED:
         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;
             break;
         case MQTT_EVENT_PUBLISHED:
         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;
             break;
         case MQTT_EVENT_DATA:
         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);
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_DATA");
+            ESP_LOGI(TAG_INTERFACEMQTT, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
+            ESP_LOGI(TAG_INTERFACEMQTT, "DATA=%.*s\r\n", event->data_len, event->data);
+            topic.assign(event->topic, event->topic_len);
+            if (subscribeFunktionMap != NULL) {
+                if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
+                    ESP_LOGD(TAG_INTERFACEMQTT, "call handler function\r\n");
+                    (*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
+                }
+            } else {
+                ESP_LOGW(TAG_INTERFACEMQTT, "no handler available\r\n");
+            }
             break;
             break;
         case MQTT_EVENT_ERROR:
         case MQTT_EVENT_ERROR:
-            ESP_LOGI(TAG, "MQTT_EVENT_ERROR");
+            ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_ERROR");
             break;
             break;
         default:
         default:
-            ESP_LOGI(TAG, "Other event id:%d", event->event_id);
+            ESP_LOGI(TAG_INTERFACEMQTT, "Other event id:%d", event->event_id);
             break;
             break;
     }
     }
     return ESP_OK;
     return ESP_OK;
 }
 }
 
 
 static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
 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);
     mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
 }
 }
 
 
@@ -82,7 +107,7 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
     if (_user.length() && _password.length()){
     if (_user.length() && _password.length()){
         mqtt_cfg.username = _user.c_str();
         mqtt_cfg.username = _user.c_str();
         mqtt_cfg.password = _password.c_str();
         mqtt_cfg.password = _password.c_str();
-        printf("Connect to MQTT: %s, %s", mqtt_cfg.username, mqtt_cfg.password);
+        ESP_LOGI(TAG_INTERFACEMQTT, "Connect to MQTT: %s, %s", mqtt_cfg.username, mqtt_cfg.password);
     };
     };
 
 
     client = esp_mqtt_client_init(&mqtt_cfg);
     client = esp_mqtt_client_init(&mqtt_cfg);
@@ -91,3 +116,91 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st
 
 
     MQTTPublish(_LWTContext, "", 1);
     MQTTPublish(_LWTContext, "", 1);
 }
 }
+
+void MQTTdestroy() {
+    if (client != NULL) {
+        esp_mqtt_client_stop(client);
+        esp_mqtt_client_destroy(client);
+    }
+}
+
+bool MQTTisConnected() {
+    return mqtt_connected;
+}
+
+void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
+    ESP_LOGD(TAG_INTERFACEMQTT, "MQTTregisteronnectFunction %s\r\n", name.c_str());
+    if (connectFunktionMap == NULL) {
+        connectFunktionMap = new std::map<std::string, std::function<void()>>();
+    }
+
+    if ((*connectFunktionMap)[name] != NULL) {
+        ESP_LOGW(TAG_INTERFACEMQTT, "connect function %s already registred", name.c_str());
+        return;
+    }
+
+    (*connectFunktionMap)[name] = func;
+
+    if (mqtt_connected) {
+        func();
+    }
+}
+
+void MQTTunregisterConnectFunction(std::string name){
+    ESP_LOGD(TAG_INTERFACEMQTT, "MQTTregisteronnectFunction %s\r\n", name.c_str());
+    if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
+        connectFunktionMap->erase(name);
+    }
+}
+
+void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
+    ESP_LOGD(TAG_INTERFACEMQTT, "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_LOGD(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
+    }
+}
+
+void MQTTconnected(){
+    if (mqtt_connected) {
+        if (connectFunktionMap != NULL) {
+            for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
+                it->second();
+                ESP_LOGD(TAG_INTERFACEMQTT, "call connect function %s", it->first.c_str());
+            }
+        }
+
+        if (subscribeFunktionMap != NULL) {
+            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_LOGD(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;
+    }
+}

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

@@ -1,7 +1,23 @@
+#ifndef INTERFACE_MQTT_H
+#define INTERFACE_MQTT_H
+
 #include <string>
 #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 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 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 MQTTregisterConnectFunction(std::string name, std::function<void()> func);
+void MQTTunregisterConnectFunction(std::string name);
+void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func);
+void MQTTdestroySubscribeFunction();
+void MQTTconnected();
+
+#endif //INTERFACE_MQTT_H

+ 8 - 2
code/components/jomjol_tfliteclass/CTfLiteClass.cpp

@@ -98,7 +98,8 @@ void CTfLiteClass::GetOutPut()
 
 
 void CTfLiteClass::Invoke()
 void CTfLiteClass::Invoke()
 {
 {
-    interpreter->Invoke();
+    if (interpreter != nullptr)
+      interpreter->Invoke();
 }
 }
 
 
 
 
@@ -208,7 +209,7 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
     return result;
     return result;
 }
 }
 
 
-void CTfLiteClass::LoadModel(std::string _fn){
+bool CTfLiteClass::LoadModel(std::string _fn){
 
 
 #ifdef SUPRESS_TFLITE_ERRORS
 #ifdef SUPRESS_TFLITE_ERRORS
     this->error_reporter = new tflite::OwnMicroErrorReporter;
     this->error_reporter = new tflite::OwnMicroErrorReporter;
@@ -219,9 +220,14 @@ void CTfLiteClass::LoadModel(std::string _fn){
     unsigned char *rd;
     unsigned char *rd;
     rd = ReadFileToCharArray(_fn.c_str());
     rd = ReadFileToCharArray(_fn.c_str());
 
 
+    if (rd == NULL) 
+      return false;
+
     this->model = tflite::GetModel(rd);
     this->model = tflite::GetModel(rd);
     free(rd);
     free(rd);
     TFLITE_MINIMAL_CHECK(model != nullptr); 
     TFLITE_MINIMAL_CHECK(model != nullptr); 
+    
+    return true;
 }
 }
 
 
 
 

+ 1 - 1
code/components/jomjol_tfliteclass/CTfLiteClass.h

@@ -56,7 +56,7 @@ class CTfLiteClass
     public:
     public:
         CTfLiteClass();
         CTfLiteClass();
         ~CTfLiteClass();        
         ~CTfLiteClass();        
-        void LoadModel(std::string _fn);
+        bool LoadModel(std::string _fn);
         void MakeAllocate();
         void MakeAllocate();
         void GetInputTensorSize();
         void GetInputTensorSize();
         bool LoadInputImageBasis(CImageBasis *rs);
         bool LoadInputImageBasis(CImageBasis *rs);

+ 75 - 17
code/components/jomjol_tfliteclass/server_tflite.cpp

@@ -8,6 +8,7 @@
 #include <iomanip>
 #include <iomanip>
 #include <sstream>
 #include <sstream>
 
 
+#include "defines.h"
 #include "Helper.h"
 #include "Helper.h"
 
 
 #include "esp_camera.h"
 #include "esp_camera.h"
@@ -17,8 +18,9 @@
 #include "ClassFlowControll.h"
 #include "ClassFlowControll.h"
 
 
 #include "ClassLogFile.h"
 #include "ClassLogFile.h"
+#include "server_GPIO.h"
 
 
-//#define DEBUG_DETAIL_ON       
+// #define DEBUG_DETAIL_ON       
 
 
 
 
 ClassFlowControll tfliteflow;
 ClassFlowControll tfliteflow;
@@ -37,6 +39,9 @@ bool auto_isrunning = false;
 
 
 int countRounds = 0;
 int countRounds = 0;
 
 
+static const char *TAGTFLITE = "server_tflite";
+
+
 int getCountFlowRounds() {
 int getCountFlowRounds() {
     return countRounds;
     return countRounds;
 }
 }
@@ -64,9 +69,11 @@ void KillTFliteTasks()
 #ifdef DEBUG_DETAIL_ON          
 #ifdef DEBUG_DETAIL_ON          
     printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow);  
     printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow);  
 #endif  
 #endif  
-    if (xHandleblink_task_doFlow)
+    if (xHandleblink_task_doFlow != NULL)
     {
     {
-        vTaskDelete(xHandleblink_task_doFlow);
+        TaskHandle_t xHandleblink_task_doFlowTmp = xHandleblink_task_doFlow;
+        xHandleblink_task_doFlow = NULL;
+        vTaskDelete(xHandleblink_task_doFlowTmp);
 #ifdef DEBUG_DETAIL_ON      
 #ifdef DEBUG_DETAIL_ON      
         printf("Killed: xHandleblink_task_doFlow\n");
         printf("Killed: xHandleblink_task_doFlow\n");
 #endif
 #endif
@@ -75,9 +82,11 @@ void KillTFliteTasks()
 #ifdef DEBUG_DETAIL_ON      
 #ifdef DEBUG_DETAIL_ON      
     printf("Handle: xHandletask_autodoFlow: %ld\n", (long) xHandletask_autodoFlow);  
     printf("Handle: xHandletask_autodoFlow: %ld\n", (long) xHandletask_autodoFlow);  
 #endif
 #endif
-    if (xHandletask_autodoFlow)
+    if (xHandletask_autodoFlow != NULL)
     {
     {
-        vTaskDelete(xHandletask_autodoFlow);
+        TaskHandle_t xHandletask_autodoFlowTmp = xHandletask_autodoFlow;
+        xHandletask_autodoFlow = NULL;
+        vTaskDelete(xHandletask_autodoFlowTmp);
 #ifdef DEBUG_DETAIL_ON      
 #ifdef DEBUG_DETAIL_ON      
         printf("Killed: xHandletask_autodoFlow\n");
         printf("Killed: xHandletask_autodoFlow\n");
 #endif
 #endif
@@ -87,11 +96,10 @@ void KillTFliteTasks()
 
 
 void doInit(void)
 void doInit(void)
 {
 {
-    string config = "/sdcard/config/config.ini";
 #ifdef DEBUG_DETAIL_ON             
 #ifdef DEBUG_DETAIL_ON             
     printf("Start tfliteflow.InitFlow(config);\n");
     printf("Start tfliteflow.InitFlow(config);\n");
 #endif
 #endif
-    tfliteflow.InitFlow(config);
+    tfliteflow.InitFlow(CONFIG_FILE);
 #ifdef DEBUG_DETAIL_ON      
 #ifdef DEBUG_DETAIL_ON      
     printf("Finished tfliteflow.InitFlow(config);\n");
     printf("Finished tfliteflow.InitFlow(config);\n");
 #endif
 #endif
@@ -136,7 +144,7 @@ esp_err_t handler_init(httpd_req_t *req)
     printf("handler_doinit uri:\n"); printf(req->uri); printf("\n");
     printf("handler_doinit uri:\n"); printf(req->uri); printf("\n");
 #endif
 #endif
 
 
-    char* resp_str = "Init started<br>";
+    const char* resp_str = "Init started<br>";
     httpd_resp_send(req, resp_str, strlen(resp_str));     
     httpd_resp_send(req, resp_str, strlen(resp_str));     
 
 
     doInit();
     doInit();
@@ -159,8 +167,6 @@ esp_err_t handler_doflow(httpd_req_t *req)
     LogFile.WriteHeapInfo("handler_doflow - Start");       
     LogFile.WriteHeapInfo("handler_doflow - Start");       
 #endif
 #endif
 
 
-    char* resp_str;
-
     printf("handler_doFlow uri: "); printf(req->uri); printf("\n");
     printf("handler_doFlow uri: "); printf(req->uri); printf("\n");
 
 
     if (flowisrunning)
     if (flowisrunning)
@@ -173,7 +179,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);
         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));  
     httpd_resp_send(req, resp_str, strlen(resp_str));  
     /* Respond with an empty chunk to signal HTTP response completion */
     /* Respond with an empty chunk to signal HTTP response completion */
     httpd_resp_send_chunk(req, NULL, 0);       
     httpd_resp_send_chunk(req, NULL, 0);       
@@ -196,6 +202,8 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
 
 
     bool _rawValue = false;
     bool _rawValue = false;
     bool _noerror = false;
     bool _noerror = false;
+    bool _all = false;
+    std::string _type = "value";
     string zw;
     string zw;
 
 
     printf("handler_wasserzaehler uri:\n"); printf(req->uri); printf("\n");
     printf("handler_wasserzaehler uri:\n"); printf(req->uri); printf("\n");
@@ -206,6 +214,22 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
     if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
     if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
     {
     {
 //        printf("Query: "); printf(_query); printf("\n");
 //        printf("Query: "); printf(_query); printf("\n");
+        if (httpd_query_key_value(_query, "all", _size, 10) == ESP_OK)
+        {
+#ifdef DEBUG_DETAIL_ON       
+            printf("all is found"); printf(_size); printf("\n"); 
+#endif
+            _all = true;
+        }
+
+        if (httpd_query_key_value(_query, "type", _size, 10) == ESP_OK)
+        {
+#ifdef DEBUG_DETAIL_ON       
+            printf("all is found"); printf(_size); printf("\n"); 
+#endif
+            _type = std::string(_size);
+        }
+
         if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK)
         if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK)
         {
         {
 #ifdef DEBUG_DETAIL_ON       
 #ifdef DEBUG_DETAIL_ON       
@@ -222,6 +246,29 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
         }        
         }        
     }  
     }  
 
 
+    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+
+    if (_all)
+    {
+        httpd_resp_set_type(req, "text/plain");
+        printf("TYPE: %s\n", _type.c_str());
+        int _intype = READOUT_TYPE_VALUE;
+        if (_type == "prevalue")
+            _intype = READOUT_TYPE_PREVALUE;
+        if (_type == "raw")
+            _intype = READOUT_TYPE_RAWVALUE;
+        if (_type == "error")
+            _intype = READOUT_TYPE_ERROR;
+
+
+        zw = tfliteflow.getReadoutAll(_intype);
+        printf("ZW: %s\n", zw.c_str());
+        if (zw.length() > 0)
+            httpd_resp_sendstr_chunk(req, zw.c_str()); 
+        httpd_resp_sendstr_chunk(req, NULL);   
+        return ESP_OK;
+    }
+
     zw = tfliteflow.getReadout(_rawValue, _noerror);
     zw = tfliteflow.getReadout(_rawValue, _noerror);
     if (zw.length() > 0)
     if (zw.length() > 0)
         httpd_resp_sendstr_chunk(req, zw.c_str()); 
         httpd_resp_sendstr_chunk(req, zw.c_str()); 
@@ -429,7 +476,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
 
 
 //        printf("Parameter host: "); printf(_host.c_str()); printf("\n"); 
 //        printf("Parameter host: "); printf(_host.c_str()); printf("\n"); 
 //        string zwzw = "Do " + _task + " start\n"; printf(zwzw.c_str());
 //        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);
         std::string zw = tfliteflow.doSingleStep("[MakeImage]", _host);
         httpd_resp_sendstr_chunk(req, zw.c_str()); 
         httpd_resp_sendstr_chunk(req, zw.c_str()); 
     } 
     } 
@@ -498,6 +545,7 @@ esp_err_t handler_prevalue(httpd_req_t *req)
 
 
     char _query[100];
     char _query[100];
     char _size[10] = "";
     char _size[10] = "";
+    char _numbers[50] = "default";
 
 
     if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
     if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
     {
     {
@@ -511,15 +559,24 @@ esp_err_t handler_prevalue(httpd_req_t *req)
             printf("Value: "); printf(_size); printf("\n"); 
             printf("Value: "); printf(_size); printf("\n"); 
 #endif
 #endif
         }
         }
+
+        httpd_query_key_value(_query, "numbers", _numbers, 50);
     }      
     }      
 
 
     if (strlen(_size) == 0)
     if (strlen(_size) == 0)
-        zw = tfliteflow.GetPrevalue();
+    {
+        zw = tfliteflow.GetPrevalue(std::string(_numbers));
+    }
     else
     else
-        zw = "SetPrevalue to " + tfliteflow.UpdatePrevalue(_size);
+    {
+        zw = "SetPrevalue to " + tfliteflow.UpdatePrevalue(_size, _numbers);
+    }
     
     
     resp_str = zw.c_str();
     resp_str = zw.c_str();
 
 
+    httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
+
+
     httpd_resp_send(req, resp_str, strlen(resp_str));   
     httpd_resp_send(req, resp_str, strlen(resp_str));   
     /* Respond with an empty chunk to signal HTTP response completion */
     /* Respond with an empty chunk to signal HTTP response completion */
     httpd_resp_send_chunk(req, NULL, 0);      
     httpd_resp_send_chunk(req, NULL, 0);      
@@ -535,17 +592,17 @@ void task_autodoFlow(void *pvParameter)
 {
 {
     int64_t fr_start, fr_delta_ms;
     int64_t fr_start, fr_delta_ms;
 
 
+    printf("task_autodoFlow: start\r\n");
     doInit();
     doInit();
-    
-    auto_isrunning = tfliteflow.isAutoStart(auto_intervall);
+    gpio_handler_init();
 
 
+    auto_isrunning = tfliteflow.isAutoStart(auto_intervall);
     if (isSetupModusActive()) {
     if (isSetupModusActive()) {
         auto_isrunning = false;
         auto_isrunning = false;
         std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
         std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
         tfliteflow.doFlowMakeImageOnly(zw_time);
         tfliteflow.doFlowMakeImageOnly(zw_time);
 
 
     }
     }
-
     while (auto_isrunning)
     while (auto_isrunning)
     {
     {
         std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds);
         std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds);
@@ -590,6 +647,7 @@ void task_autodoFlow(void *pvParameter)
     }
     }
     vTaskDelete(NULL); //Delete this task if it exits from the loop above
     vTaskDelete(NULL); //Delete this task if it exits from the loop above
     xHandletask_autodoFlow = NULL;
     xHandletask_autodoFlow = NULL;
+    printf("task_autodoFlow: end\r\n");
 }
 }
 
 
 void TFliteDoAutoStart()
 void TFliteDoAutoStart()

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

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

+ 14 - 0
code/components/jomjol_time_sntp/time_sntp.cpp

@@ -18,6 +18,7 @@
 static const char *TAG = "sntp";
 static const char *TAG = "sntp";
 
 
 bool setTimeAlwaysOnReboot = true;
 bool setTimeAlwaysOnReboot = true;
+time_t bootTime;
 
 
 static void obtain_time(void);
 static void obtain_time(void);
 static void initialize_sntp(void);
 static void initialize_sntp(void);
@@ -125,4 +126,17 @@ static void initialize_sntp(void)
     sntp_setservername(0, "pool.ntp.org");
     sntp_setservername(0, "pool.ntp.org");
 //    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
 //    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
     sntp_init();
     sntp_init();
+}
+
+void setBootTime() 
+{
+    time(&bootTime);
+}
+
+time_t getUpTime() 
+{
+    time_t now;
+    time(&now);
+
+    return now - bootTime;
 }
 }

+ 4 - 1
code/components/jomjol_time_sntp/time_sntp.h

@@ -18,4 +18,7 @@ std::string gettimestring(const char * frm);
 std::string ConvertTimeToString(time_t _time, const char * frm);
 std::string ConvertTimeToString(time_t _time, const char * frm);
 
 
 void setTimeZone(std::string _tzstring);
 void setTimeZone(std::string _tzstring);
-void reset_servername(std::string _servername);
+void reset_servername(std::string _servername);
+
+void setBootTime();
+time_t getUpTime();

+ 6 - 0
code/include/defines.h

@@ -0,0 +1,6 @@
+#ifndef defines_h
+#define defines_h
+
+#define CONFIG_FILE "/sdcard/config/config.ini"
+
+#endif // ifndef defines_h

+ 15 - 16
code/main/main.cpp

@@ -19,6 +19,7 @@
 #include "connect_wlan.h"
 #include "connect_wlan.h"
 #include "read_wlanini.h"
 #include "read_wlanini.h"
 
 
+#include "server_main.h"
 #include "server_tflite.h"
 #include "server_tflite.h"
 #include "server_file.h"
 #include "server_file.h"
 #include "server_ota.h"
 #include "server_ota.h"
@@ -30,16 +31,14 @@
 
 
 #define __SD_USE_ONE_LINE_MODE__
 #define __SD_USE_ONE_LINE_MODE__
 
 
-#ifdef __SD_USE_ONE_LINE_MODE__
 #include "server_GPIO.h"
 #include "server_GPIO.h"
-#endif
 
 
 
 
 #define BLINK_GPIO GPIO_NUM_33
 #define BLINK_GPIO GPIO_NUM_33
 
 
-static const char *TAGMAIN = "connect_wlan_main";
+static const char *TAGMAIN = "main";
 
 
-#define FLASH_GPIO GPIO_NUM_4
+//#define FLASH_GPIO GPIO_NUM_4
 
 
 bool Init_NVS_SDCard()
 bool Init_NVS_SDCard()
 {
 {
@@ -50,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();
     sdmmc_host_t host = SDMMC_HOST_DEFAULT();
 
 
     // This initializes the slot without card detect (CD) and write protect (WP) signals.
     // This initializes the slot without card detect (CD) and write protect (WP) signals.
@@ -92,10 +91,10 @@ bool Init_NVS_SDCard()
 
 
     if (ret != ESP_OK) {
     if (ret != ESP_OK) {
         if (ret == ESP_FAIL) {
         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.");
                 "If you want the card to be formatted, set format_if_mount_failed = true.");
         } else {
         } 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));
                 "Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
         }
         }
         return false;
         return false;
@@ -108,9 +107,9 @@ bool Init_NVS_SDCard()
 	// Init the GPIO
 	// Init the GPIO
     // Flash ausschalten
     // Flash ausschalten
     
     
-    gpio_pad_select_gpio(FLASH_GPIO);
-    gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT);  
-    gpio_set_level(FLASH_GPIO, 0);   
+    // gpio_pad_select_gpio(FLASH_GPIO);
+    // gpio_set_direction(FLASH_GPIO, GPIO_MODE_OUTPUT);  
+    // gpio_set_level(FLASH_GPIO, 0);   
 
 
     return true;
     return true;
 }
 }
@@ -174,11 +173,12 @@ extern "C" void app_main(void)
     
     
     TickType_t xDelay;
     TickType_t xDelay;
     xDelay = 2000 / portTICK_PERIOD_MS;
     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");      
 //    LogFile.WriteToFile("Startsequence 06");      
     vTaskDelay( xDelay );   
     vTaskDelay( xDelay );   
 //    LogFile.WriteToFile("Startsequence 07");  
 //    LogFile.WriteToFile("Startsequence 07");  
     setup_time();
     setup_time();
+    setBootTime();
     LogFile.WriteToFile("=============================================================================================");
     LogFile.WriteToFile("=============================================================================================");
     LogFile.WriteToFile("=================================== Main Started ============================================");
     LogFile.WriteToFile("=================================== Main Started ============================================");
     LogFile.WriteToFile("=============================================================================================");
     LogFile.WriteToFile("=============================================================================================");
@@ -190,7 +190,7 @@ extern "C" void app_main(void)
 //    Camera.InitCam();
 //    Camera.InitCam();
 //    Camera.LightOnOff(false); 
 //    Camera.LightOnOff(false); 
     xDelay = 2000 / portTICK_PERIOD_MS;
     xDelay = 2000 / portTICK_PERIOD_MS;
-    printf("Autoflow: sleep for : %ldms\n", (long) xDelay);
+    printf("main: sleep for : %ldms\n", (long) xDelay);
     vTaskDelay( xDelay ); 
     vTaskDelay( xDelay ); 
 
 
     server = start_webserver();   
     server = start_webserver();   
@@ -199,13 +199,12 @@ extern "C" void app_main(void)
     register_server_file_uri(server, "/sdcard");
     register_server_file_uri(server, "/sdcard");
     register_server_ota_sdcard_uri(server);
     register_server_ota_sdcard_uri(server);
 
 
-#ifdef __SD_USE_ONE_LINE_MODE__
-    register_server_GPIO_uri(server);
-#endif    
-    printf("vor reg server main\n");
+    gpio_handler_create(server);
 
 
+    printf("vor reg server main\n");
     register_server_main_uri(server, "/sdcard");
     register_server_main_uri(server, "/sdcard");
 
 
     printf("vor dotautostart\n");
     printf("vor dotautostart\n");
     TFliteDoAutoStart();
     TFliteDoAutoStart();
 }
 }
+

+ 16 - 14
code/main/server_main.cpp

@@ -20,9 +20,9 @@
 
 
 
 
 httpd_handle_t server = NULL;   
 httpd_handle_t server = NULL;   
-
 std::string starttime = "";
 std::string starttime = "";
 
 
+static const char *TAG_SERVERMAIN = "server-main";
 
 
 /* An HTTP GET handler */
 /* An HTTP GET handler */
 esp_err_t info_get_handler(httpd_req_t *req)
 esp_err_t info_get_handler(httpd_req_t *req)
@@ -198,7 +198,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
     printf("File requested: %s\n", filetosend.c_str());    
     printf("File requested: %s\n", filetosend.c_str());    
 
 
     if (!filename) {
     if (!filename) {
-        ESP_LOGE(TAG, "Filename is too long");
+        ESP_LOGE(TAG_SERVERMAIN, "Filename is too long");
         /* Respond with 500 Internal Server Error */
         /* Respond with 500 Internal Server Error */
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
         httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
         return ESP_FAIL;
         return ESP_FAIL;
@@ -234,7 +234,7 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
     filetosend = filetosend + "/img_tmp/" + std::string(filename);
     filetosend = filetosend + "/img_tmp/" + std::string(filename);
     printf("File to upload: %s\n", filetosend.c_str());    
     printf("File to upload: %s\n", filetosend.c_str());    
 
 
-    esp_err_t res = send_file(req, filetosend);
+    esp_err_t res = send_file(req, filetosend); 
     if (res != ESP_OK)
     if (res != ESP_OK)
         return res;
         return res;
 
 
@@ -299,7 +299,9 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
     std::string gitbranch = libfive_git_branch();
     std::string gitbranch = libfive_git_branch();
     std::string gitbasebranch = git_base_branch();
     std::string gitbasebranch = git_base_branch();
     std::string htmlversion = getHTMLversion();
     std::string htmlversion = getHTMLversion();
-
+    char freeheapmem[11];
+    sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
+    
     tcpip_adapter_ip_info_t ip_info;
     tcpip_adapter_ip_info_t ip_info;
     ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
     ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
     const char *hostname;
     const char *hostname;
@@ -314,7 +316,8 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
                 \"html\" : \"" + htmlversion + "\",\
                 \"html\" : \"" + htmlversion + "\",\
                 \"cputemp\" : \"" + cputemp + "\",\
                 \"cputemp\" : \"" + cputemp + "\",\
                 \"hostname\" : \"" + hostname + "\",\
                 \"hostname\" : \"" + hostname + "\",\
-                \"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\"\
+                \"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\",\
+                \"freeHeapMem\" : \"" + freeheapmem + "\"\
             }\
             }\
         ]";
         ]";
 
 
@@ -387,7 +390,7 @@ httpd_handle_t start_webserver(void)
     httpd_config_t config = { };
     httpd_config_t config = { };
 
 
     config.task_priority      = tskIDLE_PRIORITY+5;
     config.task_priority      = tskIDLE_PRIORITY+5;
-    config.stack_size         = 32384;                  // bei 32k stürzt das Programm beim Bilderaufnehmen ab
+    config.stack_size         = 32768;                  // bei 32k stürzt das Programm beim Bilderaufnehmen ab
     config.core_id            = tskNO_AFFINITY;
     config.core_id            = tskNO_AFFINITY;
     config.server_port        = 80;
     config.server_port        = 80;
     config.ctrl_port          = 32768;
     config.ctrl_port          = 32768;
@@ -403,21 +406,22 @@ httpd_handle_t start_webserver(void)
     config.global_transport_ctx = NULL;                   
     config.global_transport_ctx = NULL;                   
     config.global_transport_ctx_free_fn = NULL;           
     config.global_transport_ctx_free_fn = NULL;           
     config.open_fn = NULL;                                
     config.open_fn = NULL;                                
-    config.close_fn = NULL;                               
+    config.close_fn = NULL;     
+    config.lru_purge_enable = true;             // neu, um schlechte Serverbindung zu verhindern                          
 //    config.uri_match_fn = NULL;                            
 //    config.uri_match_fn = NULL;                            
     config.uri_match_fn = httpd_uri_match_wildcard;
     config.uri_match_fn = httpd_uri_match_wildcard;
 
 
     starttime = gettimestring("%Y%m%d-%H%M%S");
     starttime = gettimestring("%Y%m%d-%H%M%S");
 
 
     // Start the httpd server
     // 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) {
     if (httpd_start(&server, &config) == ESP_OK) {
         // Set URI handlers
         // Set URI handlers
-        ESP_LOGI(TAG, "Registering URI handlers");
+        ESP_LOGI(TAG_SERVERMAIN, "Registering URI handlers");
         return server;
         return server;
     }
     }
 
 
-    ESP_LOGI(TAG, "Error starting server!");
+    ESP_LOGI(TAG_SERVERMAIN, "Error starting server!");
     return NULL;
     return NULL;
 }
 }
 
 
@@ -432,7 +436,7 @@ void disconnect_handler(void* arg, esp_event_base_t event_base,
 {
 {
     httpd_handle_t* server = (httpd_handle_t*) arg;
     httpd_handle_t* server = (httpd_handle_t*) arg;
     if (*server) {
     if (*server) {
-        ESP_LOGI(TAG, "Stopping webserver");
+        ESP_LOGI(TAG_SERVERMAIN, "Stopping webserver");
         stop_webserver(*server);
         stop_webserver(*server);
         *server = NULL;
         *server = NULL;
     }
     }
@@ -443,9 +447,7 @@ void connect_handler(void* arg, esp_event_base_t event_base,
 {
 {
     httpd_handle_t* server = (httpd_handle_t*) arg;
     httpd_handle_t* server = (httpd_handle_t*) arg;
     if (*server == NULL) {
     if (*server == NULL) {
-        ESP_LOGI(TAG, "Starting webserver");
+        ESP_LOGI(TAG_SERVERMAIN, "Starting webserver");
         *server = start_webserver();
         *server = start_webserver();
     }
     }
 }
 }
-
-

+ 3 - 4
code/main/server_main.h

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

+ 4 - 4
code/main/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="21a59fb";
-const char* GIT_TAG="v7.1.1";
-const char* GIT_BRANCH="master";
-const char* BUILD_TIME="2021-06-17 19:59";
+const char* GIT_REV="1f6b02a";
+const char* GIT_TAG="";
+const char* GIT_BRANCH="rolling";
+const char* BUILD_TIME="2021-07-13 20:37";

+ 5 - 1
code/platformio.ini

@@ -22,7 +22,8 @@ framework = espidf
 ;board_build.partitions = partitions_singleapp.csv
 ;board_build.partitions = partitions_singleapp.csv
 board_build.partitions = partitions.csv
 board_build.partitions = partitions.csv
 
 
-lib_deps = 
+lib_deps =
+  jomjol_configfile 
   jomjol_helper 
   jomjol_helper 
   jomjol_wlan  
   jomjol_wlan  
   jomjol_image_proc 
   jomjol_image_proc 
@@ -36,6 +37,9 @@ lib_deps =
   jomjol_mqtt
   jomjol_mqtt
   jomjol_controlGPIO
   jomjol_controlGPIO
 
 
+
 monitor_speed = 115200
 monitor_speed = 115200
+monitor_rts = 0
+monitor_dtr = 0
 
 
 debug_tool = esp-prog
 debug_tool = esp-prog

+ 4 - 2
code/sdkconfig

@@ -138,7 +138,8 @@ CONFIG_COMPILER_OPTIMIZATION_SIZE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
 # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
 # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT is not set
 # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set
 # CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE is not set
-# CONFIG_COMPILER_CXX_EXCEPTIONS is not set
+CONFIG_COMPILER_CXX_EXCEPTIONS=y
+CONFIG_COMPILER_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
 # CONFIG_COMPILER_CXX_RTTI is not set
 # CONFIG_COMPILER_CXX_RTTI is not set
 CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
 CONFIG_COMPILER_STACK_CHECK_MODE_NONE=y
 # CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
 # CONFIG_COMPILER_STACK_CHECK_MODE_NORM is not set
@@ -1061,7 +1062,8 @@ CONFIG_COMPILER_OPTIMIZATION_LEVEL_RELEASE=y
 CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
 CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y
 # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
 # CONFIG_OPTIMIZATION_ASSERTIONS_SILENT is not set
 # CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
 # CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED is not set
-# CONFIG_CXX_EXCEPTIONS is not set
+CONFIG_CXX_EXCEPTIONS=y
+CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE=0
 CONFIG_STACK_CHECK_NONE=y
 CONFIG_STACK_CHECK_NONE=y
 # CONFIG_STACK_CHECK_NORM is not set
 # CONFIG_STACK_CHECK_NORM is not set
 # CONFIG_STACK_CHECK_STRONG is not set
 # CONFIG_STACK_CHECK_STRONG is not set

+ 2 - 3
code/sdkconfig.old

@@ -131,8 +131,8 @@ CONFIG_EXAMPLE_CONNECT_IPV6=y
 #
 #
 # Compiler options
 # Compiler options
 #
 #
-CONFIG_COMPILER_OPTIMIZATION_DEFAULT=y
-# CONFIG_COMPILER_OPTIMIZATION_SIZE is not set
+# CONFIG_COMPILER_OPTIMIZATION_DEFAULT is not set
+CONFIG_COMPILER_OPTIMIZATION_SIZE=y
 # CONFIG_COMPILER_OPTIMIZATION_PERF is not set
 # CONFIG_COMPILER_OPTIMIZATION_PERF is not set
 # CONFIG_COMPILER_OPTIMIZATION_NONE is not set
 # CONFIG_COMPILER_OPTIMIZATION_NONE is not set
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
 CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y
@@ -598,7 +598,6 @@ CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0
 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
 # CONFIG_FREERTOS_USE_TRACE_FACILITY is not set
 # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
 # CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS is not set
 # CONFIG_FREERTOS_DEBUG_INTERNALS is not set
 # CONFIG_FREERTOS_DEBUG_INTERNALS is not set
-CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=y
 CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
 CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER=y
 # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
 # CONFIG_FREERTOS_CHECK_PORT_CRITICAL_COMPLIANCE is not set
 CONFIG_FREERTOS_DEBUG_OCDAWARE=y
 CONFIG_FREERTOS_DEBUG_OCDAWARE=y

+ 4 - 4
code/version.cpp

@@ -1,4 +1,4 @@
-const char* GIT_REV="21a59fb";
-const char* GIT_TAG="v7.1.1";
-const char* GIT_BRANCH="master";
-const char* BUILD_TIME="2021-06-17 19:47";
+const char* GIT_REV="1f6b02a";
+const char* GIT_TAG="";
+const char* GIT_BRANCH="rolling";
+const char* BUILD_TIME="2021-07-13 20:37";

BIN
firmware/bootloader.bin


BIN
firmware/firmware.bin


BIN
firmware/html.zip


+ 35 - 28
sd-card/config/config.ini

@@ -1,61 +1,69 @@
 [MakeImage]
 [MakeImage]
 ;LogImageLocation = /log/source
 ;LogImageLocation = /log/source
-;LogfileRetentionInDays = 15
 WaitBeforeTakingPicture = 5
 WaitBeforeTakingPicture = 5
+;LogfileRetentionInDays = 15
+Brightness = -2
+;Contrast = 0
+;Saturation = 0
 ImageQuality = 5
 ImageQuality = 5
 ImageSize = VGA
 ImageSize = VGA
-;Brightness = -2
 FixedExposure = false
 FixedExposure = false
 
 
 [Alignment]
 [Alignment]
-InitialRotate=180
-FlipImageSize = false
-/config/ref0.jpg 119 273
-/config/ref1.jpg 456 138
+InitialRotate = 179
+InitialMirror = false
 SearchFieldX = 20
 SearchFieldX = 20
 SearchFieldY = 20
 SearchFieldY = 20
-InitialMirror= false
 AlignmentAlgo = Default
 AlignmentAlgo = Default
+FlipImageSize = false
+/config/ref0.jpg 103 271
+/config/ref1.jpg 442 142
 
 
 [Digits]
 [Digits]
-Model = /config/dig0870s3q.tflite
+Model = /config/dig1100s2q.tflite
 ;LogImageLocation = /log/digit
 ;LogImageLocation = /log/digit
 ;LogfileRetentionInDays = 3
 ;LogfileRetentionInDays = 3
 ModelInputSize = 20 32
 ModelInputSize = 20 32
-digit1 306 120 37 67
-digit2 355 120 37 67
-digit3 404 120 37 67
+main.dig1 294 126 30 54
+main.dig2 343 126 30 54
+main.dig3 391 126 30 54
 
 
 [Analog]
 [Analog]
 Model = /config/ana0700s1lq.tflite
 Model = /config/ana0700s1lq.tflite
 ;LogImageLocation = /log/analog
 ;LogImageLocation = /log/analog
 ;LogfileRetentionInDays = 3
 ;LogfileRetentionInDays = 3
 ModelInputSize = 32 32
 ModelInputSize = 32 32
-analog1 444 225 92 92
-analog2 391 329 92 92
-analog3 294 369 92 92
-analog4 168 326 92 92
-ExtendedResolution = false
+ExtendedResolution = true
+main.ana1 432 230 92 92
+main.ana2 379 332 92 92
+main.ana3 283 374 92 92
+main.ana4 155 328 92 92
 
 
 [PostProcessing]
 [PostProcessing]
-DecimalShift = 0
+main.DecimalShift = 0
 PreValueUse = true
 PreValueUse = true
 PreValueAgeStartup = 720
 PreValueAgeStartup = 720
 AllowNegativeRates = false
 AllowNegativeRates = false
-MaxRateValue = 0.1
+main.MaxRateValue = 0.1
 ErrorMessage = true
 ErrorMessage = true
-CheckDigitIncreaseConsistency = false
+CheckDigitIncreaseConsistency = true
 
 
-[MQTT]
+;[MQTT]
 ;Uri = mqtt://IP-ADRESS:1883
 ;Uri = mqtt://IP-ADRESS:1883
-;Topic = wasserzaehler/zaehlerstand
-;TopicError = wasserzaehler/error
-;TopicRate = wasserzaehler/rate
-;TopicTimeStamp = wasserzaehler/timestamp
+;MainTopic = wasserzaehler
 ;ClientID = wasser
 ;ClientID = wasser
 ;user = USERNAME
 ;user = USERNAME
 ;password = PASSWORD
 ;password = PASSWORD
 
 
+;[GPIO]
+;MainTopicMQTT = wasserzaehler/GPIO
+;IO0 = input disabled 10 false false 
+;IO1 = input disabled 10 false false 
+;IO3 = input disabled 10 false false 
+;IO4 = built-in-led disabled 10 false false 
+;IO12 = input-pullup disabled 10 false false 
+;IO13 = input-pullup disabled 10 false false 
+
 [AutoTimer]
 [AutoTimer]
 AutoStart = true
 AutoStart = true
 Intervall = 4.85
 Intervall = 4.85
@@ -66,8 +74,7 @@ LogfileRetentionInDays = 3
 
 
 [System]
 [System]
 TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
 TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
-;TimeServer = fritz.box
-;hostname = watermeter
+;TimeServer = undefined
+;AutoAdjustSummertime = false
+;Hostname = undefined
 SetupMode = true
 SetupMode = true
-
-[Ende]

BIN
sd-card/config/dig0870s3q.tflite


BIN
sd-card/config/dig1100s2q.tflite


+ 14 - 16
sd-card/html/edit_alignment.html

@@ -61,7 +61,7 @@ select {
 			  <option value="1" >Reference 1</option>
 			  <option value="1" >Reference 1</option>
 			</select>
 			</select>
 		</td>
 		</td>
-		<td colspan="2">Storage Path/Name: <input type="text" name="name" id="name"></td>
+		<td colspan="2">Storage Path/Name: <input type="text" name="name" id="name" onchange="namechanged()"></td>
 	  </tr>
 	  </tr>
 	  <tr>
 	  <tr>
 		<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
 		<td style="padding-top: 10px">x: <input type="number" name="refx" id="refx" step=1 onchange="valuemanualchanged()"></td>
@@ -90,9 +90,8 @@ select {
 	</table>
 	</table>
 
 
 <script type="text/javascript" src="./gethost.js"></script> 
 <script type="text/javascript" src="./gethost.js"></script> 
-<script type="text/javascript" src="./readconfig.js"></script> 
 <script type="text/javascript" src="./readconfigcommon.js"></script>
 <script type="text/javascript" src="./readconfigcommon.js"></script>
-
+<script type="text/javascript" src="./readconfigparam.js"></script>  
 
 
 <script language="JavaScript">
 <script language="JavaScript">
         var canvas = document.getElementById('canvas'),
         var canvas = document.getElementById('canvas'),
@@ -105,7 +104,8 @@ select {
             enhanceCon = false,
             enhanceCon = false,
             param;
             param;
             basepath = "http://192.168.178.26";
             basepath = "http://192.168.178.26";
-            basepath = "";
+            basepath = "",
+            param;
 
 
 function ChangeSelection(){
 function ChangeSelection(){
     aktindex = parseInt(document.getElementById("index").value);
     aktindex = parseInt(document.getElementById("index").value);
@@ -113,14 +113,9 @@ function ChangeSelection(){
 }
 }
 
 
 function SaveToConfig(){
 function SaveToConfig(){
-/*
-    refInfo[aktindex]["name"] = document.getElementById("name").value;
-    refInfo[aktindex]["x"] = document.getElementById("refx").value;
-    refInfo[aktindex]["y"] = document.getElementById("refy").value; 
-    refInfo[aktindex]["dx"] = document.getElementById("refdx").value;
-    refInfo[aktindex]["dy"] = document.getElementById("refdy").value;
-*/   
-    UpdateConfigReference(refInfo, basepath); 
+    WriteConfigININew();
+    UpdateConfigReference(basepath)
+    SaveConfigToServer(basepath);
 }
 }
 
 
 function EnhanceContrast(){
 function EnhanceContrast(){
@@ -133,10 +128,6 @@ function EnhanceContrast(){
     enhanceCon = true;
     enhanceCon = true;
     MakeContrastImageZW(refInfo[aktindex], enhanceCon, basepath);
     MakeContrastImageZW(refInfo[aktindex], enhanceCon, basepath);
     UpdateReference();
     UpdateReference();
-//    var url = basepath + "/fileserver" + "/img_tmp/ref_zw.jpg?" + Date.now();
-//    document.getElementById("img_ref").src = url;
-//    var url = basepath + "/fileserver" + "/img_tmp/ref_zw_org.jpg?" + Date.now();
-//    document.getElementById("img_ref_org").src = url;
 }
 }
 
 
 function UpdateReference(){
 function UpdateReference(){
@@ -211,6 +202,7 @@ function dataURLtoBlob(dataurl) {
             basepath = getbasepath();
             basepath = getbasepath();
             loadConfig(basepath); 
             loadConfig(basepath); 
             ParseConfig();
             ParseConfig();
+            param = getConfigParameters();
 
 
             canvas.addEventListener('mousedown', mouseDown, false);
             canvas.addEventListener('mousedown', mouseDown, false);
             canvas.addEventListener('mouseup', mouseUp, false);
             canvas.addEventListener('mouseup', mouseUp, false);
@@ -355,6 +347,12 @@ function dataURLtoBlob(dataurl) {
         }
         }
     }
     }
 
 
+    function namechanged()
+    {
+        _name = document.getElementById("name").value;
+        refInfo[aktindex]["name"] = _name;
+    }
+
     function valuemanualchanged(){
     function valuemanualchanged(){
         if (!drag) {
         if (!drag) {
             rect.w = document.getElementById("refdx").value;
             rect.w = document.getElementById("refdx").value;

+ 188 - 53
sd-card/html/edit_analog.html

@@ -69,13 +69,28 @@ th, td {
    
    
 
 
 <div id="div1">
 <div id="div1">
-
 	<table>
 	<table>
 	  <tr>
 	  <tr>
 		<td><canvas id="canvas" crossorigin></canvas></td>
 		<td><canvas id="canvas" crossorigin></canvas></td>
 	  </tr>
 	  </tr>
 	</table>	
 	</table>	
-			 
+
+    <p>
+        <table>
+            <tr>
+                <class id="Numbers_text" style="color:black;"><b>Number: </b></class>
+                <select id="Numbers_value1" onchange="numberChanged()">
+                    <option value="0" selected>default</option>
+                    <option value="1" >NT</option>
+                    <option value="2" >HT</option>
+                </select>
+                <input class="move" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename">  
+                <input class="move" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New">  
+                <input class="move" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Remove">
+            </tr>
+        </table>
+    </p>
+
 	<table>
 	<table>
 	  <tr>
 	  <tr>
 		<td><input class="button" type="submit" id= "newROI" name="newROI" onclick="newROI()" value="New ROI (after current)"></td>	  
 		<td><input class="button" type="submit" id= "newROI" name="newROI" onclick="newROI()" value="New ROI (after current)"></td>	  
@@ -89,10 +104,12 @@ th, td {
 			  <option value="1" >ROI 1</option>
 			  <option value="1" >ROI 1</option>
             </select>
             </select>
 		</td>
 		</td>
-		<td>Name: <input type="text" name="name" id="name" onchange="onNameChange()" size="13"></td>
+		<td>                
+            <input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename">  
 		<td>
 		<td>
-		<input class="button" type="submit" id="moveNext" onclick="moveNext()" value="move Next">
-		<input class="button" type="submit" id="movePrevious" onclick="movePrevious()" value="move Previous">  
+		<td>
+		<input class="move" type="submit" id="moveNext" onclick="moveNext()" value="move Next">
+		<input class="move" type="submit" id="movePrevious" onclick="movePrevious()" value="move Previous">  
 		</td>	
 		</td>	
 	  </tr>
 	  </tr>
 	  <tr>
 	  <tr>
@@ -114,11 +131,10 @@ th, td {
     </table>	
     </table>	
 
 
 
 
-<script type="text/javascript" src="./gethost.js"></script> 
-<script type="text/javascript" src="./readconfigcommon.js"></script>  
-<script type="text/javascript" src="./readconfig.js"></script>  
-<script type="text/javascript" src="./jquery-3.5.1.min.js"></script>  
-
+    <script type="text/javascript" src="./gethost.js"></script> 
+    <script type="text/javascript" src="./readconfigcommon.js"></script>
+    <script type="text/javascript" src="./readconfigparam.js"></script>  
+    
 <script language="JavaScript">
 <script language="JavaScript">
         var canvas = document.getElementById('canvas'),
         var canvas = document.getElementById('canvas'),
             ctx = canvas.getContext('2d'),
             ctx = canvas.getContext('2d'),
@@ -179,21 +195,22 @@ function deleteROI(){
 }
 }
 
 
 function newROI(){
 function newROI(){
-    var zw = ROIInfo[ROIInfo.length-1];
-    ROIInfo.push(zw);
-    for (var i = ROIInfo.length-2; i > aktindex + 1; --i){
-        ROIInfo[i] = ROIInfo[i-1];
-    }
-    aktindex++;
-    ROIInfo[aktindex] = new Object;
-    ROIInfo[aktindex]["pos_ref"] = -1;
-    ROIInfo[aktindex]["name"] = "ROI" + aktindex;
-    ROIInfo[aktindex]["x"] = 1;
-    ROIInfo[aktindex]["y"] = 1;
-    ROIInfo[aktindex]["dx"] = ROIInfo[aktindex-1]["dx"];
-    ROIInfo[aktindex]["dy"] = ROIInfo[aktindex-1]["dy"];
-    ROIInfo[aktindex]["ar"] = ROIInfo[aktindex-1]["ar"];
-    UpdateROIs();
+    var sel = document.getElementById("Numbers_value1");
+    var _number= sel.options[sel.selectedIndex].text;
+    sel = document.getElementById("index");
+    var _roialt= sel.options[sel.selectedIndex].text;
+
+    var _roinew = prompt("Please enter name of new ROI", "name");
+
+    if (ROIInfo.length > 0)
+        erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"]);
+    else
+        erg = CreateROI(_number, "analog", sel.selectedIndex, _roinew, 1, 1, 30, 30);
+
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateROIs(_roinew);
 }
 }
 
 
 function movePrevious(){
 function movePrevious(){
@@ -223,34 +240,64 @@ function ChangeSelection(){
 }
 }
 
 
 function SaveToConfig(){
 function SaveToConfig(){
-    _enabled = document.getElementById("Category_Analog_enabled").checked;
-    SaveROIToConfig(ROIInfo, "[Analog]", basepath, _enabled);
-    UpdatePage();  
+    _zwcat = getConfigCategory();
+    _zwcat["Analog"]["enabled"] = document.getElementById("Category_Analog_enabled").checked;
+    WriteConfigININew();
+    SaveConfigToServer(basepath);    
 }
 }
 
 
 
 
 function UpdateROIs(){
 function UpdateROIs(){
+    document.getElementById("Category_Analog_enabled").checked = true;
+    var sel = document.getElementById("Numbers_value1");
+    var _number = sel.options[sel.selectedIndex].text;
+
+    ROIInfo = getROIInfo("analog", _number);
+    _catzw = getConfigCategory();
+
+    if (_catzw["Analog"]["enabled"] == false) 
+    {
+        document.getElementById("Category_Analog_enabled").checked = false;
+        EnDisableDigits();
+        alert("Analog ROIs are disabled - please enable (Check box top left).\n");
+        return;
+    }
+
     if (ROIInfo.length == 0){
     if (ROIInfo.length == 0){
-        alert("There are no ROIs defined.\nPlease first define minimum one ROI in the config.ini by hand.\n");
-        document.getElementById("newROI").disabled = true;
+        alert("There are no ROIs defined.\nPlease first create a new ROI (\"New ROIs ...\").\n");
+        document.getElementById("newROI").disabled = false;
         document.getElementById("deleteROI").disabled = true;
         document.getElementById("deleteROI").disabled = true;
         document.getElementById("index").disabled = true;
         document.getElementById("index").disabled = true;
-        document.getElementById("saveroi").disabled = true;
+        document.getElementById("renameROI").disabled = true;
         document.getElementById("moveNext").disabled = true;
         document.getElementById("moveNext").disabled = true;
         document.getElementById("movePrevious").disabled = true;
         document.getElementById("movePrevious").disabled = true;
         return;
         return;
     }
     }
+    else
+    {
+        document.getElementById("newROI").disabled = false;
+        document.getElementById("deleteROI").disabled = false;
+        document.getElementById("renameROI").disabled = false;
+        document.getElementById("index").disabled = false;
+    }
 
 
     var _index = document.getElementById("index");
     var _index = document.getElementById("index");
     while (_index.length){
     while (_index.length){
         _index.remove(0);
         _index.remove(0);
     }
     }
 
 
+    if (aktindex > ROIInfo.length)
+        aktindex = ROIInfo.length;
+
     for (var i = 0; i < ROIInfo.length; ++i){
     for (var i = 0; i < ROIInfo.length; ++i){
         var option = document.createElement("option");
         var option = document.createElement("option");
-        option.text = "ROI " + (i + 1);
+        option.text = ROIInfo[i]["name"];
         option.value = i;
         option.value = i;
-        _index.add(option); 
+        _index.add(option);
+        if (typeof _sel !== 'undefined') {
+            if (option.text == _sel)
+                aktindex = i;
+        }
     }
     }
     _index.selectedIndex = aktindex; 
     _index.selectedIndex = aktindex; 
 
 
@@ -267,7 +314,6 @@ function UpdateROIs(){
     
     
     document.getElementById("lockAR").checked = lockAR;
     document.getElementById("lockAR").checked = lockAR;
        
        
-    document.getElementById("name").value = ROIInfo[aktindex]["name"];
     document.getElementById("refx").value = ROIInfo[aktindex]["x"];
     document.getElementById("refx").value = ROIInfo[aktindex]["x"];
     document.getElementById("refy").value = ROIInfo[aktindex]["y"];  
     document.getElementById("refy").value = ROIInfo[aktindex]["y"];  
     document.getElementById("refdx").value = ROIInfo[aktindex]["dx"];  
     document.getElementById("refdx").value = ROIInfo[aktindex]["dx"];  
@@ -277,26 +323,8 @@ function UpdateROIs(){
     rect.w = ROIInfo[aktindex]["dx"];
     rect.w = ROIInfo[aktindex]["dx"];
     rect.h = ROIInfo[aktindex]["dy"];
     rect.h = ROIInfo[aktindex]["dy"];
     draw();      
     draw();      
-}
 
 
-function ParseIni(_basepath) {
-    loadConfig(_basepath);
-    ParseConfig();
-
-    document.getElementById("Category_Analog_enabled").checked = true;
-    ROIInfo = getROIInfo("[Analog]");
-
-    if (!GetAnalogEnabled()) 
-    {
-        document.getElementById("Category_Analog_enabled").checked = false;
-        EnDisableAnalog();
-        alert("Analog ROIs are disabled - please enable (Check box top left).\n");
-        return;
-    }
-
-    UpdateROIs();
 }
 }
-			
     
     
         function loadCanvas(dataURL) {
         function loadCanvas(dataURL) {
                 var canvas = document.getElementById('canvas');
                 var canvas = document.getElementById('canvas');
@@ -334,7 +362,10 @@ function ParseIni(_basepath) {
             canvas.addEventListener('mouseup', mouseUp, false);
             canvas.addEventListener('mouseup', mouseUp, false);
             canvas.addEventListener('mousemove', mouseMove, false);
             canvas.addEventListener('mousemove', mouseMove, false);
             loadCanvas(basepath + "/fileserver/config/reference.jpg");
             loadCanvas(basepath + "/fileserver/config/reference.jpg");
-            ParseIni(basepath);
+            loadConfig(basepath); 
+            ParseConfig();
+            param = getConfigParameters(); 
+            UpdateNUMBERS();
             drawImage();
             drawImage();
             draw();
             draw();
         }
         }
@@ -349,6 +380,66 @@ function ParseIni(_basepath) {
 //            context.restore();
 //            context.restore();
         }  
         }  
 
 
+function UpdateNUMBERS(_sel){
+    zw = getNUMBERInfo();
+
+    index = 0;
+
+    var _index = document.getElementById("Numbers_value1");
+    while (_index.length){
+        _index.remove(0);
+    }
+
+    for (var i = 0; i < zw.length; ++i){
+        var option = document.createElement("option");
+        option.text = zw[i]["name"];
+        option.value = i;
+        _index.add(option); 
+
+        if (typeof _sel !== 'undefined') {
+            if (zw[i]["name"] == _sel)
+                index = i
+        }
+    }
+    _index.selectedIndex = index;
+
+    UpdateROIs();
+}
+
+function renameNumber(){
+    var sel = document.getElementById("Numbers_value1");
+    var _delte= sel.options[sel.selectedIndex].text;
+    var _numbernew = prompt("Please enter new name", _delte);
+
+    erg = RenameNUMBER(_delte, _numbernew);
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateNUMBERS(_numbernew);
+}
+
+function newNumber(){
+    var _numbernew = prompt("Please enter name of new number", "name");
+
+    erg = CreateNUMBER(_numbernew);
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateNUMBERS(_numbernew);
+}
+
+
+function removeNumber(){
+	if (confirm("This will remove the number complete (analog and digital).\nIf you only want to remove the digital ROIs, please use \"Delete ROIs\".\nDo you want to proceed?")) {
+        var sel = document.getElementById("Numbers_value1");
+        var _delte= sel.options[sel.selectedIndex].text;
+        erg = DeleteNUMBER(_delte);
+        if (erg != "")
+            alert(erg);
+        UpdateNUMBERS();
+	}	    
+}
+
 
 
     function draw() {
     function draw() {
         var canvas = document.getElementById('canvas');
         var canvas = document.getElementById('canvas');
@@ -356,6 +447,26 @@ function ParseIni(_basepath) {
         context.drawImage(imageObj, 0, 0);
         context.drawImage(imageObj, 0, 0);
         if (document.getElementById("Category_Analog_enabled").checked)
         if (document.getElementById("Category_Analog_enabled").checked)
         {
         {
+            var sel = document.getElementById("index");
+            var _number = sel.selectedIndex;
+            for (var _nb = 0; _nb < ROIInfo.length; _nb++)
+            {
+                if (_nb != _number)
+                {
+                    lw = 1;
+                    context.lineWidth = lw;
+                    context.strokeStyle = "#990000";
+                    var x0 = parseInt(ROIInfo[_nb].x) - parseInt(lw/2);
+                    var y0 = parseInt(ROIInfo[_nb].y) - parseInt(lw/2);
+                    var dx = parseInt(ROIInfo[_nb].dx) + parseInt(lw);
+                    var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw);
+                    context.strokeRect(x0, y0, dx, dy);
+                }
+
+            }
+
+
+
             lw = 4
             lw = 4
             context.lineWidth = lw;
             context.lineWidth = lw;
             context.strokeStyle = "#FF0000";
             context.strokeStyle = "#FF0000";
@@ -483,6 +594,30 @@ function ParseIni(_basepath) {
         }
         }
     }
     }
 
 
+
+    function renameROI(){
+        var sel = document.getElementById("Numbers_value1");
+        var _number= sel.options[sel.selectedIndex].text;
+        sel = document.getElementById("index");
+        var _roialt= sel.options[sel.selectedIndex].text;
+
+
+        var _roinew = prompt("Please enter new name", _roialt);
+
+        erg = RenameROI(_number, "analog", _roialt, _roinew);
+        if (erg != "")
+            alert(erg);
+        else
+            UpdateROIs(_roinew);
+    }
+
+    function numberChanged()
+    {
+        UpdateROIs();
+    }    
+
+
+
     
     
     init();
     init();
 </script>
 </script>

+ 0 - 1
sd-card/html/edit_config.html

@@ -41,7 +41,6 @@ textarea {
 </table>
 </table>
 
 
 <script type="text/javascript" src="./gethost.js"></script> 
 <script type="text/javascript" src="./gethost.js"></script> 
-<script type="text/javascript" src="./readconfig.js"></script>  
 <script type="text/javascript" src="./readconfigcommon.js"></script>  
 <script type="text/javascript" src="./readconfigcommon.js"></script>  
  
  
 <script type="text/javascript">
 <script type="text/javascript">

Fișier diff suprimat deoarece este prea mare
+ 692 - 93
sd-card/html/edit_config_param.html


+ 188 - 55
sd-card/html/edit_digits.html

@@ -64,8 +64,24 @@ th, td {
 	  <tr>
 	  <tr>
 		<canvas id="canvas" crossorigin></canvas>
 		<canvas id="canvas" crossorigin></canvas>
 	  </tr>
 	  </tr>
-	</table>	
-			 
+	</table>
+    
+    <p>
+        <table>
+            <tr>
+                <class id="Numbers_text" style="color:black;"><b>Number:</b> </class>
+                <select id="Numbers_value1" onchange="numberChanged()">
+                    <option value="0" selected>default</option>
+                    <option value="1" >NT</option>
+                    <option value="2" >HT</option>
+                </select>
+                <input class="move" type="submit" id="renameNumber" name="renameNumber" onclick="renameNumber()" value="Rename">  
+                <input class="move" type="submit" id="newNumber" name="newNumber" onclick="newNumber()" value="New">  
+                <input class="move" type="submit" id="removeNumber" name="removeNumber" onclick="removeNumber()" value="Remove">
+            </tr>
+        </table>
+    </p>
+    
 	<table>
 	<table>
 	  <tr>
 	  <tr>
 		<td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI (after current)"></td>	  
 		<td><input class="button" type="submit" id="newROI" name="newROI" onclick="newROI()" value="New ROI (after current)"></td>	  
@@ -79,7 +95,8 @@ th, td {
 			  <option value="1" >ROI 1</option>
 			  <option value="1" >ROI 1</option>
 			</select>
 			</select>
 		</td>
 		</td>
-		<td>Name: <input type="text" name="name" id="name" onchange="onNameChange()" size="13"></td>
+		<td>                
+            <input class="button" type="submit" id="renameROI" name="renameROI" onclick="renameROI()" value="Rename">  
 		<td>
 		<td>
 		<input class="move" type="submit" id="moveNext" onclick="moveNext()" value="move Next">
 		<input class="move" type="submit" id="moveNext" onclick="moveNext()" value="move Next">
 		<input class="move" type="submit" id="movePrevious" onclick="movePrevious()" value="move Previous">  
 		<input class="move" type="submit" id="movePrevious" onclick="movePrevious()" value="move Previous">  
@@ -105,9 +122,10 @@ th, td {
 	</table>
 	</table>
 
 
 <script type="text/javascript" src="./gethost.js"></script> 
 <script type="text/javascript" src="./gethost.js"></script> 
-<script type="text/javascript" src="./readconfig.js"></script>  
-<script type="text/javascript" src="./readconfigcommon.js"></script>  
-<script type="text/javascript" src="./jquery-3.5.1.min.js"></script>  
+<script type="text/javascript" src="./readconfigcommon.js"></script>
+<script type="text/javascript" src="./readconfigparam.js"></script>  
+
+<script type="text/javascript" src="./jquery-3.6.0.min.js"></script>  
 
 
 <script language="JavaScript">
 <script language="JavaScript">
         var canvas = document.getElementById('canvas'),
         var canvas = document.getElementById('canvas'),
@@ -169,22 +187,23 @@ function deleteROI(){
     UpdateROIs();
     UpdateROIs();
 }
 }
 
 
-function newROI(){
-    var zw = ROIInfo[ROIInfo.length-1];
-    ROIInfo.push(zw);
-    for (var i = ROIInfo.length-2; i > aktindex + 1; --i){
-        ROIInfo[i] = ROIInfo[i-1];
-    }
-    aktindex++;
-    ROIInfo[aktindex] = new Object;
-    ROIInfo[aktindex]["pos_ref"] = -1;
-    ROIInfo[aktindex]["name"] = "ROI" + aktindex;
-    ROIInfo[aktindex]["x"] = 1;
-    ROIInfo[aktindex]["y"] = 1;
-    ROIInfo[aktindex]["dx"] = ROIInfo[aktindex-1]["dx"];
-    ROIInfo[aktindex]["dy"] = ROIInfo[aktindex-1]["dy"];
-    ROIInfo[aktindex]["ar"] = ROIInfo[aktindex-1]["ar"];
-    UpdateROIs();
+function newROI() {
+    var sel = document.getElementById("Numbers_value1");
+    var _number= sel.options[sel.selectedIndex].text;
+    sel = document.getElementById("index");
+    var _roialt= sel.options[sel.selectedIndex].text;
+
+    var _roinew = prompt("Please enter name of new ROI", "name");
+
+    if (ROIInfo.length > 0)
+        erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, ROIInfo[aktindex]["dx"], ROIInfo[aktindex]["dy"]);
+    else
+        erg = CreateROI(_number, "digit", sel.selectedIndex, _roinew, 1, 1, 30, 51);
+
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateROIs(_roinew);
 }
 }
 
 
 function movePrevious(){
 function movePrevious(){
@@ -214,34 +233,66 @@ function ChangeSelection(){
 }
 }
 
 
 function SaveToConfig(){
 function SaveToConfig(){
-    _enabled = document.getElementById("Category_Digits_enabled").checked;
-    SaveROIToConfig(ROIInfo, "[Digits]", basepath, _enabled);
-    UpdatePage();  
+    _zwcat = getConfigCategory();
+    _zwcat["Digits"]["enabled"] = document.getElementById("Category_Digits_enabled").checked;
+    WriteConfigININew();
+    SaveConfigToServer(basepath);    
 }
 }
 
 
 
 
-function UpdateROIs(){
+function UpdateROIs(_sel){
+    document.getElementById("Category_Digits_enabled").checked = true;
+    var sel = document.getElementById("Numbers_value1");
+    var _number = sel.options[sel.selectedIndex].text;
+
+    ROIInfo = getROIInfo("digit", _number);
+    _catzw = getConfigCategory();
+
+    if (_catzw["Digits"]["enabled"] == false) 
+    {
+        document.getElementById("Category_Digits_enabled").checked = false;
+        EnDisableDigits();
+        alert("Digital ROIs are disabled - please enable (Check box top left).\n");
+        return;
+    }
+
     if (ROIInfo.length == 0){
     if (ROIInfo.length == 0){
-        alert("There are no ROIs defined.\nPlease first define minimum one ROI in the config.ini by hand.\n");
-        document.getElementById("newROI").disabled = true;
+        alert("There are no ROIs defined.\nPlease first create a new ROI (\"New ROIs ...\").\n");
+        document.getElementById("newROI").disabled = false;
         document.getElementById("deleteROI").disabled = true;
         document.getElementById("deleteROI").disabled = true;
         document.getElementById("index").disabled = true;
         document.getElementById("index").disabled = true;
         document.getElementById("saveroi").disabled = true;
         document.getElementById("saveroi").disabled = true;
+        document.getElementById("renameROI").disabled = true;
         document.getElementById("moveNext").disabled = true;
         document.getElementById("moveNext").disabled = true;
         document.getElementById("movePrevious").disabled = true;
         document.getElementById("movePrevious").disabled = true;
         return;
         return;
     }
     }
+    else
+    {
+        document.getElementById("newROI").disabled = false;
+        document.getElementById("deleteROI").disabled = false;
+        document.getElementById("renameROI").disabled = false;
+        document.getElementById("index").disabled = false;
+        document.getElementById("saveroi").disabled = false;
+    }
 
 
     var _index = document.getElementById("index");
     var _index = document.getElementById("index");
     while (_index.length){
     while (_index.length){
         _index.remove(0);
         _index.remove(0);
     }
     }
 
 
+    if (aktindex > ROIInfo.length)
+        aktindex = ROIInfo.length;
+
     for (var i = 0; i < ROIInfo.length; ++i){
     for (var i = 0; i < ROIInfo.length; ++i){
         var option = document.createElement("option");
         var option = document.createElement("option");
-        option.text = "ROI " + (i + 1);
+        option.text = ROIInfo[i]["name"];
         option.value = i;
         option.value = i;
-        _index.add(option); 
+        _index.add(option);
+        if (typeof _sel !== 'undefined') {
+            if (option.text == _sel)
+                aktindex = i;
+        }
     }
     }
     _index.selectedIndex = aktindex; 
     _index.selectedIndex = aktindex; 
 
 
@@ -258,7 +309,6 @@ function UpdateROIs(){
     
     
     document.getElementById("lockAR").checked = lockAR;
     document.getElementById("lockAR").checked = lockAR;
        
        
-    document.getElementById("name").value = ROIInfo[aktindex]["name"];
     document.getElementById("refx").value = ROIInfo[aktindex]["x"];
     document.getElementById("refx").value = ROIInfo[aktindex]["x"];
     document.getElementById("refy").value = ROIInfo[aktindex]["y"];  
     document.getElementById("refy").value = ROIInfo[aktindex]["y"];  
     document.getElementById("refdx").value = ROIInfo[aktindex]["dx"];  
     document.getElementById("refdx").value = ROIInfo[aktindex]["dx"];  
@@ -269,26 +319,6 @@ function UpdateROIs(){
     rect.h = ROIInfo[aktindex]["dy"];
     rect.h = ROIInfo[aktindex]["dy"];
     draw();      
     draw();      
 }
 }
-
-function ParseIni(_basepath) {
-    loadConfig(_basepath);
-    ParseConfig();
-
-    document.getElementById("Category_Digits_enabled").checked = true;
-    ROIInfo = getROIInfo("[Digits]");
-
-    if (!GetDigitsEnabled()) 
-    {
-        document.getElementById("Category_Digits_enabled").checked = false;
-        EnDisableDigits();
-        alert("Digital ROIs are disabled - please enable (Check box top left).\n");
-        return;
-    }
-
-
-    UpdateROIs();
-}
-			
     
     
         function loadCanvas(dataURL) {
         function loadCanvas(dataURL) {
                 var canvas = document.getElementById('canvas');
                 var canvas = document.getElementById('canvas');
@@ -317,8 +347,6 @@ function ParseIni(_basepath) {
             var left = box.left + scrollLeft - clientLeft;
             var left = box.left + scrollLeft - clientLeft;
             return { top: Math.round(top), left: Math.round(left) };
             return { top: Math.round(top), left: Math.round(left) };
         }
         }
-   
-    
     
     
         function init() {
         function init() {
             basepath = getbasepath();
             basepath = getbasepath();
@@ -326,10 +354,14 @@ function ParseIni(_basepath) {
             canvas.addEventListener('mouseup', mouseUp, false);
             canvas.addEventListener('mouseup', mouseUp, false);
             canvas.addEventListener('mousemove', mouseMove, false);
             canvas.addEventListener('mousemove', mouseMove, false);
             loadCanvas(basepath + "/fileserver/config/reference.jpg");
             loadCanvas(basepath + "/fileserver/config/reference.jpg");
-            ParseIni(basepath);
+            loadConfig(basepath); 
+            ParseConfig();
+            param = getConfigParameters(); 
+            UpdateNUMBERS();
             drawImage();
             drawImage();
             draw();
             draw();
         }
         }
+
         function drawImage(){
         function drawImage(){
             var canvas = document.getElementById('canvas');
             var canvas = document.getElementById('canvas');
             var context = canvas.getContext('2d');
             var context = canvas.getContext('2d');
@@ -340,6 +372,66 @@ function ParseIni(_basepath) {
 //            context.restore();
 //            context.restore();
         }  
         }  
 
 
+function UpdateNUMBERS(_sel){
+    zw = getNUMBERInfo();
+
+    index = 0;
+
+    var _index = document.getElementById("Numbers_value1");
+    while (_index.length){
+        _index.remove(0);
+    }
+
+    for (var i = 0; i < zw.length; ++i){
+        var option = document.createElement("option");
+        option.text = zw[i]["name"];
+        option.value = i;
+        _index.add(option); 
+
+        if (typeof _sel !== 'undefined') {
+            if (zw[i]["name"] == _sel)
+                index = i
+        }
+    }
+    _index.selectedIndex = index;
+
+    UpdateROIs();
+}
+
+function renameNumber(){
+    var sel = document.getElementById("Numbers_value1");
+    var _delte= sel.options[sel.selectedIndex].text;
+    var _numbernew = prompt("Please enter new name", _delte);
+
+    erg = RenameNUMBER(_delte, _numbernew);
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateNUMBERS(_numbernew);
+}
+
+function newNumber(){
+    var _numbernew = prompt("Please enter name of new number", "name");
+
+    erg = CreateNUMBER(_numbernew);
+    if (erg != "")
+        alert(erg);
+    else
+        UpdateNUMBERS(_numbernew);
+}
+
+
+function removeNumber(){
+	if (confirm("This will remove the number complete (analog and digital).\nIf you only want to remove the digital ROIs, please use \"Delete ROIs\".\nDo you want to proceed?")) {
+        var sel = document.getElementById("Numbers_value1");
+        var _delte= sel.options[sel.selectedIndex].text;
+        erg = DeleteNUMBER(_delte);
+        if (erg != "")
+            alert(erg);
+        UpdateNUMBERS();
+	}	    
+}
+
 
 
 function draw() {
 function draw() {
         var canvas = document.getElementById('canvas');
         var canvas = document.getElementById('canvas');
@@ -347,6 +439,24 @@ function draw() {
         context.drawImage(imageObj, 0, 0);
         context.drawImage(imageObj, 0, 0);
         if (document.getElementById("Category_Digits_enabled").checked)
         if (document.getElementById("Category_Digits_enabled").checked)
         {
         {
+            var sel = document.getElementById("index");
+            var _number = sel.selectedIndex;
+            for (var _nb = 0; _nb < ROIInfo.length; _nb++)
+            {
+                if (_nb != _number)
+                {
+                    lw = 2;
+                    context.lineWidth = lw;
+                    context.strokeStyle = "#990000";
+                    var x0 = parseInt(ROIInfo[_nb].x) - parseInt(lw/2);
+                    var y0 = parseInt(ROIInfo[_nb].y) - parseInt(lw/2);
+                    var dx = parseInt(ROIInfo[_nb].dx) + parseInt(lw);
+                    var dy = parseInt(ROIInfo[_nb].dy) + parseInt(lw);
+                    context.strokeRect(x0, y0, dx, dy);
+                }
+
+            }
+
             lw = 4
             lw = 4
             context.lineWidth = lw;
             context.lineWidth = lw;
             context.strokeStyle = "#FF0000";
             context.strokeStyle = "#FF0000";
@@ -468,8 +578,31 @@ function draw() {
         }
         }
     }
     }
 
 
-    
+    function renameROI(){
+        var sel = document.getElementById("Numbers_value1");
+        var _number= sel.options[sel.selectedIndex].text;
+        sel = document.getElementById("index");
+        var _roialt= sel.options[sel.selectedIndex].text;
+
+
+        var _roinew = prompt("Please enter new name", _roialt);
+
+        erg = RenameROI(_number, "digit", _roialt, _roinew);
+        if (erg != "")
+            alert(erg);
+        else
+            UpdateROIs(_roinew);
+    }
+
+    function numberChanged()
+    {
+        UpdateROIs();
+    }    
+
+
+
     init();
     init();
+
 </script>
 </script>
 
 
 </body>
 </body>

+ 4 - 4
sd-card/html/edit_explain_6.html

@@ -63,10 +63,10 @@ p {font-size: 1em;}
             param = getConfigParameters();
             param = getConfigParameters();
             param["System"]["SetupMode"]["enabled"] = false;
             param["System"]["SetupMode"]["enabled"] = false;
             param["System"]["SetupMode"]["value1"] = "false";
             param["System"]["SetupMode"]["value1"] = "false";
-            setConfigParameters(param);
-            var textToSave = setConfigParameters(param);
-		    FileDeleteOnServer("/config/config.ini", basepath);
-		    FileSendContent(textToSave, "/config/config.ini", basepath);
+
+            WriteConfigININew();
+            SaveConfigToServer(basepath);    
+
 
 
             var stringota = "/reboot";
             var stringota = "/reboot";
             window.location = stringota;
             window.location = stringota;

+ 7 - 5
sd-card/html/edit_reference.html

@@ -53,7 +53,7 @@ table {
 	  </tr>
 	  </tr>
 	  <tr>
 	  <tr>
         <td><label for="mirror">Pre-rotate Angle:</label></td>	  
         <td><label for="mirror">Pre-rotate Angle:</label></td>	  
-		<td><input type="number" id="prerotateangle" name="prerotateangle" value=0 min="-360" max="360" onchange="drawRotated()">Degrees</td>
+		<td><input type="number" id="prerotateangle" name="prerotateangle" value="0" min="-360" max="360" onchange="drawRotated()">Degrees</td>
         <td>
         <td>
             <class id="MakeImage_Brightness_text" style="color:black;">Brightness: </class>
             <class id="MakeImage_Brightness_text" style="color:black;">Brightness: </class>
             <input type="number" id="MakeImage_Brightness_value1" size="13" value=0  min="-2" max="2" style="float: right; clear: both;">
             <input type="number" id="MakeImage_Brightness_value1" size="13" value=0  min="-2" max="2" style="float: right; clear: both;">
@@ -86,7 +86,6 @@ table {
 
 
 
 
     <script type="text/javascript" src="./gethost.js"></script> 
     <script type="text/javascript" src="./gethost.js"></script> 
-    <script type="text/javascript" src="./readconfig.js"></script>  
     <script type="text/javascript" src="./readconfigcommon.js"></script>  
     <script type="text/javascript" src="./readconfigcommon.js"></script>  
     <script type="text/javascript" src="./readconfigparam.js"></script>  
     <script type="text/javascript" src="./readconfigparam.js"></script>  
     
     
@@ -209,7 +208,11 @@ table {
                 param["Alignment"]["InitialRotate"].value1 = document.getElementById("prerotateangle").value;
                 param["Alignment"]["InitialRotate"].value1 = document.getElementById("prerotateangle").value;
 
 
                 if ((param["Alignment"]["InitialMirror"].found == true) && (document.getElementById("mirror").checked))
                 if ((param["Alignment"]["InitialMirror"].found == true) && (document.getElementById("mirror").checked))
+                {
                     param["Alignment"]["InitialMirror"].value1 = "true";
                     param["Alignment"]["InitialMirror"].value1 = "true";
+                    param["Alignment"]["InitialMirror"]["found"] = true;
+                    param["Alignment"]["InitialMirror"]["enabled"] = true;
+                }
                 else
                 else
                     param["Alignment"]["InitialMirror"].value1 = "false";
                     param["Alignment"]["InitialMirror"].value1 = "false";
 
 
@@ -228,9 +231,8 @@ table {
                 var canvas = document.getElementById("canvas");
                 var canvas = document.getElementById("canvas");
                 drawRotated(false);
                 drawRotated(false);
 
 
-                var textToSave = setConfigParameters(param);
-                FileDeleteOnServer("/config/config.ini", basepath);
-                FileSendContent(textToSave, "/config/config.ini", basepath);
+                WriteConfigININew();
+                SaveConfigToServer(basepath);    
 
 
                 SaveCanvasToImage(canvas, "/config/reference.jpg", true, basepath);
                 SaveCanvasToImage(canvas, "/config/reference.jpg", true, basepath);
                 showReference();
                 showReference();

+ 1 - 1
sd-card/html/explain_3.html

@@ -22,7 +22,7 @@ p {font-size: 1em;}
 <body style="font-family: arial">
 <body style="font-family: arial">
 
 
 <h4>Define Digits</h4>
 <h4>Define Digits</h4>
-Here you define your digits you want to read.
+Here you define your digits you want to read. If you have more than one number on the reading you can define several numbers with the <b>"Number"</b> selector. There you can also define new numbers.
 <p>
 <p>
     With the drop down menue <b>"ROI x"</b> you can change between the different digits. Mark them with the mouse or the coordinates.
     With the drop down menue <b>"ROI x"</b> you can change between the different digits. Mark them with the mouse or the coordinates.
     <br>
     <br>

+ 1 - 1
sd-card/html/explain_4.html

@@ -22,7 +22,7 @@ p {font-size: 1em;}
 <body style="font-family: arial">
 <body style="font-family: arial">
 
 
 <h4>Define Digits</h4>
 <h4>Define Digits</h4>
-Here you define your analog counters you want to read. If you do not have analog counters delete all ROIs.
+Here you define your analog counters you want to read. If you have more than one number on the reading you can define several numbers with the <b>"Number"</b> selector. There you can also define new numbers. If you do not have analog counters delete all ROIs.
 <p>
 <p>
     With the drop down menue <b>"ROI x"</b> you can change between the different counters. Mark them with the mouse or the coordinates.
     With the drop down menue <b>"ROI x"</b> you can change between the different counters. Mark them with the mouse or the coordinates.
     <br>
     <br>

+ 4 - 3
sd-card/html/gethost.js

@@ -5,11 +5,12 @@ function gethost_Version(){
 
 
 function getbasepath(){
 function getbasepath(){
     var host = window.location.hostname;
     var host = window.location.hostname;
-    if ((host == "127.0.0.1") || (host == "localhost"))
+    if ((host == "127.0.0.1") || (host == "localhost") || (host == ""))
     {
     {
-//        host = "http://192.168.2.118";          // jomjol interner test
-//        host = "http://192.168.178.26";          // jomjol interner test
+//        host = "http://192.168.2.219";          // jomjol interner test
+//        host = "http://192.168.178.46";          // jomjol interner test
         host = "http://192.168.178.22";          // jomjol interner Real
         host = "http://192.168.178.22";          // jomjol interner Real
+//        host = "http://192.168.43.191";
 //        host = ".";                           // jomjol interner localhost   
 //        host = ".";                           // jomjol interner localhost   
 
 
     }
     }

+ 17 - 0
sd-card/html/info.html

@@ -24,8 +24,25 @@ div {
 </head>
 </head>
 
 
 <body style="font-family: arial; padding: 0px 10px;">
 <body style="font-family: arial; padding: 0px 10px;">
+<h3>Current</h3>
+<table style="font-family: arial">
+	<tr>
+		<td>
+			Last restart:
+		</td>
+		<td>
+			<div id="gitbranch">
+				<object data="/starttime"></object>
+			</div>
+		</td>
+	</tr>
+	</table>
+
+
+<table style="font-family: arial">
 <h3>Host Info</h3>
 <h3>Host Info</h3>
 
 
+
 <table style="font-family: arial">
 <table style="font-family: arial">
 	<tr>
 	<tr>
 		<td>
 		<td>

Fișier diff suprimat deoarece este prea mare
+ 0 - 1
sd-card/html/jquery-3.5.1.min.js


Fișier diff suprimat deoarece este prea mare
+ 1 - 0
sd-card/html/jquery-3.6.0.min.js


+ 103 - 23
sd-card/html/prevalue_set.html

@@ -36,33 +36,23 @@ input[type=number] {
 	
 	
 </head>
 </head>
 
 
-<script src="/jquery-3.5.1.min.js"></script>
-<script>
-  $ (document).ready(function() {
-	$("#prevalue").load("/setPreValue.html");
-  });
-</script>
-
-<script>
-function setprevalue() {
-	var inputVal = document.getElementById("myInput").value;
-	inputVal = inputVal.replace(",", ".");
-	_value = "<object data=" + "/setPreValue.html?value=" + inputVal + " ></object>";
-	document.getElementById("result").innerHTML=_value;
-//	location.reload();	
-}
-</script>
-
 <body style="font-family: arial; padding: 0px 10px;">
 <body style="font-family: arial; padding: 0px 10px;">
 <h3>Set the previous value for consistency check and substitution for NaN</h3>
 <h3>Set the previous value for consistency check and substitution for NaN</h3>
 
 
+<class id="Numbers_text" style="font-size: 120%; color:black;"><b>Choose Number: </b>
+<select id="Numbers_value1" onchange="numberChanged()">
+	<option value="0" selected>default</option>
+	<option value="1" >NT</option>
+	<option value="2" >HT</option>
+</select>
+</class>
+
+
 <table style="width:100%">
 <table style="width:100%">
   <tr>
   <tr>
-    <h2>Current Value:</h2><p>
+    <h3>Current Value:</h3><p>
 	<div id="prevalue"></div>
 	<div id="prevalue"></div>
-  </tr>	 
-  <tr>
-  <h2>Set Value:</h2><p>
+  <h3>Set Value:</h3><p>
     Input (Format = 123.456):<p>
     Input (Format = 123.456):<p>
 	PreValue: 
 	PreValue: 
 	 <input type="number" id="myInput" name="myInput"
 	 <input type="number" id="myInput" name="myInput"
@@ -72,10 +62,100 @@ function setprevalue() {
 	<button class="button" type="button" onclick="setprevalue()">Set PreValue</button>
 	<button class="button" type="button" onclick="setprevalue()">Set PreValue</button>
   </tr>	
   </tr>	
   <tr>
   <tr>
-    <h2>Result:</h2><p>
+    <h3>Result:</h3><p>
 	<div id="result" readonly></div>
 	<div id="result" readonly></div>
   </tr>	 
   </tr>	 
 
 
 </table>
 </table>
 
 
-</body></html>
+</body></html>
+
+
+<script type="text/javascript" src="./gethost.js"></script> 
+<script type="text/javascript" src="./readconfigcommon.js"></script>  
+<script type="text/javascript" src="./readconfigparam.js"></script>  
+
+<script type="text/javascript">
+ 	var basepath = "http://192.168.178.22"; 
+  var	NUMBERS;
+
+function setprevalue() {
+	var inputVal = document.getElementById("myInput").value;
+	var sel = document.getElementById("Numbers_value1");
+	var _number = sel.options[sel.selectedIndex].text;  
+	inputVal = inputVal.replace(",", ".");
+  	var xhttp = new XMLHttpRequest();
+    try {
+          url = basepath + "/setPreValue.html?value=" + inputVal + "&numbers=" + _number;     
+          xhttp.open("GET", url, false);
+          xhttp.send();
+          response = xhttp.responseText;
+          document.getElementById("result").innerHTML=response;
+     }
+     catch (error)
+     {
+     //          alert("Deleting Config.ini failed");
+     }
+}
+
+function loadPrevalue(_basepath) {
+    var sel = document.getElementById("Numbers_value1");
+    var _number = sel.options[sel.selectedIndex].text;  
+
+     var xhttp = new XMLHttpRequest();
+     try {
+          url = _basepath + '/setPreValue.html?numbers=' + _number;     
+          xhttp.open("GET", url, false);
+          xhttp.send();
+          response = xhttp.responseText;
+          document.getElementById("prevalue").innerHTML=response;
+     }
+     catch (error)
+     {
+     //          alert("Deleting Config.ini failed");
+     }
+     return true;
+}
+
+
+function numberChanged(){
+  loadPrevalue(basepath);
+}
+
+function UpdateNUMBERS(_sel){
+    zw = getNUMBERInfo();
+
+    index = 0;
+
+    var _index = document.getElementById("Numbers_value1");
+    while (_index.length){
+        _index.remove(0);
+    }
+
+    for (var i = 0; i < zw.length; ++i){
+        var option = document.createElement("option");
+        option.text = zw[i]["name"];
+        option.value = i;
+        _index.add(option); 
+
+        if (typeof _sel !== 'undefined') {
+            if (zw[i]["name"] == _sel)
+                index = i
+        }
+    }
+    _index.selectedIndex = index;
+
+    loadPrevalue(basepath);
+}
+
+
+function init(){
+	basepath = getbasepath();
+  loadConfig(basepath); 
+  ParseConfig();
+  UpdateNUMBERS();
+  loadPrevalue(basepath);
+}
+
+init();
+</script>

+ 0 - 427
sd-card/html/readconfig.js

@@ -1,427 +0,0 @@
-function readconfig_Version(){
-     return "1.0.0 - 20200910";
- }
-
-var config_gesamt;
-var config_split;
-var ref = new Array(2);
-var digit = new Array(0);
-var analog = new Array(0);
-var initalrotate = new Object();
-var analogEnabled = false;
-var posAnalogHeader;
-var digitsEnabled = false;
-var posDigitsHeader;
-
-function MakeRefZW(zw, _basepath){
-     _filetarget = zw["name"].replace("/config/", "/img_tmp/");
-     _filetarget = _filetarget.replace(".jpg", "_org.jpg");
-     url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out="+_filetarget+"&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
-     var xhttp = new XMLHttpRequest();  
-     try {
-          xhttp.open("GET", url, false);
-          xhttp.send();     }
-     catch (error)
-     {
-//          alert("Deleting Config.ini failed");
-     }
-     _filetarget2 = zw["name"].replace("/config/", "/img_tmp/");
-//     _filetarget2 = _filetarget2.replace(".jpg", "_org.jpg");
-     FileCopyOnServer(_filetarget, _filetarget2, _basepath);
-}
-
-function CopyReferenceToImgTmp(_basepath)
-{
-     for (index = 0; index < 2; ++index)
-     {
-          _filenamevon = ref[index]["name"];
-          _filenamenach = _filenamevon.replace("/config/", "/img_tmp/");
-          FileDeleteOnServer(_filenamenach, _basepath);
-          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
-     
-          _filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
-          _filenamenach = _filenamenach.replace(".jpg", "_org.jpg");
-          FileDeleteOnServer(_filenamenach, _basepath);
-          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
-     }
-}
-
-function GetReferencesInfo(){
-     return ref;
-}
-
-function ParseConfigAlignment(_aktline){
-     var akt_ref = 0;
-     ++_aktline;
-
-     while ((_aktline < config_split.length) 
-            && !(config_split[_aktline][0] == "[") 
-            && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) {
-          var linesplit = ZerlegeZeile(config_split[_aktline]);
-          if ((linesplit[0].toUpperCase() == "INITIALMIRROR") && (linesplit.length > 1))
-          {
-              initalrotate["mirror"] = linesplit[1].toUpperCase().localeCompare("TRUE") == 0;
-              initalrotate["pos_config_mirror"] = _aktline;
-          }          
-
-          if (((linesplit[0].toUpperCase() == "INITALROTATE") || (linesplit[0].toUpperCase() == "INITIALROTATE"))  && (linesplit.length > 1))
-          {
-              initalrotate["angle"] = parseInt(linesplit[1]);
-              initalrotate["pos_config"] = _aktline;
-          }          
-          if (linesplit.length == 3)
-          {
-               ref[akt_ref] = new Object();
-               ref[akt_ref]["pos_ref"] = _aktline;
-               ref[akt_ref]["name"] = linesplit[0];
-               ref[akt_ref]["x"] = linesplit[1];
-               ref[akt_ref]["y"] = linesplit[2];
-               akt_ref++;
-          }
-          ++_aktline;
-     }    
-     return _aktline; 
-}
-
-function ParseConfigDigit(_aktline){
-     ++_aktline;
-     digit.length = 0;
-
-     while ((_aktline < config_split.length) 
-            && !(config_split[_aktline][0] == "[") 
-            && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) {
-          var linesplit = ZerlegeZeile(config_split[_aktline]);
-          if (linesplit.length >= 5)
-          {
-               zw = new Object();
-               zw["pos_ref"] = _aktline;
-               zw["name"] = linesplit[0];
-               zw["x"] = linesplit[1];
-               zw["y"] = linesplit[2];
-               zw["dx"] = linesplit[3];
-               zw["dy"] = linesplit[4];
-               zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]);
-               digit.push(zw);
-          }
-          ++_aktline;
-     }    
-     return _aktline; 
-}
-
-function GetAnalogEnabled() {
-     return analogEnabled;
-}
-
-
-function GetDigitsEnabled() {
-     return digitsEnabled;
-}
-
-
-function ParseConfigAnalog(_aktline){
-     ++_aktline;
-     analog.length = 0;
-
-     while ((_aktline < config_split.length) 
-            && !(config_split[_aktline][0] == "[") 
-            && !((config_split[_aktline][0] == ";") && (config_split[_aktline][1] == "["))) {
-          var linesplit = ZerlegeZeile(config_split[_aktline]);
-          if (linesplit.length >= 5)
-          {
-               zw = new Object();
-               zw["pos_ref"] = _aktline;
-               zw["name"] = linesplit[0];
-               zw["x"] = linesplit[1];
-               zw["y"] = linesplit[2];
-               zw["dx"] = linesplit[3];
-               zw["dy"] = linesplit[4];
-               zw["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]);
-               analog.push(zw);
-          }
-          ++_aktline;
-     }    
-     return _aktline; 
-}
-
-
-function getROIInfo(_typeROI){
-     if (_typeROI == "[Digits]"){
-          targetROI = digit;
-     }
-     if (_typeROI == "[Analog]"){
-          targetROI = analog;
-     }
-     return targetROI.slice();         // Kopie senden, nicht orginal!!!
-}
-
-function SaveROIToConfig(_ROIInfo, _typeROI, _basepath, _enabled){
-     if (_enabled) {
-          text = _typeROI;
-     }
-     else {
-          text = ";" + _typeROI;
-     }
-
-     if (_typeROI == "[Digits]"){
-          config_split[posDigitsHeader] = text;
-          targetROI = digit;
-     }
-
-     if (_typeROI == "[Analog]"){
-          config_split[posAnalogHeader] = text;
-          targetROI = analog;
-     }
-
-     // Abstimmen Anzahl ROIs:
-     var _pos = targetROI[targetROI.length-1]["pos_ref"];
-
-     for (var i = targetROI.length; i < _ROIInfo.length; ++i){
-          var zw = config_split[config_split.length-1];
-          config_split.push(zw);
-          for (var j = config_split.length-2; j > _pos + 1; --j){
-               config_split[j] = config_split[j-1];
-          }
-     }
-
-     for (i = targetROI.length-1; i > _ROIInfo.length-1; --i){
-          var _zwpos = targetROI[i]["pos_ref"];
-          config_split.splice(_zwpos, 1);
-     }
-
-     var linewrite = 0;
-     for (i = 0; i < _ROIInfo.length; ++i){
-          if (i < targetROI.length){
-               linewrite = targetROI[i]["pos_ref"];
-          }
-          else {
-               linewrite++;
-          }
-          config_split[linewrite] = _ROIInfo[i]["name"] + " " + _ROIInfo[i]["x"] + " " + _ROIInfo[i]["y"] + " " + _ROIInfo[i]["dx"] + " " + _ROIInfo[i]["dy"];
-     }
-
-     SaveConfigToServer(_basepath);
-}
-
-
-function ParseConfig() {
-     config_split = config_gesamt.split("\n");
-     var aktline = 0;
-
-     while (aktline < config_split.length){
-          if ((config_split[aktline].trim().toUpperCase() == "[ALIGNMENT]") || (config_split[aktline].trim().toUpperCase() == ";[ALIGNMENT]")){
-               aktline = ParseConfigAlignment(aktline);
-               continue;
-          }
-          if ((config_split[aktline].trim().toUpperCase() == "[DIGITS]") || (config_split[aktline].trim().toUpperCase() == ";[DIGITS]")){
-               posDigitsHeader = aktline;
-               if (config_split[aktline][0] == "[") {
-                    digitsEnabled = true;
-               }
-               aktline = ParseConfigDigit(aktline);
-               continue;
-          }
-
-          if ((config_split[aktline].trim().toUpperCase() == "[ANALOG]") || (config_split[aktline].trim().toUpperCase() == ";[ANALOG]")) {
-               posAnalogHeader = aktline;
-               if (config_split[aktline][0] == "[") {
-                    analogEnabled = true;
-               }
-               aktline = ParseConfigAnalog(aktline);
-               continue;
-          }
-
-          aktline++;
-     }
-}
-
-function getPreRotate(){
-     return initalrotate["angle"];
-}
-
-function setPreRotate(_prerotate){
-     initalrotate["angle"] = _prerotate;
-}
-
-function getMirror(){
-     if (initalrotate.hasOwnProperty("mirror")) {
-          return initalrotate["mirror"];
-     }
-     return false;
-}
-
-function setMirror(_mirror){
-     initalrotate["mirror"] = _mirror;
-}
-
-function SaveCanvasToImage(_canvas, _filename, _delete = true, _basepath = ""){
-     var JPEG_QUALITY=0.8;
-     var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY);	
-     var rtn = dataURLtoBlob(dataUrl);
-
-     if (_delete) {
-          FileDeleteOnServer(_filename, _basepath);
-     }
-	
-     FileSendContent(rtn, _filename, _basepath);
-}
-
-function SaveConfigToServer(_basepath){
-     // leere Zeilen am Ende löschen
-     var zw = config_split.length - 1;
-     while (config_split[zw] == "") {
-          config_split.pop();
-     }
-
-     var config_gesamt = "";
-     for (var i = 0; i < config_split.length; ++i)
-     {
-          config_gesamt = config_gesamt + config_split[i] + "\n";
-     } 
-
-     FileDeleteOnServer("/config/config.ini", _basepath);
-
-     FileSendContent(config_gesamt, "/config/config.ini", _basepath);          
-}
-
-function UpdateConfigFileReferenceChange(_basepath){
-     for (var _index = 0; _index < ref.length; ++_index){
-          var zeile = ref[_index]["name"] + " " + ref[_index]["x"] + " " + ref[_index]["y"];
-          var _pos = ref[_index]["pos_ref"];
-          config_split[_pos] = zeile;          
-     }
-
-     zeile = "InitialRotate = " + initalrotate["angle"];
-     var _pos = initalrotate["pos_config"];
-     config_split[_pos] = zeile;
-
-     var mirror = false;
-     if (initalrotate.hasOwnProperty("mirror")) {
-          mirror = initalrotate["mirror"];
-     }
-     var mirror_pos = -1;
-     if (initalrotate.hasOwnProperty("pos_config_mirror")) {
-          mirror_pos = initalrotate["pos_config_mirror"];
-     }     
-     if (mirror_pos > -1) {
-          if (mirror) {
-               config_split[mirror_pos] = "InitialMirror = true";
-          }
-          else {
-               config_split[mirror_pos] = "InitialMirror = false";
-          }
-     }
-     else {
-          if (mirror) {       // neue Zeile muss an der richtigen Stelle eingefügt werden - hier direct nach [Alignment]
-               var aktline = 0;
-
-               while (aktline < config_split.length){
-                    if (config_split[aktline].trim() == "[Alignment]") {
-                         break;
-                    }
-                    aktline++
-               }
-
-               // fuege neue Zeile in config_split ein
-               var zw = config_split[config_split.length-1];
-               config_split.push(zw);
-               for (var j = config_split.length-2; j > aktline + 1; --j){
-                    config_split[j] = config_split[j-1];
-               }
-
-               config_split[aktline + 1] = "InitialMirror = True"
-          }
-     }
-
-     SaveConfigToServer(_basepath);
-}
-
-function UpdateConfigReference(zw, _basepath){
-     for (var index = 0; index < 2; ++index)
-     {
-          var zeile = zw[index]["name"] + " " + zw[index]["x"] + " " + zw[index]["y"];
-          var _pos = zw[index]["pos_ref"];
-          config_split[_pos] = zeile;
-
-          _filenamenach = ref[index]["name"];
-          _filenamevon = _filenamenach.replace("/config/", "/img_tmp/");
-          FileDeleteOnServer(_filenamenach, _basepath);
-          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
-     
-          _filenamenach = _filenamenach.replace(".jpg", "_org.jpg");
-          _filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
-          FileDeleteOnServer(_filenamenach, _basepath);
-          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
-
-     }
-
-     SaveConfigToServer(_basepath);
-}
-
-function MakeContrastImageZW(zw, _enhance, _basepath){
-     _filename = zw["name"].replace("/config/", "/img_tmp/");
-     url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
-     if (_enhance == true){
-          url = url + "&enhance=true";
-     }
-
-     var xhttp = new XMLHttpRequest();  
-     try {
-          xhttp.open("GET", url, false);
-          xhttp.send();     }
-     catch (error)
-     {
-//          alert("Deleting Config.ini failed");
-     }
-}
-
-
-function GetReferenceSize(name){
-     img = new Image();
-     var xhttp = new XMLHttpRequest();
-			
-     url = "http://192.168.178.22/fileserver" + name;
-     xhttp.open("GET", url, false);
-     xhttp.send();
-
-     var response = xhttp.responseText;
-     var binary = ""
-     
-     for (var responseText = xhttp.responseText, responseTextLen = responseText.length, binary = "", i = 0; i < responseTextLen; ++i) {
-          binary += String.fromCharCode(responseText.charCodeAt(i) & 255)
-        }
-     img.src = 'data:image/jpeg;base64,'+ window.btoa(binary);     
-
-     return [img.width, img.height];
-}
-
-	 
-function getConfig() {
-	return config_gesamt;
-     }
-     
-
-
-function dataURLtoBlob(dataurl) {
-     var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
-          bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
-     while(n--){
-          u8arr[n] = bstr.charCodeAt(n);
-     }
-     return new Blob([u8arr], {type:mime});
-     }	
-
-                    
-function SaveReferenceImage(_id_canvas, _filename, _doDelete, _basepath = ""){
-     if (_doDelete){
-          FileDeleteOnServer(_filename, _basepath);
-     }
-
-     var canvas = document.getElementById(_id_canvas);
-     var JPEG_QUALITY=0.8;
-     var dataUrl = canvas.toDataURL('image/jpeg', JPEG_QUALITY);	
-     var rtn = dataURLtoBlob(dataUrl);	
-     if (!FileSendContent(rtn, _filename, _basepath)){
-          alert("Error on saving reference image (" + _filename + ")!\nPlease retry.");
-          location.reload();  
-     };  
-}

+ 58 - 61
sd-card/html/readconfigcommon.js

@@ -20,65 +20,7 @@ function SaveConfigToServer(_basepath){
      FileSendContent(config_gesamt, "/config/config.ini", _basepath);          
      FileSendContent(config_gesamt, "/config/config.ini", _basepath);          
 }
 }
 
 
-function UpdateConfigFileReferenceChange(_basepath){
-     for (var _index = 0; _index < ref.length; ++_index){
-          var zeile = ref[_index]["name"] + " " + ref[_index]["x"] + " " + ref[_index]["y"];
-          var _pos = ref[_index]["pos_ref"];
-          config_split[_pos] = zeile;          
-     }
-
-     zeile = "InitialRotate = " + initalrotate["angle"];
-     var _pos = initalrotate["pos_config"];
-     config_split[_pos] = zeile;
-
-     var mirror = false;
-     if (initalrotate.hasOwnProperty("mirror")) {
-          mirror = initalrotate["mirror"];
-     }
-     var mirror_pos = -1;
-     if (initalrotate.hasOwnProperty("pos_config_mirror")) {
-          mirror_pos = initalrotate["pos_config_mirror"];
-     }     
-     if (mirror_pos > -1) {
-          if (mirror) {
-               config_split[mirror_pos] = "InitialMirror = true";
-          }
-          else {
-               config_split[mirror_pos] = "InitialMirror = false";
-          }
-     }
-     else {
-          if (mirror) {       // neue Zeile muss an der richtigen Stelle eingefügt werden - hier direct nach [Alignment]
-               var aktline = 0;
-
-               while (aktline < config_split.length){
-                    if (config_split[aktline].trim() == "[Alignment]") {
-                         break;
-                    }
-                    aktline++
-               }
-
-               // fuege neue Zeile in config_split ein
-               var zw = config_split[config_split.length-1];
-               config_split.push(zw);
-               for (var j = config_split.length-2; j > aktline + 1; --j){
-                    config_split[j] = config_split[j-1];
-               }
-
-               config_split[aktline + 1] = "InitialMirror = True"
-          }
-     }
-
-     SaveConfigToServer(_basepath);
-}
-
 function UpdateConfig(zw, _index, _enhance, _basepath){
 function UpdateConfig(zw, _index, _enhance, _basepath){
-     var zeile = zw["name"] + " " + zw["x"] + " " + zw["y"];
-     var _pos = ref[_index]["pos_ref"];
-     config_split[_pos] = zeile;
-
-     SaveConfigToServer(_basepath);
-
      var namezw = zw["name"];
      var namezw = zw["name"];
      FileCopyOnServer("/img_tmp/ref_zw.jpg", namezw, _basepath);
      FileCopyOnServer("/img_tmp/ref_zw.jpg", namezw, _basepath);
      var namezw = zw["name"].replace(".jpg", "_org.jpg");
      var namezw = zw["name"].replace(".jpg", "_org.jpg");
@@ -102,10 +44,10 @@ function createReader(file) {
 
 
 
 
 
 
-function ZerlegeZeile(input)
+function ZerlegeZeile(input, delimiter = " =\t\r")
      {
      {
           var Output = Array(0);
           var Output = Array(0);
-          delimiter = " =,\r";
+//          delimiter = " =,\t";
      
      
           input = trim(input, delimiter);
           input = trim(input, delimiter);
           var pos = findDelimiterPos(input, delimiter);
           var pos = findDelimiterPos(input, delimiter);
@@ -164,6 +106,11 @@ function trim(istring, adddelimiter)
      }
      }
      
      
 
 
+function getConfig()
+{
+     return config_gesamt;
+}
+
      
      
 function loadConfig(_basepath) {
 function loadConfig(_basepath) {
      var xhttp = new XMLHttpRequest();
      var xhttp = new XMLHttpRequest();
@@ -261,4 +208,54 @@ function FileSendContent(_content, _filename, _basepath = ""){
 //          alert("Deleting Config.ini failed");
 //          alert("Deleting Config.ini failed");
      }     
      }     
     return okay;        
     return okay;        
-}
+}
+
+
+function SaveCanvasToImage(_canvas, _filename, _delete = true, _basepath = ""){
+     var JPEG_QUALITY=0.8;
+     var dataUrl = _canvas.toDataURL('image/jpeg', JPEG_QUALITY);	
+     var rtn = dataURLtoBlob(dataUrl);
+
+     if (_delete) {
+          FileDeleteOnServer(_filename, _basepath);
+     }
+	
+     FileSendContent(rtn, _filename, _basepath);
+}
+
+function MakeContrastImageZW(zw, _enhance, _basepath){
+     _filename = zw["name"].replace("/config/", "/img_tmp/");
+     url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out=" + _filename + "&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
+     if (_enhance == true){
+          url = url + "&enhance=true";
+     }
+
+     var xhttp = new XMLHttpRequest();  
+     try {
+          xhttp.open("GET", url, false);
+          xhttp.send();     }
+     catch (error)
+     {
+//          alert("Deleting Config.ini failed");
+     }
+}
+
+
+
+function MakeRefZW(zw, _basepath){
+     _filetarget = zw["name"].replace("/config/", "/img_tmp/");
+     _filetarget = _filetarget.replace(".jpg", "_org.jpg");
+     url = _basepath + "/editflow.html?task=cutref&in=/config/reference.jpg&out="+_filetarget+"&x=" + zw["x"] + "&y="  + zw["y"] + "&dx=" + zw["dx"] + "&dy=" + zw["dy"];
+     var xhttp = new XMLHttpRequest();  
+     try {
+          xhttp.open("GET", url, false);
+          xhttp.send();     }
+     catch (error)
+     {
+//          alert("Deleting Config.ini failed");
+     }
+     _filetarget2 = zw["name"].replace("/config/", "/img_tmp/");
+//     _filetarget2 = _filetarget2.replace(".jpg", "_org.jpg");
+     FileCopyOnServer(_filetarget, _filetarget2, _basepath);
+}
+

+ 442 - 47
sd-card/html/readconfigparam.js

@@ -7,6 +7,8 @@ var config_split;
 var param;
 var param;
 var category;
 var category;
 var ref = new Array(2);
 var ref = new Array(2);
+var NUMBERS = new Array(0);
+var REFERENCES = new Array(0);
 
 
 function ParseConfig() {
 function ParseConfig() {
      config_split = config_gesamt.split("\n");
      config_split = config_gesamt.split("\n");
@@ -68,11 +70,11 @@ function ParseConfig() {
      category[catname]["enabled"] = false;
      category[catname]["enabled"] = false;
      category[catname]["found"] = false;
      category[catname]["found"] = false;
      param[catname] = new Object();
      param[catname] = new Object();
-     ParamAddValue(param, catname, "DecimalShift");
+     ParamAddValue(param, catname, "DecimalShift", 1, true);
      ParamAddValue(param, catname, "PreValueUse");
      ParamAddValue(param, catname, "PreValueUse");
      ParamAddValue(param, catname, "PreValueAgeStartup");
      ParamAddValue(param, catname, "PreValueAgeStartup");
      ParamAddValue(param, catname, "AllowNegativeRates");
      ParamAddValue(param, catname, "AllowNegativeRates");
-     ParamAddValue(param, catname, "MaxRateValue");
+     ParamAddValue(param, catname, "MaxRateValue", 1, true);
      ParamAddValue(param, catname, "ErrorMessage");
      ParamAddValue(param, catname, "ErrorMessage");
      ParamAddValue(param, catname, "CheckDigitIncreaseConsistency");     
      ParamAddValue(param, catname, "CheckDigitIncreaseConsistency");     
 
 
@@ -82,13 +84,23 @@ function ParseConfig() {
      category[catname]["found"] = false;
      category[catname]["found"] = false;
      param[catname] = new Object();
      param[catname] = new Object();
      ParamAddValue(param, catname, "Uri");
      ParamAddValue(param, catname, "Uri");
-     ParamAddValue(param, catname, "Topic");
-     ParamAddValue(param, catname, "TopicError");
-     ParamAddValue(param, catname, "TopicRate");
-     ParamAddValue(param, catname, "TopicTimeStamp");
+     ParamAddValue(param, catname, "MainTopic", 1, false, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]);
      ParamAddValue(param, catname, "ClientID");
      ParamAddValue(param, catname, "ClientID");
      ParamAddValue(param, catname, "user");
      ParamAddValue(param, catname, "user");
-     ParamAddValue(param, catname, "password");     
+     ParamAddValue(param, catname, "password");
+     
+     var catname = "GPIO";
+     category[catname] = new Object(); 
+     category[catname]["enabled"] = false;
+     category[catname]["found"] = false;
+     param[catname] = new Object();
+     ParamAddValue(param, catname, "MainTopicMQTT", 1, false, [/^([a-zA-Z0-9_-]+\/){0,10}[a-zA-Z0-9_-]+$/]);
+     ParamAddValue(param, catname, "IO0", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+     ParamAddValue(param, catname, "IO1", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+     ParamAddValue(param, catname, "IO3", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+     ParamAddValue(param, catname, "IO4", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+     ParamAddValue(param, catname, "IO12", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
+     ParamAddValue(param, catname, "IO13", 6, false, [null, null, /^[0-9]*$/, null, null, /^[a-zA-Z0-9_-]*$/]);
 
 
      var catname = "AutoTimer";
      var catname = "AutoTimer";
      category[catname] = new Object(); 
      category[catname] = new Object(); 
@@ -115,8 +127,9 @@ function ParseConfig() {
      ParamAddValue(param, catname, "TimeServer");         
      ParamAddValue(param, catname, "TimeServer");         
      ParamAddValue(param, catname, "AutoAdjustSummertime");
      ParamAddValue(param, catname, "AutoAdjustSummertime");
      ParamAddValue(param, catname, "Hostname");   
      ParamAddValue(param, catname, "Hostname");   
-     ParamAddValue(param, catname, "SetupMode");   
-
+     ParamAddValue(param, catname, "SetupMode"); 
+     
+     
      while (aktline < config_split.length){
      while (aktline < config_split.length){
           for (var cat in category) {
           for (var cat in category) {
                zw = cat.toUpperCase();
                zw = cat.toUpperCase();
@@ -136,16 +149,16 @@ function ParseConfig() {
      }
      }
 }
 }
 
 
-function ParamAddValue(param, _cat, _param, _anzParam = 1){
+function ParamAddValue(param, _cat, _param, _anzParam = 1, _isNUMBER = false, _checkRegExList = null){
      param[_cat][_param] = new Object(); 
      param[_cat][_param] = new Object(); 
      param[_cat][_param]["found"] = false;
      param[_cat][_param]["found"] = false;
      param[_cat][_param]["enabled"] = false;
      param[_cat][_param]["enabled"] = false;
      param[_cat][_param]["line"] = -1; 
      param[_cat][_param]["line"] = -1; 
-     param[_cat][_param]["anzParam"] = _anzParam;    
+     param[_cat][_param]["anzParam"] = _anzParam;
+     param[_cat][_param]["Numbers"] = _isNUMBER;
+     param[_cat][_param].checkRegExList = _checkRegExList;
 };
 };
 
 
-
-
 function ParseConfigParamAll(_aktline, _catname){
 function ParseConfigParamAll(_aktline, _catname){
      ++_aktline;
      ++_aktline;
 
 
@@ -156,6 +169,18 @@ function ParseConfigParamAll(_aktline, _catname){
           let [isCom, input] = isCommented(_input);
           let [isCom, input] = isCommented(_input);
           var linesplit = ZerlegeZeile(input);
           var linesplit = ZerlegeZeile(input);
           ParamExtractValueAll(param, linesplit, _catname, _aktline, isCom);
           ParamExtractValueAll(param, linesplit, _catname, _aktline, isCom);
+          if (!isCom && (linesplit.length == 5) && (_catname == 'Digits'))
+               ExtractROIs(input, "digit");
+          if (!isCom && (linesplit.length == 5) && (_catname == 'Analog'))
+               ExtractROIs(input, "analog");
+          if (!isCom && (linesplit.length == 3) && (_catname == 'Alignment'))
+          {
+               _newref = new Object();
+               _newref["name"] = linesplit[0];
+               _newref["x"] = linesplit[1];
+               _newref["y"] = linesplit[2];
+               REFERENCES.push(_newref);
+          }
 
 
           ++_aktline;
           ++_aktline;
      }    
      }    
@@ -177,14 +202,59 @@ function ParamExtractValue(_param, _linesplit, _catname, _paramname, _aktline, _
 
 
 function ParamExtractValueAll(_param, _linesplit, _catname, _aktline, _iscom){
 function ParamExtractValueAll(_param, _linesplit, _catname, _aktline, _iscom){
      for (var paramname in _param[_catname]) {
      for (var paramname in _param[_catname]) {
-          if ((_linesplit[0].toUpperCase() == paramname.toUpperCase()) && (_linesplit.length > _param[_catname][paramname]["anzParam"]))
+          _AktROI = "default";
+          _AktPara = _linesplit[0];
+          _pospunkt = _AktPara.indexOf (".");
+          if (_pospunkt > -1)
+          {
+               _AktROI = _AktPara.substring(0, _pospunkt);
+               _AktPara = _AktPara.substring(_pospunkt+1);
+          }
+          if (_AktPara.toUpperCase() == paramname.toUpperCase())
           {
           {
+               while (_linesplit.length <= _param[_catname][paramname]["anzParam"]) {
+                    _linesplit.push("");
+               }
+
                _param[_catname][paramname]["found"] = true;
                _param[_catname][paramname]["found"] = true;
                _param[_catname][paramname]["enabled"] = !_iscom;
                _param[_catname][paramname]["enabled"] = !_iscom;
                _param[_catname][paramname]["line"] = _aktline;
                _param[_catname][paramname]["line"] = _aktline;
-               for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) {
-                    _param[_catname][paramname]["value"+j] = _linesplit[j];
+               if (_param[_catname][paramname]["Numbers"] == true)         // möglicher Multiusage
+               {
+                    abc = getNUMBERS(_linesplit[0]);
+                    abc[_catname][paramname] = new Object;
+                    abc[_catname][paramname]["found"] = true;
+                    abc[_catname][paramname]["enabled"] = !_iscom;
+     
+                    for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) {
+                         abc[_catname][paramname]["value"+j] = _linesplit[j];
+                         }
+                    if (abc["name"] == "default")
+                    {
+                    for (_num in NUMBERS)         // wert mit Default belegen
+                         {
+                              if (NUMBERS[_num][_catname][paramname]["found"] == false)
+                              {
+                                   NUMBERS[_num][_catname][paramname]["found"] = true;
+                                   NUMBERS[_num][_catname][paramname]["enabled"] = !_iscom;
+                                   NUMBERS[_num][_catname][paramname]["line"] = _aktline;
+                                   for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) {
+                                        NUMBERS[_num][_catname][paramname]["value"+j] = _linesplit[j];
+                                        }
+
+                              }
+                         }
                     }
                     }
+               }
+               else
+               {
+                    _param[_catname][paramname]["found"] = true;
+                    _param[_catname][paramname]["enabled"] = !_iscom;
+                    _param[_catname][paramname]["line"] = _aktline;
+                         for (var j = 1; j <= _param[_catname][paramname]["anzParam"]; ++j) {
+                         _param[_catname][paramname]["value"+j] = _linesplit[j];
+                         }
+               }
           }
           }
      }
      }
 }
 }
@@ -193,54 +263,114 @@ function getConfigParameters() {
      return param;
      return param;
 }
 }
 
 
-function setConfigParameters(_param, _category = "") {
-     for (var cat in _param) {
-          for (var name in _param[cat]) {
-               param[cat][name]["found"] = _param[cat][name]["found"];
-               param[cat][name]["enabled"] = _param[cat][name]["enabled"];
-               param[cat][name]["line"] = _param[cat][name]["line"];
+function WriteConfigININew()
+{
+     // Cleanup empty NUMBERS
+     for (var j = 0; j < NUMBERS.length; ++j)
+     {
+          if ((NUMBERS[j]["digit"].length + NUMBERS[j]["analog"].length) == 0)
+          {
+               NUMBERS.splice(j, 1);
+          }
+     }
 
 
-               param[cat][name]["anzParam"] = _param[cat][name]["anzParam"];
-               for (var j = 1; j <= _param[cat][name]["anzParam"]; ++j) {
-                    param[cat][name]["value"+j] =  _param[cat][name]["value"+j];
-                    }
 
 
-               if (param[cat][name]["found"]) {
+
+     config_split = new Array(0);
+
+     for (var cat in param) {
+          text = "[" + cat + "]";
+          if (!category[cat]["enabled"]) {
+               text = ";" + text;
+          }
+          config_split.push(text);
+
+          for (var name in param[cat]) {
+               if (param[cat][name]["Numbers"])
+               {
+                    for (_num in NUMBERS)
+                    {
+                         text = NUMBERS[_num]["name"] + "." + name;
+
+                         var text = text + " =" 
+                         
+                         for (var j = 1; j <= param[cat][name]["anzParam"]; ++j) {
+                              if (!(typeof NUMBERS[_num][cat][name]["value"+j] == 'undefined'))
+                                   text = text + " " + NUMBERS[_num][cat][name]["value"+j];
+                              }
+                         if (!NUMBERS[_num][cat][name]["enabled"]) {
+                              text = ";" + text;
+                         }
+                         config_split.push(text);
+                    }
+               }
+               else
+               {
                     var text = name + " =" 
                     var text = name + " =" 
                     
                     
-                    for (var j = 1; j <= _param[cat][name]["anzParam"]; ++j) {
-                         text = text + " " + param[cat][name]["value"+j];
+                    for (var j = 1; j <= param[cat][name]["anzParam"]; ++j) {
+                         if (!(typeof param[cat][name]["value"+j] == 'undefined'))
+                              text = text + " " + param[cat][name]["value"+j];
                          }
                          }
                     if (!param[cat][name]["enabled"]) {
                     if (!param[cat][name]["enabled"]) {
                          text = ";" + text;
                          text = ";" + text;
                     }
                     }
-                    config_split[param[cat][name]["line"]] = text;
+                    config_split.push(text);
                }
                }
           }
           }
-     }
-
-     for (var cat in _category) {
-          if (category[cat]["found"])
+          if (cat == "Digits")
+          {
+               for (var _roi in NUMBERS)
+               {
+                    if (NUMBERS[_roi]["digit"].length > 0)
+                    {
+                         for (var _roiddet in NUMBERS[_roi]["digit"])
+                         {
+                              text = NUMBERS[_roi]["name"] + "." + NUMBERS[_roi]["digit"][_roiddet]["name"];
+                              text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["x"];
+                              text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["y"];
+                              text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dx"];
+                              text = text + " " + NUMBERS[_roi]["digit"][_roiddet]["dy"];
+                              config_split.push(text);
+                         }
+                    }
+               }
+          }
+          if (cat == "Analog")
           {
           {
-               category[cat]["enabled"] = _category[cat]["enabled"];
-               text = "[" + cat + "]";
-               if (!category[cat]["enabled"]) {
-                    text = ";" + text;
+               for (var _roi in NUMBERS)
+               {
+                    if (NUMBERS[_roi]["analog"].length > 0)
+                    {
+                         for (var _roiddet in NUMBERS[_roi]["analog"])
+                         {
+                              text = NUMBERS[_roi]["name"] + "." + NUMBERS[_roi]["analog"][_roiddet]["name"];
+                              text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["x"];
+                              text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["y"];
+                              text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dx"];
+                              text = text + " " + NUMBERS[_roi]["analog"][_roiddet]["dy"];
+                              config_split.push(text);
+                         }
+                    }
+               }
+          }
+          if (cat == "Alignment")
+          {
+               for (var _roi in REFERENCES)
+               {
+                    text = REFERENCES[_roi]["name"];
+                    text = text + " " + REFERENCES[_roi]["x"];
+                    text = text + " " + REFERENCES[_roi]["y"];
+                    config_split.push(text);
                }
                }
-               config_split[category[cat]["line"]] = text;
-
           }
           }
-     }
-     
-     config_gesamt = config_split[0];
-     for (var i = 1; i < config_split.length; ++i){
-          config_gesamt = config_gesamt + "\n" + config_split[i]; 
-     }
 
 
-     return config_gesamt;
+          config_split.push("");
+     }
 }
 }
 
 
 
 
+
 function isCommented(input)
 function isCommented(input)
      {
      {
           let isComment = false;
           let isComment = false;
@@ -275,6 +405,271 @@ function getConfig() {
 function getConfigCategory() {
 function getConfigCategory() {
      return category;
      return category;
 }
 }
+
+
+
+function ExtractROIs(_aktline, _type){
+     var linesplit = ZerlegeZeile(_aktline);
+     abc = getNUMBERS(linesplit[0], _type);
+     abc["pos_ref"] = _aktline;
+     abc["x"] = linesplit[1];
+     abc["y"] = linesplit[2];
+     abc["dx"] = linesplit[3];
+     abc["dy"] = linesplit[4];
+     abc["ar"] = parseFloat(linesplit[3]) / parseFloat(linesplit[4]);
+}
+
+
+function getNUMBERS(_name, _type, _create = true)
+{
+     _pospunkt = _name.indexOf (".");
+     if (_pospunkt > -1)
+     {
+          _digit = _name.substring(0, _pospunkt);
+          _roi = _name.substring(_pospunkt+1);
+     }
+     else
+     {
+          _digit = "default";
+          _roi = _name;
+     }
+
+     _ret = -1;
+
+     for (i = 0; i < NUMBERS.length; ++i)
+     {
+          if (NUMBERS[i]["name"] == _digit)
+               _ret = NUMBERS[i];
+     }
+
+     if (!_create)         // nicht gefunden und soll auch nicht erzeugt werden, ggf. geht eine NULL zurück
+          return _ret;
+
+     if (_ret == -1)
+     {
+          _ret = new Object();
+          _ret["name"] = _digit;
+          _ret['digit'] = new Array();
+          _ret['analog'] = new Array();
+
+          for (_cat in param)
+               for (_param in param[_cat])
+                    if (param[_cat][_param]["Numbers"] == true){
+                         if (typeof  _ret[_cat] == 'undefined')
+                              _ret[_cat] = new Object();
+                         _ret[_cat][_param] = new Object();
+                         _ret[_cat][_param]["found"] = false;
+                         _ret[_cat][_param]["enabled"] = false;
+                         _ret[_cat][_param]["anzParam"] = param[_cat][_param]["anzParam"]; 
+
+                    }
+
+          NUMBERS.push(_ret);
+     }
+
+     if (typeof _type == 'undefined')             // muss schon existieren !!! - also erst nach Digits / Analog aufrufen
+          return _ret;
+
+     neuroi = new Object();
+     neuroi["name"] = _roi;
+     _ret[_type].push(neuroi);
+
+
+     return neuroi;
+
+}
+
+ 
+
+function CopyReferenceToImgTmp(_basepath)
+{
+     for (index = 0; index < 2; ++index)
+     {
+          _filenamevon = REFERENCES[index]["name"];
+          _filenamenach = _filenamevon.replace("/config/", "/img_tmp/");
+          FileDeleteOnServer(_filenamenach, _basepath);
+          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
+     
+          _filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
+          _filenamenach = _filenamenach.replace(".jpg", "_org.jpg");
+          FileDeleteOnServer(_filenamenach, _basepath);
+          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
+     }
+}
+
+function GetReferencesInfo(){
+     return REFERENCES;
+}
+
+
+function UpdateConfigReference(_basepath){
+     for (var index = 0; index < 2; ++index)
+     {
+          _filenamenach = REFERENCES[index]["name"];
+          _filenamevon = _filenamenach.replace("/config/", "/img_tmp/");
+          FileDeleteOnServer(_filenamenach, _basepath);
+          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
+     
+          _filenamenach = _filenamenach.replace(".jpg", "_org.jpg");
+          _filenamevon = _filenamevon.replace(".jpg", "_org.jpg");
+          FileDeleteOnServer(_filenamenach, _basepath);
+          FileCopyOnServer(_filenamevon, _filenamenach, _basepath);
+
+     }
+}
+
+
+function getNUMBERInfo(){
+     return NUMBERS;
+}
+
+function RenameNUMBER(_alt, _neu){
+     index = -1;
+     found = false;
+     for (i = 0; i < NUMBERS.length; ++i) {
+          if (NUMBERS[i]["name"] == _alt)
+               index = i;
+          if (NUMBERS[i]["name"] == _neu)
+               found = true;
+     }
+
+     if (found)
+          return "Name is already existing - please use another name";
+
+     NUMBERS[index]["name"] = _neu;
      
      
+     return "";
+}
+
+function DeleteNUMBER(_delte){
+     if (NUMBERS.length == 1)
+          return "The last number cannot be deleted."
+     
+
+     index = -1;
+     for (i = 0; i < NUMBERS.length; ++i) {
+          if (NUMBERS[i]["name"] == _delte)
+               index = i;
+     }
+
+     if (index > -1) {
+          NUMBERS.splice(index, 1);
+     }
+
+     return "";
+}
+
+function CreateNUMBER(_numbernew){
+     found = false;
+     for (i = 0; i < NUMBERS.length; ++i) {
+          if (NUMBERS[i]["name"] == _numbernew)
+               found = true;
+     }
+
+     if (found)
+          return "Name does already exist, please choose another one!";
+
+     _ret = new Object();
+     _ret["name"] = _numbernew;
+     _ret['digit'] = new Array();
+     _ret['analog'] = new Array();
+
+     for (_cat in param)
+          for (_param in param[_cat])
+               if (param[_cat][_param]["Numbers"] == true)
+               {
+                    if (typeof (_ret[_cat]) === "undefined")
+                    {
+                         _ret[_cat] = new Object();
+                    }
+                    _ret[_cat][_param] = new Object();
+                    _ret[_cat][_param]["found"] = false;
+                    _ret[_cat][_param]["enabled"] = false;
+                    _ret[_cat][_param]["anzParam"] = param[_cat][_param]["anzParam"]; 
+
+               }
+
+     NUMBERS.push(_ret);               
+     return "";
+}
+
+
+function getROIInfo(_typeROI, _number){
+     index = 0;
+     for (var i = 0; i < NUMBERS.length; ++i)
+          if (NUMBERS[i]["name"] == _number)
+               index = i;
+
+     return NUMBERS[index][_typeROI];         
+}
+
+
+function RenameROI(_number, _type, _alt, _neu){
+     index = -1;
+     found = false;
+     _indexnumber = -1;
+     for (j = 0; j < NUMBERS.length; ++j)
+          if (NUMBERS[j]["name"] == _number)
+               _indexnumber = j;
+
+     for (i = 0; i < NUMBERS[_indexnumber][_type].length; ++i) {
+          if (NUMBERS[_indexnumber][_type][i]["name"] == _alt)
+               index = i;
+          if (NUMBERS[_indexnumber][_type][i]["name"] == _neu)
+               found = true;
+     }
+
+     if (found)
+          return "Name is already existing - please use another name";
+
+     NUMBERS[_indexnumber][_type][index]["name"] = _neu;
+     
+     return "";
+}
+
+function DeleteNUMBER(_delte){
+     if (NUMBERS.length == 1)
+          return "The last number cannot be deleted."
+     
+
+     index = -1;
+     for (i = 0; i < NUMBERS.length; ++i) {
+          if (NUMBERS[i]["name"] == _delte)
+               index = i;
+     }
+
+     if (index > -1) {
+          NUMBERS.splice(index, 1);
+     }
+
+     return "";
+}
+
+function CreateROI(_number, _type, _pos, _roinew, _x, _y, _dx, _dy){
+     _indexnumber = -1;
+     for (j = 0; j < NUMBERS.length; ++j)
+          if (NUMBERS[j]["name"] == _number)
+               _indexnumber = j;
+
+
+     found = false;
+     for (i = 0; i < NUMBERS.length; ++i) {
+          if (NUMBERS[_indexnumber][_type]["name"] == _roinew)
+               found = true;
+     }
+
+     if (found)
+          return "ROI does already exist, please choose another name!";
+
+     _ret = new Object();
+     _ret["name"] = _roinew;
+     _ret["x"] = _x;
+     _ret["y"] = _y;
+     _ret["dx"] = _dx;
+     _ret["dy"] = _dy;
+     _ret["ar"] = _dx / _dy;
 
 
+     NUMBERS[_indexnumber][_type].splice(_pos+1, 0, _ret);
 
 
+     return "";
+}

BIN
sd-card/html/sd-card - Verknüpfung.lnk


+ 32 - 0
sd-card/html/test.html

@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+</head>
+
+<body style="font-family: arial">
+	testschrift
+  <div id="value"></div>
+</html>
+
+<script type="text/javascript" src="./gethost.js"></script> 
+
+<script type="text/javascript">
+	var basepath = "http://192.168.178.22"; 
+	function testinit(){
+		basepath = getbasepath();
+		url = basepath + '/wasserzaehler.html?all=true';     
+		var xhttp = new XMLHttpRequest();
+		xhttp.onreadystatechange = function() {
+			if (this.readyState == 4 && this.status == 200) {
+			// Typical action to be performed when the document is ready:
+			document.getElementById("value").innerHTML = xhttp.responseText;
+			}
+		};
+		xhttp.open("GET", url, true);
+		xhttp.send();		
+	}
+
+	testinit();
+</script>
+</body>

+ 1 - 1
sd-card/html/version.txt

@@ -1 +1 @@
-6.8.0
+9.5.0

+ 107 - 57
sd-card/html/wasserzaehler_roi.html

@@ -7,7 +7,7 @@
 <style>
 <style>
 .tg  {border-collapse:collapse;border-spacing:0;width:100%;color: darkslategray;border: inset;height:585px;}
 .tg  {border-collapse:collapse;border-spacing:0;width:100%;color: darkslategray;border: inset;height:585px;}
 .tg td{font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
 .tg td{font-size:14px;padding:10px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;}
-.tg th{height: 55px;font-size:24px;font-weight:bold;text-align:left;padding:0px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;background-color:#f0f0f0}
+.tg th{height: 50px;font-size:24px;font-weight:bold;text-align:left;padding:0px 5px;border-style:solid;border-width:1px;overflow:hidden;word-break:normal;background-color:#f0f0f0}
 .tg .tg-1{width:77%;font-size:20px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}
 .tg .tg-1{width:77%;font-size:20px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}
 .tg .tg-2{font-size:20px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}
 .tg .tg-2{font-size:20px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}
 .tg .tg-3{height: 15px;font-size:14px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}		
 .tg .tg-3{height: 15px;font-size:14px;font-family:Arial, Helvetica, sans-serif !important;border: inset;}		
@@ -15,27 +15,72 @@
 
 
 </head>
 </head>
 
 
-<script src="/jquery-3.5.1.min.js"></script>
+<body style="font-family: arial">
 
 
-<script>
-	function addZero(i) {
+<table class="tg">
+  <tr>
+    <td class="tg-1" rowspan="9"><div id="img"></div></td>
+    <th class="th">Value:</th>
+  </tr>	
+  <tr>	
+    <td class="tg-2">
+	<div id="value"></div>
+	</td>	
+  </tr>
+  <tr>
+    <th class="th">Previous Value:</th>
+  </tr>	
+  <tr>	
+    <td class="tg-2">
+	<div id="prevalue"></div>
+	</td>	
+  </tr>
+
+  <tr>
+    <th class="th">Raw Value:</th>
+  </tr>	
+  <tr>	
+    <td class="tg-2">
+	<div id="raw"></div>
+	</td>	
+  </tr>
+  <tr>
+    <th class="th">Error:</th>
+  </tr>	
+  <tr>	
+    <td class="tg-2">
+	<div id="error"></div>
+	</td>	
+  </tr> 
+  <tr>	
+    <td class="tg-3">
+	<div id="timestamp" ></div>	
+	</td>	
+  </tr>    
+</table>
+
+</body>
+</html>
+
+<script src="/jquery-3.6.0.min.js"></script>
+<script type="text/javascript" src="./gethost.js"></script> 
+<script type="text/javascript" src="./readconfigcommon.js"></script> 
+<script type="text/javascript">
+
+function addZero(i) {
 	  if (i < 10) {
 	  if (i < 10) {
 		i = "0" + i;
 		i = "0" + i;
 	  }
 	  }
 	  return i;
 	  return i;
 	}
 	}
 
 
-	$ (document).ready(function() {
+	$(document).ready(function() {
 	var d = new Date();
 	var d = new Date();
 	var h = addZero(d.getHours());
 	var h = addZero(d.getHours());
 	var m = addZero(d.getMinutes());
 	var m = addZero(d.getMinutes());
 	var s = addZero(d.getSeconds());
 	var s = addZero(d.getSeconds());
 
 
 	$('#img').html('<img src="/img_tmp/alg_roi.jpg" style="max-height:555px; display:block; margin-left:auto;  margin-right:auto;"></img>');
 	$('#img').html('<img src="/img_tmp/alg_roi.jpg" style="max-height:555px; display:block; margin-left:auto;  margin-right:auto;"></img>');
-	$("#raw").load("/wasserzaehler.html?rawvalue=true");
-	$("#corrected").load("/wasserzaehler.html");
-	$("#checked").load("/setPreValue.html");
-	$("#start").load("/starttime");
 	$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
 	$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
 	refresh();
 	refresh();
 	});
 	});
@@ -50,58 +95,63 @@
 	var s = addZero(d.getSeconds());	
 	var s = addZero(d.getSeconds());	
 	// reassign the url to be like alg_roi.jpg?timestamp=456784512 based on timestamp
 	// reassign the url to be like alg_roi.jpg?timestamp=456784512 based on timestamp
 	$('#img').html('<img src="/img_tmp/alg_roi.jpg?timestamp='+ timestamp +'"max-height:555px; display:block; margin-left:auto;  margin-right:auto;"></img>');
 	$('#img').html('<img src="/img_tmp/alg_roi.jpg?timestamp='+ timestamp +'"max-height:555px; display:block; margin-left:auto;  margin-right:auto;"></img>');
-	$("#raw").load("/wasserzaehler.html?rawvalue=true");
-	$("#corrected").load("/wasserzaehler.html");
-	$("#checked").load("/setPreValue.html");
-	$("#start").load("/starttime");
 	$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
 	$('#timestamp').html("Last Page Refresh:" + (h + ":" + m + ":" + s));
+	init();
 	  refresh();
 	  refresh();
 	}, 300000);
 	}, 300000);
+
   }
   }
-</script>
 
 
-<body style="font-family: arial">
+	var basepath = "http://192.168.178.22"; 
 
 
-<table class="tg">
-  <tr>
-    <td class="tg-1" rowspan="9"><div id="img"></div></td>
-    <th class="th">Raw Value:</th>
-  </tr>	
-  <tr>	
-    <td class="tg-2">
-	<div id="raw"></div>
-	</td>	
-  </tr>
-  <tr>
-    <th class="th">Corrected Value:</th>
-  </tr>	
-  <tr>	
-    <td class="tg-2">
-	<div id="corrected"></div>
-	</td>	
-  </tr>
-  <tr>
-    <th class="th">Checked Value:</th>
-  </tr>	
-  <tr>	
-    <td class="tg-2">
-	<div id="checked"></div>
-	</td>	
-  </tr> 
-   <tr>
-    <th class="th">Start Time:</th>
-  </tr>	
-  <tr>	
-    <td class="tg-2">
-	<div id="start"></div>	
-	</td>	
-  </tr> 
-  <tr>	
-    <td class="tg-3">
-	<div id="timestamp"></div>	
-	</td>	
-  </tr>    
-</table>
+	function loadValue(_type, _div, _style) {
+		url = basepath + '/wasserzaehler.html?all=true&type=' + _type;     
+		var xhttp = new XMLHttpRequest();
+		xhttp.onreadystatechange = function() {
+			if (this.readyState == 4 && this.status == 200) {
+			var _rsp = xhttp.responseText;
+			var _split = _rsp.split("\r");
+			if (typeof _style == undefined)
+				out = "<table>";
+			else
+				out = "<table style=\"" + _style + "\">";
 
 
-</body>
-</html>
+			if (_split.length == 1)
+			{
+				var _zer = ZerlegeZeile(_split[0], "\t")
+				if (_zer.length > 1)
+					out = _zer[1]; 
+				else
+					out = ""; 
+			}
+			else
+			{
+				for (var j = 0; j < _split.length; ++j)
+				{
+					var _zer = ZerlegeZeile(_split[j], "\t")
+					if (_zer.length == 1)
+						out = out + "<tr><td>" + _zer[0] + "</td><td> </td></tr>"; 
+					else
+						out = out + "<tr><td>" + _zer[0] + "</td><td>" + _zer[1] + "</td></tr>"; 
+				}
+				out = out + "</table>"
+
+				}
+			document.getElementById(_div).innerHTML = out;
+			}
+		};
+		xhttp.open("GET", url, true);
+		xhttp.send();		
+	}
+
+	function init(){
+		basepath = getbasepath();
+		loadValue("value", "value");
+		loadValue("raw", "raw");
+		loadValue("prevalue", "prevalue");
+		loadValue("error", "error", "font-size:8px");
+	}
+
+	init();
+
+</script>

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff