diff --git a/README.md b/README.md index 8fb9cdbc..f7494e64 100644 --- a/README.md +++ b/README.md @@ -23,30 +23,68 @@ If you would like to support the developer with a cup of coffee you can do that + +## Donate + +------ + +If you would like to support the developer with a cup of coffee you can do that via [Paypal](https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL). + +
+ + + +
+ + ## Change log ------ ### Known Issues -* Reboot on extensive web access due to the limits of the internal web server +* slow response of web server during picture analysis ------ **General remark:** Beside the `firmware.bin`, typically also the content of `/html` needs to be updated! + + +##### 6.0.0 Image Processing in Memory - (2021-01-02) + +* **Major change**: image processing fully in memory - no need of SD card buffer anymore + + * Need to limit camera resolution to VGA (due to memory limits) + +* MQTT: Last Will Testament (LWT) implemented: "connection lost" in case of connection lost to `TopicError` + +* Disabled `CheckDigitIncreaseConsistency` in default configuration - must now be explicit enabled if needed + +* Update digital CNN to v7.2.1 (additional digital images trained) + +* Setting of arbitrary time server in `config.ini` + +* Option for fixed IP-, DNS-Settings in `wlan.ini` + +* Increased stability (internal image and camera handling) + +* Bug fixing: edit digits, handling PreValue, html-bugs + + + ##### 5.0.0 Setup Modus - (2020-12-06) * Implementation of intial setup modus for fresh installation * Code restructuring (full compatibility between pure ESP-IDF and Platformio w/ espressif) + ##### 4.1.1 Configuration editor - (2020-12-02) * Bug fixing: internal improvement of file handling (reduce not responding) - ##### 4.1.0 Configuration editor - (2020-11-30) @@ -62,7 +100,6 @@ If you would like to support the developer with a cup of coffee you can do that * Bug fixing: truncation error, CheckDigitConsistency & PreValue implementation - ##### 4.0.0 Tflite Core - (2020-11-15) diff --git a/code/components/connect_wlan/connect_wlan.cpp b/code/components/connect_wlan/connect_wlan.cpp index 432d9698..1af2bf63 100644 --- a/code/components/connect_wlan/connect_wlan.cpp +++ b/code/components/connect_wlan/connect_wlan.cpp @@ -232,7 +232,7 @@ void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphra FILE* pFile; fn = FormatFileName(fn); - pFile = fopen(fn.c_str(), "r"); + pFile = OpenFileAndWait(fn.c_str(), "r"); printf("file loaded\n"); @@ -270,7 +270,48 @@ void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphra } } -/* + if (fgets(zw, 1024, pFile) == NULL) + { + line = ""; + } + else + { + line = std::string(zw); + } + } + + fclose(pFile); + + // Check if Hostname was empty in .ini if yes set to std_hostname + if(_hostname.length() <= 0){ + _hostname = std_hostname; + } +} + +void LoadNetConfigFromFile(std::string fn, std::string &_ip, std::string &_gw, std::string &_netmask, std::string &_dns) +{ + string line = ""; + std::vector zerlegt; + + FILE* pFile; + fn = FormatFileName(fn); + pFile = OpenFileAndWait(fn.c_str(), "r"); + + printf("file loaded\n"); + + if (pFile == NULL) + return; + + char zw[1024]; + fgets(zw, 1024, pFile); + line = std::string(zw); + + while ((line.size() > 0) || !(feof(pFile))) + { + printf("%s", line.c_str()); + zerlegt = ZerlegeZeile(line, "="); + zerlegt[0] = trim(zerlegt[0], " "); + if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "IP")){ _ip = zerlegt[1]; if ((_ip[0] == '"') && (_ip[_ip.length()-1] == '"')){ @@ -298,8 +339,6 @@ void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphra _dns = _dns.substr(1, _dns.length()-2); } } -*/ - if (fgets(zw, 1024, pFile) == NULL) { @@ -312,11 +351,6 @@ void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphra } fclose(pFile); - - // Check if Hostname was empty in .ini if yes set to std_hostname - if(_hostname.length() <= 0){ - _hostname = std_hostname; - } } diff --git a/code/components/connect_wlan/connect_wlan.h b/code/components/connect_wlan/connect_wlan.h index 6e707d0f..066901ed 100644 --- a/code/components/connect_wlan/connect_wlan.h +++ b/code/components/connect_wlan/connect_wlan.h @@ -11,7 +11,7 @@ void initialise_wifi_fixed_ip(std::string _ip, std::string _gw, std::string _net void LoadWlanFromFile(std::string fn, std::string &_ssid, std::string &_passphrase, std::string &_hostname); -void LoadNetConfigFromFile(std::string &_ip, std::string &_gw, std::string &_netmask, std::string &_dns); +void LoadNetConfigFromFile(std::string fn, std::string &_ip, std::string &_gw, std::string &_netmask, std::string &_dns); std::string getHostname(); std::string getIPAddress(); diff --git a/code/components/jomjol_controlGPIO/CMakeLists.txt b/code/components/jomjol_controlGPIO/CMakeLists.txt new file mode 100644 index 00000000..c5ad1e71 --- /dev/null +++ b/code/components/jomjol_controlGPIO/CMakeLists.txt @@ -0,0 +1,9 @@ +FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) + +list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common) + +idf_component_register(SRCS ${app_sources} + INCLUDE_DIRS "." + REQUIRES esp_http_server jomjol_logfile) + + diff --git a/code/components/jomjol_controlGPIO/server_GPIO.cpp b/code/components/jomjol_controlGPIO/server_GPIO.cpp new file mode 100644 index 00000000..02bd4411 --- /dev/null +++ b/code/components/jomjol_controlGPIO/server_GPIO.cpp @@ -0,0 +1,123 @@ +#include +#include "string.h" + +#include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_system.h" +#include "esp_event.h" +#include "esp_log.h" +#include "driver/gpio.h" +//#include "errno.h" + +#include + +#include "server_GPIO.h" + +#include "ClassLogFile.h" + +#include "Helper.h" + +#define DEBUG_DETAIL_ON + +esp_err_t handler_switch_GPIO(httpd_req_t *req) +{ +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_switch_GPIO - Start"); +#endif + + LogFile.WriteToFile("handler_switch_GPIO"); + char _query[200]; + char _valueGPIO[30]; + char _valueStatus[30]; + std::string gpio, status, zw; + int gpionum = 0; + gpio_num_t gpio_num; + + if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) + { + printf("Query: "); printf(_query); printf("\n"); + + if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK) + { + printf("GPIO is found"); printf(_valueGPIO); printf("\n"); + gpio = std::string(_valueGPIO); + } + if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK) + { + printf("Status is found"); printf(_valueStatus); printf("\n"); + status = std::string(_valueStatus); + } + }; + + status = toUpper(status); + if (!(status == "HIGH") && !(status == "LOW")) + { + zw = "Status not valid: " + status;; + httpd_resp_sendstr_chunk(req, zw.c_str()); + httpd_resp_sendstr_chunk(req, NULL); + return ESP_OK; + } + + gpionum = stoi(gpio); + + // frei: 16; 12-15; 2; 4 + + switch (gpionum) { + case 2: + gpio_num = GPIO_NUM_2; + break; + case 4: + gpio_num = GPIO_NUM_4; + break; + case 12: + gpio_num = GPIO_NUM_12; + break; + case 13: + gpio_num = GPIO_NUM_13; + break; + case 14: + gpio_num = GPIO_NUM_14; + break; + case 15: + gpio_num = GPIO_NUM_15; + break; + case 16: + gpio_num = (gpio_num_t) 16; + break; + default: + zw = "GPIO" + std::to_string(gpionum) + " not support - only 2, 4, 12-16 free"; + httpd_resp_sendstr_chunk(req, zw.c_str()); + httpd_resp_sendstr_chunk(req, NULL); + return ESP_OK; + } + + // Init the GPIO + gpio_pad_select_gpio(gpio_num); + /* Set the GPIO as a push/pull output */ + gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT); + + if (status == "HIGH") + gpio_set_level(gpio_num, 1); + 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); + return ESP_OK; +}; + + + +void register_server_GPIO_uri(httpd_handle_t server) +{ + 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); +} diff --git a/code/components/jomjol_controlGPIO/server_GPIO.h b/code/components/jomjol_controlGPIO/server_GPIO.h new file mode 100644 index 00000000..f91e24c2 --- /dev/null +++ b/code/components/jomjol_controlGPIO/server_GPIO.h @@ -0,0 +1,10 @@ +#include + +#include + +//#include "ClassControllCamera.h" + +static const char *TAGPARTGPIO = "server_GPIO"; + +void register_server_GPIO_uri(httpd_handle_t server); + diff --git a/code/components/jomjol_controlcamera/ClassControllCamera.cpp b/code/components/jomjol_controlcamera/ClassControllCamera.cpp index b24c8831..dfd693a6 100644 --- a/code/components/jomjol_controlcamera/ClassControllCamera.cpp +++ b/code/components/jomjol_controlcamera/ClassControllCamera.cpp @@ -1,4 +1,5 @@ #include "ClassControllCamera.h" +#include "ClassLogFile.h" #include #include "driver/gpio.h" @@ -6,34 +7,11 @@ #include "esp_log.h" #include "Helper.h" -#include "CFindTemplate.h" +#include "CImageBasis.h" -// #include "camera_define.h" -///////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////// #define BOARD_ESP32CAM_AITHINKER -/** - * 2. Kconfig setup - * - * If you have a Kconfig file, copy the content from - * https://github.com/espressif/esp32-camera/blob/master/Kconfig into it. - * In case you haven't, copy and paste this Kconfig file inside the src directory. - * This Kconfig file has definitions that allows more control over the camera and - * how it will be initialized. - */ - -/** - * 3. Enable PSRAM on sdkconfig: - * - * CONFIG_ESP32_SPIRAM_SUPPORT=y - * - * More info on - * https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-esp32-spiram-support - */ - -// ================================ CODE ====================================== #include #include @@ -47,31 +25,10 @@ #include "esp_camera.h" -// WROVER-KIT PIN Map -#ifdef BOARD_WROVER_KIT +// #define DEBUG_DETAIL_ON -#define CAM_PIN_PWDN -1 //power down is not used -#define CAM_PIN_RESET -1 //software reset will be performed -#define CAM_PIN_XCLK 21 -#define CAM_PIN_SIOD 26 -#define CAM_PIN_SIOC 27 - -#define CAM_PIN_D7 35 -#define CAM_PIN_D6 34 -#define CAM_PIN_D5 39 -#define CAM_PIN_D4 36 -#define CAM_PIN_D3 19 -#define CAM_PIN_D2 18 -#define CAM_PIN_D1 5 -#define CAM_PIN_D0 4 -#define CAM_PIN_VSYNC 25 -#define CAM_PIN_HREF 23 -#define CAM_PIN_PCLK 22 - -#endif // ESP32Cam (AiThinker) PIN Map -#ifdef BOARD_ESP32CAM_AITHINKER #define CAM_PIN_PWDN (gpio_num_t) 32 #define CAM_PIN_RESET -1 //software reset will be performed @@ -91,8 +48,6 @@ #define CAM_PIN_HREF 23 #define CAM_PIN_PCLK 22 -#endif - static const char *TAG = "example:take_picture"; static camera_config_t camera_config = { @@ -115,12 +70,14 @@ static camera_config_t camera_config = { .pin_pclk = CAM_PIN_PCLK, //XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental) - .xclk_freq_hz = 20000000, +// .xclk_freq_hz = 20000000, // Orginalwert + .xclk_freq_hz = 5000000, // Test, um die Bildfehler los zu werden !!!! .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, .pixel_format = PIXFORMAT_JPEG, //YUV422,GRAYSCALE,RGB565,JPEG - .frame_size = FRAMESIZE_UXGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG + .frame_size = FRAMESIZE_VGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG +// .frame_size = FRAMESIZE_UXGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG @@ -128,14 +85,11 @@ static camera_config_t camera_config = { .fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG }; -///////////////////////////////////////////////////////////////////////////////////////////////// -///////////////////////////////////////////////////////////////////////////////////////////////// #include "driver/ledc.h" CCamera Camera; - #define FLASH_GPIO GPIO_NUM_4 #define BLINK_GPIO GPIO_NUM_33 @@ -145,8 +99,6 @@ typedef struct { } jpg_chunking_t; - -/////////////////////////////////////////////////////////////////////////////////////////////////////// #define LEDC_LS_CH2_GPIO (4) #define LEDC_LS_CH2_CHANNEL LEDC_CHANNEL_2 #define LEDC_LS_TIMER LEDC_TIMER_1 @@ -172,14 +124,6 @@ void test(){ - -//////////////////////////////////////////////////////////////////////////////////////////////////////// - - - - - - static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len){ jpg_chunking_t *j = (jpg_chunking_t *)arg; if(!index){ @@ -200,15 +144,144 @@ void CCamera::SetQualitySize(int qual, framesize_t resol) s->set_framesize(s, resol); ActualResolution = resol; ActualQuality = qual; + + if (resol == FRAMESIZE_QVGA) + { + image_height = 240; + image_width = 320; + } + if (resol == FRAMESIZE_VGA) + { + image_height = 480; + image_width = 640; + } + // No higher Mode than VGA, damit der Kameraspeicher ausreicht. +/* + if (resol == FRAMESIZE_SVGA) + { + image_height = 600; + image_width = 800; + } + if (resol == FRAMESIZE_XGA) + { + image_height = 768; + image_width = 1024; + } + if (resol == FRAMESIZE_SXGA) + { + image_height = 1024; + image_width = 1280; + } + if (resol == FRAMESIZE_UXGA) + { + image_height = 1200; + image_width = 1600; + } +*/ +} + + + +esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay) +{ + string ftype; + + uint8_t *zwischenspeicher = NULL; + + + LEDOnOff(true); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start"); +#endif + + if (delay > 0) + { + LightOnOff(true); + const TickType_t xDelay = delay / portTICK_PERIOD_MS; + vTaskDelay( xDelay ); + } + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn"); +#endif + + camera_fb_t * fb = esp_camera_fb_get(); + if (!fb) { + ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed"); + LEDOnOff(false); + return ESP_FAIL; + } + + int _size = fb->len; + zwischenspeicher = (uint8_t*) malloc(_size); + for (int i = 0; i < _size; ++i) + *(zwischenspeicher + i) = *(fb->buf + i); + esp_camera_fb_return(fb); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get"); +#endif + + LEDOnOff(false); + + if (delay > 0) + LightOnOff(false); + +// TickType_t xDelay = 1000 / portTICK_PERIOD_MS; +// vTaskDelay( xDelay ); // wait for power to recover + + uint8_t * buf = NULL; + + CImageBasis _zwImage; + _zwImage.LoadFromMemory(zwischenspeicher, _size); + free(zwischenspeicher); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LoadFromMemory"); +#endif + + stbi_uc* p_target; + stbi_uc* p_source; + int channels = 3; + int width = image_width; + int height = image_height; + +#ifdef DEBUG_DETAIL_ON + std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height); + _zw = _zw + " _zwImage: " + std::to_string((int) _zwImage.rgb_image) + " Size: " + std::to_string(_zwImage.width) + ", " + std::to_string(_zwImage.height); + LogFile.WriteToFile(_zw); +#endif + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_target = _Image->rgb_image + (channels * (y * width + x)); + p_source = _zwImage.rgb_image + (channels * (y * width + x)); + p_target[0] = p_source[0]; + p_target[1] = p_source[1]; + p_target[2] = p_source[2]; + } + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After Copy To Target"); +#endif + + free(buf); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done"); +#endif + + return ESP_OK; } esp_err_t CCamera::CaptureToFile(std::string nm, int delay) { -// nm = "/sdcard/josef_zw.bmp"; string ftype; - LEDOnOff(true); + LEDOnOff(true); // Abgeschaltet, um Strom zu sparen !!!!!! if (delay > 0) { @@ -224,13 +297,22 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay) return ESP_FAIL; } LEDOnOff(false); - + +#ifdef DEBUG_DETAIL_ON printf("w %d, h %d, size %d\n", fb->width, fb->height, fb->len); +#endif nm = FormatFileName(nm); + +#ifdef DEBUG_DETAIL_ON printf("Save Camera to : %s\n", nm.c_str()); +#endif + ftype = toUpper(getFileType(nm)); + +#ifdef DEBUG_DETAIL_ON printf("Filetype: %s\n", ftype.c_str()); +#endif uint8_t * buf = NULL; size_t buf_len = 0; @@ -255,7 +337,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay) } } - FILE * fp = fopen(nm.c_str(), "wb"); + FILE * fp = OpenFileAndWait(nm.c_str(), "wb"); if (fp == NULL) /* If an error occurs during the file creation */ { fprintf(stderr, "fopen() failed for '%s'\n", nm.c_str()); @@ -286,15 +368,29 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay) size_t fb_len = 0; int64_t fr_start = esp_timer_get_time(); + + LEDOnOff(true); + + if (delay > 0) + { + LightOnOff(true); + const TickType_t xDelay = delay / portTICK_PERIOD_MS; + vTaskDelay( xDelay ); + } + + fb = esp_camera_fb_get(); if (!fb) { ESP_LOGE(TAGCAMERACLASS, "Camera capture failed"); httpd_resp_send_500(req); return ESP_FAIL; } + + LEDOnOff(false); + res = httpd_resp_set_type(req, "image/jpeg"); if(res == ESP_OK){ - res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg"); + res = httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=raw.jpg"); } if(res == ESP_OK){ @@ -312,6 +408,12 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay) int64_t fr_end = esp_timer_get_time(); ESP_LOGI(TAGCAMERACLASS, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000)); + + if (delay > 0) + { + LightOnOff(false); + } + return res; } @@ -357,7 +459,9 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol printf("Query: "); printf(_query); printf("\n"); if (httpd_query_key_value(_query, "size", _size, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("Size: "); printf(_size); printf("\n"); +#endif if (strcmp(_size, "QVGA") == 0) resol = FRAMESIZE_QVGA; // 320x240 if (strcmp(_size, "VGA") == 0) @@ -369,11 +473,13 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol if (strcmp(_size, "SXGA") == 0) resol = FRAMESIZE_SXGA; // 1280x1024 if (strcmp(_size, "UXGA") == 0) - resol = FRAMESIZE_UXGA; // 1600x1200 + resol = FRAMESIZE_UXGA; // 1600x1200 } if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("Quality: "); printf(_qual); printf("\n"); +#endif qual = atoi(_qual); if (qual > 63) @@ -404,13 +510,13 @@ framesize_t CCamera::TextToFramesize(const char * _size) CCamera::CCamera() { +#ifdef DEBUG_DETAIL_ON printf("CreateClassCamera\n"); +#endif } esp_err_t CCamera::InitCam() { - printf("Init Flash\n"); - //power up the camera if PWDN pin is defined if(CAM_PIN_PWDN != -1){ // Init the GPIO gpio_pad_select_gpio(CAM_PIN_PWDN); diff --git a/code/components/jomjol_controlcamera/ClassControllCamera.h b/code/components/jomjol_controlcamera/ClassControllCamera.h index 7ccfae19..7e4dd6bb 100644 --- a/code/components/jomjol_controlcamera/ClassControllCamera.h +++ b/code/components/jomjol_controlcamera/ClassControllCamera.h @@ -10,12 +10,13 @@ #include "esp_camera.h" #include #include +#include "CImageBasis.h" #define CAMERA_MODEL_AI_THINKER -static const char *TAGCAMERACLASS = "server_part_camera"; +static const char *TAGCAMERACLASS = "server_part_camera"; class CCamera { @@ -24,6 +25,8 @@ class CCamera { framesize_t ActualResolution; public: + int image_height, image_width; + CCamera(); esp_err_t InitCam(); @@ -35,13 +38,11 @@ class CCamera { framesize_t TextToFramesize(const char * text); - esp_err_t CaptureToFile(std::string nm, int delay = 0); - + esp_err_t CaptureToBasisImage(CImageBasis *_Image, int delay = 0); }; extern CCamera Camera; - #endif \ No newline at end of file diff --git a/code/components/jomjol_controlcamera/server_camera.cpp b/code/components/jomjol_controlcamera/server_camera.cpp index 0904ea48..21eb9363 100644 --- a/code/components/jomjol_controlcamera/server_camera.cpp +++ b/code/components/jomjol_controlcamera/server_camera.cpp @@ -11,6 +11,9 @@ #define SCRATCH_BUFSIZE2 8192 char scratch2[SCRATCH_BUFSIZE2]; +//#define DEBUG_DETAIL_ON + + void PowerResetCamera(){ ESP_LOGD(TAGPARTCAMERA, "Resetting camera by power down line"); @@ -29,42 +32,72 @@ void PowerResetCamera(){ esp_err_t handler_lightOn(httpd_req_t *req) { - LogFile.WriteToFile("handler_lightOn"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_lightOn - Start"); printf("handler_lightOn uri:\n"); printf(req->uri); printf("\n"); +#endif + Camera.LightOnOff(true); const char* resp_str = (const char*) req->user_ctx; - httpd_resp_send(req, resp_str, strlen(resp_str)); + httpd_resp_send(req, resp_str, strlen(resp_str)); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_lightOn - Done"); +#endif + return ESP_OK; }; esp_err_t handler_lightOff(httpd_req_t *req) { - LogFile.WriteToFile("handler_lightOff"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_lightOff - Start"); printf("handler_lightOff uri:\n"); printf(req->uri); printf("\n"); +#endif Camera.LightOnOff(false); const char* resp_str = (const char*) req->user_ctx; httpd_resp_send(req, resp_str, strlen(resp_str)); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_lightOff - Done"); +#endif + return ESP_OK; }; esp_err_t handler_capture(httpd_req_t *req) { - LogFile.WriteToFile("handler_capture"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_capture - Start"); +#endif + int quality; framesize_t res; Camera.GetCameraParameter(req, quality, res); + +#ifdef DEBUG_DETAIL_ON printf("Size: %d", res); printf(" Quality: %d\n", quality); +#endif + Camera.SetQualitySize(quality, res); esp_err_t ressult; ressult = Camera.CaptureToHTTP(req); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_capture - Done"); +#endif + return ressult; }; esp_err_t handler_capture_with_ligth(httpd_req_t *req) { + + LogFile.WriteHeapInfo("handler_capture_with_ligth - Start"); + LogFile.WriteToFile("handler_capture_with_ligth"); char _query[100]; char _delay[10]; @@ -78,7 +111,9 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req) printf("Query: "); printf(_query); printf("\n"); if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK) { - printf("Delay: "); printf(_delay); printf("\n"); +#ifdef DEBUG_DETAIL_ON + printf("Delay: "); printf(_delay); printf("\n"); +#endif delay = atoi(_delay); if (delay < 0) @@ -87,9 +122,12 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req) }; Camera.GetCameraParameter(req, quality, res); - printf("Size: %d", res); printf(" Quality: %d\n", quality); - Camera.SetQualitySize(quality, res); +#ifdef DEBUG_DETAIL_ON + printf("Size: %d", res); printf(" Quality: %d\n", quality); +#endif + + Camera.SetQualitySize(quality, res); Camera.LightOnOff(true); const TickType_t xDelay = delay / portTICK_PERIOD_MS; vTaskDelay( xDelay ); @@ -98,7 +136,11 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req) ressult = Camera.CaptureToHTTP(req); Camera.LightOnOff(false); - + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_capture_with_ligth - Done"); +#endif + return ressult; }; @@ -106,7 +148,10 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req) esp_err_t handler_capture_save_to_file(httpd_req_t *req) { - LogFile.WriteToFile("handler_capture_save_to_file"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_capture_save_to_file - Start"); +#endif + char _query[100]; char _delay[10]; int delay = 0; @@ -123,14 +168,18 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req) if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK) { fn.append(filename); +#ifdef DEBUG_DETAIL_ON printf("Filename: "); printf(fn.c_str()); printf("\n"); +#endif } else fn.append("noname.jpg"); if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("Delay: "); printf(_delay); printf("\n"); +#endif delay = atoi(_delay); if (delay < 0) @@ -142,7 +191,9 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req) fn.append("noname.jpg"); Camera.GetCameraParameter(req, quality, res); +#ifdef DEBUG_DETAIL_ON printf("Size: %d", res); printf(" Quality: %d\n", quality); +#endif Camera.SetQualitySize(quality, res); esp_err_t ressult; @@ -151,6 +202,10 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req) const char* resp_str = (const char*) fn.c_str(); httpd_resp_send(req, resp_str, strlen(resp_str)); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_capture_save_to_file - Done"); +#endif + return ressult; }; @@ -158,8 +213,10 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req) void register_server_camera_uri(httpd_handle_t server) { +#ifdef DEBUG_DETAIL_ON ESP_LOGI(TAGPARTCAMERA, "server_part_camera - Registering URI handlers"); - +#endif + httpd_uri_t camuri = { }; camuri.method = HTTP_GET; diff --git a/code/components/jomjol_fileserver_ota/server_file.cpp b/code/components/jomjol_fileserver_ota/server_file.cpp index 3c8eb2dc..6c6ed261 100644 --- a/code/components/jomjol_fileserver_ota/server_file.cpp +++ b/code/components/jomjol_fileserver_ota/server_file.cpp @@ -68,6 +68,8 @@ static esp_err_t index_html_get_handler(httpd_req_t *req) /* Handler to respond with an icon file embedded in flash. * Browsers expect to GET website icon at URI /favicon.ico. * This can be overridden by uploading file with same name */ + +/* static esp_err_t favicon_get_handler(httpd_req_t *req) { extern const unsigned char favicon_ico_start[] asm("_binary_favicon_ico_start"); @@ -75,10 +77,10 @@ static esp_err_t favicon_get_handler(httpd_req_t *req) const size_t favicon_ico_size = (favicon_ico_end - favicon_ico_start); httpd_resp_set_type(req, "image/x-icon"); httpd_resp_send(req, (const char *)favicon_ico_start, favicon_ico_size); - /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); return ESP_OK; } +*/ /* Send HTTP response with a run-time generated html consisting of * a list of all files and folders under the requested path. @@ -121,7 +123,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const ///////////////////////////////////////////////// if (!readonly) { - FILE *fd = fopen("/sdcard/html/upload_script.html", "r"); + FILE *fd = OpenFileAndWait("/sdcard/html/upload_script.html", "r"); char *chunk = ((struct file_server_data *)req->user_ctx)->scratch; size_t chunksize; do { @@ -231,7 +233,7 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req) std::string currentfilename = LogFile.GetCurrentFileName(); - fd = fopen(currentfilename.c_str(), "r"); + fd = OpenFileAndWait(currentfilename.c_str(), "r"); if (!fd) { ESP_LOGE(TAG, "Failed to read existing file : %s", filepath); /* Respond with 500 Internal Server Error */ @@ -337,7 +339,7 @@ static esp_err_t download_get_handler(httpd_req_t *req) return ESP_FAIL; } - fd = fopen(filepath, "r"); + fd = OpenFileAndWait(filepath, "r"); if (!fd) { ESP_LOGE(TAG, "Failed to read existing file : %s", filepath); /* Respond with 500 Internal Server Error */ @@ -424,7 +426,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req) return ESP_FAIL; } - fd = fopen(filepath, "w"); + fd = OpenFileAndWait(filepath, "w"); if (!fd) { ESP_LOGE(TAG, "Failed to create file : %s", filepath); /* Respond with 500 Internal Server Error */ @@ -710,7 +712,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){ zw = std::string(archive_filename); zw = _target_directory + zw; printf("Filename to extract: %s", zw.c_str()); - FILE* fpTargetFile = fopen(zw.c_str(), "wb"); + FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb"); fwrite(p, 1, (uint)uncomp_size, fpTargetFile); fclose(fpTargetFile); diff --git a/code/components/jomjol_fileserver_ota/server_help.cpp b/code/components/jomjol_fileserver_ota/server_help.cpp index 81ed8a9d..00b3e826 100644 --- a/code/components/jomjol_fileserver_ota/server_help.cpp +++ b/code/components/jomjol_fileserver_ota/server_help.cpp @@ -10,6 +10,8 @@ #include "esp_err.h" #include "esp_log.h" +#include "Helper.h" + #include "esp_http_server.h" @@ -23,9 +25,9 @@ char scratch[SCRATCH_BUFSIZE]; (strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0) -esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_stat) +esp_err_t send_file(httpd_req_t *req, std::string filename) { - FILE *fd = fopen(filename.c_str(), "r"); + FILE *fd = OpenFileAndWait(filename.c_str(), "r"); if (!fd) { ESP_LOGE(TAG, "Failed to read existing file : %s", filename.c_str()); /* Respond with 500 Internal Server Error */ @@ -33,7 +35,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_ return ESP_FAIL; } - ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", filename.c_str(), file_stat->st_size); + ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str()); set_content_type_from_file(req, filename.c_str()); /* Retrieve the pointer to scratch buffer for temporary storage */ @@ -65,6 +67,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_ + /* Copies the full path into destination buffer and returns * pointer to path (skipping the preceding base path) */ const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize) diff --git a/code/components/jomjol_fileserver_ota/server_help.h b/code/components/jomjol_fileserver_ota/server_help.h index 650a8a8e..eb836cc6 100644 --- a/code/components/jomjol_fileserver_ota/server_help.h +++ b/code/components/jomjol_fileserver_ota/server_help.h @@ -5,6 +5,6 @@ const char* get_path_from_uri(char *dest, const char *base_path, const char *uri, size_t destsize); -esp_err_t send_file(httpd_req_t *req, std::string filename, struct stat * file_stat); +esp_err_t send_file(httpd_req_t *req, std::string filename); esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename); \ No newline at end of file diff --git a/code/components/jomjol_fileserver_ota/server_ota.cpp b/code/components/jomjol_fileserver_ota/server_ota.cpp index c18409c7..6c69ae1e 100644 --- a/code/components/jomjol_fileserver_ota/server_ota.cpp +++ b/code/components/jomjol_fileserver_ota/server_ota.cpp @@ -31,6 +31,10 @@ #include "ClassLogFile.h" +#include "Helper.h" + + +// #define DEBUG_DETAIL_ON #define BUFFSIZE 1024 @@ -89,7 +93,7 @@ static bool ota_example_task(std::string fn) int data_read; - FILE* f = fopen(fn.c_str(), "rb"); // vorher nur "r" + FILE* f = OpenFileAndWait(fn.c_str(), "rb"); // vorher nur "r" data_read = fread(ota_write_data, 1, BUFFSIZE, f); while (data_read > 0) { @@ -301,6 +305,10 @@ void CheckOTAUpdate(void) esp_err_t handler_ota_update(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_ota_update - Start"); +#endif + LogFile.WriteToFile("handler_ota_update"); char _query[200]; char _filename[30]; @@ -376,7 +384,11 @@ esp_err_t handler_ota_update(httpd_req_t *req) } httpd_resp_send(req, resp_str, strlen(resp_str)); - + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_ota_update - Done"); +#endif + return ESP_OK; }; @@ -412,6 +424,10 @@ void doReboot(){ esp_err_t handler_reboot(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_reboot - Start"); +#endif + LogFile.WriteToFile("handler_reboot"); ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!"); const char* resp_str = "!!! System will restart within 5 sec!!!"; @@ -419,6 +435,10 @@ esp_err_t handler_reboot(httpd_req_t *req) doReboot(); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_reboot - Done"); +#endif + return ESP_OK; } diff --git a/code/components/jomjol_fileserver_ota/server_ota.h b/code/components/jomjol_fileserver_ota/server_ota.h index 440cb67d..622fd0a8 100644 --- a/code/components/jomjol_fileserver_ota/server_ota.h +++ b/code/components/jomjol_fileserver_ota/server_ota.h @@ -8,4 +8,5 @@ static const char *TAGPARTOTA = "server_ota"; void register_server_ota_sdcard_uri(httpd_handle_t server); void CheckOTAUpdate(); -void doReboot(); \ No newline at end of file +void doReboot(); + diff --git a/code/components/jomjol_flowcontroll/CMakeLists.txt b/code/components/jomjol_flowcontroll/CMakeLists.txt index 670be171..b1dfec86 100644 --- a/code/components/jomjol_flowcontroll/CMakeLists.txt +++ b/code/components/jomjol_flowcontroll/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota) + REQUIRES jomjol_tfliteclass jomjol_helper jomjol_controlcamera jomjol_mqtt jomjol_fileserver_ota jomjol_image_proc) diff --git a/code/components/jomjol_flowcontroll/ClassFlow.cpp b/code/components/jomjol_flowcontroll/ClassFlow.cpp index 5913d304..60ca0620 100644 --- a/code/components/jomjol_flowcontroll/ClassFlow.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlow.cpp @@ -9,9 +9,11 @@ void ClassFlow::SetInitialParameter(void) { ListFlowControll = NULL; + previousElement = NULL; } -//std::vector ClassFlow::ZerlegeZeile(std::string input, std::string delimiter); + + std::vector ClassFlow::ZerlegeZeile(std::string input, std::string delimiter) { @@ -55,7 +57,6 @@ bool ClassFlow::GetNextParagraph(FILE* pfile, string& aktparamgraph) ClassFlow::ClassFlow(void) { SetInitialParameter(); - ListFlowControll = NULL; } ClassFlow::ClassFlow(std::vector * lfc) @@ -64,6 +65,13 @@ ClassFlow::ClassFlow(std::vector * lfc) ListFlowControll = lfc; } +ClassFlow::ClassFlow(std::vector * lfc, ClassFlow *_prev) +{ + SetInitialParameter(); + ListFlowControll = lfc; + previousElement = _prev; +} + bool ClassFlow::ReadParameter(FILE* pfile, string &aktparamgraph) { return false; @@ -100,7 +108,7 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt) } *rt = zw; *rt = trim(*rt); - while (zw[0] == '#' || (rt->size() == 0)) // Kommentarzeilen und Leerzeilen überspringen + while (zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) // Kommentarzeilen (; oder #) und Leerzeilen überspringen { fgets(zw, 1024, pfile); printf("%s", zw); diff --git a/code/components/jomjol_flowcontroll/ClassFlow.h b/code/components/jomjol_flowcontroll/ClassFlow.h index 11a5b25d..9a21bb11 100644 --- a/code/components/jomjol_flowcontroll/ClassFlow.h +++ b/code/components/jomjol_flowcontroll/ClassFlow.h @@ -5,7 +5,7 @@ #include #include "Helper.h" -#include "CFindTemplate.h" +#include "CImageBasis.h" using namespace std; @@ -16,7 +16,10 @@ using namespace std; struct HTMLInfo { float val; + CImageBasis *image = NULL; + CImageBasis *image_org = NULL; std::string filename; + std::string filename_org; }; @@ -30,12 +33,15 @@ protected: bool getNextLine(FILE* pfile, string* rt); std::vector* ListFlowControll; + ClassFlow *previousElement; virtual void SetInitialParameter(void); public: ClassFlow(void); ClassFlow(std::vector * lfc); + ClassFlow(std::vector * lfc, ClassFlow *_prev); + virtual bool ReadParameter(FILE* pfile, string &aktparamgraph); virtual bool doFlow(string time); virtual string getHTMLSingleStep(string host); diff --git a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp index fa97aa7f..866d1952 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowAlignment.cpp @@ -1,29 +1,55 @@ #include "ClassFlowAlignment.h" +#include "ClassFlowMakeImage.h" +#include "ClassFlow.h" + +#include "CRotateImage.h" #include "ClassLogFile.h" -ClassFlowAlignment::ClassFlowAlignment() + + +bool AlignmentExtendedDebugging = true; + + +void ClassFlowAlignment::SetInitialParameter(void) { initalrotate = 0; anz_ref = 0; suchex = 40; suchey = 40; initialmirror = false; + SaveAllFiles = false; namerawimage = "/sdcard/img_tmp/raw.jpg"; ListFlowControll = NULL; + AlignAndCutImage = NULL; + ImageBasis = NULL; + ImageTMP = NULL; + previousElement = NULL; + ref_dx[0] = 0; ref_dx[1] = 0; + ref_dy[0] = 0; ref_dy[1] = 0; } ClassFlowAlignment::ClassFlowAlignment(std::vector* lfc) { - initalrotate = 0; - anz_ref = 0; - suchex = 40; - suchey = 40; - initialmirror = false; - namerawimage = "/sdcard/img_tmp/raw.jpg"; + SetInitialParameter(); ListFlowControll = lfc; + + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowMakeImage") == 0) + { + ImageBasis = ((ClassFlowMakeImage*) (*ListFlowControll)[i])->rawImage; + } + } + + if (!ImageBasis) // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN + { + if (AlignmentExtendedDebugging) printf("CImageBasis musste erzeugt werden\n"); + ImageBasis = new CImageBasis(namerawimage); + } } + bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph) { std::vector zerlegt; @@ -59,11 +85,18 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph) } if ((zerlegt.size() == 3) && (anz_ref < 2)) { - this->reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]); - this->ref_x[anz_ref] = std::stod(zerlegt[1]); - this->ref_y[anz_ref] = std::stod(zerlegt[2]); + reffilename[anz_ref] = FormatFileName("/sdcard" + zerlegt[0]); + ref_x[anz_ref] = std::stod(zerlegt[1]); + ref_y[anz_ref] = std::stod(zerlegt[2]); anz_ref++; } + + if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + SaveAllFiles = true; + } + } return true; @@ -80,72 +113,52 @@ string ClassFlowAlignment::getHTMLSingleStep(string host) } -bool ClassFlowAlignment::doFlow(string time) +bool ClassFlowAlignment::doFlow(string time) { - string input = namerawimage; - string output = "/sdcard/img_tmp/rot.jpg"; - string output3 = "/sdcard/img_tmp/rot_roi.jpg"; - string output2 = "/sdcard/img_tmp/alg.jpg"; - string output4 = "/sdcard/img_tmp/alg_roi.jpg"; - string output1 = "/sdcard/img_tmp/mirror.jpg"; + if (!ImageTMP) + ImageTMP = new CImageBasis(ImageBasis, 5); - input = FormatFileName(input); - output = FormatFileName(output); - output2 = FormatFileName(output2); + if (AlignAndCutImage) + delete AlignAndCutImage; + AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP); + CRotateImage rt(AlignAndCutImage, ImageTMP); if (initialmirror){ - CRotate *rt; - rt = new CRotate(input); - if (!rt->ImageOkay()){ - LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate Inital Mirror raw.jpg not okay!"); - delete rt; - return false; - } printf("do mirror\n"); - rt->Mirror(); - rt->SaveToFile(output1); - input = output1; - delete rt; + rt.Mirror(); + if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg")); } - - + if (initalrotate != 0) { - CRotate *rt = NULL; - printf("Load rotationfile: %s\n", input.c_str()); - rt = new CRotate(input); - if (!rt->ImageOkay()){ - LogFile.WriteToFile("ClassFlowAlignment::doFlow CRotate raw.jpg not okay!"); - delete rt; - return false; - } - rt->Rotate(this->initalrotate); - rt->SaveToFile(output); - delete rt; + rt.Rotate(initalrotate); + if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg")); } - else + + AlignAndCutImage->Align(reffilename[0], ref_x[0], ref_y[0], reffilename[1], ref_x[1], ref_y[1], suchex, suchey, ""); + AlignAndCutImage->GetRefSize(ref_dx, ref_dy); + if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg")); + + if (SaveAllFiles) { - CopyFile(input, output); + DrawRef(ImageTMP); + ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg")); } - CAlignAndCutImage *caic; - caic = new CAlignAndCutImage(output); - caic->Align(this->reffilename[0], this->ref_x[0], this->ref_y[0], this->reffilename[1], this->ref_x[1], this->ref_y[1], suchex, suchey, output3); - caic->SaveToFile(output2); - - printf("Startwriting Output4:%s\n", output4.c_str()); - if (output4.length() > 0) + if (ImageTMP) // nuss gelöscht werden, um Speicherplatz für das Laden von tflite zu haben { - caic->drawRect(ref_x[0], ref_y[0], caic->t0_dx, caic->t0_dy, 255, 0, 0, 2); - caic->drawRect(ref_x[1], ref_y[1], caic->t1_dx, caic->t1_dy, 255, 0, 0, 2); - caic->SaveToFile(output4); - printf("Write output4: %s\n", output4.c_str()); - } + delete ImageTMP; + ImageTMP = NULL; + } - delete caic; - - // Align mit Templates return true; } + +void ClassFlowAlignment::DrawRef(CImageBasis *_zw) +{ + _zw->drawRect(ref_x[0], ref_y[0], ref_dx[0], ref_dy[0], 255, 0, 0, 2); + _zw->drawRect(ref_x[1], ref_y[1], ref_dx[1], ref_dy[1], 255, 0, 0, 2); +} + diff --git a/code/components/jomjol_flowcontroll/ClassFlowAlignment.h b/code/components/jomjol_flowcontroll/ClassFlowAlignment.h index b34908bc..3127064c 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAlignment.h +++ b/code/components/jomjol_flowcontroll/ClassFlowAlignment.h @@ -2,6 +2,7 @@ #include "ClassFlow.h" #include "Helper.h" +#include "CAlignAndCutImage.h" #include @@ -15,13 +16,24 @@ protected: bool initialmirror; string reffilename[2]; int ref_x[2], ref_y[2]; + int ref_dx[2], ref_dy[2]; int anz_ref; int suchex, suchey; string namerawimage; + bool SaveAllFiles; + CAlignAndCutImage *AlignAndCutImage; + + void SetInitialParameter(void); public: - ClassFlowAlignment(); + CImageBasis *ImageBasis, *ImageTMP; + ClassFlowAlignment(std::vector* lfc); + + CAlignAndCutImage* GetAlignAndCutImage(){return AlignAndCutImage;}; + + void DrawRef(CImageBasis *_zw); + bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp b/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp index d0dea860..bf076096 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog.cpp @@ -16,21 +16,30 @@ static const char* TAG = "flow_analog"; bool debugdetailanalog = false; -ClassFlowAnalog::ClassFlowAnalog() : ClassFlowImage(TAG) +void ClassFlowAnalog::SetInitialParameter(void) { string cnnmodelfile = ""; modelxsize = 1; modelysize = 1; ListFlowControll = NULL; -} + previousElement = NULL; + SaveAllFiles = false; +} ClassFlowAnalog::ClassFlowAnalog(std::vector* lfc) : ClassFlowImage(lfc, TAG) { - string cnnmodelfile = ""; - modelxsize = 1; - modelysize = 1; -} + SetInitialParameter(); + ListFlowControll = lfc; + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } + } + +} string ClassFlowAnalog::getReadout() @@ -113,9 +122,24 @@ bool ClassFlowAnalog::ReadParameter(FILE* pfile, string& aktparamgraph) neuroi->deltax = std::stoi(zerlegt[3]); neuroi->deltay = std::stoi(zerlegt[4]); neuroi->result = -1; + neuroi->image = NULL; + neuroi->image_org = NULL; ROI.push_back(neuroi); } + + if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + SaveAllFiles = true; + } } + + for (int i = 0; i < ROI.size(); ++i) + { + ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); + ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3); + } + return true; } @@ -162,79 +186,37 @@ bool ClassFlowAnalog::doFlow(string time) bool ClassFlowAnalog::doAlignAndCut(string time) { - string input = "/sdcard/img_tmp/alg.jpg"; - string input_roi = "/sdcard/img_tmp/alg_roi.jpg"; - string ioresize = "/sdcard/img_tmp/resize.bmp"; - string output; - string nm; - input = FormatFileName(input); - input_roi = FormatFileName(input_roi); - - CResizeImage *rs; - CImageBasis *img_roi = NULL; - CAlignAndCutImage *caic = new CAlignAndCutImage(input); - - if (!caic->ImageOkay()){ - if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut not okay!"); - delete caic; - return false; - } - - if (input_roi.length() > 0){ - img_roi = new CImageBasis(input_roi); - if (!img_roi->ImageOkay()){ - if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut ImageRoi not okay!"); - delete caic; - delete img_roi; - return false; - } - } + CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage(); for (int i = 0; i < ROI.size(); ++i) { printf("Analog %d - Align&Cut\n", i); - output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg"; - output = FormatFileName(output); - caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay); + + 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")); - rs = new CResizeImage(output); - if (!rs->ImageOkay()){ - if (debugdetailanalog) LogFile.WriteToFile("ClassFlowAnalog::doAlignAndCut CResizeImage(output);!"); - delete caic; - delete rs; - return false; - } - - rs->Resize(modelxsize, modelysize); - ioresize = "/sdcard/img_tmp/ra" + std::to_string(i) + ".bmp"; - ioresize = FormatFileName(ioresize); - rs->SaveToFile(ioresize); - delete rs; - - if (img_roi) - { - int r = 0; - int g = 255; - int b = 0; - img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, r, g, b, 1); - img_roi->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); - img_roi->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); - img_roi->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); - } + ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image); + if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp")); } - delete caic; - - - if (img_roi) - { - img_roi->SaveToFile(input_roi); - delete img_roi; - } - return true; } +void ClassFlowAnalog::DrawROI(CImageBasis *_zw) +{ + int r = 0; + int g = 255; + 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); + } +} + bool ClassFlowAnalog::doNeuralNetwork(string time) { string logPath = CreateLogFolder(time); @@ -265,7 +247,8 @@ bool ClassFlowAnalog::doNeuralNetwork(string time) #ifndef OHNETFLITE // LogFile.WriteToFile("ClassFlowAnalog::doNeuralNetwork vor CNN tflite->LoadInputImage(ioresize)"); - tflite->LoadInputImage(ioresize); +// tflite->LoadInputImage(ioresize); + tflite->LoadInputImageBasis(ROI[i]->image); tflite->Invoke(); if (debugdetailanalog) LogFile.WriteToFile("Nach Invoke"); @@ -278,9 +261,12 @@ bool ClassFlowAnalog::doNeuralNetwork(string time) // printf("Result sin, cos, ziffer: %f, %f, %f\n", f1, f2, result); ROI[i]->result = result * 10; - printf("Result Analog%i: %f\n", i, ROI[i]->result); + printf("Result Analog%i: %f\n", i, ROI[i]->result); - LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time); + if (isLogImage) + { + LogImage(logPath, ROI[i]->name, &ROI[i]->result, NULL, time, ROI[i]->image_org); + } } #ifndef OHNETFLITE delete tflite; @@ -297,8 +283,11 @@ std::vector ClassFlowAnalog::GetHTMLInfo() for (int i = 0; i < ROI.size(); ++i) { HTMLInfo *zw = new HTMLInfo; - zw->filename = ROI[i]->name + ".jpg"; + 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); } diff --git a/code/components/jomjol_flowcontroll/ClassFlowAnalog.h b/code/components/jomjol_flowcontroll/ClassFlowAnalog.h index 89f2f6e2..64de44e0 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowAnalog.h +++ b/code/components/jomjol_flowcontroll/ClassFlowAnalog.h @@ -1,10 +1,12 @@ #pragma once #include "ClassFlowImage.h" +#include "ClassFlowAlignment.h" // #include "CTfLiteClass.h" struct roianalog { int posx, posy, deltax, deltay; float result; + CImageBasis *image, *image_org; string name; }; @@ -17,14 +19,21 @@ protected: string cnnmodelfile; int modelxsize, modelysize; int ZeigerEval(float zahl, int ziffer_vorgaenger); + bool SaveAllFiles; + + ClassFlowAlignment* flowpostalignment; + + void SetInitialParameter(void); public: - ClassFlowAnalog(); ClassFlowAnalog(std::vector* lfc); + bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); - string getReadout(); + string getReadout(); + + void DrawROI(CImageBasis *_zw); bool doNeuralNetwork(string time); bool doAlignAndCut(string time); diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp index 2eb72fe6..9fb50a76 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.cpp @@ -9,8 +9,13 @@ #include "Helper.h" #include "server_ota.h" +#include "server_help.h" + +//#define DEBUG_DETAIL_ON + static const char* TAG = "flow_controll"; + std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){ std::string _classname = ""; std::string result = ""; @@ -68,6 +73,9 @@ void ClassFlowControll::SetInitialParameter(void) AutoStart = false; SetupModeActive = false; AutoIntervall = 10; + flowdigit = NULL; + flowanalog = NULL; + flowpostprocessing = NULL; } bool ClassFlowControll::isAutoStart(long &_intervall) @@ -83,13 +91,25 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type) _type = trim(_type); if (toUpper(_type).compare("[MAKEIMAGE]") == 0) + { cfc = new ClassFlowMakeImage(&FlowControll); + flowmakeimage = (ClassFlowMakeImage*) cfc; + } if (toUpper(_type).compare("[ALIGNMENT]") == 0) + { cfc = new ClassFlowAlignment(&FlowControll); + flowalignment = (ClassFlowAlignment*) cfc; + } if (toUpper(_type).compare("[ANALOG]") == 0) + { cfc = new ClassFlowAnalog(&FlowControll); + flowanalog = (ClassFlowAnalog*) cfc; + } if (toUpper(_type).compare("[DIGITS]") == 0) + { cfc = new ClassFlowDigit(&FlowControll); + flowdigit = (ClassFlowDigit*) cfc; + } if (toUpper(_type).compare("[MQTT]") == 0) cfc = new ClassFlowMQTT(&FlowControll); if (toUpper(_type).compare("[POSTPROCESSING]") == 0) @@ -122,7 +142,7 @@ void ClassFlowControll::InitFlow(std::string config) ClassFlow* cfc; FILE* pFile; config = FormatFileName(config); - pFile = fopen(config.c_str(), "r"); + pFile = OpenFileAndWait(config.c_str(), "r"); line = ""; @@ -139,6 +159,7 @@ void ClassFlowControll::InitFlow(std::string config) cfc = CreateClassFlow(line); if (cfc) { + printf("Start ReadParameter\n"); cfc->ReadParameter(pFile, line); } else @@ -158,9 +179,7 @@ std::string ClassFlowControll::getActStatus(){ } void ClassFlowControll::doFlowMakeImageOnly(string time){ - bool result = true; std::string zw_time; - int repeat = 0; for (int i = 0; i < FlowControll.size(); ++i) { @@ -181,12 +200,20 @@ bool ClassFlowControll::doFlow(string time) std::string zw_time; int repeat = 0; +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow - Start"); +#endif + for (int i = 0; i < FlowControll.size(); ++i) { zw_time = gettimestring("%Y%m%d-%H%M%S"); aktstatus = zw_time + ": " + FlowControll[i]->name(); + +// #ifdef DEBUG_DETAIL_ON string zw = "FlowControll.doFlow - " + FlowControll[i]->name(); - LogFile.WriteToFile(zw); + LogFile.WriteHeapInfo(zw); +// #endif + if (!FlowControll[i]->doFlow(time)){ repeat++; LogFile.WriteToFile("Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt"); @@ -202,6 +229,11 @@ bool ClassFlowControll::doFlow(string time) { result = true; } + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("ClassFlowAnalog::doFlow"); +#endif + } zw_time = gettimestring("%Y%m%d-%H%M%S"); aktstatus = zw_time + ": Flow is done"; @@ -320,6 +352,14 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph) setTimeZone(zerlegt[1]); } + if ((toUpper(zerlegt[0]) == "TIMESERVER") && (zerlegt.size() > 1)) + { + string zw = "Set TimeZone: " + zerlegt[1]; + reset_servername(zerlegt[1]); + } + + + if ((toUpper(zerlegt[0]) == "SETUPMODE") && (zerlegt.size() > 1)) { if (toUpper(zerlegt[1]) == "TRUE") @@ -362,4 +402,85 @@ int ClassFlowControll::CleanTempFolder() { ESP_LOGI(TAG, "%d files deleted", deleted); return 0; +} + + +esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req) +{ + return flowmakeimage->SendRawJPG(req); +} + + +esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req) +{ + printf("ClassFlowControll::GetJPGStream %s\n", _fn.c_str()); + + CImageBasis *_send = NULL; + esp_err_t result = ESP_FAIL; + bool Dodelete = false; + + if (_fn == "alg.jpg") + { + _send = flowalignment->ImageBasis; + } + + + + if (_fn == "alg_roi.jpg") + { + CImageBasis* _imgzw = new CImageBasis(flowalignment->ImageBasis); + flowalignment->DrawRef(_imgzw); + if (flowdigit) flowdigit->DrawROI(_imgzw); + if (flowanalog) flowanalog->DrawROI(_imgzw); + _send = _imgzw; + Dodelete = true; + } + + std::vector htmlinfo; + htmlinfo = GetAllDigital(); + for (int i = 0; i < htmlinfo.size(); ++i) + { + if (_fn == htmlinfo[i]->filename) + { + if (htmlinfo[i]->image) + _send = htmlinfo[i]->image; + } + if (_fn == htmlinfo[i]->filename_org) + { + if (htmlinfo[i]->image_org) + _send = htmlinfo[i]->image_org; + } + } + + htmlinfo = GetAllAnalog(); + for (int i = 0; i < htmlinfo.size(); ++i) + { + if (_fn == htmlinfo[i]->filename) + { + if (htmlinfo[i]->image) + _send = htmlinfo[i]->image; + } + if (_fn == htmlinfo[i]->filename_org) + { + if (htmlinfo[i]->image_org) + _send = htmlinfo[i]->image_org; + } + } + + if (_send) + { + ESP_LOGI(TAG, "Sending file : %s ...", _fn.c_str()); + set_content_type_from_file(req, _fn.c_str()); + result = _send->SendJPGtoHTTP(req); + ESP_LOGI(TAG, "File sending complete"); + /* Respond with an empty chunk to signal HTTP response completion */ + httpd_resp_send_chunk(req, NULL, 0); + } + + if (Dodelete) + { + delete _send; + } + + return result; } \ No newline at end of file diff --git a/code/components/jomjol_flowcontroll/ClassFlowControll.h b/code/components/jomjol_flowcontroll/ClassFlowControll.h index adf7ef6a..d46d1829 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowControll.h +++ b/code/components/jomjol_flowcontroll/ClassFlowControll.h @@ -17,6 +17,10 @@ class ClassFlowControll : protected: std::vector FlowControll; ClassFlowPostProcessing* flowpostprocessing; + ClassFlowAlignment* flowalignment; + ClassFlowAnalog* flowanalog; + ClassFlowDigit* flowdigit; + ClassFlowMakeImage* flowmakeimage; ClassFlow* CreateClassFlow(std::string _type); bool AutoStart; @@ -35,6 +39,9 @@ public: string GetPrevalue(); bool ReadParameter(FILE* pfile, string& aktparamgraph); + esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req); + esp_err_t SendRawJPG(httpd_req_t *req); + std::string doSingleStep(std::string _stepname, std::string _host); bool isAutoStart(long &_intervall); @@ -49,3 +56,4 @@ public: string name(){return "ClassFlowControll";}; }; + diff --git a/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp b/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp index 90f02254..f0bf83ad 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowDigit.cpp @@ -1,5 +1,6 @@ #include "ClassFlowDigit.h" + //#include "CFindTemplate.h" //#include "CTfLiteClass.h" @@ -15,19 +16,49 @@ static const char* TAG = "flow_digital"; -ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG) + +void ClassFlowDigit::SetInitialParameter(void) { string cnnmodelfile = ""; modelxsize = 1; modelysize = 1; ListFlowControll = NULL; + previousElement = NULL; + SaveAllFiles = false; +} + +ClassFlowDigit::ClassFlowDigit() : ClassFlowImage(TAG) +{ + SetInitialParameter(); } ClassFlowDigit::ClassFlowDigit(std::vector* lfc) : ClassFlowImage(lfc, TAG) { - string cnnmodelfile = ""; - modelxsize = 1; - modelysize = 1; + SetInitialParameter(); + ListFlowControll = lfc; + + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } + } +} + +ClassFlowDigit::ClassFlowDigit(std::vector* lfc, ClassFlow *_prev) : ClassFlowImage(lfc, _prev, TAG) +{ + SetInitialParameter(); + ListFlowControll = lfc; + previousElement = _prev; + + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowAlignment") == 0) + { + flowpostalignment = (ClassFlowAlignment*) (*ListFlowControll)[i]; + } + } } string ClassFlowDigit::getReadout() @@ -85,9 +116,25 @@ bool ClassFlowDigit::ReadParameter(FILE* pfile, string& aktparamgraph) neuroi->deltax = std::stoi(zerlegt[3]); neuroi->deltay = std::stoi(zerlegt[4]); neuroi->resultklasse = -1; + neuroi->image = NULL; + neuroi->image_org = NULL; ROI.push_back(neuroi); } + + if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + SaveAllFiles = true; + } + } + + for (int i = 0; i < ROI.size(); ++i) + { + ROI[i]->image = new CImageBasis(modelxsize, modelysize, 3); + ROI[i]->image_org = new CImageBasis(ROI[i]->deltax, ROI[i]->deltay, 3); + } + return true; } @@ -133,60 +180,17 @@ bool ClassFlowDigit::doFlow(string time) bool ClassFlowDigit::doAlignAndCut(string time) { - string input = "/sdcard/img_tmp/alg.jpg"; - string input_roi = "/sdcard/img_tmp/alg_roi.jpg"; - string ioresize = "/sdcard/img_tmp/resize.bmp"; - string output; - string nm; - input = FormatFileName(input); - input_roi = FormatFileName(input_roi); - - CResizeImage *rs; - CImageBasis *img_roi = NULL; - CAlignAndCutImage *caic = new CAlignAndCutImage(input); - if (!caic->ImageOkay()){ - LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut not okay!"); - delete caic; - return false; - } - - if (input_roi.length() > 0){ - img_roi = new CImageBasis(input_roi); - if (!img_roi->ImageOkay()){ - LogFile.WriteToFile("ClassFlowDigit::doAlignAndCut ImageRoi not okay!"); - delete caic; - delete img_roi; - return false; - } - } - - + CAlignAndCutImage *caic = flowpostalignment->GetAlignAndCutImage(); for (int i = 0; i < ROI.size(); ++i) { printf("DigitalDigit %d - Align&Cut\n", i); - output = "/sdcard/img_tmp/" + ROI[i]->name + ".jpg"; - output = FormatFileName(output); - caic->CutAndSave(output, ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay); + + 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")); - rs = new CResizeImage(output); - rs->Resize(modelxsize, modelysize); - ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp"; - ioresize = FormatFileName(ioresize); - rs->SaveToFile(ioresize); - delete rs; - - if (img_roi) - { - img_roi->drawRect(ROI[i]->posx, ROI[i]->posy, ROI[i]->deltax, ROI[i]->deltay, 0, 0, 255, 2); - } - } - delete caic; - - if (img_roi) - { - img_roi->SaveToFile(input_roi); - delete img_roi; + ROI[i]->image_org->Resize(modelxsize, modelysize, ROI[i]->image); + if (SaveAllFiles) ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + ROI[i]->name + ".bmp")); } return true; @@ -196,17 +200,9 @@ bool ClassFlowDigit::doNeuralNetwork(string time) { string logPath = CreateLogFolder(time); - string input = "/sdcard/img_tmp/alg.jpg"; - string ioresize = "/sdcard/img_tmp/resize.bmp"; - string output; - string nm; - input = FormatFileName(input); - - #ifndef OHNETFLITE CTfLiteClass *tflite = new CTfLiteClass; - string zwcnn = "/sdcard" + cnnmodelfile; - zwcnn = FormatFileName(zwcnn); + string zwcnn = FormatFileName("/sdcard" + cnnmodelfile); printf(zwcnn.c_str());printf("\n"); tflite->LoadModel(zwcnn); tflite->MakeAllocate(); @@ -215,17 +211,18 @@ bool ClassFlowDigit::doNeuralNetwork(string time) for (int i = 0; i < ROI.size(); ++i) { printf("DigitalDigit %d - TfLite\n", i); - ioresize = "/sdcard/img_tmp/rd" + std::to_string(i) + ".bmp"; - ioresize = FormatFileName(ioresize); -// printf("output: %s, ioresize: %s\n", output.c_str(), ioresize.c_str()); ROI[i]->resultklasse = 0; #ifndef OHNETFLITE - ROI[i]->resultklasse = tflite->GetClassFromImage(ioresize); + ROI[i]->resultklasse = tflite->GetClassFromImageBasis(ROI[i]->image); + #endif printf("Result Digit%i: %d\n", i, ROI[i]->resultklasse); - LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time); + if (isLogImage) + { + LogImage(logPath, ROI[i]->name, NULL, &ROI[i]->resultklasse, time, ROI[i]->image_org); + } } #ifndef OHNETFLITE delete tflite; @@ -233,6 +230,11 @@ bool ClassFlowDigit::doNeuralNetwork(string time) return true; } +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); +} std::vector ClassFlowDigit::GetHTMLInfo() { @@ -241,10 +243,14 @@ std::vector ClassFlowDigit::GetHTMLInfo() for (int i = 0; i < ROI.size(); ++i) { HTMLInfo *zw = new HTMLInfo; - zw->filename = ROI[i]->name + ".jpg"; + 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); } return result; -} \ No newline at end of file +} + diff --git a/code/components/jomjol_flowcontroll/ClassFlowDigit.h b/code/components/jomjol_flowcontroll/ClassFlowDigit.h index 3546bb36..d3043642 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowDigit.h +++ b/code/components/jomjol_flowcontroll/ClassFlowDigit.h @@ -1,5 +1,6 @@ #pragma once #include "ClassFlowImage.h" +#include "ClassFlowAlignment.h" #include "Helper.h" #include @@ -8,6 +9,7 @@ struct roi { int posx, posy, deltax, deltay; int resultklasse; string name; + CImageBasis *image, *image_org; roi* next; }; @@ -18,19 +20,27 @@ protected: std::vector ROI; string cnnmodelfile; int modelxsize, modelysize; + bool SaveAllFiles; + + ClassFlowAlignment* flowpostalignment; bool doNeuralNetwork(string time); bool doAlignAndCut(string time); + void SetInitialParameter(void); + public: ClassFlowDigit(); ClassFlowDigit(std::vector* lfc); + ClassFlowDigit(std::vector* lfc, ClassFlow *_prev); bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); string getReadout(); std::vector GetHTMLInfo(); + void DrawROI(CImageBasis *_zw); + string name(){return "ClassFlowDigit";}; }; diff --git a/code/components/jomjol_flowcontroll/ClassFlowImage.cpp b/code/components/jomjol_flowcontroll/ClassFlowImage.cpp index 5c09160e..35336462 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowImage.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowImage.cpp @@ -5,6 +5,7 @@ #include #include "time_sntp.h" #include "ClassLogFile.h" +#include "CImageBasis.h" ClassFlowImage::ClassFlowImage(const char* logTag) { @@ -12,12 +13,19 @@ ClassFlowImage::ClassFlowImage(const char* logTag) isLogImage = false; } -ClassFlowImage::ClassFlowImage(std::vector * lfc, const char* logTag) : ClassFlow((std::vector*)lfc) +ClassFlowImage::ClassFlowImage(std::vector * lfc, const char* logTag) : ClassFlow(lfc) { this->logTag = logTag; isLogImage = false; } +ClassFlowImage::ClassFlowImage(std::vector * lfc, ClassFlow *_prev, const char* logTag) : ClassFlow(lfc, _prev) +{ + this->logTag = logTag; + isLogImage = false; +} + + string ClassFlowImage::CreateLogFolder(string time) { if (!isLogImage) return ""; @@ -32,7 +40,7 @@ string ClassFlowImage::CreateLogFolder(string time) { return logPath; } -void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time) { +void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img) { if (!isLogImage) return; @@ -50,7 +58,8 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i string output = "/sdcard/img_tmp/" + name + ".jpg"; output = FormatFileName(output); printf("save to file: %s\n", nm.c_str()); - CopyFile(output, nm); + _img->SaveToFile(nm); +// CopyFile(output, nm); } void ClassFlowImage::RemoveOldLogs() diff --git a/code/components/jomjol_flowcontroll/ClassFlowImage.h b/code/components/jomjol_flowcontroll/ClassFlowImage.h index 23154c64..e3dacc35 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowImage.h +++ b/code/components/jomjol_flowcontroll/ClassFlowImage.h @@ -12,11 +12,13 @@ protected: const char* logTag; string CreateLogFolder(string time); - void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time); + void LogImage(string logPath, string name, float *resultFloat, int *resultInt, string time, CImageBasis *_img); + public: ClassFlowImage(const char* logTag); ClassFlowImage(std::vector * lfc, const char* logTag); - + ClassFlowImage(std::vector * lfc, ClassFlow *_prev, const char* logTag); + void RemoveOldLogs(); }; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp index e96de968..66247305 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.cpp @@ -6,7 +6,7 @@ #include -ClassFlowMQTT::ClassFlowMQTT() +void ClassFlowMQTT::SetInitialParameter(void) { uri = ""; topic = ""; @@ -15,20 +15,35 @@ ClassFlowMQTT::ClassFlowMQTT() OldValue = ""; flowpostprocessing = NULL; user = ""; - password = ""; + password = ""; + previousElement = NULL; + ListFlowControll = NULL; +} + +ClassFlowMQTT::ClassFlowMQTT() +{ + SetInitialParameter(); } ClassFlowMQTT::ClassFlowMQTT(std::vector* lfc) { - uri = ""; - topic = ""; - topicError = ""; - clientname = "watermeter"; - OldValue = ""; - flowpostprocessing = NULL; - user = ""; - password = ""; + SetInitialParameter(); + ListFlowControll = lfc; + for (int i = 0; i < ListFlowControll->size(); ++i) + { + if (((*ListFlowControll)[i])->name().compare("ClassFlowPostProcessing") == 0) + { + flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; + } + } +} + +ClassFlowMQTT::ClassFlowMQTT(std::vector* lfc, ClassFlow *_prev) +{ + SetInitialParameter(); + + previousElement = _prev; ListFlowControll = lfc; for (int i = 0; i < ListFlowControll->size(); ++i) @@ -38,9 +53,9 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector* lfc) flowpostprocessing = (ClassFlowPostProcessing*) (*ListFlowControll)[i]; } } - } + bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) { std::vector zerlegt; @@ -86,7 +101,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph) if ((uri.length() > 0) && (topic.length() > 0)) { - MQTTInit(uri, clientname, user, password); + MQTTInit(uri, clientname, user, password, topicError, 60); } return true; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h index 48e93f0f..2ac29135 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMQTT.h +++ b/code/components/jomjol_flowcontroll/ClassFlowMQTT.h @@ -13,11 +13,13 @@ protected: std::string OldValue; ClassFlowPostProcessing* flowpostprocessing; std::string user, password; - + void SetInitialParameter(void); public: ClassFlowMQTT(); ClassFlowMQTT(std::vector* lfc); + ClassFlowMQTT(std::vector* lfc, ClassFlow *_prev); + bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string name(){return "ClassFlowMQTT";}; diff --git a/code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp b/code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp index d1f4d78c..d6d948ab 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowMakeImage.cpp @@ -1,11 +1,14 @@ #include "ClassFlowMakeImage.h" #include "Helper.h" +#include "ClassLogFile.h" -#include "CFindTemplate.h" +#include "CImageBasis.h" #include "ClassControllCamera.h" #include +// #define DEBUG_DETAIL_ON + static const char* TAG = "flow_make_image"; esp_err_t ClassFlowMakeImage::camera_capture(){ @@ -16,30 +19,27 @@ esp_err_t ClassFlowMakeImage::camera_capture(){ void ClassFlowMakeImage::takePictureWithFlash(int flashdauer) { - string nm = namerawimage; - if (isImageSize && (ImageQuality > 0)) - Camera.SetQualitySize(ImageQuality, ImageSize); - printf("Start CaptureFile\n"); - Camera.CaptureToFile(nm, flashdauer); + Camera.CaptureToBasisImage(rawImage, flashdauer); + if (SaveAllFiles) rawImage->SaveToFile(namerawimage); } - -ClassFlowMakeImage::ClassFlowMakeImage() : ClassFlowImage(TAG) +void ClassFlowMakeImage::SetInitialParameter(void) { waitbeforepicture = 5; isImageSize = false; ImageQuality = -1; TimeImageTaken = 0; + ImageQuality = 5; + rawImage = NULL; + ImageSize = FRAMESIZE_VGA; + SaveAllFiles = false; namerawimage = "/sdcard/img_tmp/raw.jpg"; -} +} + ClassFlowMakeImage::ClassFlowMakeImage(std::vector* lfc) : ClassFlowImage(lfc, TAG) { - waitbeforepicture = 5; - isImageSize = false; - ImageQuality = -1; - TimeImageTaken = 0; - namerawimage = "/sdcard/img_tmp/raw.jpg"; + SetInitialParameter(); } bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph) @@ -64,14 +64,28 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph) isLogImage = true; } if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1)) - this->ImageQuality = std::stod(zerlegt[1]); + ImageQuality = std::stod(zerlegt[1]); + if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1)) { ImageSize = Camera.TextToFramesize(zerlegt[1].c_str()); isImageSize = true; } + + if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1)) + { + if (toUpper(zerlegt[1]) == "TRUE") + SaveAllFiles = true; + } + } - + + Camera.SetQualitySize(ImageQuality, ImageSize); + image_width = Camera.image_width; + image_height = Camera.image_height; + rawImage = new CImageBasis(); + rawImage->CreateEmptyImage(image_width, image_height, 3); + return true; } @@ -84,27 +98,56 @@ string ClassFlowMakeImage::getHTMLSingleStep(string host) bool ClassFlowMakeImage::doFlow(string zwtime) { - //////////////////////////////////////////////////////////////////// - // TakeImage and Store into /image_tmp/raw.jpg TO BE DONE - //////////////////////////////////////////////////////////////////// - string logPath = CreateLogFolder(zwtime); int flashdauer = (int) waitbeforepicture * 1000; - + + #ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash"); +#endif takePictureWithFlash(flashdauer); - time(&TimeImageTaken); - localtime(&TimeImageTaken); - LogImage(logPath, "raw", NULL, NULL, zwtime); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash"); +#endif + + LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage); RemoveOldLogs(); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs"); +#endif + return true; } +esp_err_t ClassFlowMakeImage::SendRawJPG(httpd_req_t *req) +{ + int flashdauer = (int) waitbeforepicture * 1000; + return Camera.CaptureToHTTP(req, flashdauer); +} + + +ImageData* ClassFlowMakeImage::SendRawImage() +{ + CImageBasis *zw = new CImageBasis(rawImage); + ImageData *id; + int flashdauer = (int) waitbeforepicture * 1000; + Camera.CaptureToBasisImage(zw, flashdauer); + id = zw->writeToMemoryAsJPG(); + delete zw; + return id; +} + time_t ClassFlowMakeImage::getTimeImageTaken() { return TimeImageTaken; } + +ClassFlowMakeImage::~ClassFlowMakeImage(void) +{ + delete rawImage; +} + diff --git a/code/components/jomjol_flowcontroll/ClassFlowMakeImage.h b/code/components/jomjol_flowcontroll/ClassFlowMakeImage.h index febb2ab3..744c2cd3 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowMakeImage.h +++ b/code/components/jomjol_flowcontroll/ClassFlowMakeImage.h @@ -20,19 +20,32 @@ protected: int ImageQuality; time_t TimeImageTaken; string namerawimage; + int image_height, image_width; + bool SaveAllFiles; + void CopyFile(string input, string output); esp_err_t camera_capture(); - void takePictureWithFlash(int flashdauer); + void takePictureWithFlash(int flashdauer); + + void SetInitialParameter(void); public: - ClassFlowMakeImage(); + CImageBasis *rawImage; + ClassFlowMakeImage(std::vector* lfc); + bool ReadParameter(FILE* pfile, string& aktparamgraph); bool doFlow(string time); string getHTMLSingleStep(string host); time_t getTimeImageTaken(); string name(){return "ClassFlowMakeImage";}; + + ImageData* SendRawImage(); + esp_err_t SendRawJPG(httpd_req_t *req); + + ~ClassFlowMakeImage(void); }; + diff --git a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp index abe02045..dd59a9ce 100644 --- a/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp +++ b/code/components/jomjol_flowcontroll/ClassFlowPostProcessing.cpp @@ -108,6 +108,8 @@ void ClassFlowPostProcessing::SavePreValue(float value, string zwtime) zwtime = std::string(buffer); } + PreValue = value; + fputs(zwtime.c_str(), pFile); fputs("\n", pFile); fputs(to_string(value).c_str(), pFile); diff --git a/code/components/jomjol_helper/CMakeLists.txt b/code/components/jomjol_helper/CMakeLists.txt index bd92d82d..948e3829 100644 --- a/code/components/jomjol_helper/CMakeLists.txt +++ b/code/components/jomjol_helper/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES tfmicro) + REQUIRES tfmicro jomjol_logfile) diff --git a/code/components/jomjol_helper/Helper.cpp b/code/components/jomjol_helper/Helper.cpp index 5ffd73e0..0a32b30e 100644 --- a/code/components/jomjol_helper/Helper.cpp +++ b/code/components/jomjol_helper/Helper.cpp @@ -1,5 +1,8 @@ //#pragma warning(disable : 4996) +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + #include "Helper.h" #include #include @@ -7,11 +10,91 @@ #include #include +#include "ClassLogFile.h" +//#include "ClassLogFile.h" + //#define ISWINDOWS_TRUE #define PATH_MAX_STRING_SIZE 256 using namespace std; +///////////////////////////////////////////////////////////////////////////////////////////// +string getESPHeapInfo(){ + string espInfoResultStr = ""; + char aMsgBuf[80]; + + multi_heap_info_t aMultiHead_info ; + heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT); + size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); + size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); + size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); + sprintf(aMsgBuf," Free Heap Size: %ld", (long) aFreeHeapSize); + size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM); + size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + + sprintf(aMsgBuf," Heap: %ld", (long) aFreeHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," Min Free: %ld", (long) aMinFreeHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," larg. Block: %ld", (long) aHeapLargestFreeBlockSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," SPI Heap: %ld", (long) aFreeSPIHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," Min Free Heap Size: %ld", (long) aMinFreeHeadSize); + sprintf(aMsgBuf," NOT_SPI Heap: %ld", (long) (aFreeHeapSize - aFreeSPIHeapSize)); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," largest Block Size: %ld", (long) aHeapLargestFreeBlockSize); + sprintf(aMsgBuf," Internal Heap: %ld", (long) (aFreeInternalHeapSize)); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf," Internal Min Heap free: %ld", (long) (aMinFreeInternalHeapSize)); + espInfoResultStr += string(aMsgBuf); + return espInfoResultStr; +} + + +size_t getESPHeapSize(){ + size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT); + return aFreeHeapSize; +} + +size_t getInternalESPHeapSize() { + size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + return aFreeInternalHeapSize; +} + + + + +/////////////////////////////////////////////////////////////////////////////////////////////// + +void memCopyGen(uint8_t* _source, uint8_t* _target, int _size) +{ + for (int i = 0; i < _size; ++i) + *(_target + i) = *(_source + i); +} + + + +FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec) +{ + FILE *pfile = fopen(nm, _mode); + + if (pfile == NULL) + { + TickType_t xDelay; + xDelay = _waitsec * 1000 / portTICK_PERIOD_MS; + std::string zw = "File is locked: " + std::string(nm) + " - wait for " + std::to_string(_waitsec); + printf(zw.c_str()); + printf("\n"); + LogFile.WriteToFile(zw); + vTaskDelay( xDelay ); + pfile = fopen(nm, _mode); + } + return pfile; +} + std::string FormatFileName(std::string input) { #ifdef ISWINDOWS_TRUE @@ -126,14 +209,14 @@ void CopyFile(string input, string output) } char cTemp; - FILE* fpSourceFile = fopen(input.c_str(), "rb"); + FILE* fpSourceFile = OpenFileAndWait(input.c_str(), "rb"); if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch! { printf("File %s existiert nicht!\n", input.c_str()); return; } - FILE* fpTargetFile = fopen(output.c_str(), "wb"); + FILE* fpTargetFile = OpenFileAndWait(output.c_str(), "wb"); // Code Section diff --git a/code/components/jomjol_helper/Helper.h b/code/components/jomjol_helper/Helper.h index 7891263c..5ecf2f5f 100644 --- a/code/components/jomjol_helper/Helper.h +++ b/code/components/jomjol_helper/Helper.h @@ -10,6 +10,8 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri void CopyFile(string input, string output); +FILE* OpenFileAndWait(const char* nm, char* _mode, int _waitsec = 1); + size_t findDelimiterPos(string input, string delimiter); //string trim(string istring); string trim(string istring, string adddelimiter = ""); @@ -25,3 +27,12 @@ string toUpper(string in); float temperatureRead(); time_t addDays(time_t startTime, int days); + +void memCopyGen(uint8_t* _source, uint8_t* _target, int _size); + +/////////////////////////// +size_t getInternalESPHeapSize(); +size_t getESPHeapSize(); +string getESPHeapInfo(); + +///////////////////////////// diff --git a/code/components/jomjol_image_proc/CAlignAndCutImage.cpp b/code/components/jomjol_image_proc/CAlignAndCutImage.cpp new file mode 100644 index 00000000..cb38b211 --- /dev/null +++ b/code/components/jomjol_image_proc/CAlignAndCutImage.cpp @@ -0,0 +1,205 @@ +#include "CAlignAndCutImage.h" +#include "CRotateImage.h" +#include "CFindTemplate.h" + +#define _USE_MATH_DEFINES +#include +#include + +//#define GET_MEMORY malloc +#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM) + + + +CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp) +{ + rgb_image = _org->rgb_image; + channels = _org->channels; + width = _org->width; + height = _org->height; + bpp = _org->bpp; + externalImage = true; + + islocked = false; + + ImageTMP = _temp; +} + +void CAlignAndCutImage::GetRefSize(int *ref_dx, int *ref_dy) +{ + ref_dx[0] = t0_dx; + ref_dy[0] = t0_dy; + ref_dx[1] = t1_dx; + ref_dy[1] = t1_dy; +} + +void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, std::string _template1, int ref1_x, int ref1_y, int deltax, int deltay, std::string imageROI) +{ + int dx, dy; + int r0_x, r0_y, r1_x, r1_y; + +// CFindTemplate* ft = new CFindTemplate(filename); + CFindTemplate* ft = new CFindTemplate(rgb_image, channels, width, height, bpp); + + r0_x = ref0_x; + r0_y = ref0_y; + ft->FindTemplate(_template0, &r0_x, &r0_y, deltax, deltay); + t0_dx = ft->tpl_width; + t0_dy = ft->tpl_height; + + r1_x = ref1_x; + r1_y = ref1_y; + ft->FindTemplate(_template1, &r1_x, &r1_y, deltax, deltay); + t1_dx = ft->tpl_width; + t1_dy = ft->tpl_height; + + delete ft; + + + dx = ref0_x - r0_x; + dy = ref0_y - r0_y; + + r0_x += dx; + r0_y += dy; + + r1_x += dx; + r1_y += dy; + + float w_org, w_ist, d_winkel; + + w_org = atan2(ref1_y - ref0_y, ref1_x - ref0_x); + w_ist = atan2(r1_y - r0_y, r1_x - r0_x); + + d_winkel = (w_org - w_ist) * 180 / M_PI; + + if (imageROI.length() > 0) + { + CImageBasis* imgzw = new CImageBasis(this); + imgzw->drawRect(r0_x, r0_y, t0_dx, t0_dy, 255, 0, 0, 2); + imgzw->drawRect(r1_x, r1_y, t1_dx, t1_dy, 255, 0, 0, 2); + imgzw->SaveToFile(imageROI); + printf("Alignment: alignment ROI created: %s\n", imageROI.c_str()); + delete imgzw; + } + + std::string zw = "\tdx:\t" + std::to_string(dx) + "\tdy:\t" + std::to_string(dy) + "\td_winkel:\t" + std::to_string(d_winkel); +// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw); + + CRotateImage rt(this, ImageTMP); + rt.Translate(dx, dy); + rt.Rotate(d_winkel, ref0_x, ref0_y); + printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel); +} + + + +void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy) +{ + + int x2, y2; + + x2 = x1 + dx; + y2 = y1 + dy; + x2 = std::min(x2, width - 1); + y2 = std::min(y2, height - 1); + + dx = x2 - x1; + dy = y2 - y1; + + int memsize = dx * dy * channels; + uint8_t* odata = (unsigned char*) GET_MEMORY(memsize); + + stbi_uc* p_target; + stbi_uc* p_source; + + RGBImageLock(); + + for (int x = x1; x < x2; ++x) + for (int y = y1; y < y2; ++y) + { + p_target = odata + (channels * ((y - y1) * dx + (x - x1))); + p_source = rgb_image + (channels * (y * width + x)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + + // stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 0); + stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata); + + RGBImageRelease(); + + stbi_image_free(odata); +} + +void CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *_target) +{ + int x2, y2; + + x2 = x1 + dx; + y2 = y1 + dy; + x2 = std::min(x2, width - 1); + y2 = std::min(y2, height - 1); + + dx = x2 - x1; + dy = y2 - y1; + + if ((_target->height != dy) || (_target->width != dx) || (_target->channels != channels)) + { + printf("CAlignAndCutImage::CutAndSave - Bildgröße passt nicht !!!!!!!!!"); + return; + } + + uint8_t* odata = _target->RGBImageLock(); + RGBImageLock(); + + stbi_uc* p_target; + stbi_uc* p_source; + + for (int x = x1; x < x2; ++x) + for (int y = y1; y < y2; ++y) + { + p_target = odata + (channels * ((y - y1) * dx + (x - x1))); + p_source = rgb_image + (channels * (y * width + x)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + + RGBImageRelease(); + _target->RGBImageRelease(); +} + + +CImageBasis* CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy) +{ + int x2, y2; + + x2 = x1 + dx; + y2 = y1 + dy; + x2 = std::min(x2, width - 1); + y2 = std::min(y2, height - 1); + + dx = x2 - x1; + dy = y2 - y1; + + int memsize = dx * dy * channels; + uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); + + stbi_uc* p_target; + stbi_uc* p_source; + + RGBImageLock(); + + for (int x = x1; x < x2; ++x) + for (int y = y1; y < y2; ++y) + { + p_target = odata + (channels * ((y - y1) * dx + (x - x1))); + p_source = rgb_image + (channels * (y * width + x)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + + CImageBasis* rs = new CImageBasis(odata, channels, dx, dy, bpp); + RGBImageRelease(); + rs->SetIndepended(); + return rs; +} diff --git a/code/components/jomjol_image_proc/CAlignAndCutImage.h b/code/components/jomjol_image_proc/CAlignAndCutImage.h new file mode 100644 index 00000000..92f4454a --- /dev/null +++ b/code/components/jomjol_image_proc/CAlignAndCutImage.h @@ -0,0 +1,18 @@ +#include "CImageBasis.h" + +class CAlignAndCutImage : public CImageBasis +{ + public: + int t0_dx, t0_dy, t1_dx, t1_dy; + CImageBasis *ImageTMP; + CAlignAndCutImage(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;}; + CAlignAndCutImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;}; + CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp); + + void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = ""); + void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy); + CImageBasis* CutAndSave(int x1, int y1, int dx, int dy); + void CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *_target); + void GetRefSize(int *ref_dx, int *ref_dy); +}; + diff --git a/code/components/jomjol_image_proc/CFindTemplate.cpp b/code/components/jomjol_image_proc/CFindTemplate.cpp index 69397e81..33f02eae 100644 --- a/code/components/jomjol_image_proc/CFindTemplate.cpp +++ b/code/components/jomjol_image_proc/CFindTemplate.cpp @@ -1,197 +1,26 @@ #include "CFindTemplate.h" -#include "Helper.h" -#include "ClassLogFile.h" - -#include "esp_system.h" - -#define _USE_MATH_DEFINES -#include -#include - -#define _ESP32_PSRAM - -using namespace std; - -#define GET_MEMORY malloc - -/* -CResizeImage::CResizeImage(std::string _image, int _new_dx, int _new_dy) -{ - CImageBasis::CImageBasis(_image); -} -*/ - -uint8_t CImageBasis::GetPixelColor(int x, int y, int ch) -{ - stbi_uc* p_source; - p_source = this->rgb_image + (this->channels * (y * this->width + x)); - return p_source[ch]; -} - -void CResizeImage::Resize(int _new_dx, int _new_dy) -{ - int memsize = _new_dx * _new_dy * this->channels; - uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); - - stbir_resize_uint8(this->rgb_image, this->width, this->height, 0, odata, _new_dx, _new_dy, 0, this->channels); - - stbi_image_free(this->rgb_image); - this->rgb_image = (unsigned char*)GET_MEMORY(memsize); - - this->memCopy(odata, this->rgb_image, memsize); - this->width = _new_dx; - this->height = _new_dy; - stbi_image_free(odata); -} - -void CRotate::Mirror(){ - int memsize = this->width * this->height * this->channels; - uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); - - int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; - - for (int x = 0; x < this->width; ++x) - for (int y = 0; y < this->height; ++y) - { - p_target = odata + (this->channels * (y * this->width + x)); - - x_source = this->width - x; - y_source = y; - - p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source)); - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = p_source[channels]; - } - - // memcpy(this->rgb_image, odata, memsize); - this->memCopy(odata, this->rgb_image, memsize); - stbi_image_free(odata); -} - -void CRotate::Rotate(float _angle, int _centerx, int _centery) -{ - float m[2][3]; - - float x_center = _centerx; - float y_center = _centery; - _angle = _angle / 180 * M_PI; - - m[0][0] = cos(_angle); - m[0][1] = sin(_angle); - m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center; - - m[1][0] = -m[0][1]; - m[1][1] = m[0][0]; - m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center; - - int memsize = this->width * this->height * this->channels; - uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); - - int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; - - for (int x = 0; x < this->width; ++x) - for (int y = 0; y < this->height; ++y) - { - p_target = odata + (this->channels * (y * this->width + x)); - - x_source = int(m[0][0] * x + m[0][1] * y); - y_source = int(m[1][0] * x + m[1][1] * y); - - x_source += int(m[0][2]); - y_source += int(m[1][2]); - - if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height)) - { - p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source)); - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = p_source[channels]; - } - else - { - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = 255; - } - } - - // memcpy(this->rgb_image, odata, memsize); - this->memCopy(odata, this->rgb_image, memsize); - stbi_image_free(odata); -} - -void CRotate::Rotate(float _angle) -{ - this->Rotate(_angle, this->width / 2, this->height / 2); -} - -void CRotate::Translate(int _dx, int _dy) -{ - int memsize = this->width * this->height * this->channels; - uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); - - - int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; - - for (int x = 0; x < this->width; ++x) - for (int y = 0; y < this->height; ++y) - { - p_target = odata + (this->channels * (y * this->width + x)); - - x_source = x - _dx; - y_source = y - _dy; - - if ((x_source >= 0) && (x_source < this->width) && (y_source >= 0) && (y_source < this->height)) - { - p_source = this->rgb_image + (this->channels * (y_source * this->width + x_source)); - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = p_source[channels]; - } - else - { - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = 255; - } - } - - // memcpy(this->rgb_image, odata, memsize); - this->memCopy(odata, this->rgb_image, memsize); - stbi_image_free(odata); -} - - - -CFindTemplate::CFindTemplate(std::string _image) -{ - this->channels = 1; - this->rgb_image = stbi_load(_image.c_str(), &(this->width), &(this->height), &(this->bpp), this->channels); -} void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y) { - this->FindTemplate(_template, found_x, found_y, 0, 0); + FindTemplate(_template, found_x, found_y, 0, 0); } void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy) { - uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, this->channels); + uint8_t* rgb_template = stbi_load(_template.c_str(), &tpl_width, &tpl_height, &tpl_bpp, channels); int ow, ow_start, ow_stop; int oh, oh_start, oh_stop; if (_dx == 0) { - _dx = this->width; + _dx = width; *found_x = 0; } if (_dy == 0) { - _dy = this->height; + _dy = height; *found_y = 0; } @@ -199,22 +28,24 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found ow_start = *found_x - _dx; ow_start = std::max(ow_start, 0); ow_stop = *found_x + _dx; - if ((ow_stop + tpl_width) > this->width) - ow_stop = this->width - tpl_width; + if ((ow_stop + tpl_width) > width) + ow_stop = width - tpl_width; ow = ow_stop - ow_start + 1; oh_start = *found_y - _dy; oh_start = std::max(oh_start, 0); oh_stop = *found_y + _dy; - if ((oh_stop + tpl_height) > this->height) - oh_stop = this->height - tpl_height; + if ((oh_stop + tpl_height) > height) + oh_stop = height - tpl_height; oh = oh_stop - oh_start + 1; - uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * this->channels); + uint8_t* odata = (unsigned char*)GET_MEMORY(ow * oh * channels); double aktSAD; double minSAD = pow(tpl_width * tpl_height * 255, 2); + RGBImageLock(); + for (int xouter = ow_start; xouter <= ow_stop; xouter++) for (int youter = oh_start; youter <= oh_stop; ++youter) { @@ -222,11 +53,11 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found for (int tpl_x = 0; tpl_x < tpl_width; tpl_x++) for (int tpl_y = 0; tpl_y < tpl_height; tpl_y++) { - stbi_uc* p_org = this->rgb_image + (this->channels * ((youter + tpl_y) * this->width + (xouter + tpl_x))); - stbi_uc* p_tpl = rgb_template + (this->channels * (tpl_y * tpl_width + tpl_x)); + stbi_uc* p_org = rgb_image + (channels * ((youter + tpl_y) * width + (xouter + tpl_x))); + stbi_uc* p_tpl = rgb_template + (channels * (tpl_y * tpl_width + tpl_x)); aktSAD += pow(p_tpl[0] - p_org[0], 2); } - stbi_uc* p_out = odata + (this->channels * ((youter - oh_start) * ow + (xouter - ow_start))); + stbi_uc* p_out = odata + (channels * ((youter - oh_start) * ow + (xouter - ow_start))); p_out[0] = int(sqrt(aktSAD / (tpl_width * tpl_height))); if (aktSAD < minSAD) @@ -237,7 +68,9 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found } } - stbi_write_bmp("sdcard\\find.bmp", ow, oh, this->channels, odata); + RGBImageRelease(); + + stbi_write_bmp("sdcard\\find.bmp", ow, oh, channels, odata); stbi_image_free(odata); stbi_image_free(rgb_template); @@ -245,303 +78,14 @@ void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout) { - this->FindTemplate(_template, found_x, found_y); - this->SaveToFile(_imageout); + FindTemplate(_template, found_x, found_y); + SaveToFile(_imageout); } void CFindTemplate::FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout) { - this->FindTemplate(_template, found_x, found_y, _dx, _dy); - this->SaveToFile(_imageout); + FindTemplate(_template, found_x, found_y, _dx, _dy); + SaveToFile(_imageout); } - -void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size) -{ -#ifdef _ESP32_PSRAM - for (int i = 0; i < _size; ++i) - *(_target + i) = *(_source + i); -#else - memcpy(_target, _source, _size); -#endif -} - -bool CImageBasis::isInImage(int x, int y) -{ - if ((x < 0) || (x > this->width - 1)) - return false; - - if ((y < 0) || (y > this->height- 1)) - return false; - - return true; -} - -void CImageBasis::setPixelColor(int x, int y, int r, int g, int b) -{ - stbi_uc* p_source; - - p_source = this->rgb_image + (this->channels * (y * this->width + x)); - p_source[0] = r; - if (this-> channels > 2) - { - p_source[1] = g; - p_source[2] = b; - } -} - -void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness) -{ - int zwx1, zwx2, zwy1, zwy2; - int _x, _y, _thick; - - zwx1 = x - thickness + 1; - zwx2 = x + dx + thickness - 1; - zwy1 = y; - zwy2 = y; - for (_thick = 0; _thick < thickness; _thick++) - for (_x = zwx1; _x <= zwx2; ++_x) - for (_y = zwy1; _y <= zwy2; _y++) - if (isInImage(_x, _y)) - setPixelColor(_x, _y - _thick, r, g, b); - - zwx1 = x - thickness + 1; - zwx2 = x + dx + thickness - 1; - zwy1 = y + dy; - zwy2 = y + dy; - for (_thick = 0; _thick < thickness; _thick++) - for (_x = zwx1; _x <= zwx2; ++_x) - for (_y = zwy1; _y <= zwy2; _y++) - if (isInImage(_x, _y)) - setPixelColor(_x, _y + _thick, r, g, b); - - zwx1 = x; - zwx2 = x; - zwy1 = y; - zwy2 = y + dy; - for (_thick = 0; _thick < thickness; _thick++) - for (_x = zwx1; _x <= zwx2; ++_x) - for (_y = zwy1; _y <= zwy2; _y++) - if (isInImage(_x, _y)) - setPixelColor(_x - _thick, _y, r, g, b); - - zwx1 = x + dx; - zwx2 = x + dx; - zwy1 = y; - zwy2 = y + dy; - for (_thick = 0; _thick < thickness; _thick++) - for (_x = zwx1; _x <= zwx2; ++_x) - for (_y = zwy1; _y <= zwy2; _y++) - if (isInImage(_x, _y)) - setPixelColor(_x + _thick, _y, r, g, b); - -} - -void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness) -{ - int _x, _y, _thick; - int _zwy1, _zwy2; - thickness = (thickness-1) / 2; - - for (_thick = 0; _thick <= thickness; ++_thick) - for (_x = x1 - _thick; _x <= x2 + _thick; ++_x) - { - if (x2 == x1) - { - _zwy1 = y1; - _zwy2 = y2; - } - else - { - _zwy1 = (y2 - y1) * (float)(_x - x1) / (float)(x2 - x1) + y1; - _zwy2 = (y2 - y1) * (float)(_x + 1 - x1) / (float)(x2 - x1) + y1; - } - - for (_y = _zwy1 - _thick; _y <= _zwy2 + _thick; _y++) - if (isInImage(_x, _y)) - setPixelColor(_x, _y, r, g, b); - } -} - -void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness) -{ - float deltarad, aktrad; - int _thick, _x, _y; - - deltarad = 1 / (4 * M_PI * (rad + thickness - 1)); - - for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad) - for (_thick = 0; _thick < thickness; ++_thick) - { - _x = sin(aktrad) * (rad + _thick) + x1; - _y = cos(aktrad) * (rad + _thick) + y1; - if (isInImage(_x, _y)) - setPixelColor(_x, _y, r, g, b); - } -} - -CImageBasis::CImageBasis() -{ - this->externalImage = false; -} - -CImageBasis::CImageBasis(std::string _image) -{ - channels = 3; - externalImage = false; - filename = _image; -// long freebefore = esp_get_free_heap_size(); - - rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels); -// if (rgb_image == NULL) -// LogFile.WriteToFile("Image Load failed:" + _image + " FreeHeapSize before: " + to_string(freebefore) + " after: " + to_string(esp_get_free_heap_size())); - // printf("CImageBasis after load\n"); - // printf("w %d, h %d, b %d, c %d", this->width, this->height, this->bpp, this->channels); -} - -bool CImageBasis::ImageOkay(){ - return rgb_image != NULL; -} - -CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) -{ - this->rgb_image = _rgb_image; - this->channels = _channels; - this->width = _width; - this->height = _height; - this->bpp = _bpp; - this->externalImage = true; -} - -void CImageBasis::Contrast(float _contrast) //input range [-100..100] -{ - stbi_uc* p_source; - - float contrast = (_contrast/100) + 1; //convert to decimal & shift range: [0..2] - float intercept = 128 * (1 - contrast); - - for (int x = 0; x < width; ++x) - for (int y = 0; y < height; ++y) - { - p_source = this->rgb_image + (this->channels * (y * this->width + x)); - for (int channels = 0; channels < this->channels; ++channels) - p_source[channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[channels] * contrast + intercept))); - } -} - -CImageBasis::~CImageBasis() -{ - if (!this->externalImage) - stbi_image_free(this->rgb_image); -} - -void CImageBasis::SaveToFile(std::string _imageout) -{ - string typ = getFileType(_imageout); - - if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM ESP32 - { - stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0); - } - - if ((typ == "bmp") || (typ == "BMP")) - { - stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image); - } - // stbi_write_jpg(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image, 0); - // stbi_write_bmp(_imageout.c_str(), this->width, this->height, this->channels, this->rgb_image); -} - - - -void CAlignAndCutImage::Align(std::string _template0, int ref0_x, int ref0_y, std::string _template1, int ref1_x, int ref1_y, int deltax, int deltay, std::string imageROI) -{ - int dx, dy; - int r0_x, r0_y, r1_x, r1_y; - - CFindTemplate* ft = new CFindTemplate(this->filename); - - r0_x = ref0_x; - r0_y = ref0_y; - ft->FindTemplate(_template0, &r0_x, &r0_y, deltax, deltay); - t0_dx = ft->tpl_width; - t0_dy = ft->tpl_height; - - r1_x = ref1_x; - r1_y = ref1_y; - ft->FindTemplate(_template1, &r1_x, &r1_y, deltax, deltay); - t1_dx = ft->tpl_width; - t1_dy = ft->tpl_height; - - delete ft; - - - dx = ref0_x - r0_x; - dy = ref0_y - r0_y; - - r0_x += dx; - r0_y += dy; - - r1_x += dx; - r1_y += dy; - - float w_org, w_ist, d_winkel; - - w_org = atan2(ref1_y - ref0_y, ref1_x - ref0_x); - w_ist = atan2(r1_y - r0_y, r1_x - r0_x); - - d_winkel = (w_org - w_ist) * 180 / M_PI; - - if (imageROI.length() > 0) - { - CImageBasis* imgzw = new CImageBasis(this->filename); - imgzw->drawRect(r0_x, r0_y, t0_dx, t0_dy, 255, 0, 0, 2); - imgzw->drawRect(r1_x, r1_y, t1_dx, t1_dy, 255, 0, 0, 2); - imgzw->SaveToFile(imageROI); - printf("Alignment: alignment ROI created: %s\n", imageROI.c_str()); - delete imgzw; - } - - string zw = "\tdx:\t" + to_string(dx) + "\tdy:\t" + to_string(dy) + "\td_winkel:\t" + to_string(d_winkel); - LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw); - - CRotate rt(this->rgb_image, this->channels, this->width, this->height, this->bpp); - rt.Translate(dx, dy); - rt.Rotate(d_winkel, ref0_x, ref0_y); - printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel); -} - -void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int dx, int dy) -{ - - int x2, y2; - - x2 = x1 + dx; - y2 = y1 + dy; - x2 = min(x2, this->width - 1); - y2 = min(y2, this->height - 1); - - dx = x2 - x1; - dy = y2 - y1; - - int memsize = dx * dy * this->channels; - uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); - - stbi_uc* p_target; - stbi_uc* p_source; - - for (int x = x1; x < x2; ++x) - for (int y = y1; y < y2; ++y) - { - p_target = odata + (this->channels * ((y - y1) * dx + (x - x1))); - p_source = this->rgb_image + (this->channels * (y * this->width + x)); - for (int channels = 0; channels < this->channels; ++channels) - p_target[channels] = p_source[channels]; - } - - // stbi_write_jpg(_template1.c_str(), dx, dy, this->channels, odata, 0); - stbi_write_bmp(_template1.c_str(), dx, dy, this->channels, odata); - - stbi_image_free(odata); -} diff --git a/code/components/jomjol_image_proc/CFindTemplate.h b/code/components/jomjol_image_proc/CFindTemplate.h index 0023d666..c32c6672 100644 --- a/code/components/jomjol_image_proc/CFindTemplate.h +++ b/code/components/jomjol_image_proc/CFindTemplate.h @@ -1,98 +1,16 @@ -#pragma once +#include "CImageBasis.h" -#ifndef __CFINDTEMPLATE -#define __CFINGTEMPLATE - -#include -#include - -#define _USE_MATH_DEFINES -#include - -#include "stb_image.h" -#include "stb_image_write.h" -#include "stb_image_resize.h" - - -class CImageBasis -{ - protected: - uint8_t* rgb_image; - int channels; - int width, height, bpp; - bool externalImage; - std::string filename; - - void memCopy(uint8_t* _source, uint8_t* _target, int _size); - bool isInImage(int x, int y); - - public: - int getWidth(){return this->width;}; - int getHeight(){return this->height;}; - int getChannels(){return this->channels;}; - void drawRect(int x, int y, int dx, int dy, int r = 255, int g = 255, int b = 255, int thickness = 1); - void drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness = 1); - void drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness = 1); - void setPixelColor(int x, int y, int r, int g, int b); - void Contrast(float _contrast); - bool ImageOkay(); - - - CImageBasis(); - CImageBasis(std::string _image); - CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp); - uint8_t GetPixelColor(int x, int y, int ch); - - ~CImageBasis(); - - void SaveToFile(std::string _imageout); -}; - class CFindTemplate : public CImageBasis { public: int tpl_width, tpl_height, tpl_bpp; - CFindTemplate(std::string _image); +// CFindTemplate(std::string _image); + CFindTemplate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {}; + void FindTemplate(std::string _template, int* found_x, int* found_y, std::string _imageout); void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy, std::string _imageout); void FindTemplate(std::string _template, int* found_x, int* found_y); void FindTemplate(std::string _template, int* found_x, int* found_y, int _dx, int _dy); -}; - -class CRotate: public CImageBasis -{ - public: - CRotate(std::string _image) : CImageBasis(_image) {}; - CRotate(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {}; - - void Rotate(float _angle); - void Rotate(float _angle, int _centerx, int _centery); - void Translate(int _dx, int _dy); - void Mirror(); -}; - - -class CAlignAndCutImage : public CImageBasis -{ - public: - int t0_dx, t0_dy, t1_dx, t1_dy; - CAlignAndCutImage(std::string _image) : CImageBasis(_image) {}; - - void Align(std::string _template1, int x1, int y1, std::string _template2, int x2, int y2, int deltax = 40, int deltay = 40, std::string imageROI = ""); - void CutAndSave(std::string _template1, int x1, int y1, int dx, int dy); -}; - - -class CResizeImage : public CImageBasis -{ -public: - CResizeImage(std::string _image) : CImageBasis(_image) {}; -// CResizeImage(std::string _image, int _new_dx, int _new_dy); - void Resize(int _new_dx, int _new_dy); -}; - - -#endif - +}; \ No newline at end of file diff --git a/code/components/jomjol_image_proc/CImageBasis.cpp b/code/components/jomjol_image_proc/CImageBasis.cpp new file mode 100644 index 00000000..b850210c --- /dev/null +++ b/code/components/jomjol_image_proc/CImageBasis.cpp @@ -0,0 +1,523 @@ +#include "CImageBasis.h" +#include "Helper.h" +#include "ClassLogFile.h" + +#include + +#include "esp_system.h" + +#include + + +#define _USE_MATH_DEFINES +#include +#include + +#define _ESP32_PSRAM + +using namespace std; + +static const char *TAG = "CImageBasis"; + +//#define DEBUG_DETAIL_ON + + + +uint8_t * CImageBasis::RGBImageLock(int _waitmaxsec) +{ + if (islocked) + { +#ifdef DEBUG_DETAIL_ON + printf("Image is locked: sleep for : %ds\n", _waitmaxsec); +#endif + TickType_t xDelay; + xDelay = 1000 / portTICK_PERIOD_MS; + for (int i = 0; i <= _waitmaxsec; ++i) + { + vTaskDelay( xDelay ); + if (!islocked) + break; + } + } + + if (islocked) + return NULL; + + return rgb_image; +} + +void CImageBasis::RGBImageRelease() +{ + islocked = false; +} + +uint8_t * CImageBasis::RGBImageGet() +{ + return rgb_image; +} + + + +void writejpghelp(void *context, void *data, int size) +{ +// printf("Size all: %d, size %d\n", ((ImageData*)context)->size, size); + ImageData* _zw = (ImageData*) context; + uint8_t *voidstart = _zw->data; + uint8_t *datastart = (uint8_t*) data; + voidstart += _zw->size; + + for (int i = 0; i < size; ++i) + *(voidstart + i) = *(datastart + i); + + _zw->size += size; +} + + + + +ImageData* CImageBasis::writeToMemoryAsJPG(const int quality) +{ + ImageData* ii = new ImageData; + + RGBImageLock(); + stbi_write_jpg_to_func(writejpghelp, ii, width, height, channels, rgb_image, quality); + RGBImageRelease(); + + return ii; +} + +#define HTTP_BUFFER_SENT 1024 + +struct SendJPGHTTP +{ + httpd_req_t *req; + esp_err_t res; + char buf[HTTP_BUFFER_SENT]; + int size = 0; +}; + +inline void writejpgtohttphelp(void *context, void *data, int size) +{ + SendJPGHTTP* _send = (SendJPGHTTP*) context; + if ((_send->size + size) >= HTTP_BUFFER_SENT) // data passt nich mehr in buffer + { + httpd_req_t *_req = _send->req; + if (httpd_resp_send_chunk(_req, _send->buf, _send->size) != ESP_OK) + { + ESP_LOGE(TAG, "File sending failed!"); + _send->res = ESP_FAIL; + } + _send->size = 0; + } + std::memcpy((void*) (&(_send->buf[0]) + _send->size), data, size); + _send->size+= size; +} + + + +esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality) +{ + SendJPGHTTP ii; + ii.req = _req; + ii.res = ESP_OK; + ii.size = 0; + + RGBImageLock(); + stbi_write_jpg_to_func(writejpgtohttphelp, &ii, width, height, channels, rgb_image, quality); + RGBImageRelease(); + + if (ii.size > 0) + { + if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) // verschicke noch den Rest + { + ESP_LOGE(TAG, "File sending failed!"); + ii.res = ESP_FAIL; + } + } + + return ii.res; +} + + + +bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size) +{ + int gr = height * width * channels; + if (gr != _size) // Größe passt nicht + { + printf("Kann Bild nicht von Speicher kopierte - Größen passen nicht zusammen: soll %d, ist %d\n", _size, gr); + return false; + } + + RGBImageLock(); + memCopy(_source, rgb_image, _size); + RGBImageRelease(); + + return true; +} + +uint8_t CImageBasis::GetPixelColor(int x, int y, int ch) +{ + stbi_uc* p_source; + p_source = rgb_image + (channels * (y * width + x)); + return p_source[ch]; +} + + +void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size) +{ +#ifdef _ESP32_PSRAM + for (int i = 0; i < _size; ++i) + *(_target + i) = *(_source + i); +#else + memcpy(_target, _source, _size); +#endif +} + +bool CImageBasis::isInImage(int x, int y) +{ + if ((x < 0) || (x > width - 1)) + return false; + + if ((y < 0) || (y > height- 1)) + return false; + + return true; +} + +void CImageBasis::setPixelColor(int x, int y, int r, int g, int b) +{ + stbi_uc* p_source; + + RGBImageLock(); + p_source = rgb_image + (channels * (y * width + x)); + p_source[0] = r; + if ( channels > 2) + { + p_source[1] = g; + p_source[2] = b; + } + RGBImageRelease(); +} + +void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness) +{ + int zwx1, zwx2, zwy1, zwy2; + int _x, _y, _thick; + + zwx1 = x - thickness + 1; + zwx2 = x + dx + thickness - 1; + zwy1 = y; + zwy2 = y; + for (_thick = 0; _thick < thickness; _thick++) + for (_x = zwx1; _x <= zwx2; ++_x) + for (_y = zwy1; _y <= zwy2; _y++) + if (isInImage(_x, _y)) + setPixelColor(_x, _y - _thick, r, g, b); + + zwx1 = x - thickness + 1; + zwx2 = x + dx + thickness - 1; + zwy1 = y + dy; + zwy2 = y + dy; + for (_thick = 0; _thick < thickness; _thick++) + for (_x = zwx1; _x <= zwx2; ++_x) + for (_y = zwy1; _y <= zwy2; _y++) + if (isInImage(_x, _y)) + setPixelColor(_x, _y + _thick, r, g, b); + + zwx1 = x; + zwx2 = x; + zwy1 = y; + zwy2 = y + dy; + for (_thick = 0; _thick < thickness; _thick++) + for (_x = zwx1; _x <= zwx2; ++_x) + for (_y = zwy1; _y <= zwy2; _y++) + if (isInImage(_x, _y)) + setPixelColor(_x - _thick, _y, r, g, b); + + zwx1 = x + dx; + zwx2 = x + dx; + zwy1 = y; + zwy2 = y + dy; + for (_thick = 0; _thick < thickness; _thick++) + for (_x = zwx1; _x <= zwx2; ++_x) + for (_y = zwy1; _y <= zwy2; _y++) + if (isInImage(_x, _y)) + setPixelColor(_x + _thick, _y, r, g, b); + +} + +void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness) +{ + int _x, _y, _thick; + int _zwy1, _zwy2; + thickness = (thickness-1) / 2; + + for (_thick = 0; _thick <= thickness; ++_thick) + for (_x = x1 - _thick; _x <= x2 + _thick; ++_x) + { + if (x2 == x1) + { + _zwy1 = y1; + _zwy2 = y2; + } + else + { + _zwy1 = (y2 - y1) * (float)(_x - x1) / (float)(x2 - x1) + y1; + _zwy2 = (y2 - y1) * (float)(_x + 1 - x1) / (float)(x2 - x1) + y1; + } + + for (_y = _zwy1 - _thick; _y <= _zwy2 + _thick; _y++) + if (isInImage(_x, _y)) + setPixelColor(_x, _y, r, g, b); + } +} + +void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness) +{ + float deltarad, aktrad; + int _thick, _x, _y; + + deltarad = 1 / (4 * M_PI * (rad + thickness - 1)); + + for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad) + for (_thick = 0; _thick < thickness; ++_thick) + { + _x = sin(aktrad) * (rad + _thick) + x1; + _y = cos(aktrad) * (rad + _thick) + y1; + if (isInImage(_x, _y)) + setPixelColor(_x, _y, r, g, b); + } +} + +CImageBasis::CImageBasis() +{ + externalImage = false; + rgb_image = NULL; + width = 0; + height = 0; + channels = 0; + islocked = false; +} + +void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels) +{ + bpp = _channels; + width = _width; + height = _height; + channels = _channels; + + RGBImageLock(); + + + int memsize = width * height * channels; + rgb_image = (unsigned char*)GET_MEMORY(memsize); + + + stbi_uc* p_source; + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_source = rgb_image + (channels * (y * width + x)); + for (int _channels = 0; _channels < channels; ++_channels) + p_source[_channels] = (uint8_t) 0; + } + + RGBImageRelease(); + + +} + +void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len) +{ + RGBImageLock(); + if (rgb_image) + stbi_image_free(rgb_image); + rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3); + bpp = channels; + printf("Image loaded from memory: %d, %d, %d\n", width, height, channels); + RGBImageRelease(); +} + +CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat) +{ + islocked = false; + externalImage = false; + channels = _copyfrom->channels; + width = _copyfrom->width; + height = _copyfrom->height; + bpp = _copyfrom->bpp; + + RGBImageLock(); + + int memsize = width * height * channels; + rgb_image = (unsigned char*)GET_MEMORY(memsize); + + TickType_t xDelay; + int anz = 1; + while (!rgb_image && (anz < _anzrepeat)) + { + printf("Create Image from Copy - Speicher ist voll - Versuche es erneut: %d.\n", anz); + xDelay = 1000 / portTICK_PERIOD_MS; + rgb_image = (unsigned char*) malloc(memsize); + anz++; + } + + + if (!rgb_image) + { + printf(getESPHeapInfo().c_str()); + printf("\nKein freier Speicher mehr!!!! Benötigt: %d %d %d %d\n", width, height, channels, memsize); + RGBImageRelease(); + return; + } + + memCopy(_copyfrom->rgb_image, rgb_image, memsize); + RGBImageRelease(); +} + +CImageBasis::CImageBasis(int _width, int _height, int _channels) +{ + islocked = false; + externalImage = false; + channels = _channels; + width = _width; + height = _height; + bpp = _channels; + + int memsize = width * height * channels; + + rgb_image = (unsigned char*)GET_MEMORY(memsize); + if (!rgb_image) + { + printf(getESPHeapInfo().c_str()); + printf("\nKein freier Speicher mehr!!!! Benötigt: %d %d %d %d\n", width, height, channels, memsize); + return; + } +} + + +CImageBasis::CImageBasis(std::string _image) +{ + islocked = false; + channels = 3; + externalImage = false; + filename = _image; + long zwld = esp_get_free_heap_size(); + printf("freeheapsize before: %ld\n", zwld); + + RGBImageLock(); + rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels); + RGBImageRelease(); + + zwld = esp_get_free_heap_size(); + printf("freeheapsize after : %ld\n", zwld); + + std::string zw = "Image Load failed:" + _image + "\n"; + if (rgb_image == NULL) + printf(zw.c_str()); + zw = "CImageBasis after load " + _image + "\n"; + printf(zw.c_str()); + printf("w %d, h %d, b %d, c %d\n", width, height, bpp, channels); + +} + +bool CImageBasis::ImageOkay(){ + return rgb_image != NULL; +} + +CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) +{ + islocked = false; + rgb_image = _rgb_image; + channels = _channels; + width = _width; + height = _height; + bpp = _bpp; + externalImage = true; +} + +void CImageBasis::Contrast(float _contrast) //input range [-100..100] +{ + stbi_uc* p_source; + + float contrast = (_contrast/100) + 1; //convert to decimal & shift range: [0..2] + float intercept = 128 * (1 - contrast); + + RGBImageLock(); + + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_source = rgb_image + (channels * (y * width + x)); + for (int _channels = 0; _channels < channels; ++_channels) + p_source[_channels] = (uint8_t) std::min(255, std::max(0, (int) (p_source[_channels] * contrast + intercept))); + } + + RGBImageRelease(); +} + +CImageBasis::~CImageBasis() +{ + RGBImageLock(); + if (!externalImage) + stbi_image_free(rgb_image); +} + +void CImageBasis::SaveToFile(std::string _imageout) +{ + string typ = getFileType(_imageout); + + RGBImageLock(); + + if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM ESP32 + { + stbi_write_jpg(_imageout.c_str(), width, height, channels, rgb_image, 0); + } + + if ((typ == "bmp") || (typ == "BMP")) + { + stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image); + } + RGBImageRelease(); +} + + +void CImageBasis::Resize(int _new_dx, int _new_dy) +{ + int memsize = _new_dx * _new_dy * channels; + uint8_t* odata = (unsigned char*)GET_MEMORY(memsize); + + RGBImageLock(); + + + stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels); + + stbi_image_free(rgb_image); + rgb_image = (unsigned char*)GET_MEMORY(memsize); + + memCopy(odata, rgb_image, memsize); + RGBImageRelease(); + + width = _new_dx; + height = _new_dy; + stbi_image_free(odata); +} + +void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target) +{ + if ((_target->height != _new_dy) || (_target->width != _new_dx) || (_target->channels != channels)) + { + printf("CImageBasis::Resize - Targetbildgröße passt nicht !!!!!!!!!"); + return; + } + + RGBImageLock(); + + uint8_t* odata = _target->rgb_image; + stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels); + RGBImageRelease(); +} + diff --git a/code/components/jomjol_image_proc/CImageBasis.h b/code/components/jomjol_image_proc/CImageBasis.h new file mode 100644 index 00000000..c754aa24 --- /dev/null +++ b/code/components/jomjol_image_proc/CImageBasis.h @@ -0,0 +1,94 @@ +#pragma once + +#ifndef __CIMAGEBASIS +#define __CIMAGEBASIS + +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +#include "stb_image.h" +#include "stb_image_write.h" +#include "stb_image_resize.h" + +#include "esp_heap_caps.h" + +//#define GET_MEMORY malloc +#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM) + + +#define MAX_JPG_SIZE 128000 + + +struct ImageData +{ + uint8_t data[MAX_JPG_SIZE]; + size_t size = 0; +}; + + + +class CImageBasis +{ + protected: + bool externalImage; + std::string filename; + + void memCopy(uint8_t* _source, uint8_t* _target, int _size); + bool isInImage(int x, int y); + + bool islocked; + + public: + uint8_t* rgb_image; + int channels; + int width, height, bpp; + + uint8_t * RGBImageLock(int _waitmaxsec = 60); + void RGBImageRelease(); + uint8_t * RGBImageGet(); + + int getWidth(){return this->width;}; + int getHeight(){return this->height;}; + int getChannels(){return this->channels;}; + void drawRect(int x, int y, int dx, int dy, int r = 255, int g = 255, int b = 255, int thickness = 1); + void drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness = 1); + void drawCircle(int x1, int y1, int rad, int r, int g, int b, int thickness = 1); + void setPixelColor(int x, int y, int r, int g, int b); + void Contrast(float _contrast); + bool ImageOkay(); + bool CopyFromMemory(uint8_t* _source, int _size); + + void SetIndepended(){externalImage = false;}; + + void CreateEmptyImage(int _width, int _height, int _channels); + + + CImageBasis(); + CImageBasis(std::string _image); + CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp); + CImageBasis(int _width, int _height, int _channels); + CImageBasis(CImageBasis *_copyfrom, int _anzrepeat = 0); + + void Resize(int _new_dx, int _new_dy); + void Resize(int _new_dx, int _new_dy, CImageBasis *_target); + + void LoadFromMemory(stbi_uc *_buffer, int len); + + ImageData* writeToMemoryAsJPG(const int quality = 90); + + esp_err_t SendJPGtoHTTP(httpd_req_t *req, const int quality = 90); + + uint8_t GetPixelColor(int x, int y, int ch); + + ~CImageBasis(); + + void SaveToFile(std::string _imageout); +}; + + +#endif + diff --git a/code/components/jomjol_image_proc/CMakeLists.txt b/code/components/jomjol_image_proc/CMakeLists.txt index df20b56b..806966b1 100644 --- a/code/components/jomjol_image_proc/CMakeLists.txt +++ b/code/components/jomjol_image_proc/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES jomjol_helper jomjol_logfile) + REQUIRES jomjol_helper jomjol_logfile esp_http_server) diff --git a/code/components/jomjol_image_proc/CRotateImage.cpp b/code/components/jomjol_image_proc/CRotateImage.cpp new file mode 100644 index 00000000..e40efda5 --- /dev/null +++ b/code/components/jomjol_image_proc/CRotateImage.cpp @@ -0,0 +1,192 @@ +#include "CRotateImage.h" + + +CRotateImage::CRotateImage(CImageBasis *_org, CImageBasis *_temp) +{ + rgb_image = _org->rgb_image; + channels = _org->channels; + width = _org->width; + height = _org->height; + bpp = _org->bpp; + externalImage = true; + ImageTMP = _temp; + islocked = false; +} + +void CRotateImage::Mirror(){ + int memsize = width * height * channels; + uint8_t* odata; + if (ImageTMP) + { + odata = ImageTMP->RGBImageLock(); + } + else + { + odata = (unsigned char*)GET_MEMORY(memsize); + } + + + int x_source, y_source; + stbi_uc* p_target; + stbi_uc* p_source; + + RGBImageLock(); + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_target = odata + (channels * (y * width + x)); + + x_source = width - x; + y_source = y; + + p_source = rgb_image + (channels * (y_source * width + x_source)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + + // memcpy(rgb_image, odata, memsize); + memCopy(odata, rgb_image, memsize); + if (!ImageTMP) + stbi_image_free(odata); + + if (ImageTMP) + ImageTMP->RGBImageRelease(); + + RGBImageRelease(); +} + +void CRotateImage::Rotate(float _angle, int _centerx, int _centery) +{ + float m[2][3]; + + float x_center = _centerx; + float y_center = _centery; + _angle = _angle / 180 * M_PI; + + m[0][0] = cos(_angle); + m[0][1] = sin(_angle); + m[0][2] = (1 - m[0][0]) * x_center - m[0][1] * y_center; + + m[1][0] = -m[0][1]; + m[1][1] = m[0][0]; + m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center; + + int memsize = width * height * channels; + uint8_t* odata; + if (ImageTMP) + { + odata = ImageTMP->RGBImageLock(); + } + else + { + odata = (unsigned char*)GET_MEMORY(memsize); + } + + + int x_source, y_source; + stbi_uc* p_target; + stbi_uc* p_source; + + RGBImageLock(); + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_target = odata + (channels * (y * width + x)); + + x_source = int(m[0][0] * x + m[0][1] * y); + y_source = int(m[1][0] * x + m[1][1] * y); + + x_source += int(m[0][2]); + y_source += int(m[1][2]); + + if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height)) + { + p_source = rgb_image + (channels * (y_source * width + x_source)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + else + { + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = 255; + } + } + + // memcpy(rgb_image, odata, memsize); + memCopy(odata, rgb_image, memsize); + + if (!ImageTMP) + { + stbi_image_free(odata); + } + if (ImageTMP) + ImageTMP->RGBImageRelease(); + + RGBImageRelease(); +} + +void CRotateImage::Rotate(float _angle) +{ +// printf("width %d, height %d\n", width, height); + Rotate(_angle, width / 2, height / 2); +} + +void CRotateImage::Translate(int _dx, int _dy) +{ + int memsize = width * height * channels; + uint8_t* odata; + if (ImageTMP) + { + odata = ImageTMP->RGBImageLock(); + } + else + { + odata = (unsigned char*)GET_MEMORY(memsize); + } + + + + int x_source, y_source; + stbi_uc* p_target; + stbi_uc* p_source; + + RGBImageLock(); + + for (int x = 0; x < width; ++x) + for (int y = 0; y < height; ++y) + { + p_target = odata + (channels * (y * width + x)); + + x_source = x - _dx; + y_source = y - _dy; + + if ((x_source >= 0) && (x_source < width) && (y_source >= 0) && (y_source < height)) + { + p_source = rgb_image + (channels * (y_source * width + x_source)); + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = p_source[_channels]; + } + else + { + for (int _channels = 0; _channels < channels; ++_channels) + p_target[_channels] = 255; + } + } + + // memcpy(rgb_image, odata, memsize); + memCopy(odata, rgb_image, memsize); + if (!ImageTMP) + { + stbi_image_free(odata); + } + + if (ImageTMP) + { + ImageTMP->RGBImageRelease(); + } + RGBImageRelease(); + +} + diff --git a/code/components/jomjol_image_proc/CRotateImage.h b/code/components/jomjol_image_proc/CRotateImage.h new file mode 100644 index 00000000..ccd362b4 --- /dev/null +++ b/code/components/jomjol_image_proc/CRotateImage.h @@ -0,0 +1,16 @@ +#include "CImageBasis.h" + + +class CRotateImage: public CImageBasis +{ + public: + CImageBasis *ImageTMP; + CRotateImage(std::string _image) : CImageBasis(_image) {ImageTMP = NULL;}; + CRotateImage(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : CImageBasis(_rgb_image, _channels, _width, _height, _bpp) {ImageTMP = NULL;}; + CRotateImage(CImageBasis *_org, CImageBasis *_temp); + + void Rotate(float _angle); + void Rotate(float _angle, int _centerx, int _centery); + void Translate(int _dx, int _dy); + void Mirror(); +}; diff --git a/code/components/jomjol_logfile/ClassLogFile.cpp b/code/components/jomjol_logfile/ClassLogFile.cpp index 78b0df19..ad525fd5 100644 --- a/code/components/jomjol_logfile/ClassLogFile.cpp +++ b/code/components/jomjol_logfile/ClassLogFile.cpp @@ -10,6 +10,48 @@ static const char *TAG = "log"; ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt"); +void ClassLogFile::WriteHeapInfo(std::string _id) +{ + std::string _zw; + _zw = "\t" + _id + "\t" + getESPHeapInfo(); + WriteToFile(_zw); +} + + +std::string ClassLogFile::getESPHeapInfo(){ + string espInfoResultStr = ""; + char aMsgBuf[80]; + + multi_heap_info_t aMultiHead_info ; + heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT); + size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); + size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT); + size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT); + sprintf(aMsgBuf,"Free Heap Size: \t%ld", (long) aFreeHeapSize); + size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM); + size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + + sprintf(aMsgBuf,"\tHeap:\t%ld", (long) aFreeHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tMin Free:\t%ld", (long) aMinFreeHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tlarg. Block: \t%ld", (long) aHeapLargestFreeBlockSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tSPI Heap:\t%ld", (long) aFreeSPIHeapSize); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tMin Free Heap Size:\t%ld", (long) aMinFreeHeadSize); + sprintf(aMsgBuf,"\tNOT_SPI Heap:\t%ld", (long) (aFreeHeapSize - aFreeSPIHeapSize)); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tlargest Block Size: \t%ld", (long) aHeapLargestFreeBlockSize); + sprintf(aMsgBuf,"\tInternal Heap:\t%ld", (long) (aFreeInternalHeapSize)); + espInfoResultStr += string(aMsgBuf); + sprintf(aMsgBuf,"\tInternal Min Heap free:\t%ld", (long) (aMinFreeInternalHeapSize)); + espInfoResultStr += string(aMsgBuf); + return espInfoResultStr; +} + void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool _time) { FILE* pFile; @@ -19,7 +61,10 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool return; } +// pFile = OpenFileAndWait(_fn.c_str(), "a"); pFile = fopen(_fn.c_str(), "a+"); + printf("Logfile opened: %s\n", _fn.c_str()); + if (pFile!=NULL) { if (_time) { @@ -54,6 +99,7 @@ void ClassLogFile::SetRetention(unsigned short _retentionInDays){ void ClassLogFile::WriteToFile(std::string info, bool _time) { +/* struct stat path_stat; if (stat(logroot.c_str(), &path_stat) != 0) { ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str()); @@ -61,7 +107,7 @@ void ClassLogFile::WriteToFile(std::string info, bool _time) ESP_LOGI(TAG, "Can't create log foolder"); } } - +*/ time_t rawtime; struct tm* timeinfo; char buffer[30]; @@ -79,12 +125,12 @@ std::string ClassLogFile::GetCurrentFileName() { time_t rawtime; struct tm* timeinfo; - char buffer[30]; + char buffer[60]; time(&rawtime); timeinfo = localtime(&rawtime); - strftime(buffer, 30, logfile.c_str(), timeinfo); + strftime(buffer, 60, logfile.c_str(), timeinfo); std::string logpath = logroot + "/" + buffer; return logpath; diff --git a/code/components/jomjol_logfile/ClassLogFile.h b/code/components/jomjol_logfile/ClassLogFile.h index 8f7841ba..b4a3429c 100644 --- a/code/components/jomjol_logfile/ClassLogFile.h +++ b/code/components/jomjol_logfile/ClassLogFile.h @@ -12,6 +12,10 @@ private: public: ClassLogFile(std::string _logpath, std::string _logfile); + std::string getESPHeapInfo(); + + void WriteHeapInfo(std::string _id); + void SwitchOnOff(bool _doLogFile); void SetRetention(unsigned short _retentionInDays); diff --git a/code/components/jomjol_mqtt/interface_mqtt.cpp b/code/components/jomjol_mqtt/interface_mqtt.cpp index dfa30408..dec910b5 100644 --- a/code/components/jomjol_mqtt/interface_mqtt.cpp +++ b/code/components/jomjol_mqtt/interface_mqtt.cpp @@ -64,10 +64,18 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_ mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data); } -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, std::string _LWTContext, int _keepalive){ + std::string _zwmessage = "connection lost"; + + int _lzw = _zwmessage.length(); + esp_mqtt_client_config_t mqtt_cfg = { .uri = _mqttURI.c_str(), .client_id = _clientid.c_str(), + .lwt_topic = _LWTContext.c_str(), + .lwt_msg = _zwmessage.c_str(), + .lwt_msg_len = _lzw, + .keepalive = _keepalive }; if (_user.length() && _password.length()){ @@ -79,4 +87,6 @@ void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, st client = esp_mqtt_client_init(&mqtt_cfg); esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client); esp_mqtt_client_start(client); + + MQTTPublish(_LWTContext, ""); } diff --git a/code/components/jomjol_mqtt/interface_mqtt.h b/code/components/jomjol_mqtt/interface_mqtt.h index c34c93a6..7ca5fa64 100644 --- a/code/components/jomjol_mqtt/interface_mqtt.h +++ b/code/components/jomjol_mqtt/interface_mqtt.h @@ -1,4 +1,7 @@ #include -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, std::string _LWTContext, int _keepalive); + +//void MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user = "", std::string _password = ""); + void MQTTPublish(std::string _key, std::string _content); \ No newline at end of file diff --git a/code/components/jomjol_tfliteclass/CMakeLists.txt b/code/components/jomjol_tfliteclass/CMakeLists.txt index 8d140751..7c2c5594 100644 --- a/code/components/jomjol_tfliteclass/CMakeLists.txt +++ b/code/components/jomjol_tfliteclass/CMakeLists.txt @@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*) idf_component_register(SRCS ${app_sources} INCLUDE_DIRS "." - REQUIRES jomjol_image_proc jomjol_logfile esp_http_server esp32-camera-master jomjol_controlcamera jomjol_flowcontroll) + REQUIRES jomjol_image_proc jomjol_logfile esp_http_server esp32-camera-master jomjol_controlcamera jomjol_flowcontroll jomjol_helper) diff --git a/code/components/jomjol_tfliteclass/CTfLiteClass.cpp b/code/components/jomjol_tfliteclass/CTfLiteClass.cpp index c6a2d7c5..fc0043d3 100644 --- a/code/components/jomjol_tfliteclass/CTfLiteClass.cpp +++ b/code/components/jomjol_tfliteclass/CTfLiteClass.cpp @@ -1,12 +1,10 @@ #include "CTfLiteClass.h" - -#include "bitmap_image.hpp" - #include "ClassLogFile.h" +#include "Helper.h" #include -bool debugdetailtflite = false; +// #define DEBUG_DETAIL_ON float CTfLiteClass::GetOutputValue(int nr) { @@ -19,19 +17,14 @@ float CTfLiteClass::GetOutputValue(int nr) return output2->data.f[nr]; } - -int CTfLiteClass::GetClassFromImage(std::string _fn) +int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs) { -// printf("Before Load image %s\n", _fn.c_str()); - if (!LoadInputImage(_fn)) + if (!LoadInputImageBasis(rs)) return -1000; -// printf("After Load image %s\n", _fn.c_str()); Invoke(); - printf("After Invoke %s\n", _fn.c_str()); return GetOutClassification(); -// return 0; } int CTfLiteClass::GetOutClassification() @@ -55,7 +48,6 @@ int CTfLiteClass::GetOutClassification() zw_class = i; } } -// printf("Result Ziffer: %d\n", zw_class); return zw_class; } @@ -107,21 +99,17 @@ void CTfLiteClass::GetOutPut() void CTfLiteClass::Invoke() { interpreter->Invoke(); -// printf("Invoke Done.\n"); } -bool CTfLiteClass::LoadInputImage(std::string _fn) + +bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs) { - std::string zw = "ClassFlowAnalog::doNeuralNetwork nach Load Image: " + _fn; -// LogFile.WriteToFile(zw); - bitmap_image image(_fn); - if (debugdetailtflite) LogFile.WriteToFile(zw); + std::string zw = "ClassFlowAnalog::doNeuralNetwork nach LoadInputResizeImage: "; - unsigned int w = image.width(); - unsigned int h = image.height(); + unsigned int w = rs->width; + unsigned int h = rs->height; unsigned char red, green, blue; - // printf("Image: %s size: %d x %d\n", _fn.c_str(), w, h); input_i = 0; @@ -130,21 +118,20 @@ bool CTfLiteClass::LoadInputImage(std::string _fn) for (int y = 0; y < h; ++y) for (int x = 0; x < w; ++x) { - red = image.red_channel(x, y); - green = image.green_channel(x, y); - blue = image.blue_channel(x, y); + red = rs->GetPixelColor(x, y, 0); + green = rs->GetPixelColor(x, y, 1); + blue = rs->GetPixelColor(x, y, 2); *(input_data_ptr) = (float) red; input_data_ptr++; *(input_data_ptr) = (float) green; input_data_ptr++; *(input_data_ptr) = (float) blue; input_data_ptr++; - -// printf("BMP: %f %f %f\n", (float) red, (float) green, (float) blue); - } - - if (debugdetailtflite) LogFile.WriteToFile("Nach dem Laden in input"); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteToFile("Nach dem Laden in input"); +#endif return true; } @@ -152,7 +139,6 @@ bool CTfLiteClass::LoadInputImage(std::string _fn) void CTfLiteClass::MakeAllocate() { -// static tflite::ops::micro::AllOpsResolver resolver; static tflite::AllOpsResolver resolver; this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter); @@ -162,16 +148,15 @@ void CTfLiteClass::MakeAllocate() this->GetInputDimension(); return; } - // printf("Allocate Done.\n"); } void CTfLiteClass::GetInputTensorSize(){ float *zw = this->input; int test = sizeof(zw); +#ifdef DEBUG_DETAIL_ON printf("Input Tensor Dimension: %d\n", test); - - printf("Input Tensor Dimension: %d\n", test); +#endif } long CTfLiteClass::GetFileSize(std::string filename) @@ -186,24 +171,34 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn) { long size; - size = this->GetFileSize(_fn); + size = GetFileSize(_fn); if (size == -1) { - printf("\nFile existiert nicht.\n"); - return NULL; + printf("\nFile existiert nicht.\n"); + return NULL; } - unsigned char *result = (unsigned char*) malloc(size); + int anz = 1; + TickType_t xDelay; + while (!result && (anz < 6)) // maximal 5x versuchen (= 5s) + { +#ifdef DEBUG_DETAIL_ON + printf("Speicher ist voll - Versuche es erneut: %d.\n", anz); +#endif + xDelay = 1000 / portTICK_PERIOD_MS; + result = (unsigned char*) malloc(size); + anz++; + } + - if(result != NULL) { -// printf("\nSpeicher ist reserviert\n"); - FILE* f = fopen(_fn.c_str(), "rb"); // vorher nur "r" + if(result != NULL) { + FILE* f = OpenFileAndWait(_fn.c_str(), "rb"); // vorher nur "r" fread(result, 1, size, f); fclose(f); - }else { - printf("\nKein freier Speicher vorhanden.\n"); + }else { + printf("\nKein freier Speicher vorhanden.\n"); } @@ -219,14 +214,11 @@ void CTfLiteClass::LoadModel(std::string _fn){ #endif unsigned char *rd; - rd = this->ReadFileToCharArray(_fn.c_str()); -// printf("loadedfile: %d", (int) rd); + rd = ReadFileToCharArray(_fn.c_str()); this->model = tflite::GetModel(rd); free(rd); TFLITE_MINIMAL_CHECK(model != nullptr); -// printf("tfile Loaded.\n"); - } @@ -237,7 +229,7 @@ CTfLiteClass::CTfLiteClass() this->interpreter = nullptr; this->input = nullptr; this->output = nullptr; - this->kTensorArenaSize = 600 * 1024; + this->kTensorArenaSize = 150 * 1024; /// laut testfile: 108000 - bisher 600 this->tensor_arena = new uint8_t[kTensorArenaSize]; } @@ -255,6 +247,6 @@ namespace tflite { return 0; } -} // namespace tflite +} diff --git a/code/components/jomjol_tfliteclass/CTfLiteClass.h b/code/components/jomjol_tfliteclass/CTfLiteClass.h index 1350a86a..c4bd057e 100644 --- a/code/components/jomjol_tfliteclass/CTfLiteClass.h +++ b/code/components/jomjol_tfliteclass/CTfLiteClass.h @@ -14,6 +14,8 @@ #include "esp_err.h" #include "esp_log.h" +#include "CImageBasis.h" + #define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE @@ -39,7 +41,6 @@ class CTfLiteClass const tflite::Model* model; tflite::MicroInterpreter* interpreter; TfLiteTensor* output = nullptr; -// static tflite::ops::micro::AllOpsResolver *resolver; static tflite::AllOpsResolver resolver; int kTensorArenaSize; @@ -58,11 +59,11 @@ class CTfLiteClass void LoadModel(std::string _fn); void MakeAllocate(); void GetInputTensorSize(); - bool LoadInputImage(std::string _fn); + bool LoadInputImageBasis(CImageBasis *rs); void Invoke(); void GetOutPut(); int GetOutClassification(); - int GetClassFromImage(std::string _fn); + int GetClassFromImageBasis(CImageBasis *rs); float GetOutputValue(int nr); void GetInputDimension(bool silent); diff --git a/code/components/jomjol_tfliteclass/server_tflite.cpp b/code/components/jomjol_tfliteclass/server_tflite.cpp index efe6ab21..963fa9b5 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.cpp +++ b/code/components/jomjol_tfliteclass/server_tflite.cpp @@ -18,17 +18,41 @@ #include "ClassLogFile.h" +//#define DEBUG_DETAIL_ON + + ClassFlowControll tfliteflow; TaskHandle_t xHandleblink_task_doFlow = NULL; TaskHandle_t xHandletask_autodoFlow = NULL; + + bool flowisrunning = false; long auto_intervall = 0; bool auto_isrunning = false; + +int countRounds = 0; + +int getCountFlowRounds() { + return countRounds; +} + + + +esp_err_t GetJPG(std::string _filename, httpd_req_t *req) +{ + return tfliteflow.GetJPGStream(_filename, req); +} + +esp_err_t GetRawJPG(httpd_req_t *req) +{ + return tfliteflow.SendRawJPG(req); +} + bool isSetupModusActive() { return tfliteflow.getStatusSetupModus(); return false; @@ -37,28 +61,40 @@ bool isSetupModusActive() { void KillTFliteTasks() { - printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow); +#ifdef DEBUG_DETAIL_ON + printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow); +#endif if (xHandleblink_task_doFlow) { vTaskDelete(xHandleblink_task_doFlow); +#ifdef DEBUG_DETAIL_ON printf("Killed: xHandleblink_task_doFlow\n"); +#endif } +#ifdef DEBUG_DETAIL_ON printf("Handle: xHandletask_autodoFlow: %ld\n", (long) xHandletask_autodoFlow); +#endif if (xHandletask_autodoFlow) { vTaskDelete(xHandletask_autodoFlow); +#ifdef DEBUG_DETAIL_ON printf("Killed: xHandletask_autodoFlow\n"); +#endif } } void doInit(void) { - string config = "/sdcard/config/config.ini"; + string config = "/sdcard/config/config.ini"; +#ifdef DEBUG_DETAIL_ON printf("Start tfliteflow.InitFlow(config);\n"); +#endif tfliteflow.InitFlow(config); +#ifdef DEBUG_DETAIL_ON printf("Finished tfliteflow.InitFlow(config);\n"); +#endif } @@ -71,13 +107,17 @@ bool doflow(void) tfliteflow.doFlow(zw_time); flowisrunning = false; +#ifdef DEBUG_DETAIL_ON printf("doflow - end %s\n", zw_time.c_str()); +#endif return true; } void blink_task_doFlow(void *pvParameter) { +#ifdef DEBUG_DETAIL_ON printf("blink_task_doFlow\n"); +#endif if (!flowisrunning) { flowisrunning = true; @@ -91,8 +131,10 @@ void blink_task_doFlow(void *pvParameter) esp_err_t handler_init(httpd_req_t *req) { - LogFile.WriteToFile("handler_init"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_init - Start"); printf("handler_doinit uri:\n"); printf(req->uri); printf("\n"); +#endif char* resp_str = "Init started
"; httpd_resp_send(req, resp_str, strlen(resp_str)); @@ -104,12 +146,19 @@ esp_err_t handler_init(httpd_req_t *req) /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_init - Done"); +#endif + return ESP_OK; }; esp_err_t handler_doflow(httpd_req_t *req) { - LogFile.WriteToFile("handler_doflow"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_doflow - Start"); +#endif + char* resp_str; printf("handler_doFlow uri: "); printf(req->uri); printf("\n"); @@ -127,7 +176,12 @@ esp_err_t handler_doflow(httpd_req_t *req) resp_str = "doFlow gestartet - dauert ca. 60 Sekunden"; httpd_resp_send(req, resp_str, strlen(resp_str)); /* Respond with an empty chunk to signal HTTP response completion */ - httpd_resp_send_chunk(req, NULL, 0); + httpd_resp_send_chunk(req, NULL, 0); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_doflow - Done"); +#endif + return ESP_OK; }; @@ -136,7 +190,10 @@ esp_err_t handler_doflow(httpd_req_t *req) esp_err_t handler_wasserzaehler(httpd_req_t *req) { - LogFile.WriteToFile("handler_wasserzaehler"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_wasserzaehler - Start"); +#endif + bool _rawValue = false; bool _noerror = false; string zw; @@ -151,12 +208,16 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) // printf("Query: "); printf(_query); printf("\n"); if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("rawvalue is found"); printf(_size); printf("\n"); +#endif _rawValue = true; } if (httpd_query_key_value(_query, "noerror", _size, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("noerror is found"); printf(_size); printf("\n"); +#endif _noerror = true; } } @@ -171,7 +232,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) { string txt, zw; - txt = "

Aligned Image:

\n"; + txt = "

Aligned Image:

\n"; txt = txt + "Digital Counter:

"; httpd_resp_sendstr_chunk(req, txt.c_str()); @@ -205,7 +266,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) httpd_resp_sendstr_chunk(req, txt.c_str()); delete htmlinfo[i]; } - htmlinfo.clear(); + htmlinfo.clear(); } @@ -217,13 +278,18 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req) /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_sendstr_chunk(req, NULL); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_wasserzaehler - Done"); +#endif return ESP_OK; }; esp_err_t handler_editflow(httpd_req_t *req) { - LogFile.WriteToFile("handler_editflow"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_editflow - Start"); +#endif printf("handler_editflow uri: "); printf(req->uri); printf("\n"); @@ -235,7 +301,9 @@ esp_err_t handler_editflow(httpd_req_t *req) { if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("task is found: %s\n", _valuechar); +#endif _task = string(_valuechar); } } @@ -246,11 +314,13 @@ esp_err_t handler_editflow(httpd_req_t *req) httpd_query_key_value(_query, "in", _valuechar, 30); in = string(_valuechar); - printf("in: "); printf(in.c_str()); printf("\n"); - httpd_query_key_value(_query, "out", _valuechar, 30); out = string(_valuechar); + +#ifdef DEBUG_DETAIL_ON + printf("in: "); printf(in.c_str()); printf("\n"); printf("out: "); printf(out.c_str()); printf("\n"); +#endif in = "/sdcard" + in; out = "/sdcard" + out; @@ -269,31 +339,34 @@ esp_err_t handler_editflow(httpd_req_t *req) httpd_query_key_value(_query, "in", _valuechar, 30); in = string(_valuechar); - printf("in: "); printf(in.c_str()); printf("\n"); httpd_query_key_value(_query, "out", _valuechar, 30); out = string(_valuechar); - printf("out: "); printf(out.c_str()); printf("\n"); httpd_query_key_value(_query, "x", _valuechar, 30); zw = string(_valuechar); x = stoi(zw); - printf("x: "); printf(zw.c_str()); printf("\n"); httpd_query_key_value(_query, "y", _valuechar, 30); zw = string(_valuechar); y = stoi(zw); - printf("y: "); printf(zw.c_str()); printf("\n"); httpd_query_key_value(_query, "dx", _valuechar, 30); zw = string(_valuechar); dx = stoi(zw); - printf("dx: "); printf(zw.c_str()); printf("\n"); httpd_query_key_value(_query, "dy", _valuechar, 30); zw = string(_valuechar); dy = stoi(zw); + +#ifdef DEBUG_DETAIL_ON + printf("in: "); printf(in.c_str()); printf("\n"); + printf("out: "); printf(out.c_str()); printf("\n"); + printf("x: "); printf(zw.c_str()); printf("\n"); + printf("y: "); printf(zw.c_str()); printf("\n"); + printf("dx: "); printf(zw.c_str()); printf("\n"); printf("dy: "); printf(zw.c_str()); printf("\n"); +#endif if (httpd_query_key_value(_query, "enhance", _valuechar, 10) == ESP_OK) { @@ -324,6 +397,7 @@ esp_err_t handler_editflow(httpd_req_t *req) zw = "CutImage Done"; httpd_resp_sendstr_chunk(req, zw.c_str()); + } if (_task.compare("test_take") == 0) @@ -379,13 +453,20 @@ esp_err_t handler_editflow(httpd_req_t *req) /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_sendstr_chunk(req, NULL); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_editflow - Done"); +#endif + return ESP_OK; }; esp_err_t handler_prevalue(httpd_req_t *req) { - LogFile.WriteToFile("handler_prevalue"); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_prevalue - Start"); +#endif + const char* resp_str; string zw; @@ -399,7 +480,9 @@ esp_err_t handler_prevalue(httpd_req_t *req) // printf("Query: "); printf(_query); printf("\n"); if (httpd_query_key_value(_query, "value", _size, 10) == ESP_OK) { +#ifdef DEBUG_DETAIL_ON printf("Value: "); printf(_size); printf("\n"); +#endif } } @@ -414,6 +497,10 @@ esp_err_t handler_prevalue(httpd_req_t *req) /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("handler_prevalue - Start"); +#endif + return ESP_OK; }; @@ -434,20 +521,27 @@ void task_autodoFlow(void *pvParameter) while (auto_isrunning) { - LogFile.WriteToFile("task_autodoFlow - next round"); + std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds); + LogFile.WriteToFile(_zw); printf("Autoflow: start\n"); fr_start = esp_timer_get_time(); if (flowisrunning) { +#ifdef DEBUG_DETAIL_ON printf("Autoflow: doFLow laeuft bereits!\n"); +#endif } else { +#ifdef DEBUG_DETAIL_ON printf("Autoflow: doFLow wird gestartet\n"); +#endif flowisrunning = true; doflow(); +#ifdef DEBUG_DETAIL_ON printf("Remove older log files\n"); +#endif LogFile.RemoveOld(); } @@ -507,5 +601,4 @@ void register_server_tflite_uri(httpd_handle_t server) camuri.handler = handler_wasserzaehler; camuri.user_ctx = (void*) "Wasserzaehler"; httpd_register_uri_handler(server, &camuri); - } diff --git a/code/components/jomjol_tfliteclass/server_tflite.h b/code/components/jomjol_tfliteclass/server_tflite.h index 68fc1dbc..148be20e 100644 --- a/code/components/jomjol_tfliteclass/server_tflite.h +++ b/code/components/jomjol_tfliteclass/server_tflite.h @@ -1,6 +1,7 @@ #include #include +#include "CImageBasis.h" //#include "ClassControllCamera.h" @@ -12,4 +13,8 @@ void KillTFliteTasks(); void TFliteDoAutoStart(); -bool isSetupModusActive(); \ No newline at end of file +bool isSetupModusActive(); + +esp_err_t GetJPG(std::string _filename, httpd_req_t *req); + +esp_err_t GetRawJPG(httpd_req_t *req); diff --git a/code/components/jomjol_time_sntp/time_sntp.cpp b/code/components/jomjol_time_sntp/time_sntp.cpp index da746ebd..4be9b8f2 100644 --- a/code/components/jomjol_time_sntp/time_sntp.cpp +++ b/code/components/jomjol_time_sntp/time_sntp.cpp @@ -1,11 +1,5 @@ #include "time_sntp.h" -/* LwIP SNTP example - This example code is in the Public Domain (or CC0 licensed, at your option.) - Unless required by applicable law or agreed to in writing, this - software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR - CONDITIONS OF ANY KIND, either express or implied. -*/ #include #include #include @@ -17,25 +11,19 @@ #include "esp_log.h" #include "esp_attr.h" #include "esp_sleep.h" -// #include "nvs_flash.h" -// #include "protocol_examples_common.h" #include "esp_sntp.h" #include "ClassLogFile.h" static const char *TAG = "sntp"; -RTC_DATA_ATTR int boot_count = 0; - bool setTimeAlwaysOnReboot = true; static void obtain_time(void); static void initialize_sntp(void); - void time_sync_notification_cb(struct timeval *tv) { -// LogFile.WriteToFile("Notification of a time synchronization event"); ESP_LOGI(TAG, "Notification of a time synchronization event"); } @@ -54,9 +42,6 @@ std::string gettimestring(const char * frm) void setup_time() { - ++boot_count; - ESP_LOGI(TAG, "Boot count: %d", boot_count); - time_t now; struct tm timeinfo; time(&now); @@ -72,8 +57,6 @@ void setup_time() char strftime_buf[64]; setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3"); -// setTimeZone("Europe/Berlin"); -// setTimeZone("Asia/Tokyo"); localtime_r(&now, &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo); @@ -97,9 +80,6 @@ void setTimeZone(std::string _tzstring) static void obtain_time(void) { -// initialize_sntp(); - - // wait for time to be set time_t now = 0; struct tm timeinfo = {}; int retry = 0; @@ -110,18 +90,23 @@ static void obtain_time(void) ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); vTaskDelay(2000 / portTICK_PERIOD_MS); } - if (retry == retry_count) { -// LogFile.WriteToFile("Time Synchzronisation nicht erfolgreich ..."); - } - else - { -// LogFile.WriteToFile("Time erfolgreich ..."); - } time(&now); localtime_r(&now, &timeinfo); } +void reset_servername(std::string _servername) +{ + printf("Set SNTP-Server: %s\n", _servername.c_str()); + sntp_stop(); + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, _servername.c_str()); + sntp_init(); + obtain_time(); + std::string zw = gettimestring("%Y%m%d-%H%M%S"); + printf("Time ist %s\n", zw.c_str()); +} + static void initialize_sntp(void) { ESP_LOGI(TAG, "Initializing SNTP"); diff --git a/code/components/jomjol_time_sntp/time_sntp.h b/code/components/jomjol_time_sntp/time_sntp.h index 3238e68a..930bfa35 100644 --- a/code/components/jomjol_time_sntp/time_sntp.h +++ b/code/components/jomjol_time_sntp/time_sntp.h @@ -15,4 +15,5 @@ void setup_time(void); std::string gettimestring(const char * frm); -void setTimeZone(std::string _tzstring); \ No newline at end of file +void setTimeZone(std::string _tzstring); +void reset_servername(std::string _servername); \ No newline at end of file diff --git a/code/main/main.cpp b/code/main/main.cpp index 11b26e79..0970180e 100644 --- a/code/main/main.cpp +++ b/code/main/main.cpp @@ -25,7 +25,7 @@ #include "ClassControllCamera.h" #include "server_main.h" #include "server_camera.h" - +#include "server_GPIO.h" static const char *TAGMAIN = "connect_wlan_main"; #define FLASH_GPIO GPIO_NUM_4 @@ -44,10 +44,15 @@ void Init_NVS_SDCard() // sdmmc_host_t host = SDMMC_HOST_SLOT_1(); // host.flags = SDMMC_HOST_FLAG_1BIT; sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + slot_config.width = 1; // 1 line SD mode + esp_vfs_fat_sdmmc_mount_config_t mount_config = { }; mount_config.format_if_mount_failed = false; mount_config.max_files = 5; + gpio_set_pull_mode((gpio_num_t) 15, GPIO_PULLUP_ONLY); // CMD, needed in 4- and 1- line modes + gpio_set_pull_mode((gpio_num_t) 2, GPIO_PULLUP_ONLY); // D0, needed in 4- and 1-line modes + sdmmc_card_t* card; ret = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, &card); if (ret != ESP_OK) { @@ -88,11 +93,12 @@ extern "C" void app_main(void) // LoadWlanFromFile("/sdcard/wlan.ini", ssid, password, hostname, ip, gw, netmask, dns); LoadWlanFromFile("/sdcard/wlan.ini", ssid, password, hostname); + LoadNetConfigFromFile("/sdcard/wlan.ini", ip, gw, netmask, dns); // LogFile.WriteToFile("Startsequence 04"); printf("To use WLan: %s, %s\n", ssid.c_str(), password.c_str()); printf("To set Hostename: %s\n", hostname.c_str()); - printf("Fixed IP: %s, Gateway %s, Netmask %s\n", ip.c_str(), gw.c_str(), netmask.c_str()); + printf("Fixed IP: %s, Gateway %s, Netmask %s, DNS %s\n", ip.c_str(), gw.c_str(), netmask.c_str(), dns.c_str()); if (ip.length() == 0 || gw.length() == 0 || netmask.length() == 0) { @@ -115,7 +121,9 @@ extern "C" void app_main(void) vTaskDelay( xDelay ); // LogFile.WriteToFile("Startsequence 07"); setup_time(); - LogFile.WriteToFile("============================== Main Started ======================================="); + LogFile.WriteToFile("============================================================================================="); + LogFile.WriteToFile("=================================== Main Started ============================================"); + LogFile.WriteToFile("============================================================================================="); LogFile.SwitchOnOff(false); std::string zw = gettimestring("%Y%m%d-%H%M%S"); diff --git a/code/main/server_main.cpp b/code/main/server_main.cpp index 084dca5d..37802ebf 100644 --- a/code/main/server_main.cpp +++ b/code/main/server_main.cpp @@ -15,16 +15,22 @@ #include "server_tflite.h" +//#define DEBUG_DETAIL_ON + + httpd_handle_t server = NULL; - std::string starttime = ""; /* An HTTP GET handler */ esp_err_t info_get_handler(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("info_get_handler - Start"); +#endif + LogFile.WriteToFile("info_get_handler"); char _query[200]; char _valuechar[30]; @@ -125,25 +131,40 @@ esp_err_t info_get_handler(httpd_req_t *req) return ESP_OK; } +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("info_get_handler - Done"); +#endif return ESP_OK; } esp_err_t starttime_get_handler(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("starttime_get_handler - Start"); +#endif + httpd_resp_send(req, starttime.c_str(), strlen(starttime.c_str())); /* Respond with an empty chunk to signal HTTP response completion */ - httpd_resp_send_chunk(req, NULL, 0); + httpd_resp_send_chunk(req, NULL, 0); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("starttime_get_handler - Done"); +#endif return ESP_OK; } esp_err_t hello_main_handler(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("hello_main_handler - Start"); +#endif + char filepath[50]; - struct stat file_stat; printf("uri: %s\n", req->uri); int _pos; + esp_err_t res; char *base_path = (char*) req->user_ctx; std::string filetosend(base_path); @@ -182,60 +203,37 @@ esp_err_t hello_main_handler(httpd_req_t *req) httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long"); return ESP_FAIL; } - if (stat(filetosend.c_str(), &file_stat) == -1) { - /* If file not present on SPIFFS check if URI - * corresponds to one of the hardcoded paths */ - ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str()); - /* Respond with 404 Not Found */ - httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist"); - return ESP_FAIL; - } - esp_err_t res; - res = httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); - if (res != ESP_OK) - return res; - res = send_file(req, filetosend, &file_stat); + res = send_file(req, filetosend); if (res != ESP_OK) return res; /* Respond with an empty chunk to signal HTTP response completion */ httpd_resp_send_chunk(req, NULL, 0); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("hello_main_handler - Stop"); +#endif + return ESP_OK; } esp_err_t img_tmp_handler(httpd_req_t *req) { char filepath[50]; - struct stat file_stat; printf("uri: %s\n", req->uri); char *base_path = (char*) req->user_ctx; std::string filetosend(base_path); const char *filename = get_path_from_uri(filepath, base_path, - req->uri + sizeof("/img_tmp") - 1, sizeof(filepath)); + req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath)); printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath); filetosend = filetosend + "/img_tmp/" + std::string(filename); printf("File to upload: %s\n", filetosend.c_str()); - if (!filename) { - ESP_LOGE(TAG, "Filename is too long"); - /* Respond with 500 Internal Server Error */ - httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long"); - return ESP_FAIL; - } - if (stat(filetosend.c_str(), &file_stat) == -1) { - /* If file not present on SPIFFS check if URI - * corresponds to one of the hardcoded paths */ - ESP_LOGE(TAG, "Failed to stat file : %s", filetosend.c_str()); - /* Respond with 404 Not Found */ - httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist"); - return ESP_FAIL; - } - - esp_err_t res = send_file(req, filetosend, &file_stat); + esp_err_t res = send_file(req, filetosend); if (res != ESP_OK) return res; @@ -244,8 +242,54 @@ esp_err_t img_tmp_handler(httpd_req_t *req) return ESP_OK; } +esp_err_t img_tmp_virtual_handler(httpd_req_t *req) +{ +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start"); +#endif + + char filepath[50]; + + printf("uri: %s\n", req->uri); + + char *base_path = (char*) req->user_ctx; + std::string filetosend(base_path); + + const char *filename = get_path_from_uri(filepath, base_path, + req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath)); + printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath); + + filetosend = std::string(filename); + printf("File to upload: %s\n", filetosend.c_str()); + + if (filetosend == "raw.jpg") + { + return GetRawJPG(req); + } + + esp_err_t zw = GetJPG(filetosend, req); + + if (zw == ESP_OK) + return ESP_OK; + + // File wird nicht intern bereit gestellt --> klassischer weg: +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done"); +#endif + + return img_tmp_handler(req); +} + + + + + esp_err_t sysinfo_handler(httpd_req_t *req) { +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("sysinfo_handler - Start"); +#endif + const char* resp_str; std::string zw; std::string cputemp = std::to_string(temperatureRead()); @@ -279,7 +323,11 @@ esp_err_t sysinfo_handler(httpd_req_t *req) httpd_resp_set_type(req, "application/json"); httpd_resp_send(req, resp_str, strlen(resp_str)); /* Respond with an empty chunk to signal HTTP response completion */ - httpd_resp_send_chunk(req, NULL, 0); + httpd_resp_send_chunk(req, NULL, 0); + +#ifdef DEBUG_DETAIL_ON + LogFile.WriteHeapInfo("sysinfo_handler - Done"); +#endif return ESP_OK; } @@ -314,7 +362,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path) httpd_uri_t img_tmp_handle = { .uri = "/img_tmp/*", // Match all URIs of type /path/to/file .method = HTTP_GET, - .handler = img_tmp_handler, + .handler = img_tmp_virtual_handler, .user_ctx = (void*) base_path // Pass server data as context }; httpd_register_uri_handler(server, &img_tmp_handle); diff --git a/code/main/server_main.h b/code/main/server_main.h index 16a851ed..e4f75b4c 100644 --- a/code/main/server_main.h +++ b/code/main/server_main.h @@ -22,9 +22,4 @@ httpd_handle_t start_webserver(void); void register_server_main_uri(httpd_handle_t server, const char *base_path); - -//void disconnect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); -//void connect_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data); - - #endif diff --git a/code/main/version.cpp b/code/main/version.cpp index 20df4b18..b1155d92 100644 --- a/code/main/version.cpp +++ b/code/main/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="bcdd0c6"; +const char* GIT_REV="0e36010"; const char* GIT_TAG=""; -const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2020-12-06 19:32"; \ No newline at end of file +const char* GIT_BRANCH="rolling"; +const char* BUILD_TIME="2021-01-02 08:39"; \ No newline at end of file diff --git a/code/platformio.ini b/code/platformio.ini index 43ce1528..9aa203f6 100644 --- a/code/platformio.ini +++ b/code/platformio.ini @@ -39,6 +39,7 @@ lib_deps = jomjol_time_sntp jomjol_logfile jomjol_mqtt + jomjol_controlGPIO monitor_speed = 115200 diff --git a/code/sdkconfig b/code/sdkconfig index dd11c44e..30ad0482 100644 --- a/code/sdkconfig +++ b/code/sdkconfig @@ -173,7 +173,95 @@ CONFIG_BTDM_BLE_SLEEP_CLOCK_ACCURACY_INDEX_EFF=1 CONFIG_BT_RESERVE_DRAM=0 # end of Bluetooth -# CONFIG_BLE_MESH is not set +CONFIG_BLE_MESH=y +CONFIG_BLE_MESH_HCI_5_0=y +# CONFIG_BLE_MESH_ALLOC_FROM_PSRAM_FIRST is not set +# CONFIG_BLE_MESH_FAST_PROV is not set +# CONFIG_BLE_MESH_NODE is not set +# CONFIG_BLE_MESH_PROVISIONER is not set +CONFIG_BLE_MESH_PROV=y +CONFIG_BLE_MESH_PB_ADV=y +# CONFIG_BLE_MESH_PB_GATT is not set +CONFIG_BLE_MESH_PROXY=y +# CONFIG_BLE_MESH_GATT_PROXY_CLIENT is not set +CONFIG_BLE_MESH_NET_BUF_POOL_USAGE=y +# CONFIG_BLE_MESH_SETTINGS is not set +CONFIG_BLE_MESH_SUBNET_COUNT=3 +CONFIG_BLE_MESH_APP_KEY_COUNT=3 +CONFIG_BLE_MESH_MODEL_KEY_COUNT=3 +CONFIG_BLE_MESH_MODEL_GROUP_COUNT=3 +CONFIG_BLE_MESH_LABEL_COUNT=3 +CONFIG_BLE_MESH_CRPL=10 +CONFIG_BLE_MESH_MSG_CACHE_SIZE=10 +CONFIG_BLE_MESH_ADV_BUF_COUNT=60 +# CONFIG_BLE_MESH_SUPPORT_BLE_ADV is not set +CONFIG_BLE_MESH_IVU_DIVIDER=4 +CONFIG_BLE_MESH_TX_SEG_MSG_COUNT=1 +CONFIG_BLE_MESH_RX_SEG_MSG_COUNT=1 +CONFIG_BLE_MESH_RX_SDU_MAX=384 +CONFIG_BLE_MESH_TX_SEG_MAX=32 +# CONFIG_BLE_MESH_FRIEND is not set +# CONFIG_BLE_MESH_NO_LOG is not set + +# +# BLE Mesh STACK DEBUG LOG LEVEL +# +# CONFIG_BLE_MESH_TRACE_LEVEL_NONE is not set +# CONFIG_BLE_MESH_TRACE_LEVEL_ERROR is not set +CONFIG_BLE_MESH_TRACE_LEVEL_WARNING=y +# CONFIG_BLE_MESH_TRACE_LEVEL_INFO is not set +# CONFIG_BLE_MESH_TRACE_LEVEL_DEBUG is not set +# CONFIG_BLE_MESH_TRACE_LEVEL_VERBOSE is not set +CONFIG_BLE_MESH_STACK_TRACE_LEVEL=2 +# end of BLE Mesh STACK DEBUG LOG LEVEL + +# +# BLE Mesh NET BUF DEBUG LOG LEVEL +# +# CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_NONE is not set +# CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_ERROR is not set +CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_WARNING=y +# CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_INFO is not set +# CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_DEBUG is not set +# CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL_VERBOSE is not set +CONFIG_BLE_MESH_NET_BUF_TRACE_LEVEL=2 +# end of BLE Mesh NET BUF DEBUG LOG LEVEL + +CONFIG_BLE_MESH_CLIENT_MSG_TIMEOUT=4000 + +# +# Support for BLE Mesh Client Models +# +# CONFIG_BLE_MESH_CFG_CLI is not set +# CONFIG_BLE_MESH_HEALTH_CLI is not set +# CONFIG_BLE_MESH_GENERIC_ONOFF_CLI is not set +# CONFIG_BLE_MESH_GENERIC_LEVEL_CLI is not set +# CONFIG_BLE_MESH_GENERIC_DEF_TRANS_TIME_CLI is not set +# CONFIG_BLE_MESH_GENERIC_POWER_ONOFF_CLI is not set +# CONFIG_BLE_MESH_GENERIC_POWER_LEVEL_CLI is not set +# CONFIG_BLE_MESH_GENERIC_BATTERY_CLI is not set +# CONFIG_BLE_MESH_GENERIC_LOCATION_CLI is not set +# CONFIG_BLE_MESH_GENERIC_PROPERTY_CLI is not set +# CONFIG_BLE_MESH_SENSOR_CLI is not set +# CONFIG_BLE_MESH_TIME_CLI is not set +# CONFIG_BLE_MESH_SCENE_CLI is not set +# CONFIG_BLE_MESH_SCHEDULER_CLI is not set +# CONFIG_BLE_MESH_LIGHT_LIGHTNESS_CLI is not set +# CONFIG_BLE_MESH_LIGHT_CTL_CLI is not set +# CONFIG_BLE_MESH_LIGHT_HSL_CLI is not set +# CONFIG_BLE_MESH_LIGHT_XYL_CLI is not set +# CONFIG_BLE_MESH_LIGHT_LC_CLI is not set +# end of Support for BLE Mesh Client Models + +# CONFIG_BLE_MESH_IV_UPDATE_TEST is not set + +# +# BLE Mesh specific test option +# +# CONFIG_BLE_MESH_SELF_TEST is not set +# CONFIG_BLE_MESH_SHELL is not set +# CONFIG_BLE_MESH_DEBUG is not set +# end of BLE Mesh specific test option # # CoAP Configuration @@ -537,8 +625,8 @@ CONFIG_FATFS_MAX_LFN=255 CONFIG_FATFS_API_ENCODING_ANSI_OEM=y # CONFIG_FATFS_API_ENCODING_UTF_16 is not set # CONFIG_FATFS_API_ENCODING_UTF_8 is not set -CONFIG_FATFS_FS_LOCK=5 -CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_FS_LOCK=10 +CONFIG_FATFS_TIMEOUT_MS=5000 CONFIG_FATFS_PER_FILE_CACHE=y CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y # end of FAT Filesystem support @@ -965,7 +1053,7 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y # # Virtual file system # -CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT is not set CONFIG_VFS_SUPPORT_TERMIOS=y # @@ -1166,6 +1254,6 @@ CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set -CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT is not set CONFIG_SUPPORT_TERMIOS=y # End of deprecated options diff --git a/code/sdkconfig.old b/code/sdkconfig.old index 88827b07..f8a0f2c5 100644 --- a/code/sdkconfig.old +++ b/code/sdkconfig.old @@ -83,11 +83,11 @@ CONFIG_ESPTOOLPY_FLASHFREQ_40M=y # CONFIG_ESPTOOLPY_FLASHFREQ_20M is not set CONFIG_ESPTOOLPY_FLASHFREQ="40m" # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y -# CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set +# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set -CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE="4MB" CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y CONFIG_ESPTOOLPY_BEFORE_RESET=y # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set @@ -315,8 +315,8 @@ CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR=y CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES=4 # CONFIG_ESP32_ULP_COPROC_ENABLED is not set CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=0 -# CONFIG_ESP32_PANIC_PRINT_HALT is not set -CONFIG_ESP32_PANIC_PRINT_REBOOT=y +CONFIG_ESP32_PANIC_PRINT_HALT=y +# CONFIG_ESP32_PANIC_PRINT_REBOOT is not set # CONFIG_ESP32_PANIC_SILENT_REBOOT is not set # CONFIG_ESP32_PANIC_GDBSTUB is not set CONFIG_ESP32_DEBUG_OCDAWARE=y @@ -537,8 +537,8 @@ CONFIG_FATFS_MAX_LFN=255 CONFIG_FATFS_API_ENCODING_ANSI_OEM=y # CONFIG_FATFS_API_ENCODING_UTF_16 is not set # CONFIG_FATFS_API_ENCODING_UTF_8 is not set -CONFIG_FATFS_FS_LOCK=5 -CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_FS_LOCK=10 +CONFIG_FATFS_TIMEOUT_MS=5000 CONFIG_FATFS_PER_FILE_CACHE=y CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y # end of FAT Filesystem support @@ -965,7 +965,7 @@ CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y # # Virtual file system # -CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_VFS_SUPPRESS_SELECT_DEBUG_OUTPUT is not set CONFIG_VFS_SUPPORT_TERMIOS=y # @@ -1166,6 +1166,6 @@ CONFIG_ESP32_PTHREAD_TASK_NAME_DEFAULT="pthread" CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS is not set # CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED is not set -CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT=y +# CONFIG_SUPPRESS_SELECT_DEBUG_OUTPUT is not set CONFIG_SUPPORT_TERMIOS=y # End of deprecated options diff --git a/code/version.cpp b/code/version.cpp index 20df4b18..b1155d92 100644 --- a/code/version.cpp +++ b/code/version.cpp @@ -1,4 +1,4 @@ -const char* GIT_REV="bcdd0c6"; +const char* GIT_REV="0e36010"; const char* GIT_TAG=""; -const char* GIT_BRANCH="master"; -const char* BUILD_TIME="2020-12-06 19:32"; \ No newline at end of file +const char* GIT_BRANCH="rolling"; +const char* BUILD_TIME="2021-01-02 08:39"; \ No newline at end of file diff --git a/firmware/bootloader.bin b/firmware/bootloader.bin index ce3a6d8f..df78ead7 100644 Binary files a/firmware/bootloader.bin and b/firmware/bootloader.bin differ diff --git a/firmware/firmware.bin b/firmware/firmware.bin index 8a751444..2dc60cb9 100644 Binary files a/firmware/firmware.bin and b/firmware/firmware.bin differ diff --git a/firmware/html.zip b/firmware/html.zip index 9d1ae20c..70151534 100644 Binary files a/firmware/html.zip and b/firmware/html.zip differ diff --git a/sd-card/config/config.ini b/sd-card/config/config.ini index a7e80a44..b4c1c631 100644 --- a/sd-card/config/config.ini +++ b/sd-card/config/config.ini @@ -14,7 +14,7 @@ SearchFieldY = 20 [Digits] -Model = /config/dig0720s1.tflite +Model = /config/dig0721s1.tflite ;LogImageLocation = /log/digit ;LogfileRetentionInDays = 3 ModelInputSize = 20 32 @@ -39,13 +39,13 @@ PreValueAgeStartup = 720 AllowNegativeRates = false MaxRateValue = 0.1 ErrorMessage = true -CheckDigitIncreaseConsistency = true +CheckDigitIncreaseConsistency = false [MQTT] -Uri = mqtt://IP-ADRESS:1883 -Topic = wasserzaehler/zaehlerstand -TopicError = wasserzaehler/error -ClientID = wasser +;Uri = mqtt://IP-ADRESS:1883 +;Topic = wasserzaehler/zaehlerstand +;TopicError = wasserzaehler/error +;ClientID = wasser ;user = USERNAME ;password = PASSWORD @@ -59,6 +59,7 @@ LogfileRetentionInDays = 3 [System] TimeZone = CET-1CEST,M3.5.0,M10.5.0/3 +;TimeServer = fritz.box SetupMode = true [Ende] \ No newline at end of file diff --git a/sd-card/config/dig0710s3.tflite b/sd-card/config/dig0710s3.tflite deleted file mode 100644 index db7aaf1c..00000000 Binary files a/sd-card/config/dig0710s3.tflite and /dev/null differ diff --git a/sd-card/config/dig0720s1.tflite b/sd-card/config/dig0720s1.tflite deleted file mode 100644 index e0325e91..00000000 Binary files a/sd-card/config/dig0720s1.tflite and /dev/null differ diff --git a/sd-card/config/dig0721s1.tflite b/sd-card/config/dig0721s1.tflite new file mode 100644 index 00000000..f535bfb9 Binary files /dev/null and b/sd-card/config/dig0721s1.tflite differ diff --git a/sd-card/html/edit_config_param.html b/sd-card/html/edit_config_param.html index 1b995808..437cc01a 100644 --- a/sd-card/html/edit_config_param.html +++ b/sd-card/html/edit_config_param.html @@ -61,7 +61,7 @@ textarea { - + LogImageLocation @@ -75,7 +75,7 @@ textarea { - + LogfileRetentionInDays @@ -123,7 +123,7 @@ textarea { @@ -538,7 +538,7 @@ textarea { - + LogfileRetentionInDays @@ -556,7 +556,7 @@ textarea { - + TimeZone @@ -570,16 +570,16 @@ textarea { - - - - TimeUpdateIntervall + - + TimeServer + + + - Intervall for synchronizing the time with the time server (in hours) + Time server to synchronize system time (default: "pool.ntp.org" - used if nothing is specified) @@ -717,7 +717,7 @@ function UpdateInput() { WriteParameter(param, "Debug", "LogfileRetentionInDays", true); WriteParameter(param, "System", "TimeZone", true); - WriteParameter(param, "System", "TimeUpdateIntervall", true); + WriteParameter(param, "System", "TimeServer", true); } function WriteConfig(){ @@ -731,13 +731,13 @@ function WriteConfig(){ ReadParameter(param, "Alignment", "SearchFieldY", false); ReadParameter(param, "Digits", "Model", false); - ReadParameter(param, "Digits", "LogImageLocation", false); - ReadParameter(param, "Digits", "LogfileRetentionInDays", false); + ReadParameter(param, "Digits", "LogImageLocation", true); + ReadParameter(param, "Digits", "LogfileRetentionInDays", true); ReadParameter(param, "Digits", "ModelInputSize", false, false, 2); ReadParameter(param, "Analog", "Model", false); - ReadParameter(param, "Analog", "LogImageLocation", false); - ReadParameter(param, "Analog", "LogfileRetentionInDays", false); + ReadParameter(param, "Analog", "LogImageLocation", true); + ReadParameter(param, "Analog", "LogfileRetentionInDays", true); ReadParameter(param, "Analog", "ModelInputSize", false, false, 2); ReadParameter(param, "PostProcessing", "DecimalShift", true); @@ -762,7 +762,7 @@ function WriteConfig(){ ReadParameter(param, "Debug", "LogfileRetentionInDays", true); ReadParameter(param, "System", "TimeZone", true); - ReadParameter(param, "System", "TimeUpdateIntervall", true); + ReadParameter(param, "System", "TimeServer", true); FormatDecimalValue(param, "PostProcessing", "MaxRateValue"); diff --git a/sd-card/html/edit_reference.html b/sd-card/html/edit_reference.html index 34e02678..0ea705dd 100644 --- a/sd-card/html/edit_reference.html +++ b/sd-card/html/edit_reference.html @@ -87,7 +87,7 @@ table { } function loadRawImage(){ - url = basepath + "/fileserver/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1); + url = basepath + "/img_tmp/raw.jpg" + "?session=" + Math.floor((Math.random() * 1000000) + 1); document.getElementById("finerotate").value = 0; document.getElementById("prerotateangle").value = getPreRotate(); document.getElementById("mirror").checked = getMirror(); diff --git a/sd-card/html/gethost.js b/sd-card/html/gethost.js index 90d993d7..80ae6d85 100644 --- a/sd-card/html/gethost.js +++ b/sd-card/html/gethost.js @@ -7,9 +7,11 @@ function getbasepath(){ var host = window.location.hostname; if ((host == "127.0.0.1") || (host == "localhost")) { - host = "http://192.168.178.26"; // jomjol interner test + host = "http://192.168.2.118"; // jomjol interner test +// host = "http://192.168.178.26"; // jomjol interner test // host = "http://192.168.178.22"; // jomjol interner Real // host = "."; // jomjol interner localhost + } else { diff --git a/sd-card/html/readconfig.js b/sd-card/html/readconfig.js index e1164b02..3db248ba 100644 --- a/sd-card/html/readconfig.js +++ b/sd-card/html/readconfig.js @@ -350,7 +350,7 @@ function GetReferenceSize(name){ function ZerlegeZeile(input) { var Output = Array(0); - delimiter = " =,"; + delimiter = " =,\r"; input = trim(input, delimiter); var pos = findDelimiterPos(input, delimiter); diff --git a/sd-card/html/readconfigparam.js b/sd-card/html/readconfigparam.js index ddd5903e..9c31994d 100644 --- a/sd-card/html/readconfigparam.js +++ b/sd-card/html/readconfigparam.js @@ -72,9 +72,9 @@ function ParseConfig() { var catname = "System"; param[catname] = new Object(); ParamAddValue(param, catname, "TimeZone"); + ParamAddValue(param, catname, "TimeServer"); ParamAddValue(param, catname, "AutoAdjustSummertime"); - ParamAddValue(param, catname, "TimeUpdateIntervall"); - ParamAddValue(param, catname, "SetupMode"); + ParamAddValue(param, catname, "SetupMode"); while (aktline < config_split.length){ if (config_split[aktline].trim().toUpperCase() == "[MAKEIMAGE]") { @@ -149,6 +149,7 @@ function ParseConfigParamSystem(_aktline){ var linesplit = ZerlegeZeile(input, " ="); ParamExtractValue(param, linesplit, catname, "TimeZone", _aktline, isCom); + ParamExtractValue(param, linesplit, catname, "TimeServer", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "AutoAdjustSummertime", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "TimeUpdateIntervall", _aktline, isCom); ParamExtractValue(param, linesplit, catname, "SetupMode", _aktline, isCom); diff --git a/sd-card/html/version.txt b/sd-card/html/version.txt index 4a36342f..4d54dadd 100644 --- a/sd-card/html/version.txt +++ b/sd-card/html/version.txt @@ -1 +1 @@ -3.0.0 +4.0.2 diff --git a/sd-card/log/digit/10/leer.txt b/sd-card/log/digit/10/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/2/leer.txt b/sd-card/log/digit/2/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/3/leer.txt b/sd-card/log/digit/3/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/4/leer.txt b/sd-card/log/digit/4/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/5/leer.txt b/sd-card/log/digit/5/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/6/leer.txt b/sd-card/log/digit/6/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/7/leer.txt b/sd-card/log/digit/7/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/8/leer.txt b/sd-card/log/digit/8/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/9/leer.txt b/sd-card/log/digit/9/leer.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/sd-card/log/digit/0/leer.txt b/sd-card/log/digit/leer.txt similarity index 100% rename from sd-card/log/digit/0/leer.txt rename to sd-card/log/digit/leer.txt diff --git a/sd-card/log/digit/1/leer.txt b/sd-card/log/message/leer.txt similarity index 100% rename from sd-card/log/digit/1/leer.txt rename to sd-card/log/message/leer.txt diff --git a/sd-card/wlan.ini b/sd-card/wlan.ini index fac2d609..60073814 100644 --- a/sd-card/wlan.ini +++ b/sd-card/wlan.ini @@ -1,4 +1,12 @@ ssid = "SSID" password = "PASSWORD" hostname = "watermeter" -;hostname is optional \ No newline at end of file +;hostname is optional + +;if you want to use a fixed IP you need to specify the following 3 parameters (ip, gateway, netmask) with IP4-Addresses "123.456.789.012" +;ip = "IP4-ADDRESS" +;gateway = "IP4-ADDRESS" +;netmask = "255.255.255.0" + +;in some cases you want to specify the DNS server as well (especially, if it is not identical to the gateway - this is optional for a fixed IP +;dns = "IP4-ADDRESS" \ No newline at end of file