diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..9165f3867 --- /dev/null +++ b/.clang-format @@ -0,0 +1,48 @@ +BasedOnStyle: LLVM +AccessModifierOffset: -2 +AlignConsecutiveMacros: + Enabled: true + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignTrailingComments: true +AllowShortEnumsOnASingleLine: false +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: Never +AllowShortLoopsOnASingleLine: false +BreakAfterReturnType: Automatic +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: Never + AfterEnum: false + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: false + AfterExternBlock: false + BeforeCatch: true + BeforeElse: true + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false +BreakBeforeBraces: Custom +ColumnLimit: 140 +#IndentAccessModifiers: true # If activated struct content is indented twice +IndentCaseLabels: true +IndentWidth: 4 +InsertBraces: true +InsertNewlineAtEOF: true +MaxEmptyLinesToKeep: 2 +PenaltyBreakAssignment : 60 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 50 +PenaltyBreakOpenParenthesis: 60 +PenaltyReturnTypeOnItsOwnLine: 200 +SortIncludes: Never diff --git a/code/README.md b/code/README.md index 157d75eff..1ff93c41e 100644 --- a/code/README.md +++ b/code/README.md @@ -120,3 +120,38 @@ in `/.platformio/packages`. esp-coredump info_corefile --gdb --rom-elf esp32_rev0_rom.elf --core-format raw --core firmware_ESP32CAM_coredump-elf.bin firmware.elf ``` +--- +## Source Code Style Guide +| Type | Style | Example +|--------------------|----------------------|----- +| Classes | Pascal Case | `ClassName` +| Structs | Pascal Case | `StructName` +| Functions | Camel Case | `callFunction1` +| Variables | Camel Case | `testVariable1` +| Constants | Screaming Snake Case | `#define DEFINITION_1` + +## Automatic Source Code Formatting + +### Configuration +#### Pre-Condition +- Development environment has an automatic formatter function (e.g. VSCode) +- Formatting rule file (`.clang-format`) needs to be available in project root folder +- Every developer needs to use defined formatting rules to avoid unnecessary style changes + +#### VSCode development environment +- No extention necessary (Using VSCode default formatter which is able to handle clang format) +- The formatting is applied automatically whenever pasting or saving the file by adding the following content to project specific `settings.json` file located in project subfolder `.vscode`. + ``` + "editor.formatOnSave": false, + "editor.formatOnPaste": false, + "[cpp]": { + "editor.formatOnSave": true, + "editor.formatOnPaste": true + } + ``` +- With this settings it only applies per project and is enabled only for the language C++ (cpp, h files), but could also be configured globally. +- Formatting exlusion: Formating of file `defines.h` is disabled (`// clang-format off`) to keep better readability (nested PPDirectives) + +### Formating rules (clang-format) +- Formatting rule file: [.clang-format](../.clang-format) +- [Online Configurator](https://clang-format-configurator.site/) \ No newline at end of file diff --git a/code/components/camera_ctrl/ClassControlCamera.cpp b/code/components/camera_ctrl/ClassControlCamera.cpp index 25be1af7c..663c8337f 100644 --- a/code/components/camera_ctrl/ClassControlCamera.cpp +++ b/code/components/camera_ctrl/ClassControlCamera.cpp @@ -34,40 +34,40 @@ ClassControlCamera cameraCtrl; /* Camera live stream */ #define PART_BOUNDARY "123456789000000000000987654321" -static const char* _STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; -static const char* _STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; -static const char* _STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; +static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY; +static const char *_STREAM_BOUNDARY = "\r\n--" PART_BOUNDARY "\r\n"; +static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\n\r\n"; static camera_config_t cameraConfig = { - .pin_pwdn = PWDN_GPIO_NUM, - .pin_reset = RESET_GPIO_NUM, - .pin_xclk = XCLK_GPIO_NUM, - .pin_sccb_sda = SIOD_GPIO_NUM, - .pin_sccb_scl = SIOC_GPIO_NUM, - .pin_d7 = Y9_GPIO_NUM, - .pin_d6 = Y8_GPIO_NUM, - .pin_d5 = Y7_GPIO_NUM, - .pin_d4 = Y6_GPIO_NUM, - .pin_d3 = Y5_GPIO_NUM, - .pin_d2 = Y4_GPIO_NUM, - .pin_d1 = Y3_GPIO_NUM, - .pin_d0 = Y2_GPIO_NUM, - .pin_vsync = VSYNC_GPIO_NUM, - .pin_href = HREF_GPIO_NUM, - .pin_pclk = PCLK_GPIO_NUM, - - .xclk_freq_hz = 20000000, // Frequency (20Mhz) + .pin_pwdn = PWDN_GPIO_NUM, + .pin_reset = RESET_GPIO_NUM, + .pin_xclk = XCLK_GPIO_NUM, + .pin_sccb_sda = SIOD_GPIO_NUM, + .pin_sccb_scl = SIOC_GPIO_NUM, + .pin_d7 = Y9_GPIO_NUM, + .pin_d6 = Y8_GPIO_NUM, + .pin_d5 = Y7_GPIO_NUM, + .pin_d4 = Y6_GPIO_NUM, + .pin_d3 = Y5_GPIO_NUM, + .pin_d2 = Y4_GPIO_NUM, + .pin_d1 = Y3_GPIO_NUM, + .pin_d0 = Y2_GPIO_NUM, + .pin_vsync = VSYNC_GPIO_NUM, + .pin_href = HREF_GPIO_NUM, + .pin_pclk = PCLK_GPIO_NUM, + + .xclk_freq_hz = 20000000, // Frequency (20Mhz) .ledc_timer = LEDC_TIMER_0, .ledc_channel = LEDC_CHANNEL_0, - .pixel_format = PIXFORMAT_JPEG, // YUV422, GRAYSCALE, RGB565, JPEG - .frame_size = FRAMESIZE_VGA, // QQVGA-UXGA Do not use sizes above QVGA when not JPEG - .jpeg_quality = 12, // 0-63 lower number means higher quality - .fb_count = 1, // if more than one, i2s runs in continuous mode. Use only with JPEG - .fb_location = CAMERA_FB_IN_PSRAM, // The location where the frame buffer will be allocated */ - .grab_mode = CAMERA_GRAB_LATEST // only from new esp32cam version + .pixel_format = PIXFORMAT_JPEG, // YUV422, GRAYSCALE, RGB565, JPEG + .frame_size = FRAMESIZE_VGA, // QQVGA-UXGA Do not use sizes above QVGA when not JPEG + .jpeg_quality = 12, // 0-63 lower number means higher quality + .fb_count = 1, // if more than one, i2s runs in continuous mode. Use only with JPEG + .fb_location = CAMERA_FB_IN_PSRAM, // The location where the frame buffer will be allocated */ + .grab_mode = CAMERA_GRAB_LATEST // only from new esp32cam version }; @@ -82,28 +82,29 @@ ClassControlCamera::ClassControlCamera() #ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM ledcInitFlashlightDefault(); -#endif +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM } esp_err_t ClassControlCamera::initCam() { - if (cameraInitSuccessful) + if (cameraInitSuccessful) { deinitCam(); // De-init in case it was already initialized + } vTaskDelay(pdMS_TO_TICKS(100)); // Init camera esp_err_t err = esp_camera_init(&cameraConfig); if (err != ESP_OK) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Camera init failed: " + intToHexString(err)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Camera init failed: " + intToHexString(err)); - if (err == ESP_ERR_NOT_FOUND) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "No camera detected, check camera and electrical connection"); - } - else if (err == ESP_ERR_NOT_SUPPORTED) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Detected camera model or JPEG format is not supported"); - } + if (err == ESP_ERR_NOT_FOUND) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "No camera detected, check camera and electrical connection"); + } + else if (err == ESP_ERR_NOT_SUPPORTED) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Detected camera model or JPEG format is not supported"); + } return err; } @@ -156,7 +157,7 @@ void ClassControlCamera::powerResetCamera() vTaskDelay(pdMS_TO_TICKS(1000)); gpio_set_level(PWDN_GPIO_NUM, 0); vTaskDelay(pdMS_TO_TICKS(1000)); -#endif +#endif // PWDN_GPIO_NUM == -1 } @@ -179,15 +180,15 @@ void ClassControlCamera::printCamInfo(void) // Print camera infos // ******************************************** char caminfo[96]; - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "printCamInfo: Failed to get control structure"); return; } camera_sensor_info_t *info = esp_camera_sensor_get_info(&s->id); - sprintf(caminfo, "TYPE: %s, PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x, FREQ: %dMhz", - info->name, s->id.PID, s->id.VER, s->id.MIDH, s->id.MIDL, s->xclk_freq_hz/1000000); + sprintf(caminfo, "TYPE: %s, PID: 0x%02x, VER: 0x%02x, MIDL: 0x%02x, MIDH: 0x%02x, FREQ: %dMhz", info->name, s->id.PID, s->id.VER, + s->id.MIDH, s->id.MIDL, s->xclk_freq_hz / 1000000); LogFile.writeToFile(ESP_LOG_INFO, TAG, "Info: " + std::string(caminfo)); } @@ -198,22 +199,22 @@ void ClassControlCamera::printCamConfig(void) // ******************************************** char camconfig[512]; - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "printCamConfig: Failed to get control structure"); return; } - sprintf(camconfig, "ae_level:%d, aec2:%d, aec:%d, aec_value:%d, agc:%d, agc_gain:%d, awb:%d, awb_gain:%d, " - "binning:%d, bpc:%d, brightness:%d, colorbar:%d, contrast:%d, dcw:%d, deonoise:%d, framesize:%d, " - "gainceiling:%d, hmirror:%d, lenc:%d, quality:%d, raw_gma:%d, saturation:%d, scale:%d, sharpness:%d, " - "special_effect:%d, vflip:%d, wb_mode:%d, wpc:%d", - s->status.ae_level, s->status.aec2, s->status.aec, s->status.aec_value, - s->status.agc, s->status.agc_gain, s->status.awb, s->status.awb_gain, s->status.binning, - s->status.bpc, s->status.brightness, s->status.colorbar, s->status.contrast, s->status.dcw, - s->status.denoise, s->status.framesize, s->status.gainceiling, s->status.hmirror, s->status.lenc, - s->status.quality, s->status.raw_gma, s->status.saturation, s->status.scale, s->status.sharpness, - s->status.special_effect, s->status.vflip, s->status.wb_mode, s->status.wpc); + sprintf(camconfig, + "ae_level:%d, aec2:%d, aec:%d, aec_value:%d, agc:%d, agc_gain:%d, awb:%d, awb_gain:%d, " + "binning:%d, bpc:%d, brightness:%d, colorbar:%d, contrast:%d, dcw:%d, deonoise:%d, framesize:%d, " + "gainceiling:%d, hmirror:%d, lenc:%d, quality:%d, raw_gma:%d, saturation:%d, scale:%d, sharpness:%d, " + "special_effect:%d, vflip:%d, wb_mode:%d, wpc:%d", + s->status.ae_level, s->status.aec2, s->status.aec, s->status.aec_value, s->status.agc, s->status.agc_gain, s->status.awb, + s->status.awb_gain, s->status.binning, s->status.bpc, s->status.brightness, s->status.colorbar, s->status.contrast, + s->status.dcw, s->status.denoise, s->status.framesize, s->status.gainceiling, s->status.hmirror, s->status.lenc, + s->status.quality, s->status.raw_gma, s->status.saturation, s->status.scale, s->status.sharpness, s->status.special_effect, + s->status.vflip, s->status.wb_mode, s->status.wpc); LogFile.writeToFile(ESP_LOG_INFO, TAG, "Camera config: " + std::string(camconfig)); } @@ -225,12 +226,10 @@ esp_err_t ClassControlCamera::setCameraParameter(const CfgData::SectionTakeImage setCameraFrequency(paramCameraInternal.cameraFrequency); setImageQuality(paramCameraInternal.imageQuality); setImageSize(paramCameraInternal.zoomFactor, paramCameraInternal.zoomOffsetX, paramCameraInternal.zoomOffsetY); - setImageManipulation(paramCameraInternal.brightness, paramCameraInternal.contrast, - paramCameraInternal.saturation, paramCameraInternal.sharpness, - paramCameraInternal.exposureControlMode, paramCameraInternal.autoExposureLevel, - paramCameraInternal.manualExposureValue, paramCameraInternal.gainControlMode, - paramCameraInternal.manualGainValue, paramCameraInternal.specialEffect, - paramCameraInternal.mirrorImage, paramCameraInternal.flipImage); + setImageManipulation(paramCameraInternal.brightness, paramCameraInternal.contrast, paramCameraInternal.saturation, + paramCameraInternal.sharpness, paramCameraInternal.exposureControlMode, paramCameraInternal.autoExposureLevel, + paramCameraInternal.manualExposureValue, paramCameraInternal.gainControlMode, paramCameraInternal.manualGainValue, + paramCameraInternal.specialEffect, paramCameraInternal.mirrorImage, paramCameraInternal.flipImage); return ESP_OK; } @@ -238,18 +237,23 @@ esp_err_t ClassControlCamera::setCameraParameter(const CfgData::SectionTakeImage void ClassControlCamera::setCameraFrequency(int _frequency) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return; + } paramCameraInternal.cameraFrequency = _frequency; - if (cameraConfig.xclk_freq_hz == (paramCameraInternal.cameraFrequency * 1000000)) // If frequency is matching, return without any action + if (cameraConfig.xclk_freq_hz == (paramCameraInternal.cameraFrequency * 1000000)) { // If frequency is matching, return without any + // action return; + } - if (paramCameraInternal.cameraFrequency >= 5 && paramCameraInternal.cameraFrequency <= 20) - cameraConfig.xclk_freq_hz = paramCameraInternal.cameraFrequency * 1000000; - else + if (paramCameraInternal.cameraFrequency >= 5 && paramCameraInternal.cameraFrequency <= 20) { + cameraConfig.xclk_freq_hz = paramCameraInternal.cameraFrequency * 1000000; + } + else { cameraConfig.xclk_freq_hz = 2000000; + } initCam(); printCamInfo(); @@ -258,12 +262,14 @@ void ClassControlCamera::setCameraFrequency(int _frequency) void ClassControlCamera::setImageQuality(int _qual) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return; + } - paramCameraInternal.imageQuality = std::min(63, std::max(8, _qual)); // Limit quality from 8..63 (values lower than 8 tent to be unstable) + paramCameraInternal.imageQuality = std::min(63, std::max(8, _qual)); // Limit quality from 8..63 (values lower than 8 tent to be + // unstable) - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setSizeQuality: Failed to get control structure"); return; @@ -274,8 +280,9 @@ void ClassControlCamera::setImageQuality(int _qual) void ClassControlCamera::setImageSize(int _zoomFactor, int _zoomOffsetX, int _zoomOffsetY) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return; + } sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { @@ -327,13 +334,13 @@ void ClassControlCamera::setImageSize(int _zoomFactor, int _zoomOffsetX, int _zo // NOTE 1: Function offset parameter based on image top-left (0,0). imageZoomOffsetX,Y are +/- values based on image center // NOTE 2: Parameter startX --> Sensor frame size (0: 1600 x 1200) // NOTE 3: Unused parameters: startY, endX, endY, scale, binning - s->set_res_raw(s, 0, 0, 0, 0, offsetX, offsetY, imageWidthZoomed, imageHeightZoomed, - outputFrameSizeWidth, outputFrameSizeHeight, false, false); + s->set_res_raw(s, 0, 0, 0, 0, offsetX, offsetY, imageWidthZoomed, imageHeightZoomed, outputFrameSizeWidth, outputFrameSizeHeight, + false, false); } else if (paramCameraInternal.cameraModel == CAMERA_OV5640) { // NOTE: Add sensor offset (x = 32, y = 16 --> see ov5640_settings.h: ratio_table -> 4x3) const uint8_t sensorOffsetX = 16; // Offset / 2 - const uint8_t sensorOffsetY = 8; // Offset / 2 + const uint8_t sensorOffsetY = 8; // Offset / 2 uint16_t ispWindowXStart = sensorOffsetX + imageZoomOffsetX + (sensorFrameSizeWidth - imageWidthZoomed) / 2; if (ispWindowXStart < sensorOffsetX) { // If too low set to sensor offset @@ -360,14 +367,14 @@ void ClassControlCamera::setImageSize(int _zoomFactor, int _zoomOffsetX, int _zo #ifdef DEBUG_DETAIL_ON ESP_LOGD(TAG, "SensorSize W:%d, H:%d | ImageZoomed W:%d, H:%d | Offset X:%d, Y:%d | ISPWindowStart X:%d, Y:%d", - sensorFrameSizeWidth, sensorFrameSizeHeight, imageWidthZoomed, imageHeightZoomed, - imageZoomOffsetX, imageZoomOffsetY, ispWindowXStart, ispWindowXEnd); -#endif + sensorFrameSizeWidth, sensorFrameSizeHeight, imageWidthZoomed, imageHeightZoomed, imageZoomOffsetX, imageZoomOffsetY, + ispWindowXStart, ispWindowXEnd); +#endif // DEBUG_DETAIL_ON // Set customized resolution (and scale image to output resolution) // NOTE: Function offset parameter are not used --> Offsets are applied to start values - s->set_res_raw(s, ispWindowXStart, ispWindowYStart, ispWindowXEnd, ispWindowYEnd, 0, 0, - sensorTotalPixelX, sensorTotalPixelY, outputFrameSizeWidth, outputFrameSizeHeight, true, false); + s->set_res_raw(s, ispWindowXStart, ispWindowYStart, ispWindowXEnd, ispWindowYEnd, 0, 0, sensorTotalPixelX, sensorTotalPixelY, + outputFrameSizeWidth, outputFrameSizeHeight, true, false); } else { s->set_framesize(s, FRAMESIZE_VGA); @@ -377,13 +384,14 @@ void ClassControlCamera::setImageSize(int _zoomFactor, int _zoomOffsetX, int _zo bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, int _saturation, int _sharpness, int _exposureControlMode, - int _autoExposureLevel, int _manualExposureValue, int _gainControlMode, - int _manualGainValue, int _specialEffect, bool _mirror, bool _flip) + int _autoExposureLevel, int _manualExposureValue, int _gainControlMode, int _manualGainValue, + int _specialEffect, bool _mirror, bool _flip) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return false; + } - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setImageManipulation: Failed to get control structure"); return false; @@ -405,16 +413,19 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in // Basic image manipulation // ********************************************************************* s->set_saturation(s, std::min(2, std::max(-2, paramCameraInternal.saturation))); // [-2 .. 2] - s->set_contrast(s, std::min(2, std::max(-2, paramCameraInternal.contrast ))); // [-2 .. 2] - s->set_brightness(s, std::min(2, std::max(-2, paramCameraInternal.brightness))); // [-2 .. 2] (IMPORTANT: Apply brightness after saturation and conrast) + s->set_contrast(s, std::min(2, std::max(-2, paramCameraInternal.contrast))); // [-2 .. 2] + s->set_brightness(s, std::min(2, std::max(-2, paramCameraInternal.brightness))); // [-2 .. 2] (IMPORTANT: Apply brightness after + // saturation and conrast) // Set special effect (0: None, 1: Negative, 2: Grayscale, 3: Reddish, 4: Greenish, 5: Blueish, 6: Sepia) // ********************************************************************* - if (paramCameraInternal.specialEffect >= 0 && paramCameraInternal.specialEffect <= 6) + if (paramCameraInternal.specialEffect >= 0 && paramCameraInternal.specialEffect <= 6) { s->set_special_effect(s, paramCameraInternal.specialEffect); // [0 .. 6] + } // Set sepcial effect: 7: Grayscale + Negative in combination. Do grayscale on camera + negative on MCU - else if (paramCameraInternal.specialEffect == 7) + else if (paramCameraInternal.specialEffect == 7) { s->set_special_effect(s, 2); // 2: Grayscale + } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setImageManipulation: Selected special effect unknown"); return false; @@ -442,12 +453,12 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in // Sepcial effect: 7: Grayscale + Negative in combination // NOTE: It's not possible to process both together on camera else if (paramCameraInternal.specialEffect == 7) { - registerValue |= 0x18; // Workaround: Do grayscale on camera + negative on MCU - // Disadvantage: Effect in combination not visible in other camera consumers like live stream / REST API + registerValue |= 0x18; // Workaround: Do grayscale on camera + negative on MCU + // Disadvantage: Effect in combination not visible in other camera consumers like live stream / REST API } // Maintain DSP bank byte 0 register to keep brightness, contrast, saturation and special effect settings - s->set_reg(s, 0xFF, 0x01, 0); // Select DSP bank - s->set_reg(s, 0x7C, 0xFF, 0x00); // Select byte 0 on DSP bank (IRA_BPADDR) + s->set_reg(s, 0xFF, 0x01, 0); // Select DSP bank + s->set_reg(s, 0x7C, 0xFF, 0x00); // Select byte 0 on DSP bank (IRA_BPADDR) s->set_reg(s, 0x7D, 0x5E, registerValue); // Write value (IRA_BPDATA) (bitmask 0101 1110) @@ -461,7 +472,8 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in s->set_sharpness(s, std::min(3, std::max(-3, paramCameraInternal.sharpness))); // [-3 .. 3] } else { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "setImageManipulation: Camera model not fully supported. " + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "setImageManipulation: Camera model not fully supported. " "Sharpness, brightness, contrast, saturation and special effects not properly set"); } @@ -470,7 +482,7 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in s->set_exposure_ctrl(s, paramCameraInternal.exposureControlMode > 0 ? 1 : 0); // Set exposure control if (s->status.aec) { // Auto exposure control --> Use exposure level correction - s->set_ae_level(s, std:: min(5, std::max(-5, paramCameraInternal.autoExposureLevel))); // Adjust auto exposure level [-5 .. 5] + s->set_ae_level(s, std::min(5, std::max(-5, paramCameraInternal.autoExposureLevel))); // Adjust auto exposure level [-5 .. 5] s->set_aec2(s, paramCameraInternal.exposureControlMode == 2 ? 1 : 0); // Switch to alternative alogrithm (aka night mode) } else { // Manual exposure control -> Use exposure value [0 .. sensorFrameHeight] @@ -485,16 +497,19 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in // Manual: Manual gain control between 0 .. 30 // Try to keep the gain as low as possible to keep noise at a minimum. Increase manual exposure value instead. s->set_gain_ctrl(s, paramCameraInternal.gainControlMode == 1 ? 1 : 0); // Set gain control - if (s->status.agc) // Auto gain control + + if (s->status.agc) { // Auto gain control s->set_gainceiling(s, GAINCEILING_2X); - else // Manual gain control + } + else { // Manual gain control s->set_agc_gain(s, std::min(30, std::max(0, paramCameraInternal.manualGainValue))); + } // White balance control // ********************************************************************* s->set_whitebal(s, 1); // Enable auto white balance control s->set_awb_gain(s, 1); // Enable auto white balance gain control - s->set_wb_mode(s, 0); // Set white balance mode to Auto + s->set_wb_mode(s, 0); // Set white balance mode to Auto // Image orientation // ********************************************************************* @@ -503,7 +518,7 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in #ifdef DEBUG_DETAIL_ON printCamConfig(); -#endif +#endif // DEBUG_DETAIL_ON return true; } @@ -511,10 +526,11 @@ bool ClassControlCamera::setImageManipulation(int _brightness, int _contrast, in bool ClassControlCamera::setMirrorFlip(bool _mirror, bool _flip) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return false; + } - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setMirrorFlip: Failed to get control structure"); return false; @@ -538,7 +554,7 @@ bool ClassControlCamera::getCameraInitSuccessful() camera_model_t ClassControlCamera::getCamModel(void) { - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "getCamType: Failed to get control structure"); return CAMERA_NONE; @@ -550,7 +566,7 @@ camera_model_t ClassControlCamera::getCamModel(void) std::string ClassControlCamera::getCamType(void) { - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "getCamType: Failed to get control structure"); return "Unknown"; @@ -562,7 +578,7 @@ std::string ClassControlCamera::getCamType(void) std::string ClassControlCamera::getCamPID(void) { - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "getCamPID: Failed to get control structure"); return "Unknown"; @@ -574,7 +590,7 @@ std::string ClassControlCamera::getCamPID(void) std::string ClassControlCamera::getCamVersion(void) { - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "getCamVersion: Failed to get control structure"); return "Unknown"; @@ -586,7 +602,7 @@ std::string ClassControlCamera::getCamVersion(void) int ClassControlCamera::getCamFrequencyMhz(void) { - sensor_t * s = esp_camera_sensor_get(); + sensor_t *s = esp_camera_sensor_get(); if (s == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "getCamFrequencyMhz: Failed to get control structure"); return -1; @@ -605,20 +621,21 @@ void ClassControlCamera::getOutputFrameSize(int &width, int &height) esp_err_t ClassControlCamera::captureToBasisImage(CImageBasis *_Image) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return ESP_FAIL; + } - if (paramFlashlightInternal.flashTime > 0) { // Switch on for defined time if a flashTime is set + if (paramFlashlightInternal.flashTime > 0) { // Switch on for defined time if a flashTime is set setStatusLed(true); setFlashlight(true); vTaskDelay(paramFlashlightInternal.flashTime / portTICK_PERIOD_MS); } - camera_fb_t * fb = esp_camera_fb_get(); + camera_fb_t *fb = esp_camera_fb_get(); esp_camera_fb_return(fb); fb = esp_camera_fb_get(); - if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on + if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on setStatusLed(false); setFlashlight(false); } @@ -634,19 +651,21 @@ esp_err_t ClassControlCamera::captureToBasisImage(CImageBasis *_Image) } if (_Image != NULL) { - STBIObjectPSRAM.name="rawImage"; + STBIObjectPSRAM.name = "rawImage"; STBIObjectPSRAM.usePreallocated = true; STBIObjectPSRAM.PreallocatedMemory = _Image->getRgbImage(); STBIObjectPSRAM.PreallocatedMemorySize = _Image->getMemsize(); - if(!_Image->loadFromMemoryPreallocated(fb->buf, fb->len)) + if (!_Image->loadFromMemoryPreallocated(fb->buf, fb->len)) { return ESP_FAIL; + } // Special effect: grayscale + negative in combination // Workaround: Do grayscale on camera + negative on MCU // Disadvantage: Effect in combination not visible in other camera consumers like live stream / REST API - if (paramCameraInternal.specialEffect == 7) + if (paramCameraInternal.specialEffect == 7) { _Image->createNegativeImage(); + } } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "captureToBasisImage: rawImage not allocated"); @@ -659,8 +678,9 @@ esp_err_t ClassControlCamera::captureToBasisImage(CImageBasis *_Image) esp_err_t ClassControlCamera::captureToFile(std::string _nm) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return ESP_FAIL; + } esp_err_t retVal = ESP_OK; std::string ftype; @@ -671,11 +691,11 @@ esp_err_t ClassControlCamera::captureToFile(std::string _nm) vTaskDelay(paramFlashlightInternal.flashTime / portTICK_PERIOD_MS); } - camera_fb_t * fb = esp_camera_fb_get(); + camera_fb_t *fb = esp_camera_fb_get(); esp_camera_fb_return(fb); fb = esp_camera_fb_get(); - if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on + if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on setStatusLed(false); setFlashlight(false); } @@ -687,21 +707,21 @@ esp_err_t ClassControlCamera::captureToFile(std::string _nm) #ifdef DEBUG_DETAIL_ON ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len); -#endif +#endif // DEBUG_DETAIL_ON _nm = formatFileName(_nm); #ifdef DEBUG_DETAIL_ON ESP_LOGD(TAG, "Save Camera to: %s", _nm.c_str()); -#endif +#endif // DEBUG_DETAIL_ON ftype = toUpper(getFileType(_nm)); #ifdef DEBUG_DETAIL_ON ESP_LOGD(TAG, "Filetype: %s", ftype.c_str()); -#endif +#endif // DEBUG_DETAIL_ON - uint8_t * buf = NULL; + uint8_t *buf = NULL; size_t buf_len = 0; bool converted = false; @@ -710,7 +730,7 @@ esp_err_t ClassControlCamera::captureToFile(std::string _nm) converted = true; } else if (ftype.compare("JPG") == 0) { - if (fb->format != PIXFORMAT_JPEG){ + if (fb->format != PIXFORMAT_JPEG) { bool jpeg_converted = frame2jpg(fb, paramCameraInternal.imageQuality, &buf, &buf_len); converted = true; if (!jpeg_converted) { @@ -725,7 +745,7 @@ esp_err_t ClassControlCamera::captureToFile(std::string _nm) esp_camera_fb_return(fb); - FILE * fp = fopen(_nm.c_str(), "wb"); + FILE *fp = fopen(_nm.c_str(), "wb"); if (fp == NULL) { // If an error occurs during the file creation LogFile.writeToFile(ESP_LOG_ERROR, TAG, "captureToFile: Failed to open file " + _nm); retVal = ESP_FAIL; @@ -739,14 +759,15 @@ esp_err_t ClassControlCamera::captureToFile(std::string _nm) fclose(fp); } - if (converted) + if (converted) { free(buf); + } return retVal; } -static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size_t len) +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; @@ -766,8 +787,9 @@ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size esp_err_t ClassControlCamera::captureToHTTP(httpd_req_t *_req) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return ESP_FAIL; + } esp_err_t res = ESP_OK; size_t fb_len = 0; @@ -783,7 +805,7 @@ esp_err_t ClassControlCamera::captureToHTTP(httpd_req_t *_req) esp_camera_fb_return(fb); fb = esp_camera_fb_get(); - if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on + if (paramFlashlightInternal.flashTime > 0) { // Switch off if flashlight was on setStatusLed(false); setFlashlight(false); } @@ -823,7 +845,7 @@ esp_err_t ClassControlCamera::captureToHTTP(httpd_req_t *_req) esp_camera_fb_return(fb); int64_t fr_end = esp_timer_get_time(); - ESP_LOGI(TAG, "JPG: %dKB %dms", (int)(fb_len/1024), (int)((fr_end - fr_start)/1000)); + ESP_LOGI(TAG, "JPG: %dKB %dms", (int)(fb_len / 1024), (int)((fr_end - fr_start) / 1000)); return res; } @@ -831,13 +853,14 @@ esp_err_t ClassControlCamera::captureToHTTP(httpd_req_t *_req) esp_err_t ClassControlCamera::captureToStream(httpd_req_t *_req, bool _flashlightOn) { - if (!cameraInitSuccessful) + if (!cameraInitSuccessful) { return ESP_FAIL; + } esp_err_t res = ESP_OK; size_t fb_len = 0; int64_t fr_start; - char * part_buf[64]; + char *part_buf[64]; LogFile.writeToFile(ESP_LOG_INFO, TAG, "Live stream started"); @@ -846,12 +869,12 @@ esp_err_t ClassControlCamera::captureToStream(httpd_req_t *_req, bool _flashligh setFlashlight(true); } - //httpd_resp_set_hdr(_req, "Access-Control-Allow-Origin", "*"); //stream is blocking web interface, only serving to local + // httpd_resp_set_hdr(_req, "Access-Control-Allow-Origin", "*"); //stream is blocking web interface, only serving to local httpd_resp_set_type(_req, _STREAM_CONTENT_TYPE); httpd_resp_send_chunk(_req, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY)); - while(1) { + while (1) { fr_start = esp_timer_get_time(); camera_fb_t *fb = esp_camera_fb_get(); esp_camera_fb_return(fb); @@ -876,7 +899,7 @@ esp_err_t ClassControlCamera::captureToStream(httpd_req_t *_req, bool _flashligh esp_camera_fb_return(fb); int64_t fr_end = esp_timer_get_time(); - ESP_LOGD(TAG, "JPG: %dKB %dms", (int)(fb_len/1024), (int)((fr_end - fr_start)/1000)); + ESP_LOGD(TAG, "JPG: %dKB %dms", (int)(fb_len / 1024), (int)((fr_end - fr_start) / 1000)); if (res != ESP_OK) { // Exit loop, e.g. also when closing the webpage break; @@ -884,8 +907,8 @@ esp_err_t ClassControlCamera::captureToStream(httpd_req_t *_req, bool _flashligh int64_t fr_delta_ms = (fr_end - fr_start) / 1000; if (CAM_LIVESTREAM_REFRESHRATE > fr_delta_ms) { - const TickType_t xDelay = (CAM_LIVESTREAM_REFRESHRATE - fr_delta_ms) / portTICK_PERIOD_MS; - ESP_LOGD(TAG, "Stream: sleep for: %ldms", (long) xDelay*10); + const TickType_t xDelay = (CAM_LIVESTREAM_REFRESHRATE - fr_delta_ms) / portTICK_PERIOD_MS; + ESP_LOGD(TAG, "Stream: sleep for: %ldms", (long)xDelay * 10); vTaskDelay(xDelay); } } @@ -903,42 +926,46 @@ esp_err_t ClassControlCamera::captureToStream(httpd_req_t *_req, bool _flashligh void ClassControlCamera::ledcInitFlashlightDefault(void) { // Prepare GPIO for flashlight default - gpio_config_t conf = { }; + gpio_config_t conf = {}; conf.pin_bit_mask = 1LL << GPIO_FLASHLIGHT_DEFAULT; conf.mode = GPIO_MODE_OUTPUT; gpio_config(&conf); // Prepare LEDC PWM timer configuration - ledc_timer_config_t ledc_timer = { }; + ledc_timer_config_t ledc_timer = {}; - ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; - ledc_timer.timer_num = FLASHLIGHT_DEFAULT_LEDC_TIMER; // Use TIMER 1 (TIMER0: camera) - ledc_timer.duty_resolution = FLASHLIGHT_DEFAULT_DUTY_RESOLUTION; // 13 bit - ledc_timer.freq_hz = FLASHLIGHT_DEFAULT_FREQUENCY; // Use output frequency at 5 kHz - ledc_timer.clk_cfg = LEDC_USE_APB_CLK; + ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_timer.timer_num = FLASHLIGHT_DEFAULT_LEDC_TIMER; // Use TIMER 1 (TIMER0: camera) + ledc_timer.duty_resolution = FLASHLIGHT_DEFAULT_DUTY_RESOLUTION; // 13 bit + ledc_timer.freq_hz = FLASHLIGHT_DEFAULT_FREQUENCY; // Use output frequency at 5 kHz + ledc_timer.clk_cfg = LEDC_USE_APB_CLK; esp_err_t retVal = ledc_timer_config(&ledc_timer); - if (retVal != ESP_OK) - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to init LEDC timer " + - std::to_string((int)FLASHLIGHT_DEFAULT_LEDC_TIMER) + ", Error: " +intToHexString(retVal)); + if (retVal != ESP_OK) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Failed to init LEDC timer " + std::to_string((int)FLASHLIGHT_DEFAULT_LEDC_TIMER) + + ", Error: " + intToHexString(retVal)); + } // Prepare LEDC PWM channel configuration - ledc_channel_config_t ledc_channel = { }; + ledc_channel_config_t ledc_channel = {}; - ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE; - ledc_channel.channel = FLASHLIGHT_DEFAULT_LEDC_CHANNEL; // CH0: Camera, CH2 - CH7: GPIO - ledc_channel.timer_sel = FLASHLIGHT_DEFAULT_LEDC_TIMER; // Use TIMER 1 (TIMER0: camera) - ledc_channel.intr_type = LEDC_INTR_DISABLE; - ledc_channel.gpio_num = GPIO_FLASHLIGHT_DEFAULT; // Use default flashlight GPIO pin - ledc_channel.duty = 0; // Set duty to 0% - ledc_channel.hpoint = 0; + ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_channel.channel = FLASHLIGHT_DEFAULT_LEDC_CHANNEL; // CH0: Camera, CH2 - CH7: GPIO + ledc_channel.timer_sel = FLASHLIGHT_DEFAULT_LEDC_TIMER; // Use TIMER 1 (TIMER0: camera) + ledc_channel.intr_type = LEDC_INTR_DISABLE; + ledc_channel.gpio_num = GPIO_FLASHLIGHT_DEFAULT; // Use default flashlight GPIO pin + ledc_channel.duty = 0; // Set duty to 0% + ledc_channel.hpoint = 0; retVal = ledc_channel_config(&ledc_channel); - if (retVal != ESP_OK) - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to init LEDC channel " + - std::to_string((int)FLASHLIGHT_DEFAULT_LEDC_CHANNEL) + ", Error: " +intToHexString(retVal)); + if (retVal != ESP_OK) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Failed to init LEDC channel " + std::to_string((int)FLASHLIGHT_DEFAULT_LEDC_CHANNEL) + + ", Error: " + intToHexString(retVal)); + } } #endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM @@ -976,7 +1003,7 @@ int ClassControlCamera::getFlashTime() void ClassControlCamera::setFlashlight(bool _status) { - GpioHandler* gpioHandler = gpio_handler_get(); + GpioHandler *gpioHandler = gpio_handler_get(); #ifdef GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED if (gpioHandler != NULL) { gpioHandler->gpioFlashlightControl(_status, paramFlashlightInternal.flashIntensity); @@ -986,25 +1013,25 @@ void ClassControlCamera::setFlashlight(bool _status) gpioHandler->gpioFlashlightControl(_status, paramFlashlightInternal.flashIntensity); } else { - #ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM +#ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM if (_status) { int intensityValue = (paramFlashlightInternal.flashIntensity * FLASHLIGHT_DEFAULT_RESOLUTION_RANGE) / 100; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Default flashlight PWM: GPIO" + - std::to_string((int)GPIO_FLASHLIGHT_DEFAULT) + ", State: 1, Intensity: " + - std::to_string(intensityValue) + "/" + std::to_string(FLASHLIGHT_DEFAULT_RESOLUTION_RANGE)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Default flashlight PWM: GPIO" + std::to_string((int)GPIO_FLASHLIGHT_DEFAULT) + ", State: 1, Intensity: " + + std::to_string(intensityValue) + "/" + std::to_string(FLASHLIGHT_DEFAULT_RESOLUTION_RANGE)); ledc_set_duty(LEDC_LOW_SPEED_MODE, FLASHLIGHT_DEFAULT_LEDC_CHANNEL, intensityValue); ledc_update_duty(LEDC_LOW_SPEED_MODE, FLASHLIGHT_DEFAULT_LEDC_CHANNEL); // Update duty to apply the new value } else { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Default flashlight PWM: GPIO" + - std::to_string((int)GPIO_FLASHLIGHT_DEFAULT) + ", State: 0"); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Default flashlight PWM: GPIO" + std::to_string((int)GPIO_FLASHLIGHT_DEFAULT) + ", State: 0"); ledc_set_duty(LEDC_LOW_SPEED_MODE, FLASHLIGHT_DEFAULT_LEDC_CHANNEL, 0); ledc_update_duty(LEDC_LOW_SPEED_MODE, FLASHLIGHT_DEFAULT_LEDC_CHANNEL); } - #else - esp_rom_gpio_pad_select_gpio(GPIO_FLASHLIGHT_DEFAULT); // Init the GPIO +#else + esp_rom_gpio_pad_select_gpio(GPIO_FLASHLIGHT_DEFAULT); // Init the GPIO gpio_set_direction(GPIO_FLASHLIGHT_DEFAULT, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output if (_status) { @@ -1013,7 +1040,7 @@ void ClassControlCamera::setFlashlight(bool _status) else { gpio_set_level(GPIO_FLASHLIGHT_DEFAULT, 0); } - #endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM } #endif // GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED } @@ -1021,23 +1048,27 @@ void ClassControlCamera::setFlashlight(bool _status) void ClassControlCamera::setStatusLed(bool _status) { - if (xHandle_task_StatusLED == NULL) { // Only if status LED is not used by higher prior status + if (xHandle_task_StatusLED == NULL) { // Only if status LED is not used by higher prior status // Init the GPIO esp_rom_gpio_pad_select_gpio(GPIO_STATUS_LED_ONBOARD); /* Set the GPIO as a push/pull output */ gpio_set_direction(GPIO_STATUS_LED_ONBOARD, GPIO_MODE_OUTPUT); #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - if (!_status) + if (!_status) { gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); - else + } + else { gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); + } #else - if (_status) + if (_status) { gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); - else + } + else { gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); -#endif + } +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE } } @@ -1061,8 +1092,8 @@ void ClassControlCamera::enableDemoMode() } fclose(fd); - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Using demo images (" + std::to_string(demoFiles.size()) + - " files) instead of real camera image"); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Using demo images (" + std::to_string(demoFiles.size()) + " files) instead of real camera image"); /*// Print all file to log for (auto &file : demoFiles) { diff --git a/code/components/camera_ctrl/ClassControlCamera.h b/code/components/camera_ctrl/ClassControlCamera.h index 41b38f46b..eabb450e0 100644 --- a/code/components/camera_ctrl/ClassControlCamera.h +++ b/code/components/camera_ctrl/ClassControlCamera.h @@ -19,67 +19,67 @@ typedef struct { class ClassControlCamera { - protected: - CfgData::SectionTakeImage::Camera paramCameraInternal; - CfgData::SectionTakeImage::Flashlight paramFlashlightInternal; - bool cameraInitSuccessful; - uint16_t sensorFrameSizeWidth, sensorFrameSizeHeight; - uint16_t outputFrameSizeWidth, outputFrameSizeHeight; - - bool demoMode; - std::vector demoFiles; - - void setStatusLed(bool status); - bool loadNextDemoImage(camera_fb_t *_fb); - - public: - ClassControlCamera(); - ~ClassControlCamera(); - void powerResetCamera(); - esp_err_t initCam(); - esp_err_t deinitCam(); - - bool testCamera(void); - void printCamInfo(void); - void printCamConfig(void); - - esp_err_t setCameraParameter(const CfgData::SectionTakeImage::Camera *paramCamera); - void setCameraFrequency(int _frequency); - void setImageQuality(int _qual); - void setImageSize(int _zoomFactor, int _zoomOffsetX, int _zoomOffsetY); - bool setImageManipulation(int _brightness, int _contrast, int _saturation, int _sharpness, int _exposureControlMode, - int _autoExposureLevel, int _manualExposureValue, int _gainControlMode, int _manualGainValue, - int _specialEffect, bool _mirror, bool _flip); - bool setMirrorFlip(bool _mirror, bool _flip); - - bool getCameraInitSuccessful(); - camera_model_t getCamModel(void); - std::string getCamType(void); - std::string getCamPID(void); - std::string getCamVersion(void); - int getCamFrequencyMhz(void); - void getOutputFrameSize(int &width, int &height); - - esp_err_t captureToBasisImage(CImageBasis *_Image); - esp_err_t captureToFile(std::string _nm); - esp_err_t captureToHTTP(httpd_req_t *_req); - esp_err_t captureToStream(httpd_req_t *_req, bool _flashlightOn); - - #ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM - void ledcInitFlashlightDefault(void); - #endif - esp_err_t setFlashlightParameter(const CfgData::SectionTakeImage::Flashlight *paramFlashlight); - void setFlashIntensity(int _flashIntensity); - void setFlashTime(int _flashTime); - int getFlashTime(); - void setFlashlight(bool _status); - - void enableDemoMode(void); - void disableDemoMode(void); - void freeDemoMemoryOnly(); + protected: + CfgData::SectionTakeImage::Camera paramCameraInternal; + CfgData::SectionTakeImage::Flashlight paramFlashlightInternal; + bool cameraInitSuccessful; + uint16_t sensorFrameSizeWidth, sensorFrameSizeHeight; + uint16_t outputFrameSizeWidth, outputFrameSizeHeight; + + bool demoMode; + std::vector demoFiles; + + void setStatusLed(bool status); + bool loadNextDemoImage(camera_fb_t *_fb); + + public: + ClassControlCamera(); + ~ClassControlCamera(); + void powerResetCamera(); + esp_err_t initCam(); + esp_err_t deinitCam(); + + bool testCamera(void); + void printCamInfo(void); + void printCamConfig(void); + + esp_err_t setCameraParameter(const CfgData::SectionTakeImage::Camera *paramCamera); + void setCameraFrequency(int _frequency); + void setImageQuality(int _qual); + void setImageSize(int _zoomFactor, int _zoomOffsetX, int _zoomOffsetY); + bool setImageManipulation(int _brightness, int _contrast, int _saturation, int _sharpness, int _exposureControlMode, + int _autoExposureLevel, int _manualExposureValue, int _gainControlMode, int _manualGainValue, + int _specialEffect, bool _mirror, bool _flip); + bool setMirrorFlip(bool _mirror, bool _flip); + + bool getCameraInitSuccessful(); + camera_model_t getCamModel(void); + std::string getCamType(void); + std::string getCamPID(void); + std::string getCamVersion(void); + int getCamFrequencyMhz(void); + void getOutputFrameSize(int &width, int &height); + + esp_err_t captureToBasisImage(CImageBasis *_Image); + esp_err_t captureToFile(std::string _nm); + esp_err_t captureToHTTP(httpd_req_t *_req); + esp_err_t captureToStream(httpd_req_t *_req, bool _flashlightOn); + +#ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM + void ledcInitFlashlightDefault(void); +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM + esp_err_t setFlashlightParameter(const CfgData::SectionTakeImage::Flashlight *paramFlashlight); + void setFlashIntensity(int _flashIntensity); + void setFlashTime(int _flashTime); + int getFlashTime(); + void setFlashlight(bool _status); + + void enableDemoMode(void); + void disableDemoMode(void); + void freeDemoMemoryOnly(); }; extern ClassControlCamera cameraCtrl; -#endif \ No newline at end of file +#endif // CLASSCONTROLCAMERA_H diff --git a/code/components/camera_ctrl/ov2640_sharpness.cpp b/code/components/camera_ctrl/ov2640_sharpness.cpp index 20e3d1d4e..cef9fbf20 100644 --- a/code/components/camera_ctrl/ov2640_sharpness.cpp +++ b/code/components/camera_ctrl/ov2640_sharpness.cpp @@ -5,91 +5,72 @@ #define OV2640_MAXLEVEL_SHARPNESS 6 -const static uint8_t OV2640_SHARPNESS_AUTO[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0x20, 0x20, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_AUTO[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0x20, 0x20, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_MANUAL[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0x00, 0x20, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_MANUAL[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0x00, 0x20, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL0[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xc0, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL0[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xC0, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL1[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xc1, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL1[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xC1, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL2[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xc2, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL2[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xC2, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL3[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xc4, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL3[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xC4, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL4[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xc8, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL4[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xC8, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL5[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xd0, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL5[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xD0, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t OV2640_SHARPNESS_LEVEL6[]= -{ - 0xFF, 0x00, 0xff, - 0x92, 0x01, 0xff, - 0x93, 0xdf, 0x1f, - 0x00, 0x00, 0x00 +const static uint8_t OV2640_SHARPNESS_LEVEL6[] = { + 0xFF, 0x00, 0xFF, // + 0x92, 0x01, 0xFF, // + 0x93, 0xDF, 0x1F, // + 0x00, 0x00, 0x00 // }; - -const static uint8_t *OV2640_SETTING_SHARPNESS[]= -{ - OV2640_SHARPNESS_LEVEL0, // -3 sharpness - OV2640_SHARPNESS_LEVEL1, - OV2640_SHARPNESS_LEVEL2, - OV2640_SHARPNESS_LEVEL3, - OV2640_SHARPNESS_LEVEL4, - OV2640_SHARPNESS_LEVEL5, - OV2640_SHARPNESS_LEVEL6 // +3 sharpness +const static uint8_t *OV2640_SETTING_SHARPNESS[] = { + OV2640_SHARPNESS_LEVEL0, // -3 + OV2640_SHARPNESS_LEVEL1, // + OV2640_SHARPNESS_LEVEL2, // + OV2640_SHARPNESS_LEVEL3, // + OV2640_SHARPNESS_LEVEL4, // + OV2640_SHARPNESS_LEVEL5, // + OV2640_SHARPNESS_LEVEL6 // +3 }; -static bool table_mask_write(sensor_t *_sensor, const uint8_t* _ptab) +static bool table_mask_write(sensor_t *_sensor, const uint8_t *_ptab) { uint8_t address; uint8_t value; @@ -97,16 +78,17 @@ static bool table_mask_write(sensor_t *_sensor, const uint8_t* _ptab) uint8_t mask; const uint8_t *pdata = _ptab; - if (pdata == NULL) + if (pdata == NULL) { return false; + } - while (1) - { + while (1) { address = *pdata++; value = *pdata++; mask = *pdata++; - if ((address == 0) && (value == 0) && (mask == 0)) + if ((address == 0) && (value == 0) && (mask == 0)) { break; + } _sensor->set_reg(_sensor, address, mask, value); } @@ -122,8 +104,9 @@ bool ov2640_enable_auto_sharpness(sensor_t *_sensor) bool ov2640_set_sharpness(sensor_t *_sensor, int _sharpness) { - if ((_sharpness < -3) || (_sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)) + if ((_sharpness < -3) || (_sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)) { return false; + } bool retval = false; retval = table_mask_write(_sensor, OV2640_SHARPNESS_MANUAL); diff --git a/code/components/camera_ctrl/ov2640_sharpness.h b/code/components/camera_ctrl/ov2640_sharpness.h index e4e325b21..2366421b9 100644 --- a/code/components/camera_ctrl/ov2640_sharpness.h +++ b/code/components/camera_ctrl/ov2640_sharpness.h @@ -6,4 +6,4 @@ bool ov2640_enable_auto_sharpness(sensor_t *_sensor); bool ov2640_set_sharpness(sensor_t *_sensor, int _sharpness); // -3 to +3, -4 for auto-sharpness -#endif +#endif // OV2640_SHARPNESS_H diff --git a/code/components/camera_ctrl/server_camera.cpp b/code/components/camera_ctrl/server_camera.cpp index af14e5ade..91a304675 100644 --- a/code/components/camera_ctrl/server_camera.cpp +++ b/code/components/camera_ctrl/server_camera.cpp @@ -15,7 +15,7 @@ static const char *TAG = "SERVER_CAM"; esp_err_t handler_camera(httpd_req_t *req) { - const char* APIName = "camera:v2"; // API name and version + const char *APIName = "camera:v2"; // API name and version char _query[384]; char _valuechar[30], _flashtime[30], _filename[100]; std::string task; @@ -27,8 +27,8 @@ esp_err_t handler_camera(httpd_req_t *req) "Handler usage:
" "1. Set camera parameter:
" "- '/camera?task=set_parameter&flashtime=0.1&flashintensity=1&brightness=-2&contrast=0& " - "saturation=0&sharpness=1&exposurecontrolmode=0&autoexposurelevel=0&manualexposurevalue=1200& " - "gaincontrolmode=0&manualgainvalue=2&specialeffect=0&mirror=false&flip=false&zoomfactor=1000&zoomx=0&zoomy=0'
" + "saturation=0&sharpness=1&exposurecontrolmode=0&autoexposurelevel=0&manualexposurevalue=1200& " + "gaincontrolmode=0&manualgainvalue=2&specialeffect=0&mirror=false&flip=false&zoomfactor=1000&zoomx=0&zoomy=0'
" "2. Capture image
" " - '/camera?task=capture' : Capture without flashlight
" " - '/camera?task=capture_with_flashlight&flashtime=1000' : Capture with flashlight (flashtime in ms)
" @@ -52,7 +52,7 @@ esp_err_t handler_camera(httpd_req_t *req) fn.append(_filename); } } - else { // if no parameter is provided, print handler usage + else { // if no parameter is provided, print handler usage httpd_resp_set_type(req, "text/html"); httpd_resp_sendstr(req, RESTUsageInfo.c_str()); return ESP_OK; @@ -91,7 +91,7 @@ esp_err_t handler_camera(httpd_req_t *req) paramCamera.sharpness = stoi(std::string(_valuechar)); } if (httpd_query_key_value(_query, "exposurecontrolmode", _valuechar, sizeof(_valuechar)) == ESP_OK) { - paramCamera.exposureControlMode = stoi(std::string(_valuechar)); + paramCamera.exposureControlMode = stoi(std::string(_valuechar)); } if (httpd_query_key_value(_query, "autoexposurelevel", _valuechar, sizeof(_valuechar)) == ESP_OK) { paramCamera.autoExposureLevel = stoi(std::string(_valuechar)); @@ -109,12 +109,12 @@ esp_err_t handler_camera(httpd_req_t *req) paramCamera.specialEffect = stoi(std::string(_valuechar)); } if (httpd_query_key_value(_query, "mirror", _valuechar, sizeof(_valuechar)) == ESP_OK) { - (std::string(_valuechar) == "1" || std::string(_valuechar) == "true") ? - paramCamera.mirrorImage = true : paramCamera.mirrorImage = false; + (std::string(_valuechar) == "1" || std::string(_valuechar) == "true") ? paramCamera.mirrorImage = true + : paramCamera.mirrorImage = false; } if (httpd_query_key_value(_query, "flip", _valuechar, sizeof(_valuechar)) == ESP_OK) { - (std::string(_valuechar) == "1" || std::string(_valuechar) == "true") ? - paramCamera.flipImage = true : paramCamera.flipImage = false; + (std::string(_valuechar) == "1" || std::string(_valuechar) == "true") ? paramCamera.flipImage = true + : paramCamera.flipImage = false; } if (httpd_query_key_value(_query, "zoomfactor", _valuechar, sizeof(_valuechar)) == ESP_OK) { paramCamera.zoomFactor = stoi(std::string(_valuechar)); @@ -149,7 +149,7 @@ esp_err_t handler_camera(httpd_req_t *req) else if (task.compare("capture_with_flashlight") == 0) { if (flashtime == 0) { httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, - "E93: No flashtime provided, e.g. '/capture?task=capture_with_flashlight&flashtime=1000'"); + "E93: No flashtime provided, e.g. '/capture?task=capture_with_flashlight&flashtime=1000'"); return ESP_FAIL; } @@ -169,13 +169,15 @@ esp_err_t handler_camera(httpd_req_t *req) } else if (task.compare("capture_to_file") == 0) { if (flashtime == 0) { - httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, + httpd_resp_send_err( + req, HTTPD_400_BAD_REQUEST, "E93: No flashtime provided, e.g. '/capture?task=capture_to_file&flashtime=1000&filename=/img_tmp/test.jpg'"); return ESP_FAIL; } if (fn.compare("/sdcard/") == 0) { - httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, + httpd_resp_send_err( + req, HTTPD_400_BAD_REQUEST, "E94: No destination provided, e.g. '/capture?task=capture_to_file&flashtime=1000&filename=/img_tmp/test.jpg'"); return ESP_FAIL; } @@ -224,11 +226,11 @@ void registerCameraUri(httpd_handle_t server) { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t camuri = { }; - camuri.method = HTTP_GET; + httpd_uri_t camuri = {}; + camuri.method = HTTP_GET; - camuri.uri = "/camera"; - camuri.handler = handler_camera; - camuri.user_ctx = NULL; + camuri.uri = "/camera"; + camuri.handler = handler_camera; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); -} \ No newline at end of file +} diff --git a/code/components/camera_ctrl/server_camera.h b/code/components/camera_ctrl/server_camera.h index 7e62ca978..c27b6bac0 100644 --- a/code/components/camera_ctrl/server_camera.h +++ b/code/components/camera_ctrl/server_camera.h @@ -7,4 +7,4 @@ void registerCameraUri(httpd_handle_t server); -#endif \ No newline at end of file +#endif // SERVER_CAMERA_H \ No newline at end of file diff --git a/code/components/config_handling/configClass.cpp b/code/components/config_handling/configClass.cpp index 2f0e0eaa3..6b9cdcf51 100644 --- a/code/components/config_handling/configClass.cpp +++ b/code/components/config_handling/configClass.cpp @@ -120,8 +120,8 @@ void ConfigClass::readConfigFile(bool unityTest, std::string unityTestData) { std::stringstream streamBuffer; - if (unityTest) { // Unity test - clearCfgDataTemp(); // Clear internal struct + if (unityTest) { // Unity test + clearCfgDataTemp(); // Clear internal struct streamBuffer.str(unityTestData); // Inject test data } else { // Read data from file @@ -180,7 +180,7 @@ esp_err_t ConfigClass::setConfigRequest(httpd_req_t *req) httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_type(req, "application/json"); - char *httpBuffer = (char *) ((struct HttpServerData *)req->user_ctx)->scratch; + char *httpBuffer = (char *)((struct HttpServerData *)req->user_ctx)->scratch; while (remaining > 0) { // Receive the file part by part into a buffer if ((received = httpd_req_recv(req, httpBuffer, std::min(remaining, WEBSERVER_SCRATCH_BUFSIZE))) <= 0) { @@ -235,13 +235,15 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // Config Verison // *************************** cJSON *objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "config"), "version"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionConfig.version = objEl->valueint; + } if (init) { // Reload data from backup during initial boot cJSON *objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "config"), "lastmodified"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionConfig.lastModified = objEl->valuestring; + } } else { // Update timestamp whenever content gets updated cfgDataTemp.sectionConfig.lastModified = getCurrentTimeString(TIME_FORMAT_OUTPUT); @@ -251,103 +253,127 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // Operation Mode // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "operationmode"), "opmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionOperationMode.opMode = std::clamp(objEl->valueint, -1, 1); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "operationmode"), "automaticprocessinterval"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionOperationMode.automaticProcessInterval = std::max(std::stof(objEl->valuestring), (float)0.1); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "operationmode"), "usedemoimages"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionOperationMode.useDemoImages = objEl->valueint; + } // TakeImage // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "flashlight"), "flashtime"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.flashlight.flashTime = std::max(objEl->valueint, 100); // milliseconds + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "flashlight"), "flashintensity"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.flashlight.flashIntensity = std::clamp(objEl->valueint, 0, 100); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "cameramodel"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.imageQuality = std::clamp(objEl->valueint, 0, 14); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "camerafrequency"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.cameraFrequency = std::clamp(objEl->valueint, 5, 20); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "imagequality"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.imageQuality = std::clamp(objEl->valueint, 8, 63); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "brightness"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.brightness = std::clamp(objEl->valueint, -2, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "contrast"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.contrast = std::clamp(objEl->valueint, -2, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "saturation"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.saturation = std::clamp(objEl->valueint, -2, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "sharpness"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.sharpness = std::clamp(objEl->valueint, -3, 3); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "exposurecontrolmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.exposureControlMode = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "autoexposurelevel"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.autoExposureLevel = std::clamp(objEl->valueint, -5, 5); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "manualexposurevalue"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.manualExposureValue = std::clamp(objEl->valueint, 0, 1920); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "gaincontrolmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.gainControlMode = std::clamp(objEl->valueint, 0, 1); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "manualgainvalue"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.manualGainValue = std::clamp(objEl->valueint, 0, 30); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "specialeffect"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.specialEffect = std::clamp(objEl->valueint, 0, 7); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "mirrorimage"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionTakeImage.camera.mirrorImage = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "flipimage"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionTakeImage.camera.flipImage = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "zoomfactor"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.zoomFactor = std::clamp(objEl->valueint, 1000, 4000); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "zoomoffsetx"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.zoomOffsetX = std::clamp(objEl->valueint, -960, 960); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "zoomoffsety"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.camera.zoomOffsetY = std::clamp(objEl->valueint, -720, 720); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "debug"), "saverawimages"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionTakeImage.debug.saveRawImages = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "debug"), "rawimageslocation"); if (cJSON_IsString(objEl)) { @@ -356,27 +382,32 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "debug"), "rawimagesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionTakeImage.debug.rawImagesRetention = std::max(objEl->valueint, 0); + } // Image Alignment // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "alignmentalgo"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionImageAlignment.alignmentAlgo = std::clamp(objEl->valueint, 0, 4); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "searchfield"), "x"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionImageAlignment.searchField.x = std::max(objEl->valueint, 1); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "searchfield"), "y"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionImageAlignment.searchField.y = std::max(objEl->valueint, 1); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "imagerotation"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionImageAlignment.imageRotation = std::clamp(std::stof(objEl->valuestring), (float)-180.0, (float)180.0); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "marker"); for (int i = 0; i < cJSON_GetArraySize(objEl); i++) { @@ -384,17 +415,20 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) cJSON *arrEl; arrEl = cJSON_GetObjectItem(objArrEl, "x"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { cfgDataTemp.sectionImageAlignment.marker[i].x = std::max(arrEl->valueint, 1); + } arrEl = cJSON_GetObjectItem(objArrEl, "y"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { cfgDataTemp.sectionImageAlignment.marker[i].y = std::max(arrEl->valueint, 1); + } } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "imagealignment"), "debug"), "savedebuginfo"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionImageAlignment.debug.saveDebugInfo = objEl->valueint; + } // Number Sequences @@ -457,17 +491,17 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } if (!existing) { cfgDataTemp.sectionNumberSequences.sequence.erase(cfgDataTemp.sectionNumberSequences.sequence.begin() + i); - //cfgDataTemp.sectionNumberSequences.sequence.shrink_to_fit(); + // cfgDataTemp.sectionNumberSequences.sequence.shrink_to_fit(); cfgDataTemp.sectionDigit.sequence.erase(cfgDataTemp.sectionDigit.sequence.begin() + i); - //cfgDataTemp.sectionDigit.sequence.shrink_to_fit(); + // cfgDataTemp.sectionDigit.sequence.shrink_to_fit(); cfgDataTemp.sectionAnalog.sequence.erase(cfgDataTemp.sectionAnalog.sequence.begin() + i); - //cfgDataTemp.sectionAnalog.sequence.shrink_to_fit(); + // cfgDataTemp.sectionAnalog.sequence.shrink_to_fit(); cfgDataTemp.sectionPostProcessing.sequence.erase(cfgDataTemp.sectionPostProcessing.sequence.begin() + i); - //cfgDataTemp.sectionPostProcessing.sequence.shrink_to_fit(); + // cfgDataTemp.sectionPostProcessing.sequence.shrink_to_fit(); cfgDataTemp.sectionInfluxDBv1.sequence.erase(cfgDataTemp.sectionInfluxDBv1.sequence.begin() + i); - //cfgDataTemp.sectionInfluxDBv1.sequence.shrink_to_fit(); + // cfgDataTemp.sectionInfluxDBv1.sequence.shrink_to_fit(); cfgDataTemp.sectionInfluxDBv2.sequence.erase(cfgDataTemp.sectionInfluxDBv2.sequence.begin() + i); - //cfgDataTemp.sectionInfluxDBv2.sequence.shrink_to_fit(); + // cfgDataTemp.sectionInfluxDBv2.sequence.shrink_to_fit(); i--; } } @@ -478,8 +512,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) std::string sequenceNameTemp = ""; cJSON *sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequencename"); - if (cJSON_IsString(sequenceArrEl)) + if (cJSON_IsString(sequenceArrEl)) { sequenceNameTemp = sequenceArrEl->valuestring; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequenceid"); if (cJSON_IsNumber(sequenceArrEl)) { @@ -494,7 +529,7 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) sequenceEl.sequenceName = sequenceNameTemp; cfgDataTemp.sectionNumberSequences.sequence.push_back(sequenceEl); RoiPerSequence sequenceRoiEl; - sequenceRoiEl.sequenceId = cfgDataTemp.sectionNumberSequences.sequence.back().sequenceId ; + sequenceRoiEl.sequenceId = cfgDataTemp.sectionNumberSequences.sequence.back().sequenceId; sequenceRoiEl.sequenceName = cfgDataTemp.sectionNumberSequences.sequence.back().sequenceName; cfgDataTemp.sectionDigit.sequence.push_back(sequenceRoiEl); cfgDataTemp.sectionAnalog.sequence.push_back(sequenceRoiEl); @@ -513,15 +548,24 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) if (sequenceArrEl->valueint == cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId) { cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName = sequenceNameTemp; cfgDataTemp.sectionDigit.sequence[i].sequenceId = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; - cfgDataTemp.sectionDigit.sequence[i].sequenceName = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; - cfgDataTemp.sectionAnalog.sequence[i].sequenceId = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; - cfgDataTemp.sectionAnalog.sequence[i].sequenceName = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; - cfgDataTemp.sectionPostProcessing.sequence[i].sequenceId = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; - cfgDataTemp.sectionPostProcessing.sequence[i].sequenceName = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; - cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceId = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; - cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceName = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; - cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceId = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; - cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceName = cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; + cfgDataTemp.sectionDigit.sequence[i].sequenceName = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; + cfgDataTemp.sectionAnalog.sequence[i].sequenceId = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; + cfgDataTemp.sectionAnalog.sequence[i].sequenceName = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; + cfgDataTemp.sectionPostProcessing.sequence[i].sequenceId = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; + cfgDataTemp.sectionPostProcessing.sequence[i].sequenceName = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; + cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceId = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; + cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceName = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; + cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceId = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId; + cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceName = + cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName; break; } } @@ -536,17 +580,17 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // Sort sequences std::sort(cfgDataTemp.sectionNumberSequences.sequence.begin(), cfgDataTemp.sectionNumberSequences.sequence.end(), - [](const SequenceList &x, const SequenceList &y) { return x.sequenceId < y.sequenceId; }); + [](const SequenceList &x, const SequenceList &y) { return x.sequenceId < y.sequenceId; }); std::sort(cfgDataTemp.sectionDigit.sequence.begin(), cfgDataTemp.sectionDigit.sequence.end(), - [](const RoiPerSequence &x, const RoiPerSequence &y) { return x.sequenceId < y.sequenceId; }); + [](const RoiPerSequence &x, const RoiPerSequence &y) { return x.sequenceId < y.sequenceId; }); std::sort(cfgDataTemp.sectionAnalog.sequence.begin(), cfgDataTemp.sectionAnalog.sequence.end(), - [](const RoiPerSequence &x, const RoiPerSequence &y) { return x.sequenceId < y.sequenceId; }); + [](const RoiPerSequence &x, const RoiPerSequence &y) { return x.sequenceId < y.sequenceId; }); std::sort(cfgDataTemp.sectionPostProcessing.sequence.begin(), cfgDataTemp.sectionPostProcessing.sequence.end(), - [](const PostProcessingPerSequence &x, const PostProcessingPerSequence &y) { return x.sequenceId < y.sequenceId; }); + [](const PostProcessingPerSequence &x, const PostProcessingPerSequence &y) { return x.sequenceId < y.sequenceId; }); std::sort(cfgDataTemp.sectionInfluxDBv1.sequence.begin(), cfgDataTemp.sectionInfluxDBv1.sequence.end(), - [](const InfluxDBPerSequence &x, const InfluxDBPerSequence &y) { return x.sequenceId < y.sequenceId; }); + [](const InfluxDBPerSequence &x, const InfluxDBPerSequence &y) { return x.sequenceId < y.sequenceId; }); std::sort(cfgDataTemp.sectionInfluxDBv2.sequence.begin(), cfgDataTemp.sectionInfluxDBv2.sequence.end(), - [](const InfluxDBPerSequence &x, const InfluxDBPerSequence &y) { return x.sequenceId < y.sequenceId; }); + [](const InfluxDBPerSequence &x, const InfluxDBPerSequence &y) { return x.sequenceId < y.sequenceId; }); } else if (cfgDataTemp.sectionNumberSequences.sequence.size() == 0) { // Make sure, at least one sequence is available @@ -571,16 +615,19 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // Digit // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionDigit.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "model"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionDigit.model = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "cnngoodthreshold"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionDigit.cnnGoodThreshold = std::clamp(std::stof(objEl->valuestring), (float)0.00, (float)1.00); + } // Update sequences objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "sequence"); @@ -590,8 +637,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) std::string sequenceNameTemp = ""; cJSON *sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequencename"); - if (cJSON_IsString(sequenceArrEl)) + if (cJSON_IsString(sequenceArrEl)) { sequenceNameTemp = sequenceArrEl->valuestring; + } RoiPerSequence *sequenceEl = NULL; sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequenceid"); @@ -604,13 +652,14 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } } else if (sequenceArrEl->valueint == seqEl.sequenceId) { // Update existing sequence - sequenceEl = &seqEl; // Get sequence config structure + sequenceEl = &seqEl; // Get sequence config structure break; } } } - if (sequenceEl == NULL) + if (sequenceEl == NULL) { continue; + } sequenceEl->roi.clear(); @@ -621,23 +670,27 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) cJSON *roiEl; RoiElement roiElTemp; - roiElTemp.roiName = sequenceEl->sequenceName + "_dig" + std::to_string(j+1); + roiElTemp.roiName = sequenceEl->sequenceName + "_dig" + std::to_string(j + 1); roiEl = cJSON_GetObjectItem(roiArrEl, "x"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.x = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "y"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.y = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "dx"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.dx = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "dy"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.dy = std::max(roiEl->valueint, 1); + } sequenceEl->roi.push_back(roiElTemp); } @@ -645,8 +698,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "debug"), "saveroiimages"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionDigit.debug.saveRoiImages = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "debug"), "roiimageslocation"); if (cJSON_IsString(objEl)) { @@ -655,19 +709,22 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "digit"), "debug"), "roiimagesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionDigit.debug.roiImagesRetention = std::max(objEl->valueint, 0); + } // Analog // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "analog"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionAnalog.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "analog"), "model"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionAnalog.model = objEl->valuestring; + } // Update sequences @@ -678,8 +735,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) std::string sequenceNameTemp = ""; cJSON *sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequencename"); - if (cJSON_IsString(sequenceArrEl)) + if (cJSON_IsString(sequenceArrEl)) { sequenceNameTemp = sequenceArrEl->valuestring; + } RoiPerSequence *sequenceEl = NULL; sequenceArrEl = cJSON_GetObjectItem(objArrEl, "sequenceid"); @@ -692,13 +750,14 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } } else if (sequenceArrEl->valueint == seqEl.sequenceId) { // Update existing sequence - sequenceEl = &seqEl; // Get sequence config structure + sequenceEl = &seqEl; // Get sequence config structure break; } } } - if (sequenceEl == NULL) + if (sequenceEl == NULL) { continue; + } sequenceEl->roi.clear(); sequenceEl->roi.shrink_to_fit(); @@ -708,27 +767,32 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) cJSON *roiEl; RoiElement roiElTemp; - roiElTemp.roiName = sequenceEl->sequenceName + "_ana" + std::to_string(j+1); + roiElTemp.roiName = sequenceEl->sequenceName + "_ana" + std::to_string(j + 1); roiEl = cJSON_GetObjectItem(roiArrEl, "x"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.x = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "y"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.y = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "dx"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.dx = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "dy"); - if (cJSON_IsNumber(roiEl)) + if (cJSON_IsNumber(roiEl)) { roiElTemp.dy = std::max(roiEl->valueint, 1); + } roiEl = cJSON_GetObjectItem(roiArrEl, "ccw"); - if (cJSON_IsBool(roiEl)) + if (cJSON_IsBool(roiEl)) { roiElTemp.ccw = roiEl->valueint; + } sequenceEl->roi.push_back(roiElTemp); } @@ -736,8 +800,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "analog"), "debug"), "saveroiimages"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionAnalog.debug.saveRoiImages = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "analog"), "debug"), "roiimageslocation"); if (cJSON_IsString(objEl)) { @@ -746,8 +811,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "analog"), "debug"), "roiimagesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionAnalog.debug.roiImagesRetention = std::max(objEl->valueint, 0); + } // Post-Processing @@ -768,13 +834,14 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) if (cJSON_IsString(sequenceArrEl)) { for (auto &seqEl : cfgDataTemp.sectionPostProcessing.sequence) { if (sequenceArrEl->valuestring == seqEl.sequenceName) { // Update existing sequence - sequenceEl = &seqEl; // Get sequence config structure + sequenceEl = &seqEl; // Get sequence config structure break; } } } - if (sequenceEl == NULL) + if (sequenceEl == NULL) { continue; + } // Disable post-processing per sequence not yet implemented // @TODO FEATURE /*sequenceArrEl = cJSON_GetObjectItem(objArrEl, "enabled"); @@ -782,61 +849,74 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) sequenceEl->enabled = sequenceArrEl->valueint;*/ sequenceArrEl = cJSON_GetObjectItem(objArrEl, "decimalshift"); - if (cJSON_IsNumber(sequenceArrEl)) + if (cJSON_IsNumber(sequenceArrEl)) { sequenceEl->decimalShift = std::clamp(sequenceArrEl->valueint, -9, 9); + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "analogdigitsyncvalue"); - if (cJSON_IsString(sequenceArrEl)) + if (cJSON_IsString(sequenceArrEl)) { sequenceEl->analogDigitSyncValue = std::clamp(std::stof(sequenceArrEl->valuestring), (float)6.0, (float)9.9); + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "extendedresolution"); - if (cJSON_IsBool(sequenceArrEl)) + if (cJSON_IsBool(sequenceArrEl)) { sequenceEl->extendedResolution = sequenceArrEl->valueint; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "ignoreleadingnan"); - if (cJSON_IsBool(sequenceArrEl)) + if (cJSON_IsBool(sequenceArrEl)) { sequenceEl->ignoreLeadingNaN = sequenceArrEl->valueint; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "checkdigitincreaseconsistency"); - if (cJSON_IsBool(sequenceArrEl)) + if (cJSON_IsBool(sequenceArrEl)) { sequenceEl->checkDigitIncreaseConsistency = sequenceArrEl->valueint; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "maxratechecktype"); - if (cJSON_IsNumber(sequenceArrEl)) + if (cJSON_IsNumber(sequenceArrEl)) { sequenceEl->maxRateCheckType = std::clamp(sequenceArrEl->valueint, 0, 2); + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "maxrate"); - if (cJSON_IsString(sequenceArrEl)) + if (cJSON_IsString(sequenceArrEl)) { sequenceEl->maxRate = std::max(std::stof(sequenceArrEl->valuestring), (float)0.001); + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "allownegativerate"); - if (cJSON_IsBool(sequenceArrEl)) + if (cJSON_IsBool(sequenceArrEl)) { sequenceEl->allowNegativeRate = sequenceArrEl->valueint; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "usefallbackvalue"); - if (cJSON_IsBool(sequenceArrEl)) + if (cJSON_IsBool(sequenceArrEl)) { sequenceEl->useFallbackValue = sequenceArrEl->valueint; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "fallbackvalueagestartup"); - if (cJSON_IsNumber(sequenceArrEl)) + if (cJSON_IsNumber(sequenceArrEl)) { sequenceEl->fallbackValueAgeStartup = std::max(sequenceArrEl->valueint, 0); + } } } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "postprocessing"), "debug"), "savedebuginfo"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionPostProcessing.debug.saveDebugInfo = objEl->valueint; + } // MQTT // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionMqtt.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "uri"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionMqtt.uri = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "maintopic"); if (cJSON_IsString(objEl)) { @@ -845,16 +925,19 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "clientid"); - if (cJSON_IsString(objEl) && strlen(objEl->valuestring) <= 23) // MQTT v3.1 spec limits to max 23 character + if (cJSON_IsString(objEl) && strlen(objEl->valuestring) <= 23) { // MQTT v3.1 spec limits to max 23 character cfgDataTemp.sectionMqtt.clientID = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "authmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionMqtt.authMode = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "username"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionMqtt.username = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "password"); if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0) { @@ -886,16 +969,19 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "processdatanotation"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionMqtt.processDataNotation = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "retainprocessdata"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionMqtt.retainProcessData = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "homeassistant"), "discoveryenabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionMqtt.homeAssistant.discoveryEnabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "homeassistant"), "discoveryprefix"); if (cJSON_IsString(objEl)) { @@ -910,35 +996,42 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "homeassistant"), "metertype"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionMqtt.homeAssistant.meterType = std::clamp(objEl->valueint, 0, 10); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "mqtt"), "homeassistant"), "retaindiscovery"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionMqtt.homeAssistant.retainDiscovery = objEl->valueint; + } // InfluxDB v1.x // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionInfluxDBv1.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "uri"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv1.uri = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "database"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv1.database = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "authmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionInfluxDBv1.authMode = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "username"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv1.username = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv1"), "password"); if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0) { @@ -980,13 +1073,14 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) if (cJSON_IsString(sequenceArrEl)) { for (auto &seqEl : cfgDataTemp.sectionInfluxDBv1.sequence) { if (sequenceArrEl->valuestring == seqEl.sequenceName) { // Update existing sequence - sequenceEl = &seqEl; // Get sequence config structure + sequenceEl = &seqEl; // Get sequence config structure break; } } } - if (sequenceEl == NULL) + if (sequenceEl == NULL) { continue; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "measurementname"); if (cJSON_IsString(sequenceArrEl)) { @@ -1006,24 +1100,29 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // InfluxDB v2.x // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionInfluxDBv2.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "uri"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv2.uri = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "bucket"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv2.bucket = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "organization"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionInfluxDBv2.organization = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "authmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionInfluxDBv2.authMode = std::clamp(objEl->valueint, 1, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "influxdbv2"), "token"); if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0) { @@ -1066,13 +1165,14 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) if (cJSON_IsString(sequenceArrEl)) { for (auto &seqEl : cfgDataTemp.sectionInfluxDBv2.sequence) { if (sequenceArrEl->valuestring == seqEl.sequenceName) { // Update existing sequence - sequenceEl = &seqEl; // Get sequence config structure + sequenceEl = &seqEl; // Get sequence config structure break; } } } - if (sequenceEl == NULL) + if (sequenceEl == NULL) { continue; + } sequenceArrEl = cJSON_GetObjectItem(objArrEl, "measurementname"); if (cJSON_IsString(sequenceArrEl)) { @@ -1092,28 +1192,34 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // Webhook // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionWebhook.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "uri"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionWebhook.uri = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "apikey"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionWebhook.apiKey = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "publishimage"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionWebhook.publishImage = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "authmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionWebhook.authMode = std::clamp(objEl->valueint, 0, 2); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "username"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionWebhook.username = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webhook"), "password"); if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0) { @@ -1148,14 +1254,16 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) // GPIO // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "gpio"), "customizationenabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionGpio.customizationEnabled = objEl->valueint; + } // Restore backup --> Add sequences if (init) { for (int i = 0; i < GPIO_SPARE_PIN_COUNT; i++) { - if (gpio_spare[i] == -1) + if (gpio_spare[i] == -1) { continue; + } bool elementVerified = false; for (auto it = std::begin(cfgDataTemp.sectionGpio.gpioPin); it != std::end(cfgDataTemp.sectionGpio.gpioPin); ++it) { @@ -1168,8 +1276,9 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) GpioElement gpioEl; gpioEl.gpioNumber = (int)gpio_spare[i]; gpioEl.gpioUsage = gpio_spare_usage[i]; - if (std::string(gpio_spare_usage[i]).substr(0, 10) == "flashlight") + if (std::string(gpio_spare_usage[i]).substr(0, 10) == "flashlight") { gpioEl.pinMode = "flashlight-default"; + } cfgDataTemp.sectionGpio.gpioPin.push_back(gpioEl); } @@ -1195,107 +1304,131 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } } } - if (gpioElTemp == NULL) + if (gpioElTemp == NULL) { continue; + } for (int i = 0; i < GPIO_SPARE_PIN_COUNT; i++) { - if (gpio_spare[i] == gpioElTemp->gpioNumber) + if (gpio_spare[i] == gpioElTemp->gpioNumber) { gpioElTemp->gpioUsage = gpio_spare_usage[i]; + } } arrEl = cJSON_GetObjectItem(objArrEl, "pinenabled"); - if (cJSON_IsBool(arrEl)) + if (cJSON_IsBool(arrEl)) { gpioElTemp->pinEnabled = arrEl->valueint; + } arrEl = cJSON_GetObjectItem(objArrEl, "pinname"); - if (cJSON_IsString(arrEl)) + if (cJSON_IsString(arrEl)) { gpioElTemp->pinName = arrEl->valuestring; + } arrEl = cJSON_GetObjectItem(objArrEl, "pinmode"); - if (cJSON_IsString(arrEl)) + if (cJSON_IsString(arrEl)) { gpioElTemp->pinMode = arrEl->valuestring; + } arrEl = cJSON_GetObjectItem(objArrEl, "capturemode"); - if (cJSON_IsString(arrEl)) + if (cJSON_IsString(arrEl)) { gpioElTemp->captureMode = arrEl->valuestring; + } arrEl = cJSON_GetObjectItem(objArrEl, "inputdebouncetime"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->inputDebounceTime = std::clamp(arrEl->valueint, 0, 5000); // Milliseconds + } arrEl = cJSON_GetObjectItem(objArrEl, "pwmfrequency"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->PwmFrequency = std::clamp(arrEl->valueint, 5, 1000000); // Hertz + } arrEl = cJSON_GetObjectItem(objArrEl, "logicactivelow"); - if (cJSON_IsBool(arrEl)) + if (cJSON_IsBool(arrEl)) { gpioElTemp->logicActiveLow = arrEl->valueint; + } arrEl = cJSON_GetObjectItem(objArrEl, "exposetomqtt"); - if (cJSON_IsBool(arrEl)) + if (cJSON_IsBool(arrEl)) { gpioElTemp->exposeToMqtt = arrEl->valueint; + } arrEl = cJSON_GetObjectItem(objArrEl, "exposetorest"); - if (cJSON_IsBool(arrEl)) + if (cJSON_IsBool(arrEl)) { gpioElTemp->exposeToRest = arrEl->valueint; + } arrEl = cJSON_GetObjectItem(cJSON_GetObjectItem(objArrEl, "smartled"), "type"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->smartLed.type = std::clamp(arrEl->valueint, 0, 5); + } arrEl = cJSON_GetObjectItem(cJSON_GetObjectItem(objArrEl, "smartled"), "quantity"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->smartLed.quantity = std::max(arrEl->valueint, 1); + } arrEl = cJSON_GetObjectItem(cJSON_GetObjectItem(objArrEl, "smartled"), "colorredchannel"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->smartLed.colorRedChannel = std::clamp(arrEl->valueint, 0, 255); + } arrEl = cJSON_GetObjectItem(cJSON_GetObjectItem(objArrEl, "smartled"), "colorgreenchannel"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->smartLed.colorGreenChannel = std::clamp(arrEl->valueint, 0, 255); + } arrEl = cJSON_GetObjectItem(cJSON_GetObjectItem(objArrEl, "smartled"), "colorbluechannel"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->smartLed.colorBlueChannel = std::clamp(arrEl->valueint, 0, 255); + } arrEl = cJSON_GetObjectItem(objArrEl, "intensitycorrectionfactor"); - if (cJSON_IsNumber(arrEl)) + if (cJSON_IsNumber(arrEl)) { gpioElTemp->intensityCorrectionFactor = std::clamp(arrEl->valueint, 1, 100); + } } // Logging // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "log"), "debug"), "loglevel"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionLog.debug.logLevel = std::clamp(objEl->valueint, 1, 4); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "log"), "debug"), "logfilesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionLog.debug.logFilesRetention = std::max(objEl->valueint, 0); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "log"), "debug"), "debugfilesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionLog.debug.debugFilesRetention = std::max(objEl->valueint, 0); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "log"), "data"), "enabled"); - if (cJSON_IsBool(objEl)) + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionLog.data.enabled = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "log"), "data"), "datafilesretention"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionLog.data.dataFilesRetention = std::max(objEl->valueint, 0); + } // Network objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "opmode"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionNetwork.opmode = std::clamp(objEl->valueint, -1, 3); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "timedoffdelay"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionNetwork.timedOffDelay = std::max(objEl->valueint, 1); + } bool ssidEmpty = false; objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ssid"); @@ -1316,7 +1449,7 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "password"); - if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0 && !ssidEmpty) { + if (cJSON_IsString(objEl) && strcmp(objEl->valuestring, "******") != 0 && !ssidEmpty) { cfgDataTemp.sectionNetwork.wlan.password = objEl->valuestring; saveDataToNVS("wlan_pw", cfgDataTemp.sectionNetwork.wlan.password); } @@ -1327,104 +1460,140 @@ esp_err_t ConfigClass::parseConfig(httpd_req_t *req, bool init, bool unityTest) } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "hostname"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionNetwork.wlan.hostname = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), "networkconfig"); - if (cJSON_IsNumber(objEl)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), + "networkconfig"); + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig = std::clamp(objEl->valueint, 0, 1); + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), "ipaddress"); - if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), + "ipaddress"); + if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) { cfgDataTemp.sectionNetwork.wlan.ipv4.ipAddress = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), "subnetmask"); - if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), + "subnetmask"); + if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) { cfgDataTemp.sectionNetwork.wlan.ipv4.subnetMask = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), "gatewayaddress"); - if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), + "gatewayaddress"); + if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) { cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress = objEl->valuestring; + } // Static IP config selected, but IP config invalid --> Fallback to DHCP if (cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig == NETWORK_WLAN_IP_CONFIG_STATIC) { if (!isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.ipAddress.c_str()) || !isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.subnetMask.c_str()) || !isValidIpAddress(cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress.c_str())) { - cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig = NETWORK_WLAN_IP_CONFIG_DHCP; - LogFile.writeToFile(ESP_LOG_WARN, TAG, "parseConfig: Static network config invalid. Use DHCP as fallback"); + cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig = NETWORK_WLAN_IP_CONFIG_DHCP; + LogFile.writeToFile(ESP_LOG_WARN, TAG, "parseConfig: Static network config invalid. Use DHCP as fallback"); } } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), "dnsserver"); - if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "ipv4"), + "dnsserver"); + if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) { cfgDataTemp.sectionNetwork.wlan.ipv4.dnsServer = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "wlanroaming"), "enabled"); - if (cJSON_IsBool(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "wlanroaming"), "enabled"); + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionNetwork.wlan.wlanRoaming.enabled = objEl->valueint; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "wlanroaming"), "rssithreshold"); - if (cJSON_IsNumber(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlan"), "wlanroaming"), "rssithreshold"); + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionNetwork.wlan.wlanRoaming.rssiThreshold = std::clamp(objEl->valueint, -100, 0); + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "ssid"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionNetwork.wlanAp.ssid = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "password"); - if (cJSON_IsString(objEl) && (strlen(objEl->valuestring) == 0 || strlen(objEl->valuestring) >= 8)) + if (cJSON_IsString(objEl) && (strlen(objEl->valuestring) == 0 || strlen(objEl->valuestring) >= 8)) { cfgDataTemp.sectionNetwork.wlanAp.password = objEl->valuestring; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "channel"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionNetwork.wlanAp.channel = std::clamp(objEl->valueint, 1, 14); + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "ipv4"), "ipaddress"); - if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "wlanap"), "ipv4"), + "ipaddress"); + if (cJSON_IsString(objEl) && isValidIpAddress(objEl->valuestring)) { cfgDataTemp.sectionNetwork.wlanAp.ipv4.ipAddress = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), "timesyncenabled"); - if (cJSON_IsBool(objEl)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), + "timesyncenabled"); + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionNetwork.time.ntp.timeSyncEnabled = objEl->valueint; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), "timeserver"); - if (cJSON_IsString(objEl)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), + "timeserver"); + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionNetwork.time.ntp.timeServer = objEl->valuestring; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), "processstartinterlock"); - if (cJSON_IsBool(objEl)) + objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "ntp"), + "processstartinterlock"); + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionNetwork.time.ntp.processStartInterlock = objEl->valueint; + } objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "network"), "time"), "timezone"); - if (cJSON_IsString(objEl)) + if (cJSON_IsString(objEl)) { cfgDataTemp.sectionNetwork.time.timeZone = objEl->valuestring; + } // System // *************************** objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "system"), "cpufrequency"); - if (cJSON_IsNumber(objEl)) + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionSystem.cpuFrequency = std::clamp(objEl->valueint, 160, 240); + } // WebUI // *************************** - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "overviewpage"), "enabled"); - if (cJSON_IsBool(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "overviewpage"), "enabled"); + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.enabled = objEl->valueint; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "overviewpage"), "refreshtime"); - if (cJSON_IsNumber(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "overviewpage"), "refreshtime"); + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.refreshTime = std::max(objEl->valueint, 1); + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "datagraphpage"), "enabled"); - if (cJSON_IsBool(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "datagraphpage"), "enabled"); + if (cJSON_IsBool(objEl)) { cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.enabled = objEl->valueint; + } - objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "datagraphpage"), "refreshtime"); - if (cJSON_IsNumber(objEl)) + objEl = cJSON_GetObjectItem( + cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "webui"), "autorefresh"), "datagraphpage"), "refreshtime"); + if (cJSON_IsNumber(objEl)) { cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.refreshTime = std::max(objEl->valueint, 1); + } // Check for configuration migration if (!unityTest) { @@ -1482,600 +1651,845 @@ esp_err_t ConfigClass::serializeConfig(bool unityTest) // Config Version // *************************** cJSON *config; - if (!cJSON_AddItemToObject(cJsonObject, "config", config = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "config", config = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(config, "version", cfgDataTemp.sectionConfig.version) == NULL) + } + if (cJSON_AddNumberToObject(config, "version", cfgDataTemp.sectionConfig.version) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(config, "lastmodified", cfgDataTemp.sectionConfig.lastModified.c_str()) == NULL) + } + if (cJSON_AddStringToObject(config, "lastmodified", cfgDataTemp.sectionConfig.lastModified.c_str()) == NULL) { retVal = ESP_FAIL; + } // Operation Mode // *************************** cJSON *operationmode; - if (!cJSON_AddItemToObject(cJsonObject, "operationmode", operationmode = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "operationmode", operationmode = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(operationmode, "opmode", cfgDataTemp.sectionOperationMode.opMode) == NULL) + } + if (cJSON_AddNumberToObject(operationmode, "opmode", cfgDataTemp.sectionOperationMode.opMode) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddStringToObject(operationmode, "automaticprocessinterval", - to_stringWithPrecision(cfgDataTemp.sectionOperationMode.automaticProcessInterval, 1).c_str()) == NULL) + to_stringWithPrecision(cfgDataTemp.sectionOperationMode.automaticProcessInterval, 1).c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(operationmode, "usedemoimages", cfgDataTemp.sectionOperationMode.useDemoImages) == NULL) + } + if (cJSON_AddBoolToObject(operationmode, "usedemoimages", cfgDataTemp.sectionOperationMode.useDemoImages) == NULL) { retVal = ESP_FAIL; + } // Take Image // *************************** cJSON *takeImage, *flashlight, *camera, *takeImageDebug; - if (!cJSON_AddItemToObject(cJsonObject, "takeimage", takeImage = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "takeimage", takeImage = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(takeImage, "flashlight", flashlight = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(takeImage, "flashlight", flashlight = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(flashlight, "flashtime", cfgDataTemp.sectionTakeImage.flashlight.flashTime) == NULL) + } + if (cJSON_AddNumberToObject(flashlight, "flashtime", cfgDataTemp.sectionTakeImage.flashlight.flashTime) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(flashlight, "flashintensity", cfgDataTemp.sectionTakeImage.flashlight.flashIntensity) == NULL) + } + if (cJSON_AddNumberToObject(flashlight, "flashintensity", cfgDataTemp.sectionTakeImage.flashlight.flashIntensity) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(takeImage, "camera", camera = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(takeImage, "camera", camera = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "cameramodel", cfgDataTemp.sectionTakeImage.camera.cameraModel) == NULL) + } + if (cJSON_AddNumberToObject(camera, "cameramodel", cfgDataTemp.sectionTakeImage.camera.cameraModel) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "camerafrequency", cfgDataTemp.sectionTakeImage.camera.cameraFrequency) == NULL) + } + if (cJSON_AddNumberToObject(camera, "camerafrequency", cfgDataTemp.sectionTakeImage.camera.cameraFrequency) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "imagequality", cfgDataTemp.sectionTakeImage.camera.imageQuality) == NULL) + } + if (cJSON_AddNumberToObject(camera, "imagequality", cfgDataTemp.sectionTakeImage.camera.imageQuality) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "brightness", cfgDataTemp.sectionTakeImage.camera.brightness) == NULL) + } + if (cJSON_AddNumberToObject(camera, "brightness", cfgDataTemp.sectionTakeImage.camera.brightness) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "contrast", cfgDataTemp.sectionTakeImage.camera.contrast) == NULL) + } + if (cJSON_AddNumberToObject(camera, "contrast", cfgDataTemp.sectionTakeImage.camera.contrast) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "saturation", cfgDataTemp.sectionTakeImage.camera.saturation) == NULL) + } + if (cJSON_AddNumberToObject(camera, "saturation", cfgDataTemp.sectionTakeImage.camera.saturation) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "sharpness", cfgDataTemp.sectionTakeImage.camera.sharpness) == NULL) + } + if (cJSON_AddNumberToObject(camera, "sharpness", cfgDataTemp.sectionTakeImage.camera.sharpness) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "exposurecontrolmode", cfgDataTemp.sectionTakeImage.camera.exposureControlMode) == NULL) + } + if (cJSON_AddNumberToObject(camera, "exposurecontrolmode", cfgDataTemp.sectionTakeImage.camera.exposureControlMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "autoexposurelevel", cfgDataTemp.sectionTakeImage.camera.autoExposureLevel) == NULL) + } + if (cJSON_AddNumberToObject(camera, "autoexposurelevel", cfgDataTemp.sectionTakeImage.camera.autoExposureLevel) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "manualexposurevalue", cfgDataTemp.sectionTakeImage.camera.manualExposureValue) == NULL) + } + if (cJSON_AddNumberToObject(camera, "manualexposurevalue", cfgDataTemp.sectionTakeImage.camera.manualExposureValue) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "gaincontrolmode", cfgDataTemp.sectionTakeImage.camera.gainControlMode) == NULL) + } + if (cJSON_AddNumberToObject(camera, "gaincontrolmode", cfgDataTemp.sectionTakeImage.camera.gainControlMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "manualgainvalue", cfgDataTemp.sectionTakeImage.camera.manualGainValue) == NULL) + } + if (cJSON_AddNumberToObject(camera, "manualgainvalue", cfgDataTemp.sectionTakeImage.camera.manualGainValue) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "specialeffect", cfgDataTemp.sectionTakeImage.camera.specialEffect) == NULL) + } + if (cJSON_AddNumberToObject(camera, "specialeffect", cfgDataTemp.sectionTakeImage.camera.specialEffect) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(camera, "mirrorimage", cfgDataTemp.sectionTakeImage.camera.mirrorImage) == NULL) + } + if (cJSON_AddBoolToObject(camera, "mirrorimage", cfgDataTemp.sectionTakeImage.camera.mirrorImage) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(camera, "flipimage", cfgDataTemp.sectionTakeImage.camera.flipImage) == NULL) + } + if (cJSON_AddBoolToObject(camera, "flipimage", cfgDataTemp.sectionTakeImage.camera.flipImage) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "zoomfactor", cfgDataTemp.sectionTakeImage.camera.zoomFactor) == NULL) + } + if (cJSON_AddNumberToObject(camera, "zoomfactor", cfgDataTemp.sectionTakeImage.camera.zoomFactor) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "zoomoffsetx", cfgDataTemp.sectionTakeImage.camera.zoomOffsetX) == NULL) + } + if (cJSON_AddNumberToObject(camera, "zoomoffsetx", cfgDataTemp.sectionTakeImage.camera.zoomOffsetX) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(camera, "zoomoffsety", cfgDataTemp.sectionTakeImage.camera.zoomOffsetY) == NULL) + } + if (cJSON_AddNumberToObject(camera, "zoomoffsety", cfgDataTemp.sectionTakeImage.camera.zoomOffsetY) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(takeImage, "debug", takeImageDebug = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(takeImage, "debug", takeImageDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(takeImageDebug, "saverawimages", cfgDataTemp.sectionTakeImage.debug.saveRawImages) == NULL) + } + if (cJSON_AddBoolToObject(takeImageDebug, "saverawimages", cfgDataTemp.sectionTakeImage.debug.saveRawImages) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(takeImageDebug, "rawimageslocation", cfgDataTemp.sectionTakeImage.debug.rawImagesLocation.c_str()) == NULL) + } + if (cJSON_AddStringToObject(takeImageDebug, "rawimageslocation", cfgDataTemp.sectionTakeImage.debug.rawImagesLocation.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(takeImageDebug, "rawimagesretention", cfgDataTemp.sectionTakeImage.debug.rawImagesRetention) == NULL) + } + if (cJSON_AddNumberToObject(takeImageDebug, "rawimagesretention", cfgDataTemp.sectionTakeImage.debug.rawImagesRetention) == NULL) { retVal = ESP_FAIL; + } // Image Alignment // *************************** cJSON *imageAlignment, *searchField, *marker, *markerEl, *imageAlignmentDebug; - if (!cJSON_AddItemToObject(cJsonObject, "imagealignment", imageAlignment = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "imagealignment", imageAlignment = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(imageAlignment, "alignmentalgo", cfgDataTemp.sectionImageAlignment.alignmentAlgo) == NULL) + } + if (cJSON_AddNumberToObject(imageAlignment, "alignmentalgo", cfgDataTemp.sectionImageAlignment.alignmentAlgo) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(imageAlignment, "searchfield", searchField = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(imageAlignment, "searchfield", searchField = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(searchField, "x", cfgDataTemp.sectionImageAlignment.searchField.x) == NULL) + } + if (cJSON_AddNumberToObject(searchField, "x", cfgDataTemp.sectionImageAlignment.searchField.x) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(searchField, "y", cfgDataTemp.sectionImageAlignment.searchField.y) == NULL) + } + if (cJSON_AddNumberToObject(searchField, "y", cfgDataTemp.sectionImageAlignment.searchField.y) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(imageAlignment, "imagerotation", to_stringWithPrecision(cfgDataTemp.sectionImageAlignment.imageRotation, 1).c_str()) == - NULL) + } + if (cJSON_AddStringToObject(imageAlignment, "imagerotation", + to_stringWithPrecision(cfgDataTemp.sectionImageAlignment.imageRotation, 1).c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(imageAlignment, "marker", marker = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(imageAlignment, "marker", marker = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < 2; ++i) { cJSON_AddItemToArray(marker, markerEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(markerEl, "x", cfgDataTemp.sectionImageAlignment.marker[i].x) == NULL) + if (cJSON_AddNumberToObject(markerEl, "x", cfgDataTemp.sectionImageAlignment.marker[i].x) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(markerEl, "y", cfgDataTemp.sectionImageAlignment.marker[i].y) == NULL) + } + if (cJSON_AddNumberToObject(markerEl, "y", cfgDataTemp.sectionImageAlignment.marker[i].y) == NULL) { retVal = ESP_FAIL; + } } - if (!cJSON_AddItemToObject(imageAlignment, "debug", imageAlignmentDebug = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(imageAlignment, "debug", imageAlignmentDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(imageAlignmentDebug, "savedebuginfo", cfgDataTemp.sectionImageAlignment.debug.saveDebugInfo) == NULL) + } + if (cJSON_AddBoolToObject(imageAlignmentDebug, "savedebuginfo", cfgDataTemp.sectionImageAlignment.debug.saveDebugInfo) == NULL) { retVal = ESP_FAIL; + } // Number Sequences // *************************** cJSON *numbersequences, *sequences, *sequence; - if (!cJSON_AddItemToObject(cJsonObject, "numbersequences", numbersequences = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "numbersequences", numbersequences = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(numbersequences, "sequence", sequences = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(numbersequences, "sequence", sequences = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionNumberSequences.sequence.size(); ++i) { cJSON_AddItemToArray(sequences, sequence = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(sequence, "sequenceid", cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(sequence, "sequenceid", cfgDataTemp.sectionNumberSequences.sequence[i].sequenceId) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(sequence, "sequencename", cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(sequence, "sequencename", cfgDataTemp.sectionNumberSequences.sequence[i].sequenceName.c_str()) == + NULL) { retVal = ESP_FAIL; + } } // Digit // *************************** cJSON *digit, *digitSequence, *digitSequenceEl, *digitRoi, *digitRoiEl, *digitDebug; - if (!cJSON_AddItemToObject(cJsonObject, "digit", digit = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "digit", digit = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(digit, "enabled", cfgDataTemp.sectionDigit.enabled) == NULL) + } + if (cJSON_AddBoolToObject(digit, "enabled", cfgDataTemp.sectionDigit.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(digit, "model", cfgDataTemp.sectionDigit.model.c_str()) == NULL) + } + if (cJSON_AddStringToObject(digit, "model", cfgDataTemp.sectionDigit.model.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(digit, "cnngoodthreshold", to_stringWithPrecision(cfgDataTemp.sectionDigit.cnnGoodThreshold, 2).c_str()) == NULL) + } + if (cJSON_AddStringToObject(digit, "cnngoodthreshold", to_stringWithPrecision(cfgDataTemp.sectionDigit.cnnGoodThreshold, 2).c_str()) == + NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(digit, "sequence", digitSequence = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(digit, "sequence", digitSequence = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionDigit.sequence.size(); i++) { cJSON_AddItemToArray(digitSequence, digitSequenceEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(digitSequenceEl, "sequenceid", cfgDataTemp.sectionDigit.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(digitSequenceEl, "sequenceid", cfgDataTemp.sectionDigit.sequence[i].sequenceId) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(digitSequenceEl, "sequencename", cfgDataTemp.sectionDigit.sequence[i].sequenceName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(digitSequenceEl, "sequencename", cfgDataTemp.sectionDigit.sequence[i].sequenceName.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(digitSequenceEl, "roi", digitRoi = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(digitSequenceEl, "roi", digitRoi = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int j = 0; j < cfgDataTemp.sectionDigit.sequence[i].roi.size(); j++) { cJSON_AddItemToArray(digitRoi, digitRoiEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(digitRoiEl, "x", cfgDataTemp.sectionDigit.sequence[i].roi[j].x) == NULL) + if (cJSON_AddNumberToObject(digitRoiEl, "x", cfgDataTemp.sectionDigit.sequence[i].roi[j].x) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(digitRoiEl, "y", cfgDataTemp.sectionDigit.sequence[i].roi[j].y) == NULL) + } + if (cJSON_AddNumberToObject(digitRoiEl, "y", cfgDataTemp.sectionDigit.sequence[i].roi[j].y) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(digitRoiEl, "dx", cfgDataTemp.sectionDigit.sequence[i].roi[j].dx) == NULL) + } + if (cJSON_AddNumberToObject(digitRoiEl, "dx", cfgDataTemp.sectionDigit.sequence[i].roi[j].dx) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(digitRoiEl, "dy", cfgDataTemp.sectionDigit.sequence[i].roi[j].dy) == NULL) + } + if (cJSON_AddNumberToObject(digitRoiEl, "dy", cfgDataTemp.sectionDigit.sequence[i].roi[j].dy) == NULL) { retVal = ESP_FAIL; + } } } - if (!cJSON_AddItemToObject(digit, "debug", digitDebug = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(digit, "debug", digitDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(digitDebug, "saveroiimages", cfgDataTemp.sectionDigit.debug.saveRoiImages) == NULL) + } + if (cJSON_AddBoolToObject(digitDebug, "saveroiimages", cfgDataTemp.sectionDigit.debug.saveRoiImages) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(digitDebug, "roiimageslocation", cfgDataTemp.sectionDigit.debug.roiImagesLocation.c_str()) == NULL) + } + if (cJSON_AddStringToObject(digitDebug, "roiimageslocation", cfgDataTemp.sectionDigit.debug.roiImagesLocation.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(digitDebug, "roiimagesretention", cfgDataTemp.sectionDigit.debug.roiImagesRetention) == NULL) + } + if (cJSON_AddNumberToObject(digitDebug, "roiimagesretention", cfgDataTemp.sectionDigit.debug.roiImagesRetention) == NULL) { retVal = ESP_FAIL; + } // Analog // *************************** cJSON *analog, *analogSequence, *analogSequenceEl, *analogRoi, *analogRoiEl, *analogDebug; - if (!cJSON_AddItemToObject(cJsonObject, "analog", analog = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "analog", analog = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(analog, "enabled", cfgDataTemp.sectionAnalog.enabled) == NULL) + } + if (cJSON_AddBoolToObject(analog, "enabled", cfgDataTemp.sectionAnalog.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(analog, "model", cfgDataTemp.sectionAnalog.model.c_str()) == NULL) + } + if (cJSON_AddStringToObject(analog, "model", cfgDataTemp.sectionAnalog.model.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(analog, "sequence", analogSequence = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(analog, "sequence", analogSequence = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionAnalog.sequence.size(); i++) { cJSON_AddItemToArray(analogSequence, analogSequenceEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(analogSequenceEl, "sequenceid", cfgDataTemp.sectionAnalog.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(analogSequenceEl, "sequenceid", cfgDataTemp.sectionAnalog.sequence[i].sequenceId) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(analogSequenceEl, "sequencename", cfgDataTemp.sectionAnalog.sequence[i].sequenceName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(analogSequenceEl, "sequencename", cfgDataTemp.sectionAnalog.sequence[i].sequenceName.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(analogSequenceEl, "roi", analogRoi = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(analogSequenceEl, "roi", analogRoi = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int j = 0; j < cfgDataTemp.sectionAnalog.sequence[i].roi.size(); j++) { cJSON_AddItemToArray(analogRoi, analogRoiEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(analogRoiEl, "x", cfgDataTemp.sectionAnalog.sequence[i].roi[j].x) == NULL) + if (cJSON_AddNumberToObject(analogRoiEl, "x", cfgDataTemp.sectionAnalog.sequence[i].roi[j].x) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(analogRoiEl, "y", cfgDataTemp.sectionAnalog.sequence[i].roi[j].y) == NULL) + } + if (cJSON_AddNumberToObject(analogRoiEl, "y", cfgDataTemp.sectionAnalog.sequence[i].roi[j].y) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(analogRoiEl, "dx", cfgDataTemp.sectionAnalog.sequence[i].roi[j].dx) == NULL) + } + if (cJSON_AddNumberToObject(analogRoiEl, "dx", cfgDataTemp.sectionAnalog.sequence[i].roi[j].dx) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(analogRoiEl, "dy", cfgDataTemp.sectionAnalog.sequence[i].roi[j].dy) == NULL) + } + if (cJSON_AddNumberToObject(analogRoiEl, "dy", cfgDataTemp.sectionAnalog.sequence[i].roi[j].dy) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(analogRoiEl, "ccw", cfgDataTemp.sectionAnalog.sequence[i].roi[j].ccw) == NULL) + } + if (cJSON_AddBoolToObject(analogRoiEl, "ccw", cfgDataTemp.sectionAnalog.sequence[i].roi[j].ccw) == NULL) { retVal = ESP_FAIL; + } } } - if (!cJSON_AddItemToObject(analog, "debug", analogDebug = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(analog, "debug", analogDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(analogDebug, "saveroiimages", cfgDataTemp.sectionAnalog.debug.saveRoiImages) == NULL) + } + if (cJSON_AddBoolToObject(analogDebug, "saveroiimages", cfgDataTemp.sectionAnalog.debug.saveRoiImages) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(analogDebug, "roiimageslocation", cfgDataTemp.sectionAnalog.debug.roiImagesLocation.c_str()) == NULL) + } + if (cJSON_AddStringToObject(analogDebug, "roiimageslocation", cfgDataTemp.sectionAnalog.debug.roiImagesLocation.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(analogDebug, "roiimagesretention", cfgDataTemp.sectionAnalog.debug.roiImagesRetention) == NULL) + } + if (cJSON_AddNumberToObject(analogDebug, "roiimagesretention", cfgDataTemp.sectionAnalog.debug.roiImagesRetention) == NULL) { retVal = ESP_FAIL; + } // Post-Processing // *************************** cJSON *postprocessing, *postprocessingSequence, *postprocessingSequenceEl, *postprocessingDebug; - if (!cJSON_AddItemToObject(cJsonObject, "postprocessing", postprocessing = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "postprocessing", postprocessing = cJSON_CreateObject())) { retVal = ESP_FAIL; + } // Disable post-processing not yet implemented // @TODO FEATURE /*if (cJSON_AddBoolToObject(postprocessing, "enabled", cfgDataTemp.sectionPostProcessing.enabled) == NULL) retVal = ESP_FAIL;*/ - if (!cJSON_AddItemToObject(postprocessing, "sequence", postprocessingSequence = cJSON_CreateArray())) + if (!cJSON_AddItemToObject(postprocessing, "sequence", postprocessingSequence = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionPostProcessing.sequence.size(); ++i) { cJSON_AddItemToArray(postprocessingSequence, postprocessingSequenceEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(postprocessingSequenceEl, "sequenceid", - cfgDataTemp.sectionPostProcessing.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(postprocessingSequenceEl, "sequenceid", cfgDataTemp.sectionPostProcessing.sequence[i].sequenceId) == + NULL) { retVal = ESP_FAIL; + } if (cJSON_AddStringToObject(postprocessingSequenceEl, "sequencename", - cfgDataTemp.sectionPostProcessing.sequence[i].sequenceName.c_str()) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].sequenceName.c_str()) == NULL) { retVal = ESP_FAIL; + } // Disable post-processing per sequence not yet implemented // @TODO FEATURE /*if (cJSON_AddBoolToObject(postprocessingSequenceEl, "enabled", cfgDataTemp.sectionPostProcessing.sequence[i].enabled) == NULL) retVal = ESP_FAIL;*/ - if (cJSON_AddNumberToObject(postprocessingSequenceEl, "decimalshift", - cfgDataTemp.sectionPostProcessing.sequence[i].decimalShift) == NULL) + if (cJSON_AddNumberToObject(postprocessingSequenceEl, "decimalshift", cfgDataTemp.sectionPostProcessing.sequence[i].decimalShift) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(postprocessingSequenceEl, "analogdigitsyncvalue", - to_stringWithPrecision(cfgDataTemp.sectionPostProcessing.sequence[i].analogDigitSyncValue, 1).c_str()) == NULL) + } + if (cJSON_AddStringToObject( + postprocessingSequenceEl, "analogdigitsyncvalue", + to_stringWithPrecision(cfgDataTemp.sectionPostProcessing.sequence[i].analogDigitSyncValue, 1).c_str()) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddBoolToObject(postprocessingSequenceEl, "extendedresolution", - cfgDataTemp.sectionPostProcessing.sequence[i].extendedResolution) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].extendedResolution) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddBoolToObject(postprocessingSequenceEl, "ignoreleadingnan", - cfgDataTemp.sectionPostProcessing.sequence[i].ignoreLeadingNaN) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].ignoreLeadingNaN) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddBoolToObject(postprocessingSequenceEl, "checkdigitincreaseconsistency", - cfgDataTemp.sectionPostProcessing.sequence[i].checkDigitIncreaseConsistency) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].checkDigitIncreaseConsistency) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddNumberToObject(postprocessingSequenceEl, "maxratechecktype", - cfgDataTemp.sectionPostProcessing.sequence[i].maxRateCheckType) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].maxRateCheckType) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddStringToObject(postprocessingSequenceEl, "maxrate", - to_stringWithPrecision(cfgDataTemp.sectionPostProcessing.sequence[i].maxRate, 3).c_str()) == NULL) + to_stringWithPrecision(cfgDataTemp.sectionPostProcessing.sequence[i].maxRate, 3).c_str()) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddBoolToObject(postprocessingSequenceEl, "allownegativerate", - cfgDataTemp.sectionPostProcessing.sequence[i].allowNegativeRate) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].allowNegativeRate) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddBoolToObject(postprocessingSequenceEl, "usefallbackvalue", - cfgDataTemp.sectionPostProcessing.sequence[i].useFallbackValue) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].useFallbackValue) == NULL) { retVal = ESP_FAIL; + } if (cJSON_AddNumberToObject(postprocessingSequenceEl, "fallbackvalueagestartup", - cfgDataTemp.sectionPostProcessing.sequence[i].fallbackValueAgeStartup) == NULL) + cfgDataTemp.sectionPostProcessing.sequence[i].fallbackValueAgeStartup) == NULL) { retVal = ESP_FAIL; + } } - if (!cJSON_AddItemToObject(postprocessing, "debug", postprocessingDebug = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(postprocessing, "debug", postprocessingDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(postprocessingDebug, "savedebuginfo", cfgDataTemp.sectionPostProcessing.debug.saveDebugInfo) == NULL) + } + if (cJSON_AddBoolToObject(postprocessingDebug, "savedebuginfo", cfgDataTemp.sectionPostProcessing.debug.saveDebugInfo) == NULL) { retVal = ESP_FAIL; + } // MQTT // *************************** cJSON *mqtt, *mqttTls, *mqttHomeAssistant; - if (!cJSON_AddItemToObject(cJsonObject, "mqtt", mqtt = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "mqtt", mqtt = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(mqtt, "enabled", cfgDataTemp.sectionMqtt.enabled) == NULL) + } + if (cJSON_AddBoolToObject(mqtt, "enabled", cfgDataTemp.sectionMqtt.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqtt, "uri", cfgDataTemp.sectionMqtt.uri.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqtt, "uri", cfgDataTemp.sectionMqtt.uri.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqtt, "maintopic", cfgDataTemp.sectionMqtt.mainTopic.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqtt, "maintopic", cfgDataTemp.sectionMqtt.mainTopic.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqtt, "clientid", cfgDataTemp.sectionMqtt.clientID.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqtt, "clientid", cfgDataTemp.sectionMqtt.clientID.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(mqtt, "authmode", cfgDataTemp.sectionMqtt.authMode) == NULL) + } + if (cJSON_AddNumberToObject(mqtt, "authmode", cfgDataTemp.sectionMqtt.authMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqtt, "username", cfgDataTemp.sectionMqtt.username.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqtt, "username", cfgDataTemp.sectionMqtt.username.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqtt, "password", cfgDataTemp.sectionMqtt.password.empty() ? "" : "******") == NULL) + } + if (cJSON_AddStringToObject(mqtt, "password", cfgDataTemp.sectionMqtt.password.empty() ? "" : "******") == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(mqtt, "tls", mqttTls = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(mqtt, "tls", mqttTls = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqttTls, "cacert", cfgDataTemp.sectionMqtt.tls.caCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqttTls, "cacert", cfgDataTemp.sectionMqtt.tls.caCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqttTls, "clientcert", cfgDataTemp.sectionMqtt.tls.clientCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqttTls, "clientcert", cfgDataTemp.sectionMqtt.tls.clientCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqttTls, "clientkey", cfgDataTemp.sectionMqtt.tls.clientKey.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqttTls, "clientkey", cfgDataTemp.sectionMqtt.tls.clientKey.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(mqtt, "processdatanotation", cfgDataTemp.sectionMqtt.processDataNotation) == NULL) + } + if (cJSON_AddNumberToObject(mqtt, "processdatanotation", cfgDataTemp.sectionMqtt.processDataNotation) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(mqtt, "retainprocessdata", cfgDataTemp.sectionMqtt.retainProcessData) == NULL) + } + if (cJSON_AddBoolToObject(mqtt, "retainprocessdata", cfgDataTemp.sectionMqtt.retainProcessData) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(mqtt, "homeassistant", mqttHomeAssistant = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(mqtt, "homeassistant", mqttHomeAssistant = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(mqttHomeAssistant, "discoveryenabled", cfgDataTemp.sectionMqtt.homeAssistant.discoveryEnabled) == NULL) + } + if (cJSON_AddBoolToObject(mqttHomeAssistant, "discoveryenabled", cfgDataTemp.sectionMqtt.homeAssistant.discoveryEnabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqttHomeAssistant, "discoveryprefix", cfgDataTemp.sectionMqtt.homeAssistant.discoveryPrefix.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqttHomeAssistant, "discoveryprefix", cfgDataTemp.sectionMqtt.homeAssistant.discoveryPrefix.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(mqttHomeAssistant, "statustopic", cfgDataTemp.sectionMqtt.homeAssistant.statusTopic.c_str()) == NULL) + } + if (cJSON_AddStringToObject(mqttHomeAssistant, "statustopic", cfgDataTemp.sectionMqtt.homeAssistant.statusTopic.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(mqttHomeAssistant, "metertype", cfgDataTemp.sectionMqtt.homeAssistant.meterType) == NULL) + } + if (cJSON_AddNumberToObject(mqttHomeAssistant, "metertype", cfgDataTemp.sectionMqtt.homeAssistant.meterType) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(mqttHomeAssistant, "retaindiscovery", cfgDataTemp.sectionMqtt.homeAssistant.retainDiscovery) == NULL) + } + if (cJSON_AddBoolToObject(mqttHomeAssistant, "retaindiscovery", cfgDataTemp.sectionMqtt.homeAssistant.retainDiscovery) == NULL) { retVal = ESP_FAIL; + } // InfluxDB v1.x // *************************** cJSON *influxdbv1, *influxdbv1Tls, *influxdbv1Sequence, *influxdbv1SequenceEl; - if (!cJSON_AddItemToObject(cJsonObject, "influxdbv1", influxdbv1 = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "influxdbv1", influxdbv1 = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(influxdbv1, "enabled", cfgDataTemp.sectionInfluxDBv1.enabled) == NULL) + } + if (cJSON_AddBoolToObject(influxdbv1, "enabled", cfgDataTemp.sectionInfluxDBv1.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1, "uri", cfgDataTemp.sectionInfluxDBv1.uri.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1, "uri", cfgDataTemp.sectionInfluxDBv1.uri.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1, "database", cfgDataTemp.sectionInfluxDBv1.database.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1, "database", cfgDataTemp.sectionInfluxDBv1.database.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(influxdbv1, "authmode", cfgDataTemp.sectionInfluxDBv1.authMode) == NULL) + } + if (cJSON_AddNumberToObject(influxdbv1, "authmode", cfgDataTemp.sectionInfluxDBv1.authMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1, "username", cfgDataTemp.sectionInfluxDBv1.username.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1, "username", cfgDataTemp.sectionInfluxDBv1.username.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1, "password", cfgDataTemp.sectionInfluxDBv1.password.empty() ? "" : "******") == NULL) + } + if (cJSON_AddStringToObject(influxdbv1, "password", cfgDataTemp.sectionInfluxDBv1.password.empty() ? "" : "******") == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(influxdbv1, "tls", influxdbv1Tls = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(influxdbv1, "tls", influxdbv1Tls = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1Tls, "cacert", cfgDataTemp.sectionInfluxDBv1.tls.caCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1Tls, "cacert", cfgDataTemp.sectionInfluxDBv1.tls.caCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1Tls, "clientcert", cfgDataTemp.sectionInfluxDBv1.tls.clientCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1Tls, "clientcert", cfgDataTemp.sectionInfluxDBv1.tls.clientCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1Tls, "clientkey", cfgDataTemp.sectionInfluxDBv1.tls.clientKey.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1Tls, "clientkey", cfgDataTemp.sectionInfluxDBv1.tls.clientKey.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(influxdbv1, "sequence", influxdbv1Sequence = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(influxdbv1, "sequence", influxdbv1Sequence = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionInfluxDBv1.sequence.size(); ++i) { cJSON_AddItemToArray(influxdbv1Sequence, influxdbv1SequenceEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(influxdbv1SequenceEl, "sequenceid", cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(influxdbv1SequenceEl, "sequenceid", cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceId) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1SequenceEl, "sequencename", cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1SequenceEl, "sequencename", cfgDataTemp.sectionInfluxDBv1.sequence[i].sequenceName.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1SequenceEl, "measurementname", cfgDataTemp.sectionInfluxDBv1.sequence[i].measurementName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1SequenceEl, "measurementname", + cfgDataTemp.sectionInfluxDBv1.sequence[i].measurementName.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv1SequenceEl, "fieldkey1", cfgDataTemp.sectionInfluxDBv1.sequence[i].fieldKey1.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv1SequenceEl, "fieldkey1", cfgDataTemp.sectionInfluxDBv1.sequence[i].fieldKey1.c_str()) == + NULL) { retVal = ESP_FAIL; + } } // InfluxDB v2.x // *************************** cJSON *influxdbv2, *influxdbv2Tls, *influxdbv2Sequence, *influxdbv2SequenceEl; - if (!cJSON_AddItemToObject(cJsonObject, "influxdbv2", influxdbv2 = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "influxdbv2", influxdbv2 = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(influxdbv2, "enabled", cfgDataTemp.sectionInfluxDBv2.enabled) == NULL) + } + if (cJSON_AddBoolToObject(influxdbv2, "enabled", cfgDataTemp.sectionInfluxDBv2.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2, "uri", cfgDataTemp.sectionInfluxDBv2.uri.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2, "uri", cfgDataTemp.sectionInfluxDBv2.uri.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2, "bucket", cfgDataTemp.sectionInfluxDBv2.bucket.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2, "bucket", cfgDataTemp.sectionInfluxDBv2.bucket.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2, "organization", cfgDataTemp.sectionInfluxDBv2.organization.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2, "organization", cfgDataTemp.sectionInfluxDBv2.organization.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(influxdbv2, "authmode", cfgDataTemp.sectionInfluxDBv2.authMode) == NULL) + } + if (cJSON_AddNumberToObject(influxdbv2, "authmode", cfgDataTemp.sectionInfluxDBv2.authMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2, "token", cfgDataTemp.sectionInfluxDBv2.token.empty() ? "" : "******") == NULL) + } + if (cJSON_AddStringToObject(influxdbv2, "token", cfgDataTemp.sectionInfluxDBv2.token.empty() ? "" : "******") == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(influxdbv2, "tls", influxdbv2Tls = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(influxdbv2, "tls", influxdbv2Tls = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2Tls, "cacert", cfgDataTemp.sectionInfluxDBv2.tls.caCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2Tls, "cacert", cfgDataTemp.sectionInfluxDBv2.tls.caCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2Tls, "clientcert", cfgDataTemp.sectionInfluxDBv2.tls.clientCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2Tls, "clientcert", cfgDataTemp.sectionInfluxDBv2.tls.clientCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2Tls, "clientkey", cfgDataTemp.sectionInfluxDBv2.tls.clientKey.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2Tls, "clientkey", cfgDataTemp.sectionInfluxDBv2.tls.clientKey.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(influxdbv2, "sequence", influxdbv2Sequence = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(influxdbv2, "sequence", influxdbv2Sequence = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionInfluxDBv2.sequence.size(); ++i) { cJSON_AddItemToArray(influxdbv2Sequence, influxdbv2SequenceEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(influxdbv2SequenceEl, "sequenceid", cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceId) == NULL) + if (cJSON_AddNumberToObject(influxdbv2SequenceEl, "sequenceid", cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceId) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2SequenceEl, "sequencename", cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2SequenceEl, "sequencename", cfgDataTemp.sectionInfluxDBv2.sequence[i].sequenceName.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2SequenceEl, "measurementname", cfgDataTemp.sectionInfluxDBv2.sequence[i].measurementName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2SequenceEl, "measurementname", + cfgDataTemp.sectionInfluxDBv2.sequence[i].measurementName.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(influxdbv2SequenceEl, "fieldkey1", cfgDataTemp.sectionInfluxDBv2.sequence[i].fieldKey1.c_str()) == NULL) + } + if (cJSON_AddStringToObject(influxdbv2SequenceEl, "fieldkey1", cfgDataTemp.sectionInfluxDBv2.sequence[i].fieldKey1.c_str()) == + NULL) { retVal = ESP_FAIL; + } } // Webhook // *************************** cJSON *webhook, *webhookTls; - if (!cJSON_AddItemToObject(cJsonObject, "webhook", webhook = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "webhook", webhook = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(webhook, "enabled", cfgDataTemp.sectionWebhook.enabled) == NULL) + } + if (cJSON_AddBoolToObject(webhook, "enabled", cfgDataTemp.sectionWebhook.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhook, "uri", cfgDataTemp.sectionWebhook.uri.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhook, "uri", cfgDataTemp.sectionWebhook.uri.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhook, "apikey", cfgDataTemp.sectionWebhook.apiKey.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhook, "apikey", cfgDataTemp.sectionWebhook.apiKey.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(webhook, "publishimage", cfgDataTemp.sectionWebhook.publishImage) == NULL) + } + if (cJSON_AddNumberToObject(webhook, "publishimage", cfgDataTemp.sectionWebhook.publishImage) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(webhook, "authmode", cfgDataTemp.sectionWebhook.authMode) == NULL) + } + if (cJSON_AddNumberToObject(webhook, "authmode", cfgDataTemp.sectionWebhook.authMode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhook, "username", cfgDataTemp.sectionWebhook.username.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhook, "username", cfgDataTemp.sectionWebhook.username.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhook, "password", cfgDataTemp.sectionWebhook.password.empty() ? "" : "******") == NULL) + } + if (cJSON_AddStringToObject(webhook, "password", cfgDataTemp.sectionWebhook.password.empty() ? "" : "******") == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(webhook, "tls", webhookTls = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(webhook, "tls", webhookTls = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhookTls, "cacert", cfgDataTemp.sectionWebhook.tls.caCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhookTls, "cacert", cfgDataTemp.sectionWebhook.tls.caCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhookTls, "clientcert", cfgDataTemp.sectionWebhook.tls.clientCert.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhookTls, "clientcert", cfgDataTemp.sectionWebhook.tls.clientCert.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(webhookTls, "clientkey", cfgDataTemp.sectionWebhook.tls.clientKey.c_str()) == NULL) + } + if (cJSON_AddStringToObject(webhookTls, "clientkey", cfgDataTemp.sectionWebhook.tls.clientKey.c_str()) == NULL) { retVal = ESP_FAIL; + } // GPIO // *************************** cJSON *gpio, *gpiopin, *gpiopinEl, *gpiopinSmartled; - if (!cJSON_AddItemToObject(cJsonObject, "gpio", gpio = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "gpio", gpio = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(gpio, "customizationenabled", cfgDataTemp.sectionGpio.customizationEnabled) == NULL) + } + if (cJSON_AddBoolToObject(gpio, "customizationenabled", cfgDataTemp.sectionGpio.customizationEnabled) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(gpio, "gpiopin", gpiopin = cJSON_CreateArray())) + } + if (!cJSON_AddItemToObject(gpio, "gpiopin", gpiopin = cJSON_CreateArray())) { retVal = ESP_FAIL; + } for (int i = 0; i < cfgDataTemp.sectionGpio.gpioPin.size(); ++i) { cJSON_AddItemToArray(gpiopin, gpiopinEl = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(gpiopinEl, "gpionumber", cfgDataTemp.sectionGpio.gpioPin[i].gpioNumber) == NULL) + if (cJSON_AddNumberToObject(gpiopinEl, "gpionumber", cfgDataTemp.sectionGpio.gpioPin[i].gpioNumber) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(gpiopinEl, "gpiousage", cfgDataTemp.sectionGpio.gpioPin[i].gpioUsage.c_str()) == NULL) + } + if (cJSON_AddStringToObject(gpiopinEl, "gpiousage", cfgDataTemp.sectionGpio.gpioPin[i].gpioUsage.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(gpiopinEl, "pinenabled", cfgDataTemp.sectionGpio.gpioPin[i].pinEnabled) == NULL) + } + if (cJSON_AddBoolToObject(gpiopinEl, "pinenabled", cfgDataTemp.sectionGpio.gpioPin[i].pinEnabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(gpiopinEl, "pinname", cfgDataTemp.sectionGpio.gpioPin[i].pinName.c_str()) == NULL) + } + if (cJSON_AddStringToObject(gpiopinEl, "pinname", cfgDataTemp.sectionGpio.gpioPin[i].pinName.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(gpiopinEl, "pinmode", cfgDataTemp.sectionGpio.gpioPin[i].pinMode.c_str()) == NULL) + } + if (cJSON_AddStringToObject(gpiopinEl, "pinmode", cfgDataTemp.sectionGpio.gpioPin[i].pinMode.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(gpiopinEl, "capturemode", cfgDataTemp.sectionGpio.gpioPin[i].captureMode.c_str()) == NULL) + } + if (cJSON_AddStringToObject(gpiopinEl, "capturemode", cfgDataTemp.sectionGpio.gpioPin[i].captureMode.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinEl, "inputdebouncetime", cfgDataTemp.sectionGpio.gpioPin[i].inputDebounceTime) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinEl, "inputdebouncetime", cfgDataTemp.sectionGpio.gpioPin[i].inputDebounceTime) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinEl, "pwmfrequency", cfgDataTemp.sectionGpio.gpioPin[i].PwmFrequency) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinEl, "pwmfrequency", cfgDataTemp.sectionGpio.gpioPin[i].PwmFrequency) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(gpiopinEl, "logicactivelow", cfgDataTemp.sectionGpio.gpioPin[i].logicActiveLow) == NULL) + } + if (cJSON_AddBoolToObject(gpiopinEl, "logicactivelow", cfgDataTemp.sectionGpio.gpioPin[i].logicActiveLow) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(gpiopinEl, "exposetomqtt", cfgDataTemp.sectionGpio.gpioPin[i].exposeToMqtt) == NULL) + } + if (cJSON_AddBoolToObject(gpiopinEl, "exposetomqtt", cfgDataTemp.sectionGpio.gpioPin[i].exposeToMqtt) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(gpiopinEl, "exposetorest", cfgDataTemp.sectionGpio.gpioPin[i].exposeToRest) == NULL) + } + if (cJSON_AddBoolToObject(gpiopinEl, "exposetorest", cfgDataTemp.sectionGpio.gpioPin[i].exposeToRest) == NULL) { retVal = ESP_FAIL; + } cJSON_AddItemToObject(gpiopinEl, "smartled", gpiopinSmartled = cJSON_CreateObject()); - if (cJSON_AddNumberToObject(gpiopinSmartled, "type", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.type) == NULL) + if (cJSON_AddNumberToObject(gpiopinSmartled, "type", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.type) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinSmartled, "quantity", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.quantity) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinSmartled, "quantity", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.quantity) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinSmartled, "colorredchannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorRedChannel) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinSmartled, "colorredchannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorRedChannel) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinSmartled, "colorgreenchannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorGreenChannel) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinSmartled, "colorgreenchannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorGreenChannel) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinSmartled, "colorbluechannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorBlueChannel) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinSmartled, "colorbluechannel", cfgDataTemp.sectionGpio.gpioPin[i].smartLed.colorBlueChannel) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(gpiopinEl, "intensitycorrectionfactor", cfgDataTemp.sectionGpio.gpioPin[i].intensityCorrectionFactor) == NULL) + } + if (cJSON_AddNumberToObject(gpiopinEl, "intensitycorrectionfactor", cfgDataTemp.sectionGpio.gpioPin[i].intensityCorrectionFactor) == + NULL) { retVal = ESP_FAIL; + } } // Logging // *************************** cJSON *log, *logDebug, *logDatda; - if (!cJSON_AddItemToObject(cJsonObject, "log", log = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "log", log = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(log, "debug", logDebug = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(log, "debug", logDebug = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(logDebug, "loglevel", cfgDataTemp.sectionLog.debug.logLevel) == NULL) + } + if (cJSON_AddNumberToObject(logDebug, "loglevel", cfgDataTemp.sectionLog.debug.logLevel) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(logDebug, "logfilesretention", cfgDataTemp.sectionLog.debug.logFilesRetention) == NULL) + } + if (cJSON_AddNumberToObject(logDebug, "logfilesretention", cfgDataTemp.sectionLog.debug.logFilesRetention) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(logDebug, "debugfilesretention", cfgDataTemp.sectionLog.debug.debugFilesRetention) == NULL) + } + if (cJSON_AddNumberToObject(logDebug, "debugfilesretention", cfgDataTemp.sectionLog.debug.debugFilesRetention) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(log, "data", logDatda = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(log, "data", logDatda = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(logDatda, "enabled", cfgDataTemp.sectionLog.data.enabled) == NULL) + } + if (cJSON_AddBoolToObject(logDatda, "enabled", cfgDataTemp.sectionLog.data.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(logDatda, "datafilesretention", cfgDataTemp.sectionLog.data.dataFilesRetention) == NULL) + } + if (cJSON_AddNumberToObject(logDatda, "datafilesretention", cfgDataTemp.sectionLog.data.dataFilesRetention) == NULL) { retVal = ESP_FAIL; + } // Network // *************************** cJSON *network, *networkWlan, *networkIpv4, *networkWlanRoaming, *networkWlanAp, *networkApIpv4, *networkTime, *networkTimeNtp; - if (!cJSON_AddItemToObject(cJsonObject, "network", network = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "network", network = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(network, "opmode", cfgDataTemp.sectionNetwork.opmode) == NULL) + } + if (cJSON_AddNumberToObject(network, "opmode", cfgDataTemp.sectionNetwork.opmode) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(network, "timedoffdelay", cfgDataTemp.sectionNetwork.timedOffDelay) == NULL) + } + if (cJSON_AddNumberToObject(network, "timedoffdelay", cfgDataTemp.sectionNetwork.timedOffDelay) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(network, "wlan", networkWlan = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(network, "wlan", networkWlan = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkWlan, "ssid", cfgDataTemp.sectionNetwork.wlan.ssid.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkWlan, "ssid", cfgDataTemp.sectionNetwork.wlan.ssid.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkWlan, "password", cfgDataTemp.sectionNetwork.wlan.password.empty() ? "" : "******") == NULL) + } + if (cJSON_AddStringToObject(networkWlan, "password", cfgDataTemp.sectionNetwork.wlan.password.empty() ? "" : "******") == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkWlan, "hostname", cfgDataTemp.sectionNetwork.wlan.hostname.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkWlan, "hostname", cfgDataTemp.sectionNetwork.wlan.hostname.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(networkWlan, "ipv4", networkIpv4 = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(networkWlan, "ipv4", networkIpv4 = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(networkIpv4, "networkconfig", cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig) == NULL) + } + if (cJSON_AddNumberToObject(networkIpv4, "networkconfig", cfgDataTemp.sectionNetwork.wlan.ipv4.networkConfig) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkIpv4, "ipaddress", cfgDataTemp.sectionNetwork.wlan.ipv4.ipAddress.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkIpv4, "ipaddress", cfgDataTemp.sectionNetwork.wlan.ipv4.ipAddress.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkIpv4, "subnetmask", cfgDataTemp.sectionNetwork.wlan.ipv4.subnetMask.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkIpv4, "subnetmask", cfgDataTemp.sectionNetwork.wlan.ipv4.subnetMask.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkIpv4, "gatewayaddress", cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkIpv4, "gatewayaddress", cfgDataTemp.sectionNetwork.wlan.ipv4.gatewayAddress.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkIpv4, "dnsserver", cfgDataTemp.sectionNetwork.wlan.ipv4.dnsServer.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkIpv4, "dnsserver", cfgDataTemp.sectionNetwork.wlan.ipv4.dnsServer.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(networkWlan, "wlanroaming", networkWlanRoaming = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(networkWlan, "wlanroaming", networkWlanRoaming = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(networkWlanRoaming, "enabled", cfgDataTemp.sectionNetwork.wlan.wlanRoaming.enabled) == NULL) + } + if (cJSON_AddBoolToObject(networkWlanRoaming, "enabled", cfgDataTemp.sectionNetwork.wlan.wlanRoaming.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(networkWlanRoaming, "rssithreshold", cfgDataTemp.sectionNetwork.wlan.wlanRoaming.rssiThreshold) == NULL) + } + if (cJSON_AddNumberToObject(networkWlanRoaming, "rssithreshold", cfgDataTemp.sectionNetwork.wlan.wlanRoaming.rssiThreshold) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(network, "wlanap", networkWlanAp = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(network, "wlanap", networkWlanAp = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkWlanAp, "ssid", cfgDataTemp.sectionNetwork.wlanAp.ssid.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkWlanAp, "ssid", cfgDataTemp.sectionNetwork.wlanAp.ssid.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkWlanAp, "password", cfgDataTemp.sectionNetwork.wlanAp.password.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkWlanAp, "password", cfgDataTemp.sectionNetwork.wlanAp.password.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(networkWlanAp, "channel", cfgDataTemp.sectionNetwork.wlanAp.channel) == NULL) + } + if (cJSON_AddNumberToObject(networkWlanAp, "channel", cfgDataTemp.sectionNetwork.wlanAp.channel) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(networkWlanAp, "ipv4", networkApIpv4 = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(networkWlanAp, "ipv4", networkApIpv4 = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkApIpv4, "ipaddress", cfgDataTemp.sectionNetwork.wlanAp.ipv4.ipAddress.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkApIpv4, "ipaddress", cfgDataTemp.sectionNetwork.wlanAp.ipv4.ipAddress.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(network, "time", networkTime = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(network, "time", networkTime = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkTime, "timezone", cfgDataTemp.sectionNetwork.time.timeZone.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkTime, "timezone", cfgDataTemp.sectionNetwork.time.timeZone.c_str()) == NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(networkTime, "ntp", networkTimeNtp = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(networkTime, "ntp", networkTimeNtp = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(networkTimeNtp, "timesyncenabled", cfgDataTemp.sectionNetwork.time.ntp.timeSyncEnabled) == NULL) + } + if (cJSON_AddBoolToObject(networkTimeNtp, "timesyncenabled", cfgDataTemp.sectionNetwork.time.ntp.timeSyncEnabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(networkTimeNtp, "timeserver", cfgDataTemp.sectionNetwork.time.ntp.timeServer.c_str()) == NULL) + } + if (cJSON_AddStringToObject(networkTimeNtp, "timeserver", cfgDataTemp.sectionNetwork.time.ntp.timeServer.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(networkTimeNtp, "processstartinterlock", cfgDataTemp.sectionNetwork.time.ntp.processStartInterlock) == NULL) + } + if (cJSON_AddBoolToObject(networkTimeNtp, "processstartinterlock", cfgDataTemp.sectionNetwork.time.ntp.processStartInterlock) == NULL) { retVal = ESP_FAIL; + } // System // *************************** cJSON *system; - if (!cJSON_AddItemToObject(cJsonObject, "system", system = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "system", system = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(system, "cpufrequency", cfgDataTemp.sectionSystem.cpuFrequency) == NULL) + } + if (cJSON_AddNumberToObject(system, "cpufrequency", cfgDataTemp.sectionSystem.cpuFrequency) == NULL) { retVal = ESP_FAIL; + } // WebUI // *************************** cJSON *webui, *webuiAutorefresh, *webuiAutorefreshOverview, *webuiAutorefreshDataGraph; - if (!cJSON_AddItemToObject(cJsonObject, "webui", webui = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJsonObject, "webui", webui = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(webui, "autorefresh", webuiAutorefresh = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(webui, "autorefresh", webuiAutorefresh = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(webuiAutorefresh, "overviewpage", webuiAutorefreshOverview = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(webuiAutorefresh, "overviewpage", webuiAutorefreshOverview = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(webuiAutorefreshOverview, "enabled", cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.enabled) == NULL) + } + if (cJSON_AddBoolToObject(webuiAutorefreshOverview, "enabled", cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(webuiAutorefreshOverview, "refreshtime", cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.refreshTime) == NULL) + } + if (cJSON_AddNumberToObject(webuiAutorefreshOverview, "refreshtime", cfgDataTemp.sectionWebUi.AutoRefresh.overviewPage.refreshTime) == + NULL) { retVal = ESP_FAIL; - if (!cJSON_AddItemToObject(webuiAutorefresh, "datagraphpage", webuiAutorefreshDataGraph = cJSON_CreateObject())) + } + if (!cJSON_AddItemToObject(webuiAutorefresh, "datagraphpage", webuiAutorefreshDataGraph = cJSON_CreateObject())) { retVal = ESP_FAIL; - if (cJSON_AddBoolToObject(webuiAutorefreshDataGraph, "enabled", cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.enabled) == NULL) + } + if (cJSON_AddBoolToObject(webuiAutorefreshDataGraph, "enabled", cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.enabled) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(webuiAutorefreshDataGraph, "refreshtime", cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.refreshTime) == NULL) + } + if (cJSON_AddNumberToObject(webuiAutorefreshDataGraph, "refreshtime", cfgDataTemp.sectionWebUi.AutoRefresh.dataGraphPage.refreshTime) == + NULL) { retVal = ESP_FAIL; + } cJSON_InitHooks(NULL); // Reset cJSON hooks to default portEXIT_CRITICAL(&mutex); jsonBuffer[0] = '\0'; // Reset content // Print to preallocted buffer - if (!cJSON_PrintPreallocated(cJsonObject, jsonBuffer, CONFIG_HANDLING_PREALLOCATED_BUFFER_SIZE, unityTest ? 0 : 1)) + if (!cJSON_PrintPreallocated(cJsonObject, jsonBuffer, CONFIG_HANDLING_PREALLOCATED_BUFFER_SIZE, unityTest ? 0 : 1)) { retVal = ESP_FAIL; + } return retVal; } @@ -2149,7 +2563,7 @@ bool ConfigClass::loadDataFromNVS(std::string key, std::string &value) } if (requiredSize > 0) { - char cValue[requiredSize+1]; + char cValue[requiredSize + 1]; err = nvs_get_str(nvshandle, key.c_str(), cValue, &requiredSize); if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "loadDataFromNVS: nvs_get_str | Key: " + key + " | error: " + intToHexString(err)); @@ -2199,41 +2613,47 @@ bool ConfigClass::saveDataToNVS(std::string key, std::string value) } -void ConfigClass::validatePath(std::string& path, bool withFile) +void ConfigClass::validatePath(std::string &path, bool withFile) { - if (path.empty()) - return; + if (path.empty()) { + return; + } - // Replace backslashes - std::replace(path.begin(), path.end(), '\\', '/'); + // Replace backslashes + std::replace(path.begin(), path.end(), '\\', '/'); - if (!withFile) { - // Remove slash or backslash at the end of the string - if(path.back() == '/') - path.pop_back(); - } + if (!withFile) { + // Remove slash or backslash at the end of the string + if (path.back() == '/') { + path.pop_back(); + } + } - // Add slash at the beginning - if(path[0] != '/') - path = "/" + path; + // Add slash at the beginning + if (path[0] != '/') { + path = "/" + path; + } } -void ConfigClass::validateStructure(std::string& structureName) +void ConfigClass::validateStructure(std::string &structureName) { - if (structureName.empty()) - return; + if (structureName.empty()) { + return; + } - // Replace backslashes - std::replace(structureName.begin(), structureName.end(), '\\', '/'); + // Replace backslashes + std::replace(structureName.begin(), structureName.end(), '\\', '/'); - // Remove slash at the begin of the string - if(structureName[0] == '/') - structureName.erase(structureName.begin()); + // Remove slash at the begin of the string + if (structureName[0] == '/') { + structureName.erase(structureName.begin()); + } - // Remove slash at the end of the string - if(structureName.back() == '/') - structureName.pop_back(); + // Remove slash at the end of the string + if (structureName.back() == '/') { + structureName.pop_back(); + } } diff --git a/code/components/config_handling/configClass.h b/code/components/config_handling/configClass.h index da45e7784..f6bc43815 100644 --- a/code/components/config_handling/configClass.h +++ b/code/components/config_handling/configClass.h @@ -14,18 +14,19 @@ /* Function calls -* 1. Restore Config : readConfigFile() > parseConfig > serializeConfig > writeConfigFile -* 2. REST API Set : setConfigRequest() > parseConfig > serializeConfig > REST API Response -* 3. REST API Get : getConfigRequest() > serializeConfig > REST API Response -* 4. Cfg Migration : readConfigFile() > parseConfig > migrateConfiguration() > serializeConfig > writeConfigFile -*/ + * 1. Restore Config : readConfigFile() > parseConfig > serializeConfig > writeConfigFile + * 2. REST API Set : setConfigRequest() > parseConfig > serializeConfig > REST API Response + * 3. REST API Get : getConfigRequest() > serializeConfig > REST API Response + * 4. Cfg Migration : readConfigFile() > parseConfig > migrateConfiguration() > serializeConfig > writeConfigFile + */ class ConfigClass { private: static ConfigClass cfgClass; // Config class init here instead of global variable + extern declaration - CfgData cfgDataTemp; // Keeps last parameter modifications, but not in yet used by process (gets promoted to active config by reinitConfig()) - CfgData cfgData; // Keep parameter configuration (in use by process) + CfgData cfgDataTemp; // Keeps last parameter modifications, but not in yet used by process (gets promoted to active config by + // reinitConfig()) + CfgData cfgData; // Keep parameter configuration (in use by process) portMUX_TYPE mutex = portMUX_INITIALIZER_UNLOCKED; cJSON *cJsonObject = NULL; @@ -40,8 +41,8 @@ class ConfigClass bool loadDataFromNVS(std::string key, std::string &value); bool saveDataToNVS(std::string key, std::string value); - void validatePath(std::string& path, bool withFile = false); - void validateStructure(std::string& structureName); + void validatePath(std::string &path, bool withFile = false); + void validateStructure(std::string &structureName); public: ConfigClass(); @@ -52,7 +53,11 @@ class ConfigClass void readConfigFile(bool unityTest = false, std::string unityTestData = "{}"); void reinitConfig(void) { cfgData = cfgDataTemp; }; - void persistConfig(void) { serializeConfig(); writeConfigFile(); }; + void persistConfig(void) + { + serializeConfig(); + writeConfigFile(); + }; static ConfigClass *getInstance(void) { return &cfgClass; } const CfgData *get(void) const { return &cfgData; }; @@ -61,7 +66,11 @@ class ConfigClass esp_err_t setConfigRequest(httpd_req_t *req); // Only for migration and internal parameter modification purpose - void initCfgTmp(void) { clearCfgDataTemp(); cfgDataTemp = {}; }; + void initCfgTmp(void) + { + clearCfgDataTemp(); + cfgDataTemp = {}; + }; CfgData *cfgTmp(void) { return &cfgDataTemp; }; bool saveMigDataToNVS(std::string key, std::string value) { return saveDataToNVS(key, value); }; @@ -72,4 +81,4 @@ class ConfigClass void registerConfigFileUri(httpd_handle_t server); -#endif // CONFIGCLASS_H \ No newline at end of file +#endif // CONFIGCLASS_H diff --git a/code/components/config_handling/configMigration.cpp b/code/components/config_handling/configMigration.cpp index 13f9eac75..18737ae18 100644 --- a/code/components/config_handling/configMigration.cpp +++ b/code/components/config_handling/configMigration.cpp @@ -17,7 +17,7 @@ static const char *TAG = "CFGMIG"; // Migrate config based on JSON notation // Firmware version: v17.0 and newer, Config version 3 and newer // ******************************************************************************** -void migrateConfiguration(cJSON* cJsonObject) +void migrateConfiguration(cJSON *cJsonObject) { uint16_t migratedVersion = 0; @@ -32,20 +32,21 @@ void migrateConfiguration(cJSON* cJsonObject) migratedVersion = ConfigClass::getInstance()->cfgTmp()->sectionConfig.version; ConfigClass::getInstance()->cfgTmp()->sectionConfig.version += 1; ConfigClass::getInstance()->cfgTmp()->sectionConfig.lastModified = ""; // Reset last modified - LogFile.writeToFile(ESP_LOG_WARN, TAG, "cfgData: Migrate v" + std::to_string(migratedVersion) + - " > v" + std::to_string(ConfigClass::getInstance()->cfgTmp()->sectionConfig.version)); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "cfgData: Migrate v" + std::to_string(migratedVersion) + " > v" + + std::to_string(ConfigClass::getInstance()->cfgTmp()->sectionConfig.version)); // Update parameter // --------------------- const cJSON *objEl = cJSON_GetObjectItem(cJSON_GetObjectItem(cJSON_GetObjectItem(cJsonObject, "takeimage"), "camera"), "zoommode"); if (cJSON_IsNumber(objEl)) { - if (objEl->valueint == 0) { // Disabled + if (objEl->valueint == 0) { // Disabled ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.zoomFactor = 1000; // 1.0x } - else if (objEl->valueint == 1) { // Crop (1600 x 1200 -> 640 x 480) + else if (objEl->valueint == 1) { // Crop (1600 x 1200 -> 640 x 480) ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.zoomFactor = 2500; // 2.5x } - else if (objEl->valueint == 2) { // Scale & Crop (800 x 600 -> 640 x 480) + else if (objEl->valueint == 2) { // Scale & Crop (800 x 600 -> 640 x 480) ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.zoomFactor = 1250; // 1.25x } } @@ -77,7 +78,7 @@ void migrateConfigIni(void) return; } - const std::string sectionConfigFile= "[ConfigFile]"; + const std::string sectionConfigFile = "[ConfigFile]"; bool configSectionFound = false; int actualConfigFileVersion = 0; @@ -96,7 +97,7 @@ void migrateConfigIni(void) if (configLines[i] == sectionConfigFile) { configSectionFound = true; - std::vector splitted = splitString(configLines[i+1]); + std::vector splitted = splitString(configLines[i + 1]); if (toUpper(splitted[0]) == "VERSION") { actualConfigFileVersion = std::stoi(splitted[1]); } @@ -106,16 +107,16 @@ void migrateConfigIni(void) // If no [Config] section is available, add section and set config version to zero if (!configSectionFound) { - configLines.insert(configLines.begin(), ""); // 3rd line - configLines.insert(configLines.begin(), "Version = 0"); //2nd line - configLines.insert(configLines.begin(), sectionConfigFile); // 1st line + configLines.insert(configLines.begin(), ""); // 3rd line + configLines.insert(configLines.begin(), "Version = 0"); // 2nd line + configLines.insert(configLines.begin(), sectionConfigFile); // 1st line migrated = true; } // Process every version iteration beginning from actual version // Up to version 2 config handled in config.ini. // Newer version of config is handled in cfgData struct and config.json (only persistence) - for (int configFileVersion = actualConfigFileVersion; configFileVersion < 3; configFileVersion++) { + for (int configFileVersion = actualConfigFileVersion; configFileVersion < 3; configFileVersion++) { // Process each line of config for (int i = 0; i < configLines.size(); i++) { if (configLines[i].find("[") != std::string::npos) { // Detect start of new section @@ -125,7 +126,7 @@ void migrateConfigIni(void) } } - //************************************************************************************************* + //************************************************************************************************* // Migrate from version 2 to version 3 // Date: October 2024 // Description: Migrate config.ini to internal struct which gets persistant to config.json @@ -137,8 +138,9 @@ void migrateConfigIni(void) // Update config version // --------------------- ConfigClass::getInstance()->cfgTmp()->sectionConfig.version = configFileVersion + 1; - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Config.ini: Migrate v" + std::to_string(configFileVersion) + - " > v" + std::to_string(configFileVersion+1) + " => Config will be handled in firmware + config.json"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Config.ini: Migrate v" + std::to_string(configFileVersion) + " > v" + + std::to_string(configFileVersion + 1) + " => Config will be handled in firmware + config.json"); // Remove unused files deleteFile("/sdcard/bootloader.bin"); @@ -170,24 +172,30 @@ void migrateConfigIni(void) i += 2; // Skip lines } else if (section == "[TakeImage]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } - if ((toUpper(splitted[0]) == "RAWIMAGESLOCATION" || toUpper(splitted[0]) == ";RAWIMAGESLOCATION") && (splitted[0].size() > 1)) { + if ((toUpper(splitted[0]) == "RAWIMAGESLOCATION" || toUpper(splitted[0]) == ";RAWIMAGESLOCATION") && + (splitted[0].size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.debug.rawImagesLocation = splitted[1]; - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.debug.saveRawImages = true; + } } - else if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION" || toUpper(splitted[0]) == ";RAWIMAGESRETENTION") && (splitted.size() > 1)) { + else if ((toUpper(splitted[0]) == "RAWIMAGESRETENTION" || toUpper(splitted[0]) == ";RAWIMAGESRETENTION") && + (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.debug.rawImagesRetention = std::stoi(splitted[1]); } else if ((toUpper(splitted[0]) == "FLASHTIME") && (splitted.size() > 1)) { - ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.flashlight.flashTime = (int)(stof(splitted[1])*1000); // Flashtime in ms + ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.flashlight.flashTime = (int)(stof(splitted[1]) * + 1000); // Flashtime in ms } else if ((toUpper(splitted[0]) == "FLASHINTENSITY") && (splitted.size() > 1)) { - ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.flashlight.flashIntensity = std::max(0, std::min(std::stoi(splitted[1]), 100)); + ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.flashlight.flashIntensity = + std::max(0, std::min(std::stoi(splitted[1]), 100)); } else if ((toUpper(splitted[0]) == "CAMERAFREQUENCY") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.cameraFrequency = std::stoi(splitted[1]); @@ -232,10 +240,10 @@ void migrateConfigIni(void) ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.flipImage = (toUpper(splitted[1]) == "TRUE"); } else if ((toUpper(splitted[0]) == "ZOOMMODE") && (splitted.size() > 1)) { - if (std::stoi(splitted[1]) == 0) { // Disabled + if (std::stoi(splitted[1]) == 0) { // Disabled ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.zoomFactor = 1000; // 1.0x } - else if (std::stoi(splitted[1]) == 1) { // Crop from 1600 x 1200 + else if (std::stoi(splitted[1]) == 1) { // Crop from 1600 x 1200 ConfigClass::getInstance()->cfgTmp()->sectionTakeImage.camera.zoomFactor = 2500; // 2.5x } else if (std::stoi(splitted[1]) == 2) { // Scale and crop from 800 x 600 @@ -256,23 +264,29 @@ void migrateConfigIni(void) } } else if (section == "[Alignment]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } static int idx = 0; if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1)) { - if (toUpper(splitted[1]) == "HIGHACCURACY") + if (toUpper(splitted[1]) == "HIGHACCURACY") { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.alignmentAlgo = ALIGNALGO_HIGH_ACCURACY; - else if (toUpper(splitted[1]) == "FAST") + } + else if (toUpper(splitted[1]) == "FAST") { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.alignmentAlgo = ALIGNALGO_FAST; - else if (toUpper(splitted[1]) == "ROTATION") + } + else if (toUpper(splitted[1]) == "ROTATION") { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.alignmentAlgo = ALIGNALGO_ROTATION_ONLY; - else if (toUpper(splitted[1]) == "OFF") + } + else if (toUpper(splitted[1]) == "OFF") { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.alignmentAlgo = ALIGNALGO_OFF; - else + } + else { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.alignmentAlgo = ALIGNALGO_DEFAULT; + } } else if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionImageAlignment.searchField.x = std::stoi(splitted[1]); @@ -298,10 +312,11 @@ void migrateConfigIni(void) else if (section == "[Digits]" || section == ";[Digits]") { ConfigClass::getInstance()->cfgTmp()->sectionDigit.enabled = !section.starts_with(";"); - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "MODEL") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionDigit.model = splitted[1].substr(8, std::string::npos); @@ -309,16 +324,19 @@ void migrateConfigIni(void) else if ((toUpper(splitted[0]) == "CNNGOODTHRESHOLD") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionDigit.cnnGoodThreshold = std::stof(splitted[1]); } - else if ((toUpper(splitted[0]) == "ROIIMAGESLOCATION" || (toUpper(splitted[0]) == ";ROIIMAGESLOCATION")) && (splitted.size() > 1)) { + else if ((toUpper(splitted[0]) == "ROIIMAGESLOCATION" || (toUpper(splitted[0]) == ";ROIIMAGESLOCATION")) && + (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionDigit.debug.roiImagesLocation = splitted[1]; - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionDigit.debug.saveRoiImages = true; + } } - else if ((toUpper(splitted[0]) == "ROIIMAGESRETENTION" || (toUpper(splitted[0]) == ";ROIIMAGESRETENTION")) && (splitted.size() > 1)) { + else if ((toUpper(splitted[0]) == "ROIIMAGESRETENTION" || (toUpper(splitted[0]) == ";ROIIMAGESRETENTION")) && + (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionDigit.debug.roiImagesRetention = std::stoi(splitted[1]); } else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1)) { - ConfigClass::getInstance()->cfgTmp()->sectionDigit.debug.saveAllFiles = (toUpper(splitted[1]) == "TRUE"); + ConfigClass::getInstance()->cfgTmp()->sectionDigit.debug.saveAllFiles = (toUpper(splitted[1]) == "TRUE"); } else if (splitted.size() >= 5) { RoiElement roiEl; @@ -367,24 +385,27 @@ void migrateConfigIni(void) else if (section == "[Analog]" || section == ";[Analog]") { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.enabled = !section.starts_with(";"); - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "MODEL") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.model = splitted[1].substr(8, std::string::npos); } - else if ((toUpper(splitted[0]) == "ROIIMAGESLOCATION" || (toUpper(splitted[0]) == ";ROIIMAGESLOCATION")) && (splitted.size() > 1)) { + else if ((toUpper(splitted[0]) == "ROIIMAGESLOCATION" || (toUpper(splitted[0]) == ";ROIIMAGESLOCATION")) && + (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.debug.roiImagesLocation = splitted[1]; - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.debug.saveRoiImages = true; + } } - else if ((toUpper(splitted[0]) == "ROIIMAGESRETENTION" || (toUpper(splitted[0]) == ";ROIIMAGESRETENTION")) && (splitted.size() > 1)) { + else if ((toUpper(splitted[0]) == "ROIIMAGESRETENTION" || (toUpper(splitted[0]) == ";ROIIMAGESRETENTION")) && + (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.debug.roiImagesRetention = std::stoi(splitted[1]); } - else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1)) - { + else if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionAnalog.debug.saveAllFiles = (toUpper(splitted[1]) == "TRUE"); } else if (splitted.size() >= 5) { @@ -404,10 +425,11 @@ void migrateConfigIni(void) } } else if (section == "[PostProcessing]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } // Global parameter used for all sequences and now they are parameter per sequence if (toUpper(splitted[0]) == "FALLBACKVALUEUSE" && (splitted.size() > 1)) { @@ -422,12 +444,12 @@ void migrateConfigIni(void) } else if (toUpper(splitted[0]) == "CHECKDIGITINCREASECONSISTENCY" && (splitted.size() > 1)) { for (auto &seqEl : ConfigClass::getInstance()->cfgTmp()->sectionPostProcessing.sequence) { - seqEl.checkDigitIncreaseConsistency = (toUpper(splitted[1]) == "TRUE"); + seqEl.checkDigitIncreaseConsistency = (toUpper(splitted[1]) == "TRUE"); } } // Parameter per sequence else if (splitted[0].find_first_of(".") != std::string::npos) { - std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".")+1)); + std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".") + 1)); for (auto &seqEl : ConfigClass::getInstance()->cfgTmp()->sectionPostProcessing.sequence) { if (seqEl.sequenceName == toLower(splitted[0].substr(0, splitted[0].find_first_of(".")))) { @@ -474,10 +496,11 @@ void migrateConfigIni(void) else if (section == "[MQTT]" || section == ";[MQTT]") { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.enabled = !section.starts_with(";"); - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.uri = @@ -491,8 +514,9 @@ void migrateConfigIni(void) } else if ((toUpper(splitted[0]) == "USER" || toUpper(splitted[0]) == ";USER") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.username = (splitted[1] == "undefined" ? "" : splitted[1]); - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.authMode = AUTH_BASIC; + } } else if ((toUpper(splitted[0]) == "PASSWORD" || toUpper(splitted[0]) == ";PASSWORD") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.password = (splitted[1] == "undefined" ? "" : splitted[1]); @@ -503,20 +527,21 @@ void migrateConfigIni(void) } } else if ((toUpper(splitted[0]) == "TLSENCRYPTION") && (splitted.size() > 1)) { - if (toUpper(splitted[1]) == "TRUE") + if (toUpper(splitted[1]) == "TRUE") { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.authMode = AUTH_TLS; + } } else if ((toUpper(splitted[0]) == "TLSCACERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.tls.caCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTCERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.tls.clientCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTKEY") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.tls.clientKey = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "RETAINPROCESSDATA") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionMqtt.retainProcessData = (toUpper(splitted[1]) == "TRUE"); @@ -575,10 +600,11 @@ void migrateConfigIni(void) else if (section == "[InfluxDB]" || section == ";[InfluxDB]") { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.enabled = !section.starts_with(";"); - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.uri = @@ -589,12 +615,14 @@ void migrateConfigIni(void) } else if ((toUpper(splitted[0]) == "USER" || toUpper(splitted[0]) == ";USER") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.username = (splitted[1] == "undefined" ? "" : splitted[1]); - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.authMode = AUTH_BASIC; + } } else if ((toUpper(splitted[0]) == "PASSWORD" || toUpper(splitted[0]) == ";PASSWORD") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.password = (splitted[1] == "undefined" ? "" : splitted[1]); - ConfigClass::getInstance()->saveMigDataToNVS("influxdbv1_pw", ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.password); + ConfigClass::getInstance()->saveMigDataToNVS("influxdbv1_pw", + ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.password); if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.authMode = AUTH_BASIC; @@ -607,18 +635,18 @@ void migrateConfigIni(void) } else if ((toUpper(splitted[0]) == "TLSCACERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.tls.caCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTCERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.tls.clientCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTKEY") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.tls.clientKey = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if (splitted[0].find_first_of(".") != std::string::npos) { - std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".")+1)); + std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".") + 1)); for (auto &seqEl : ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv1.sequence) { if (seqEl.sequenceName == toLower(splitted[0].substr(0, splitted[0].find_first_of(".")))) { @@ -636,10 +664,11 @@ void migrateConfigIni(void) else if (section == "[InfluxDBv2]" || section == ";[InfluxDBv2]") { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.enabled = !section.starts_with(";"); - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.uri = @@ -649,11 +678,13 @@ void migrateConfigIni(void) ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.bucket = (splitted[1] == "undefined" ? "" : splitted[1]); } else if ((toUpper(splitted[0]) == "ORG" || (toUpper(splitted[0]) == ";ORG")) && (splitted.size() > 1)) { - ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.organization = (splitted[1] == "undefined" ? "" : splitted[1]); + ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.organization = (splitted[1] == "undefined" ? "" + : splitted[1]); } else if ((toUpper(splitted[0]) == "TOKEN" || (toUpper(splitted[0]) == ";TOKEN")) && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.token = (splitted[1] == "undefined" ? "" : splitted[1]); - ConfigClass::getInstance()->saveMigDataToNVS("influxdbv2_pw", ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.token); + ConfigClass::getInstance()->saveMigDataToNVS("influxdbv2_pw", + ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.token); } else if ((toUpper(splitted[0]) == "TLSENCRYPTION") && (splitted.size() > 1)) { if (toUpper(splitted[1]) == "TRUE") { @@ -662,18 +693,18 @@ void migrateConfigIni(void) } else if ((toUpper(splitted[0]) == "TLSCACERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.tls.caCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTCERT") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.tls.clientCert = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if ((toUpper(splitted[0]) == "TLSCLIENTKEY") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.tls.clientKey = - (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/")+1)); + (splitted[1] == "undefined" ? "" : splitted[1].substr(splitted[1].find_last_of("/") + 1)); } else if (splitted[0].find_first_of(".") != std::string::npos) { - std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".")+1)); + std::string parameter = toUpper(splitted[0].substr(splitted[0].find_first_of(".") + 1)); for (auto &seqEl : ConfigClass::getInstance()->cfgTmp()->sectionInfluxDBv2.sequence) { if (seqEl.sequenceName == toLower(splitted[0].substr(0, splitted[0].find_first_of(".")))) { @@ -688,30 +719,34 @@ void migrateConfigIni(void) } } } - else if (section == "[GPIO]" || section == ";[GPIO]" ) { + else if (section == "[GPIO]" || section == ";[GPIO]") { // GPIO config migration is not implemented (depends on hardware) --> Needs to be configured from scratch } else if (section == "[AutoTimer]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "AUTOSTART") && (splitted.size() > 1)) { - if (toUpper(splitted[1]) == "TRUE") + if (toUpper(splitted[1]) == "TRUE") { ConfigClass::getInstance()->cfgTmp()->sectionOperationMode.opMode = OPMODE_AUTO; - else + } + else { ConfigClass::getInstance()->cfgTmp()->sectionOperationMode.opMode = OPMODE_MANUAL; + } } else if ((toUpper(splitted[0]) == "INTERVAL") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionOperationMode.automaticProcessInterval = std::stof(splitted[1]); } } else if (section == "[DataLogging]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "DATALOGACTIVE") && (splitted.size() > 1)) { ConfigClass::getInstance()->cfgTmp()->sectionLog.data.enabled = (toUpper(splitted[1]) == "TRUE"); @@ -721,10 +756,11 @@ void migrateConfigIni(void) } } else if (section == "[Debug]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "LOGLEVEL") && (splitted.size() > 1)) { if ((toUpper(splitted[1]) == "TRUE") || (toUpper(splitted[1]) == "2")) { @@ -751,10 +787,11 @@ void migrateConfigIni(void) } } else if (section == "[System]") { - splitted = splitString(configLines[i+1]); + splitted = splitString(configLines[i + 1]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if ((toUpper(splitted[0]) == "TIMESERVER") || (toUpper(splitted[0]) == ";TIMESERVER")) { ConfigClass::getInstance()->cfgTmp()->sectionNetwork.time.ntp.timeServer = splitted[1]; @@ -766,8 +803,9 @@ void migrateConfigIni(void) ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.hostname = splitted[1]; } else if ((toUpper(splitted[0]) == "RSSITHRESHOLD") || (toUpper(splitted[0]) == ";RSSITHRESHOLD")) { - if (!splitted[0].starts_with(";")) + if (!splitted[0].starts_with(";")) { ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.wlanRoaming.enabled = true; + } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.wlanRoaming.rssiThreshold = atoi(splitted[1].c_str()); } @@ -783,30 +821,34 @@ void migrateConfigIni(void) else if (section == "[WebUI]") { splitted = splitString(configLines[i]); - if (splitted[0] == "") // Skip empty lines + if (splitted[0] == "") { // Skip empty lines continue; + } if (toUpper(splitted[0]) == "OVERVIEWAUTOREFRESH") { - ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.overviewPage.enabled = (toUpper(splitted[1]) == "TRUE"); + ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.overviewPage.enabled = (toUpper(splitted[1]) == + "TRUE"); } else if (toUpper(splitted[0]) == "OVERVIEWAUTOREFRESHTIME") { ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.overviewPage.refreshTime = atoi(splitted[1].c_str()); } else if (toUpper(splitted[0]) == "DATAGRAPHAUTOREFRESH") { - ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.dataGraphPage.enabled = (toUpper(splitted[1]) == "TRUE"); + ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.dataGraphPage.enabled = (toUpper(splitted[1]) == + "TRUE"); } else if (toUpper(splitted[0]) == "DATAGRAPHAUTOREFRESHTIME") { - ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.dataGraphPage.refreshTime = atoi(splitted[1].c_str()); + ConfigClass::getInstance()->cfgTmp()->sectionWebUi.AutoRefresh.dataGraphPage.refreshTime = + atoi(splitted[1].c_str()); } } } /* Notes: - * The migration has some simplifications: - * - Case sensitiveness must be like in the config.ini - * - No whitespace after a semicollon - * - Only one whitespace before/after the equal sign - */ + * The migration has some simplifications: + * - Case sensitiveness must be like in the config.ini + * - No whitespace after a semicollon + * - Only one whitespace before/after the equal sign + */ //************************************************************************************************* // Migrate from version 1 to version 2 @@ -816,10 +858,11 @@ void migrateConfigIni(void) // Update config version // --------------------- if (section == sectionConfigFile) { - if(replaceString(configLines[i], "Version = " + std::to_string(configFileVersion), - "Version = " + std::to_string(configFileVersion+1))) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Config.ini: Migrate v" + std::to_string(configFileVersion) + - " > v" + std::to_string(configFileVersion+1)); + if (replaceString(configLines[i], "Version = " + std::to_string(configFileVersion), + "Version = " + std::to_string(configFileVersion + 1))) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Config.ini: Migrate v" + std::to_string(configFileVersion) + " > v" + + std::to_string(configFileVersion + 1)); migrated = true; } } @@ -830,7 +873,7 @@ void migrateConfigIni(void) // Erase complete section content due to major change in parameter usage // Section will be filled again by WebUI after save config initially if (configLines[i].find("[GPIO]") == std::string::npos && !configLines[i].empty()) { - configLines.erase(configLines.begin()+i); + configLines.erase(configLines.begin() + i); i--; // One element removed, check same position again } } @@ -844,10 +887,11 @@ void migrateConfigIni(void) // Update config version // --------------------- if (section == sectionConfigFile) { - if(replaceString(configLines[i], "Version = " + std::to_string(configFileVersion), - "Version = " + std::to_string(configFileVersion+1))) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Config.ini: Migrate v" + std::to_string(configFileVersion) + - " > v" + std::to_string(configFileVersion+1)); + if (replaceString(configLines[i], "Version = " + std::to_string(configFileVersion), + "Version = " + std::to_string(configFileVersion + 1))) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Config.ini: Migrate v" + std::to_string(configFileVersion) + " > v" + + std::to_string(configFileVersion + 1)); migrated = true; } } @@ -863,24 +907,27 @@ void migrateConfigIni(void) migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "RawImagesRetention"); migrated = migrated | replaceString(configLines[i], "WaitBeforeTakingPicture", "FlashTime"); // Rename - migrated = migrated | replaceString(configLines[i], "LEDIntensity", "FlashIntensity"); // Rename + migrated = migrated | replaceString(configLines[i], "LEDIntensity", "FlashIntensity"); // Rename migrated = migrated | replaceString(configLines[i], "FixedExposure", "UNUSED"); // Mark as unused migrated = migrated | replaceString(configLines[i], ";Demo = true", ";Demo = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";Demo", "Demo"); // Enable it + migrated = migrated | replaceString(configLines[i], ";Demo", "Demo"); // Enable it } if (section == "[Alignment]") { - if (isInString(configLines[i], "AlignmentAlgo") && isInString(configLines[i], ";")) { // It is the parameter "AlignmentAlgo" and it is commented out - migrated = migrated | replaceString(configLines[i], "highAccuracy", "default"); // Set it to its default value and enable it + if (isInString(configLines[i], "AlignmentAlgo") && + isInString(configLines[i], ";")) { // It is the parameter "AlignmentAlgo" and it is commented out + migrated = migrated | + replaceString(configLines[i], "highAccuracy", "default"); // Set it to its default value and enable it migrated = migrated | replaceString(configLines[i], "fast", "default"); // Set it to its default value and enable it - migrated = migrated | replaceString(configLines[i], "off", "default"); // Set it to its default value and enable it - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], "off", "default"); // Set it to its default value and enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - migrated = migrated | replaceString(configLines[i], ";FlipImageSize = true", ";FlipImageSize = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";FlipImageSize", "FlipImageSize"); // Enable it + migrated = migrated | replaceString(configLines[i], ";FlipImageSize = true", ";FlipImageSize = false"); // Set it to its + // default value + migrated = migrated | replaceString(configLines[i], ";FlipImageSize", "FlipImageSize"); // Enable it migrated = migrated | replaceString(configLines[i], "InitialMirror", "UNUSED"); // Mark as unused } @@ -897,180 +944,210 @@ void migrateConfigIni(void) if (section == "[Analog]") { migrated = migrated | replaceString(configLines[i], "LogImageLocation", "ROIImagesLocation"); migrated = migrated | replaceString(configLines[i], "LogfileRetentionInDays", "ROIImagesRetention"); - migrated = migrated | replaceString(configLines[i], "CNNGoodThreshold", ";UNUSED_PARAMETER"); // This parameter is no longer used - migrated = migrated | replaceString(configLines[i], "ExtendedResolution", ";UNUSED_PARAMETER"); // This parameter is no longer used + migrated = migrated | + replaceString(configLines[i], "CNNGoodThreshold", ";UNUSED_PARAMETER"); // This parameter is no longer used + migrated = migrated | + replaceString(configLines[i], "ExtendedResolution", ";UNUSED_PARAMETER"); // This parameter is no longer used } if (section == "[PostProcessing]") { - migrated = migrated | replaceString(configLines[i], ";PreValueUse = true", ";PreValueUse = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";PreValueUse", "PreValueUse"); // Enable it - migrated = migrated | replaceString(configLines[i], "PreValueUse", "FallbackValueUse"); // Rename it + migrated = migrated | + replaceString(configLines[i], ";PreValueUse = true", ";PreValueUse = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], ";PreValueUse", "PreValueUse"); // Enable it + migrated = migrated | replaceString(configLines[i], "PreValueUse", "FallbackValueUse"); // Rename it migrated = migrated | replaceString(configLines[i], ";PreValueAgeStartup", "PreValueAgeStartup"); // Enable it migrated = migrated | replaceString(configLines[i], "PreValueAgeStartup", "FallbackValueAgeStartup"); - migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency = true", ";CheckDigitIncreaseConsistency = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency", "CheckDigitIncreaseConsistency"); // Enable it + migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency = true", + ";CheckDigitIncreaseConsistency = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], ";CheckDigitIncreaseConsistency", + "CheckDigitIncreaseConsistency"); // Enable it - if (isInString(configLines[i], "DecimalShift") && isInString(configLines[i], ";")) { // It is the parameter "DecimalShift" and it is commented out + if (isInString(configLines[i], "DecimalShift") && + isInString(configLines[i], ";")) { // It is the parameter "DecimalShift" and it is commented out migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* AllowNegativeRates has a as prefix! */ - if (isInString(configLines[i], "AllowNegativeRates") && isInString(configLines[i], ";")) { // It is the parameter "AllowNegativeRates" and it is commented out + if (isInString(configLines[i], "AllowNegativeRates") && + isInString(configLines[i], ";")) { // It is the parameter "AllowNegativeRates" and it is commented out migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "AnalogDigitalTransitionStart") && isInString(configLines[i], ";")) { // It is the parameter "AnalogDigitalTransitionStart" and it is commented out + if (isInString(configLines[i], "AnalogDigitalTransitionStart") && + isInString(configLines[i], ";")) { // It is the parameter "AnalogDigitalTransitionStart" and it is commented out migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* MaxRateType has a as prefix! */ if (isInString(configLines[i], "MaxRateType")) { // It is the parameter "MaxRateType" - if (isInString(configLines[i], ";")) { // if disabled + if (isInString(configLines[i], ";")) { // if disabled migrated = migrated | replaceString(configLines[i], "= Off", "= RatePerMin"); // Convert it to its default value - migrated = migrated | replaceString(configLines[i], "= RateChange", "= RatePerMin"); // Convert it to its default value - migrated = migrated | replaceString(configLines[i], "= AbsoluteChange", "= RatePerMin"); // Convert it to its default value - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | + replaceString(configLines[i], "= RateChange", "= RatePerMin"); // Convert it to its default value + migrated = migrated | + replaceString(configLines[i], "= AbsoluteChange", "= RatePerMin"); // Convert it to its default value + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } else { migrated = migrated | replaceString(configLines[i], "= Off", "= RateOff"); // Convert it to its new name - migrated = migrated | replaceString(configLines[i], "= RateChange", "= RatePerMin"); // Convert it to its new name - migrated = migrated | replaceString(configLines[i], "= AbsoluteChange", "= RatePerInterval"); // Convert it to its new name + migrated = migrated | + replaceString(configLines[i], "= RateChange", "= RatePerMin"); // Convert it to its new name + migrated = migrated | + replaceString(configLines[i], "= AbsoluteChange", "= RatePerInterval"); // Convert it to its new name } } - if (isInString(configLines[i], "MaxRateValue") && isInString(configLines[i], ";")) { // It is the parameter "MaxRateValue" and it is commented out + if (isInString(configLines[i], "MaxRateValue") && + isInString(configLines[i], ";")) { // It is the parameter "MaxRateValue" and it is commented out migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* ExtendedResolution has a as prefix! */ - if (isInString(configLines[i], "ExtendedResolution") && isInString(configLines[i], ";")) { // It is the parameter "ExtendedResolution" and it is commented out + if (isInString(configLines[i], "ExtendedResolution") && + isInString(configLines[i], ";")) { // It is the parameter "ExtendedResolution" and it is commented out migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* IgnoreLeadingNaN has a as prefix! */ - if (isInString(configLines[i], "IgnoreLeadingNaN") && isInString(configLines[i], ";")) { // It is the parameter "IgnoreLeadingNaN" and it is commented out + if (isInString(configLines[i], "IgnoreLeadingNaN") && + isInString(configLines[i], ";")) { // It is the parameter "IgnoreLeadingNaN" and it is commented out migrated = migrated | replaceString(configLines[i], "true", "false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } } if (section == "[MQTT]") { - migrated = migrated | replaceString(configLines[i], ";Uri", "Uri"); // Enable it + migrated = migrated | replaceString(configLines[i], ";Uri", "Uri"); // Enable it migrated = migrated | replaceString(configLines[i], ";MainTopic", "MainTopic"); // Enable it - migrated = migrated | replaceString(configLines[i], ";ClientID", "ClientID"); // Enable it + migrated = migrated | replaceString(configLines[i], ";ClientID", "ClientID"); // Enable it if (isInString(configLines[i], "CACert") && !isInString(configLines[i], "TLSCACert")) { migrated = migrated | replaceString(configLines[i], "CACert =", "TLSCACert ="); // Rename it - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } if (isInString(configLines[i], "ClientCert") && !isInString(configLines[i], "TLSClientCert")) { migrated = migrated | replaceString(configLines[i], "ClientCert =", "TLSClientCert ="); // Rename it - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } if (isInString(configLines[i], "ClientKey") && !isInString(configLines[i], "TLSClientKey")) { migrated = migrated | replaceString(configLines[i], "ClientKey =", "TLSClientKey ="); // Rename it - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - migrated = migrated | replaceString(configLines[i], "SetRetainFlag", "RetainMessages"); // First rename it, enable it with its default value - migrated = migrated | replaceString(configLines[i], ";RetainMessages = true", ";RetainMessages = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], "SetRetainFlag", "RetainMessages"); // First rename it, enable it + // with its default value + migrated = migrated | replaceString(configLines[i], ";RetainMessages = true", + ";RetainMessages = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";RetainMessages", "RetainMessages"); // Enable it migrated = migrated | replaceString(configLines[i], "RetainMessages", "RetainProcessData"); // Rename it - migrated = migrated | replaceString(configLines[i], ";HomeassistantDiscovery = true", ";HomeassistantDiscovery = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], ";HomeassistantDiscovery = true", + ";HomeassistantDiscovery = false"); // Set it to its default value migrated = migrated | replaceString(configLines[i], ";HomeassistantDiscovery", "HomeassistantDiscovery"); // Enable it if (isInString(configLines[i], "MeterType") && !isInString(configLines[i], "HAMeterType")) { - migrated = migrated | replaceString(configLines[i], "MeterType =", "HAMeterType ="); // Rename it - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], "MeterType =", "HAMeterType ="); // Rename it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it migrated = migrated | replaceString(configLines[i], "HAMeterType = other", "HAMeterType = water_m3"); // Enable it } - if (configLines[i].rfind("Topic", 0) != std::string::npos) { // only if string starts with "Topic" (Was the naming in very old version) + if (configLines[i].rfind("Topic", 0) != std::string::npos) { // only if string starts with "Topic" (Was the naming in + // very old version) migrated = migrated | replaceString(configLines[i], "Topic", "MainTopic"); } } if (section == "[InfluxDB]") { - if (isInString(configLines[i], "Uri") && isInString(configLines[i], ";")) { // It is the parameter "Uri" and it is commented out - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Uri") && isInString(configLines[i], ";")) { // It is the parameter "Uri" and it is + // commented out + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "Database") && isInString(configLines[i], ";")) { // It is the parameter "Database" and it is commented out - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Database") && isInString(configLines[i], ";")) { // It is the parameter "Database" and + // it is commented out + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* Measurement has a as prefix! */ - if (isInString(configLines[i], "Measurement") && isInString(configLines[i], ";")) { // It is the parameter "Measurement" and is it disabled - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Measurement") && isInString(configLines[i], ";")) { // It is the parameter "Measurement" + // and is it disabled + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* Fieldname has a as prefix! */ - if (isInString(configLines[i], "Fieldname")) { // It is the parameter "Fieldname" + if (isInString(configLines[i], "Fieldname")) { // It is the parameter "Fieldname" migrated = migrated | replaceString(configLines[i], "Fieldname", "Field"); // Rename it to Field - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* Field has a as prefix! */ - if (isInString(configLines[i], "Field") && isInString(configLines[i], ";")) { // It is the parameter "Field" and is it disabled - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Field") && isInString(configLines[i], ";")) { // It is the parameter "Field" and is it + // disabled + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } } if (section == "[InfluxDBv2]") { - if (isInString(configLines[i], "Uri") && isInString(configLines[i], ";")) { // It is the parameter "Uri" and it is commented out - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Uri") && isInString(configLines[i], ";")) { // It is the parameter "Uri" and it is + // commented out + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "Database") && isInString(configLines[i], ";")) { // It is the parameter "Database" and it is commented out - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Database") && isInString(configLines[i], ";")) { // It is the parameter "Database" and + // it is commented out + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "Database")) { // It is the parameter "Database" + if (isInString(configLines[i], "Database")) { // It is the parameter "Database" migrated = migrated | replaceString(configLines[i], "Database", "Bucket"); // Rename it to Bucket } /* Measurement has a as prefix! */ - if (isInString(configLines[i], "Measurement") && isInString(configLines[i], ";")) { // It is the parameter "Measurement" and is it disabled - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Measurement") && isInString(configLines[i], ";")) { // It is the parameter "Measurement" + // and is it disabled + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* Fieldname has a as prefix! */ - if (isInString(configLines[i], "Fieldname")) { // It is the parameter "Fieldname" + if (isInString(configLines[i], "Fieldname")) { // It is the parameter "Fieldname" migrated = migrated | replaceString(configLines[i], "Fieldname", "Field"); // Rename it to Field - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } /* Field has a as prefix! */ - if (isInString(configLines[i], "Field") && isInString(configLines[i], ";")) { // It is the parameter "Field" and is it disabled - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "Field") && isInString(configLines[i], ";")) { // It is the parameter "Field" and is it + // disabled + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } } if (section == "[DataLogging]") { /* DataLogActive is true by default! */ - migrated = migrated | replaceString(configLines[i], ";DataLogActive = false", ";DataLogActive = true"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";DataLogActive", "DataLogActive"); // Enable it + migrated = migrated | replaceString(configLines[i], ";DataLogActive = false", ";DataLogActive = true"); // Set it to its + // default value + migrated = migrated | replaceString(configLines[i], ";DataLogActive", "DataLogActive"); // Enable it migrated = migrated | replaceString(configLines[i], "DataLogRetentionInDays", "DataFilesRetention"); } if (section == "[AutoTimer]") { - migrated = migrated | replaceString(configLines[i], ";AutoStart = true", ";AutoStart = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";AutoStart", "AutoStart"); // Enable it + migrated = migrated | + replaceString(configLines[i], ";AutoStart = true", ";AutoStart = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], ";AutoStart", "AutoStart"); // Enable it migrated = migrated | replaceString(configLines[i], "Intervall", "Interval"); } if (section == "[Debug]") { - migrated = migrated | replaceString(configLines[i], "Logfile ", "LogLevel "); // Whitespace needed so it does not match `LogfileRetentionInDays` + migrated = migrated | replaceString(configLines[i], "Logfile ", "LogLevel "); // Whitespace needed so it does not match + // `LogfileRetentionInDays` /* LogLevel (resp. LogFile) was originally a boolean, but we switched it to an int - * For both cases (true/false), we set it to level 2 (WARNING) */ + * For both cases (true/false), we set it to level 2 (WARNING) */ migrated = migrated | replaceString(configLines[i], "LogLevel = true", "LogLevel = 2"); migrated = migrated | replaceString(configLines[i], "LogLevel = false", "LogLevel = 2"); @@ -1078,32 +1155,37 @@ void migrateConfigIni(void) } if (section == "[System]") { - if (isInString(configLines[i], "TimeServer = undefined") && isInString(configLines[i], ";")) - { // It is the parameter "TimeServer" and is it disabled + if (isInString(configLines[i], "TimeServer = undefined") && + isInString(configLines[i], ";")) { // It is the parameter "TimeServer" and is it disabled migrated = migrated | replaceString(configLines[i], "undefined", "pool.ntp.org"); migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "TimeZone") && isInString(configLines[i], ";")) { // It is the parameter "TimeZone" and it is commented out - migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it + if (isInString(configLines[i], "TimeZone") && isInString(configLines[i], ";")) { // It is the parameter "TimeZone" and + // it is commented out + migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - if (isInString(configLines[i], "Hostname") && isInString(configLines[i], ";")) { // It is the parameter "Hostname" and is it disabled + if (isInString(configLines[i], "Hostname") && isInString(configLines[i], ";")) { // It is the parameter "Hostname" and + // is it disabled migrated = migrated | replaceString(configLines[i], "undefined", "watermeter"); migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } migrated = migrated | replaceString(configLines[i], "RSSIThreashold", "RSSIThreshold"); - if (isInString(configLines[i], "CPUFrequency") && isInString(configLines[i], ";")) { // It is the parameter "CPUFrequency" and is it disabled + if (isInString(configLines[i], "CPUFrequency") && + isInString(configLines[i], ";")) { // It is the parameter "CPUFrequency" and is it disabled migrated = migrated | replaceString(configLines[i], "240", "160"); migrated = migrated | replaceString(configLines[i], ";", ""); // Enable it } - migrated = migrated | replaceString(configLines[i], "AutoAdjustSummertime", ";UNUSED_PARAMETER"); // This parameter is no longer used + migrated = migrated | replaceString(configLines[i], "AutoAdjustSummertime", ";UNUSED_PARAMETER"); // This parameter is + // no longer used - migrated = migrated | replaceString(configLines[i], ";SetupMode = true", ";SetupMode = false"); // Set it to its default value - migrated = migrated | replaceString(configLines[i], ";SetupMode", "SetupMode"); // Enable it + migrated = migrated | + replaceString(configLines[i], ";SetupMode = true", ";SetupMode = false"); // Set it to its default value + migrated = migrated | replaceString(configLines[i], ";SetupMode", "SetupMode"); // Enable it } } } @@ -1137,7 +1219,7 @@ void migrateWlanIni() std::string tmp = ""; std::vector splitted; - FILE* pFile = fopen(std::string(CONFIG_WIFI_FILE_LEGACY).c_str(), "r"); + FILE *pFile = fopen(std::string(CONFIG_WIFI_FILE_LEGACY).c_str(), "r"); if (pFile == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Unable to open file (read)"); return; @@ -1155,57 +1237,57 @@ void migrateWlanIni() } while ((line.size() > 0) || !(feof(pFile))) { - if (line[0] != ';') { // Skip lines which starts with ';' + if (line[0] != ';') { // Skip lines which starts with ';' splitted = splitStringWLAN(line, "="); splitted[0] = trim(splitted[0], " "); if ((splitted.size() > 1) && (toUpper(splitted[0]) == "SSID")) { tmp = trim(splitted[1]); - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ssid = tmp; } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "PASSWORD")) { tmp = splitted[1]; - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.password = tmp; ConfigClass::getInstance()->saveMigDataToNVS("wlan_pw", ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.password); } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")) { tmp = trim(splitted[1]); - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.hostname = tmp; } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")) { tmp = splitted[1]; - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.ipAddress = tmp; } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")) { tmp = splitted[1]; - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.gatewayAddress = tmp; } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")) { tmp = splitted[1]; - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.subnetMask = tmp; } else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")) { tmp = splitted[1]; - if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')) { - tmp = tmp.substr(1, tmp.length()-2); + if ((tmp[0] == '"') && (tmp[tmp.length() - 1] == '"')) { + tmp = tmp.substr(1, tmp.length() - 2); } ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.dnsServer = tmp; } @@ -1223,8 +1305,7 @@ void migrateWlanIni() if (!ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.ipAddress.empty() && !ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.subnetMask.empty() && - !ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.gatewayAddress.empty()) - { + !ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.gatewayAddress.empty()) { ConfigClass::getInstance()->cfgTmp()->sectionNetwork.wlan.ipv4.networkConfig = NETWORK_WLAN_IP_CONFIG_STATIC; } @@ -1238,53 +1319,53 @@ void migrateWlanIni() std::vector splitString(std::string input, std::string delimiter) { - std::vector output; + std::vector output; // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence - if ((input.find("password") != std::string::npos) || (input.find("Token") != std::string::npos)) { - size_t pos = input.find("="); - output.push_back(trim(input.substr(0, pos), "")); - output.push_back(trim(input.substr(pos +1, std::string::npos), "")); - } - else { // Legacy Mode - input = trim(input, delimiter); // trim to avoid delimiter deletion at the of string (z.B. == in string) - size_t pos = findDelimiterPos(input, delimiter); - std::string token; - while (pos != std::string::npos) { - token = input.substr(0, pos); - token = trim(token, delimiter); - output.push_back(token); - input.erase(0, pos + 1); - input = trim(input, delimiter); - pos = findDelimiterPos(input, delimiter); - } - output.push_back(input); - } - - return output; + if ((input.find("password") != std::string::npos) || (input.find("Token") != std::string::npos)) { + size_t pos = input.find("="); + output.push_back(trim(input.substr(0, pos), "")); + output.push_back(trim(input.substr(pos + 1, std::string::npos), "")); + } + else { // Legacy Mode + input = trim(input, delimiter); // trim to avoid delimiter deletion at the of string (z.B. == in string) + size_t pos = findDelimiterPos(input, delimiter); + std::string token; + while (pos != std::string::npos) { + token = input.substr(0, pos); + token = trim(token, delimiter); + output.push_back(token); + input.erase(0, pos + 1); + input = trim(input, delimiter); + pos = findDelimiterPos(input, delimiter); + } + output.push_back(input); + } + + return output; } std::vector splitStringWLAN(std::string input, std::string _delimiter) { - std::vector output; - std::string delimiter = " =,"; + std::vector output; + std::string delimiter = " =,"; if (_delimiter.length() > 0) { delimiter = _delimiter; } - input = trim(input, delimiter); - size_t pos = findDelimiterPos(input, delimiter); - std::string token; + input = trim(input, delimiter); + size_t pos = findDelimiterPos(input, delimiter); + std::string token; if (pos != std::string::npos) { // splitted only up to first equal sign !!! Special case for WLAN.ini - token = input.substr(0, pos); - token = trim(token, delimiter); - output.push_back(token); - input.erase(0, pos + 1); - input = trim(input, delimiter); - } - output.push_back(input); - - return output; + token = input.substr(0, pos); + token = trim(token, delimiter); + output.push_back(token); + input.erase(0, pos + 1); + input = trim(input, delimiter); + } + output.push_back(input); + + return output; } diff --git a/code/components/config_handling/configMigration.h b/code/components/config_handling/configMigration.h index 0e38036a6..e588f2bba 100644 --- a/code/components/config_handling/configMigration.h +++ b/code/components/config_handling/configMigration.h @@ -15,4 +15,4 @@ std::vector splitStringWLAN(std::string input, std::string _delimit bool replaceString(std::string &s, std::string const &toReplace, std::string const &replaceWith); bool replaceString(std::string &s, std::string const &toReplace, std::string const &replaceWith, bool logIt); -#endif //CONFIGMIGRATION_H \ No newline at end of file +#endif // CONFIGMIGRATION_H diff --git a/code/components/fileserver_ota/server_file.cpp b/code/components/fileserver_ota/server_file.cpp index 2b3d38d49..6cea0890e 100644 --- a/code/components/fileserver_ota/server_file.cpp +++ b/code/components/fileserver_ota/server_file.cpp @@ -38,7 +38,7 @@ extern "C" { #ifdef ENABLE_MQTT #include "interface_mqtt.h" -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT static const char *TAG = "SERVER_FILE"; @@ -219,21 +219,10 @@ esp_err_t sendFile(httpd_req_t *req, std::string filename) // httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); // For all files with the following file extention tell the webbrowser to cache them for a long period - if (endsWith(filename, ".html") || - endsWith(filename, ".htm") || - endsWith(filename, ".css") || - endsWith(filename, ".js") || - endsWith(filename, ".map") || - endsWith(filename, ".jpg") || - endsWith(filename, ".jpeg") || - endsWith(filename, ".ico") || - endsWith(filename, ".gif") || - endsWith(filename, ".svg") || - endsWith(filename, ".png") || - endsWith(filename, ".md") || - endsWith(filename, ".webmanifest") || - endsWith(filename, ".txt")) - { + if (endsWith(filename, ".html") || endsWith(filename, ".htm") || endsWith(filename, ".css") || endsWith(filename, ".js") || + endsWith(filename, ".map") || endsWith(filename, ".jpg") || endsWith(filename, ".jpeg") || endsWith(filename, ".ico") || + endsWith(filename, ".gif") || endsWith(filename, ".svg") || endsWith(filename, ".png") || endsWith(filename, ".md") || + endsWith(filename, ".webmanifest") || endsWith(filename, ".txt")) { if (filename == "/sdcard/html/index.html") { httpd_resp_set_hdr(req, "Cache-Control", "max-age=0"); } @@ -248,7 +237,7 @@ esp_err_t sendFile(httpd_req_t *req, std::string filename) setContentTypeFromFile(req, filename.c_str()); /* Retrieve the pointer to scratch buffer for temporary storage */ - char *chunk = (char *) ((struct HttpServerData *)req->user_ctx)->scratch; + char *chunk = (char *)((struct HttpServerData *)req->user_ctx)->scratch; size_t chunksize; do { /* Read file in chunks into the scratch buffer */ @@ -281,15 +270,17 @@ static esp_err_t sendLogfile(httpd_req_t *req, bool send_full_file) FILE *fd = NULL; std::string currentfilename = LogFile.getCurrentFileName(); - //ESP_LOGD(TAG, "uri: %s, filepath: %s", req->uri, currentfilename.c_str()); + // ESP_LOGD(TAG, "uri: %s, filepath: %s", req->uri, currentfilename.c_str()); // !!! Do not close actual logfile to avoid software exception !!! - //LogFile.closeLogFileAppendHandle(); + // LogFile.closeLogFileAppendHandle(); fd = fopen(currentfilename.c_str(), "r"); if (fd == NULL) { - // LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendLogfile: Failed to read file: " + currentfilename); // It's not a fault if no file is available - httpd_resp_send(req, "No recent log entries", HTTPD_RESP_USE_STRLEN); // Respond with a positive feedback, no logs available from today + // LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendLogfile: Failed to read file: " + currentfilename); // It's not a fault if no file + // is available + httpd_resp_send(req, "No recent log entries", HTTPD_RESP_USE_STRLEN); // Respond with a positive feedback, no logs available from + // today return ESP_OK; } @@ -318,8 +309,9 @@ static esp_err_t sendLogfile(httpd_req_t *req, bool send_full_file) pos = pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos); if (fseek(fd, pos, SEEK_SET)) { // Go to start position - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendLogfile: Failed to go back " + - std::to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + " bytes within the file"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "sendLogfile: Failed to go back " + std::to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + + " bytes within the file"); return ESP_FAIL; } } @@ -350,7 +342,7 @@ static esp_err_t sendLogfile(httpd_req_t *req, bool send_full_file) return ESP_FAIL; } - /* Keep looping till the whole file is sent */ + /* Keep looping till the whole file is sent */ } while (chunksize != 0); /* Close file after sending complete */ @@ -365,7 +357,7 @@ static esp_err_t sendLogfile(httpd_req_t *req, bool send_full_file) static esp_err_t handler_logfiles(httpd_req_t *req) { - const char* APIName = "log:v2"; // API name and version + const char *APIName = "log:v2"; // API name and version char query[100]; char valuechar[30]; std::string type; @@ -402,7 +394,7 @@ static esp_err_t sendDatafile(httpd_req_t *req, bool send_full_file) FILE *fd = NULL; std::string currentfilename = LogFile.getCurrentFileNameData(); - //ESP_LOGD(TAG, "uri: %s, filepath: %s", req->uri, currentfilename.c_str()); + // ESP_LOGD(TAG, "uri: %s, filepath: %s", req->uri, currentfilename.c_str()); httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_hdr(req, "Cache-Control", "no-cache"); @@ -410,8 +402,10 @@ static esp_err_t sendDatafile(httpd_req_t *req, bool send_full_file) fd = fopen(currentfilename.c_str(), "r"); if (fd == NULL) { - //LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendDatafile: Failed to read file: " + currentfilename); // It's not a fault if no file is available - httpd_resp_send(req, "No recent data entries", HTTPD_RESP_USE_STRLEN); // Respond with a positive feedback, no data available from today + // LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendDatafile: Failed to read file: " + currentfilename); // It's not a fault if no file + // is available + httpd_resp_send(req, "No recent data entries", HTTPD_RESP_USE_STRLEN); // Respond with a positive feedback, no data available from + // today return ESP_OK; } @@ -436,8 +430,9 @@ static esp_err_t sendDatafile(httpd_req_t *req, bool send_full_file) pos = pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos); if (fseek(fd, pos, SEEK_SET)) { // Go to start position - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "sendDatafile: Failed to go back " + - std::to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + " bytes within the file"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "sendDatafile: Failed to go back " + std::to_string(std::min((long)LOGFILE_LAST_PART_BYTES, pos)) + + " bytes within the file"); return ESP_FAIL; } } @@ -483,7 +478,7 @@ static esp_err_t sendDatafile(httpd_req_t *req, bool send_full_file) static esp_err_t handler_datafiles(httpd_req_t *req) { - const char* APIName = "data:v2"; // API name and version + const char *APIName = "data:v2"; // API name and version char query[100]; char valuechar[30]; std::string type; @@ -516,7 +511,7 @@ static esp_err_t handler_datafiles(httpd_req_t *req) // Response with a run-time generated html consisting all files and folders of requested path -static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char* uripath, bool readonly) +static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char *uripath, bool readonly) { char entrypath[FILE_PATH_MAX]; char entrysize[16]; @@ -528,9 +523,11 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const char dirpath_corrected[FILE_PATH_MAX]; strcpy(dirpath_corrected, dirpath); - HttpServerData * server_data = (HttpServerData *) req->user_ctx; - if ((strlen(dirpath_corrected)-1) > strlen(server_data->basePathFileserver)) // if dirpath is not mountpoint, the last "\" needs to be removed - dirpath_corrected[strlen(dirpath_corrected)-1] = '\0'; + HttpServerData *server_data = (HttpServerData *)req->user_ctx; + if ((strlen(dirpath_corrected) - 1) > strlen(server_data->basePathFileserver)) { // if dirpath is not mountpoint, the last "\" needs to + // be removed + dirpath_corrected[strlen(dirpath_corrected) - 1] = '\0'; + } DIR *dir = opendir(dirpath_corrected); @@ -551,7 +548,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const httpd_resp_set_hdr(req, "Cache-Control", "no-cache"); /* Send HTML file header */ - //httpd_resp_sendstr_chunk(req, ""); --> This is already part of 'sys_fileserver.html' file + // httpd_resp_sendstr_chunk(req, ""); --> This is already part of 'sys_fileserver.html' file ///////////////////////////////////////////////// if (!readonly) { @@ -565,8 +562,8 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const size_t chunksize; do { chunksize = fread(chunk, 1, WEBSERVER_SCRATCH_BUFSIZE, fd); - //ESP_LOGD(TAG, "Chunksize %d", chunksize); - if (chunksize > 0){ + // ESP_LOGD(TAG, "Chunksize %d", chunksize); + if (chunksize > 0) { if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) { fclose(fd); std::string msg_txt = "http_resp_dir_html: File sending failed: /sdcard/html/sys_fileserver.html"; @@ -578,7 +575,7 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const } } while (chunksize != 0); fclose(fd); - //ESP_LOGD(TAG, "File sending complete"); + // ESP_LOGD(TAG, "File sending complete"); } /////////////////////////////// @@ -589,16 +586,15 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const /* Send file-list table definition and column labels */ httpd_resp_sendstr_chunk(req, - "" - "" - ""); + "
NameTypeSize
" + "" + ""); if (!readonly) { httpd_resp_sendstr_chunk(req, ""); + httpd_resp_sendstr_chunk(req, "\">" + ""); } httpd_resp_sendstr_chunk(req, "\n"); @@ -615,8 +611,8 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len); ESP_LOGD(TAG, "Entrypath: %s", entrypath); if (stat(entrypath, &entry_stat) == -1) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "http_resp_dir_html: Failed to read " + - std::string(entrytype) + ": " + std::string(entry->d_name)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "http_resp_dir_html: Failed to read " + std::string(entrytype) + ": " + std::string(entry->d_name)); continue; } @@ -679,7 +675,7 @@ static esp_err_t download_get_handler(httpd_req_t *req) struct stat file_stat; const char *filename = getPathFromUri(filepath, ((struct HttpServerData *)req->user_ctx)->basePathFileserver, - req->uri + sizeof("/fileserver") - 1, sizeof(filepath)); + req->uri + sizeof("/fileserver") - 1, sizeof(filepath)); if (!filename) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "download_get_handler: Filename is too long"); @@ -713,10 +709,8 @@ static esp_err_t download_get_handler(httpd_req_t *req) // Reject unavailable files if (stat(filepath, &file_stat) == -1) { // Special case: Do not log special config files in log to avoid confusion because they are missing before finalizing initial setup - if (strcmp("/sdcard/config/reference.jpg", filepath) != 0 && - strcmp("/sdcard/config/marker1.jpg", filepath) != 0 && - strcmp("/sdcard/config/marker2.jpg", filepath) != 0) - { + if (strcmp("/sdcard/config/reference.jpg", filepath) != 0 && strcmp("/sdcard/config/marker1.jpg", filepath) != 0 && + strcmp("/sdcard/config/marker2.jpg", filepath) != 0) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "download_get_handler: File not found: " + std::string(filepath)); } httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File not found"); @@ -725,8 +719,7 @@ static esp_err_t download_get_handler(httpd_req_t *req) // Reject special files with sensitive data if (strcmp("/sdcard/wlan.ini", filepath) == 0 || strcmp("/sdcard/config/backup/wlan_ini.bak", filepath) == 0 || - strcmp("/sdcard/config/config.ini", filepath) == 0 || strcmp("/sdcard/config/backup/config_ini.bak", filepath) == 0) - { + strcmp("/sdcard/config/config.ini", filepath) == 0 || strcmp("/sdcard/config/backup/config_ini.bak", filepath) == 0) { httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "File request forbidden (sensitive data)"); return ESP_FAIL; } @@ -790,7 +783,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req) /* Skip leading "/upload" from URI to get filename */ /* Note sizeof() counts NULL termination hence the -1 */ const char *filename = getPathFromUri(filepath, ((struct HttpServerData *)req->user_ctx)->basePathFileserver, - req->uri + sizeof("/upload") - 1, sizeof(filepath)); + req->uri + sizeof("/upload") - 1, sizeof(filepath)); if (!filename) { httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "upload_post_handler: Filename too long"); return ESP_FAIL; @@ -882,35 +875,33 @@ static esp_err_t upload_post_handler(httpd_req_t *req) std::string directory = std::string(filepath); - size_t zw = directory.find("/"); - size_t found = zw; - while (zw != std::string::npos) { - zw = directory.find("/", found+1); - if (zw != std::string::npos) - found = zw; - } + size_t zw = directory.find("/"); + size_t found = zw; + while (zw != std::string::npos) { + zw = directory.find("/", found + 1); + if (zw != std::string::npos) { + found = zw; + } + } int start_fn = strlen(((struct HttpServerData *)req->user_ctx)->basePathFileserver); ESP_LOGD(TAG, "Directory: %s, start_fn: %d, found: %d", directory.c_str(), start_fn, found); - directory = directory.substr(start_fn, found - start_fn + 1); + directory = directory.substr(start_fn, found - start_fn + 1); directory = "/fileserver" + directory; // ESP_LOGD(TAG, "Directory danach 2: %s", directory.c_str()); /* Redirect onto root to see the updated file list */ - if (strcmp(filename, "/config/marker1.jpg") == 0 || - strcmp(filename, "/config/marker2.jpg") == 0 || - strcmp(filename, "/config/reference.jpg") == 0 || - strcmp(filename, "/img_tmp/marker1.jpg") == 0 || - strcmp(filename, "/img_tmp/marker2.jpg") == 0 || - strcmp(filename, "/img_tmp/reference.jpg") == 0 ) - { + if (strcmp(filename, "/config/marker1.jpg") == 0 || strcmp(filename, "/config/marker2.jpg") == 0 || + strcmp(filename, "/config/reference.jpg") == 0 || strcmp(filename, "/img_tmp/marker1.jpg") == 0 || + strcmp(filename, "/img_tmp/marker2.jpg") == 0 || strcmp(filename, "/img_tmp/reference.jpg") == 0) { httpd_resp_set_status(req, HTTPD_200); // Response without redirection request -> Avoid reloading of folder content } else { httpd_resp_set_status(req, "303 See Other"); // Respond with redirection request } - httpd_resp_set_hdr(req, "Location", directory.c_str()); // If 303 -> Redirect onto root to see the updated file list (only for fileserver action) + httpd_resp_set_hdr(req, "Location", directory.c_str()); // If 303 -> Redirect onto root to see the updated file list (only for + // fileserver action) httpd_resp_sendstr(req, "File uploaded successfully"); return ESP_OK; @@ -942,13 +933,13 @@ static esp_err_t delete_post_handler(httpd_req_t *req) /* Skip leading "/delete" from URI to get filename */ /* Note sizeof() counts NULL termination hence the -1 */ const char *filename = getPathFromUri(filepath, ((struct HttpServerData *)req->user_ctx)->basePathFileserver, - req->uri + sizeof("/delete") - 1, sizeof(filepath)); + req->uri + sizeof("/delete") - 1, sizeof(filepath)); if (!filename) { httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "delete_post_handler: Filename too long"); return ESP_FAIL; } zw = std::string(filename); - zw = zw.substr(0, zw.length()-1); + zw = zw.substr(0, zw.length() - 1); directory = "/fileserver" + zw + "/"; zw = "/sdcard" + zw; ESP_LOGD(TAG, "Directory to delete: %s", zw.c_str()); @@ -960,7 +951,7 @@ static esp_err_t delete_post_handler(httpd_req_t *req) /* Skip leading "/delete" from URI to get filename */ /* Note sizeof() counts NULL termination hence the -1 */ const char *filename = getPathFromUri(filepath, ((struct HttpServerData *)req->user_ctx)->basePathFileserver, - req->uri + sizeof("/delete") - 1, sizeof(filepath)); + req->uri + sizeof("/delete") - 1, sizeof(filepath)); if (!filename) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "delete_post_handler: Filename too long"); return ESP_FAIL; @@ -975,7 +966,8 @@ static esp_err_t delete_post_handler(httpd_req_t *req) if (stat(filepath, &file_stat) == -1) { // File does not exist /* This is ok, we would delete it anyway */ - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "delete_post_handler: Deletion triggered, but file not existing: " + std::string(filename)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "delete_post_handler: Deletion triggered, but file not existing: " + std::string(filename)); } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "delete_post_handler: Deleting file: " + std::string(filename)); @@ -984,13 +976,9 @@ static esp_err_t delete_post_handler(httpd_req_t *req) } /* Avoid redirect to root folder after deletion for system processed files */ - if (strcmp(filename, "/config/marker1.jpg") == 0 || - strcmp(filename, "/config/marker2.jpg") == 0 || - strcmp(filename, "/config/reference.jpg") == 0 || - strcmp(filename, "/img_tmp/marker1.jpg") == 0 || - strcmp(filename, "/img_tmp/marker2.jpg") == 0 || - strcmp(filename, "/img_tmp/reference.jpg") == 0 ) - { + if (strcmp(filename, "/config/marker1.jpg") == 0 || strcmp(filename, "/config/marker2.jpg") == 0 || + strcmp(filename, "/config/reference.jpg") == 0 || strcmp(filename, "/img_tmp/marker1.jpg") == 0 || + strcmp(filename, "/img_tmp/marker2.jpg") == 0 || strcmp(filename, "/img_tmp/reference.jpg") == 0) { httpd_resp_set_status(req, HTTPD_200); // Response without redirection request -> Avoid reloading of folder content } else { @@ -1001,10 +989,11 @@ static esp_err_t delete_post_handler(httpd_req_t *req) *pos = '\0'; // Cut off filename -> From here filename is not valid anymore directory = std::string(filename); directory = "/fileserver" + directory + "/"; - //ESP_LOGI(TAG, "DELETE HANDLER2: Directory: %s", directory.c_str()); + // ESP_LOGI(TAG, "DELETE HANDLER2: Directory: %s", directory.c_str()); } - httpd_resp_set_hdr(req, "Location", directory.c_str()); // If 303 -> Redirect onto root to see the updated file list (only for fileserver action) + httpd_resp_set_hdr(req, "Location", directory.c_str()); // If 303 -> Redirect onto root to see the updated file list (only for + // fileserver action) httpd_resp_sendstr(req, "File successfully deleted"); return ESP_OK; } @@ -1030,17 +1019,15 @@ static std::string printCoreDumpBacktraceInfo(const esp_core_dump_summary_t *sum } } - return std::string("Backtrace: " + std::string(results) + - "\nDepth: " + std::to_string((int)summary->exc_bt_info.depth) + - "\nCorrupted: " + std::to_string(summary->exc_bt_info.corrupted) + - "\nPC: " + std::to_string((int)summary->exc_pc) + - "\nFirmware version: " + getFwVersion()); + return std::string("Backtrace: " + std::string(results) + "\nDepth: " + std::to_string((int)summary->exc_bt_info.depth) + + "\nCorrupted: " + std::to_string(summary->exc_bt_info.corrupted) + "\nPC: " + std::to_string((int)summary->exc_pc) + + "\nFirmware version: " + getFwVersion()); } static esp_err_t coredump_handler(httpd_req_t *req) { - const char* APIName = "coredump:v1"; // API name and version + const char *APIName = "coredump:v1"; // API name and version char query[200]; char valuechar[30]; std::string task; @@ -1055,8 +1042,7 @@ static esp_err_t coredump_handler(httpd_req_t *req) } // Check if coredump partition is available - const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, - ESP_PARTITION_SUBTYPE_DATA_COREDUMP, "coredump"); + const esp_partition_t *partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, "coredump"); if (partition == NULL) { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Partition 'coredump' not found"); return ESP_FAIL; @@ -1151,61 +1137,61 @@ void registerFileserverUri(httpd_handle_t server, const char *basePath) /* Validate file storage base path */ if (!basePath) { - //if (!basePath || strcmp(basePath, "/spiffs") != 0) { + // if (!basePath || strcmp(basePath, "/spiffs") != 0) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "basePath for fileserver root folder not set"); - //return ESP_ERR_INVALID_ARG; + // return ESP_ERR_INVALID_ARG; } strlcpy(httpServerData->basePathFileserver, basePath, sizeof(httpServerData->basePathFileserver)); httpd_uri_t file_download = { - .uri = "/fileserver*", // Match all URIs of type /path/to/file - .method = HTTP_GET, - .handler = download_get_handler, - .user_ctx = httpServerData // Pass server data as context + .uri = "/fileserver*", // Match all URIs of type /path/to/file + .method = HTTP_GET, + .handler = download_get_handler, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &file_download); /* URI handler for uploading files to server */ httpd_uri_t file_upload = { - .uri = "/upload/*", // Match all URIs of type /upload/path/to/file - .method = HTTP_POST, - .handler = upload_post_handler, - .user_ctx = httpServerData // Pass server data as context + .uri = "/upload/*", // Match all URIs of type /upload/path/to/file + .method = HTTP_POST, + .handler = upload_post_handler, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &file_upload); /* URI handler for deleting files from server */ httpd_uri_t file_delete = { - .uri = "/delete/*", // Match all URIs of type /delete/path/to/file - .method = HTTP_POST, - .handler = delete_post_handler, - .user_ctx = httpServerData // Pass server data as context + .uri = "/delete/*", // Match all URIs of type /delete/path/to/file + .method = HTTP_POST, + .handler = delete_post_handler, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &file_delete); /* URI handler for deleting files from server */ httpd_uri_t coredump = { - .uri = "/coredump", - .method = HTTP_GET, - .handler = coredump_handler, - .user_ctx = httpServerData // Pass server data as context + .uri = "/coredump", + .method = HTTP_GET, + .handler = coredump_handler, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &coredump); httpd_uri_t handler_logfile = { - .uri = "/log", - .method = HTTP_GET, - .handler = handler_logfiles, - .user_ctx = httpServerData // Pass server data as context + .uri = "/log", + .method = HTTP_GET, + .handler = handler_logfiles, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &handler_logfile); httpd_uri_t handler_datafile = { - .uri = "/data", - .method = HTTP_GET, - .handler = handler_datafiles, - .user_ctx = httpServerData // Pass server data as context + .uri = "/data", + .method = HTTP_GET, + .handler = handler_datafiles, + .user_ctx = httpServerData // Pass server data as context }; httpd_register_uri_handler(server, &handler_datafile); -} \ No newline at end of file +} diff --git a/code/components/fileserver_ota/server_file.h b/code/components/fileserver_ota/server_file.h index fb3072d40..90a28e839 100644 --- a/code/components/fileserver_ota/server_file.h +++ b/code/components/fileserver_ota/server_file.h @@ -13,4 +13,4 @@ esp_err_t sendFile(httpd_req_t *req, std::string filename); void registerFileserverUri(httpd_handle_t server, const char *basePath); -#endif //SERVERFILE_H \ No newline at end of file +#endif // SERVERFILE_H diff --git a/code/components/fileserver_ota/server_help.cpp b/code/components/fileserver_ota/server_help.cpp index a9bbdbbf5..cca50ae59 100644 --- a/code/components/fileserver_ota/server_help.cpp +++ b/code/components/fileserver_ota/server_help.cpp @@ -37,7 +37,7 @@ bool endsWith(std::string const &str, std::string const &suffix) /* Copies the full path into destination buffer and returns * pointer to path (skipping the preceding base path) */ -const char* getPathFromUri(char *dest, const char *basePath, const char *uri, size_t destsize) +const char *getPathFromUri(char *dest, const char *basePath, const char *uri, size_t destsize) { const size_t basePathLength = strlen(basePath); size_t pathLength = strlen(uri); diff --git a/code/components/fileserver_ota/server_help.h b/code/components/fileserver_ota/server_help.h index 262a3aaa5..12510086d 100644 --- a/code/components/fileserver_ota/server_help.h +++ b/code/components/fileserver_ota/server_help.h @@ -6,7 +6,7 @@ #include "esp_http_server.h" bool endsWith(std::string const &str, std::string const &suffix); -const char* getPathFromUri(char *dest, const char *basePath, const char *uri, size_t destsize); +const char *getPathFromUri(char *dest, const char *basePath, const char *uri, size_t destsize); esp_err_t setContentTypeFromFile(httpd_req_t *req, const char *filename); -#endif //SERVERHELP_H \ No newline at end of file +#endif // SERVERHELP_H diff --git a/code/components/fileserver_ota/server_ota.cpp b/code/components/fileserver_ota/server_ota.cpp index 7842dddc2..805d715c1 100644 --- a/code/components/fileserver_ota/server_ota.cpp +++ b/code/components/fileserver_ota/server_ota.cpp @@ -24,7 +24,7 @@ #ifdef ENABLE_MQTT #include "interface_mqtt.h" -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT #include "webserver.h" #include "MainFlowControl.h" @@ -41,7 +41,7 @@ static const char *TAG = "SERVER_OTA"; std::string file_name_update; // An ota data write buffer ready to write to the flash -static char ota_write_data[SERVER_OTA_SCRATCH_BUFSIZE + 1] = { 0 }; +static char ota_write_data[SERVER_OTA_SCRATCH_BUFSIZE + 1] = {0}; #ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE @@ -49,12 +49,12 @@ static void infinite_loop(void) { int i = 0; LogFile.writeToFile(ESP_LOG_INFO, TAG, "When a new firmware is available on the server, press the reset button to download it"); - while(1) { + while (1) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Waiting for a new firmware (" + std::to_string(++i) + ")"); vTaskDelay(1000 / portTICK_PERIOD_MS); } } -#endif +#endif // CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE // OTA update: 3rd step @@ -62,7 +62,7 @@ static bool ota_update_firmware(std::string fn) { esp_err_t err; /* update handle : set by esp_ota_begin(), must be freed via esp_ota_end() */ - esp_ota_handle_t update_handle = 0 ; + esp_ota_handle_t update_handle = 0; const esp_partition_t *update_partition = NULL; ESP_LOGI(TAG, "Starting firmware update"); @@ -71,27 +71,27 @@ static bool ota_update_firmware(std::string fn) const esp_partition_t *running = esp_ota_get_running_partition(); if (configured != running) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Configured OTA boot partition at offset " + std::to_string(configured->address) + - ", but running from offset " + std::to_string(running->address)); - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "This can happen if either the OTA boot data or preferred boot image become somehow corrupted."); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Configured OTA boot partition at offset " + std::to_string(configured->address) + + ", but running from offset " + std::to_string(running->address)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "This can happen if either the OTA boot data or preferred boot image become somehow corrupted."); } - ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", - running->type, running->subtype, (unsigned int)running->address); + ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)", running->type, running->subtype, (unsigned int)running->address); update_partition = esp_ota_get_next_update_partition(NULL); - ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", - update_partition->subtype, (unsigned int)update_partition->address); - //assert(update_partition != NULL); + ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", update_partition->subtype, (unsigned int)update_partition->address); + // assert(update_partition != NULL); - FILE* f = fopen(fn.c_str(), "rb"); // previously only "r + FILE *f = fopen(fn.c_str(), "rb"); // previously only "r if (f == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ota_update_firmware: File open failed: " + fn); return false; } int binary_file_length = 0; - //deal with all receive packet + // deal with all receive packet bool image_header_was_checked = false; int data_read = fread(ota_write_data, 1, SERVER_OTA_SCRATCH_BUFSIZE, f); @@ -101,7 +101,8 @@ static bool ota_update_firmware(std::string fn) esp_app_desc_t new_app_info; if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) { // check current version with downloading - memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t)); + memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], + sizeof(esp_app_desc_t)); ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version); esp_app_desc_t running_app_info; @@ -109,31 +110,32 @@ static bool ota_update_firmware(std::string fn) ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version); } - #ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE - const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition(); - esp_app_desc_t invalid_app_info; - if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { - ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); - } - - // check current version with last invalid partition - if (last_invalid_app != NULL) { - if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "New version is the same as invalid version"); - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Previously, there was an attempt to launch the firmware with " + - std::string(invalid_app_info.version) + " version, but it failed"); - LogFile.writeToFile(ESP_LOG_WARN, TAG, "The firmware has been rolled back to the previous version"); - infinite_loop(); - } - } +#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE + const esp_partition_t *last_invalid_app = esp_ota_get_last_invalid_partition(); + esp_app_desc_t invalid_app_info; + if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) { + ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version); + } - /* - if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Current running version is the same as a new. We will not continue the update"); + // check current version with last invalid partition + if (last_invalid_app != NULL) { + if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, "New version is the same as invalid version"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Previously, there was an attempt to launch the firmware with " + + std::string(invalid_app_info.version) + " version, but it failed"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, "The firmware has been rolled back to the previous version"); infinite_loop(); } - */ - #endif + } + + /* + if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, "Current running version is the same as a new. We will not continue the update"); + infinite_loop(); + } + */ +#endif // CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE image_header_was_checked = true; @@ -145,7 +147,8 @@ static bool ota_update_firmware(std::string fn) ESP_LOGI(TAG, "esp_ota_begin succeeded"); } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ota_update_firmware: Update file size too small. File size: " + std::to_string(data_read)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ota_update_firmware: Update file size too small. File size: " + std::to_string(data_read)); return false; } } @@ -191,7 +194,7 @@ static bool ota_update_firmware(std::string fn) // OTA update: 2nd step void task_ota_update(void *pvParameter) { - setStatusLed(AP_OR_OTA, 1, true); // Signaling an OTA update + setStatusLed(AP_OR_OTA, 1, true); // Signaling an OTA update std::string filetype = toUpper(getFileType(file_name_update)); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "File name: " + file_name_update + " | File type: " + filetype); @@ -205,8 +208,9 @@ void task_ota_update(void *pvParameter) } else { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Found firmware.bin"); - if (!ota_update_firmware(retval)) + if (!ota_update_firmware(retval)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to update firmware. Update process failed"); + } } } else { @@ -216,15 +220,16 @@ void task_ota_update(void *pvParameter) doRebootOTA(); } else if (filetype == "BIN") { - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Processing BIN file: " + file_name_update); - if (!ota_update_firmware(file_name_update)) + LogFile.writeToFile(ESP_LOG_INFO, TAG, "Processing BIN file: " + file_name_update); + if (!ota_update_firmware(file_name_update)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Firmware update failed"); + } LogFile.writeToFile(ESP_LOG_INFO, TAG, "Reboot to finalize update process"); doRebootOTA(); } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "task_ota_update: Only ZIP or BIN files are supported"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "task_ota_update: Only ZIP or BIN files are supported"); } } @@ -232,22 +237,22 @@ void task_ota_update(void *pvParameter) // OTA update: 1st step void checkOTAUpdate() { - FILE *pfile; + FILE *pfile; if ((pfile = fopen("/sdcard/update.txt", "r")) == NULL) { - LogFile.writeToFile(ESP_LOG_INFO, TAG, "No pending update"); + LogFile.writeToFile(ESP_LOG_INFO, TAG, "No pending update"); return; - } + } - char zw[256]; - fgets(zw, sizeof(zw), pfile); + char zw[256]; + fgets(zw, sizeof(zw), pfile); file_name_update = std::string(zw); fclose(pfile); - deleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!! + deleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!! - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Prepare update process | File: " + file_name_update); + LogFile.writeToFile(ESP_LOG_INFO, TAG, "Prepare update process | File: " + file_name_update); xTaskCreate(&task_ota_update, "task_ota_update", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY + 1, NULL); - while(1) { // wait until reboot within task_do_update + while (1) { // wait until reboot within task_do_update vTaskDelay(1000 / portTICK_PERIOD_MS); } } @@ -278,20 +283,20 @@ void checkOTAPartitionState(void) { ESP_LOGI(TAG, "Check OTA partition state"); - uint8_t sha_256[HASH_LEN] = { 0 }; + uint8_t sha_256[HASH_LEN] = {0}; esp_partition_t partition; // get sha256 digest for the partition table - partition.address = ESP_PARTITION_TABLE_OFFSET; - partition.size = ESP_PARTITION_TABLE_MAX_LEN; - partition.type = ESP_PARTITION_TYPE_DATA; + partition.address = ESP_PARTITION_TABLE_OFFSET; + partition.size = ESP_PARTITION_TABLE_MAX_LEN; + partition.type = ESP_PARTITION_TYPE_DATA; esp_partition_get_sha256(&partition, sha_256); print_sha256(sha_256, "SHA-256 for the partition table"); // get sha256 digest for bootloader - partition.address = ESP_BOOTLOADER_OFFSET; - partition.size = ESP_PARTITION_TABLE_OFFSET; - partition.type = ESP_PARTITION_TYPE_APP; + partition.address = ESP_BOOTLOADER_OFFSET; + partition.size = ESP_PARTITION_TABLE_OFFSET; + partition.type = ESP_PARTITION_TYPE_APP; esp_partition_get_sha256(&partition, sha_256); print_sha256(sha_256, "SHA-256 for bootloader"); @@ -307,14 +312,15 @@ void checkOTAPartitionState(void) if (diagnostic()) { ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution"); esp_ota_mark_app_valid_cancel_rollback(); - } else { + } + else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Diagnostics failed! Start rollback to the previous version"); esp_ota_mark_app_invalid_rollback_and_reboot(); } } } } -#endif +#endif // CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE //**************************************************************************** @@ -379,7 +385,7 @@ esp_err_t handler_ota_update(httpd_req_t *req) } else if (task.compare("unziphtml") == 0) { - //ESP_LOGD(TAG, "Task unziphtml"); + // ESP_LOGD(TAG, "Task unziphtml"); std::string in, out, zw; in = "/sdcard/firmware/html.zip"; @@ -395,7 +401,7 @@ esp_err_t handler_ota_update(httpd_req_t *req) } if (deleteFileRequest) { - if(!deleteFile(fn)) { + if (!deleteFile(fn)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Deletetion failed. File does not exist: " + fn); httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File deletion failed"); return ESP_FAIL; @@ -419,10 +425,10 @@ std::string unzipOTA(std::string _in_zip_file, std::string _root_folder) mz_bool status; size_t uncomp_size; mz_zip_archive zip_archive; - void* p; + void *p; char archive_filename[256]; std::string zw = ""; - std::string retVal = ""; // return string "ERROR" -> FAILURE | return string != "ERROR" -> firmware filename + std::string retVal = ""; // return string "ERROR" -> FAILURE | return string != "ERROR" -> firmware filename ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION); ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str()); @@ -449,8 +455,8 @@ std::string unzipOTA(std::string _in_zip_file, std::string _root_folder) // IMPORTANT NOTE -> miniz v3.x crashes here with ESP32S3, more details --> miniz changelog p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0); if (!p) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "unzipOTA: mz_zip_reader_extract_file_to_heap() failed | file: " + - std::string(archive_filename)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "unzipOTA: mz_zip_reader_extract_file_to_heap() failed | file: " + std::string(archive_filename)); mz_zip_reader_end(&zip_archive); return "ERROR"; } @@ -484,7 +490,7 @@ std::string unzipOTA(std::string _in_zip_file, std::string _root_folder) // Ensure that temp file is surly deleted before writting data deleteFile(filename_zw); - FILE* fpTargetFile = fopen(filename_zw.c_str(), "wb"); + FILE *fpTargetFile = fopen(filename_zw.c_str(), "wb"); uint writtenbytes = fwrite(p, 1, (uint)uncomp_size, fpTargetFile); fclose(fpTargetFile); mz_free(p); @@ -492,13 +498,14 @@ std::string unzipOTA(std::string _in_zip_file, std::string _root_folder) bool isokay = true; if (writtenbytes != (uint)uncomp_size) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "unzipOTA: Failed to write file (written size differ from extracted size). File: " + - std::string(archive_filename) + " | Extracted size: " + std::to_string(uncomp_size)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "unzipOTA: Failed to write file (written size differ from extracted size). File: " + + std::string(archive_filename) + " | Extracted size: " + std::to_string(uncomp_size)); isokay = false; } else { deleteFile(zw); // Make sure, file is not exisitng. Note: It is possible that no file exists - if(!renameFile(filename_zw, zw)) { + if (!renameFile(filename_zw, zw)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "unzipOTA: Failed to rename file: " + filename_zw + " -> " + zw); isokay = false; } @@ -528,7 +535,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory) mz_bool status; size_t uncomp_size; mz_zip_archive zip_archive; - void* p; + void *p; char archive_filename[64]; std::string zw; @@ -571,7 +578,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory) zw = std::string(archive_filename); zw = _target_directory + zw; ESP_LOGD(TAG, "Unzip file: %s", zw.c_str()); - FILE* fpTargetFile = fopen(zw.c_str(), "wb"); + FILE *fpTargetFile = fopen(zw.c_str(), "wb"); fwrite(p, 1, (uint)uncomp_size, fpTargetFile); fclose(fpTargetFile); @@ -591,22 +598,23 @@ void forceReboot() { esp_task_wdt_config_t twdt_config = { .timeout_ms = 1, - .idle_core_mask = (1 << portNUM_PROCESSORS) - 1, // Bitmask of all cores + .idle_core_mask = (1 << portNUM_PROCESSORS) - 1, // Bitmask of all cores .trigger_panic = true, }; ESP_ERROR_CHECK(esp_task_wdt_init(&twdt_config)); esp_task_wdt_add(NULL); - while(true); + while (true) + ; } void task_reboot(void *DeleteMainFlow) { // Write a reboot, to identify a reboot by purpouse - FILE* pfile = fopen("/sdcard/reboot.txt", "w"); + FILE *pfile = fopen("/sdcard/reboot.txt", "w"); if (pfile) { - std::string zw= "reboot"; + std::string zw = "reboot"; fwrite(zw.c_str(), strlen(zw.c_str()), 1, pfile); fclose(pfile); } @@ -616,10 +624,10 @@ void task_reboot(void *DeleteMainFlow) deleteMainFlowTask(); } - /* Stop service tasks */ - #ifdef ENABLE_MQTT - deinitMqttClient(true); - #endif //ENABLE_MQTT +/* Stop service tasks */ +#ifdef ENABLE_MQTT + deinitMqttClient(true); +#endif // ENABLE_MQTT gpio_handler_destroy(); @@ -633,13 +641,13 @@ void task_reboot(void *DeleteMainFlow) deinitWifi(); vTaskDelay(1000 / portTICK_PERIOD_MS); - esp_restart(); // Reset type: CPU reset (Reset both CPUs) + esp_restart(); // Reset type: CPU reset (Reset both CPUs) vTaskDelay(5000 / portTICK_PERIOD_MS); - forceReboot(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated) + forceReboot(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated) LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Reboot failed"); - vTaskDelete(NULL); //Delete this task if it comes to this point + vTaskDelete(NULL); // Delete this task if it comes to this point } @@ -648,11 +656,10 @@ void doReboot() LogFile.writeToFile(ESP_LOG_INFO, TAG, "Reboot triggered by software"); LogFile.writeToFile(ESP_LOG_WARN, TAG, "Reboot in 5 seconds"); - BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 4, (void*) true, 10, NULL); - if( xReturned != pdPASS ) - { + BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 4, (void *)true, 10, NULL); + if (xReturned != pdPASS) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "task_reboot not created -> force reboot without killing flow"); - task_reboot((void*) false); + task_reboot((void *)false); } } @@ -666,10 +673,10 @@ void doRebootOTA() cameraCtrl.deinitCam(); vTaskDelay(5000 / portTICK_PERIOD_MS); - esp_restart(); // Reset type: CPU reset (Reset both CPUs) + esp_restart(); // Reset type: CPU reset (Reset both CPUs) vTaskDelay(5000 / portTICK_PERIOD_MS); - forceReboot(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated) + forceReboot(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated) } @@ -692,17 +699,16 @@ void registerOtaRebootUri(httpd_handle_t server) { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t camuri = { }; - camuri.method = HTTP_GET; - camuri.uri = "/ota"; - camuri.handler = handler_ota_update; - camuri.user_ctx = NULL; + httpd_uri_t camuri = {}; + camuri.method = HTTP_GET; + camuri.uri = "/ota"; + camuri.handler = handler_ota_update; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); - camuri.method = HTTP_GET; - camuri.uri = "/reboot"; - camuri.handler = handler_reboot; - camuri.user_ctx = NULL; + camuri.method = HTTP_GET; + camuri.uri = "/reboot"; + camuri.handler = handler_reboot; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); - } diff --git a/code/components/fileserver_ota/server_ota.h b/code/components/fileserver_ota/server_ota.h index 5676cbfb8..2334d5d18 100644 --- a/code/components/fileserver_ota/server_ota.h +++ b/code/components/fileserver_ota/server_ota.h @@ -9,7 +9,7 @@ void checkOTAUpdate(); #ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE void checkOTAPartitionState(); -#endif +#endif // CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE std::string unzipOTA(std::string _in_zip_file, std::string _root_folder = "/sdcard/"); void unzip(std::string _in_zip_file, std::string _target_directory); @@ -20,4 +20,4 @@ void forceReboot(); void registerOtaRebootUri(httpd_handle_t server); -#endif //SERVEROTA_H \ No newline at end of file +#endif // SERVEROTA_H diff --git a/code/components/gpio_ctrl/gpioControl.cpp b/code/components/gpio_ctrl/gpioControl.cpp index c48a7c1f7..70752f97f 100644 --- a/code/components/gpio_ctrl/gpioControl.cpp +++ b/code/components/gpio_ctrl/gpioControl.cpp @@ -19,7 +19,7 @@ #ifdef ENABLE_MQTT #include "interface_mqtt.h" #include "server_mqtt.h" -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT static const char *TAG = "GPIOCTRL"; @@ -47,7 +47,7 @@ GpioHandler::~GpioHandler() } -void GpioHandler::gpioPinInterrupt(GpioResult* gpioResult) +void GpioHandler::gpioPinInterrupt(GpioResult *gpioResult) { if ((gpioMap != NULL) && (gpioMap->find(gpioResult->gpio) != gpioMap->end())) { (*gpioMap)[gpioResult->gpio]->updatePinState(gpioResult->state); @@ -57,18 +57,18 @@ void GpioHandler::gpioPinInterrupt(GpioResult* gpioResult) static void gpioHandlerTask(void *arg) { - while(1) { - if(uxQueueMessagesWaiting(gpio_queue_handle)) { - while(uxQueueMessagesWaiting(gpio_queue_handle)) { + while (1) { + if (uxQueueMessagesWaiting(gpio_queue_handle)) { + while (uxQueueMessagesWaiting(gpio_queue_handle)) { GpioResult gpioResult; - xQueueReceive(gpio_queue_handle, (void*)&gpioResult, 5); - //LogFile.writeToFile(ESP_LOG_INFO, TAG, "Pin interrupt: GPIO" + std::to_string((int)gpioResult.gpio) + - // ", State: " + std::to_string(gpioResult.state)); - ((GpioHandler*)arg)->gpioPinInterrupt(&gpioResult); + xQueueReceive(gpio_queue_handle, (void *)&gpioResult, 5); + // LogFile.writeToFile(ESP_LOG_INFO, TAG, "Pin interrupt: GPIO" + std::to_string((int)gpioResult.gpio) + + // ", State: " + std::to_string(gpioResult.state)); + ((GpioHandler *)arg)->gpioPinInterrupt(&gpioResult); } } - ((GpioHandler*)arg)->gpioInputStatePolling(); + ((GpioHandler *)arg)->gpioInputStatePolling(); vTaskDelay(pdMS_TO_TICKS(1000)); } } @@ -77,11 +77,10 @@ static void gpioHandlerTask(void *arg) void GpioHandler::gpioInputStatePolling() { if (gpioMap != NULL) { - for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { + for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { if (it->second->getMode() == GPIO_PIN_MODE_INPUT || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLUP || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION) - { + it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION) { it->second->updatePinState(); } } @@ -91,48 +90,50 @@ void GpioHandler::gpioInputStatePolling() void GpioHandler::ledcInitGpio(ledc_timer_t _timer, ledc_channel_t _channel, int _gpioNum, int _frequency) { - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init LEDC timer " + std::to_string((int)_timer) + - ", Frequency: " + std::to_string(_frequency) + + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Init LEDC timer " + std::to_string((int)_timer) + ", Frequency: " + std::to_string(_frequency) + ", Duty Resolution: " + std::to_string((int)calcDutyResolution(_frequency))); // Prepare and then apply the LEDC PWM timer configuration - ledc_timer_config_t ledc_timer = { }; + ledc_timer_config_t ledc_timer = {}; - ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; - ledc_timer.timer_num = _timer; - ledc_timer.duty_resolution = calcDutyResolution(_frequency); - ledc_timer.freq_hz = _frequency; - ledc_timer.clk_cfg = LEDC_USE_APB_CLK; + ledc_timer.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_timer.timer_num = _timer; + ledc_timer.duty_resolution = calcDutyResolution(_frequency); + ledc_timer.freq_hz = _frequency; + ledc_timer.clk_cfg = LEDC_USE_APB_CLK; esp_err_t retVal = ledc_timer_config(&ledc_timer); - if (retVal != ESP_OK) - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to init LEDC timer " + - std::to_string((int)_timer) + ", Error: " +intToHexString(retVal)); + if (retVal != ESP_OK) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Failed to init LEDC timer " + std::to_string((int)_timer) + ", Error: " + intToHexString(retVal)); + } // Prepare and then apply the LEDC PWM channel configuration - ledc_channel_config_t ledc_channel = { }; + ledc_channel_config_t ledc_channel = {}; - ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE; - ledc_channel.channel = _channel; - ledc_channel.timer_sel = _timer; - ledc_channel.intr_type = LEDC_INTR_DISABLE; - ledc_channel.gpio_num = _gpioNum; - ledc_channel.duty = 0; // Set duty to 0% - ledc_channel.hpoint = 0; + ledc_channel.speed_mode = LEDC_LOW_SPEED_MODE; + ledc_channel.channel = _channel; + ledc_channel.timer_sel = _timer; + ledc_channel.intr_type = LEDC_INTR_DISABLE; + ledc_channel.gpio_num = _gpioNum; + ledc_channel.duty = 0; // Set duty to 0% + ledc_channel.hpoint = 0; retVal = ledc_channel_config(&ledc_channel); - if (retVal != ESP_OK) - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to init LEDC channel " + - std::to_string((int)_channel) + ", Error: " +intToHexString(retVal)); + if (retVal != ESP_OK) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Failed to init LEDC channel " + std::to_string((int)_channel) + ", Error: " + intToHexString(retVal)); + } } bool GpioHandler::init() { if (gpioMap == NULL) { - gpioMap = new std::map(); + gpioMap = new std::map(); } else { clearData(); @@ -151,16 +152,16 @@ bool GpioHandler::init() } int smartLedChannel = 0; // max. 8 channels - int ledcChannel = 1; // max 8 channels (CH0: camera, CH1 - CH7: spare) + int ledcChannel = 1; // max 8 channels (CH0: camera, CH1 - CH7: spare) bool initHandlerTask = false; - for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { + for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { it->second->init(); if (it->second->getMode() == GPIO_PIN_MODE_FLASHLIGHT_SMARTLED) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init SmartLED (Flashlight): GPIO" + std::to_string((int)it->second->getGPIO())); - it->second->setSmartLed(new SmartLed(it->second->getLEDType(), it->second->getLEDQuantity(), - it->second->getGPIO(), smartLedChannel, DoubleBuffer)); + it->second->setSmartLed(new SmartLed(it->second->getLEDType(), it->second->getLEDQuantity(), it->second->getGPIO(), + smartLedChannel, DoubleBuffer)); smartLedChannel++; if (smartLedChannel == detail::CHANNEL_COUNT) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Insufficient SmartLED channels"); @@ -205,25 +206,23 @@ bool GpioHandler::init() // Handler task is only needed to maintain input pin state (interrupt or polling) if (it->second->getMode() == GPIO_PIN_MODE_INPUT || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLUP || it->second->getMode() == GPIO_PIN_MODE_INPUT_PULLDOWN || it->second->getMode() == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION) - { + it->second->getMode() == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION) { initHandlerTask = true; } - } - #ifdef ENABLE_MQTT - std::function f = std::bind(&GpioHandler::handleMQTTconnect, this); - registerMqttConnectFunction("gpioHandler", f); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + std::function f = std::bind(&GpioHandler::handleMQTTconnect, this); + registerMqttConnectFunction("gpioHandler", f); +#endif // ENABLE_MQTT // Handler task is only needed to maintain input pin state (interrupt or polling) if (initHandlerTask && xHandleTaskGpio == NULL) { gpio_queue_handle = xQueueCreate(10, sizeof(GpioResult)); - BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpioHandlerTask", 3 * 1024, (void *)this, - tskIDLE_PRIORITY + 4, &xHandleTaskGpio); + BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpioHandlerTask", 3 * 1024, (void *)this, tskIDLE_PRIORITY + 4, + &xHandleTaskGpio); - if (xReturned != pdPASS ) { + if (xReturned != pdPASS) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create gpioHandlerTask"); return false; } @@ -246,12 +245,12 @@ esp_err_t GpioHandler::loadParameter() if (!cfgDataPtr->customizationEnabled) { #if defined(GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED) // Special case: Flashlight default uses SmartLED functionality -> init smartLED functionality only - for (int i= 0; i < GPIO_SPARE_PIN_COUNT; ++i) { + for (int i = 0; i < GPIO_SPARE_PIN_COUNT; ++i) { if (strcmp(gpio_spare_usage[i], FLASHLIGHT_SMARTLED) == 0) { - GpioPin* gpioPin = new GpioPin((gpio_num_t)gpio_spare[i], ("gpio" + std::to_string((int)gpio_spare[i])).c_str(), - GPIO_PIN_MODE_FLASHLIGHT_SMARTLED, GPIO_INTR_DISABLE, 200, 5000, false, false, false, "", - GPIO_FLASHLIGHT_DEFAULT_SMARTLED_TYPE, GPIO_FLASHLIGHT_DEFAULT_SMARTLED_QUANTITY, - Rgb{255,255,255}, 100); + GpioPin *gpioPin = new GpioPin((gpio_num_t)gpio_spare[i], ("gpio" + std::to_string((int)gpio_spare[i])).c_str(), + GPIO_PIN_MODE_FLASHLIGHT_SMARTLED, GPIO_INTR_DISABLE, 200, 5000, false, false, false, "", + GPIO_FLASHLIGHT_DEFAULT_SMARTLED_TYPE, GPIO_FLASHLIGHT_DEFAULT_SMARTLED_QUANTITY, + Rgb{255, 255, 255}, 100); (*gpioMap)[(gpio_num_t)gpio_spare[i]] = gpioPin; return ESP_OK; } @@ -259,7 +258,7 @@ esp_err_t GpioHandler::loadParameter() LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Default flashlight configured as SmartLED, but no valid GPIO config found"); return ESP_FAIL; -#endif +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED return ESP_ERR_NOT_FOUND; } @@ -268,8 +267,9 @@ esp_err_t GpioHandler::loadParameter() for (const auto &pin : cfgDataPtr->gpioPin) { // Skip pin if disabled - if (!pin.pinEnabled) + if (!pin.pinEnabled) { continue; + } gpio_num_t gpioNr = (gpio_num_t)pin.gpioNumber; @@ -285,25 +285,31 @@ esp_err_t GpioHandler::loadParameter() } LedType LEDType = LED_WS2812; - if (pin.smartLed.type == LEDTYPE_WS2812) + if (pin.smartLed.type == LEDTYPE_WS2812) { LEDType = LED_WS2812; - else if (pin.smartLed.type == LEDTYPE_WS2812B_UNIVERSAL) + } + else if (pin.smartLed.type == LEDTYPE_WS2812B_UNIVERSAL) { LEDType = LED_WS2812B; - else if (pin.smartLed.type == LEDTYPE_WS2812B_NEW_VARIANT) + } + else if (pin.smartLed.type == LEDTYPE_WS2812B_NEW_VARIANT) { LEDType = LED_WS2812B_NEWVARIANT; - else if (pin.smartLed.type == LEDTYPE_WS2812B_OLD_VARIANT) + } + else if (pin.smartLed.type == LEDTYPE_WS2812B_OLD_VARIANT) { LEDType = LED_WS2812B_OLDVARIANT; - else if (pin.smartLed.type == LEDTYPE_SK6812) + } + else if (pin.smartLed.type == LEDTYPE_SK6812) { LEDType = LED_SK6812; - else if (pin.smartLed.type == LEDTYPE_WS2813) + } + else if (pin.smartLed.type == LEDTYPE_WS2813) { LEDType = LED_WS2813; + } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "readConfig: Unknown LED type"); return ESP_FAIL; } Rgb LEDColor = Rgb{(uint8_t)pin.smartLed.colorRedChannel, (uint8_t)pin.smartLed.colorGreenChannel, - (uint8_t)pin.smartLed.colorBlueChannel}; + (uint8_t)pin.smartLed.colorBlueChannel}; char gpioName[32]; if (!pin.pinName.empty()) { @@ -319,22 +325,22 @@ esp_err_t GpioHandler::loadParameter() #else bool mqttAccess = false; std::string mqttTopic = ""; -#endif - - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Pin Config: GPIO" + std::to_string((int)gpioNr) + - ", Name: " + std::string(gpioName) + ", Mode: " + pin.pinMode + ", Interrupt Type: " + - pin.captureMode + ", Debounce Time: " + std::to_string(pin.inputDebounceTime) + ", Frequency: " + - std::to_string(pin.PwmFrequency) + ", Logic Active Low: " + std::to_string(pin.logicActiveLow) + - ", HTTP Access: " + std::to_string(pin.exposeToRest) + - ", MQTT Access: " + std::to_string(mqttAccess) + ", MQTT Topic: " + mqttTopic + - ", LED Type: " + std::to_string(pin.smartLed.type) + ", LED Quantity: " + std::to_string(pin.smartLed.quantity) + - ", LED Color: R:" + std::to_string(LEDColor.r) + " | G:" + std::to_string(LEDColor.g) + - " | B:" + std::to_string(LEDColor.b) + ", LED Intensity Correction: " + - std::to_string(pin.intensityCorrectionFactor)); - - GpioPin* gpioPin = new GpioPin(gpioNr, gpioName, pinMode, captureMode, pin.inputDebounceTime, pin.PwmFrequency, - pin.logicActiveLow, pin.exposeToRest, mqttAccess, mqttTopic, LEDType, pin.smartLed.quantity, - LEDColor, pin.intensityCorrectionFactor); +#endif // ENABLE_MQTT + + LogFile.writeToFile( + ESP_LOG_DEBUG, TAG, + "Pin Config: GPIO" + std::to_string((int)gpioNr) + ", Name: " + std::string(gpioName) + ", Mode: " + pin.pinMode + + ", Interrupt Type: " + pin.captureMode + ", Debounce Time: " + std::to_string(pin.inputDebounceTime) + + ", Frequency: " + std::to_string(pin.PwmFrequency) + ", Logic Active Low: " + std::to_string(pin.logicActiveLow) + + ", HTTP Access: " + std::to_string(pin.exposeToRest) + ", MQTT Access: " + std::to_string(mqttAccess) + + ", MQTT Topic: " + mqttTopic + ", LED Type: " + std::to_string(pin.smartLed.type) + + ", LED Quantity: " + std::to_string(pin.smartLed.quantity) + ", LED Color: R:" + std::to_string(LEDColor.r) + + " | G:" + std::to_string(LEDColor.g) + " | B:" + std::to_string(LEDColor.b) + + ", LED Intensity Correction: " + std::to_string(pin.intensityCorrectionFactor)); + + GpioPin *gpioPin = new GpioPin(gpioNr, gpioName, pinMode, captureMode, pin.inputDebounceTime, pin.PwmFrequency, pin.logicActiveLow, + pin.exposeToRest, mqttAccess, mqttTopic, LEDType, pin.smartLed.quantity, LEDColor, + pin.intensityCorrectionFactor); (*gpioMap)[gpioNr] = gpioPin; } @@ -350,7 +356,7 @@ esp_err_t GpioHandler::loadParameter() void GpioHandler::clearData() { if (gpioMap != NULL) { - for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); it++) { + for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); it++) { if (it->second->getSmartLed() != NULL) { delete it->second->getSmartLed(); it->second->setSmartLed(NULL); @@ -369,9 +375,9 @@ void GpioHandler::clearData() void GpioHandler::deinit() { - #ifdef ENABLE_MQTT +#ifdef ENABLE_MQTT unregisterMqttConnectFunction("gpioHandler"); - #endif //ENABLE_MQTT +#endif // ENABLE_MQTT clearData(); @@ -384,31 +390,34 @@ void GpioHandler::deinit() void GpioHandler::gpioFlashlightControl(bool _state, int _intensity) { - if (gpioMap == NULL) + if (gpioMap == NULL) { return; + } - for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { + for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { if (it->second->getMode() == GPIO_PIN_MODE_FLASHLIGHT_PWM) { int dutyResultionMaxValue = calcDutyResolutionMaxValue(it->second->getFrequency()); - int intensityValueCorrected = std::min(std::max(0, it->second->getIntensityCorrection() * - _intensity * dutyResultionMaxValue / 10000), dutyResultionMaxValue); + int intensityValueCorrected = std::min( + std::max(0, it->second->getIntensityCorrection() * _intensity * dutyResultionMaxValue / 10000), dutyResultionMaxValue); esp_err_t retVal = it->second->setPinState(_state, intensityValueCorrected); if (retVal != ESP_OK) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight PWM: GPIO" + std::to_string((int)it->first) + - " failed to set state | Error: " + intToHexString(retVal)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight PWM: GPIO" + std::to_string((int)it->first) + + " failed to set state | Error: " + intToHexString(retVal)); return; } if (_state) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight PWM: GPIO" + std::to_string((int)it->first) + - ", State: " + std::to_string(_state) + ", Intensity: " + std::to_string(intensityValueCorrected) + - "/" + std::to_string(dutyResultionMaxValue)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight PWM: GPIO" + std::to_string((int)it->first) + ", State: " + std::to_string(_state) + + ", Intensity: " + std::to_string(intensityValueCorrected) + "/" + + std::to_string(dutyResultionMaxValue)); } else { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight PWM: GPIO" + std::to_string((int)it->first) + - ", State: " + std::to_string(_state)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight PWM: GPIO" + std::to_string((int)it->first) + ", State: " + std::to_string(_state)); } } else if (it->second->getMode() == GPIO_PIN_MODE_FLASHLIGHT_SMARTLED) { @@ -424,40 +433,44 @@ void GpioHandler::gpioFlashlightControl(bool _state, int _intensity) (*it->second->getSmartLed())[i] = LEDColorIntensityCorrected; } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + - ", State: " + std::to_string(_state) + ", Intensity: " + std::to_string(intensityValueCorrected) + - "/8191, | R: " + std::to_string(LEDColorIntensityCorrected.r) + - ", G:" + std::to_string(LEDColorIntensityCorrected.g) + - ", B:" + std::to_string(LEDColorIntensityCorrected.b)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + ", State: " + std::to_string(_state) + + ", Intensity: " + std::to_string(intensityValueCorrected) + + "/8191, | R: " + std::to_string(LEDColorIntensityCorrected.r) + + ", G:" + std::to_string(LEDColorIntensityCorrected.g) + + ", B:" + std::to_string(LEDColorIntensityCorrected.b)); } else { for (int i = 0; i < it->second->getLEDQuantity(); ++i) { (*it->second->getSmartLed())[i] = Rgb{0, 0, 0}; } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + - ", State: " + std::to_string(_state)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + ", State: " + std::to_string(_state)); } esp_err_t retVal = it->second->getSmartLed()->show(); it->second->updatePinState(_state ? 1 : 0); if (retVal != ESP_OK) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + - " failed to set state | Error: " + intToHexString(retVal)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight SmartLED: GPIO" + std::to_string((int)it->first) + + " failed to set state | Error: " + intToHexString(retVal)); } } else if (it->second->getMode() == GPIO_PIN_MODE_FLASHLIGHT_DIGITAL) { esp_err_t retVal = it->second->setPinState(it->second->getLogicLevelActiveLow() ? !_state : _state); if (retVal != ESP_OK) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight Digital: GPIO" + std::to_string((int)it->first) + - " failed to set state | Error: " + intToHexString(retVal)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight Digital: GPIO" + std::to_string((int)it->first) + + " failed to set state | Error: " + intToHexString(retVal)); return; } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Flashlight Digital: GPIO" + std::to_string((int)it->first) + - ", State: " + std::to_string(it->second->getLogicLevelActiveLow() ? !_state : _state)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Flashlight Digital: GPIO" + std::to_string((int)it->first) + + ", State: " + std::to_string(it->second->getLogicLevelActiveLow() ? !_state : _state)); } } } @@ -466,8 +479,9 @@ void GpioHandler::gpioFlashlightControl(bool _state, int _intensity) gpio_num_t GpioHandler::resolveSparePinNr(uint8_t _sparePinNr) { for (int i = 0; i < GPIO_SPARE_PIN_COUNT; ++i) { - if (gpio_spare[i] == _sparePinNr) + if (gpio_spare[i] == _sparePinNr) { return gpio_spare[i]; + } } return GPIO_NUM_NC; } @@ -475,37 +489,48 @@ gpio_num_t GpioHandler::resolveSparePinNr(uint8_t _sparePinNr) gpio_pin_mode_t GpioHandler::resolvePinMode(std::string input) { - if (input == "disabled") + if (input == "disabled") { return GPIO_PIN_MODE_DISABLED; - else if (input == "input") + } + else if (input == "input") { return GPIO_PIN_MODE_INPUT; - if (input == "input-pullup") + } + if (input == "input-pullup") { return GPIO_PIN_MODE_INPUT_PULLUP; - else if (input == "input-pulldown") + } + else if (input == "input-pulldown") { return GPIO_PIN_MODE_INPUT_PULLDOWN; - else if (input == "output") + } + else if (input == "output") { return GPIO_PIN_MODE_OUTPUT; - else if (input == "output-pwm") + } + else if (input == "output-pwm") { return GPIO_PIN_MODE_OUTPUT_PWM; - else if (input == FLASHLIGHT_PWM) + } + else if (input == FLASHLIGHT_PWM) { return GPIO_PIN_MODE_FLASHLIGHT_PWM; - else if (input == FLASHLIGHT_SMARTLED) + } + else if (input == FLASHLIGHT_SMARTLED) { return GPIO_PIN_MODE_FLASHLIGHT_SMARTLED; - else if (input == FLASHLIGHT_DIGITAL) + } + else if (input == FLASHLIGHT_DIGITAL) { return GPIO_PIN_MODE_FLASHLIGHT_DIGITAL; + } else if (input == FLASHLIGHT_DEFAULT) { - #if defined(GPIO_FLASHLIGHT_DEFAULT_USE_PWM) - return GPIO_PIN_MODE_FLASHLIGHT_PWM; - #elif defined(GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED) - return GPIO_PIN_MODE_FLASHLIGHT_SMARTLED; - #else - return GPIO_PIN_MODE_FLASHLIGHT_DIGITAL; - #endif - } - else if (input == "trigger-cycle-start") +#if defined(GPIO_FLASHLIGHT_DEFAULT_USE_PWM) + return GPIO_PIN_MODE_FLASHLIGHT_PWM; +#elif defined(GPIO_FLASHLIGHT_DEFAULT_USE_SMARTLED) + return GPIO_PIN_MODE_FLASHLIGHT_SMARTLED; +#else + return GPIO_PIN_MODE_FLASHLIGHT_DIGITAL; +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM + } + else if (input == "trigger-cycle-start") { return GPIO_PIN_MODE_TRIGGER_CYCLE_START; - else if (input == "resume-wlan-connection") + } + else if (input == "resume-wlan-connection") { return GPIO_PIN_MODE_RESUME_WLAN_CONNECTION; + } return GPIO_PIN_MODE_DISABLED; } @@ -513,7 +538,7 @@ gpio_pin_mode_t GpioHandler::resolvePinMode(std::string input) std::string GpioHandler::getPinModeDecription(gpio_pin_mode_t _mode) { - switch(_mode) { + switch (_mode) { case 0: return "disabled"; case 1: @@ -544,18 +569,24 @@ std::string GpioHandler::getPinModeDecription(gpio_pin_mode_t _mode) gpio_int_type_t GpioHandler::resolveIntType(std::string input) { - if ( input == "cyclic-polling" ) + if (input == "cyclic-polling") { return GPIO_INTR_DISABLE; - else if ( input == "interrupt-rising-edge" ) + } + else if (input == "interrupt-rising-edge") { return GPIO_INTR_POSEDGE; - else if ( input == "interrupt-falling-edge" ) + } + else if (input == "interrupt-falling-edge") { return GPIO_INTR_NEGEDGE; - else if ( input == "interrupt-rising-falling" ) - return GPIO_INTR_ANYEDGE ; - else if ( input == "interrupt-low-level" ) + } + else if (input == "interrupt-rising-falling") { + return GPIO_INTR_ANYEDGE; + } + else if (input == "interrupt-low-level") { return GPIO_INTR_LOW_LEVEL; - else if ( input == "interrupt-high-level" ) + } + else if (input == "interrupt-high-level") { return GPIO_INTR_HIGH_LEVEL; + } return GPIO_INTR_DISABLE; } @@ -563,7 +594,7 @@ gpio_int_type_t GpioHandler::resolveIntType(std::string input) std::string GpioHandler::getPinInterruptDecription(gpio_int_type_t _type) { - switch(_type) { + switch (_type) { case 0: return "cyclic-polling"; case 1: @@ -592,7 +623,7 @@ ledc_timer_bit_t GpioHandler::calcDutyResolution(int frequency) { // Calculate max duty resultion derived from device clock (LEDC_USE_APB_CLK == 80Mhz) // Limit max duty resolution to 14 bit (due to compability with ESP32S3) - return static_cast(std::min((int)log2(80000000/frequency), 14)); + return static_cast(std::min((int)log2(80000000 / frequency), 14)); } @@ -601,8 +632,9 @@ ledc_timer_t GpioHandler::getFreeTimer(int _frequency) auto it = frequencyTable.find(_frequency); // Return timer related to already registered frequency - if (it != frequencyTable.end()) + if (it != frequencyTable.end()) { return it->second; + } // Insert new frequency and return timer if (frequencyTable.size() == 0) { @@ -624,27 +656,26 @@ ledc_timer_t GpioHandler::getFreeTimer(int _frequency) } - // MQTT GPIO state publish // *********************************** #ifdef ENABLE_MQTT void GpioHandler::handleMQTTconnect() { if (gpioMap != NULL) { - for(std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { + for (std::map::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) { it->second->mqttPublishPinState(); vTaskDelay(pdMS_TO_TICKS(500)); } } } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT // Handle HTTP GPIO request // *********************************** esp_err_t callHandleHttpRequest(httpd_req_t *req) { - GpioHandler *gpioHandler = (GpioHandler*)req->user_ctx; + GpioHandler *gpioHandler = (GpioHandler *)req->user_ctx; return gpioHandler->handleHttpRequest(req); } @@ -706,7 +737,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) return ESP_OK; } - if (!(*gpioMap)[gpioNum]->getHttpAccess()) { + if (!(*gpioMap)[gpioNum]->getHttpAccess()) { httpd_resp_set_type(req, "text/plain"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Skip request, HTTP access disabled"); return ESP_FAIL; @@ -716,10 +747,9 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) requestedGpioState = "{ \"state\": " + std::to_string((*gpioMap)[gpioNum]->getPinState()); if ((*gpioMap)[gpioNum]->getMode() == GPIO_PIN_MODE_OUTPUT_PWM || - (*gpioMap)[gpioNum]->getMode() == GPIO_PIN_MODE_FLASHLIGHT_PWM) - { - requestedGpioState += ", \"pwm_duty\": " + std::to_string(ledc_get_duty(LEDC_LOW_SPEED_MODE, - (*gpioMap)[gpioNum]->getLedcChannel())); + (*gpioMap)[gpioNum]->getMode() == GPIO_PIN_MODE_FLASHLIGHT_PWM) { + requestedGpioState += ", \"pwm_duty\": " + + std::to_string(ledc_get_duty(LEDC_LOW_SPEED_MODE, (*gpioMap)[gpioNum]->getLedcChannel())); } requestedGpioState += " }"; @@ -730,8 +760,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) } else if (task.compare("set_state") == 0) { requestedGpioState = toUpper(requestedGpioState); - if (requestedGpioState != "0" && requestedGpioState != "1") - { + if (requestedGpioState != "0" && requestedGpioState != "1") { respStr = "Skip request, invalid state: " + requestedGpioState; httpd_resp_set_type(req, "text/plain"); httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, respStr.c_str()); @@ -741,15 +770,13 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req) esp_err_t retVal = ESP_OK; if (requestedPWMDuty == -1) { // Use ON/OFF retVal = (*gpioMap)[gpioNum]->setPinState(requestedGpioState == "1", GPIO_SET_SOURCE_HTTP); - respStr = "GPIO" + std::to_string(requestedGpioNum) + - ", State: " + std::to_string((*gpioMap)[gpioNum]->getPinState()); + respStr = "GPIO" + std::to_string(requestedGpioNum) + ", State: " + std::to_string((*gpioMap)[gpioNum]->getPinState()); } else { // Use PWM requestedPWMDuty = std::min(std::max(0, requestedPWMDuty), calcDutyResolutionMaxValue((*gpioMap)[gpioNum]->getFrequency())); retVal = (*gpioMap)[gpioNum]->setPinState(requestedGpioState == "1", requestedPWMDuty, GPIO_SET_SOURCE_HTTP); - respStr = "GPIO" + std::to_string(requestedGpioNum) + - ", State: " + std::to_string((*gpioMap)[gpioNum]->getPinState()) + - ", PWM Duty: " + std::to_string(requestedPWMDuty); + respStr = "GPIO" + std::to_string(requestedGpioNum) + ", State: " + std::to_string((*gpioMap)[gpioNum]->getPinState()) + + ", PWM Duty: " + std::to_string(requestedPWMDuty); } if (retVal != ESP_OK) { @@ -777,12 +804,12 @@ void GpioHandler::registerGpioUri() { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t camuri = { }; - camuri.method = HTTP_GET; + httpd_uri_t camuri = {}; + camuri.method = HTTP_GET; - camuri.uri = "/gpio"; - camuri.handler = callHandleHttpRequest; - camuri.user_ctx = (void*)this; + camuri.uri = "/gpio"; + camuri.handler = callHandleHttpRequest; + camuri.user_ctx = (void *)this; httpd_register_uri_handler(httpServer, &camuri); } @@ -791,8 +818,9 @@ void GpioHandler::registerGpioUri() // *********************************** void createGpioHandler(httpd_handle_t _server) { - if (gpioHandler == NULL) + if (gpioHandler == NULL) { gpioHandler = new GpioHandler(_server); + } } @@ -809,7 +837,7 @@ void gpio_handler_deinit() { if (gpioHandler != NULL) { gpioHandler->deinit(); - } + } } @@ -823,7 +851,7 @@ void gpio_handler_destroy() } -GpioHandler* gpio_handler_get() +GpioHandler *gpio_handler_get() { return gpioHandler; } diff --git a/code/components/gpio_ctrl/gpioControl.h b/code/components/gpio_ctrl/gpioControl.h index 84632c13b..46563c7b7 100644 --- a/code/components/gpio_ctrl/gpioControl.h +++ b/code/components/gpio_ctrl/gpioControl.h @@ -14,10 +14,9 @@ #include "gpioPin.h" -static const gpio_num_t gpio_spare[] {GPIO_SPARE_1, GPIO_SPARE_2, GPIO_SPARE_3, - GPIO_SPARE_4, GPIO_SPARE_5, GPIO_SPARE_6}; -static const char *gpio_spare_usage[] {GPIO_SPARE_1_USAGE, GPIO_SPARE_2_USAGE, GPIO_SPARE_3_USAGE, - GPIO_SPARE_4_USAGE, GPIO_SPARE_5_USAGE, GPIO_SPARE_6_USAGE}; +static const gpio_num_t gpio_spare[]{GPIO_SPARE_1, GPIO_SPARE_2, GPIO_SPARE_3, GPIO_SPARE_4, GPIO_SPARE_5, GPIO_SPARE_6}; +static const char *gpio_spare_usage[]{GPIO_SPARE_1_USAGE, GPIO_SPARE_2_USAGE, GPIO_SPARE_3_USAGE, + GPIO_SPARE_4_USAGE, GPIO_SPARE_5_USAGE, GPIO_SPARE_6_USAGE}; class GpioHandler { diff --git a/code/components/gpio_ctrl/gpioPin.cpp b/code/components/gpio_ctrl/gpioPin.cpp index 3480388ec..d5818abe8 100644 --- a/code/components/gpio_ctrl/gpioPin.cpp +++ b/code/components/gpio_ctrl/gpioPin.cpp @@ -12,7 +12,7 @@ #ifdef ENABLE_MQTT #include "interface_mqtt.h" -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT static const char *TAG = "GPIOPIN"; @@ -23,15 +23,15 @@ extern QueueHandle_t gpio_queue_handle; //******************************************************************************** // GPIO Pin //******************************************************************************** -GpioPin::GpioPin(gpio_num_t _gpio, const char* _name, gpio_pin_mode_t _mode, gpio_int_type_t _interruptType, - int _debounceTime, int _frequency, bool _logicLevelActiveLow, bool _httpAccess, bool _mqttAccess, - std::string _mqttTopic, LedType _LEDType, int _LEDQuantity, Rgb _LEDColor, int _intensityCorrection) +GpioPin::GpioPin(gpio_num_t _gpio, const char *_name, gpio_pin_mode_t _mode, gpio_int_type_t _interruptType, int _debounceTime, + int _frequency, bool _logicLevelActiveLow, bool _httpAccess, bool _mqttAccess, std::string _mqttTopic, LedType _LEDType, + int _LEDQuantity, Rgb _LEDColor, int _intensityCorrection) { gpioISR.gpio = gpio = _gpio; name = _name; mode = _mode; - interruptType = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? GPIO_INTR_ANYEDGE : _interruptType; + interruptType = mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? GPIO_INTR_ANYEDGE + : _interruptType; gpioISR.debounceTime = _debounceTime; frequency = _frequency; logicLevelActiveLow = _logicLevelActiveLow; @@ -64,19 +64,19 @@ GpioPin::~GpioPin() } -static void IRAM_ATTR gpioPinISRHandler(void* arg) +static void IRAM_ATTR gpioPinISRHandler(void *arg) { static TickType_t lastInterruptTime = 0; TickType_t interruptTime = xTaskGetTickCountFromISR(); // Depending on CONFIG_FREERTOS_HZ (100Hz) // If interrupts come faster than debounceTime, assume it's a bounce and ignore - if (interruptTime - lastInterruptTime > pdMS_TO_TICKS(((struct GpioISR*)arg)->debounceTime)) { + if (interruptTime - lastInterruptTime > pdMS_TO_TICKS(((struct GpioISR *)arg)->debounceTime)) { GpioResult gpioResult; - gpioResult.gpio = ((struct GpioISR*)arg)->gpio; + gpioResult.gpio = ((struct GpioISR *)arg)->gpio; gpioResult.state = gpio_get_level(gpioResult.gpio); BaseType_t ContextSwitchRequest = pdFALSE; - xQueueSendToBackFromISR(gpio_queue_handle, (void*)&gpioResult, &ContextSwitchRequest); + xQueueSendToBackFromISR(gpio_queue_handle, (void *)&gpioResult, &ContextSwitchRequest); if (ContextSwitchRequest) { taskYIELD(); @@ -91,34 +91,42 @@ void GpioPin::init() { gpio_config_t gpioConfig; - //set interrupt - gpioConfig.intr_type = mode == GPIO_PIN_MODE_INPUT || mode == GPIO_PIN_MODE_INPUT_PULLUP || - mode == GPIO_PIN_MODE_INPUT_PULLDOWN || mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION ? interruptType : GPIO_INTR_DISABLE; + // set interrupt + gpioConfig.intr_type = mode == GPIO_PIN_MODE_INPUT || mode == GPIO_PIN_MODE_INPUT_PULLUP || mode == GPIO_PIN_MODE_INPUT_PULLDOWN || + mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION + ? interruptType + : GPIO_INTR_DISABLE; - //set input / output mode - gpioConfig.mode = mode == GPIO_PIN_MODE_OUTPUT || mode == GPIO_PIN_MODE_OUTPUT_PWM || - mode == GPIO_PIN_MODE_FLASHLIGHT_PWM || mode == GPIO_PIN_MODE_FLASHLIGHT_SMARTLED || - mode == GPIO_PIN_MODE_FLASHLIGHT_DIGITAL ? gpio_mode_t::GPIO_MODE_OUTPUT : gpio_mode_t::GPIO_MODE_INPUT; + // set input / output mode + gpioConfig.mode = mode == GPIO_PIN_MODE_OUTPUT || mode == GPIO_PIN_MODE_OUTPUT_PWM || mode == GPIO_PIN_MODE_FLASHLIGHT_PWM || + mode == GPIO_PIN_MODE_FLASHLIGHT_SMARTLED || mode == GPIO_PIN_MODE_FLASHLIGHT_DIGITAL + ? gpio_mode_t::GPIO_MODE_OUTPUT + : gpio_mode_t::GPIO_MODE_INPUT; - //bit mask of the pins that you want to set, e.g. GPIO12 + // bit mask of the pins that you want to set, e.g. GPIO12 gpioConfig.pin_bit_mask = (1ULL << gpio); - //set pull-down mode - gpioConfig.pull_down_en = mode == GPIO_PIN_MODE_INPUT_PULLDOWN || (!logicLevelActiveLow && (mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)) ? gpio_pulldown_t::GPIO_PULLDOWN_ENABLE : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE; + // set pull-down mode + gpioConfig.pull_down_en = mode == GPIO_PIN_MODE_INPUT_PULLDOWN || + (!logicLevelActiveLow && + (mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)) + ? gpio_pulldown_t::GPIO_PULLDOWN_ENABLE + : gpio_pulldown_t::GPIO_PULLDOWN_DISABLE; - //set pull-up mode + // set pull-up mode gpioConfig.pull_up_en = mode == GPIO_PIN_MODE_INPUT_PULLUP || (logicLevelActiveLow && (mode == GPIO_PIN_MODE_TRIGGER_CYCLE_START || - mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)) ? gpio_pullup_t::GPIO_PULLUP_ENABLE : gpio_pullup_t::GPIO_PULLUP_DISABLE; + mode == GPIO_PIN_MODE_RESUME_WLAN_CONNECTION)) + ? gpio_pullup_t::GPIO_PULLUP_ENABLE + : gpio_pullup_t::GPIO_PULLUP_DISABLE; - //configure GPIO with the given settings + // configure GPIO with the given settings gpio_config(&gpioConfig); if (gpioConfig.intr_type != GPIO_INTR_DISABLE) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Register ISR handler for GPIO" + std::to_string((int)gpioISR.gpio) + - ", Debounce time: " + std::to_string(gpioISR.debounceTime)); - gpio_isr_handler_add(gpio, gpioPinISRHandler, (void*)&gpioISR); // Hook ISR handler for specific gpio pin + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Register ISR handler for GPIO" + std::to_string((int)gpioISR.gpio) + + ", Debounce time: " + std::to_string(gpioISR.debounceTime)); + gpio_isr_handler_add(gpio, gpioPinISRHandler, (void *)&gpioISR); // Hook ISR handler for specific gpio pin } // Set initial pin state (inputs: read actual pin state, outputs: 0) @@ -132,25 +140,26 @@ void GpioPin::init() #ifdef ENABLE_MQTT if (mqttAccess && (mode == GPIO_PIN_MODE_OUTPUT || mode == GPIO_PIN_MODE_OUTPUT_PWM)) { // Subcribe to [mainTopic]/device/gpio/[GpioName]/ctrl - std::function func = std::bind(&GpioPin::mqttControlPinState, this, std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3); + std::function func = std::bind(&GpioPin::mqttControlPinState, this, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3); registerMqttSubscribeFunction(mqttTopic + "/ctrl", func); } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT } void GpioPin::updatePinState(int _state) { int newState = _state; - if (_state == -1) // If no pin state provided, read pin state + if (_state == -1) { // If no pin state provided, read pin state newState = gpio_get_level(gpio); + } if (newState != pinState) { pinState = newState; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "updatePinState: GPIO" + std::to_string((int)gpio) + - ", State: " + std::to_string(pinState)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "updatePinState: GPIO" + std::to_string((int)gpio) + ", State: " + std::to_string(pinState)); // Handle special modes if ((logicLevelActiveLow && pinState == 0) || (!logicLevelActiveLow && pinState == 1)) { @@ -164,7 +173,7 @@ void GpioPin::updatePinState(int _state) #ifdef ENABLE_MQTT mqttPublishPinState(); -#endif +#endif // ENABLE_MQTT } } @@ -180,7 +189,7 @@ esp_err_t GpioPin::setPinState(bool _value, gpio_set_source _setSource) #ifdef ENABLE_MQTT mqttPublishPinState(); -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT return retVal; } @@ -205,7 +214,7 @@ esp_err_t GpioPin::setPinState(bool _value, int _intensity, gpio_set_source _set #ifdef ENABLE_MQTT mqttPublishPinState(_intensity); -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT return ESP_OK; } @@ -229,12 +238,14 @@ bool GpioPin::mqttPublishPinState(int _pwmDuty) bool retVal = true; - if (cJSON_AddNumberToObject(cJSONObject, "state", pinState) == NULL) + if (cJSON_AddNumberToObject(cJSONObject, "state", pinState) == NULL) { retVal = false; + } if (mode == GPIO_PIN_MODE_OUTPUT_PWM || mode == GPIO_PIN_MODE_FLASHLIGHT_PWM) { - if (cJSON_AddNumberToObject(cJSONObject, "pwm_duty", _pwmDuty) == NULL) + if (cJSON_AddNumberToObject(cJSONObject, "pwm_duty", _pwmDuty) == NULL) { retVal = false; + } } char *jsonChar = NULL; @@ -255,12 +266,12 @@ bool GpioPin::mqttPublishPinState(int _pwmDuty) } -bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len) +bool GpioPin::mqttControlPinState(std::string _topic, char *_data, int _data_len) { - //ESP_LOGI(TAG, "mqttControlPinStateHandler: topic %s, data %.*s", _topic.c_str(), _data_len, _data); - //example: {"state": 1, "pwm_duty": 1024} + // ESP_LOGI(TAG, "mqttControlPinStateHandler: topic %s, data %.*s", _topic.c_str(), _data_len, _data); + // example: {"state": 1, "pwm_duty": 1024} - if (_data_len == 0) { // Check if data length > 0 + if (_data_len == 0) { // Check if data length > 0 LogFile.writeToFile(ESP_LOG_WARN, TAG, "mqttControlPinStateHandler: Handler called, but no data received"); return false; } @@ -269,7 +280,7 @@ bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len cJSON *pinState = cJSON_GetObjectItemCaseSensitive(jsonData, "state"); if (mode == GPIO_PIN_MODE_OUTPUT) { - if (cJSON_IsNumber(pinState)) { // Check if pinState is a number + if (cJSON_IsNumber(pinState)) { // Check if pinState is a number LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "mqttControlPinStateHandler: state: " + std::to_string(pinState->valueint)); esp_err_t retVal = setPinState(pinState->valueint, GPIO_SET_SOURCE_MQTT); if (retVal == ESP_OK) { @@ -277,8 +288,9 @@ bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len return true; } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "mqttControlPinStateHandler: GPIO" + std::to_string((int)gpio) + - " failed to set state | Error: " + intToHexString(retVal)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "mqttControlPinStateHandler: GPIO" + std::to_string((int)gpio) + + " failed to set state | Error: " + intToHexString(retVal)); } } else { @@ -286,19 +298,21 @@ bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len } } else if (mode == GPIO_PIN_MODE_OUTPUT_PWM) { - if (cJSON_IsNumber(pinState)) { // Check if pinState is a number + if (cJSON_IsNumber(pinState)) { // Check if pinState is a number cJSON *pwmDuty = cJSON_GetObjectItemCaseSensitive(jsonData, "pwm_duty"); - if (cJSON_IsNumber(pwmDuty)) { // Check if pwmDuty is a number - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "mqttControlPinStateHandler: state: " + std::to_string(pinState->valueint) + - ", pwm_duty: " + std::to_string(pwmDuty->valueint)); + if (cJSON_IsNumber(pwmDuty)) { // Check if pwmDuty is a number + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "mqttControlPinStateHandler: state: " + std::to_string(pinState->valueint) + + ", pwm_duty: " + std::to_string(pwmDuty->valueint)); esp_err_t retVal = setPinState(pinState->valueint, pwmDuty->valueint, GPIO_SET_SOURCE_MQTT); if (retVal == ESP_OK) { cJSON_Delete(jsonData); return true; } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "mqttControlPinStateHandler: GPIO" + std::to_string((int)gpio) + - " failed to set state | Error: " + intToHexString(retVal)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "mqttControlPinStateHandler: GPIO" + std::to_string((int)gpio) + + " failed to set state | Error: " + intToHexString(retVal)); } } else { @@ -308,7 +322,6 @@ bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len else { LogFile.writeToFile(ESP_LOG_WARN, TAG, "mqttControlPinStateHandler: state not a valid number (\"state\": 1)"); } - } else { LogFile.writeToFile(ESP_LOG_WARN, TAG, "mqttControlPinStateHandler: Wrong pin mode, GPIO cannot be controlled)"); @@ -317,4 +330,4 @@ bool GpioPin::mqttControlPinState(std::string _topic, char* _data, int _data_len cJSON_Delete(jsonData); return false; } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT diff --git a/code/components/gpio_ctrl/gpioPin.h b/code/components/gpio_ctrl/gpioPin.h index 770bdef5f..0b428490a 100644 --- a/code/components/gpio_ctrl/gpioPin.h +++ b/code/components/gpio_ctrl/gpioPin.h @@ -10,26 +10,26 @@ typedef enum { - GPIO_PIN_MODE_DISABLED = 0, - GPIO_PIN_MODE_INPUT = 1, - GPIO_PIN_MODE_INPUT_PULLUP = 2, - GPIO_PIN_MODE_INPUT_PULLDOWN = 3, - GPIO_PIN_MODE_OUTPUT = 4, - GPIO_PIN_MODE_OUTPUT_PWM = 5, - GPIO_PIN_MODE_FLASHLIGHT_PWM = 6, - GPIO_PIN_MODE_FLASHLIGHT_SMARTLED = 7, - GPIO_PIN_MODE_FLASHLIGHT_DIGITAL = 8, - GPIO_PIN_MODE_TRIGGER_CYCLE_START = 9, + GPIO_PIN_MODE_DISABLED = 0, + GPIO_PIN_MODE_INPUT = 1, + GPIO_PIN_MODE_INPUT_PULLUP = 2, + GPIO_PIN_MODE_INPUT_PULLDOWN = 3, + GPIO_PIN_MODE_OUTPUT = 4, + GPIO_PIN_MODE_OUTPUT_PWM = 5, + GPIO_PIN_MODE_FLASHLIGHT_PWM = 6, + GPIO_PIN_MODE_FLASHLIGHT_SMARTLED = 7, + GPIO_PIN_MODE_FLASHLIGHT_DIGITAL = 8, + GPIO_PIN_MODE_TRIGGER_CYCLE_START = 9, GPIO_PIN_MODE_RESUME_WLAN_CONNECTION = 10, - GPIO_PIN_MODE_MAX = 11 + GPIO_PIN_MODE_MAX = 11 } gpio_pin_mode_t; typedef enum { GPIO_SET_SOURCE_INTERNAL = 0, - GPIO_SET_SOURCE_MQTT = 1, - GPIO_SET_SOURCE_HTTP = 2, - GPIO_SET_SOURCE_MAX = 3 + GPIO_SET_SOURCE_MQTT = 1, + GPIO_SET_SOURCE_HTTP = 2, + GPIO_SET_SOURCE_MAX = 3 } gpio_set_source; @@ -47,62 +47,62 @@ struct GpioISR { class GpioPin { - private: - int pinState = -1; - - gpio_num_t gpio; - const char* name; - gpio_pin_mode_t mode; - gpio_int_type_t interruptType; - int frequency; - GpioISR gpioISR; - bool logicLevelActiveLow; - - bool httpAccess = false; - bool mqttAccess = false; - std::string mqttTopic; - - ledc_channel_t ledcChannel = LEDC_CHANNEL_MAX; - SmartLed *smartLed = NULL; - LedType LEDType; - int LEDQuantity; - Rgb LEDColor; - - int intensityCorrection; - - public: - GpioPin(gpio_num_t _gpio, const char* _name, gpio_pin_mode_t _mode, gpio_int_type_t _interruptType, - int _debounceTime, int _frequency, bool _logicLevelActiveLow, bool _httpAccess, bool _mqttAccess, - std::string _mqttTopic, LedType _LEDType, int _LEDQuantity, Rgb _LEDColor, int _intensityCorrection); - ~GpioPin(); - void init(); - - void updatePinState(int state = -1); - esp_err_t setPinState(bool _state, gpio_set_source _setSource = GPIO_SET_SOURCE_INTERNAL); - esp_err_t setPinState(bool _state, int _ledIntensity, gpio_set_source _setSource = GPIO_SET_SOURCE_INTERNAL); - int getPinState(); - - #ifdef ENABLE_MQTT - bool mqttPublishPinState(int _pwmDuty = 0); - bool mqttControlPinState(std::string _topic, char* data, int data_len); - #endif - - gpio_num_t getGPIO() { return gpio; }; - gpio_pin_mode_t getMode() { return mode; }; - bool getLogicLevelActiveLow() { return logicLevelActiveLow; }; - gpio_int_type_t getInterruptType() { return interruptType; }; - int getFrequency() { return frequency; }; - bool getHttpAccess() { return httpAccess; }; - - void setLedcChannel (ledc_channel_t _ledcChannel) { ledcChannel = _ledcChannel; }; - ledc_channel_t getLedcChannel () { return ledcChannel; }; - void setSmartLed(SmartLed* _smartLed) { smartLed = _smartLed; }; - SmartLed* getSmartLed() { return smartLed; }; - LedType getLEDType() { return LEDType; }; - int getLEDQuantity() { return LEDQuantity; }; - Rgb getLEDColor() { return LEDColor; }; - - int getIntensityCorrection() { return intensityCorrection; }; + private: + int pinState = -1; + + gpio_num_t gpio; + const char *name; + gpio_pin_mode_t mode; + gpio_int_type_t interruptType; + int frequency; + GpioISR gpioISR; + bool logicLevelActiveLow; + + bool httpAccess = false; + bool mqttAccess = false; + std::string mqttTopic; + + ledc_channel_t ledcChannel = LEDC_CHANNEL_MAX; + SmartLed *smartLed = NULL; + LedType LEDType; + int LEDQuantity; + Rgb LEDColor; + + int intensityCorrection; + + public: + GpioPin(gpio_num_t _gpio, const char *_name, gpio_pin_mode_t _mode, gpio_int_type_t _interruptType, int _debounceTime, int _frequency, + bool _logicLevelActiveLow, bool _httpAccess, bool _mqttAccess, std::string _mqttTopic, LedType _LEDType, int _LEDQuantity, + Rgb _LEDColor, int _intensityCorrection); + ~GpioPin(); + void init(); + + void updatePinState(int state = -1); + esp_err_t setPinState(bool _state, gpio_set_source _setSource = GPIO_SET_SOURCE_INTERNAL); + esp_err_t setPinState(bool _state, int _ledIntensity, gpio_set_source _setSource = GPIO_SET_SOURCE_INTERNAL); + int getPinState(); + +#ifdef ENABLE_MQTT + bool mqttPublishPinState(int _pwmDuty = 0); + bool mqttControlPinState(std::string _topic, char *data, int data_len); +#endif // ENABLE_MQTT + + gpio_num_t getGPIO() { return gpio; }; + gpio_pin_mode_t getMode() { return mode; }; + bool getLogicLevelActiveLow() { return logicLevelActiveLow; }; + gpio_int_type_t getInterruptType() { return interruptType; }; + int getFrequency() { return frequency; }; + bool getHttpAccess() { return httpAccess; }; + + void setLedcChannel(ledc_channel_t _ledcChannel) { ledcChannel = _ledcChannel; }; + ledc_channel_t getLedcChannel() { return ledcChannel; }; + void setSmartLed(SmartLed *_smartLed) { smartLed = _smartLed; }; + SmartLed *getSmartLed() { return smartLed; }; + LedType getLEDType() { return LEDType; }; + int getLEDQuantity() { return LEDQuantity; }; + Rgb getLEDColor() { return LEDColor; }; + + int getIntensityCorrection() { return intensityCorrection; }; }; -#endif //GPIO_PIN_H +#endif // GPIO_PIN_H diff --git a/code/components/image_manipulation/CAlignAndCutImage.cpp b/code/components/image_manipulation/CAlignAndCutImage.cpp index 87ca8da73..37bf7ac30 100644 --- a/code/components/image_manipulation/CAlignAndCutImage.cpp +++ b/code/components/image_manipulation/CAlignAndCutImage.cpp @@ -11,7 +11,7 @@ #include "helper.h" -static const char* TAG = "IMG_ALIGNCUT"; +static const char *TAG = "IMG_ALIGNCUT"; CAlignAndCutImage::CAlignAndCutImage(std::string _name, CImageBasis *_org, CImageBasis *_temp) : CImageBasis(_name) @@ -36,11 +36,11 @@ int IRAM_ATTR CAlignAndCutImage::alignImage(AlignmentMarker *_temp1, AlignmentMa int r0_x, r0_y, r1_x, r1_y; bool isSimilar1, isSimilar2; - CFindTemplate* ft = new CFindTemplate("align", rgb_image, channels, width, height, bpp); + CFindTemplate *ft = new CFindTemplate("align", rgb_image, channels, width, height, bpp); r0_x = _temp1->targetX; r0_y = _temp1->targetY; - //ESP_LOGD(TAG, "Before ft->findTemplate(_temp1); %s", _temp1->markerImageFilename.c_str()); + // ESP_LOGD(TAG, "Before ft->findTemplate(_temp1); %s", _temp1->markerImageFilename.c_str()); isSimilar1 = ft->findTemplate(_temp1, false); _temp1->width = ft->tpl_width; _temp1->height = ft->tpl_height; @@ -48,7 +48,7 @@ int IRAM_ATTR CAlignAndCutImage::alignImage(AlignmentMarker *_temp1, AlignmentMa r1_x = _temp2->targetX; r1_y = _temp2->targetY; - //ESP_LOGD(TAG, "Before ft->findTemplate(_temp2); %s", _temp2->markerImageFilename.c_str()); + // ESP_LOGD(TAG, "Before ft->findTemplate(_temp2); %s", _temp2->markerImageFilename.c_str()); isSimilar2 = ft->findTemplate(_temp2, !isSimilar1); // disable FAST processing if first ALGO FAST result is -> no match _temp2->width = ft->tpl_width; _temp2->height = ft->tpl_height; @@ -75,44 +75,45 @@ int IRAM_ATTR CAlignAndCutImage::alignImage(AlignmentMarker *_temp1, AlignmentMa angle_deviation = (w_actual - w_org) * 180 / M_PI; - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "Align: dx1 %d, dy1 %d, dx2 %d, dy2 %d, angle dev %f", dx1, dy1, dx2, dy2, angle_deviation); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "Align: dx1 %d, dy1 %d, dx2 %d, dy2 %d, angle dev %f", dx1, dy1, dx2, dy2, angle_deviation); +#endif // DEBUG_DETAIL_ON - if (fabs(angle_deviation) > 45 || abs(dx1) >= _temp1->searchX || abs(dy1) >= _temp1->searchY || - abs(dx2) >= _temp2->searchX || abs(dy2) >= _temp2->searchY) - { + if (fabs(angle_deviation) > 45 || abs(dx1) >= _temp1->searchX || abs(dy1) >= _temp1->searchY || abs(dx2) >= _temp2->searchX || + abs(dy2) >= _temp2->searchY) { _temp1->errorMsg = _temp2->errorMsg = "Angle dev: " + to_stringWithPrecision(angle_deviation, 1) + - ", Ref0dx: " + std::to_string(dx1)+ ", Ref0dy: " + std::to_string(dy1) + - ", Ref1dx: " + std::to_string(dx2)+ ", Ref1dy: " + std::to_string(dy2); + ", Ref0dx: " + std::to_string(dx1) + ", Ref0dy: " + std::to_string(dy1) + + ", Ref1dx: " + std::to_string(dx2) + ", Ref1dy: " + std::to_string(dy2); LogFile.writeToFile(ESP_LOG_ERROR, TAG, _temp1->errorMsg); return -1; // ALIGNMENT FAILED } CRotateImage rt("Align", this, imageTMP); - if ((dx1 > 0 && dx2 > 0 && dy1 > 0 && dy2 > 0) || (dx1 < 0 && dx2 < 0 && dy1 < 0 && dy2 < 0)) { // only move linaer because no rotative motion obviuos + if ((dx1 > 0 && dx2 > 0 && dy1 > 0 && dy2 > 0) || (dx1 < 0 && dx2 < 0 && dy1 < 0 && dy2 < 0)) { // only move linaer because no rotative + // motion obviuos LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Align: Correction by linear dx + dy only"); rt.translateImage(dx1, dy1); } else if ((dx1 > 0 && dx2 > 0) || (dx1 < 0 && dx2 < 0)) { // only rotate + move x direction LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Align: Correction by rotation + linear dx"); - rt.rotateImage(angle_deviation, width/2, height/2); - rt.translateImage(dx1/2, 0); // correct only by half because some correction already happen with rotation + rt.rotateImage(angle_deviation, width / 2, height / 2); + rt.translateImage(dx1 / 2, 0); // correct only by half because some correction already happen with rotation } else if ((dy1 > 0 && dy2 > 0) || (dy1 < 0 && dy2 < 0)) { // only rotate + move y direction LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Align: Correction by rotation + linear dy"); - rt.rotateImage(angle_deviation, width/2, height/2); - rt.translateImage(0, dy1/2); // correct only by half because some correction already happen with rotation + rt.rotateImage(angle_deviation, width / 2, height / 2); + rt.translateImage(0, dy1 / 2); // correct only by half because some correction already happen with rotation } else { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Align: Correction by rotation only"); // only rotate because no obviuos linear motion detected - rt.rotateImage(angle_deviation, width/2, height/2); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Align: Correction by rotation only"); // only rotate because no obviuos linear motion + // detected + rt.rotateImage(angle_deviation, width / 2, height / 2); } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Angle dev: " + to_stringWithPrecision(angle_deviation, 1) + - ", Ref0dx: " + std::to_string(dx1)+ ", Ref0dy: " + std::to_string(dy1) + - ", Ref1dx: " + std::to_string(dx2)+ ", Ref1dy: " + std::to_string(dy2)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Angle dev: " + to_stringWithPrecision(angle_deviation, 1) + ", Ref0dx: " + std::to_string(dx1) + + ", Ref0dy: " + std::to_string(dy1) + ", Ref1dx: " + std::to_string(dx2) + ", Ref1dy: " + std::to_string(dy2)); if (isSimilar1 && isSimilar2) { return 1; // ALGO FAST match @@ -136,10 +137,10 @@ void IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(std::string _template1, int x1 dy = y2 - y1; int memsize = dx * dy * channels; - uint8_t* odata = (unsigned char*) malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - stbi_uc* p_target; - stbi_uc* p_source; + stbi_uc *p_target; + stbi_uc *p_source; rgbImageLock(); @@ -147,16 +148,17 @@ void IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(std::string _template1, int x1 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) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = p_source[_channels]; + } } } - #ifdef STBI_ONLY_JPEG - stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 100); - #else - stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata); - #endif +#ifdef STBI_ONLY_JPEG + stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 100); +#else + stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata); +#endif // STBI_ONLY_JPEG rgbImageRelease(); @@ -181,18 +183,19 @@ void IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx, int dy return; } - uint8_t* odata = _target->rgbImageLock(); + uint8_t *odata = _target->rgbImageLock(); rgbImageLock(); - stbi_uc* p_target; - stbi_uc* p_source; + 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) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = p_source[_channels]; + } } } @@ -201,7 +204,7 @@ void IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx, int dy } -CImageBasis* IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx, int dy) +CImageBasis *IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx, int dy) { int x2, y2; @@ -214,10 +217,10 @@ CImageBasis* IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx dy = y2 - y1; int memsize = dx * dy * channels; - uint8_t* odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - stbi_uc* p_target; - stbi_uc* p_source; + stbi_uc *p_target; + stbi_uc *p_source; rgbImageLock(); @@ -225,12 +228,13 @@ CImageBasis* IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx 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) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = p_source[_channels]; + } } } - CImageBasis* rs = new CImageBasis("CutAndSave", odata, channels, dx, dy, bpp); + CImageBasis *rs = new CImageBasis("CutAndSave", odata, channels, dx, dy, bpp); rgbImageRelease(); rs->setIndepended(); return rs; @@ -239,5 +243,5 @@ CImageBasis* IRAM_ATTR CAlignAndCutImage::cutAndSaveImage(int x1, int y1, int dx CAlignAndCutImage::~CAlignAndCutImage() { - //Nothing to do + // Nothing to do } diff --git a/code/components/image_manipulation/CAlignAndCutImage.h b/code/components/image_manipulation/CAlignAndCutImage.h index 1ed9502bb..2e70405ea 100644 --- a/code/components/image_manipulation/CAlignAndCutImage.h +++ b/code/components/image_manipulation/CAlignAndCutImage.h @@ -7,21 +7,26 @@ class CAlignAndCutImage : public CImageBasis { - public: - CImageBasis *imageTMP; + public: + CImageBasis *imageTMP; - CAlignAndCutImage(std::string name, std::string _image) : CImageBasis(name, _image) {imageTMP = NULL;}; - CAlignAndCutImage(std::string name, std::string _image, bool _externalImage) : - CImageBasis(name, _image, _externalImage) {imageTMP = NULL;}; - CAlignAndCutImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : - CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {imageTMP = NULL;}; - CAlignAndCutImage(std::string name, CImageBasis *_org, CImageBasis *_temp); - ~CAlignAndCutImage(); + CAlignAndCutImage(std::string name, std::string _image) : CImageBasis(name, _image) { imageTMP = NULL; }; + CAlignAndCutImage(std::string name, std::string _image, bool _externalImage) : CImageBasis(name, _image, _externalImage) + { + imageTMP = NULL; + }; + CAlignAndCutImage(std::string name, uint8_t *_rgb_image, int _channels, int _width, int _height, int _bpp) + : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) + { + imageTMP = NULL; + }; + CAlignAndCutImage(std::string name, CImageBasis *_org, CImageBasis *_temp); + ~CAlignAndCutImage(); - int alignImage(AlignmentMarker *_temp1, AlignmentMarker *_temp2); - void cutAndSaveImage(std::string _template1, int x1, int y1, int dx, int dy); - CImageBasis* cutAndSaveImage(int x1, int y1, int dx, int dy); - void cutAndSaveImage(int x1, int y1, int dx, int dy, CImageBasis *_target); + int alignImage(AlignmentMarker *_temp1, AlignmentMarker *_temp2); + void cutAndSaveImage(std::string _template1, int x1, int y1, int dx, int dy); + CImageBasis *cutAndSaveImage(int x1, int y1, int dx, int dy); + void cutAndSaveImage(int x1, int y1, int dx, int dy, CImageBasis *_target); }; -#endif //CALIGNANDCUTIMAGE_H \ No newline at end of file +#endif // CALIGNANDCUTIMAGE_H diff --git a/code/components/image_manipulation/CFindTemplate.cpp b/code/components/image_manipulation/CFindTemplate.cpp index fd4c95b22..e9f59395a 100644 --- a/code/components/image_manipulation/CFindTemplate.cpp +++ b/code/components/image_manipulation/CFindTemplate.cpp @@ -9,7 +9,7 @@ #include "psram.h" -static const char* TAG = "IMG_FINDTEMPL"; +static const char *TAG = "IMG_FINDTEMPL"; bool IRAM_ATTR CFindTemplate::findTemplate(AlignmentMarker *_ref, bool _noFast) @@ -55,19 +55,20 @@ bool IRAM_ATTR CFindTemplate::findTemplate(AlignmentMarker *_ref, bool _noFast) oh = oh_stop - oh_start + 1; if (_ref->alignmentAlgo == ALIGNALGO_FAST && _ref->algoFastX > 0 && _ref->algoFastY > 0 && !_noFast) { - //ESP_LOGD(TAG, "findTemplate - use FASTALGO"); + // ESP_LOGD(TAG, "findTemplate - use FASTALGO"); bool isSimilar = calcSimularities(_ref); - #ifdef DEBUG_DETAIL_ON - std::string zw = "\t" + _ref->markerImageFilename + "\t x_y: \t" + std::to_string(_ref->algoFastX) + "\t" + std::to_string(_ref->algoFastY); - //LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw); - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Fast Algo: " + zw); - #endif +#ifdef DEBUG_DETAIL_ON + std::string zw = "\t" + _ref->markerImageFilename + "\t x_y: \t" + std::to_string(_ref->algoFastX) + "\t" + + std::to_string(_ref->algoFastY); + // LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Fast Algo: " + zw); +#endif // DEBUG_DETAIL_ON if (isSimilar) { _ref->foundX = _ref->algoFastX; _ref->foundY = _ref->algoFastY; - //free_psram_heap(std::string(TAG) + _ref->markerImageFilename, rgb_template); // Keep alignment image markerImage in RAM + // free_psram_heap(std::string(TAG) + _ref->markerImageFilename, rgb_template); // Keep alignment image markerImage in RAM return true; } } @@ -78,22 +79,22 @@ bool IRAM_ATTR CFindTemplate::findTemplate(AlignmentMarker *_ref, bool _noFast) // 0 = "Default" (only R-channel) OR 2 = FAST ALGO (only if already processed but no match) if (_ref->alignmentAlgo == ALIGNALGO_DEFAULT || _ref->alignmentAlgo == ALIGNALGO_FAST) { - //ESP_LOGD(TAG, "findTemplate - DEFAULT - only R channel"); + // ESP_LOGD(TAG, "findTemplate - DEFAULT - only R channel"); _anzchannels = 1; } else { - //ESP_LOGD(TAG, "findTemplate - HIGH ACCURACY - process all channels"); + // ESP_LOGD(TAG, "findTemplate - HIGH ACCURACY - process all channels"); _anzchannels = channels; } - //ESP_LOGD(TAG, "findTemplate - Process STANDARD algo"); + // ESP_LOGD(TAG, "findTemplate - Process STANDARD algo"); for (int xouter = ow_start; xouter <= ow_stop; xouter++) { for (int youter = oh_start; youter <= oh_stop; ++youter) { SADsum = 0; 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 = rgb_image + (channels * ((youter + tpl_y) * width + (xouter + tpl_x))); - stbi_uc* p_tpl = rgb_template + (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)); for (int _ch = 0; _ch < _anzchannels; ++_ch) { SADsum += labs(p_tpl[_ch] - p_org[_ch]); } @@ -113,16 +114,15 @@ bool IRAM_ATTR CFindTemplate::findTemplate(AlignmentMarker *_ref, bool _noFast) _ref->algoFastY = _ref->foundY; // Print results - std::string zw = "SADsum:" + std::to_string(SADsum) + ", X:"+ std::to_string(_ref->foundX) + ", Y:" + std::to_string(_ref->foundY); + std::string zw = "SADsum:" + std::to_string(SADsum) + ", X:" + std::to_string(_ref->foundX) + ", Y:" + std::to_string(_ref->foundY); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "STANDARD Algo results: " + zw); - //free_psram_heap(std::string(TAG) + _ref->markerImageFilename, rgb_template); // Keep alignment image markerImage in RAM + // free_psram_heap(std::string(TAG) + _ref->markerImageFilename, rgb_template); // Keep alignment image markerImage in RAM return false; } - -bool IRAM_ATTR CFindTemplate::calcSimularities(AlignmentMarker* _ref) +bool IRAM_ATTR CFindTemplate::calcSimularities(AlignmentMarker *_ref) { int anz = 0; long SADsum = 0; @@ -130,8 +130,8 @@ bool IRAM_ATTR CFindTemplate::calcSimularities(AlignmentMarker* _ref) for (int xouter = 0; xouter <= tpl_width; xouter++) { for (int youter = 0; youter <= tpl_height; ++youter) { - stbi_uc* p_org = rgb_image + (channels * ((youter + _ref->algoFastY) * width + (xouter + _ref->algoFastX))); - stbi_uc* p_tpl = rgb_template + (channels * (youter * tpl_width + xouter)); + stbi_uc *p_org = rgb_image + (channels * ((youter + _ref->algoFastY) * width + (xouter + _ref->algoFastX))); + stbi_uc *p_tpl = rgb_template + (channels * (youter * tpl_width + xouter)); for (int _ch = 0; _ch < channels; ++_ch) { SADsum += labs(p_tpl[_ch] - p_org[_ch]); anz++; @@ -140,7 +140,7 @@ bool IRAM_ATTR CFindTemplate::calcSimularities(AlignmentMarker* _ref) } // normalize by number of sums - SADNorm = SADsum/anz; + SADNorm = SADsum / anz; // Print results std::string zw = "SADThreshold:" + std::to_string(_ref->algoFastSADThreshold) + ", SADNorm:" + std::to_string(SADNorm) + diff --git a/code/components/image_manipulation/CFindTemplate.h b/code/components/image_manipulation/CFindTemplate.h index 0f700e8be..c0bc3036d 100644 --- a/code/components/image_manipulation/CFindTemplate.h +++ b/code/components/image_manipulation/CFindTemplate.h @@ -7,17 +7,20 @@ class CFindTemplate : public CImageBasis { - private: - uint8_t* rgb_template; - bool calcSimularities(struct AlignmentMarker *_ref); + private: + uint8_t *rgb_template; + bool calcSimularities(struct AlignmentMarker *_ref); - public: - int tpl_width, tpl_height, tpl_bpp; + public: + int tpl_width, tpl_height, tpl_bpp; - CFindTemplate(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) : - CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {rgb_template = NULL;}; + CFindTemplate(std::string name, uint8_t *_rgb_image, int _channels, int _width, int _height, int _bpp) + : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) + { + rgb_template = NULL; + }; - bool findTemplate(struct AlignmentMarker *_ref, bool _noFAST); + bool findTemplate(struct AlignmentMarker *_ref, bool _noFAST); }; -#endif //CFINDTEMPLATE_H \ No newline at end of file +#endif // CFINDTEMPLATE_H diff --git a/code/components/image_manipulation/CImageBasis.cpp b/code/components/image_manipulation/CImageBasis.cpp index 44f3d5e67..d707e68d0 100644 --- a/code/components/image_manipulation/CImageBasis.cpp +++ b/code/components/image_manipulation/CImageBasis.cpp @@ -17,7 +17,7 @@ static const char *TAG = "IMG_BASIS"; -bool jpgFileTooLarge = false; // JPG creation verfication +bool jpgFileTooLarge = false; // JPG creation verfication CImageBasis::~CImageBasis() @@ -25,7 +25,7 @@ CImageBasis::~CImageBasis() rgbImageLock(); if (!externalImage) { - //stbi_image_free(rgb_image); + // stbi_image_free(rgb_image); free_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ", " + std::to_string(memsize) + ")", rgb_image); } @@ -57,13 +57,14 @@ CImageBasis::CImageBasis(std::string _name, CImageBasis *_copyfrom) rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_copyfrom - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_copyfrom - Start"); +#endif // DEBUG_DETAIL_ON memsize = width * height * channels; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_image == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "CImageBasis-Copyfrom: Can't allocate enough memory: " + std::to_string(memsize)); @@ -75,9 +76,9 @@ CImageBasis::CImageBasis(std::string _name, CImageBasis *_copyfrom) memCopy(_copyfrom->rgb_image, rgb_image, memsize); rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_copyfrom - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_copyfrom - done"); +#endif // DEBUG_DETAIL_ON } @@ -93,13 +94,14 @@ CImageBasis::CImageBasis(std::string _name, CImageBasis *_copyfrom, int add) rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_copyfrom - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_copyfrom - Start"); +#endif // DEBUG_DETAIL_ON memsize = (width * height * channels) + add; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_image == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "CImageBasis-Copyfrom: Can't allocate enough memory: " + std::to_string(memsize)); @@ -111,9 +113,9 @@ CImageBasis::CImageBasis(std::string _name, CImageBasis *_copyfrom, int add) memCopy(_copyfrom->rgb_image, rgb_image, memsize); rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_copyfrom - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_copyfrom - done"); +#endif // DEBUG_DETAIL_ON } @@ -129,13 +131,14 @@ CImageBasis::CImageBasis(std::string _name, int _width, int _height, int _channe rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_width,height,ch - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_width,height,ch - Start"); +#endif // DEBUG_DETAIL_ON memsize = width * height * channels; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_image == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "CImageBasis-width,height,ch: Can't allocate enough memory: " + std::to_string(memsize)); @@ -146,9 +149,9 @@ CImageBasis::CImageBasis(std::string _name, int _width, int _height, int _channe rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_width,height,ch - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_width,height,ch - done"); +#endif // DEBUG_DETAIL_ON } @@ -167,9 +170,9 @@ CImageBasis::CImageBasis(std::string _name, std::string _image) rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_image - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_image - Start"); +#endif // DEBUG_DETAIL_ON rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels); @@ -182,15 +185,15 @@ CImageBasis::CImageBasis(std::string _name, std::string _image) rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - std::string zw = "CImageBasis after load " + _image; - ESP_LOGD(TAG, "%s", zw.c_str()); - ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); - #endif +#ifdef DEBUG_DETAIL_ON + std::string zw = "CImageBasis after load " + _image; + ESP_LOGD(TAG, "%s", zw.c_str()); + ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); +#endif // DEBUG_DETAIL_ON - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_image - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_image - done"); +#endif // DEBUG_DETAIL_ON } @@ -209,9 +212,9 @@ CImageBasis::CImageBasis(std::string _name, std::string _image, bool _externalIm rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_image - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_image - Start"); +#endif // DEBUG_DETAIL_ON rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels); @@ -224,19 +227,19 @@ CImageBasis::CImageBasis(std::string _name, std::string _image, bool _externalIm rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - std::string zw = "CImageBasis after load " + _image; - ESP_LOGD(TAG, "%s", zw.c_str()); - ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); - #endif +#ifdef DEBUG_DETAIL_ON + std::string zw = "CImageBasis after load " + _image; + ESP_LOGD(TAG, "%s", zw.c_str()); + ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); +#endif // DEBUG_DETAIL_ON - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis_image - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis_image - done"); +#endif // DEBUG_DETAIL_ON } -CImageBasis::CImageBasis(std::string _name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp) +CImageBasis::CImageBasis(std::string _name, uint8_t *_rgb_image, int _channels, int _width, int _height, int _bpp) { name = _name; islocked = false; @@ -249,16 +252,16 @@ CImageBasis::CImageBasis(std::string _name, uint8_t* _rgb_image, int _channels, } -uint8_t * CImageBasis::rgbImageLock(int _waitmaxsec) +uint8_t *CImageBasis::rgbImageLock(int _waitmaxsec) { if (islocked) { - #ifdef DEBUG_DETAIL_ON - ESP_LOGD(TAG, "Image is locked: sleep for: %ds", _waitmaxsec); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGD(TAG, "Image is locked: sleep for: %ds", _waitmaxsec); +#endif // DEBUG_DETAIL_ON TickType_t xDelay; xDelay = 1000 / portTICK_PERIOD_MS; for (int i = 0; i <= _waitmaxsec; ++i) { - vTaskDelay( xDelay ); + vTaskDelay(xDelay); if (!islocked) { break; } @@ -285,7 +288,7 @@ bool CImageBasis::imageOkay() } -uint8_t * CImageBasis::getRgbImage() +uint8_t *CImageBasis::getRgbImage() { return rgb_image; } @@ -300,13 +303,14 @@ bool CImageBasis::createEmptyImage(int _width, int _height, int _channels) rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("createEmptyImage"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("createEmptyImage"); +#endif // DEBUG_DETAIL_ON memsize = width * height * channels; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_image == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "createEmptyImage: Can't allocate enough memory: " + std::to_string(memsize)); @@ -315,13 +319,14 @@ bool CImageBasis::createEmptyImage(int _width, int _height, int _channels) return false; } - stbi_uc* p_source; + 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; + for (int _channels = 0; _channels < channels; ++_channels) { + p_source[_channels] = (uint8_t)0; + } } } @@ -340,13 +345,14 @@ bool CImageBasis::createEmptyImage(int _width, int _height, int _channels, int a rgbImageLock(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("createEmptyImage"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("createEmptyImage"); +#endif // DEBUG_DETAIL_ON memsize = (width * height * channels) + add; - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (rgb_image == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "createEmptyImage: Can't allocate enough memory: " + std::to_string(memsize)); @@ -355,13 +361,14 @@ bool CImageBasis::createEmptyImage(int _width, int _height, int _channels, int a return false; } - stbi_uc* p_source; + 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; + for (int _channels = 0; _channels < channels; ++_channels) { + p_source[_channels] = (uint8_t)0; + } } } @@ -373,19 +380,20 @@ bool CImageBasis::createEmptyImage(int _width, int _height, int _channels, int a void CImageBasis::emptyImage() { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("emptyImage"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("emptyImage"); +#endif // DEBUG_DETAIL_ON - stbi_uc* p_source; + stbi_uc *p_source; 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) 0; + for (int _channels = 0; _channels < channels; ++_channels) { + p_source[_channels] = (uint8_t)0; + } } } @@ -397,8 +405,8 @@ bool CImageBasis::loadFromMemory(stbi_uc *_buffer, int len) { rgbImageLock(); - if (rgb_image != NULL ) { - //stbi_image_free(rgb_image); + if (rgb_image != NULL) { + // stbi_image_free(rgb_image); free_psram_heap(std::string(TAG) + "->rgb_image (loadFromMemory)", rgb_image); } @@ -460,9 +468,9 @@ bool CImageBasis::loadFromFilePreallocated(std::string _name, std::string _image LogFile.writeToFile(ESP_LOG_ERROR, TAG, "No preallocation found"); } - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis-loadFromFilePreallocated - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis-loadFromFilePreallocated - Start"); +#endif // DEBUG_DETAIL_ON rgb_image = stbi_load(filename.c_str(), &width, &height, &bpp, channels); @@ -475,21 +483,21 @@ bool CImageBasis::loadFromFilePreallocated(std::string _name, std::string _image rgbImageRelease(); - #ifdef DEBUG_DETAIL_ON - std::string zw = "CImageBasis loadFromFilePreallocated after load " + _image; - ESP_LOGI(TAG, "%s", zw.c_str()); - ESP_LOGI(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); - #endif +#ifdef DEBUG_DETAIL_ON + std::string zw = "CImageBasis loadFromFilePreallocated after load " + _image; + ESP_LOGI(TAG, "%s", zw.c_str()); + ESP_LOGI(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels); +#endif // DEBUG_DETAIL_ON - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CImageBasis-loadFromFilePreallocated - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CImageBasis-loadFromFilePreallocated - done"); +#endif // DEBUG_DETAIL_ON return true; } -bool CImageBasis::copyFromMemory(uint8_t* _source, int _size) +bool CImageBasis::copyFromMemory(uint8_t *_source, int _size) { int gr = height * width * channels; if (gr != _size) { // Size does not fit @@ -505,14 +513,15 @@ bool CImageBasis::copyFromMemory(uint8_t* _source, int _size) } -void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size) +void CImageBasis::memCopy(uint8_t *_source, uint8_t *_target, int _size) { #ifdef _ESP32_PSRAM - for (int i = 0; i < _size; ++i) + for (int i = 0; i < _size; ++i) { *(_target + i) = *(_source + i); + } #else memcpy(_target, _source, _size); -#endif +#endif // _ESP32_PSRAM } @@ -522,7 +531,7 @@ void CImageBasis::createNegativeImage(void) for (int i = 0; i < width * height * channels; i += channels) { for (int c = 0; c < channels; c++) { - rgb_image[i+c] = 255 - rgb_image[i+c]; + rgb_image[i + c] = 255 - rgb_image[i + c]; } } @@ -530,11 +539,11 @@ void CImageBasis::createNegativeImage(void) } -void CImageBasis::setContrast(float _contrast) //input range [-100..100] +void CImageBasis::setContrast(float _contrast) // input range [-100..100] { - stbi_uc* p_source; + stbi_uc *p_source; - float contrast = (_contrast/100) + 1; //convert to decimal & shift range: [0..2] + float contrast = (_contrast / 100) + 1; // convert to decimal & shift range: [0..2] float intercept = 128 * (1 - contrast); rgbImageLock(); @@ -542,8 +551,9 @@ void CImageBasis::setContrast(float _contrast) //input range [-100..100] 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))); + for (int _channels = 0; _channels < channels; ++_channels) { + p_source[_channels] = (uint8_t)std::min(255, std::max(0, (int)(p_source[_channels] * contrast + intercept))); + } } } @@ -554,13 +564,14 @@ void CImageBasis::setContrast(float _contrast) //input range [-100..100] void CImageBasis::resizeImage(int _new_dx, int _new_dy) { memsize = _new_dx * _new_dy * channels; - uint8_t* odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + uint8_t *odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); rgbImageLock(); stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels); - rgb_image = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->CImageBasis resizeImage (" + name + ")", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + rgb_image = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->CImageBasis resizeImage (" + name + ")", memsize, + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); memCopy(odata, rgb_image, memsize); width = _new_dx; height = _new_dy; @@ -580,7 +591,7 @@ void CImageBasis::resizeImage(int _new_dx, int _new_dy, CImageBasis *_target) rgbImageLock(); - uint8_t* odata = _target->rgb_image; + uint8_t *odata = _target->rgb_image; stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels); rgbImageRelease(); @@ -593,15 +604,15 @@ void CImageBasis::saveToFile(std::string _imageout) rgbImageLock(); - if ((typ == "jpg") || (typ == "JPG")) { // CAUTION PROBLEMATIC IN ESP32 + if ((typ == "jpg") || (typ == "JPG")) { // CAUTION PROBLEMATIC IN ESP32 stbi_write_jpg(_imageout.c_str(), width, height, channels, rgb_image, 0); } - #ifndef STBI_ONLY_JPEG +#ifndef STBI_ONLY_JPEG if ((typ == "bmp") || (typ == "BMP")) { stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image); } - #endif +#endif // STBI_ONLY_JPEG rgbImageRelease(); } @@ -609,11 +620,11 @@ void CImageBasis::saveToFile(std::string _imageout) void writeJPGHelper(void *context, void *data, int size) { // ESP_LOGD(TAG, "Size all: %d, size %d", ((ImageData*)context)->size, size); - ImageData* _zw = (ImageData*) context; + ImageData *_zw = (ImageData *)context; uint8_t *voidstart = _zw->data; - uint8_t *datastart = (uint8_t*) data; + uint8_t *datastart = (uint8_t *)data; - if ((_zw->size < MAX_JPG_SIZE)) { // Abort copy to prevent buffer overflow + if ((_zw->size < MAX_JPG_SIZE)) { // Abort copy to prevent buffer overflow voidstart += _zw->size; for (int i = 0; i < size; ++i) { @@ -628,9 +639,9 @@ void writeJPGHelper(void *context, void *data, int size) } -ImageData* CImageBasis::writeToMemoryAsJPG(const int quality) +ImageData *CImageBasis::writeToMemoryAsJPG(const int quality) { - ImageData* ii = new ImageData; + ImageData *ii = new ImageData; rgbImageLock(); stbi_write_jpg_to_func(writeJPGHelper, ii, width, height, channels, rgb_image, quality); @@ -638,15 +649,16 @@ ImageData* CImageBasis::writeToMemoryAsJPG(const int quality) if (jpgFileTooLarge) { jpgFileTooLarge = false; - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "writeToMemoryAsJPG: Creation aborted! JPG size > preallocated buffer: " + std::to_string(MAX_JPG_SIZE)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "writeToMemoryAsJPG: Creation aborted! JPG size > preallocated buffer: " + std::to_string(MAX_JPG_SIZE)); } return ii; } -void CImageBasis::writeToMemoryAsJPG(ImageData* i, const int quality) +void CImageBasis::writeToMemoryAsJPG(ImageData *i, const int quality) { - ImageData* ii = new ImageData; + ImageData *ii = new ImageData; rgbImageLock(); stbi_write_jpg_to_func(writeJPGHelper, ii, width, height, channels, rgb_image, quality); @@ -654,15 +666,15 @@ void CImageBasis::writeToMemoryAsJPG(ImageData* i, const int quality) if (jpgFileTooLarge) { jpgFileTooLarge = false; - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "writeToMemoryAsJPG: Creation aborted! JPG size > preallocated buffer: " + std::to_string(MAX_JPG_SIZE)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "writeToMemoryAsJPG: Creation aborted! JPG size > preallocated buffer: " + std::to_string(MAX_JPG_SIZE)); } - memCopy((uint8_t*) ii, (uint8_t*) i, sizeof(ImageData)); + memCopy((uint8_t *)ii, (uint8_t *)i, sizeof(ImageData)); delete ii; } -struct SendJPGHTTP -{ +struct SendJPGHTTP { httpd_req_t *req; esp_err_t res; char buf[HTTP_BUFFER_SENT]; @@ -672,7 +684,7 @@ struct SendJPGHTTP inline void writeJPGToHttpHelper(void *context, void *data, int size) { - SendJPGHTTP* _send = (SendJPGHTTP*) context; + SendJPGHTTP *_send = (SendJPGHTTP *)context; if ((_send->size + size) >= HTTP_BUFFER_SENT) { // data no longer fits in buffer if (httpd_resp_send_chunk(_send->req, _send->buf, _send->size) != ESP_OK) { ESP_LOGE(TAG, "File sending failed"); @@ -680,8 +692,8 @@ inline void writeJPGToHttpHelper(void *context, void *data, int size) } _send->size = 0; } - std::memcpy((void*) (&(_send->buf[0]) + _send->size), data, size); - _send->size+= size; + std::memcpy((void *)(&(_send->buf[0]) + _send->size), data, size); + _send->size += size; } @@ -696,7 +708,7 @@ esp_err_t CImageBasis::sendJPGtoHTTP(httpd_req_t *_req, const int quality) stbi_write_jpg_to_func(writeJPGToHttpHelper, &ii, width, height, channels, rgb_image, quality); if (ii.size > 0) { - if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) { // still send the rest + if (httpd_resp_send_chunk(_req, (char *)ii.buf, ii.size) != ESP_OK) { // still send the rest ESP_LOGE(TAG, "File sending failed"); ii.res = ESP_FAIL; } @@ -710,7 +722,7 @@ esp_err_t CImageBasis::sendJPGtoHTTP(httpd_req_t *_req, const int quality) uint8_t CImageBasis::getPixelColor(int x, int y, int ch) { - stbi_uc* p_source; + stbi_uc *p_source; p_source = rgb_image + (channels * (y * width + x)); return p_source[ch]; } @@ -718,12 +730,12 @@ uint8_t CImageBasis::getPixelColor(int x, int y, int ch) void CImageBasis::setPixelColor(int x, int y, int r, int g, int b) { - stbi_uc* p_source; + stbi_uc *p_source; rgbImageLock(); p_source = rgb_image + (channels * (y * width + x)); p_source[0] = r; - if ( channels > 2) { + if (channels > 2) { p_source[1] = g; p_source[2] = b; } @@ -738,7 +750,7 @@ bool CImageBasis::isInImage(int x, int y) return false; } - if ((y < 0) || (y > height- 1)) { + if ((y < 0) || (y > height - 1)) { return false; } @@ -772,11 +784,15 @@ void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, in 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)) + 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; @@ -814,7 +830,7 @@ void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, { int _x, _y, _thick; int _zwy1, _zwy2; - thickness = (thickness-1) / 2; + thickness = (thickness - 1) / 2; rgbImageLock(); @@ -847,8 +863,9 @@ void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g, int _thick, _x, _y; int rad = radx; - if (rady > radx) + if (rady > radx) { rad = rady; + } deltarad = 1 / (4 * M_PI * (rad + thickness - 1)); diff --git a/code/components/image_manipulation/CRotateImage.cpp b/code/components/image_manipulation/CRotateImage.cpp index ff2d6fc85..4d6955262 100644 --- a/code/components/image_manipulation/CRotateImage.cpp +++ b/code/components/image_manipulation/CRotateImage.cpp @@ -23,19 +23,20 @@ CRotateImage::CRotateImage(std::string _name, CImageBasis *_org, CImageBasis *_t } -void IRAM_ATTR CRotateImage::mirrorImage(){ +void IRAM_ATTR CRotateImage::mirrorImage() +{ int memsize = width * height * channels; - uint8_t* odata; + uint8_t *odata; if (imageTMP) { odata = imageTMP->rgbImageLock(); } else { - odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; + stbi_uc *p_target; + stbi_uc *p_source; rgbImageLock(); @@ -47,15 +48,17 @@ void IRAM_ATTR CRotateImage::mirrorImage(){ y_source = y; p_source = rgb_image + (channels * (y_source * width + x_source)); - for (int _channels = 0; _channels < channels; ++_channels) + 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) + if (!imageTMP) { free_psram_heap(std::string(TAG) + "->odata", odata); + } if (imageTMP) { imageTMP->rgbImageRelease(); @@ -78,8 +81,8 @@ void IRAM_ATTR CRotateImage::rotateImage(float _angle, int _centerx, int _center org_height = height; height = org_width; width = org_height; - x_center = x_center - (org_width/2) + (org_height/2); - y_center = y_center + (org_width/2) - (org_height/2); + x_center = x_center - (org_width / 2) + (org_height / 2); + y_center = y_center + (org_width / 2) - (org_height / 2); if (ImageOrg) { ImageOrg->height = height; ImageOrg->width = width; @@ -99,22 +102,22 @@ void IRAM_ATTR CRotateImage::rotateImage(float _angle, int _centerx, int _center m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center; if (doflip) { - m[0][2] = m[0][2] + (org_width/2) - (org_height/2); - m[1][2] = m[1][2] - (org_width/2) + (org_height/2); + m[0][2] = m[0][2] + (org_width / 2) - (org_height / 2); + m[1][2] = m[1][2] - (org_width / 2) + (org_height / 2); } int memsize = width * height * channels; - uint8_t* odata; + uint8_t *odata; if (imageTMP) { odata = imageTMP->rgbImageLock(); } else { - odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; + stbi_uc *p_target; + stbi_uc *p_source; rgbImageLock(); @@ -130,12 +133,14 @@ void IRAM_ATTR CRotateImage::rotateImage(float _angle, int _centerx, int _center if ((x_source >= 0) && (x_source < org_width) && (y_source >= 0) && (y_source < org_height)) { p_source = rgb_image + (channels * (y_source * org_width + x_source)); - for (int _channels = 0; _channels < channels; ++_channels) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = p_source[_channels]; + } } else { - for (int _channels = 0; _channels < channels; ++_channels) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = 255; + } } } } @@ -154,7 +159,6 @@ void IRAM_ATTR CRotateImage::rotateImage(float _angle, int _centerx, int _center } - void IRAM_ATTR CRotateImage::rotateImageAntiAliasing(float _angle, int _centerx, int _centery) { int org_width, org_height; @@ -169,8 +173,8 @@ void IRAM_ATTR CRotateImage::rotateImageAntiAliasing(float _angle, int _centerx, org_height = height; height = org_width; width = org_height; - x_center = x_center - (org_width/2) + (org_height/2); - y_center = y_center + (org_width/2) - (org_height/2); + x_center = x_center - (org_width / 2) + (org_height / 2); + y_center = y_center + (org_width / 2) - (org_height / 2); if (ImageOrg) { ImageOrg->height = height; ImageOrg->width = width; @@ -190,24 +194,24 @@ void IRAM_ATTR CRotateImage::rotateImageAntiAliasing(float _angle, int _centerx, m[1][2] = m[0][1] * x_center + (1 - m[0][0]) * y_center; if (doflip) { - m[0][2] = m[0][2] + (org_width/2) - (org_height/2); - m[1][2] = m[1][2] - (org_width/2) + (org_height/2); + m[0][2] = m[0][2] + (org_width / 2) - (org_height / 2); + m[1][2] = m[1][2] - (org_width / 2) + (org_height / 2); } int memsize = width * height * channels; - uint8_t* odata; + uint8_t *odata; if (imageTMP) { odata = imageTMP->rgbImageLock(); } else { - odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } int x_source_1, y_source_1, x_source_2, y_source_2; float x_source, y_source; float quad_ul, quad_ur, quad_ol, quad_or; - stbi_uc* p_target; + stbi_uc *p_target; stbi_uc *p_source_ul, *p_source_ur, *p_source_ol, *p_source_or; rgbImageLock(); @@ -228,9 +232,9 @@ void IRAM_ATTR CRotateImage::rotateImageAntiAliasing(float _angle, int _centerx, y_source_2 = y_source_1 + 1; quad_ul = (x_source_2 - x_source) * (y_source_2 - y_source); - quad_ur = (1- (x_source_2 - x_source)) * (y_source_2 - y_source); - quad_or = (x_source_2 - x_source) * (1-(y_source_2 - y_source)); - quad_ol = (1- (x_source_2 - x_source)) * (1-(y_source_2 - y_source)); + quad_ur = (1 - (x_source_2 - x_source)) * (y_source_2 - y_source); + quad_or = (x_source_2 - x_source) * (1 - (y_source_2 - y_source)); + quad_ol = (1 - (x_source_2 - x_source)) * (1 - (y_source_2 - y_source)); if ((x_source_1 >= 0) && (x_source_2 < org_width) && (y_source_1 >= 0) && (y_source_2 < org_height)) { p_source_ul = rgb_image + (channels * (y_source_1 * org_width + x_source_1)); @@ -238,10 +242,8 @@ void IRAM_ATTR CRotateImage::rotateImageAntiAliasing(float _angle, int _centerx, p_source_or = rgb_image + (channels * (y_source_2 * org_width + x_source_1)); p_source_ol = rgb_image + (channels * (y_source_2 * org_width + x_source_2)); for (int _channels = 0; _channels < channels; ++_channels) { - p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul - + (float)p_source_ur[_channels] * quad_ur - + (float)p_source_or[_channels] * quad_or - + (float)p_source_ol[_channels] * quad_ol); + p_target[_channels] = (int)((float)p_source_ul[_channels] * quad_ul + (float)p_source_ur[_channels] * quad_ur + + (float)p_source_or[_channels] * quad_or + (float)p_source_ol[_channels] * quad_ol); } } else { @@ -283,17 +285,17 @@ void CRotateImage::rotateImageAntiAliasing(float _angle) void CRotateImage::translateImage(int _dx, int _dy) { int memsize = width * height * channels; - uint8_t* odata; + uint8_t *odata; if (imageTMP) { odata = imageTMP->rgbImageLock(); } else { - odata = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + odata = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->odata", memsize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); } int x_source, y_source; - stbi_uc* p_target; - stbi_uc* p_source; + stbi_uc *p_target; + stbi_uc *p_source; rgbImageLock(); @@ -306,12 +308,14 @@ void CRotateImage::translateImage(int _dx, int _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) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = p_source[_channels]; + } } else { - for (int _channels = 0; _channels < channels; ++_channels) + for (int _channels = 0; _channels < channels; ++_channels) { p_target[_channels] = 255; + } } } } diff --git a/code/components/image_manipulation/CRotateImage.h b/code/components/image_manipulation/CRotateImage.h index 9ba5e6eb3..0ada65f2e 100644 --- a/code/components/image_manipulation/CRotateImage.h +++ b/code/components/image_manipulation/CRotateImage.h @@ -4,25 +4,34 @@ #include "CImageBasis.h" -class CRotateImage: public CImageBasis +class CRotateImage : public CImageBasis { - public: - CImageBasis *imageTMP, *ImageOrg; - bool doflip; - CRotateImage(std::string name, std::string _image, bool _flip = false) : - CImageBasis(name, _image) {imageTMP = NULL; ImageOrg = NULL; doflip = _flip;}; - CRotateImage(std::string name, uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) : - CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) {imageTMP = NULL; ImageOrg = NULL; doflip = _flip;}; - CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false); + public: + CImageBasis *imageTMP, *ImageOrg; + bool doflip; + CRotateImage(std::string name, std::string _image, bool _flip = false) : CImageBasis(name, _image) + { + imageTMP = NULL; + ImageOrg = NULL; + doflip = _flip; + }; + CRotateImage(std::string name, uint8_t *_rgb_image, int _channels, int _width, int _height, int _bpp, bool _flip = false) + : CImageBasis(name, _rgb_image, _channels, _width, _height, _bpp) + { + imageTMP = NULL; + ImageOrg = NULL; + doflip = _flip; + }; + CRotateImage(std::string name, CImageBasis *_org, CImageBasis *_temp, bool _flip = false); - void rotateImage(float _angle); - void rotateImageAntiAliasing(float _angle); + void rotateImage(float _angle); + void rotateImageAntiAliasing(float _angle); - void rotateImage(float _angle, int _centerx, int _centery); - void rotateImageAntiAliasing(float _angle, int _centerx, int _centery); + void rotateImage(float _angle, int _centerx, int _centery); + void rotateImageAntiAliasing(float _angle, int _centerx, int _centery); - void translateImage(int _dx, int _dy); - void mirrorImage(); + void translateImage(int _dx, int _dy); + void mirrorImage(); }; -#endif //CROTATEIMAGE_H \ No newline at end of file +#endif // CROTATEIMAGE_H diff --git a/code/components/image_manipulation/make_stb.cpp b/code/components/image_manipulation/make_stb.cpp index b5f70a0f7..84fbf6803 100644 --- a/code/components/image_manipulation/make_stb.cpp +++ b/code/components/image_manipulation/make_stb.cpp @@ -6,9 +6,9 @@ #include "psram.h" -#define STBI_MALLOC(sz) malloc_psram_heap_STBI("STBI", sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) -#define STBI_REALLOC(p,newsz) realloc_psram_heap("STBI", p, newsz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) -#define STBI_FREE(p) free_psram_heap("STBI", p) +#define STBI_MALLOC(sz) malloc_psram_heap_STBI("STBI", sz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) +#define STBI_REALLOC(p, newsz) realloc_psram_heap("STBI", p, newsz, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT) +#define STBI_FREE(p) free_psram_heap("STBI", p) #define STB_IMAGE_IMPLEMENTATION #include "stb/stb_image.h" @@ -17,4 +17,4 @@ #include "stb/stb_image_write.h" #define STB_IMAGE_RESIZE_IMPLEMENTATION -#include "stb/stb_image_resize.h" \ No newline at end of file +#include "stb/stb_image_resize.h" diff --git a/code/components/influxdb_ctrl/interface_influxdbv1.cpp b/code/components/influxdb_ctrl/interface_influxdbv1.cpp index c81054282..e832bbc04 100644 --- a/code/components/influxdb_ctrl/interface_influxdbv1.cpp +++ b/code/components/influxdb_ctrl/interface_influxdbv1.cpp @@ -23,20 +23,21 @@ static std::string TLSClientKey; static esp_err_t http_event_handler(esp_http_client_event_t *evt) { - switch(evt->event_id) { + switch (evt->event_id) { case HTTP_EVENT_ERROR: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Error event"); break; case HTTP_EVENT_ON_CONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Connected"); - //ESP_LOGI(TAG, "HTTP Client Connected"); + // ESP_LOGI(TAG, "HTTP Client Connected"); break; case HTTP_EVENT_HEADERS_SENT: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Headers sent"); break; case HTTP_EVENT_ON_HEADER: - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received header: key: " + std::string(evt->header_key) + - " | value: " + std::string(evt->header_value)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "HTTP client: Received header: key: " + std::string(evt->header_key) + + " | value: " + std::string(evt->header_value)); break; case HTTP_EVENT_ON_DATA: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received data: length:" + std::to_string(evt->data_len)); @@ -44,7 +45,7 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_FINISH: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Session finished"); break; - case HTTP_EVENT_DISCONNECTED: + case HTTP_EVENT_DISCONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Disconnected"); break; case HTTP_EVENT_REDIRECT: @@ -60,7 +61,7 @@ bool influxDBv1Init(const CfgData::SectionInfluxDBv1 *_cfgDataPtr) cfgDataPtr = _cfgDataPtr; if (cfgDataPtr->authMode == AUTH_TLS) { - if (cfgDataPtr->uri.substr(0,8) != "https://") { + if (cfgDataPtr->uri.substr(0, 8) != "https://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "TLS: URI parameter needs to be configured with \'https://\'"); return false; } @@ -96,7 +97,7 @@ bool influxDBv1Init(const CfgData::SectionInfluxDBv1 *_cfgDataPtr) } } else { - if (cfgDataPtr->uri.substr(0,7) != "http://") { + if (cfgDataPtr->uri.substr(0, 7) != "http://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "URI parameter needs to be configured with \'http://\'"); return false; } @@ -106,13 +107,14 @@ bool influxDBv1Init(const CfgData::SectionInfluxDBv1 *_cfgDataPtr) } -esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, const std::string &_timestamp) +esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, + const std::string &_timestamp) { esp_http_client_config_t httpConfig = { - .user_agent = "AI-on-the-Edge Device", - .method = HTTP_METHOD_POST, - .event_handler = http_event_handler, - .buffer_size = MAX_HTTP_OUTPUT_BUFFER + .user_agent = "AI-on-the-Edge Device", + .method = HTTP_METHOD_POST, + .event_handler = http_event_handler, + .buffer_size = MAX_HTTP_OUTPUT_BUFFER // Receive buffer }; if (cfgDataPtr->authMode == AUTH_BASIC) { @@ -129,7 +131,7 @@ esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string & if (!TLSCACert.empty()) { httpConfig.cert_pem = TLSCACert.c_str(); httpConfig.cert_len = TLSCACert.length() + 1; - httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field + httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CA Certificate empty, use certification bundle for server verification"); @@ -147,8 +149,9 @@ esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string & } } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "influxDBv1Publish: field key 1: " + _fieldkey1 + ", field value 1: " + - _fieldvalue1 + ", timestamp: " + _timestamp); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "influxDBv1Publish: field key 1: " + _fieldkey1 + ", field value 1: " + _fieldvalue1 + + ", timestamp: " + _timestamp); esp_err_t retVal = ESP_OK; std::string payload; @@ -165,7 +168,7 @@ esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string & t = mktime(&tm); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Timestamp: " + _timestamp + ", Timestamp (UTC): " + std::to_string(t)); - sprintf(nowTimestamp,"%ld000000000", (long) t); // UTC + sprintf(nowTimestamp, "%ld000000000", (long)t); // UTC payload = _measurement + " " + _fieldkey1 + "=" + _fieldvalue1 + " " + nowTimestamp; } else { @@ -190,10 +193,10 @@ esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string & LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Initialized"); esp_http_client_set_header(httpClient, "Content-Type", "text/plain"); - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Header setting done"); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Header setting done"); ESP_ERROR_CHECK(esp_http_client_set_post_field(httpClient, payload.c_str(), payload.length())); - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Payload post completed"); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Payload post completed"); retVal = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(httpClient)); @@ -217,10 +220,11 @@ esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string & bool getInfluxDBv1isEncrypted() { - if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) + if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) { return true; + } return false; } -#endif //ENABLE_INFLUXDB +#endif // ENABLE_INFLUXDB diff --git a/code/components/influxdb_ctrl/interface_influxdbv1.h b/code/components/influxdb_ctrl/interface_influxdbv1.h index 11f252abc..b2e7c061b 100644 --- a/code/components/influxdb_ctrl/interface_influxdbv1.h +++ b/code/components/influxdb_ctrl/interface_influxdbv1.h @@ -9,9 +9,9 @@ #include "configClass.h" bool influxDBv1Init(const CfgData::SectionInfluxDBv1 *_cfgDataPtr); -esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string &_fieldkey1, - const std::string &_fieldvalue1, const std::string &_timestamp); +esp_err_t influxDBv1Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, + const std::string &_timestamp); bool getInfluxDBv1isEncrypted(); -#endif //INTERFACE_INFLUXDBV1_H -#endif //ENABLE_INFLUXDB \ No newline at end of file +#endif // INTERFACE_INFLUXDBV1_H +#endif // ENABLE_INFLUXDB diff --git a/code/components/influxdb_ctrl/interface_influxdbv2.cpp b/code/components/influxdb_ctrl/interface_influxdbv2.cpp index 6d676c7b3..c9039ce31 100644 --- a/code/components/influxdb_ctrl/interface_influxdbv2.cpp +++ b/code/components/influxdb_ctrl/interface_influxdbv2.cpp @@ -23,20 +23,21 @@ static std::string TLSClientKey; static esp_err_t http_event_handler(esp_http_client_event_t *evt) { - switch(evt->event_id) { + switch (evt->event_id) { case HTTP_EVENT_ERROR: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Error event"); break; case HTTP_EVENT_ON_CONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Connected"); - //ESP_LOGI(TAG, "HTTP Client Connected"); + // ESP_LOGI(TAG, "HTTP Client Connected"); break; case HTTP_EVENT_HEADERS_SENT: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Headers sent"); break; case HTTP_EVENT_ON_HEADER: - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received header: key: " + std::string(evt->header_key) + - " | value: " + std::string(evt->header_value)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "HTTP client: Received header: key: " + std::string(evt->header_key) + + " | value: " + std::string(evt->header_value)); break; case HTTP_EVENT_ON_DATA: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received data: length:" + std::to_string(evt->data_len)); @@ -44,7 +45,7 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_FINISH: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Session finished"); break; - case HTTP_EVENT_DISCONNECTED: + case HTTP_EVENT_DISCONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Disconnected"); break; case HTTP_EVENT_REDIRECT: @@ -60,7 +61,7 @@ bool influxDBv2Init(const CfgData::SectionInfluxDBv2 *_cfgDataPtr) cfgDataPtr = _cfgDataPtr; if (cfgDataPtr->authMode == AUTH_TLS) { - if (cfgDataPtr->uri.substr(0,8) != "https://") { + if (cfgDataPtr->uri.substr(0, 8) != "https://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "TLS: URI parameter needs to be configured with \'https://\'"); return false; } @@ -96,7 +97,7 @@ bool influxDBv2Init(const CfgData::SectionInfluxDBv2 *_cfgDataPtr) } } else { - if (cfgDataPtr->uri.substr(0,7) != "http://") { + if (cfgDataPtr->uri.substr(0, 7) != "http://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "URI parameter needs to be configured with \'http://\'"); return false; } @@ -106,20 +107,21 @@ bool influxDBv2Init(const CfgData::SectionInfluxDBv2 *_cfgDataPtr) } -esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, const std::string &_timestamp) +esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, + const std::string &_timestamp) { esp_http_client_config_t httpConfig = { - .user_agent = "AI-on-the-Edge Device", - .method = HTTP_METHOD_POST, - .event_handler = http_event_handler, - .buffer_size = MAX_HTTP_OUTPUT_BUFFER + .user_agent = "AI-on-the-Edge Device", + .method = HTTP_METHOD_POST, + .event_handler = http_event_handler, + .buffer_size = MAX_HTTP_OUTPUT_BUFFER // Receive buffer }; if (cfgDataPtr->authMode == AUTH_TLS) { if (!TLSCACert.empty()) { httpConfig.cert_pem = TLSCACert.c_str(); httpConfig.cert_len = TLSCACert.length() + 1; - httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field + httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CA Certificate empty, use certification bundle for server verification"); @@ -137,8 +139,9 @@ esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string & } } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "influxDBv2Publish: field key 1: " + _fieldkey1 + ", field value 1: " + - _fieldvalue1 + ", Timestamp: " + _timestamp); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "influxDBv2Publish: field key 1: " + _fieldkey1 + ", field value 1: " + _fieldvalue1 + + ", Timestamp: " + _timestamp); esp_err_t retVal = ESP_OK; std::string payload; @@ -155,7 +158,7 @@ esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string & t = mktime(&tm); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Timestamp: " + _timestamp + ", Timestamp (UTC): " + std::to_string(t)); - sprintf(nowTimestamp,"%ld000000000", (long) t); // UTC + sprintf(nowTimestamp, "%ld000000000", (long)t); // UTC payload = _measurement + " " + _fieldkey1 + "=" + _fieldvalue1 + " " + nowTimestamp; } else { @@ -180,12 +183,12 @@ esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string & esp_http_client_set_header(httpClient, "Content-Type", "text/plain"); std::string authString = "Token " + cfgDataPtr->token; - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Tokenheader: %s\n", _zw.c_str()); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Tokenheader: %s\n", _zw.c_str()); esp_http_client_set_header(httpClient, "Authorization", authString.c_str()); - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Header setting done"); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Header setting done"); ESP_ERROR_CHECK(esp_http_client_set_post_field(httpClient, payload.c_str(), payload.length())); - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Payload post completed"); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Payload post completed"); retVal = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(httpClient)); @@ -209,10 +212,11 @@ esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string & bool getInfluxDBv2isEncrypted() { - if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) + if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) { return true; + } return false; } -#endif //ENABLE_INFLUXDB +#endif // ENABLE_INFLUXDB diff --git a/code/components/influxdb_ctrl/interface_influxdbv2.h b/code/components/influxdb_ctrl/interface_influxdbv2.h index 9d4926c87..788b5f730 100644 --- a/code/components/influxdb_ctrl/interface_influxdbv2.h +++ b/code/components/influxdb_ctrl/interface_influxdbv2.h @@ -9,9 +9,9 @@ #include "configClass.h" bool influxDBv2Init(const CfgData::SectionInfluxDBv2 *_cfgDataPtr); -esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string &_fieldkey1, - const std::string &_fieldvalue1, const std::string &_timestamp); +esp_err_t influxDBv2Publish(const std::string &_measurement, const std::string &_fieldkey1, const std::string &_fieldvalue1, + const std::string &_timestamp); bool getInfluxDBv2isEncrypted(); -#endif //INTERFACE_INFLUXDBV2_H -#endif //ENABLE_INFLUXDB \ No newline at end of file +#endif // INTERFACE_INFLUXDBV2_H +#endif // ENABLE_INFLUXDB diff --git a/code/components/logfile_handling/ClassLogFile.cpp b/code/components/logfile_handling/ClassLogFile.cpp index 690eb67bf..16c72ef46 100644 --- a/code/components/logfile_handling/ClassLogFile.cpp +++ b/code/components/logfile_handling/ClassLogFile.cpp @@ -22,14 +22,12 @@ extern "C" { static const char *TAG = "LOGFILE"; -ClassLogFile LogFile(LOG_LOGS_ROOT_FOLDER, LOG_FILE_TIME_FORMAT, - LOG_DATA_ROOT_FOLDER, DATA_FILE_TIME_FORMAT, - LOG_DEBUG_ROOT_FOLDER, DEBUG_FOLDER_TIME_FORMAT); +ClassLogFile LogFile(LOG_LOGS_ROOT_FOLDER, LOG_FILE_TIME_FORMAT, LOG_DATA_ROOT_FOLDER, DATA_FILE_TIME_FORMAT, LOG_DEBUG_ROOT_FOLDER, + DEBUG_FOLDER_TIME_FORMAT); - -ClassLogFile::ClassLogFile(std::string _logFileRootFolder, std::string _logfile, std::string _dataFileRootFolder, - std::string _datafile, std::string _debugFileRootFolder, std::string _debugfolder) +ClassLogFile::ClassLogFile(std::string _logFileRootFolder, std::string _logfile, std::string _dataFileRootFolder, std::string _datafile, + std::string _debugFileRootFolder, std::string _debugfolder) { logFileRootFolder = _logFileRootFolder; logfile = _logfile; @@ -48,14 +46,14 @@ ClassLogFile::ClassLogFile(std::string _logFileRootFolder, std::string _logfile, void ClassLogFile::writeHeapInfo(std::string _id) { if (loglevel >= ESP_LOG_DEBUG) { - std::string _zw = _id + "\t" + getESPHeapInfo(); + std::string _zw = _id + "\t" + getESPHeapInfo(); writeToFile(ESP_LOG_DEBUG, "HEAP", _zw); } } -void ClassLogFile::writeToData(std::string _timestamp, std::string _name, std::string _sRawValue, std::string _sValue, - std::string _sFallbackValue, std::string _sRatePerMin, std::string _sRatePerInterval, +void ClassLogFile::writeToData(std::string _timestamp, std::string _name, std::string _sRawValue, std::string _sValue, + std::string _sFallbackValue, std::string _sRatePerMin, std::string _sRatePerInterval, std::string _sValueStatus, std::string _digital, std::string _analog) { time_t rawtime; @@ -63,10 +61,10 @@ void ClassLogFile::writeToData(std::string _timestamp, std::string _name, std::s time(&rawtime); std::string logpath = dataFileRootFolder + "/" + convertTimeToString(rawtime, datafile.c_str()); - FILE* pFile; + FILE *pFile; std::string zwtime; - //ESP_LOGD(TAG, "Datalogfile: %s", logpath.c_str()); + // ESP_LOGD(TAG, "Datalogfile: %s", logpath.c_str()); pFile = fopen(logpath.c_str(), "a+"); if (pFile == NULL) { @@ -106,7 +104,7 @@ void ClassLogFile::setLogLevel(esp_log_level_t _logLevel) std::string levelText; // Print log level to log file - switch(_logLevel) { + switch (_logLevel) { case ESP_LOG_WARN: levelText = "WARNING"; break; @@ -168,13 +166,14 @@ bool ClassLogFile::getDataLogToSDStatus() } -static FILE* logFileAppendHandle = NULL; +static FILE *logFileAppendHandle = NULL; std::string fileNameDate; void ClassLogFile::writeToFile(esp_log_level_t level, std::string tag, std::string message, bool _time) { - if (level > loglevel)// Skip logging if defined message loglevel is more verbose than configured threshold loglevel + if (level > loglevel) { // Skip logging if defined message loglevel is more verbose than configured threshold loglevel return; + } std::string fileNameDateNew; std::string zwtime; @@ -200,54 +199,54 @@ void ClassLogFile::writeToFile(esp_log_level_t level, std::string tag, std::stri } std::string loglevelString; - switch(level) { - case ESP_LOG_ERROR: + switch (level) { + case ESP_LOG_ERROR: loglevelString = "ERR"; break; - case ESP_LOG_WARN: + case ESP_LOG_WARN: loglevelString = "WRN"; break; - case ESP_LOG_INFO: + case ESP_LOG_INFO: loglevelString = "INF"; break; - case ESP_LOG_DEBUG: + case ESP_LOG_DEBUG: loglevelString = "DBG"; break; - case ESP_LOG_VERBOSE: + case ESP_LOG_VERBOSE: loglevelString = "VER"; break; - case ESP_LOG_NONE: + case ESP_LOG_NONE: default: loglevelString = "NONE"; break; } - std::string fullmessage = "[" + getFormatedUptime(true) + "] " + ntpTime + "\t<" + loglevelString + ">\t" + message + "\n"; - + std::string fullmessage = "[" + getFormatedUptime(true) + "] " + ntpTime + "\t<" + loglevelString + ">\t" + message + "\n"; - #ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING - if (fileNameDateNew != fileNameDate) { // Filename changed - // Make sure each day gets its own logfile - // Also we need to re-open it in case it needed to get closed for reading - std::string logpath = logFileRootFolder + "/" + fileNameDateNew; - ESP_LOGI(TAG, "Opening logfile %s for appending", logpath.c_str()); - logFileAppendHandle = fopen(logpath.c_str(), "a"); - if (logFileAppendHandle==NULL) { - ESP_LOGE(TAG, "writeToFile: Failed to open logfile %s", logpath.c_str()); - return; - } - - fileNameDate = fileNameDateNew; - } - #else +#ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING + if (fileNameDateNew != fileNameDate) { // Filename changed + // Make sure each day gets its own logfile + // Also we need to re-open it in case it needed to get closed for reading std::string logpath = logFileRootFolder + "/" + fileNameDateNew; + + ESP_LOGI(TAG, "Opening logfile %s for appending", logpath.c_str()); logFileAppendHandle = fopen(logpath.c_str(), "a"); if (logFileAppendHandle == NULL) { ESP_LOGE(TAG, "writeToFile: Failed to open logfile %s", logpath.c_str()); return; } - #endif + + fileNameDate = fileNameDateNew; + } +#else + std::string logpath = logFileRootFolder + "/" + fileNameDateNew; + logFileAppendHandle = fopen(logpath.c_str(), "a"); + if (logFileAppendHandle == NULL) { + ESP_LOGE(TAG, "writeToFile: Failed to open logfile %s", logpath.c_str()); + return; + } +#endif // KEEP_LOGFILE_OPEN_FOR_APPENDING /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ // Set buffer to SD card allocation size of 512 byte (newlib default: 128 byte) -> reduce system read/write calls @@ -255,12 +254,12 @@ void ClassLogFile::writeToFile(esp_log_level_t level, std::string tag, std::stri fputs(fullmessage.c_str(), logFileAppendHandle); - #ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING - fflush(logFileAppendHandle); - fsync(fileno(logFileAppendHandle)); - #else - closeLogFileAppendHandle(); - #endif +#ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING + fflush(logFileAppendHandle); + fsync(fileno(logFileAppendHandle)); +#else + closeLogFileAppendHandle(); +#endif // KEEP_LOGFILE_OPEN_FOR_APPENDING } @@ -319,9 +318,9 @@ void ClassLogFile::removeOldLogFile() time_t rawtime; time(&rawtime); rawtime = addDays(rawtime, -logFileRetentionInDays + 1); - //ESP_LOGI(TAG, "logFileRetentionInDays: %d", logFileRetentionInDays); + // ESP_LOGI(TAG, "logFileRetentionInDays: %d", logFileRetentionInDays); std::string cmpfilename = convertTimeToString(rawtime, logfile.c_str()); - //ESP_LOGI(TAG, "log file name to compare: %s", cmpfilename.c_str()); + // ESP_LOGI(TAG, "log file name to compare: %s", cmpfilename.c_str()); struct dirent *entry; int deleted = 0; @@ -329,9 +328,9 @@ void ClassLogFile::removeOldLogFile() while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_REG) { - //ESP_LOGI(TAG, "compare log file: %s to %s", entry->d_name, cmpfilename.c_str()); + // ESP_LOGI(TAG, "compare log file: %s to %s", entry->d_name, cmpfilename.c_str()); if ((strlen(entry->d_name) == cmpfilename.length()) && (strcmp(entry->d_name, cmpfilename.c_str()) < 0)) { - //ESP_LOGI(TAG, "delete log file: %s", entry->d_name); + // ESP_LOGI(TAG, "delete log file: %s", entry->d_name); std::string filepath = logFileRootFolder + "/" + entry->d_name; // keep logfile log_1970-01-01.txt if time was not set at boot (some boot logs are in there) if ((strcmp(entry->d_name, "log_1970-01-01.txt") == 0) && getTimeWasNotSetAtBoot()) { @@ -377,9 +376,9 @@ void ClassLogFile::removeOldDataLog() time_t rawtime; time(&rawtime); rawtime = addDays(rawtime, -dataLogRetentionInDays + 1); - //ESP_LOGI(TAG, "dataLogRetentionInDays: %d", dataLogRetentionInDays); + // ESP_LOGI(TAG, "dataLogRetentionInDays: %d", dataLogRetentionInDays); std::string cmpfilename = convertTimeToString(rawtime, datafile.c_str()); - //ESP_LOGI(TAG, "data file name to compare: %s", cmpfilename.c_str()); + // ESP_LOGI(TAG, "data file name to compare: %s", cmpfilename.c_str()); struct dirent *entry; int deleted = 0; @@ -387,20 +386,20 @@ void ClassLogFile::removeOldDataLog() while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_REG) { - //ESP_LOGI(TAG, "Compare data file: %s to %s", entry->d_name, cmpfilename.c_str()); + // ESP_LOGI(TAG, "Compare data file: %s to %s", entry->d_name, cmpfilename.c_str()); if ((strlen(entry->d_name) == cmpfilename.length()) && (strcmp(entry->d_name, cmpfilename.c_str()) < 0)) { - //ESP_LOGI(TAG, "delete data file: %s", entry->d_name); + // ESP_LOGI(TAG, "delete data file: %s", entry->d_name); std::string filepath = dataFileRootFolder + "/" + entry->d_name; if (unlink(filepath.c_str()) == 0) { - deleted ++; + deleted++; } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete file " + filepath); - notDeleted ++; + notDeleted++; } } else { - notDeleted ++; + notDeleted++; } } } @@ -428,9 +427,9 @@ void ClassLogFile::removeOldDebugFiles() time_t rawtime; time(&rawtime); rawtime = addDays(rawtime, -debugFilesRetentionInDays + 1); - //ESP_LOGI(TAG, "debugFilesRetentionInDays: %d", debugFilesRetentionInDays); + // ESP_LOGI(TAG, "debugFilesRetentionInDays: %d", debugFilesRetentionInDays); std::string cmpfolderame = convertTimeToString(rawtime, debugfolder.c_str()); - //ESP_LOGI(TAG, "Delete all folder older than %s", cmpfolderame.c_str()); + // ESP_LOGI(TAG, "Delete all folder older than %s", cmpfolderame.c_str()); struct dirent *entry; int deleted = 0; @@ -438,27 +437,28 @@ void ClassLogFile::removeOldDebugFiles() while ((entry = readdir(dir)) != NULL) { if (entry->d_type == DT_DIR) { - //ESP_LOGI(TAG, "Compare folder %s to %s", entry->d_name, cmpfolderame.c_str()); + // ESP_LOGI(TAG, "Compare folder %s to %s", entry->d_name, cmpfolderame.c_str()); if ((strlen(entry->d_name) == cmpfolderame.length()) && (strcmp(entry->d_name, cmpfolderame.c_str()) < 0)) { std::string folderpath = debugFileRootFolder + "/" + entry->d_name; - //ESP_LOGI(TAG, "Delete folder %s", folderpath.c_str()); + // ESP_LOGI(TAG, "Delete folder %s", folderpath.c_str()); if (removeFolder(folderpath.c_str(), TAG) > 0) { deleted++; } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete folder " + folderpath); - notDeleted ++; + notDeleted++; } } else { - notDeleted ++; + notDeleted++; } } } closedir(dir); - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Folders deleted: " + std::to_string(deleted) + " | Folders kept: " + std::to_string(notDeleted)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Folders deleted: " + std::to_string(deleted) + " | Folders kept: " + std::to_string(notDeleted)); } diff --git a/code/components/logfile_handling/ClassLogFile.h b/code/components/logfile_handling/ClassLogFile.h index 607dac7c6..6072395ed 100644 --- a/code/components/logfile_handling/ClassLogFile.h +++ b/code/components/logfile_handling/ClassLogFile.h @@ -9,52 +9,52 @@ class ClassLogFile { - private: - std::string logFileRootFolder; - std::string logfile; - std::string dataFileRootFolder; - std::string datafile; - std::string debugFileRootFolder; - std::string debugfolder; - int logFileRetentionInDays; - int dataLogRetentionInDays; - int debugFilesRetentionInDays; - bool dataLogToSDEnabled; - esp_log_level_t loglevel; - - - public: - ClassLogFile(std::string _logFileRootFolder, std::string _logfile, std::string _dataFileRootFolder, - std::string _datafile, std::string _debugFileRootFolder, std::string debugfolder); - - void writeHeapInfo(std::string _id); - - void setLogLevel(esp_log_level_t _logLevel); - void setLogFileRetention(int _LogFileRetentionInDays); - void setDataLogRetention(int _DataLogRetentionInDays); - void setDebugFilesRetention(int _DebugFilesRetentionInDays); - void enableDataLogToSD(bool _dataLogToSDEnabled); - bool getDataLogToSDStatus(); - - void writeToFile(esp_log_level_t level, std::string tag, std::string message, bool _time); - void writeToFile(esp_log_level_t level, std::string tag, std::string message); - - void closeLogFileAppendHandle(); - - bool createLogDirectories(); - void removeOldLogFile(); - void removeOldDataLog(); - void removeOldDebugFiles(); - - void writeToData(std::string _timestamp, std::string _name, std::string _sRawValue, std::string _sValue, - std::string _sFallbackValue, std::string _sRatePerMin, std::string _sRatePerInterval, - std::string _sValueStatus, std::string _digital, std::string _analog); - - - std::string getCurrentFileName(); - std::string getCurrentFileNameData(); + private: + std::string logFileRootFolder; + std::string logfile; + std::string dataFileRootFolder; + std::string datafile; + std::string debugFileRootFolder; + std::string debugfolder; + int logFileRetentionInDays; + int dataLogRetentionInDays; + int debugFilesRetentionInDays; + bool dataLogToSDEnabled; + esp_log_level_t loglevel; + + + public: + ClassLogFile(std::string _logFileRootFolder, std::string _logfile, std::string _dataFileRootFolder, std::string _datafile, + std::string _debugFileRootFolder, std::string debugfolder); + + void writeHeapInfo(std::string _id); + + void setLogLevel(esp_log_level_t _logLevel); + void setLogFileRetention(int _LogFileRetentionInDays); + void setDataLogRetention(int _DataLogRetentionInDays); + void setDebugFilesRetention(int _DebugFilesRetentionInDays); + void enableDataLogToSD(bool _dataLogToSDEnabled); + bool getDataLogToSDStatus(); + + void writeToFile(esp_log_level_t level, std::string tag, std::string message, bool _time); + void writeToFile(esp_log_level_t level, std::string tag, std::string message); + + void closeLogFileAppendHandle(); + + bool createLogDirectories(); + void removeOldLogFile(); + void removeOldDataLog(); + void removeOldDebugFiles(); + + void writeToData(std::string _timestamp, std::string _name, std::string _sRawValue, std::string _sValue, std::string _sFallbackValue, + std::string _sRatePerMin, std::string _sRatePerInterval, std::string _sValueStatus, std::string _digital, + std::string _analog); + + + std::string getCurrentFileName(); + std::string getCurrentFileNameData(); }; extern ClassLogFile LogFile; -#endif //CLASSLOGFILE_H \ No newline at end of file +#endif // CLASSLOGFILE_H diff --git a/code/components/mainprocess_ctrl/ClassFlow.cpp b/code/components/mainprocess_ctrl/ClassFlow.cpp index 120ef5202..bc38072c1 100644 --- a/code/components/mainprocess_ctrl/ClassFlow.cpp +++ b/code/components/mainprocess_ctrl/ClassFlow.cpp @@ -9,60 +9,61 @@ static const char *TAG = "CLASSFLOW"; ClassFlow::ClassFlow(void) { - // Handled in derived classes + // Handled in derived classes } ClassFlow::ClassFlow(void *) { - // Handled in derived classes + // Handled in derived classes } bool ClassFlow::loadParameter() { - // Handled in derived classes - return true; + // Handled in derived classes + return true; } bool ClassFlow::doFlow(std::string time) { - // Handled in derived classes - return true; + // Handled in derived classes + return true; } void ClassFlow::doPostProcessEventHandling() { - // Handled in derived classes + // Handled in derived classes } void ClassFlow::presetFlowStateHandler(bool _init, std::string _time) { FlowState.ClassName = name(); - FlowState.ExecutionTime = _time; + FlowState.ExecutionTime = _time; FlowState.isSuccessful = true; - FlowState.EventCode.clear(); - FlowState.EventCode.shrink_to_fit(); - - - if (_init) - FlowState.getExecuted = false; - else - FlowState.getExecuted = true; + FlowState.EventCode.clear(); + FlowState.EventCode.shrink_to_fit(); + + if (_init) { + FlowState.getExecuted = false; + } + else { + FlowState.getExecuted = true; + } } void ClassFlow::setFlowStateHandlerEvent(int _eventCode) { - FlowState.isSuccessful = false; - FlowState.EventCode.push_back(_eventCode); // negative event code -> error; positive event code -> warning + FlowState.isSuccessful = false; + FlowState.EventCode.push_back(_eventCode); // negative event code -> error; positive event code -> warning } -struct strFlowState* ClassFlow::getFlowState() +struct strFlowState *ClassFlow::getFlowState() { - return &FlowState; + return &FlowState; } diff --git a/code/components/mainprocess_ctrl/ClassFlow.h b/code/components/mainprocess_ctrl/ClassFlow.h index 88d3f6cf4..18779b1c9 100644 --- a/code/components/mainprocess_ctrl/ClassFlow.h +++ b/code/components/mainprocess_ctrl/ClassFlow.h @@ -5,40 +5,37 @@ #include #include "ClassFlowDefineTypes.h" -//#include "helper.h" -//#include "CImageBasis.h" -struct strFlowState -{ - std::string ClassName = ""; - std::string ExecutionTime = ""; - bool getExecuted = false; - bool isSuccessful = true; - std::vector EventCode; // negative event code -> error; positive event code -> warning +struct strFlowState { + std::string ClassName = ""; + std::string ExecutionTime = ""; + bool getExecuted = false; + bool isSuccessful = true; + std::vector EventCode; // negative event code -> error; positive event code -> warning }; class ClassFlow { - protected: - static std::vector sequenceData; + protected: + static std::vector sequenceData; - strFlowState FlowState; + strFlowState FlowState; - public: - ClassFlow(void); - ClassFlow(void *); + public: + ClassFlow(void); + ClassFlow(void *); - virtual bool loadParameter(); - virtual bool doFlow(std::string time); - virtual void doPostProcessEventHandling(); + virtual bool loadParameter(); + virtual bool doFlow(std::string time); + virtual void doPostProcessEventHandling(); - void presetFlowStateHandler(bool _init = false, std::string _time = ""); - void setFlowStateHandlerEvent(int _eventCode = 0); - struct strFlowState* getFlowState(); + void presetFlowStateHandler(bool _init = false, std::string _time = ""); + void setFlowStateHandlerEvent(int _eventCode = 0); + struct strFlowState *getFlowState(); - virtual std::string name() {return "ClassFlow";}; + virtual std::string name() { return "ClassFlow"; }; }; -#endif //CLASSFLOW_H \ No newline at end of file +#endif // CLASSFLOW_H diff --git a/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp b/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp index 798a0a9e8..c096cf6d4 100644 --- a/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowAlignment.cpp @@ -21,13 +21,13 @@ static const char *TAG = "ALIGN"; ClassFlowAlignment::ClassFlowAlignment() { presetFlowStateHandler(true); - alignFastSADThreshold = 10; // FAST ALIGN ALGO: SADNorm -> if smaller than threshold use same alignment values as last cycle + alignFastSADThreshold = 10; // FAST ALIGN ALGO: SADNorm -> if smaller than threshold use same alignment values as last cycle alignAndCutImage = NULL; useAntialiasing = false; // @TODO: Check or remove option ImageBasis = flowctrl.getRawImage(); imageTemp = NULL; - AlgROI = (ImageData*)heap_caps_malloc(sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + AlgROI = (ImageData *)heap_caps_malloc(sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); } @@ -43,12 +43,13 @@ bool ClassFlowAlignment::loadParameter() // Configure two alignemnt marker for (int i = 0; i < 2; i++) { int x = 0, y = 0, channel = 0; - std::string sIndex = std::to_string(i+1); + std::string sIndex = std::to_string(i + 1); // Check availability of marker image before usage if (!fileExists("/sdcard/config/marker" + sIndex + ".jpg")) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Alignmant marker image missing: '/sdcard/config/marker" + sIndex + - ".jpg' > Please update alignment marker"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Alignmant marker image missing: '/sdcard/config/marker" + sIndex + + ".jpg' > Please update alignment marker"); return false; } @@ -62,7 +63,7 @@ bool ClassFlowAlignment::loadParameter() alignmentMarker[i].markerImage = new CImageBasis("marker" + sIndex); if (alignmentMarker[i].markerImage) { - if(!alignmentMarker[i].markerImage->createEmptyImage(x, y, channel, 1)) { + if (!alignmentMarker[i].markerImage->createEmptyImage(x, y, channel, 1)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create alignment marker image"); return false; } @@ -95,8 +96,9 @@ bool ClassFlowAlignment::loadParameter() } } - if (cfgDataPtr->alignmentAlgo == ALIGNALGO_FAST) // Load AlignmentMarker if "fast" algo is used + if (cfgDataPtr->alignmentAlgo == ALIGNALGO_FAST) { // Load AlignmentMarker if "fast" algo is used loadAlignmentMarkerData(); + } return true; } @@ -106,7 +108,7 @@ bool ClassFlowAlignment::doFlow(std::string time) { presetFlowStateHandler(false, time); if (AlgROI == NULL) { // AlgROI needs to be allocated before imageTemp to avoid heap fragmentation - AlgROI = (ImageData*)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + AlgROI = (ImageData *)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); if (AlgROI == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to allocate AlgROI"); LogFile.writeHeapInfo("ClassFlowAlignment-doFlow"); @@ -114,7 +116,7 @@ bool ClassFlowAlignment::doFlow(std::string time) } if (AlgROI) { - ImageBasis->writeToMemoryAsJPG((ImageData*)AlgROI, 90); + ImageBasis->writeToMemoryAsJPG((ImageData *)AlgROI, 90); } if (imageTemp == NULL) { @@ -138,41 +140,47 @@ bool ClassFlowAlignment::doFlow(std::string time) float rotation = cfgDataPtr->imageRotation; if (rotation != 0) { - if (alignmentMarker[0].alignmentAlgo == ALIGNALGO_OFF) // alignment off: no initial rotation and no additional alignment algo + if (alignmentMarker[0].alignmentAlgo == ALIGNALGO_OFF) { // alignment off: no initial rotation and no additional alignment algo rotation = 0.0; + } - if (useAntialiasing) + if (useAntialiasing) { rt.rotateImageAntiAliasing(rotation); - else + } + else { rt.rotateImage(rotation); + } - if (cfgDataPtr->debug.saveAllFiles) + if (cfgDataPtr->debug.saveAllFiles) { alignAndCutImage->saveToFile(formatFileName("/sdcard/img_tmp/rot.jpg")); + } } LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Initial rotation: " + to_stringWithPrecision(rotation, 1)); - if(alignmentMarker[0].alignmentAlgo <= ALIGNALGO_FAST) { // Only if any additional alignment algo is used: "default", "highaccuracy" or "fast" + if (alignmentMarker[0].alignmentAlgo <= ALIGNALGO_FAST) { // Only if any additional alignment algo is used: "default", "highaccuracy" or + // "fast" int AlignRetval = alignAndCutImage->alignImage(&alignmentMarker[0], &alignmentMarker[1]); if (AlignRetval >= 0) { saveAlignmentMarkerData(); } - else if (AlignRetval == -1) { // Alignment failed + else if (AlignRetval == -1) { // Alignment failed LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Alignment by algorithm failed. Verify image rotation and alignment marker"); setFlowStateHandlerEvent(-1); // Set error event code for post cycle error handler 'doPostProcessEventHandling' } } if (AlgROI) { - if(alignmentMarker[0].alignmentAlgo <= ALIGNALGO_FAST) { // Only if any additional alignment algo is used: "default", "highaccuracy" or "fast" + if (alignmentMarker[0].alignmentAlgo <= ALIGNALGO_FAST) { // Only if any additional alignment algo is used: "default", + // "highaccuracy" or "fast" drawAlignmentMarker(imageTemp); } if (getFlowState()->isSuccessful) { flowctrl.drawDigitRoi(imageTemp); flowctrl.drawAnalogRoi(imageTemp); } - imageTemp->writeToMemoryAsJPG((ImageData*)AlgROI, 90); + imageTemp->writeToMemoryAsJPG((ImageData *)AlgROI, 90); } if (cfgDataPtr->debug.saveAllFiles) { @@ -184,8 +192,9 @@ bool ClassFlowAlignment::doFlow(std::string time) delete imageTemp; imageTemp = NULL; - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -195,20 +204,23 @@ void ClassFlowAlignment::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed for (int i = 0; i < getFlowState()->EventCode.size(); i++) { - if (cfgDataPtr->debug.saveDebugInfo && getFlowState()->EventCode[i] == -1) { // If saving error logs enabled and alignment failed event + if (cfgDataPtr->debug.saveDebugInfo && getFlowState()->EventCode[i] == -1) { // If saving error logs enabled and alignment failed + // event time_t actualtime; time(&actualtime); // Define path, e.g. /sdcard/log/debug/20230814/20230814-125528/ClassFlowAlignment - std::string destination = std::string(LOG_DEBUG_ROOT_FOLDER) + "/" + getFlowState()->ExecutionTime.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + - getFlowState()->ExecutionTime + "/" + getFlowState()->ClassName; + std::string destination = std::string(LOG_DEBUG_ROOT_FOLDER) + "/" + + getFlowState()->ExecutionTime.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + getFlowState()->ExecutionTime + + "/" + getFlowState()->ClassName; - if (!makeDir(destination)) + if (!makeDir(destination)) { return; + } // Save algo results in file std::string resultFileName = "/alignment_failed.txt"; - FILE* fpResult = fopen((destination + resultFileName).c_str(), "w"); + FILE *fpResult = fopen((destination + resultFileName).c_str(), "w"); fwrite(alignmentMarker[0].errorMsg.c_str(), (alignmentMarker[0].errorMsg).length(), 1, fpResult); fclose(fpResult); @@ -273,29 +285,29 @@ bool ClassFlowAlignment::loadAlignmentMarkerData(void) nvs_handle_t align_nvshandle; err = nvs_open("align", NVS_READONLY, &align_nvshandle); - if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND ) { + if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadReferenceAlignmentValues: No valid NVS handle - error code : " + std::to_string(err)); return false; } - err = nvs_get_i32(align_nvshandle, "Ref0fastalg_x", (int32_t*)&alignmentMarker[0].algoFastX); + err = nvs_get_i32(align_nvshandle, "Ref0fastalg_x", (int32_t *)&alignmentMarker[0].algoFastX); if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadReferenceAlignmentValues: Ref0fastalg_x - error code: " + std::to_string(err)); return false; } - err = nvs_get_i32(align_nvshandle, "Ref0fastalg_y", (int32_t*)&alignmentMarker[0].algoFastY); + err = nvs_get_i32(align_nvshandle, "Ref0fastalg_y", (int32_t *)&alignmentMarker[0].algoFastY); if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadReferenceAlignmentValues: Ref0fastalg_y - error code: " + std::to_string(err)); return false; } - err = nvs_get_i32(align_nvshandle, "Ref1fastalg_x", (int32_t*)&alignmentMarker[1].algoFastX); + err = nvs_get_i32(align_nvshandle, "Ref1fastalg_x", (int32_t *)&alignmentMarker[1].algoFastX); if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadReferenceAlignmentValues: Ref1fastalg_x - error code: " + std::to_string(err)); return false; } - err = nvs_get_i32(align_nvshandle, "Ref1fastalg_y", (int32_t*)&alignmentMarker[1].algoFastY); - if (err != ESP_OK) { + err = nvs_get_i32(align_nvshandle, "Ref1fastalg_y", (int32_t *)&alignmentMarker[1].algoFastY); + if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadReferenceAlignmentValues: Ref1fastalg_y - error code: " + std::to_string(err)); return false; } @@ -308,11 +320,14 @@ bool ClassFlowAlignment::loadAlignmentMarkerData(void) void ClassFlowAlignment::drawAlignmentMarker(CImageBasis *image) { - if (!image->imageOkay()) + if (!image->imageOkay()) { return; + } - image->drawRect(alignmentMarker[0].targetX, alignmentMarker[0].targetY, alignmentMarker[0].width, alignmentMarker[0].height, 255, 51, 51, 2); - image->drawRect(alignmentMarker[1].targetX, alignmentMarker[1].targetY, alignmentMarker[1].width, alignmentMarker[1].height, 255, 51, 51, 2); + image->drawRect(alignmentMarker[0].targetX, alignmentMarker[0].targetY, alignmentMarker[0].width, alignmentMarker[0].height, 255, 51, + 51, 2); + image->drawRect(alignmentMarker[1].targetX, alignmentMarker[1].targetY, alignmentMarker[1].width, alignmentMarker[1].height, 255, 51, + 51, 2); } diff --git a/code/components/mainprocess_ctrl/ClassFlowAlignment.h b/code/components/mainprocess_ctrl/ClassFlowAlignment.h index ede52aead..c4b4d01a2 100644 --- a/code/components/mainprocess_ctrl/ClassFlowAlignment.h +++ b/code/components/mainprocess_ctrl/ClassFlowAlignment.h @@ -32,7 +32,6 @@ class ClassFlowAlignment : public ClassFlow ImageData *AlgROI; ClassFlowAlignment(); - //ClassFlowAlignment(ClassFlowTakeImage *_flowTakeImage); virtual ~ClassFlowAlignment(); bool loadParameter(); diff --git a/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.cpp b/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.cpp index 869788647..e6ef8fcc9 100644 --- a/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.cpp @@ -4,7 +4,7 @@ #include #include #include -#include // std::stringstream +#include // std::stringstream #include @@ -13,7 +13,7 @@ #include "ClassControlCamera.h" -static const char* TAG = "CNN"; +static const char *TAG = "CNN"; ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalignment, std::string _cnnname, CNNType _cnntype) : ClassLogImage(TAG) @@ -81,8 +81,9 @@ bool ClassFlowCNNGeneral::loadParameter() RoiData *roiEl = new RoiData{}; roiEl->param = &ConfigClass::getInstance()->get()->sectionDigit.sequence[i].roi[j]; - if (!roiPositionPlausibilityCheck(roiEl)) + if (!roiPositionPlausibilityCheck(roiEl)) { return false; + } if (i < sequenceData.size()) { sequenceData[i]->digitRoi.push_back(roiEl); @@ -91,7 +92,6 @@ bool ClassFlowCNNGeneral::loadParameter() } } } - } else if (cnnname == "Analog") { cnnmodelfile = "/sdcard/config/models/" + ConfigClass::getInstance()->get()->sectionAnalog.model; @@ -106,8 +106,9 @@ bool ClassFlowCNNGeneral::loadParameter() RoiData *roiEl = new RoiData{}; roiEl->param = &ConfigClass::getInstance()->get()->sectionAnalog.sequence[i].roi[j]; - if (!roiPositionPlausibilityCheck(roiEl)) + if (!roiPositionPlausibilityCheck(roiEl)) { return false; + } if (i < sequenceData.size()) { sequenceData[i]->analogRoi.push_back(roiEl); @@ -118,8 +119,9 @@ bool ClassFlowCNNGeneral::loadParameter() } } - if (!resolveNetworkParameter()) + if (!resolveNetworkParameter()) { return false; + } for (int i = 0; auto &sequence : sequenceDataInternal) { for (int j = 0; auto &roi : sequence->roiData) { @@ -149,17 +151,20 @@ bool ClassFlowCNNGeneral::doFlow(std::string time) presetFlowStateHandler(false, time); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Process ROI extraction"); - if (!doAlignAndCut(time)) + if (!doAlignAndCut(time)) { return false; + } LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Process neural network"); - if (!doNeuralNetwork(time)) + if (!doNeuralNetwork(time)) { return false; + } removeOldLogs(); - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -168,7 +173,6 @@ bool ClassFlowCNNGeneral::doFlow(std::string time) void ClassFlowCNNGeneral::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed - } @@ -192,7 +196,7 @@ bool ClassFlowCNNGeneral::doAlignAndCut(std::string time) roi->imageRoi->resizeImage(modelxsize, modelysize, roi->imageRoiResized); if (saveAllFiles) { - roi->imageRoiResized->saveToFile(formatFileName("/sdcard/img_tmp/" + roi->param->roiName + ".jpg")); + roi->imageRoiResized->saveToFile(formatFileName("/sdcard/img_tmp/" + roi->param->roiName + ".jpg")); } } } @@ -226,8 +230,7 @@ bool ClassFlowCNNGeneral::resolveNetworkParameter() return false; } int _anzoutputdimensions = tflite->GetAnzOutPut(); - switch (_anzoutputdimensions) - { + switch (_anzoutputdimensions) { case -1: LogFile.writeToFile(ESP_LOG_ERROR, TAG, "TFLITE: Failed to load output dimensions"); return false; @@ -243,17 +246,19 @@ bool ClassFlowCNNGeneral::resolveNetworkParameter() cnnType = CNNTYPE_DIGIT_CLASS11; LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CNN-Type: Digit - Class11"); break; - case 100: + case 100: if (modelxsize == 32 && modelysize == 32) { cnnType = CNNTYPE_ANALOG_CLASS100; LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CNN-Type: Analog - Class100"); - } else { + } + else { cnnType = CNNTYPE_DIGIT_CLASS100; LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CNN-Type: Digit - Class100"); } break; default: - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "CNN-Type does not fit the firmware (output_dimension=" + std::to_string(_anzoutputdimensions) + ")"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "CNN-Type does not fit the firmware (output_dimension=" + std::to_string(_anzoutputdimensions) + ")"); return false; } } @@ -282,8 +287,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "ROI: " + roi->param->roiName); switch (cnnType) { - case CNNTYPE_DIGIT_CLASS11: // for models dig-class11* - { + case CNNTYPE_DIGIT_CLASS11: { // for models dig-class11* LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Type: Digit (dig-class11)"); roi->CNNResult = tflite->GetClassFromImageBasis(roi->imageRoiResized); // 0-9 + 10 => NaN @@ -302,8 +306,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) } } break; - case CNNTYPE_DIGIT_DOUBLE_HYBRID10: // for models dig-cont* - { + case CNNTYPE_DIGIT_DOUBLE_HYBRID10: { // for models dig-cont* LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Type: Digit (dig-cont)"); int LogImageResult; @@ -338,30 +341,36 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) _fit = _val + _valminus; } - if (result >= 10) + if (result >= 10) { result = result - 10; - if (result < 0) + } + if (result < 0) { result = result + 10; + } roi->CNNResult = result * 10.0; // result normalized to 0-99 - if (roi->CNNResult < 0) + if (roi->CNNResult < 0) { roi->CNNResult = 0; - else if (roi->CNNResult >= 100) + } + else if (roi->CNNResult >= 100) { roi->CNNResult = 99; + } roi->sCNNResult = to_stringWithPrecision(roi->CNNResult / 10.0, 1); - /*std::string zw = "num (p, m): " + std::to_string(_num) + " (" + std::to_string(_numplus) + " , " + std::to_string(_numminus) + - "), val (p, m): " + std::to_string(_val) + " (" + std::to_string(_valplus) + " , " + std::to_string(_valminus) + - "), result: " + roi->sCNNResult + ", fit: " + std::to_string(_fit); + /*std::string zw = "num (p, m): " + std::to_string(_num) + " (" + std::to_string(_numplus) + " , " + + std::to_string(_numminus) + "), val (p, m): " + std::to_string(_val) + " (" + std::to_string(_valplus) + " , " + + std::to_string(_valminus) + "), result: " + roi->sCNNResult + ", fit: " + std::to_string(_fit); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, zw); */ if (_fit < CNNGoodThreshold) { roi->isRejected = true; - LogImageResult = -1 * roi->CNNResult; // In case fit is not sufficient, the result should still be saved with "-x.y". - std::string zw = "Result rejected - bad fit (Fit: " + std::to_string(_fit) + ", Threshold: " + std::to_string(CNNGoodThreshold) + ")"; + LogImageResult = -1 * + roi->CNNResult; // In case fit is not sufficient, the result should still be saved with "-x.y". + std::string zw = "Result rejected - bad fit (Fit: " + std::to_string(_fit) + + ", Threshold: " + std::to_string(CNNGoodThreshold) + ")"; LogFile.writeToFile(ESP_LOG_WARN, TAG, zw); } else { @@ -376,9 +385,8 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) } } break; - case CNNTYPE_ANALOG_CLASS100: - case CNNTYPE_DIGIT_CLASS100: // for models dig-class100* - { + case CNNTYPE_ANALOG_CLASS100: // for models ana-class100* + case CNNTYPE_DIGIT_CLASS100: { // for models dig-class100* LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Type: Analog / Digit (ana-class100 / dig-class100)"); if (tflite->LoadInputImageBasis(roi->imageRoiResized)) { @@ -392,21 +400,24 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) int _num = tflite->GetOutClassification(); - if(roi->param->ccw) { - if (_num == 0) + if (roi->param->ccw) { + if (_num == 0) { roi->CNNResult = 0; - else - roi->CNNResult = 100 -_num; - + } + else { + roi->CNNResult = 100 - _num; + } } else { roi->CNNResult = _num; } - if (roi->CNNResult < 0) + if (roi->CNNResult < 0) { roi->CNNResult = 0; - else if (roi->CNNResult >= 100) + } + else if (roi->CNNResult >= 100) { roi->CNNResult = 99; + } roi->sCNNResult = to_stringWithPrecision(roi->CNNResult / 10.0, 1); @@ -417,8 +428,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) } } break; - case CNNTYPE_ANALOG_CONT: // for models ana-cont* - { + case CNNTYPE_ANALOG_CONT: { // for models ana-cont* LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Type: Analog (ana-cont)"); if (tflite->LoadInputImageBasis(roi->imageRoiResized)) { @@ -432,31 +442,36 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) float result = fmod(atan2(tflite->GetOutputValue(0), tflite->GetOutputValue(1)) / (M_PI * 2) + 2, 1); - if(roi->param->ccw) { - if (result == 0.0) + if (roi->param->ccw) { + if (result == 0.0) { roi->CNNResult = 0; - else - roi->CNNResult = 100 - (result * 100); // result normalized to 0-99 + } + else { + roi->CNNResult = 100 - (result * 100); // result normalized to 0-99 + } } else { roi->CNNResult = result * 100; // result normalized to 0-99 } - if (roi->CNNResult < 0) + if (roi->CNNResult < 0) { roi->CNNResult = 0; - else if (roi->CNNResult >= 100) + } + else if (roi->CNNResult >= 100) { roi->CNNResult = 99; + } roi->sCNNResult = to_stringWithPrecision(roi->CNNResult / 10.0, 1); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Result: " + roi->sCNNResult); - if (saveImagesEnabled) + if (saveImagesEnabled) { logImage(logPath, roi->param->roiName, CNNTYPE_ANALOG_CONT, roi->CNNResult, time, roi->imageRoi); + } } break; default: - break; + break; } } } @@ -469,11 +484,12 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(std::string time) std::string ClassFlowCNNGeneral::getReadout(SequenceData *sequence, int valuePreviousNumber, int resultPreviousNumber) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "getReadout: Number sequence: " + sequence->sequenceName + - ", extendedResolution: " + std::to_string(sequence->paramPostProc->extendedResolution) + - ", valuePreviousNumber: " + to_stringWithPrecision(valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(resultPreviousNumber) + - ", analogDigitSyncValue: " + to_stringWithPrecision(sequence->paramPostProc->analogDigitSyncValue, 1)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "getReadout: Number sequence: " + sequence->sequenceName + + ", extendedResolution: " + std::to_string(sequence->paramPostProc->extendedResolution) + + ", valuePreviousNumber: " + to_stringWithPrecision(valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(resultPreviousNumber) + + ", analogDigitSyncValue: " + to_stringWithPrecision(sequence->paramPostProc->analogDigitSyncValue, 1)); if (cnnType == CNNTYPE_ANALOG_CONT || cnnType == CNNTYPE_ANALOG_CLASS100) { // Class-analog-model, ana-class100-model if (sequence->analogRoi.size() == 0) { @@ -526,24 +542,28 @@ std::string ClassFlowCNNGeneral::getReadout(SequenceData *sequence, int valuePre // NOTE: Ensure that this flag is only set if no analog previous number is available if (sequence->paramPostProc->extendedResolution && valuePreviousNumber == -1) { result = std::to_string(resultTemp); - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Digit Number (No previous number, Extended Resolution): Result: " + result + - ", Value: " + to_stringWithPrecision((resultTemp/10.0), 1)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Digit Number (No previous number, Extended Resolution): Result: " + result + + ", Value: " + to_stringWithPrecision((resultTemp / 10.0), 1)); resultTemp = resultTemp / 10; // resultIntergerPart to hand over a previous result to next digit evaluation } else { - if (valuePreviousNumber >= 0) // If previous number available (analog value should be handed over) - resultTemp = evalDigitNumber(sequence->digitRoi[lastROI]->CNNResult, valuePreviousNumber, - resultPreviousNumber, true, int(sequence->paramPostProc->analogDigitSyncValue * 10.0)); - else + if (valuePreviousNumber >= 0) { // If previous number available (analog value should be handed over) + resultTemp = evalDigitNumber(sequence->digitRoi[lastROI]->CNNResult, valuePreviousNumber, resultPreviousNumber, true, + int(sequence->paramPostProc->analogDigitSyncValue * 10.0)); + } + else { resultTemp = evalDigitNumber(sequence->digitRoi[lastROI]->CNNResult, -1, -1); // No previous number + } result = std::to_string(resultTemp); } } else { result = "N"; - if (sequence->paramPostProc->extendedResolution) + if (sequence->paramPostProc->extendedResolution) { result = "NN"; + } LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "getReadout Digit (dig-cont): Rejected, substitude with N"); } @@ -552,7 +572,7 @@ std::string ClassFlowCNNGeneral::getReadout(SequenceData *sequence, int valuePre for (int i = lastROI - 1; i >= 0; i--) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "ROI: " + sequence->digitRoi[i]->param->roiName); if (!sequence->digitRoi[i]->isRejected) { // valid result (e.g. model 'dig-cont*' --> bad fit)? - resultTemp = evalDigitNumber(sequence->digitRoi[i]->CNNResult, sequence->digitRoi[i+1]->CNNResult, resultTemp); + resultTemp = evalDigitNumber(sequence->digitRoi[i]->CNNResult, sequence->digitRoi[i + 1]->CNNResult, resultTemp); result = std::to_string(resultTemp) + result; } else { @@ -565,7 +585,7 @@ std::string ClassFlowCNNGeneral::getReadout(SequenceData *sequence, int valuePre LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "getReadout Digit (dig-cont/dig-class100): Result: " + result); return result; } - else if (cnnType == CNNTYPE_DIGIT_CLASS11) { // Class-11-model (1-0 + NaN) + else if (cnnType == CNNTYPE_DIGIT_CLASS11) { // Class-11-model (1-0 + NaN) if (sequence->digitRoi.size() == 0) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "getReadout: No digit ROI in processed number sequence"); return std::string(""); @@ -600,84 +620,90 @@ int ClassFlowCNNGeneral::evalAnalogNumber(int _value, int _resultPreviousNumber) { int result = -1; - if (_resultPreviousNumber <= -1) - { + if (_resultPreviousNumber <= -1) { result = _value / 10; // Return IntegerPart, remove decimal place (73 -> 7) - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogNumber (No previous number): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogNumber (No previous number): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1)); return result; } int valueMax = _value + Analog_error; - if (valueMax >= 100) // e.g. 10.2 -> 0.2 (value = 02) + if (valueMax >= 100) { // e.g. 10.2 -> 0.2 (value = 02) valueMax = valueMax - 100; + } int valueMin = _value - Analog_error; - if (valueMin < 0) // e.g. -0.3 -> 9.7 (value = 97) + if (valueMin < 0) { // e.g. -0.3 -> 9.7 (value = 97) valueMin = 100 + valueMin; + } - if (((valueMin / 10 - valueMax / 10)) != 0) - { - if (_resultPreviousNumber <= Analog_error) - { + if (((valueMin / 10 - valueMax / 10)) != 0) { + if (_resultPreviousNumber <= Analog_error) { result = valueMax / 10; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogNumber (Ambiguous, use value + corretion): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogNumber (Ambiguous, use value + corretion): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } - else if (_resultPreviousNumber >= 10 - Analog_error) - { + else if (_resultPreviousNumber >= 10 - Analog_error) { result = valueMin / 10; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogNumber (Ambiguous, use value - corretion): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogNumber (Ambiguous, use value - corretion): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } } result = _value / 10; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogNumber (Unambiguous, use value): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogNumber (Unambiguous, use value): Result: " + std::to_string(result) + ", Value: " + + to_stringWithPrecision(_value / 10.0, 1) + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } /* Evaluate digit number */ -int ClassFlowCNNGeneral::evalDigitNumber(int _value, int _valuePreviousNumber, int _resultPreviousNumber, - bool _isPreviousAnalog, int digitalAnalogTransitionStart) +int ClassFlowCNNGeneral::evalDigitNumber(int _value, int _valuePreviousNumber, int _resultPreviousNumber, bool _isPreviousAnalog, + int digitalAnalogTransitionStart) { - int result = - 1; + int result = -1; int resultIntergerPart = _value / 10; int resultDecimalPlace = _value % 10; if (_resultPreviousNumber <= -1) { // no previous number -> no correction logic for transition needed, use value as is (integer part) result = resultIntergerPart; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalDigitNumber (No previous number): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalDigitNumber (No previous number): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1)); return result; } // previous number is analog (_valuePreviousNumber: 0-99), special transistion check needed if (_isPreviousAnalog) { result = evalAnalogToDigitTransition(_value, _valuePreviousNumber, _resultPreviousNumber, digitalAnalogTransitionStart); - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalDigitNumber (Analog previous number): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalDigitNumber (Analog previous number): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } - // Previous number is digit (_valuePreviousNumber: 0-99) No digit change, because predecessor is far enough away (+/- Digital_Transition_Area_Predecessor) - if ((_valuePreviousNumber >= Digital_Transition_Area_Predecessor) && (_valuePreviousNumber <= (100 - Digital_Transition_Area_Predecessor))) { + // Previous number is digit (_valuePreviousNumber: 0-99) No digit change, because predecessor is far enough away (+/- + // Digital_Transition_Area_Predecessor) + if ((_valuePreviousNumber >= Digital_Transition_Area_Predecessor) && + (_valuePreviousNumber <= (100 - Digital_Transition_Area_Predecessor))) { // Band around the digit --> Round, as digit reaches inaccuracy in the frame - if ((resultDecimalPlace <= DigitalBand) || (resultDecimalPlace >= (10-DigitalBand))) { + if ((resultDecimalPlace <= DigitalBand) || (resultDecimalPlace >= (10 - DigitalBand))) { if (resultDecimalPlace >= 5) { result = resultIntergerPart + 1; // "Round" - if (result >= 10) + if (result >= 10) { result = 0; + } } else { result = resultIntergerPart; // "Trunc" @@ -687,10 +713,11 @@ int ClassFlowCNNGeneral::evalDigitNumber(int _value, int _valuePreviousNumber, i result = resultIntergerPart; // "Trunc" } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalDigitNumber (Digit previous number: no zero crossing, \'safe area\'): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalDigitNumber (Digit previous number: no zero crossing, \'safe area\'): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } @@ -700,19 +727,21 @@ int ClassFlowCNNGeneral::evalDigitNumber(int _value, int _valuePreviousNumber, i // We simply assume that the current digit after the zero crossing of the predecessor // has passed through at least half (x.5) if (resultDecimalPlace >= 5) { - result = resultIntergerPart + 1; // "Round": The current digit does not yet have a zero crossing, but the predecessor does.. + result = resultIntergerPart + 1; // "Round": The current digit does not yet have a zero crossing, but the predecessor does.. - if (result >= 10) + if (result >= 10) { result = 0; + } } else { - result = resultIntergerPart; // "Trunc": Act. digit and predecessor have zero crossing + result = resultIntergerPart; // "Trunc": Act. digit and predecessor have zero crossing } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalDigitNumber (Digit previous number: zero crossing): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalDigitNumber (Digit previous number: zero crossing): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } @@ -721,73 +750,80 @@ int ClassFlowCNNGeneral::evalDigitNumber(int _value, int _valuePreviousNumber, i // everything >=x.4 can be considered as current number in transition. With 9.x predecessor the current // number can still be x.6 - x.7. // Preceding (else - branch) does not already happen from 9. - if (((_valuePreviousNumber <= Digital_Transition_Area_Forward) && (_resultPreviousNumber == (int)(_valuePreviousNumber/10.0))) || - resultDecimalPlace >= 4) - { - result = resultIntergerPart; // The current digit, like the previous digit, does not yet have a zero crossing. + if (((_valuePreviousNumber <= Digital_Transition_Area_Forward) && (_resultPreviousNumber == (int)(_valuePreviousNumber / 10.0))) || + resultDecimalPlace >= 4) { + result = resultIntergerPart; // The current digit, like the previous digit, does not yet have a zero crossing. } else { // current digit precedes the smaller digit (9.x). So already >=x.0 while the previous digit has not yet // has no zero crossing. Therefore, it is reduced by 1. - result = resultIntergerPart - 1; + result = resultIntergerPart - 1; - if (result < 0) + if (result < 0) { result = 9; + } } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalDigitNumber (Digit previous number: no zero crossing yet): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalDigitNumber (Digit previous number: no zero crossing yet): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); return result; } /* Evaluate analog to digit number transition */ -int ClassFlowCNNGeneral::evalAnalogToDigitTransition(int _value, int _valuePreviousNumber, int _resultPreviousNumber, int analogDigitSyncValue) +int ClassFlowCNNGeneral::evalAnalogToDigitTransition(int _value, int _valuePreviousNumber, int _resultPreviousNumber, + int analogDigitSyncValue) { - int result = - 1; + int result = -1; int resultIntergerPart = _value / 10; int resultDecimalPlace = _value % 10; // Value within the digit inequalities - if (resultDecimalPlace >= (10 - Digital_Uncertainty) // Band around the zero crossing -> Round, as number reaches inaccuracy zone - || (_resultPreviousNumber <= 4 && resultDecimalPlace >= 6)) // or number runs after (previous result <= 4, actucal decimal place >= 6) + if (resultDecimalPlace >= (10 - Digital_Uncertainty) // Band around the zero crossing -> Round, as number reaches inaccuracy zone + || + (_resultPreviousNumber <= 4 && resultDecimalPlace >= 6)) // or number runs after (previous result <= 4, actucal decimal place >= 6) { if (resultDecimalPlace >= 5) { // "Round up" result = resultIntergerPart + 1; - if (result >= 10) + if (result >= 10) { result = 0; + } // Correct back if no zero crossing detected // analogDigitSyncValue < _valuePreviousNumber < 0.2 - if (_resultPreviousNumber >= 6 && (_valuePreviousNumber > analogDigitSyncValue || _valuePreviousNumber <= 2)) - { + if (_resultPreviousNumber >= 6 && (_valuePreviousNumber > analogDigitSyncValue || _valuePreviousNumber <= 2)) { result = result - 1; - if (result < 0) + if (result < 0) { result = 9; + } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogToDigitTransition (Digit uncertainty, no zero crossing): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + - ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogToDigitTransition (Digit uncertainty, no zero crossing): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); } } else { result = resultIntergerPart; // "Trunc -> Round down" } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogToDigitTransition (Digit uncertainty): Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1) + - ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber/10.0, 1) + + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogToDigitTransition (Digit uncertainty): Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1) + + ", valuePreviousNumber: " + to_stringWithPrecision(_valuePreviousNumber / 10.0, 1) + ", resultPreviousNumber: " + std::to_string(_resultPreviousNumber)); } else { result = resultIntergerPart; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "evalAnalogToDigitTransition: Result: " + std::to_string(result) + - ", Value: " + to_stringWithPrecision(_value/10.0, 1)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "evalAnalogToDigitTransition: Result: " + std::to_string(result) + + ", Value: " + to_stringWithPrecision(_value / 10.0, 1)); } return result; @@ -796,8 +832,9 @@ int ClassFlowCNNGeneral::evalAnalogToDigitTransition(int _value, int _valuePrevi bool ClassFlowCNNGeneral::cnnTypeAllowExtendedResolution() { - if (cnnType == CNNTYPE_DIGIT_CLASS11) + if (cnnType == CNNTYPE_DIGIT_CLASS11) { return false; + } return true; } @@ -805,31 +842,37 @@ bool ClassFlowCNNGeneral::cnnTypeAllowExtendedResolution() void ClassFlowCNNGeneral::drawROI(CImageBasis *image) { - if (!image->imageOkay()) + if (!image->imageOkay()) { return; + } for (int i = 0; const auto &sequence : sequenceDataInternal) { std::array color = {0, 255, 0}; - if (i == 0) + if (i == 0) { color = {0, 255, 0}; // Green - else if (i == 1) + } + else if (i == 1) { color = {0, 0, 255}; // Blue - else if (i == 2) + } + else if (i == 2) { color = {0, 255, 255}; // Cyan - else if (i == 3) + } + else if (i == 3) { color = {255, 0, 255}; // Pink - else if (i == 4) + } + else if (i == 4) { color = {255, 255, 0}; // Yellow + } for (const auto &roi : sequence->roiData) { if (cnnType == CNNTYPE_ANALOG_CONT || cnnType == CNNTYPE_ANALOG_CLASS100) { // image->drawRect(roi->param->x, roi->param->y, roi->param->dx, roi->param->dy, color[0], color[1], color[2], 1); - image->drawEllipse((int) (roi->param->x + roi->param->dx/2), (int) (roi->param->y + roi->param->dy/2), - (int) (roi->param->dx/2), (int) (roi->param->dy/2), color[0], color[1], color[2], 2); - image->drawLine((int) (roi->param->x + roi->param->dx/2), (int) roi->param->y, (int) (roi->param->x + roi->param->dx/2), - (int) (roi->param->y + roi->param->dy), color[0], color[1], color[2], 2); - image->drawLine((int) roi->param->x, (int) (roi->param->y + roi->param->dy/2), (int) roi->param->x + roi->param->dx, - (int) (roi->param->y + roi->param->dy/2), color[0], color[1], color[2], 2); + image->drawEllipse((int)(roi->param->x + roi->param->dx / 2), (int)(roi->param->y + roi->param->dy / 2), + (int)(roi->param->dx / 2), (int)(roi->param->dy / 2), color[0], color[1], color[2], 2); + image->drawLine((int)(roi->param->x + roi->param->dx / 2), (int)roi->param->y, (int)(roi->param->x + roi->param->dx / 2), + (int)(roi->param->y + roi->param->dy), color[0], color[1], color[2], 2); + image->drawLine((int)roi->param->x, (int)(roi->param->y + roi->param->dy / 2), (int)roi->param->x + roi->param->dx, + (int)(roi->param->y + roi->param->dy / 2), color[0], color[1], color[2], 2); } else { image->drawRect(roi->param->x, roi->param->y, roi->param->dx, roi->param->dy, color[0], color[1], color[2], 2); diff --git a/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.h b/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.h index 4b7a7ae06..6cb6f83ac 100644 --- a/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.h +++ b/code/components/mainprocess_ctrl/ClassFlowCNNGeneral.h @@ -35,7 +35,8 @@ class ClassFlowCNNGeneral : public ClassLogImage bool saveAllFiles; int evalAnalogNumber(int _value, int _resultPreviousNumber); - int evalDigitNumber(int _value, int _valuePreviousNumber, int _resultPreviousNumber, bool isPreviousAnalog = false, int analogDigitSyncValue = 92); + int evalDigitNumber(int _value, int _valuePreviousNumber, int _resultPreviousNumber, bool isPreviousAnalog = false, + int analogDigitSyncValue = 92); int evalAnalogToDigitTransition(int _value, int _valuePreviousNumber, int _resultPreviousNumber, int analogDigitSyncValue); bool resolveNetworkParameter(); @@ -60,4 +61,4 @@ class ClassFlowCNNGeneral : public ClassLogImage std::string name() { return "ClassFlowCNNGeneral - " + cnnname; }; }; -#endif +#endif // CLASSFLOWCNNGENERAL_H diff --git a/code/components/mainprocess_ctrl/ClassFlowControl.cpp b/code/components/mainprocess_ctrl/ClassFlowControl.cpp index 7b541877f..55ea196f9 100644 --- a/code/components/mainprocess_ctrl/ClassFlowControl.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowControl.cpp @@ -25,16 +25,16 @@ extern "C" { #include "gpioControl.h" #ifdef ENABLE_MQTT - #include "interface_mqtt.h" - #include "server_mqtt.h" -#endif //ENABLE_MQTT +#include "interface_mqtt.h" +#include "server_mqtt.h" +#endif // ENABLE_MQTT -static const char* TAG = "FLOWCTRL"; +static const char *TAG = "FLOWCTRL"; -//#define DEBUG_DETAIL_ON +// #define DEBUG_DETAIL_ON -std::vectorClassFlow::sequenceData = {}; +std::vector ClassFlow::sequenceData = {}; ClassFlowControl::ClassFlowControl() @@ -50,18 +50,18 @@ ClassFlowControl::ClassFlowControl() flowanalog = NULL; flowpostprocessing = NULL; - #ifdef ENABLE_MQTT +#ifdef ENABLE_MQTT flowMQTT = NULL; - #endif //ENABLE_MQTT +#endif // ENABLE_MQTT - #ifdef ENABLE_INFLUXDB - flowInfluxDBv1 = NULL; - flowInfluxDBv2 = NULL; - #endif //ENABLE_INFLUXDB +#ifdef ENABLE_INFLUXDB + flowInfluxDBv1 = NULL; + flowInfluxDBv2 = NULL; +#endif // ENABLE_INFLUXDB - #ifdef ENABLE_WEBHOOK +#ifdef ENABLE_WEBHOOK flowWebhook = NULL; - #endif //ENABLE_WEBHOOK +#endif // ENABLE_WEBHOOK setActualProcessState(std::string(FLOW_NO_TASK)); flowStateErrorInRow = 0; @@ -128,7 +128,7 @@ bool ClassFlowControl::initFlow() // Prepare sequence data struct for (const auto &sequenceCfgData : cfgClassPtr->get()->sectionNumberSequences.sequence) { - SequenceData* sequence = new SequenceData{}; + SequenceData *sequence = new SequenceData{}; sequence->sequenceId = sequenceCfgData.sequenceId; sequence->sequenceName = sequenceCfgData.sequenceName; sequenceData.push_back(sequence); @@ -184,7 +184,7 @@ bool ClassFlowControl::initFlow() retVal = false; } } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT #ifdef ENABLE_INFLUXDB if (cfgClassPtr->get()->sectionInfluxDBv1.enabled) { @@ -204,7 +204,7 @@ bool ClassFlowControl::initFlow() retVal = false; } } -#endif //ENABLE_INFLUXDB +#endif // ENABLE_INFLUXDB #ifdef ENABLE_WEBHOOK if (cfgClassPtr->get()->sectionWebhook.enabled) { @@ -215,7 +215,7 @@ bool ClassFlowControl::initFlow() retVal = false; } } -#endif +#endif // ENABLE_WEBHOOK // Load parameter handled in this class this->loadParameter(); @@ -230,54 +230,54 @@ bool ClassFlowControl::initFlow() void ClassFlowControl::deinitFlow(void) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Deinit flow"); - //LogFile.writeHeapInfo("deinitFlow start"); + // LogFile.writeHeapInfo("deinitFlow start"); - #ifdef ENABLE_WEBHOOK - delete flowWebhook; +#ifdef ENABLE_WEBHOOK + delete flowWebhook; flowWebhook = NULL; - //LogFile.writeHeapInfo("After WEBHOOK"); - #endif //ENABLE_WEBHOOK + // LogFile.writeHeapInfo("After WEBHOOK"); +#endif // ENABLE_WEBHOOK - #ifdef ENABLE_INFLUXDB +#ifdef ENABLE_INFLUXDB delete flowInfluxDBv2; flowInfluxDBv2 = NULL; - //LogFile.writeHeapInfo("After INFLUXv2"); + // LogFile.writeHeapInfo("After INFLUXv2"); delete flowInfluxDBv1; flowInfluxDBv1 = NULL; - //LogFile.writeHeapInfo("After INFLUX"); - #endif //ENABLE_INFLUXDB + // LogFile.writeHeapInfo("After INFLUX"); +#endif // ENABLE_INFLUXDB - #ifdef ENABLE_MQTT - delete flowMQTT; +#ifdef ENABLE_MQTT + delete flowMQTT; flowMQTT = NULL; - //LogFile.writeHeapInfo("After MQTT"); - #endif //ENABLE_MQTT + // LogFile.writeHeapInfo("After MQTT"); +#endif // ENABLE_MQTT delete flowpostprocessing; flowpostprocessing = NULL; - //LogFile.writeHeapInfo("After POSTPROC"); + // LogFile.writeHeapInfo("After POSTPROC"); delete flowanalog; flowanalog = NULL; - //LogFile.writeHeapInfo("After ANALOG"); + // LogFile.writeHeapInfo("After ANALOG"); delete flowdigit; flowdigit = NULL; - //LogFile.writeHeapInfo("After DIGIT"); + // LogFile.writeHeapInfo("After DIGIT"); delete flowalignment; flowalignment = NULL; - //LogFile.writeHeapInfo("After ALIGN"); + // LogFile.writeHeapInfo("After ALIGN"); delete flowtakeimage; flowtakeimage = NULL; - //LogFile.writeHeapInfo("After TAKEIMG"); + // LogFile.writeHeapInfo("After TAKEIMG"); cameraCtrl.freeDemoMemoryOnly(); // Free user allocated memory, but no cam driver deinit cameraCtrl.setFlashlight(false); setStatusLedOff(); - //LogFile.writeHeapInfo("After camera"); + // LogFile.writeHeapInfo("After camera"); FlowControlImage.clear(); FlowControlPublish.clear(); @@ -308,15 +308,15 @@ bool ClassFlowControl::doFlowImageEvaluation(std::string time) FlowStateEvaluationEvent.shrink_to_fit(); for (int i = 0; i < FlowControlImage.size(); ++i) { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowControl::doFlow: " + FlowControlImage[i]->name()); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowControl::doFlow: " + FlowControlImage[i]->name()); +#endif // DEBUG_DETAIL_ON setActualProcessState(translateActualProcessState(FlowControlImage[i]->name())); LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + getActualProcessState()); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false); +#endif // ENABLE_MQTT if (!FlowControlImage[i]->doFlow(time)) { FlowStateEvaluationEvent.push_back(FlowControlImage[i]->getFlowState()); @@ -353,15 +353,15 @@ bool ClassFlowControl::doFlowPublishData(std::string time) FlowStatePublishEvent.shrink_to_fit(); for (int i = 0; i < FlowControlPublish.size(); ++i) { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowControl::doFlow: " + FlowControlPublish[i]->name()); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowControl::doFlow: " + FlowControlPublish[i]->name()); +#endif // DEBUG_DETAIL_ON setActualProcessState(translateActualProcessState(FlowControlPublish[i]->name())); LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + getActualProcessState()); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", getActualProcessState(), 1, false); +#endif // ENABLE_MQTT if (!FlowControlPublish[i]->doFlow(time)) { FlowStatePublishEvent.push_back(FlowControlPublish[i]->getFlowState()); @@ -465,13 +465,13 @@ void ClassFlowControl::postProcessEventHandler() bool ClassFlowControl::getStatusSetupModus() - { +{ if (cfgClassPtr->get()->sectionOperationMode.opMode == OPMODE_SETUP) { return true; } return false; - } +} float ClassFlowControl::getProcessInterval(void) @@ -542,7 +542,7 @@ std::string ClassFlowControl::translateActualProcessState(std::string classname) else if (classname.compare("ClassFlowMQTT") == 0) { return std::string(FLOW_PUBLISH_MQTT); } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT #ifdef ENABLE_INFLUXDB else if (classname.compare("ClassFlowInfluxDBv1") == 0) { return std::string(FLOW_PUBLISH_INFLUXDB); @@ -550,10 +550,12 @@ std::string ClassFlowControl::translateActualProcessState(std::string classname) else if (classname.compare("ClassFlowInfluxDBv2") == 0) { return std::string(FLOW_PUBLISH_INFLUXDB2); } +#endif // ENABLE_INFLUXDB +#ifdef ENABLE_WEBHOOK else if (classname.compare("ClassFlowWebhook") == 0) { return std::string(FLOW_PUBLISH_WEBHOOK); } -#endif //ENABLE_INFLUXDB +#endif // ENABLE_WEBHOOK else { return "Unkown State (" + classname + ")"; } @@ -585,7 +587,7 @@ bool ClassFlowControl::initMqttService() return flowMQTT->initMqttService(cfgClassPtr->get()->sectionOperationMode.automaticProcessInterval); } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT // Return values for all number sequences and a given value type @@ -651,13 +653,13 @@ std::string ClassFlowControl::getFallbackValue(std::string _sequenceName) bool ClassFlowControl::setFallbackValue(std::string _sequenceName, std::string _newvalue) { double newValueAsDouble; - char* p; + char *p; _newvalue = trim(_newvalue); - //ESP_LOGD(TAG, "Input setFallbackValue: %s", _newvalue.c_str()); + // ESP_LOGD(TAG, "Input setFallbackValue: %s", _newvalue.c_str()); - if (_newvalue.substr(0,8).compare("0.000000") == 0 || _newvalue.compare("0.0") == 0 || _newvalue.compare("0") == 0) { - newValueAsDouble = 0; // preset to value = 0 + if (_newvalue.substr(0, 8).compare("0.000000") == 0 || _newvalue.compare("0.0") == 0 || _newvalue.compare("0") == 0) { + newValueAsDouble = 0; // preset to value = 0 } else { newValueAsDouble = strtod(_newvalue.c_str(), &p); @@ -682,7 +684,7 @@ bool ClassFlowControl::setFallbackValue(std::string _sequenceName, std::string _ } -CImageBasis* ClassFlowControl::getRawImage() +CImageBasis *ClassFlowControl::getRawImage() { if (flowtakeimage) { return flowtakeimage->rawImage; @@ -705,9 +707,9 @@ esp_err_t ClassFlowControl::sendRawJPG(httpd_req_t *req) esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - Start"); +#endif // DEBUG_DETAIL_ON CImageBasis *_send = NULL; esp_err_t result = ESP_FAIL; @@ -715,7 +717,7 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) if (_fn == "alg_roi.jpg") { if (getTaskAutoFlowState() == FLOW_TASK_STATE_INIT_DELAYED) { - FILE* file = fopen("/sdcard/html/flowstate_initialization_delayed.jpg", "rb"); + FILE *file = fopen("/sdcard/html/flowstate_initialization_delayed.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_initialization_delayed.jpg not found"); @@ -730,10 +732,11 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) long fileSize = ftell(file); fseek(file, 0, SEEK_SET); - unsigned char* fileBuffer = (unsigned char*) malloc(fileSize); + unsigned char *fileBuffer = (unsigned char *)malloc(fileSize); if (!fileBuffer) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); fclose(file); return ESP_FAIL; } @@ -746,7 +749,7 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) free(fileBuffer); } else if (getTaskAutoFlowState() == FLOW_TASK_STATE_INIT) { - FILE* file = fopen("/sdcard/html/flowstate_initialization.jpg", "rb"); + FILE *file = fopen("/sdcard/html/flowstate_initialization.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_initialization.jpg not found"); @@ -761,10 +764,11 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) long fileSize = ftell(file); fseek(file, 0, SEEK_SET); - unsigned char* fileBuffer = (unsigned char*) malloc(fileSize); + unsigned char *fileBuffer = (unsigned char *)malloc(fileSize); if (!fileBuffer) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); fclose(file); return ESP_FAIL; } @@ -777,7 +781,7 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) free(fileBuffer); } else if (getTaskAutoFlowState() == FLOW_TASK_STATE_SETUPMODE) { - FILE* file = fopen("/sdcard/html/flowstate_setup_mode.jpg", "rb"); + FILE *file = fopen("/sdcard/html/flowstate_setup_mode.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_setup_mode.jpg not found"); @@ -792,10 +796,11 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) long fileSize = ftell(file); fseek(file, 0, SEEK_SET); - unsigned char* fileBuffer = (unsigned char*) malloc(fileSize); + unsigned char *fileBuffer = (unsigned char *)malloc(fileSize); if (!fileBuffer) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); fclose(file); return ESP_FAIL; } @@ -808,9 +813,10 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) free(fileBuffer); } // Show only before first cycle started or error occured, otherwise result will be shown till next start - else if ((getActualProcessState() == std::string(FLOW_IDLE_NO_AUTOSTART) && (flowtakeimage != NULL) && !flowtakeimage->getFlowState()->getExecuted) || - (getActualProcessState() == std::string(FLOW_TAKE_IMAGE) && !isAutoStart() && flowStateEventOccured())) { - FILE* file = fopen("/sdcard/html/flowstate_idle_no_autostart.jpg", "rb"); + else if ((getActualProcessState() == std::string(FLOW_IDLE_NO_AUTOSTART) && (flowtakeimage != NULL) && + !flowtakeimage->getFlowState()->getExecuted) || + (getActualProcessState() == std::string(FLOW_TAKE_IMAGE) && !isAutoStart() && flowStateEventOccured())) { + FILE *file = fopen("/sdcard/html/flowstate_idle_no_autostart.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_idle_no_autostart.jpg not found"); @@ -825,10 +831,11 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) long fileSize = ftell(file); fseek(file, 0, SEEK_SET); - unsigned char* fileBuffer = (unsigned char*) malloc(fileSize); + unsigned char *fileBuffer = (unsigned char *)malloc(fileSize); if (!fileBuffer) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); fclose(file); return ESP_FAIL; } @@ -842,7 +849,7 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) } else if (getActualProcessState() == std::string(FLOW_TAKE_IMAGE)) { if (flowalignment && flowalignment->AlgROI) { - FILE* file = fopen("/sdcard/html/flowstate_take_image.jpg", "rb"); + FILE *file = fopen("/sdcard/html/flowstate_take_image.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_take_image.jpg not found"); @@ -858,8 +865,9 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) fseek(file, 0, SEEK_SET); if (flowalignment->AlgROI->size > MAX_JPG_SIZE) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_take_image.jpg (" + std::to_string(flowalignment->AlgROI->size) + - ") > allocated buffer (" + std::to_string(MAX_JPG_SIZE) + ")"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "File /sdcard/html/flowstate_take_image.jpg (" + std::to_string(flowalignment->AlgROI->size) + + ") > allocated buffer (" + std::to_string(MAX_JPG_SIZE) + ")"); fclose(file); return ESP_FAIL; } @@ -871,7 +879,8 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size); } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served"); if (flowalignment && flowalignment->ImageBasis->imageOkay()) { _send = flowalignment->ImageBasis; } @@ -882,7 +891,7 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) } } else if (getActualProcessState() == std::string(FLOW_TAKE_IMAGE) && isAutoStart() && flowStateEventOccured()) { - FILE* file = fopen("/sdcard/html/flowstate_idle_autostart.jpg", "rb"); + FILE *file = fopen("/sdcard/html/flowstate_idle_autostart.jpg", "rb"); if (!file) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/flowstate_idle_autostart.jpg not found"); @@ -895,12 +904,13 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) fseek(file, 0, SEEK_END); long fileSize = ftell(file); /* how long is the file ? */ - fseek(file, 0, SEEK_SET); /* reset */ + fseek(file, 0, SEEK_SET); /* reset */ - unsigned char* fileBuffer = (unsigned char*) malloc(fileSize); + unsigned char *fileBuffer = (unsigned char *)malloc(fileSize); if (!fileBuffer) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize)); fclose(file); return ESP_FAIL; } @@ -918,7 +928,8 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size); } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ClassFlowControl::getJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "ClassFlowControl::getJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served"); if (flowalignment && flowalignment->ImageBasis->imageOkay()) { _send = flowalignment->ImageBasis; } @@ -951,8 +962,9 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) break; } } - if (_send) + if (_send) { break; + } for (const auto &roi : sequence->analogRoi) { if (roi->param->roiName + ".jpg" == _fn) { @@ -965,14 +977,15 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) break; } } - if (_send) + if (_send) { break; + } } } - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - before send"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - before send"); +#endif // DEBUG_DETAIL_ON if (_send) { setContentTypeFromFile(req, _fn.c_str()); @@ -986,10 +999,9 @@ esp_err_t ClassFlowControl::getJPGStream(std::string _fn, httpd_req_t *req) _send = NULL; } - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowControl::getJPGStream - done"); +#endif // DEBUG_DETAIL_ON return result; } - diff --git a/code/components/mainprocess_ctrl/ClassFlowControl.h b/code/components/mainprocess_ctrl/ClassFlowControl.h index c3cae4fc4..3c91afe8b 100644 --- a/code/components/mainprocess_ctrl/ClassFlowControl.h +++ b/code/components/mainprocess_ctrl/ClassFlowControl.h @@ -12,16 +12,16 @@ #include "ClassFlowPostProcessing.h" #ifdef ENABLE_MQTT - #include "ClassFlowMQTT.h" +#include "ClassFlowMQTT.h" #endif // ENABLE_MQTT #ifdef ENABLE_INFLUXDB - #include "ClassFlowInfluxDBv1.h" - #include "ClassFlowInfluxDBv2.h" +#include "ClassFlowInfluxDBv1.h" +#include "ClassFlowInfluxDBv2.h" #endif // ENABLE_INFLUXDB #ifdef ENABLE_WEBHOOK - #include "ClassFlowWebhook.h" +#include "ClassFlowWebhook.h" #endif // ENABLE_WEBHOOK @@ -94,9 +94,9 @@ class ClassFlowControl : public ClassFlow void drawDigitRoi(CImageBasis *image); void drawAnalogRoi(CImageBasis *image); - #ifdef ENABLE_MQTT +#ifdef ENABLE_MQTT bool initMqttService(); - #endif // ENABLE_MQTT +#endif // ENABLE_MQTT const std::vector &getSequenceData() const { return sequenceData; }; std::string getSequenceResultInline(int type, std::string sequenceName = ""); diff --git a/code/components/mainprocess_ctrl/ClassFlowDefineTypes.h b/code/components/mainprocess_ctrl/ClassFlowDefineTypes.h index e7bcc41c1..ddd89e142 100644 --- a/code/components/mainprocess_ctrl/ClassFlowDefineTypes.h +++ b/code/components/mainprocess_ctrl/ClassFlowDefineTypes.h @@ -15,15 +15,15 @@ enum CNNType { CNNTYPE_DIGIT_CLASS11, CNNTYPE_DIGIT_DOUBLE_HYBRID10, CNNTYPE_DIGIT_CLASS100 - }; +}; struct AlignmentMarker { CImageBasis *markerImage = NULL; std::string markerImageFilename; std::string errorMsg = ""; - int alignmentAlgo = ALIGNALGO_DEFAULT; // 0 = "Default" (nur R-Kanal), 1 = "HighAccuracy" (RGB-Kanal), - //2 = "Fast" (1.x RGB, dann isSimilar), 3= "only initial rotation", 4 = "off" + int alignmentAlgo = ALIGNALGO_DEFAULT; // 0 = "Default" (nur R-Kanal), 1 = "HighAccuracy" (RGB-Kanal), + // 2 = "Fast" (1.x RGB, dann isSimilar), 3= "only initial rotation", 4 = "off" int targetX = 0; int targetY = 0; int width = 0; @@ -42,45 +42,45 @@ struct RoiData { // ROI const struct RoiElement *param = NULL; CImageBasis *imageRoi = NULL; CImageBasis *imageRoiResized = NULL; - bool isRejected = false; // Only used for dig-cont models - int CNNResult = -10; // Normalized to 0-99 (exception for class11: 0-10: 0-9+NaN), default: negative number equal to "-1.0" + bool isRejected = false; // Only used for dig-cont models + int CNNResult = -10; // Normalized to 0-99 (exception for class11: 0-10: 0-9+NaN), default: negative number equal to "-1.0" std::string sCNNResult = "-1"; // Result clamped and converted to string for visualization purpose }; struct SequenceData { - int sequenceId; // Sequence ID - std::string sequenceName; // Sequence Name - - std::vector digitRoi; // Digit ROIs - std::vector analogRoi; // Analog ROIs - - bool isFallbackValueValid = false; // Fallback value is valid in terms of not being outdated - bool isActualValueANumber = false; // Actual value is valid number (further processing possible) - bool isActualValueConfirmed = false;// Actual value is without any deviation (fully processed by post-processing without deviation) - int correctedDecimalShift = 0; // Decimal shift parameter adapted by actual configuration - int decimalPlaceCount = 0; // No of decimal places - - time_t timeProcessed; // Time of actual source image was taken (== actual result time) - time_t timeFallbackValue; // Time of FallbackValue in seconds - double ratePerMin = 0.0; // Rate per minute (e.g. m3/min) - double ratePerInterval = 0.0; // Rate per interval, value delta between actual and fallback value, - // e.g. dV/dT (actual value-fallbackvalue)/(actual processing timestamp-fallbackvalue processing timestamp) - double actualValue = 0.0; // Actual result value - double fallbackValue = 0.0; // Fallback value, equal the last successful processed value (legacy name: prevalue) - - std::string sTimeProcessed; // Processed timestamp -> Time of last processing - std::string sTimeFallbackValue; // FallbackValue timestamp -> Time of last valid value - std::string sRatePerMin = "0.0"; // Rate per minute, based on time between last valid and actual reading + int sequenceId; // Sequence ID + std::string sequenceName; // Sequence name + + std::vector digitRoi; // Digit ROIs + std::vector analogRoi; // Analog ROIs + + bool isFallbackValueValid = false; // Fallback value is valid in terms of not being outdated + bool isActualValueANumber = false; // Actual value is valid number (further processing possible) + bool isActualValueConfirmed = false; // Actual value is without any deviation (fully processed by post-processing without deviation) + int correctedDecimalShift = 0; // Decimal shift parameter adapted by actual configuration + int decimalPlaceCount = 0; // No of decimal places + + time_t timeProcessed; // Time of actual source image was taken (== actual result time) + time_t timeFallbackValue; // Time of FallbackValue in seconds + double ratePerMin = 0.0; // Rate per minute (e.g. m3/min) + double ratePerInterval = 0.0; // Rate per interval, value delta between actual and fallback value, e.g. dV/dT (actual value - + // fallbackvalue) / (actual processing timestamp - fallbackvalue processing timestamp) + double actualValue = 0.0; // Actual result value + double fallbackValue = 0.0; // Fallback value, equal the last successful processed value (legacy name: prevalue) + + std::string sTimeProcessed; // Processed timestamp -> Time of last processing + std::string sTimeFallbackValue; // FallbackValue timestamp -> Time of last valid value + std::string sRatePerMin = "0.0"; // Rate per minute, based on time between last valid and actual reading std::string sRatePerInterval = "0.0"; // Rate per interval, value delta between actual value and last valid value (fallback value) - std::string sRawValue = ""; // Raw value (possibly incl. N & leading 0) - std::string sActualValue = ""; // Value of actual valid reading, incl. post-processing corrections - std::string sFallbackValue = ""; // Fallback value, equal to last valid reading (legacy name: prevalue) - std::string sValueStatus = ""; // Value status + std::string sRawValue = ""; // Raw value (possibly incl. N & leading 0) + std::string sActualValue = ""; // Value of actual valid reading, incl. post-processing corrections + std::string sFallbackValue = ""; // Fallback value, equal to last valid reading (legacy name: prevalue) + std::string sValueStatus = ""; // Value status const struct PostProcessingPerSequence *paramPostProc = NULL; const struct InfluxDBPerSequence *paramInfluxDBv1 = NULL; const struct InfluxDBPerSequence *paramInfluxDBv2 = NULL; }; -#endif +#endif // CLASSFLOWDEFINETYPES_H diff --git a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.cpp b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.cpp index 996aa9344..ef703c0f6 100644 --- a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.cpp @@ -14,7 +14,7 @@ #include "connect_wlan.h" -static const char* TAG = "INFLUXDBV1"; +static const char *TAG = "INFLUXDBV1"; ClassFlowInfluxDBv1::ClassFlowInfluxDBv1() @@ -58,15 +58,17 @@ bool ClassFlowInfluxDBv1::loadParameter() // Check measurementname and fieldkey for (const auto &sequence : cfgDataPtr->sequence) { if (sequence.measurementName.empty() || sequence.fieldKey1.empty()) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Init failed, missing or invalid parameter \'Measurement Name\' or \'Field Key\' for sequence: " + - sequence.sequenceName); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Init failed, missing or invalid parameter \'Measurement Name\' or \'Field Key\' for sequence: " + + sequence.sequenceName); InfluxDBenable = false; return InfluxDBenable; } } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init: URI: " + cfgDataPtr->uri + ", Database: " + cfgDataPtr->database + - ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Init: URI: " + cfgDataPtr->uri + ", Database: " + cfgDataPtr->database + + ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); InfluxDBenable = influxDBv1Init(cfgDataPtr); @@ -76,8 +78,9 @@ bool ClassFlowInfluxDBv1::loadParameter() bool ClassFlowInfluxDBv1::doFlow(std::string zwtime) { - if (!InfluxDBenable) + if (!InfluxDBenable) { return true; + } presetFlowStateHandler(false, zwtime); @@ -87,13 +90,14 @@ bool ClassFlowInfluxDBv1::doFlow(std::string zwtime) } if (ESP_OK != influxDBv1Publish(sequence->paramInfluxDBv1->measurementName, sequence->paramInfluxDBv1->fieldKey1, - sequence->sActualValue, sequence->sTimeProcessed)) { + sequence->sActualValue, sequence->sTimeProcessed)) { setFlowStateHandlerEvent(1); // Set warning event code, continue process flow } } - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -102,7 +106,6 @@ bool ClassFlowInfluxDBv1::doFlow(std::string zwtime) void ClassFlowInfluxDBv1::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed - } @@ -111,4 +114,4 @@ ClassFlowInfluxDBv1::~ClassFlowInfluxDBv1() // nothing to do } -#endif //ENABLE_INFLUXDB \ No newline at end of file +#endif // ENABLE_INFLUXDB diff --git a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.h b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.h index c4328f909..c38218fac 100644 --- a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.h +++ b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv1.h @@ -28,5 +28,5 @@ class ClassFlowInfluxDBv1 : public ClassFlow std::string name() { return "ClassFlowInfluxDBv1"; }; }; - #endif // CLASSFLOWINFLUXDBV1_H -#endif // ENABLE_INFLUXDB \ No newline at end of file +#endif // CLASSFLOWINFLUXDBV1_H +#endif // ENABLE_INFLUXDB diff --git a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.cpp b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.cpp index 3ae105afb..d44ae3f68 100644 --- a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.cpp @@ -14,7 +14,7 @@ #include "connect_wlan.h" -static const char* TAG = "INFLUXDBV2"; +static const char *TAG = "INFLUXDBV2"; ClassFlowInfluxDBv2::ClassFlowInfluxDBv2() @@ -58,14 +58,16 @@ bool ClassFlowInfluxDBv2::loadParameter() // Check measurementname and fieldkey for (const auto &sequence : cfgDataPtr->sequence) { if (sequence.measurementName.empty() || sequence.fieldKey1.empty()) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Init failed, missing or invalid parameter \'Measurement Name\' or \'Field Key\' for sequence: " + - sequence.sequenceName); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "Init failed, missing or invalid parameter \'Measurement Name\' or \'Field Key\' for sequence: " + + sequence.sequenceName); InfluxDBenable = false; return InfluxDBenable; } } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init: URI: " + cfgDataPtr->uri + ", Bucket: " + cfgDataPtr->bucket + + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Init: URI: " + cfgDataPtr->uri + ", Bucket: " + cfgDataPtr->bucket + ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); InfluxDBenable = influxDBv2Init(cfgDataPtr); @@ -76,8 +78,9 @@ bool ClassFlowInfluxDBv2::loadParameter() bool ClassFlowInfluxDBv2::doFlow(std::string zwtime) { - if (!InfluxDBenable) + if (!InfluxDBenable) { return true; + } presetFlowStateHandler(false, zwtime); @@ -87,13 +90,14 @@ bool ClassFlowInfluxDBv2::doFlow(std::string zwtime) } if (ESP_OK != influxDBv2Publish(sequence->paramInfluxDBv2->measurementName, sequence->paramInfluxDBv2->fieldKey1, - sequence->sActualValue, sequence->sTimeProcessed)) { + sequence->sActualValue, sequence->sTimeProcessed)) { setFlowStateHandlerEvent(1); // Set warning event code, continue process flow } } - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -102,7 +106,6 @@ bool ClassFlowInfluxDBv2::doFlow(std::string zwtime) void ClassFlowInfluxDBv2::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed - } @@ -111,4 +114,4 @@ ClassFlowInfluxDBv2::~ClassFlowInfluxDBv2() // nothing to do } -#endif //ENABLE_INFLUXDB \ No newline at end of file +#endif // ENABLE_INFLUXDB diff --git a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.h b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.h index 68bfff6ad..02a127a16 100644 --- a/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.h +++ b/code/components/mainprocess_ctrl/ClassFlowInfluxDBv2.h @@ -28,5 +28,5 @@ class ClassFlowInfluxDBv2 : public ClassFlow std::string name() { return "ClassFlowInfluxDBv2"; }; }; - #endif // CLASSFLOWINFLUXDBv2_H -#endif // ENABLE_INFLUXDB \ No newline at end of file +#endif // CLASSFLOWINFLUXDBv2_H +#endif // ENABLE_INFLUXDB diff --git a/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp b/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp index 4ddcef3ad..cfc545f29 100644 --- a/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowMQTT.cpp @@ -21,7 +21,7 @@ static const char *TAG = "MQTT"; ClassFlowMQTT::ClassFlowMQTT() { presetFlowStateHandler(true); - keepAlive = 25*60; + keepAlive = 25 * 60; } @@ -80,13 +80,14 @@ bool ClassFlowMQTT::initMqttService(float _processingInterval) mqttServer_setParameter(cfgDataPtr, &sequenceData, _processingInterval); mqttServer_schedulePublishDeviceInfo(); - if (cfgDataPtr->homeAssistant.discoveryEnabled) + if (cfgDataPtr->homeAssistant.discoveryEnabled) { mqttServer_schedulePublishHADiscovery(); + } keepAlive = _processingInterval * 60 * 2.5; // Seconds, make sure it is greater than 2 processing cycles! - stream << std::fixed << std::setprecision(1) << "Process interval: " << _processingInterval << - "min -> MQTT keepAlive: " << ((float)keepAlive/60) << "min"; + stream << std::fixed << std::setprecision(1) << "Process interval: " << _processingInterval + << "min -> MQTT keepAlive: " << ((float)keepAlive / 60) << "min"; LogFile.writeToFile(ESP_LOG_DEBUG, TAG, stream.str()); if (configureMqttClient(cfgDataPtr, keepAlive)) { @@ -116,108 +117,129 @@ bool ClassFlowMQTT::doFlow(std::string zwtime) // Publish process status LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Publish process status"); - retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_status", - getProcessStatus().c_str(), MQTT_QOS, false); + retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_status", getProcessStatus().c_str(), MQTT_QOS, false); retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_interval", - to_stringWithPrecision(flowctrl.getProcessInterval(), 1).c_str(), MQTT_QOS, false); - retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_time", - std::to_string(getFlowProcessingTime()).c_str(), MQTT_QOS, false); - retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_state", - flowctrl.getActualProcessState().c_str(), MQTT_QOS, false); + to_stringWithPrecision(flowctrl.getProcessInterval(), 1).c_str(), MQTT_QOS, false); + retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_time", std::to_string(getFlowProcessingTime()).c_str(), + MQTT_QOS, false); + retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_state", flowctrl.getActualProcessState().c_str(), + MQTT_QOS, false); retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/process_error", - std::to_string(flowctrl.getFlowStateErrorOrDeviation()).c_str(), MQTT_QOS, false); - retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/cycle_counter", - std::to_string(getFlowCycleCounter()).c_str(), MQTT_QOS, false); + std::to_string(flowctrl.getFlowStateErrorOrDeviation()).c_str(), MQTT_QOS, false); + retValStatus &= publishMqttData(cfgDataPtr->mainTopic + "/process/status/cycle_counter", std::to_string(getFlowCycleCounter()).c_str(), + MQTT_QOS, false); - if (!retValStatus) + if (!retValStatus) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Failed to publish process status"); + } // Publish process data per sequence LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Publish process data"); - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/number_sequences", - std::to_string(sequenceData.size()), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/number_sequences", std::to_string(sequenceData.size()), MQTT_QOS, + cfgDataPtr->retainProcessData); for (const auto &sequence : sequenceData) { if (cfgDataPtr->processDataNotation == PROCESSDATA_JSON || cfgDataPtr->processDataNotation == PROCESSDATA_JSON_AND_TOPICS || - cfgDataPtr->homeAssistant.discoveryEnabled) { + cfgDataPtr->homeAssistant.discoveryEnabled) { cJSON *cJSONObject = cJSON_CreateObject(); if (cJSONObject == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create JSON object"); return false; } - if (cJSON_AddStringToObject(cJSONObject, "sequence_name", sequence->sequenceName.c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "sequence_name", sequence->sequenceName.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "actual_value", sequence->sActualValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "actual_value", sequence->sActualValue.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "fallback_value", sequence->sFallbackValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "fallback_value", sequence->sFallbackValue.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "raw_value", sequence->sRawValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "raw_value", sequence->sRawValue.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "value_status", sequence->sValueStatus.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "value_status", sequence->sValueStatus.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "rate_per_minute", sequence->sRatePerMin.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "rate_per_minute", sequence->sRatePerMin.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "rate_per_interval", sequence->sRatePerInterval.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "rate_per_interval", sequence->sRatePerInterval.c_str()) == NULL) { retValData = false; + } if (cfgDataPtr->homeAssistant.discoveryEnabled) { // Only used for Home Assistant integration - if (cJSON_AddStringToObject(cJSONObject, "rate_per_time_unit", (mqttServer_getTimeUnit() == "h") ? - to_stringWithPrecision(sequence->ratePerMin * 60, sequence->decimalPlaceCount).c_str() : - sequence->sRatePerMin.c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "rate_per_time_unit", + (mqttServer_getTimeUnit() == "h") + ? to_stringWithPrecision(sequence->ratePerMin * 60, sequence->decimalPlaceCount).c_str() + : sequence->sRatePerMin.c_str()) == NULL) { retValData = false; + } } - if (cJSON_AddStringToObject(cJSONObject, "timestamp_processed", sequence->sTimeProcessed.c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "timestamp_processed", sequence->sTimeProcessed.c_str()) == NULL) { retValData = false; - if (cJSON_AddStringToObject(cJSONObject, "timestamp_fallbackvalue", sequence->sTimeFallbackValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "timestamp_fallbackvalue", sequence->sTimeFallbackValue.c_str()) == NULL) { retValData = false; + } char *jsonChar = cJSON_PrintBuffered(cJSONObject, 512, 1); // Print to predefined buffer, reduce dynamic allocations cJSON_Delete(cJSONObject); if (jsonChar != NULL) { retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/json", - std::string(jsonChar), MQTT_QOS, cfgDataPtr->retainProcessData); + std::string(jsonChar), MQTT_QOS, cfgDataPtr->retainProcessData); cJSON_free(jsonChar); } } if (cfgDataPtr->processDataNotation == PROCESSDATA_TOPICS || cfgDataPtr->processDataNotation == PROCESSDATA_JSON_AND_TOPICS) { - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/sequence_name", - sequence->sequenceName.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/sequence_name", + sequence->sequenceName.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/actual_value", - sequence->sActualValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/fallback_value", - sequence->sFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + sequence->sActualValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/fallback_value", + sequence->sFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/raw_value", - sequence->sRawValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + sequence->sRawValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/value_status", - sequence->sValueStatus.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_minute", - sequence->sRatePerMin.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_interval", - sequence->sRatePerInterval.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + sequence->sValueStatus.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/rate_per_minute", + sequence->sRatePerMin.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/rate_per_interval", + sequence->sRatePerInterval.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); if (cfgDataPtr->homeAssistant.discoveryEnabled) { // Only used for Home Assistant integration - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/rate_per_time_unit", - (mqttServer_getTimeUnit() == "h") ? to_stringWithPrecision(sequence->ratePerMin * 60, - sequence->decimalPlaceCount).c_str() : sequence->sRatePerMin.c_str(), - MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/rate_per_time_unit", + (mqttServer_getTimeUnit() == "h") + ? to_stringWithPrecision(sequence->ratePerMin * 60, sequence->decimalPlaceCount).c_str() + : sequence->sRatePerMin.c_str(), + MQTT_QOS, cfgDataPtr->retainProcessData); } - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_processed", - sequence->sTimeProcessed.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); - retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + "/timestamp_fallbackvalue", - sequence->sTimeFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/timestamp_processed", + sequence->sTimeProcessed.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); + retValData &= publishMqttData(cfgDataPtr->mainTopic + "/process/data/" + std::to_string(sequence->sequenceId) + + "/timestamp_fallbackvalue", + sequence->sTimeFallbackValue.c_str(), MQTT_QOS, cfgDataPtr->retainProcessData); } } - if (!retValData) + if (!retValData) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Failed to publish process data"); + } if (!retValCommon || !retValStatus || !retValData) { // If publishing of one of the clusters failed - setFlowStateHandlerEvent(2); // Set warning event code, continue process flow + setFlowStateHandlerEvent(2); // Set warning event code, continue process flow } - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -226,7 +248,6 @@ bool ClassFlowMQTT::doFlow(std::string zwtime) void ClassFlowMQTT::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed - } @@ -235,4 +256,4 @@ ClassFlowMQTT::~ClassFlowMQTT() deinitMqttClient(true); } -#endif //ENABLE_MQTT \ No newline at end of file +#endif // ENABLE_MQTT diff --git a/code/components/mainprocess_ctrl/ClassFlowMQTT.h b/code/components/mainprocess_ctrl/ClassFlowMQTT.h index d62446f8c..6a4440e90 100644 --- a/code/components/mainprocess_ctrl/ClassFlowMQTT.h +++ b/code/components/mainprocess_ctrl/ClassFlowMQTT.h @@ -31,5 +31,5 @@ class ClassFlowMQTT : public ClassFlow std::string name() { return "ClassFlowMQTT"; }; }; - #endif // CLASSFFLOWMQTT_H -#endif // ENABLE_MQTT \ No newline at end of file +#endif // CLASSFFLOWMQTT_H +#endif // ENABLE_MQTT diff --git a/code/components/mainprocess_ctrl/ClassFlowPostProcessing.cpp b/code/components/mainprocess_ctrl/ClassFlowPostProcessing.cpp index f16e3e1d2..a678ee56d 100644 --- a/code/components/mainprocess_ctrl/ClassFlowPostProcessing.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowPostProcessing.cpp @@ -15,11 +15,11 @@ #include "ClassLogFile.h" -static const char* TAG = "POSTPROC"; +static const char *TAG = "POSTPROC"; ClassFlowPostProcessing::ClassFlowPostProcessing(ClassFlowTakeImage *_flowTakeImage, ClassFlowCNNGeneral *_flowDigit, - ClassFlowCNNGeneral *_flowAnalog) + ClassFlowCNNGeneral *_flowAnalog) { presetFlowStateHandler(true); @@ -59,22 +59,24 @@ bool ClassFlowPostProcessing::loadParameter() // Plausibility checks // Fallback Value is mandatory to evaluate negative rates - if (sequence->paramPostProc->maxRateCheckType > RATE_CHECK_OFF && - sequence->paramPostProc->allowNegativeRate && !sequence->paramPostProc->useFallbackValue) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, sequence->sequenceName + - ": Activate parameter \'Use Fallback Value\' to use negative rate evaluation"); + if (sequence->paramPostProc->maxRateCheckType > RATE_CHECK_OFF && sequence->paramPostProc->allowNegativeRate && + !sequence->paramPostProc->useFallbackValue) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, + sequence->sequenceName + ": Activate parameter \'Use Fallback Value\' to use negative rate evaluation"); } // Only valid for Class11 models if (sequence->paramPostProc->checkDigitIncreaseConsistency) { if (flowDigit != NULL && flowDigit->getCNNType() != CNNTYPE_DIGIT_CLASS11) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, sequence->sequenceName + - ": Skip \'Digit Increase Consistency\' check, only applicable for dig-class11 models"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + sequence->sequenceName + + ": Skip \'Digit Increase Consistency\' check, only applicable for dig-class11 models"); } if (!sequence->paramPostProc->useFallbackValue) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, sequence->sequenceName + - ": Activate parameter \'Use Fallback Value\' to be able use \'Digit Increase Consistency\' check"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + sequence->sequenceName + + ": Activate parameter \'Use Fallback Value\' to be able use \'Digit Increase Consistency\' check"); } } @@ -85,15 +87,16 @@ bool ClassFlowPostProcessing::loadParameter() } // Check if fallbackvalue usage is activated (at least in one sequence) - if (!fallbackValueActivated && sequence->paramPostProc->useFallbackValue) + if (!fallbackValueActivated && sequence->paramPostProc->useFallbackValue) { fallbackValueActivated = true; + } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Number sequence: " + sequence->sequenceName + - ", Digits: " + std::to_string(sequence->digitRoi.size()) + - ", Analogs: " + std::to_string(sequence->analogRoi.size())); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Number sequence: " + sequence->sequenceName + ", Digits: " + std::to_string(sequence->digitRoi.size()) + + ", Analogs: " + std::to_string(sequence->analogRoi.size())); } - setDecimalShift(); // Set decimal shift and number of decimal places in relation to extended resolution parameter + setDecimalShift(); // Set decimal shift and number of decimal places in relation to extended resolution parameter // Load fallback value only if valid system time is set // If not already loaded here, force loading before first usage in function doFlow @@ -111,12 +114,13 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) int resultPreviousNumberAnalog = -1; time_t _timeProcessed = flowTakeImage->getTimeImageTaken(); - if (_timeProcessed == 0) + if (_timeProcessed == 0) { time(&_timeProcessed); + } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "Quantity of number sequences: %d", sequenceData.size()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "Quantity of number sequences: %d", sequenceData.size()); +#endif // DEBUG_DETAIL_ON /* Post-processing for all defined number sequences */ for (auto &sequence : sequenceData) { @@ -129,7 +133,7 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) sequence->sTimeProcessed = convertTimeToString(sequence->timeProcessed, TIME_FORMAT_OUTPUT); sequence->isActualValueANumber = true; sequence->isActualValueConfirmed = true; - std::string sRawValue = ""; // Helper to avoid on the fly modifactions of sequence->sRawValue + std::string sRawValue = ""; // Helper to avoid on the fly modifactions of sequence->sRawValue std::string sActualValue = ""; // Helper to avoid on the fly modifactions of sequence->sActualValue /* Process analog numbers of sequence */ @@ -138,14 +142,15 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) sRawValue = flowAnalog->getReadout(sequence); if (sRawValue.length() > 0) { - if (sRawValue[0] >= 48 && sRawValue[0] <= 57) // Most significant analog value a number? + if (sRawValue[0] >= 48 && sRawValue[0] <= 57) { // Most significant analog value a number? resultPreviousNumberAnalog = sRawValue[0] - 48; + } } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After analog->getReadout: RawValue %s", sRawValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After analog->getReadout: RawValue %s", sRawValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Add decimal separator */ if (!sequence->digitRoi.empty() && !sequence->analogRoi.empty()) { @@ -155,18 +160,17 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) /* Process digit numbers of sequence */ if (!sequence->digitRoi.empty()) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "doFlow: Get digit ROI results"); - if (!sequence->analogRoi.empty()) {// If analog numbers available - sRawValue = flowDigit->getReadout(sequence, sequence->analogRoi[0]->CNNResult, - resultPreviousNumberAnalog) + sRawValue; + if (!sequence->analogRoi.empty()) { // If analog numbers available + sRawValue = flowDigit->getReadout(sequence, sequence->analogRoi[0]->CNNResult, resultPreviousNumberAnalog) + sRawValue; } else { // Extended resolution for digits only if no analog previous number sRawValue = flowDigit->getReadout(sequence); } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After digit->getReadout: RawValue %s", sRawValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After digit->getReadout: RawValue %s", sRawValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Check for any data */ if (sRawValue.empty()) { @@ -183,18 +187,20 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) /* Apply parametrized decimal shift */ sRawValue = shiftDecimal(sRawValue, sequence->correctedDecimalShift); - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After shiftDecimal: RawValue %s", sRawValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After shiftDecimal: RawValue %s", sRawValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Remove leading N */ - if (sequence->paramPostProc->ignoreLeadingNaN) - while ((sRawValue.length() > 1) && (sRawValue[0] == 'N')) + if (sequence->paramPostProc->ignoreLeadingNaN) { + while ((sRawValue.length() > 1) && (sRawValue[0] == 'N')) { sRawValue.erase(0, 1); + } + } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After IgnoreLeadingNaN: RawValue %s", sRawValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After IgnoreLeadingNaN: RawValue %s", sRawValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Use fully processed "Raw Value" and transfer to "Value" for further processing */ @@ -207,13 +213,15 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) sActualValue = substitudeN(sActualValue, sequence->fallbackValue); } else { // fallbackValue not valid to replace any N - if (!sequence->paramPostProc->useFallbackValue) - LogFile.writeToFile(ESP_LOG_WARN, TAG, sequence->sequenceName + + if (!sequence->paramPostProc->useFallbackValue) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, + sequence->sequenceName + ": Activate parameter \'Use Fallback Value\' to be able to substitude N positions"); + } sequence->ratePerMin = 0; sequence->ratePerInterval = 0; - sequence->sRatePerMin = to_stringWithPrecision(sequence->ratePerMin, sequence->decimalPlaceCount+1); + sequence->sRatePerMin = to_stringWithPrecision(sequence->ratePerMin, sequence->decimalPlaceCount + 1); sequence->sRatePerInterval = to_stringWithPrecision(sequence->ratePerInterval, sequence->decimalPlaceCount); sequence->sValueStatus = std::string(VALUE_STATUS_001_DATA_N_SUBST) + " | Raw: " + sequence->sRawValue; @@ -228,17 +236,18 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After substitudeN: ActualValue %s", sActualValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After substitudeN: ActualValue %s", sActualValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Delete leading zeros (unless there is only one 0 left) */ - while ((sActualValue.length() > 1) && (sActualValue[0] == '0')) + while ((sActualValue.length() > 1) && (sActualValue[0] == '0')) { sActualValue.erase(0, 1); + } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After removeLeadingZeros: ActualValue %s", sActualValue.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After removeLeadingZeros: ActualValue %s", sActualValue.c_str()); +#endif // DEBUG_DETAIL_ON /* Convert actual value to double interpretation */ if (!sActualValue.empty()) { @@ -254,9 +263,9 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) continue; // Stop here, invalid number } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After converting to double: sActualValue: %s, actualValue: %f", sActualValue.c_str(), sequence->actualValue); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After converting to double: sActualValue: %s, actualValue: %f", sActualValue.c_str(), sequence->actualValue); +#endif // DEBUG_DETAIL_ON if (sequence->paramPostProc->useFallbackValue) { /* Load fallback value if not yet loaded during init due to missing valid system time */ @@ -270,12 +279,15 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) /* Check digit plausibitily (only support and necessary for class-11 models (0-9 + NaN)) */ if (sequence->paramPostProc->checkDigitIncreaseConsistency) { if (flowDigit) { - if (flowDigit->getCNNType() != CNNTYPE_DIGIT_CLASS11) - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip \'Digit Increase Consistency\' check, only applicable for dig-class11 models"); + if (flowDigit->getCNNType() != CNNTYPE_DIGIT_CLASS11) { + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Skip \'Digit Increase Consistency\' check, only applicable for dig-class11 models"); + } else { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Check digit increase consistency for number sequence: " + sequence->sequenceName); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Check digit increase consistency for number sequence: " + sequence->sequenceName); sequence->actualValue = checkDigitConsistency(sequence->actualValue, sequence->correctedDecimalShift, - !sequence->analogRoi.empty(), sequence->fallbackValue); + !sequence->analogRoi.empty(), sequence->fallbackValue); } } else { @@ -283,20 +295,22 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After checkDigitIncreaseConsistency: actualValue %f", sequence->actualValue); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After checkDigitIncreaseConsistency: actualValue %f", sequence->actualValue); +#endif // DEBUG_DETAIL_ON /* Update Rates */ - //Calculate delta time between this reading und last valid reading in seconds - long timeDeltaToFallbackValue = abs((long)difftime(sequence->timeProcessed, sequence->timeFallbackValue)); // absolute delta in seconds + // Calculate delta time between this reading und last valid reading in seconds + long timeDeltaToFallbackValue = abs((long)difftime(sequence->timeProcessed, sequence->timeFallbackValue)); // Abs. delta [s] if (timeDeltaToFallbackValue > 0) { - sequence->ratePerMin = (sequence->actualValue - sequence->fallbackValue) / (timeDeltaToFallbackValue / 60.0); // calculate rate / minute + sequence->ratePerMin = (sequence->actualValue - sequence->fallbackValue) / + (timeDeltaToFallbackValue / 60.0); // calculate rate / minute } else { sequence->ratePerMin = 0; - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Rate calculation skipped, time delta between now and fallback value timestamp is zero"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Rate calculation skipped, time delta between now and fallback value timestamp is zero"); } sequence->ratePerInterval = sequence->actualValue - sequence->fallbackValue; @@ -306,7 +320,8 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) RatePerSelection = sequence->ratePerMin; } else { - RatePerSelection = sequence->ratePerInterval; // If Rate check is off, use 'ratePerInterval' for display only purpose (easier to interprete) + RatePerSelection = sequence->ratePerInterval; // If Rate check is off, use 'ratePerInterval' for display only purpose + // (easier to interprete) } /* Check for rate too high */ @@ -314,51 +329,57 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Max. rate check for number sequence: " + sequence->sequenceName); if (abs(RatePerSelection) > abs((double)sequence->paramPostProc->maxRate)) { if (RatePerSelection < 0) { - sequence->sValueStatus = std::string(VALUE_STATUS_003_RATE_TOO_HIGH_NEG); + sequence->sValueStatus = std::string(VALUE_STATUS_003_RATE_TOO_HIGH_NEG); - /* Update timestamp of fallback value to be prepared to identify next negative movement larger than max. rate threshold (diagnostic purpose) */ + /* Update timestamp of fallback value to be prepared to identify next negative movement larger than max. rate + * threshold (diagnostic purpose) */ sequence->timeFallbackValue = sequence->timeProcessed; sequence->sTimeFallbackValue = convertTimeToString(sequence->timeFallbackValue, TIME_FORMAT_OUTPUT); } else { - sequence->sValueStatus = std::string(VALUE_STATUS_004_RATE_TOO_HIGH_POS); + sequence->sValueStatus = std::string(VALUE_STATUS_004_RATE_TOO_HIGH_POS); } - sequence->sValueStatus += " | Value: " + to_stringWithPrecision(sequence->actualValue, sequence->decimalPlaceCount) + - ", Fallback: " + sequence->sFallbackValue + - ", Rate: " + to_stringWithPrecision(RatePerSelection, sequence->decimalPlaceCount); + sequence->sValueStatus += " | Value: " + + to_stringWithPrecision(sequence->actualValue, sequence->decimalPlaceCount) + + ", Fallback: " + sequence->sFallbackValue + + ", Rate: " + to_stringWithPrecision(RatePerSelection, sequence->decimalPlaceCount); - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Sequence: " + sequence->sequenceName + ", Status: " + sequence->sValueStatus); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Sequence: " + sequence->sequenceName + ", Status: " + sequence->sValueStatus); sequence->isActualValueConfirmed = false; - setFlowStateHandlerEvent(1); // Set warning event code for post cycle error handler 'doPostProcessEventHandling' (only warning level) + setFlowStateHandlerEvent(1); // Set warning event code for post cycle error handler 'doPostProcessEventHandling' + // (only warning level) } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After MaxRateCheck: actualValue %f", sequence->actualValue); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After MaxRateCheck: actualValue %f", sequence->actualValue); +#endif // DEBUG_DETAIL_ON /* Check for negative rate */ if (!sequence->paramPostProc->allowNegativeRate && sequence->isActualValueConfirmed) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Negative rate check for number sequence: " + sequence->sequenceName); if (sequence->actualValue < sequence->fallbackValue) { - sequence->sValueStatus = std::string(VALUE_STATUS_002_RATE_NEGATIVE); + sequence->sValueStatus = std::string(VALUE_STATUS_002_RATE_NEGATIVE); - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Sequence: " + sequence->sequenceName + ", Status: " + sequence->sValueStatus + - " | Value: " + std::to_string(sequence->actualValue) + - ", Fallback: " + std::to_string(sequence->fallbackValue) + - ", Rate: " + to_stringWithPrecision(RatePerSelection, sequence->decimalPlaceCount)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Sequence: " + sequence->sequenceName + ", Status: " + sequence->sValueStatus + + " | Value: " + std::to_string(sequence->actualValue) + + ", Fallback: " + std::to_string(sequence->fallbackValue) + + ", Rate: " + to_stringWithPrecision(RatePerSelection, sequence->decimalPlaceCount)); sequence->isActualValueConfirmed = false; - /* Update timestamp of fallback value to be prepared to identify every negative movement larger than max. rate threshold (diagnostic purpose) */ + /* Update timestamp of fallback value to be prepared to identify every negative movement larger than max. rate + * threshold (diagnostic purpose) */ sequence->timeFallbackValue = sequence->timeProcessed; sequence->sTimeFallbackValue = convertTimeToString(sequence->timeFallbackValue, TIME_FORMAT_OUTPUT); } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "After allowNegativeRates: actualValue %f", sequence->actualValue); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "After allowNegativeRates: actualValue %f", sequence->actualValue); +#endif // DEBUG_DETAIL_ON } else { // Fallback value is outdated or age indeterminable (could be the case after a reboot) -> force rates to zero sequence->ratePerMin = 0; @@ -393,22 +414,23 @@ bool ClassFlowPostProcessing::doFlow(std::string zwtime) } /* Write output values */ - sequence->sRatePerMin = to_stringWithPrecision(sequence->ratePerMin, sequence->decimalPlaceCount+1); + sequence->sRatePerMin = to_stringWithPrecision(sequence->ratePerMin, sequence->decimalPlaceCount + 1); sequence->sRatePerInterval = to_stringWithPrecision(sequence->ratePerInterval, sequence->decimalPlaceCount); sequence->sActualValue = to_stringWithPrecision(sequence->actualValue, sequence->decimalPlaceCount); /* Write log file entry */ - LogFile.writeToFile(ESP_LOG_INFO, TAG, sequence->sequenceName + ": Value: " + sequence->sActualValue + - ", Rate per min: " + sequence->sRatePerMin + - ", Status: " + sequence->sValueStatus); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + sequence->sequenceName + ": Value: " + sequence->sActualValue + ", Rate per min: " + sequence->sRatePerMin + + ", Status: " + sequence->sValueStatus); writeDataLog(sequence->sequenceName); } saveFallbackValue(); - if (!FlowState.isSuccessful) // Return false if any error detected + if (!FlowState.isSuccessful) { // Return false if any error detected return false; + } return true; } @@ -424,31 +446,37 @@ void ClassFlowPostProcessing::doPostProcessEventHandling() time(&actualtime); // Define path, e.g. /sdcard/log/debug/20230814/20230814-125528/ClassFlowPostProcessing - std::string destination = std::string(LOG_DEBUG_ROOT_FOLDER) + "/" + getFlowState()->ExecutionTime.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + - getFlowState()->ExecutionTime + "/" + getFlowState()->ClassName; + std::string destination = std::string(LOG_DEBUG_ROOT_FOLDER) + "/" + + getFlowState()->ExecutionTime.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + getFlowState()->ExecutionTime + + "/" + getFlowState()->ClassName; - if (!makeDir(destination)) + if (!makeDir(destination)) { return; + } for (const auto &sequence : sequenceData) { std::string resultFileName = "/" + sequence->sequenceName + "_rate_too_high.txt"; // Save result in file - FILE* fpResult = fopen((destination + resultFileName).c_str(), "w"); + FILE *fpResult = fopen((destination + resultFileName).c_str(), "w"); fwrite(sequence->sValueStatus.c_str(), (sequence->sValueStatus).length(), 1, fpResult); fclose(fpResult); // Save digit ROIs - if (!sequence->digitRoi.empty()) - for (const auto &roi : sequence->digitRoi) - roi->imageRoi->saveToFile(destination + "/" + to_stringWithPrecision(roi->CNNResult/10.0, 1) + - "_" + roi->param->roiName + ".jpg"); + if (!sequence->digitRoi.empty()) { + for (const auto &roi : sequence->digitRoi) { + roi->imageRoi->saveToFile(destination + "/" + to_stringWithPrecision(roi->CNNResult / 10.0, 1) + "_" + + roi->param->roiName + ".jpg"); + } + } // Save analog ROIs - if (!sequence->analogRoi.empty()) - for (const auto &roi : sequence->analogRoi) - roi->imageRoi->saveToFile(destination + "/" + to_stringWithPrecision(roi->CNNResult/10.0, 1) + - "_" + roi->param->roiName + ".jpg"); + if (!sequence->analogRoi.empty()) { + for (const auto &roi : sequence->analogRoi) { + roi->imageRoi->saveToFile(destination + "/" + to_stringWithPrecision(roi->CNNResult / 10.0, 1) + "_" + + roi->param->roiName + ".jpg"); + } + } } LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Rate too high, debug infos saved: " + destination); @@ -462,7 +490,7 @@ void ClassFlowPostProcessing::setDecimalShift() for (auto &sequence : sequenceData) { sequence->correctedDecimalShift = sequence->paramPostProc->decimalShift; // Create updated decimalshift depending on config - // Only digit numbers + // Only digit numbers if (!sequence->digitRoi.empty() && sequence->analogRoi.empty()) { if (sequence->paramPostProc->extendedResolution && flowDigit->cnnTypeAllowExtendedResolution()) { sequence->correctedDecimalShift -= 1; @@ -487,17 +515,18 @@ void ClassFlowPostProcessing::setDecimalShift() } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "setDecimalShift: Sequence %s, decimalPlace %i, DecShift %i", sequence->sequenceName.c_str(), - sequence->decimalPlaceCount, sequence->correctedDecimalShift); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "setDecimalShift: Sequence %s, decimalPlace %i, DecShift %i", sequence->sequenceName.c_str(), + sequence->decimalPlaceCount, sequence->correctedDecimalShift); +#endif // DEBUG_DETAIL_ON } } -std::string ClassFlowPostProcessing::shiftDecimal(std::string _value, int _decShift){ +std::string ClassFlowPostProcessing::shiftDecimal(std::string _value, int _decShift) +{ - if (_decShift == 0){ + if (_decShift == 0) { return _value; } @@ -513,16 +542,16 @@ std::string ClassFlowPostProcessing::shiftDecimal(std::string _value, int _decSh _pos_dec_new = _pos_dec_org + _decShift; - if (_pos_dec_new <= 0) { // comma is before the first digit - for (int i = 0; i > _pos_dec_new; --i){ + if (_pos_dec_new <= 0) { // comma is before the first digit + for (int i = 0; i > _pos_dec_new; --i) { _value = _value.insert(0, "0"); } _value = "0." + _value; return _value; } - if (_pos_dec_new > _value.length()){ // Comma should be after string (123 --> 1230) - for (int i = _value.length(); i < _pos_dec_new; ++i){ + if (_pos_dec_new > _value.length()) { // Comma should be after string (123 --> 1230) + for (int i = _value.length(); i < _pos_dec_new; ++i) { _value = _value.insert(_value.length(), "0"); } return _value; @@ -545,12 +574,11 @@ std::string ClassFlowPostProcessing::substitudeN(std::string input, double _fall posN = findDelimiterPos(input, "N"); posPunkt = findDelimiterPos(input, "."); - if (posPunkt == std::string::npos){ + if (posPunkt == std::string::npos) { posPunkt = input.length(); } - while (posN != std::string::npos) - { + while (posN != std::string::npos) { if (posN < posPunkt) { pot = posPunkt - posN - 1; } @@ -558,8 +586,8 @@ std::string ClassFlowPostProcessing::substitudeN(std::string input, double _fall pot = posPunkt - posN; } - zw =_fallbackValue / pow(10, pot); - ziffer = ((int) zw) % 10; + zw = _fallbackValue / pow(10, pot); + ziffer = ((int)zw) % 10; input[posN] = ziffer + 48; posN = findDelimiterPos(input, "N"); @@ -569,7 +597,8 @@ std::string ClassFlowPostProcessing::substitudeN(std::string input, double _fall } -float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decimalshift, bool _isanalog, double _fallbackValue){ +float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decimalshift, bool _isanalog, double _fallbackValue) +{ int aktdigit, olddigit; int aktdigit_before, olddigit_before; int pot, pot_max; @@ -581,38 +610,38 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decimals pot++; } - #ifdef DEBUG_DETAIL_ON - ESP_LOGD(TAG, "checkDigitConsistency: pot=%d, decimalShift=%d", pot, _decimalshift); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGD(TAG, "checkDigitConsistency: pot=%d, decimalShift=%d", pot, _decimalshift); +#endif // DEBUG_DETAIL_ON - pot_max = ((int) log10(input)) + 1; + pot_max = ((int)log10(input)) + 1; while (pot <= pot_max) { - zw = input / pow(10, pot-1); - aktdigit_before = ((int) zw) % 10; - zw = _fallbackValue / pow(10, pot-1); - olddigit_before = ((int) zw) % 10; + zw = input / pow(10, pot - 1); + aktdigit_before = ((int)zw) % 10; + zw = _fallbackValue / pow(10, pot - 1); + olddigit_before = ((int)zw) % 10; zw = input / pow(10, pot); - aktdigit = ((int) zw) % 10; + aktdigit = ((int)zw) % 10; zw = _fallbackValue / pow(10, pot); - olddigit = ((int) zw) % 10; + olddigit = ((int)zw) % 10; no_nulldurchgang = (olddigit_before <= aktdigit_before); if (no_nulldurchgang) { if (aktdigit != olddigit) { - input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // New Digit is replaced by old Digit; + input = input + ((float)(olddigit - aktdigit)) * pow(10, pot); // New Digit is replaced by old Digit; } } else { - if (aktdigit == olddigit) { // despite zero crossing, digit was not incremented --> add 1 - input = input + ((float) (1)) * pow(10, pot); // add 1 at the point + if (aktdigit == olddigit) { // despite zero crossing, digit was not incremented --> add 1 + input = input + ((float)(1)) * pow(10, pot); // add 1 at the point } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGD(TAG, "checkDigitConsistency: input=%f", input); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGD(TAG, "checkDigitConsistency: input=%f", input); +#endif // DEBUG_DETAIL_ON pot++; } @@ -649,14 +678,14 @@ void ClassFlowPostProcessing::writeDataLog(std::string sequenceName) return; } - LogFile.writeToData(sequence->sTimeProcessed, sequence->sequenceName, sequence->sRawValue, - sequence->sActualValue, sequence->sFallbackValue, sequence->sRatePerMin, - sequence->sRatePerInterval, sequence->sValueStatus.substr(0,3), digit, analog); + LogFile.writeToData(sequence->sTimeProcessed, sequence->sequenceName, sequence->sRawValue, sequence->sActualValue, + sequence->sFallbackValue, sequence->sRatePerMin, sequence->sRatePerInterval, + sequence->sValueStatus.substr(0, 3), digit, analog); - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "writeDataLog: %s, %s, %s, %s, %s", sequence->sRawValue.c_str(), sequence->sActualValue.c_str(), - sequence->sValueStatus.substr(0,3).c_str(), digit.c_str(), analog.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "writeDataLog: %s, %s, %s, %s, %s", sequence->sRawValue.c_str(), sequence->sActualValue.c_str(), + sequence->sValueStatus.substr(0, 3).c_str(), digit.c_str(), analog.c_str()); +#endif // DEBUG_DETAIL_ON break; } @@ -678,21 +707,21 @@ std::string ClassFlowPostProcessing::getFallbackValue(std::string sequenceName) bool ClassFlowPostProcessing::setFallbackValue(double value, std::string sequenceName) { - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "setFallbackValue: %f, %s", value, sequenceName.c_str()); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "setFallbackValue: %f, %s", value, sequenceName.c_str()); +#endif // DEBUG_DETAIL_ON for (const auto &sequence : sequenceData) { if (sequence->sequenceName == sequenceName) { - if (value >= 0) { // if new value posivive, use provided value to preset fallbackValue + if (value >= 0) { // if new value posivive, use provided value to preset fallbackValue sequence->fallbackValue = value; } - else { // if new value negative, use last raw value to preset fallbackValue - char* p; + else { // if new value negative, use last raw value to preset fallbackValue + char *p; double ReturnRawValueAsDouble = strtod(sequence->sRawValue.c_str(), &p); if (ReturnRawValueAsDouble == 0) { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "setFallbackValue: RawValue not a valid value for further processing: " - + sequence->sRawValue); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "setFallbackValue: RawValue not a valid value for further processing: " + sequence->sRawValue); return false; } sequence->fallbackValue = ReturnRawValueAsDouble; @@ -712,14 +741,15 @@ bool ClassFlowPostProcessing::setFallbackValue(double value, std::string sequenc } LogFile.writeToFile(ESP_LOG_WARN, TAG, "setFallbackValue: Numbersname not found or not valid"); - return false; // No new value was set (e.g. wrong numbersname, no numbers at all) + return false; // No new value was set (e.g. wrong numbersname, no numbers at all) } bool ClassFlowPostProcessing::loadFallbackValue(void) { - if (fallbackValueLoaded) // fallbackValue already loaded + if (fallbackValueLoaded) { // fallbackValue already loaded return false; + } esp_err_t err = ESP_OK; nvs_handle_t fallbackvalue_nvshandle; @@ -753,7 +783,7 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) return false; } - char cName[required_size+1]; + char cName[required_size + 1]; if (required_size > 0) { err = nvs_get_str(fallbackvalue_nvshandle, ("name" + std::to_string(i)).c_str(), cName, &required_size); if (err != ESP_OK) { @@ -772,7 +802,7 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) return false; } - char cTime[required_size+1]; + char cTime[required_size + 1]; if (required_size > 0) { err = nvs_get_str(fallbackvalue_nvshandle, ("time" + std::to_string(i)).c_str(), cTime, &required_size); if (err != ESP_OK) { @@ -791,7 +821,7 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) return false; } - char cValue[required_size+1]; + char cValue[required_size + 1]; if (required_size > 0) { err = nvs_get_str(fallbackvalue_nvshandle, ("value" + std::to_string(i)).c_str(), cValue, &required_size); if (err != ESP_OK) { @@ -801,14 +831,15 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) } } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "loadFallbackValue: Sequence: %s, Time: %s, Value: %s", cName, cTime, cValue); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "loadFallbackValue: Sequence: %s, Time: %s, Value: %s", cName, cTime, cValue); +#endif // DEBUG_DETAIL_ON for (const auto &sequence : sequenceData) { if (std::string(cName) == sequence->sequenceName) { - if (!sequence->paramPostProc->useFallbackValue) // Skip, because FallbackValue is disabled + if (!sequence->paramPostProc->useFallbackValue) { // Skip, because FallbackValue is disabled continue; + } time_t tStart; int yy, month, dd, hh, mm, ss; @@ -833,25 +864,27 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) sequence->isFallbackValueValid = false; sequence->fallbackValue = 0; sequence->sFallbackValue = "Outdated"; - LogFile.writeToFile(ESP_LOG_INFO, TAG, sequence->sequenceName + ": Fallback value outdated | Timestamp: " + - sequence->sTimeFallbackValue); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + sequence->sequenceName + ": Fallback value outdated | Timestamp: " + sequence->sTimeFallbackValue); } // Start time is older than fallback value timestamp -> age indeterminable else if (AgeInMinutes < 0) { sequence->isFallbackValueValid = false; sequence->fallbackValue = 0; sequence->sFallbackValue = "Not Determinable"; - LogFile.writeToFile(ESP_LOG_INFO, TAG, sequence->sequenceName + ": Fallback value age not determinable | Timestamp: " + - sequence->sTimeFallbackValue); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + sequence->sequenceName + + ": Fallback value age not determinable | Timestamp: " + sequence->sTimeFallbackValue); } // Fallback value valid else { sequence->isFallbackValueValid = true; char *pEnd = NULL; sequence->fallbackValue = strtod(cValue, &pEnd); - sequence->sFallbackValue = to_stringWithPrecision(sequence->fallbackValue, sequence->decimalPlaceCount + 1); // Keep one digit more - LogFile.writeToFile(ESP_LOG_INFO, TAG, sequence->sequenceName + ": Fallback value valid | Timestamp: " + - sequence->sTimeFallbackValue); + sequence->sFallbackValue = to_stringWithPrecision(sequence->fallbackValue, + sequence->decimalPlaceCount + 1); // Keep one digit more + LogFile.writeToFile(ESP_LOG_INFO, TAG, + sequence->sequenceName + ": Fallback value valid | Timestamp: " + sequence->sTimeFallbackValue); } break; } @@ -866,8 +899,9 @@ bool ClassFlowPostProcessing::loadFallbackValue(void) bool ClassFlowPostProcessing::saveFallbackValue() { - if (!updateFallbackValue) // fallbackValue unchanged + if (!updateFallbackValue) { // fallbackValue unchanged return false; + } esp_err_t err = ESP_OK; nvs_handle_t fallbackvalue_nvshandle; @@ -887,14 +921,15 @@ bool ClassFlowPostProcessing::saveFallbackValue() } for (int i = 0; i < sequenceData.size(); i++) { - if (!sequenceData[i]->paramPostProc->useFallbackValue) // Skip, because FallbackValue is disabled + if (!sequenceData[i]->paramPostProc->useFallbackValue) { // Skip, because FallbackValue is disabled continue; + } - #ifdef DEBUG_DETAIL_ON +#ifdef DEBUG_DETAIL_ON ESP_LOGI(TAG, "saveFallbackValue: Sequence: %s, Time: %s, Value: %s", sequenceData[i]->sequenceName.c_str(), - (sequenceData[i]->sTimeFallbackValue).c_str(), (to_stringWithPrecision(sequenceData[i]->fallbackValue, - sequenceData[i]->decimalPlaceCount)).c_str()); - #endif + (sequenceData[i]->sTimeFallbackValue).c_str(), + (to_stringWithPrecision(sequenceData[i]->fallbackValue, sequenceData[i]->decimalPlaceCount)).c_str()); +#endif // DEBUG_DETAIL_ON err = nvs_set_str(fallbackvalue_nvshandle, ("name" + std::to_string(i)).c_str(), sequenceData[i]->sequenceName.c_str()); if (err != ESP_OK) { @@ -909,7 +944,7 @@ bool ClassFlowPostProcessing::saveFallbackValue() return false; } err = nvs_set_str(fallbackvalue_nvshandle, ("value" + std::to_string(i)).c_str(), - to_stringWithPrecision(sequenceData[i]->fallbackValue, sequenceData[i]->decimalPlaceCount).c_str()); + to_stringWithPrecision(sequenceData[i]->fallbackValue, sequenceData[i]->decimalPlaceCount).c_str()); if (err != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "saveFallbackValue: nvs_set_str fallbackvalue - error: " + intToHexString(err)); nvs_close(fallbackvalue_nvshandle); diff --git a/code/components/mainprocess_ctrl/ClassFlowPostProcessing.h b/code/components/mainprocess_ctrl/ClassFlowPostProcessing.h index 3bb10fa0e..315ffe202 100644 --- a/code/components/mainprocess_ctrl/ClassFlowPostProcessing.h +++ b/code/components/mainprocess_ctrl/ClassFlowPostProcessing.h @@ -26,14 +26,12 @@ class ClassFlowPostProcessing : public ClassFlow void setDecimalShift(); std::string shiftDecimal(std::string in, int _decShift); std::string substitudeN(std::string, double _fallbackValue); - float checkDigitConsistency(double _value, int _decimalshift, - bool _isanalog, double _fallbackValue); + float checkDigitConsistency(double _value, int _decimalshift, bool _isanalog, double _fallbackValue); void writeDataLog(std::string sequenceName); public: - ClassFlowPostProcessing(ClassFlowTakeImage *_flowTakeImage, ClassFlowCNNGeneral *_flowDigit, - ClassFlowCNNGeneral *_flowAnalog); + ClassFlowPostProcessing(ClassFlowTakeImage *_flowTakeImage, ClassFlowCNNGeneral *_flowDigit, ClassFlowCNNGeneral *_flowAnalog); virtual ~ClassFlowPostProcessing(); bool loadParameter(); bool doFlow(std::string time); diff --git a/code/components/mainprocess_ctrl/ClassFlowTakeImage.cpp b/code/components/mainprocess_ctrl/ClassFlowTakeImage.cpp index 0873c47ae..dfb117193 100644 --- a/code/components/mainprocess_ctrl/ClassFlowTakeImage.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowTakeImage.cpp @@ -13,7 +13,7 @@ #include "MainFlowControl.h" -static const char* TAG = "TAKEIMAGE"; +static const char *TAG = "TAKEIMAGE"; ClassFlowTakeImage::ClassFlowTakeImage() : ClassLogImage(TAG) @@ -38,8 +38,10 @@ bool ClassFlowTakeImage::loadParameter() ConfigClass::getInstance()->get()->sectionOperationMode.useDemoImages ? cameraCtrl.enableDemoMode() : cameraCtrl.disableDemoMode(); #ifdef GPIO_FLASHLIGHT_DEFAULT_USE_PWM - cameraCtrl.ledcInitFlashlightDefault(); // PWM init needs to be done here due to parameter reload (camera class not to be deleted completely) -#endif + cameraCtrl.ledcInitFlashlightDefault(); // PWM init needs to be done here due to parameter reload (camera class not to be deleted + // completely) + +#endif // GPIO_FLASHLIGHT_DEFAULT_USE_PWM cameraCtrl.setCameraParameter(&cfgDataPtr->camera); cameraCtrl.setFlashlightParameter(&cfgDataPtr->flashlight); @@ -50,7 +52,7 @@ bool ClassFlowTakeImage::loadParameter() rawImage = new CImageBasis("rawImage"); if (rawImage) { - if(!rawImage->createEmptyImage(imgWidth, imgHeight, STBI_rgb, 1)) { + if (!rawImage->createEmptyImage(imgWidth, imgHeight, STBI_rgb, 1)) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create rawimage"); return false; } @@ -74,26 +76,26 @@ bool ClassFlowTakeImage::doFlow(std::string zwtime) presetFlowStateHandler(false, zwtime); std::string logPath = createLogFolder(zwtime); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - Start"); +#endif // DEBUG_DETAIL_ON if (!takeImage()) { setFlowStateHandlerEvent(-1); // Set error code for post cycle error handler 'doPostProcessEventHandling' (error level) return false; } - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - After takeImage"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - After takeImage"); +#endif // DEBUG_DETAIL_ON logImage(logPath, "raw", CNNTYPE_NONE, -1, zwtime, rawImage); removeOldLogs(); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - Done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ClassFlowTakeImage::doFlow - Done"); +#endif // DEBUG_DETAIL_ON return true; } @@ -105,7 +107,7 @@ void ClassFlowTakeImage::doPostProcessEventHandling() for (int i = 0; i < getFlowState()->EventCode.size(); i++) { if (getFlowState()->EventCode[i] == -1) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Camera init or framebuffer access failed, reinit camera"); - cameraCtrl.deinitCam(); // Reinit will be done here: MainFlowControl.cpp -> DoInit() + cameraCtrl.deinitCam(); // Reinit will be done here: MainFlowControl.cpp -> DoInit() setTaskAutoFlowState(FLOW_TASK_STATE_INIT); // Do fully init process to avoid SPIRAM fragmentation } } @@ -137,11 +139,11 @@ esp_err_t ClassFlowTakeImage::sendRawJPG(httpd_req_t *req) { time(&timeImageTaken); - return cameraCtrl.captureToHTTP(req); // Capture with configured flash time + return cameraCtrl.captureToHTTP(req); // Capture with configured flash time } -ImageData* ClassFlowTakeImage::sendRawImage() +ImageData *ClassFlowTakeImage::sendRawImage() { CImageBasis *imgTmp = new CImageBasis("sendRawImage", rawImage); ImageData *id = NULL; diff --git a/code/components/mainprocess_ctrl/ClassFlowWebhook.cpp b/code/components/mainprocess_ctrl/ClassFlowWebhook.cpp index 523ecd706..4b0e79ebf 100644 --- a/code/components/mainprocess_ctrl/ClassFlowWebhook.cpp +++ b/code/components/mainprocess_ctrl/ClassFlowWebhook.cpp @@ -14,7 +14,7 @@ #include "connect_wlan.h" -static const char* TAG = "WEBHOOK"; +static const char *TAG = "WEBHOOK"; ClassFlowWebhook::ClassFlowWebhook(ClassFlowAlignment *_flowAlignment) @@ -42,8 +42,9 @@ bool ClassFlowWebhook::loadParameter() return webhookEnable; } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Init: URI: " + cfgDataPtr->uri + ", API Key: " + cfgDataPtr->apiKey + - ", PublishImage: " + std::to_string(cfgDataPtr->publishImage) + ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Init: URI: " + cfgDataPtr->uri + ", API Key: " + cfgDataPtr->apiKey + ", PublishImage: " + + std::to_string(cfgDataPtr->publishImage) + ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); webhookEnable = webhookInit(cfgDataPtr); @@ -53,8 +54,9 @@ bool ClassFlowWebhook::loadParameter() bool ClassFlowWebhook::doFlow(std::string zwtime) { - if (!webhookEnable) + if (!webhookEnable) { return true; + } presetFlowStateHandler(false, zwtime); @@ -91,8 +93,8 @@ bool ClassFlowWebhook::doFlow(std::string zwtime) // Check if sequence has rate too high error if (cfgDataPtr->publishImage == WEBHOOK_PUBLISH_IMAGE_ON_ERROR_ONLY) { - if (sequence->sValueStatus.substr(0,3) == std::string(VALUE_STATUS_003_RATE_TOO_HIGH_NEG).substr(0,3) || - sequence->sValueStatus.substr(0,3) == std::string(VALUE_STATUS_004_RATE_TOO_HIGH_POS).substr(0,3)) { + if (sequence->sValueStatus.substr(0, 3) == std::string(VALUE_STATUS_003_RATE_TOO_HIGH_NEG).substr(0, 3) || + sequence->sValueStatus.substr(0, 3) == std::string(VALUE_STATUS_004_RATE_TOO_HIGH_POS).substr(0, 3)) { sequencesWithError = true; } } @@ -103,7 +105,7 @@ bool ClassFlowWebhook::doFlow(std::string zwtime) if (jsonChar != NULL) { if ((cfgDataPtr->publishImage == WEBHOOK_PUBLISH_IMAGE_ENABLED || - ((cfgDataPtr->publishImage == WEBHOOK_PUBLISH_IMAGE_ON_ERROR_ONLY) && sequencesWithError))) { + ((cfgDataPtr->publishImage == WEBHOOK_PUBLISH_IMAGE_ON_ERROR_ONLY) && sequencesWithError))) { if (flowAlignment && flowAlignment->AlgROI) { if (webhookPublish(jsonChar, flowAlignment->AlgROI, timeProcessedUtc) != ESP_OK) { setFlowStateHandlerEvent(1); // Set warning event code, continue process flow @@ -112,7 +114,7 @@ bool ClassFlowWebhook::doFlow(std::string zwtime) else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to publish image. No image data available (flowAlignment->AlgROI)"); setFlowStateHandlerEvent(1); // Set warning event code, continue process flow - webhookPublish(jsonChar); // Fallback, only publish data + webhookPublish(jsonChar); // Fallback, only publish data } } else { @@ -123,8 +125,9 @@ bool ClassFlowWebhook::doFlow(std::string zwtime) cJSON_free(jsonChar); } - if (!getFlowState()->isSuccessful) + if (!getFlowState()->isSuccessful) { return false; + } return true; } @@ -133,7 +136,6 @@ bool ClassFlowWebhook::doFlow(std::string zwtime) void ClassFlowWebhook::doPostProcessEventHandling() { // Post cycle process handling can be included here. Function is called after processing cycle is completed - } @@ -142,4 +144,4 @@ ClassFlowWebhook::~ClassFlowWebhook() // nothing to do } -#endif //ENABLE_WEBHOOK \ No newline at end of file +#endif // ENABLE_WEBHOOK diff --git a/code/components/mainprocess_ctrl/ClassFlowWebhook.h b/code/components/mainprocess_ctrl/ClassFlowWebhook.h index 39da7faf6..6b0a06c1d 100644 --- a/code/components/mainprocess_ctrl/ClassFlowWebhook.h +++ b/code/components/mainprocess_ctrl/ClassFlowWebhook.h @@ -30,5 +30,5 @@ class ClassFlowWebhook : public ClassFlow std::string name() { return "ClassFlowWebhook"; }; }; - #endif // CLASSFLOWWEBHOOK_H -#endif // ENABLE_WEBHOOK \ No newline at end of file +#endif // CLASSFLOWWEBHOOK_H +#endif // ENABLE_WEBHOOK diff --git a/code/components/mainprocess_ctrl/ClassLogImage.cpp b/code/components/mainprocess_ctrl/ClassLogImage.cpp index 159c7e975..49b9c9c6d 100644 --- a/code/components/mainprocess_ctrl/ClassLogImage.cpp +++ b/code/components/mainprocess_ctrl/ClassLogImage.cpp @@ -17,44 +17,47 @@ extern "C" { #include "helper.h" #include "time_sntp.h" -static const char* TAG = "LOGIMAGE"; +static const char *TAG = "LOGIMAGE"; ClassLogImage::ClassLogImage(const char *logTag) { - this->logTag = logTag; - this->saveImagesEnabled = false; + this->logTag = logTag; + this->saveImagesEnabled = false; this->imagesLocation = "/sdcard/log/source"; this->imagesRetention = 5; } std::string ClassLogImage::createLogFolder(std::string time) { - if (!saveImagesEnabled) - return ""; + if (!saveImagesEnabled) { + return ""; + } - std::string logPath = imagesLocation + "/" + time.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + time.DEFAULT_TIME_FORMAT_HOUR_EXTR; + std::string logPath = imagesLocation + "/" + time.DEFAULT_TIME_FORMAT_DATE_EXTR + "/" + time.DEFAULT_TIME_FORMAT_HOUR_EXTR; if (makeDirRecursive(logPath.c_str(), S_IRWXU) != 0) { LogFile.writeToFile(ESP_LOG_ERROR, logTag, "createLogFolder: failed to create folder. Path: " + logPath); return ""; } - return logPath; + return logPath; } -void ClassLogImage::logImage(std::string _logPath, std::string _sequenceName, CNNType _type, int _value, std::string _time, CImageBasis *_img) +void ClassLogImage::logImage(std::string _logPath, std::string _sequenceName, CNNType _type, int _value, std::string _time, + CImageBasis *_img) { - if (!saveImagesEnabled) - return; + if (!saveImagesEnabled) { + return; + } if (_logPath.empty()) { LogFile.writeToFile(ESP_LOG_ERROR, logTag, "logImage: logPath empty"); return; } - char valueBuf[10]; + char valueBuf[10]; if (_type == CNNTYPE_NONE) { // log with no label -> raw image valueBuf[0] = '\0'; @@ -63,26 +66,27 @@ void ClassLogImage::logImage(std::string _logPath, std::string _sequenceName, CN sprintf(valueBuf, "%d_", _value); } else { // ana-class100, dig-class100, dig-cont - sprintf(valueBuf, "%.1f_", _value/10.0); + sprintf(valueBuf, "%.1f_", _value / 10.0); } - std::string nm = _logPath + "/" + valueBuf + _sequenceName + "_" + _time + ".jpg"; - nm = formatFileName(nm); - std::string output = "/sdcard/img_tmp/" + _sequenceName + ".jpg"; - output = formatFileName(output); - ESP_LOGD(logTag, "save to file: %s", nm.c_str()); + std::string nm = _logPath + "/" + valueBuf + _sequenceName + "_" + _time + ".jpg"; + nm = formatFileName(nm); + std::string output = "/sdcard/img_tmp/" + _sequenceName + ".jpg"; + output = formatFileName(output); + ESP_LOGD(logTag, "save to file: %s", nm.c_str()); if (_img == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, logTag, "logImage: rawImage not initialized"); return; } - _img->saveToFile(nm); + _img->saveToFile(nm); } void ClassLogImage::removeOldLogs() { - if (!saveImagesEnabled) - return; + if (!saveImagesEnabled) { + return; + } if (imagesRetention == 0) { LogFile.writeToFile(ESP_LOG_DEBUG, logTag, "RemoveOldLogs: Retention deactivated"); @@ -91,7 +95,7 @@ void ClassLogImage::removeOldLogs() LogFile.writeToFile(ESP_LOG_DEBUG, logTag, "Delete image folder older than retention setting (This might take a while)"); - DIR* dir = opendir(imagesLocation.c_str()); + DIR *dir = opendir(imagesLocation.c_str()); if (!dir) { LogFile.writeToFile(ESP_LOG_ERROR, logTag, "Failed to open directory " + imagesLocation); return; @@ -100,37 +104,38 @@ void ClassLogImage::removeOldLogs() time_t rawtime; time(&rawtime); rawtime = addDays(rawtime, -imagesRetention + 1); - //ESP_LOGI(TAG, "imagesRetention: %d", imagesRetention); - std::string cmpfolderame = convertTimeToString(rawtime, DEFAULT_TIME_FORMAT).DEFAULT_TIME_FORMAT_DATE_EXTR; - //ESP_LOGI(TAG, "Delete all folder older than %s", cmpfolderame.c_str()); + // ESP_LOGI(TAG, "imagesRetention: %d", imagesRetention); + std::string cmpfolderame = convertTimeToString(rawtime, DEFAULT_TIME_FORMAT).DEFAULT_TIME_FORMAT_DATE_EXTR; + // ESP_LOGI(TAG, "Delete all folder older than %s", cmpfolderame.c_str()); struct dirent *entry; int deleted = 0; int notDeleted = 0; while ((entry = readdir(dir)) != NULL) { - if (entry->d_type == DT_DIR) { - //ESP_LOGD(TAG, "Compare folder %s to %s", entry->d_name, cmpfolderame.c_str()); - if ((strlen(entry->d_name) == cmpfolderame.length()) && (strcmp(entry->d_name, cmpfolderame.c_str()) < 0)) { + if (entry->d_type == DT_DIR) { + // ESP_LOGD(TAG, "Compare folder %s to %s", entry->d_name, cmpfolderame.c_str()); + if ((strlen(entry->d_name) == cmpfolderame.length()) && (strcmp(entry->d_name, cmpfolderame.c_str()) < 0)) { std::string folderpath = imagesLocation + "/" + entry->d_name; - //ESP_LOGI(TAG, "Delete folder %s", folderpath.c_str()); + // ESP_LOGI(TAG, "Delete folder %s", folderpath.c_str()); if (removeFolder(folderpath.c_str(), TAG) > 0) { deleted++; } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete folder " + folderpath); - notDeleted ++; + notDeleted++; } - } + } else { - notDeleted ++; + notDeleted++; } - } + } } closedir(dir); - LogFile.writeToFile(ESP_LOG_DEBUG, logTag, "Folders deleted: " + std::to_string(deleted) + " | Folders kept: " + std::to_string(notDeleted)); + LogFile.writeToFile(ESP_LOG_DEBUG, logTag, + "Folders deleted: " + std::to_string(deleted) + " | Folders kept: " + std::to_string(notDeleted)); } diff --git a/code/components/mainprocess_ctrl/MainFlowControl.cpp b/code/components/mainprocess_ctrl/MainFlowControl.cpp index 091cd616f..77a46da72 100644 --- a/code/components/mainprocess_ctrl/MainFlowControl.cpp +++ b/code/components/mainprocess_ctrl/MainFlowControl.cpp @@ -25,9 +25,9 @@ #include "psram.h" #ifdef ENABLE_MQTT - #include "interface_mqtt.h" - #include "server_mqtt.h" -#endif //ENABLE_MQTT +#include "interface_mqtt.h" +#include "server_mqtt.h" +#endif // ENABLE_MQTT static const char *TAG = "MAINCTRL"; @@ -54,8 +54,8 @@ bool doInit(void) // Deinit main flow components before init all ressources again // ******************************************** flowctrl.deinitFlow(); - //heap_caps_dump(MALLOC_CAP_INTERNAL); - //heap_caps_dump(MALLOC_CAP_SPIRAM); + // heap_caps_dump(MALLOC_CAP_INTERNAL); + // heap_caps_dump(MALLOC_CAP_SPIRAM); // Init cam if init not yet done. // Make sure this is called between deinit and init of flow components (avoid SPIRAM fragmentation) @@ -64,14 +64,15 @@ bool doInit(void) cameraCtrl.powerResetCamera(); esp_err_t camStatus = cameraCtrl.initCam(); - if (camStatus != ESP_OK) // Camera init failed + if (camStatus != ESP_OK) { // Camera init failed return false; + } LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init camera successful"); cameraCtrl.printCamInfo(); } - // // Init main flow components + // Init main flow components // ******************************************** if (!flowctrl.initFlow()) { flowctrl.deinitFlow(); @@ -82,18 +83,20 @@ bool doInit(void) // Note: It has to be initialized before MQTT (topic subscription) // and after flow init (MQTT main topic parameter) // ******************************************** - if (!gpio_handler_init()) + if (!gpio_handler_init()) { bRetVal = false; + } // Init MQTT service // ******************************************** - #ifdef ENABLE_MQTT - if (!flowctrl.initMqttService()) - bRetVal = false; - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + if (!flowctrl.initMqttService()) { + bRetVal = false; + } +#endif // ENABLE_MQTT - //heap_caps_dump(MALLOC_CAP_INTERNAL); - //heap_caps_dump(MALLOC_CAP_SPIRAM); + // heap_caps_dump(MALLOC_CAP_INTERNAL); + // heap_caps_dump(MALLOC_CAP_SPIRAM); return bRetVal; } @@ -104,16 +107,15 @@ esp_err_t triggerReloadConfig(httpd_req_t *req) httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_type(req, "text/plain"); - if (taskAutoFlowState == FLOW_TASK_STATE_INIT || - taskAutoFlowState == FLOW_TASK_STATE_SETUPMODE || - taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART) - { + if (taskAutoFlowState == FLOW_TASK_STATE_INIT || taskAutoFlowState == FLOW_TASK_STATE_SETUPMODE || + taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART) { const std::string zw = "001: Reload config and redo flow initialization (" + getCurrentTimeString("%H:%M:%S") + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); reloadConfig = true; } else if (taskAutoFlowState == FLOW_TASK_STATE_INIT_DELAYED) { - const std::string zw = "002: Abort waiting delay and continue with process initialization (" + getCurrentTimeString("%H:%M:%S") + ")"; + const std::string zw = "002: Abort waiting delay and continue with process initialization (" + getCurrentTimeString("%H:%M:%S") + + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state. } @@ -123,10 +125,8 @@ esp_err_t triggerReloadConfig(httpd_req_t *req) reloadConfig = true; xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state. } - else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || - taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || - taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) - { + else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || + taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Reload config and schedule process reinitialization"); const std::string zw = "004: Reload config and reinitialization got scheduled (" + getCurrentTimeString("%H:%M:%S") + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); @@ -144,47 +144,41 @@ esp_err_t triggerReloadConfig(httpd_req_t *req) #ifdef ENABLE_MQTT esp_err_t triggerFlowStartByMqtt(std::string _topic) { - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || - taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) - { + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by MQTT topic " + _topic); manualFlowStart = true; - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state + } } - else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || - taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || - taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) - { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by MQTT topic "+ _topic + " got scheduled"); + else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || + taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) { + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by MQTT topic " + _topic + " got scheduled"); manualFlowStart = true; } else { - LogFile.writeToFile(ESP_LOG_WARN, TAG, "Cycle start triggered by MQTT topic " + _topic + ". Main task not initialized. Request rejected"); + LogFile.writeToFile(ESP_LOG_WARN, TAG, + "Cycle start triggered by MQTT topic " + _topic + ". Main task not initialized. Request rejected"); } return ESP_OK; } -#endif //ENABLE_MQTT - +#endif // ENABLE_MQTT void triggerFlowStartByGpio() { - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || - taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) - { + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by GPIO"); manualFlowStart = true; - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state + } } - else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || - taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || - taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) - { + else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || + taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by GPIO got scheduled"); manualFlowStart = true; } @@ -199,8 +193,7 @@ esp_err_t handler_cycle_start(httpd_req_t *req) httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_type(req, "text/plain"); - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || - taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART || + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_NO_AUTOSTART || taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART || flowctrl.getActualProcessState() == FLOW_INIT_WAITING_TIME_SYNC || flowctrl.getActualProcessState() == FLOW_INIT_FAILED) // Possibility to manual retrigger a cycle when init is already failed { @@ -209,13 +202,12 @@ esp_err_t handler_cycle_start(httpd_req_t *req) httpd_resp_send(req, zw.c_str(), zw.length()); manualFlowStart = true; - if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) + if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state + } } - else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || - taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || - taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) - { + else if (taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING || taskAutoFlowState == FLOW_TASK_STATE_PUBLISH_DATA || + taskAutoFlowState == FLOW_TASK_STATE_ADDITIONAL_TASKS) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by REST API got scheduled"); const std::string zw = "002: Cycle start triggered by REST API got scheduled (" + getCurrentTimeString("%H:%M:%S") + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); @@ -224,13 +216,15 @@ esp_err_t handler_cycle_start(httpd_req_t *req) } else if (taskAutoFlowState == FLOW_TASK_STATE_INIT_DELAYED) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Cycle start triggered by REST API (abort state 'Initialization (delayed)'"); - const std::string zw = "003: Cycle start triggered by REST API abort initialization delay (" + getCurrentTimeString("%H:%M:%S") + ")"; + const std::string zw = "003: Cycle start triggered by REST API abort initialization delay (" + getCurrentTimeString("%H:%M:%S") + + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state } else { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Cycle start triggered by REST API. Main task not initialized. Request rejected"); - const std::string zw = "E90: Cycle start triggered by REST API. Main task not initialized. Request rejected (" + getCurrentTimeString("%H:%M:%S") + ")"; + const std::string zw = "E90: Cycle start triggered by REST API. Main task not initialized. Request rejected (" + + getCurrentTimeString("%H:%M:%S") + ")"; httpd_resp_send(req, zw.c_str(), zw.length()); } @@ -251,7 +245,8 @@ esp_err_t handler_fallbackvalue(httpd_req_t *req) const std::string RESTUsageInfo = "Handler usage:
" "- To retrieve actual Fallback Value, please provide a number sequence name only, e.g. /set_fallbackvalue?sequence=main
" - "- To set Fallback Value to a new value, please provide a number sequence name and a value, e.g. /set_fallbackvalue?sequence=main&value=1234.5678
" + "- To set Fallback Value to a new value, please provide a number sequence name and a value, e.g. " + "/set_fallbackvalue?sequence=main&value=1234.5678
" "NOTE:
" "value >= 0.0: Set Fallback Value to provided value
" "value < 0.0: Set Fallback Value to actual RAW value (as long RAW value is a valid number, without N)"; @@ -276,10 +271,10 @@ esp_err_t handler_fallbackvalue(httpd_req_t *req) } if (httpd_query_key_value(query, "value", value, sizeof(value)) == ESP_OK) { - //ESP_LOGD(TAG, "Value: %s", value); + // ESP_LOGD(TAG, "Value: %s", value); } } - else { // if no parameter is provided, print handler usage + else { // if no parameter is provided, print handler usage httpd_resp_set_type(req, "text/html"); httpd_resp_send(req, RESTUsageInfo.c_str(), RESTUsageInfo.length()); return ESP_OK; @@ -297,8 +292,9 @@ esp_err_t handler_fallbackvalue(httpd_req_t *req) else { // New value is positive: Set FallbackValue to provided value and return value // New value is negative and actual RAW value is a valid number: Set FallbackValue to RAW value and return value - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "REST API handler_fallbackvalue called: sequence: " + std::string(numberSequence) + - ", value: " + std::string(value)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "REST API handler_fallbackvalue called: sequence: " + std::string(numberSequence) + + ", value: " + std::string(value)); if (!flowctrl.setFallbackValue(numberSequence, value)) { sReturnMessage = "E93: Update request rejected. Please check device logs for more details"; httpd_resp_send(req, sReturnMessage.c_str(), sReturnMessage.length()); @@ -322,7 +318,7 @@ esp_err_t handler_fallbackvalue(httpd_req_t *req) esp_err_t handler_editflow(httpd_req_t *req) { - const char* APIName = "editflow:v3"; // API name and version + const char *APIName = "editflow:v3"; // API name and version char query[200]; char valuechar[30]; std::string task; @@ -393,13 +389,13 @@ esp_err_t handler_editflow(httpd_req_t *req) httpd_query_key_value(query, "dy", valuechar, sizeof(valuechar)); int dy = std::stoi(std::string(valuechar)); - in = "/sdcard" + in; // --> img_tmp/reference.jpg - out = "/sdcard" + out; // --> img_tmp/markerX.jpg + in = "/sdcard" + in; // --> img_tmp/reference.jpg + out = "/sdcard" + out; // --> img_tmp/markerX.jpg // 4MB RAM external SPIRAM are not sufficient to perform alignment marker update while processing cycle // Reuse allocated memory of CImageBasis element "rawImage" (ClassTakeImage.cpp) and interlock operation at UI level if (taskAutoFlowState >= FLOW_TASK_STATE_IDLE_NO_AUTOSTART && getSPIRAMCategory() == SPIRAMCategory_4MB) { - STBIObjectPSRAM.name="rawImage"; + STBIObjectPSRAM.name = "rawImage"; STBIObjectPSRAM.usePreallocated = true; STBIObjectPSRAM.PreallocatedMemory = flowctrl.getRawImage()->getRgbImage(); STBIObjectPSRAM.PreallocatedMemorySize = flowctrl.getRawImage()->getMemsize(); @@ -408,7 +404,7 @@ esp_err_t handler_editflow(httpd_req_t *req) STBIObjectPSRAM.usePreallocated = false; } // Create element, be aware: CImageBasis of reference.jpg will be created first (921kB RAM needed) - CAlignAndCutImage* caic = new CAlignAndCutImage("cutref1", in, STBIObjectPSRAM.usePreallocated); + CAlignAndCutImage *caic = new CAlignAndCutImage("cutref1", in, STBIObjectPSRAM.usePreallocated); caic->cutAndSaveImage(out, x, y, dx, dy); delete caic; @@ -434,7 +430,7 @@ esp_err_t handler_process_data(httpd_req_t *req) return ESP_FAIL; } - const char* APIName = "process_data:v3"; // API name and version + const char *APIName = "process_data:v3"; // API name and version char query[200]; char valuechar[30]; std::string type, numberSequence; @@ -457,73 +453,103 @@ esp_err_t handler_process_data(httpd_req_t *req) return ESP_FAIL; } - if (cJSON_AddStringToObject(cJSONObject, "api_name", APIName) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "api_name", APIName) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "number_sequences", flowctrl.getSequenceData().size()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "number_sequences", flowctrl.getSequenceData().size()) == NULL) { retVal = ESP_FAIL; + } cJSON *cJSONObjectTimestampProcessed; - if (!cJSON_AddItemToObject(cJSONObject, "timestamp_processed", cJSONObjectTimestampProcessed = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "timestamp_processed", cJSONObjectTimestampProcessed = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectTimestampFallbackValue; - if (!cJSON_AddItemToObject(cJSONObject, "timestamp_fallbackvalue", cJSONObjectTimestampFallbackValue = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "timestamp_fallbackvalue", cJSONObjectTimestampFallbackValue = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectActualValue; - if (!cJSON_AddItemToObject(cJSONObject, "actual_value", cJSONObjectActualValue = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "actual_value", cJSONObjectActualValue = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectFallbackValue; - if (!cJSON_AddItemToObject(cJSONObject, "fallback_value", cJSONObjectFallbackValue = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "fallback_value", cJSONObjectFallbackValue = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectRawValue; - if (!cJSON_AddItemToObject(cJSONObject, "raw_value", cJSONObjectRawValue = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "raw_value", cJSONObjectRawValue = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectValueStatus; - if (!cJSON_AddItemToObject(cJSONObject, "value_status", cJSONObjectValueStatus = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "value_status", cJSONObjectValueStatus = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectRatePerMin; - if (!cJSON_AddItemToObject(cJSONObject, "rate_per_minute", cJSONObjectRatePerMin = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "rate_per_minute", cJSONObjectRatePerMin = cJSON_CreateObject())) { retVal = ESP_FAIL; + } cJSON *cJSONObjectRatePerInterval; - if (!cJSON_AddItemToObject(cJSONObject, "rate_per_interval", cJSONObjectRatePerInterval = cJSON_CreateObject())) + if (!cJSON_AddItemToObject(cJSONObject, "rate_per_interval", cJSONObjectRatePerInterval = cJSON_CreateObject())) { retVal = ESP_FAIL; + } - for(const auto &sequence : flowctrl.getSequenceData()) { - if (cJSON_AddStringToObject(cJSONObjectTimestampProcessed, sequence->sequenceName.c_str(), sequence->sTimeProcessed.c_str()) == NULL) + for (const auto &sequence : flowctrl.getSequenceData()) { + if (cJSON_AddStringToObject(cJSONObjectTimestampProcessed, sequence->sequenceName.c_str(), sequence->sTimeProcessed.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectTimestampFallbackValue, sequence->sequenceName.c_str(), sequence->sTimeFallbackValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectTimestampFallbackValue, sequence->sequenceName.c_str(), + sequence->sTimeFallbackValue.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectActualValue, sequence->sequenceName.c_str(), sequence->sActualValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectActualValue, sequence->sequenceName.c_str(), sequence->sActualValue.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectFallbackValue, sequence->sequenceName.c_str(), sequence->sFallbackValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectFallbackValue, sequence->sequenceName.c_str(), sequence->sFallbackValue.c_str()) == + NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectRawValue, sequence->sequenceName.c_str(), sequence->sRawValue.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectRawValue, sequence->sequenceName.c_str(), sequence->sRawValue.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectValueStatus, sequence->sequenceName.c_str(), sequence->sValueStatus.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectValueStatus, sequence->sequenceName.c_str(), sequence->sValueStatus.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectRatePerMin, sequence->sequenceName.c_str(), sequence->sRatePerMin.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectRatePerMin, sequence->sequenceName.c_str(), sequence->sRatePerMin.c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObjectRatePerInterval, sequence->sequenceName.c_str(), sequence->sRatePerInterval.c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectRatePerInterval, sequence->sequenceName.c_str(), sequence->sRatePerInterval.c_str()) == + NULL) { retVal = ESP_FAIL; + } } - if (cJSON_AddStringToObject(cJSONObject, "process_status", getProcessStatus().c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "process_status", getProcessStatus().c_str()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "process_interval", (int)(flowctrl.getProcessInterval() * 10) / 10.0) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "process_interval", (int)(flowctrl.getProcessInterval() * 10) / 10.0) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "process_time", getFlowProcessingTime()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "process_time", getFlowProcessingTime()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddStringToObject(cJSONObject, "process_state", flowctrl.getActualProcessStateWithTime().c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "process_state", flowctrl.getActualProcessStateWithTime().c_str()) == NULL) { retVal = ESP_FAIL; + } // 0: No error, -1: Error occured, -2: Multiple errors in a row, 1: Deviation occured, 2: Multiple deviaton in a row - if (cJSON_AddNumberToObject(cJSONObject, "process_error", flowctrl.getFlowStateErrorOrDeviation()) == NULL) + if (cJSON_AddNumberToObject(cJSONObject, "process_error", flowctrl.getFlowStateErrorOrDeviation()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "device_uptime", getUptime()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "device_uptime", getUptime()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "cycle_counter", getFlowCycleCounter()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "cycle_counter", getFlowCycleCounter()) == NULL) { retVal = ESP_FAIL; - if (cJSON_AddNumberToObject(cJSONObject, "wlan_rssi", getWifiRssi()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "wlan_rssi", getWifiRssi()) == NULL) { retVal = ESP_FAIL; + } // Print to preallocted buffer char *jsonData = ((struct HttpServerData *)req->user_ctx)->scratch; @@ -537,10 +563,12 @@ esp_err_t handler_process_data(httpd_req_t *req) httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_type(req, "application/json"); - if (retVal == ESP_OK) + if (retVal == ESP_OK) { httpd_resp_send(req, jsonData, strlen(jsonData)); - else + } + else { httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "E92: Error while adding JSON elements"); + } return retVal; } @@ -655,16 +683,21 @@ esp_err_t handler_process_data(httpd_req_t *req) } else if (type.compare("process_error") == 0) { // 000: No error, E01: Error occured, E02: Multiple errors in a row, 001: Deviation occured, 002: Multiple deviaton in a row - if (flowctrl.getFlowStateErrorOrDeviation() == 0) + if (flowctrl.getFlowStateErrorOrDeviation() == 0) { httpd_resp_sendstr(req, "000: No process error/deviation"); - else if (flowctrl.getFlowStateErrorOrDeviation() == -2) + } + else if (flowctrl.getFlowStateErrorOrDeviation() == -2) { httpd_resp_sendstr(req, "E02: Multiple process errors in row"); - else if (flowctrl.getFlowStateErrorOrDeviation() == 2) + } + else if (flowctrl.getFlowStateErrorOrDeviation() == 2) { httpd_resp_sendstr(req, "002: Multiple process deviation in row"); - else if (flowctrl.getFlowStateErrorOrDeviation() == -1) + } + else if (flowctrl.getFlowStateErrorOrDeviation() == -1) { httpd_resp_sendstr(req, "E01: Process error occured"); - else if (flowctrl.getFlowStateErrorOrDeviation() == 1) + } + else if (flowctrl.getFlowStateErrorOrDeviation() == 1) { httpd_resp_sendstr(req, "001: Process deviation occured"); + } return ESP_OK; } else if (type.compare("device_uptime") == 0) { @@ -688,7 +721,7 @@ esp_err_t handler_process_data(httpd_req_t *req) esp_err_t handler_recognition_details(httpd_req_t *req) { - const char* APIName = "recognition_details:v1"; // API name and version + const char *APIName = "recognition_details:v1"; // API name and version char query[100]; char valuechar[30]; std::string type, zw; @@ -710,25 +743,31 @@ esp_err_t handler_recognition_details(httpd_req_t *req) /*++++++++++++++++++++++++++++++++++++++++*/ /* Page details */ - std::string txt = "Recognition Details\n"; - txt += ""; + std::string txt = + "Recognition Details\n"; + txt += ""; txt += "

Recognition Details

\n"; txt += "
\n"; txt += "CLICK HERE for more information\n"; txt += "

On this page recognition details including the underlaying ROI image are visualized. " - "
Be aware: The visualized infos are representing the last fully completed image evaluation of a digitalization cycle.

"; + "
Be aware: The visualized infos are representing the last fully completed image evaluation of a digitalization " + "cycle.

"; txt += "

\"Raw Value\" represents the value which gets extracted and combined from all the single image results but without " - "correction of any of the post-processing checks / alogrithms. The result after post-processing validation is represented with " - "\"Value\". In the sections \"Digit ROI\" and \"Analog ROI\" all single \"raw results\" of the respective ROI images (digit styled ROI and " - "analog styled ROI) are visualized separated per number sequence. The taken image which was used for processing (including the overlays " - "to highlight the relevant areas) is visualized at the bottom of this page.

"; + "correction of any of the post-processing checks / alogrithms. The result after post-processing validation is represented with " + "\"Value\". In the sections \"Digit ROI\" and \"Analog ROI\" all single \"raw results\" of the respective ROI images (digit " + "styled ROI and " + "analog styled ROI) are visualized separated per number sequence. The taken image which was used for processing (including the " + "overlays " + "to highlight the relevant areas) is visualized at the bottom of this page.

"; txt += "

\n"; // Display message if flow is not initialized or image processing active if (taskAutoFlowState < 3 || taskAutoFlowState == FLOW_TASK_STATE_IMG_PROCESSING) { txt += "

" - "Image recognition details are only accessable if initialization is completed and no image evaluation is ongoing. " - "Wait a few moments and refresh this page.

Current state: " + flowctrl.getActualProcessState(); + "Image recognition details are only accessable if initialization is completed and no image evaluation is ongoing. " + "Wait a few moments and refresh this page. Current state: " + + flowctrl.getActualProcessState(); httpd_resp_sendstr_chunk(req, txt.c_str()); } else { @@ -736,15 +775,20 @@ esp_err_t handler_recognition_details(httpd_req_t *req) /* Result */ txt += "

Result

\n"; txt += "
NameTypeSize" - "
" - "
"; - txt += "" - "" - ""; + txt += + "" + "" + ""; for (const auto &sequence : flowctrl.getSequenceData()) { txt += ""; + sequence->sequenceName + + ""; } txt += "
Number SequenceRaw ValueActual Value
Number SequenceRaw ValueActual " + "Value
" + - sequence->sequenceName + "" + - sequence->sRawValue + "" + - sequence->sActualValue + "
" + + sequence->sRawValue + + "" + + sequence->sActualValue + "
\n"; @@ -761,20 +805,24 @@ esp_err_t handler_recognition_details(httpd_req_t *req) else { for (const auto &sequence : flowctrl.getSequenceData()) { txt += "Number Sequence: " + - sequence->sequenceName + "\n"; + sequence->sequenceName + "\n"; txt += "\n"; if (!sequence->digitRoi.empty()) { for (const auto &roi : sequence->digitRoi) { - if (roi->CNNResult > -1) // Only show image if result is set, otherwise text "No Image" + if (roi->CNNResult > -1) { // Only show image if result is set, otherwise text "No Image" txt += "

" + - roi->sCNNResult + "

digitRoi.size() + 1), 0) + - "px\" src=\"/img_tmp/" + roi->param->roiName + "_org.jpg\">

\n"; - else + roi->sCNNResult + + "

digitRoi.size() + 1), 0) + "px\" src=\"/img_tmp/" + + roi->param->roiName + "_org.jpg\">

\n"; + } + else { txt += "

" + - roi->sCNNResult + "

No Image

\n"; - + roi->sCNNResult + + "

No Image

\n"; + } } } else { @@ -797,19 +845,24 @@ esp_err_t handler_recognition_details(httpd_req_t *req) else { for (const auto &sequence : flowctrl.getSequenceData()) { txt += "Number Sequence: " + - sequence->sequenceName + "\n"; + sequence->sequenceName + "\n"; txt += "\n"; if (!sequence->analogRoi.empty()) { for (const auto &roi : sequence->analogRoi) { - if (roi->CNNResult > -1) // Only show image if result is set, otherwise text "No Image" + if (roi->CNNResult > -1) { // Only show image if result is set, otherwise text "No Image" txt += "

" + - roi->sCNNResult + "

analogRoi.size() + 1), 0) + - "px\" src=\"/img_tmp/" + roi->param->roiName + "_org.jpg\">

\n"; - else + roi->sCNNResult + + "

analogRoi.size() + 1), 0) + "px\" src=\"/img_tmp/" + + roi->param->roiName + "_org.jpg\">

\n"; + } + else { txt += "

" + - roi->sCNNResult + "

No Image

\n"; + roi->sCNNResult + + "

No Image

\n"; + } } } else { @@ -851,14 +904,18 @@ std::string getProcessStatus(void) { std::string process_status; - if (flowctrl.isAutoStart() && (taskAutoFlowState >= 4 && taskAutoFlowState <= 7)) + if (flowctrl.isAutoStart() && (taskAutoFlowState >= 4 && taskAutoFlowState <= 7)) { process_status = "Processing (Automatic)"; - else if (!flowctrl.isAutoStart() && (taskAutoFlowState >= 3 && taskAutoFlowState <= 7)) + } + else if (!flowctrl.isAutoStart() && (taskAutoFlowState >= 3 && taskAutoFlowState <= 7)) { process_status = "Processing (Triggered Only)"; - else if (taskAutoFlowState >= 0 && taskAutoFlowState < 3) + } + else if (taskAutoFlowState >= 0 && taskAutoFlowState < 3) { process_status = "Not Processing / Not Ready"; - else + } + else { process_status = "Status unknown: " + taskAutoFlowState; + } return process_status; } @@ -889,11 +946,11 @@ void task_autodoFlow(void *pvParameter) if (flowctrl.getStatusSetupModus()) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_SETUP_MODE)); flowctrl.setActualProcessState(std::string(FLOW_SETUP_MODE)); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); +#endif // ENABLE_MQTT - while (true) { // Waiting for a REQUEST + while (true) { // Waiting for a REQUEST vTaskDelay(1000 / portTICK_PERIOD_MS); if (reloadConfig) { reloadConfig = false; @@ -901,14 +958,14 @@ void task_autodoFlow(void *pvParameter) ConfigClass::getInstance()->reinitConfig(); if (!flowctrl.getStatusSetupModus()) { - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Setup Mode done --> Do FLOW INIT + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Setup Mode done --> Do FLOW INIT break; } } } } else { - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Setup Mode done --> Do FLOW INIT + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Setup Mode done --> Do FLOW INIT } } @@ -922,7 +979,7 @@ void task_autodoFlow(void *pvParameter) flowctrl.setFlowStateError(); // Right now, it's not possible to provide state via MQTT because mqtt service is not yet started - vTaskDelay(60*5000 / portTICK_PERIOD_MS); // Wait 5 minutes to give time to do an OTA update or fetch the log + vTaskDelay(60 * 5000 / portTICK_PERIOD_MS); // Wait 5 minutes to give time to do an OTA update or fetch the log taskAutoFlowState = FLOW_TASK_STATE_INIT; // Continue to FLOW INIT } @@ -939,10 +996,12 @@ void task_autodoFlow(void *pvParameter) LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Process state: " + std::string(FLOW_INIT_FAILED)); flowctrl.setActualProcessState(std::string(FLOW_INIT_FAILED)); flowctrl.setFlowStateError(); - #ifdef ENABLE_MQTT - if (getMqttIsConnected()) - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + if (getMqttIsConnected()) { + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, + false); + } +#endif // ENABLE_MQTT while (true) { // Waiting for a REQUEST vTaskDelay(1000 / portTICK_PERIOD_MS); @@ -950,13 +1009,13 @@ void task_autodoFlow(void *pvParameter) reloadConfig = false; manualFlowStart = false; // parameter reload has higher prio LogFile.writeToFile(ESP_LOG_INFO, TAG, "Trigger: Reload configuration"); - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Repeat FLOW INIT + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Repeat FLOW INIT break; } else if (manualFlowStart) { // Possibility to manual retrigger a cycle with manual start when init is already failed manualFlowStart = false; LogFile.writeToFile(ESP_LOG_INFO, TAG, "Trigger: Start process (manual trigger)"); - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Repeat FLOW INIT + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Repeat FLOW INIT break; } } @@ -964,14 +1023,15 @@ void task_autodoFlow(void *pvParameter) else { // Waiting for NTP time sync to ensure process start with valid time if (ConfigClass::getInstance()->get()->sectionNetwork.time.ntp.timeSyncEnabled && - ConfigClass::getInstance()->get()->sectionNetwork.time.ntp.processStartInterlock) - { + ConfigClass::getInstance()->get()->sectionNetwork.time.ntp.processStartInterlock) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process start interlock: Waiting for time sync"); flowctrl.setActualProcessState(std::string(FLOW_INIT_WAITING_TIME_SYNC)); - #ifdef ENABLE_MQTT - if (getMqttIsConnected()) - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + if (getMqttIsConnected()) { + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, + false); + } +#endif // ENABLE_MQTT while (true) { // Waiting for time sync vTaskDelay(1000 / portTICK_PERIOD_MS); @@ -1009,9 +1069,9 @@ void task_autodoFlow(void *pvParameter) if (!flowctrl.isAutoStart(automaticProcessInterval)) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_IDLE_NO_AUTOSTART)); flowctrl.setActualProcessState(std::string(FLOW_IDLE_NO_AUTOSTART)); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); +#endif // ENABLE_MQTT while (true) { // Waiting for a REQUEST vTaskDelay(1000 / portTICK_PERIOD_MS); @@ -1051,14 +1111,14 @@ void task_autodoFlow(void *pvParameter) cylceStartActualTime = esp_timer_get_time(); if (flowctrl.doFlowImageEvaluation(getCurrentTimeString(DEFAULT_TIME_FORMAT))) { - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Image evaluation completed (" + - std::to_string(getUptime() - cycleStartTime) + "s)"); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Image evaluation completed (" + std::to_string(getUptime() - cycleStartTime) + "s)"); } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Image evaluation: Process error occured"); } - taskAutoFlowState = FLOW_TASK_STATE_PUBLISH_DATA; // Continue with TASKS after FLOW FINISHED + taskAutoFlowState = FLOW_TASK_STATE_PUBLISH_DATA; // Continue with TASKS after FLOW FINISHED } // PUBLISH DATA / RESULTS @@ -1073,7 +1133,7 @@ void task_autodoFlow(void *pvParameter) else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "No WLAN connection, skip publishing services"); } - taskAutoFlowState = FLOW_TASK_STATE_ADDITIONAL_TASKS; // Continue with TASKS after FLOW FINISHED + taskAutoFlowState = FLOW_TASK_STATE_ADDITIONAL_TASKS; // Continue with TASKS after FLOW FINISHED } // ADDITIONAL TASKS @@ -1086,27 +1146,27 @@ void task_autodoFlow(void *pvParameter) LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_POST_EVENT_HANDLING)); flowctrl.setActualProcessState(std::string(FLOW_POST_EVENT_HANDLING)); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); +#endif // ENABLE_MQTT flowctrl.postProcessEventHandler(); LogFile.removeOldDebugFiles(); } else { flowctrl.clearFlowStateEventInRowCounter(); - #ifdef ENABLE_MQTT - publishMqttData(std::string(mqttServer_getMainTopic() + "/process/status/process_error"), "0", 1, false); - #endif +#ifdef ENABLE_MQTT + publishMqttData(std::string(mqttServer_getMainTopic() + "/process/status/process_error"), "0", 1, false); +#endif // ENABLE_MQTT } // Additional tasks // ******************************************** LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_ADDITIONAL_TASKS)); flowctrl.setActualProcessState(std::string(FLOW_ADDITIONAL_TASKS)); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); +#endif // ENABLE_MQTT // Cleanup outdated log and data files (retention policy) LogFile.removeOldLogFile(); @@ -1120,8 +1180,8 @@ void task_autodoFlow(void *pvParameter) processingTime = (int)(getUptime() - cycleStartTime); // Cycle finished -> Logfile - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Cycle #" + std::to_string(cycleCounter) + - " completed (" + std::to_string(processingTime) + "s)"); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Cycle #" + std::to_string(cycleCounter) + " completed (" + std::to_string(processingTime) + "s)"); // Check if time is synchronized (if NTP is configured) if (getUseNtp() && !getTimeIsSynced()) { @@ -1130,22 +1190,22 @@ void task_autodoFlow(void *pvParameter) } // WIFI roaming handling (if activated) - // ******************************************** // Trigger client triggered roaming query - #if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES) - wifiRoamingQuery(); - #endif + // ******************************************** +#if (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES) + wifiRoamingQuery(); +#endif // WLAN_USE_MESH_ROAMING // Scan channels and check if an AP with better RSSI is available, then disconnect and try to reconnect to AP with better RSSI // NOTE: Keep this at the end of this state, because scan is done in blocking mode and this takes ca. 1,5 - 2s. - #ifdef WLAN_USE_ROAMING_BY_SCANNING - wifiRoamByScanning(); - #endif +#ifdef WLAN_USE_ROAMING_BY_SCANNING + wifiRoamByScanning(); +#endif // WLAN_USE_ROAMING_BY_SCANNING // Check if triggerd reload config or manually triggered single cycle // ******************************************** if (taskAutoFlowState == FLOW_TASK_STATE_INIT) { - reloadConfig = false; // reload by post process event handler has higher prio + reloadConfig = false; // reload by post process event handler has higher prio manualFlowStart = false; // Reload config has higher prio LogFile.writeToFile(ESP_LOG_INFO, TAG, "postProcessEventHandler trigger: Reload configuration"); } @@ -1153,20 +1213,20 @@ void task_autodoFlow(void *pvParameter) reloadConfig = false; manualFlowStart = false; // Reload config has higher prio LogFile.writeToFile(ESP_LOG_INFO, TAG, "Manual trigger: Reload configuration"); - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Return to state "FLOW INIT" + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Return to state "FLOW INIT" } else if (manualFlowStart) { manualFlowStart = false; if (flowctrl.isAutoStart()) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Start process (manual trigger)"); - taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle" + taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle" } else { - taskAutoFlowState = FLOW_TASK_STATE_IDLE_NO_AUTOSTART; // Return to state "Idle (NO AUTOSTART)" + taskAutoFlowState = FLOW_TASK_STATE_IDLE_NO_AUTOSTART; // Return to state "Idle (NO AUTOSTART)" } } else { - taskAutoFlowState = FLOW_TASK_STATE_IDLE_AUTOSTART; // Continue to state "Idle (AUTOSTART / WAITING STATE)" + taskAutoFlowState = FLOW_TASK_STATE_IDLE_AUTOSTART; // Continue to state "Idle (AUTOSTART / WAITING STATE)" } } @@ -1176,9 +1236,9 @@ void task_autodoFlow(void *pvParameter) else if (taskAutoFlowState == FLOW_TASK_STATE_IDLE_AUTOSTART) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_IDLE_AUTOSTART)); flowctrl.setActualProcessState(std::string(FLOW_IDLE_AUTOSTART)); - #ifdef ENABLE_MQTT - publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); - #endif //ENABLE_MQTT +#ifdef ENABLE_MQTT + publishMqttData(mqttServer_getMainTopic() + "/process/status/process_state", flowctrl.getActualProcessState(), 1, false); +#endif // ENABLE_MQTT // WLAN suspention handling (if activated) // Check whether WLAN set to suspended mode based on configured delay time @@ -1196,15 +1256,15 @@ void task_autodoFlow(void *pvParameter) reloadConfig = false; manualFlowStart = false; // Reload config has higher prio LogFile.writeToFile(ESP_LOG_INFO, TAG, "Trigger: Reload configuration"); - taskAutoFlowState = FLOW_TASK_STATE_INIT; // Return to state "FLOW INIT" + taskAutoFlowState = FLOW_TASK_STATE_INIT; // Return to state "FLOW INIT" } else if (manualFlowStart) { manualFlowStart = false; LogFile.writeToFile(ESP_LOG_INFO, TAG, "Start process (manual trigger)"); - taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle" + taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle" } else { - taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle + taskAutoFlowState = FLOW_TASK_STATE_IMG_PROCESSING; // Continue with next "FLOW PROCESSING" cycle } } @@ -1227,40 +1287,40 @@ void task_autodoFlow(void *pvParameter) void createMainFlowTask() { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CreateFlowTask: start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CreateFlowTask: start"); +#endif // DEBUG_DETAIL_ON LogFile.writeToFile(ESP_LOG_INFO, TAG, "Process state: " + std::string(FLOW_CREATE_FLOW_TASK)); flowctrl.setActualProcessState(std::string(FLOW_CREATE_FLOW_TASK)); - BaseType_t xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", 12 * 1024, NULL, tskIDLE_PRIORITY + 3, &xHandletask_autodoFlow, 0); - if( xReturned != pdPASS ) { + BaseType_t xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", 12 * 1024, NULL, tskIDLE_PRIORITY + 3, + &xHandletask_autodoFlow, 0); + if (xReturned != pdPASS) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create task_autodoFlow"); LogFile.writeHeapInfo("CreateFlowTask: Failed to create task"); flowctrl.setActualProcessState(std::string(FLOW_FLOW_TASK_FAILED)); flowctrl.setFlowStateError(); } - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("CreateFlowTask: end"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("CreateFlowTask: end"); +#endif // DEBUG_DETAIL_ON } void deleteMainFlowTask() { - #ifdef DEBUG_DETAIL_ON - ESP_LOGD(TAG, "deleteMainFlowTask: xHandletask_autodoFlow: %ld", (long) xHandletask_autodoFlow); - #endif - if( xHandletask_autodoFlow != NULL ) - { +#ifdef DEBUG_DETAIL_ON + ESP_LOGD(TAG, "deleteMainFlowTask: xHandletask_autodoFlow: %ld", (long)xHandletask_autodoFlow); +#endif // DEBUG_DETAIL_ON + if (xHandletask_autodoFlow != NULL) { vTaskDelete(xHandletask_autodoFlow); xHandletask_autodoFlow = NULL; } - #ifdef DEBUG_DETAIL_ON - ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow"); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow"); +#endif // DEBUG_DETAIL_ON } @@ -1268,31 +1328,31 @@ void registerMainFlowTaskUri(httpd_handle_t server) { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t camuri = { }; - camuri.method = HTTP_GET; + httpd_uri_t camuri = {}; + camuri.method = HTTP_GET; - camuri.uri = "/cycle_start"; - camuri.handler = handler_cycle_start; - camuri.user_ctx = NULL; + camuri.uri = "/cycle_start"; + camuri.handler = handler_cycle_start; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); - camuri.uri = "/set_fallbackvalue"; - camuri.handler = handler_fallbackvalue; - camuri.user_ctx = NULL; + camuri.uri = "/set_fallbackvalue"; + camuri.handler = handler_fallbackvalue; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); - camuri.uri = "/editflow"; - camuri.handler = handler_editflow; - camuri.user_ctx = NULL; + camuri.uri = "/editflow"; + camuri.handler = handler_editflow; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); - camuri.uri = "/process_data"; - camuri.handler = handler_process_data; - camuri.user_ctx = httpServerData; // Pass server data as context + camuri.uri = "/process_data"; + camuri.handler = handler_process_data; + camuri.user_ctx = httpServerData; // Pass server data as context httpd_register_uri_handler(server, &camuri); - camuri.uri = "/recognition_details"; - camuri.handler = handler_recognition_details; - camuri.user_ctx = NULL; + camuri.uri = "/recognition_details"; + camuri.handler = handler_recognition_details; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); } diff --git a/code/components/misc_helper/helper.cpp b/code/components/misc_helper/helper.cpp index b001e231b..c82062a58 100644 --- a/code/components/misc_helper/helper.cpp +++ b/code/components/misc_helper/helper.cpp @@ -1,4 +1,4 @@ -//#pragma warning(disable : 4996) +// #pragma warning(disable : 4996) #include "helper.h" #include "../../include/defines.h" @@ -25,115 +25,117 @@ extern "C" { #include "ClassLogFile.h" -static const char* TAG = "HELPER"; +static const char *TAG = "HELPER"; // File related helper // ********************************************************** bool fileExists(std::string filename) { - FILE* fpFile = fopen(filename.c_str(), "rb"); - if (!fpFile) { // File not existing - return false; - } - fclose(fpFile); - return true; + FILE *fpFile = fopen(filename.c_str(), "rb"); + if (!fpFile) { // File not existing + return false; + } + fclose(fpFile); + return true; } bool copyFile(std::string input, std::string output) { - input = formatFileName(input); - output = formatFileName(output); + input = formatFileName(input); + output = formatFileName(output); - char cTemp; - FILE* fpSourceFile = fopen(input.c_str(), "rb"); - if (!fpSourceFile) { // File not existing - ESP_LOGE(TAG, "copyFile: File %s not existing", input.c_str()); - return false; - } + char cTemp; + FILE *fpSourceFile = fopen(input.c_str(), "rb"); + if (!fpSourceFile) { // File not existing + ESP_LOGE(TAG, "copyFile: File %s not existing", input.c_str()); + return false; + } - /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ + /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ // Set buffer to SD card allocation size of 512 byte (newlib default: 128 byte) -> reduce system read/write calls setvbuf(fpSourceFile, NULL, _IOFBF, 512); - FILE* fpTargetFile = fopen(output.c_str(), "wb"); + FILE *fpTargetFile = fopen(output.c_str(), "wb"); - /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ + /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ // Set buffer to SD card allocation size of 512 byte (newlib default: 128 byte) -> reduce system read/write calls setvbuf(fpTargetFile, NULL, _IOFBF, 512); - // Code Section + // Code Section - // Read From The Source File - "Copy" - while (fread(&cTemp, 1, 1, fpSourceFile) == 1) { - fwrite(&cTemp, 1, 1, fpTargetFile); // Write To The Target File - "Paste" - } + // Read From The Source File - "Copy" + while (fread(&cTemp, 1, 1, fpSourceFile) == 1) { + fwrite(&cTemp, 1, 1, fpTargetFile); // Write To The Target File - "Paste" + } - // Close The Files - fclose(fpSourceFile); - fclose(fpTargetFile); - ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str()); - return true; + // Close The Files + fclose(fpSourceFile); + fclose(fpTargetFile); + ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str()); + return true; } bool renameFile(std::string from, std::string to) { - FILE* fpFile = fopen(from.c_str(), "rb"); - if (!fpFile) { // File not existing - ESP_LOGE(TAG, "renameFile: File %s not existing", from.c_str()); - return false; - } - fclose(fpFile); + FILE *fpFile = fopen(from.c_str(), "rb"); + if (!fpFile) { // File not existing + ESP_LOGE(TAG, "renameFile: File %s not existing", from.c_str()); + return false; + } + fclose(fpFile); - return (rename(from.c_str(), to.c_str()) == 0); + return (rename(from.c_str(), to.c_str()) == 0); } bool deleteFile(std::string fn) { - FILE* fpFile = fopen(fn.c_str(), "rb"); - if (!fpFile) { // File not existing - return false; - } - fclose(fpFile); + FILE *fpFile = fopen(fn.c_str(), "rb"); + if (!fpFile) { // File not existing + return false; + } + fclose(fpFile); - unlink(fn.c_str()); - return true; + unlink(fn.c_str()); + return true; } std::string getFileFullFileName(std::string filename) { - size_t lastpos = filename.find_last_of('/'); + size_t lastpos = filename.find_last_of('/'); - if (lastpos == std::string::npos) - return ""; + if (lastpos == std::string::npos) { + return ""; + } -// ESP_LOGD(TAG, "Last position: %d", lastpos); + // ESP_LOGD(TAG, "Last position: %d", lastpos); - std::string zw = filename.substr(lastpos + 1, filename.size() - lastpos); + std::string zw = filename.substr(lastpos + 1, filename.size() - lastpos); - return zw; + return zw; } std::string getFileType(std::string filename) { - size_t lastpos = filename.rfind(".", filename.length()); - size_t neu_pos; - while ((neu_pos = filename.find(".", lastpos + 1)) > -1) { - lastpos = neu_pos; - } + size_t lastpos = filename.rfind(".", filename.length()); + size_t neu_pos; + while ((neu_pos = filename.find(".", lastpos + 1)) > -1) { + lastpos = neu_pos; + } - if (lastpos == std::string::npos) - return ""; + if (lastpos == std::string::npos) { + return ""; + } - std::string zw = filename.substr(lastpos + 1, filename.size() - lastpos); - zw = toUpper(zw); + std::string zw = filename.substr(lastpos + 1, filename.size() - lastpos); + zw = toUpper(zw); - return zw; + return zw; } @@ -153,11 +155,12 @@ bool getFileIsFiletype(const std::string &filename, const std::string &filetype) std::size_t getFileSize(const std::string &filename) { - std::ifstream file(filename.c_str(),std::ios::in | std::ios::binary); - if (!file) - return 0; + std::ifstream file(filename.c_str(), std::ios::in | std::ios::binary); + if (!file) { + return 0; + } - file.seekg (0, std::ios::end); + file.seekg(0, std::ios::end); return static_cast(file.tellg()); } @@ -166,16 +169,17 @@ std::size_t getFileSize(const std::string &filename) // ********************************************************** std::string getDirectory(std::string filename) { - size_t lastpos = filename.rfind('/'); + size_t lastpos = filename.rfind('/'); - if (lastpos == std::string::npos) { - lastpos = filename.rfind('\\'); - if (lastpos == std::string::npos) - return ""; - } + if (lastpos == std::string::npos) { + lastpos = filename.rfind('\\'); + if (lastpos == std::string::npos) { + return ""; + } + } - // ESP_LOGD(TAG, "Directory: %d", lastpos); - return filename.substr(0, lastpos); + // ESP_LOGD(TAG, "Directory: %d", lastpos); + return filename.substr(0, lastpos); } @@ -184,42 +188,42 @@ std::string getDirectory(std::string filename) */ bool makeDir(std::string path) { - std::string parent; + std::string parent; - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Create folder: " + path); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Create folder: " + path); - bool bSuccess = false; - int nRC = ::mkdir( path.c_str(), 0775 ); - if( nRC == -1 ) { - switch( errno ) { + bool bSuccess = false; + int nRC = ::mkdir(path.c_str(), 0775); + if (nRC == -1) { + switch (errno) { case ENOENT: - //parent didn't exist, try to create it - parent = path.substr(0, path.find_last_of('/')); - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Create parent folder first: " + parent); - if(makeDir(parent)) { - //Now, try to create again. - bSuccess = 0 == ::mkdir( path.c_str(), 0775 ); - } + // parent didn't exist, try to create it + parent = path.substr(0, path.find_last_of('/')); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Create parent folder first: " + parent); + if (makeDir(parent)) { + // Now, try to create again. + bSuccess = 0 == ::mkdir(path.c_str(), 0775); + } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create parent folder: " + parent); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create parent folder: " + parent); bSuccess = false; - } + } break; case EEXIST: - //Done! + // Done! bSuccess = true; break; default: - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")"); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create folder: " + path + " (errno: " + std::to_string(errno) + ")"); bSuccess = false; break; } } else { bSuccess = true; - } + } return bSuccess; } @@ -238,24 +242,24 @@ int makeDirRecursive(const char *dir, const mode_t mode) if (len == 0 || len == FILE_PATH_MAX) { return -1; } - memcpy (tmp, dir, len); + memcpy(tmp, dir, len); tmp[len] = '\0'; /* remove trailing slash */ - if(tmp[len - 1] == '/') { + if (tmp[len - 1] == '/') { tmp[len - 1] = '\0'; } /* check if path exists and is a directory */ - if (stat (tmp, &sb) == 0) { - if (S_ISDIR (sb.st_mode)) { + if (stat(tmp, &sb) == 0) { + if (S_ISDIR(sb.st_mode)) { return 0; } } /* recursive mkdir */ - for(p = tmp + 1; *p; p++) { - if(*p == '/') { + for (p = tmp + 1; *p; p++) { + if (*p == '/') { *p = 0; /* test path */ if (stat(tmp, &sb) != 0) { @@ -263,7 +267,8 @@ int makeDirRecursive(const char *dir, const mode_t mode) if (mkdir(tmp, mode) < 0) { return -1; } - } else if (!S_ISDIR(sb.st_mode)) { + } + else if (!S_ISDIR(sb.st_mode)) { /* not a directory */ return -1; } @@ -276,7 +281,8 @@ int makeDirRecursive(const char *dir, const mode_t mode) if (mkdir(tmp, mode) < 0) { return -1; } - } else if (!S_ISDIR(sb.st_mode)) { + } + else if (!S_ISDIR(sb.st_mode)) { /* not a directory */ return -1; } @@ -284,13 +290,13 @@ int makeDirRecursive(const char *dir, const mode_t mode) } -int removeFolder(const char* folderPath, const char* logTag) +int removeFolder(const char *folderPath, const char *logTag) { - //ESP_LOGD(logTag, "Delete content in path %s", folderPath); + // ESP_LOGD(logTag, "Delete content in path %s", folderPath); - DIR *dir = opendir(folderPath); + DIR *dir = opendir(folderPath); if (!dir) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to open directory " + std::string(folderPath)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to open directory " + std::string(folderPath)); return -1; } @@ -298,27 +304,29 @@ int removeFolder(const char* folderPath, const char* logTag) int deleted = 0; while ((entry = readdir(dir)) != NULL) { std::string path = std::string(folderPath) + "/" + entry->d_name; - if (entry->d_type == DT_REG) { - //ESP_LOGD(logTag, "Delete file %s", path.c_str()); - if (unlink(path.c_str()) == 0) { - deleted ++; - } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete file " + path); - } + if (entry->d_type == DT_REG) { + // ESP_LOGD(logTag, "Delete file %s", path.c_str()); + if (unlink(path.c_str()) == 0) { + deleted++; + } + else { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete file " + path); + } + } + else if (entry->d_type == DT_DIR) { + if (removeFolder(path.c_str(), logTag) > 0) { + deleted++; + } } - else if (entry->d_type == DT_DIR) { - if (removeFolder(path.c_str(), logTag) > 0) - deleted++; - } } closedir(dir); - if (rmdir(folderPath) != 0) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete folder " + std::string(folderPath)); - } - //ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath); + if (rmdir(folderPath) != 0) { + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to delete folder " + std::string(folderPath)); + } + // ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath); - return deleted; + return deleted; } @@ -335,7 +343,7 @@ void deleteAllFilesInDirectory(std::string directory) /* Iterate over all files / folders and fetch their names and sizes */ while ((entry = readdir(dir)) != NULL) { - if (!(entry->d_type == DT_DIR)){ + if (!(entry->d_type == DT_DIR)) { filename = directory + "/" + std::string(entry->d_name); LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Delete file: " + filename); unlink(filename.c_str()); // Delete file @@ -358,7 +366,7 @@ void moveAllFilesWithFiletype(std::string sourceDir, std::string destinationDir, // Iterate over all files in folder and move if extention is matching struct dirent *entry; while ((entry = readdir(dir)) != NULL) { - if (!(entry->d_type == DT_DIR)){ + if (!(entry->d_type == DT_DIR)) { if (getFileIsFiletype(std::string(entry->d_name), filetype)) { std::string sourceFilename = sourceDir + "/" + std::string(entry->d_name); std::string destFilename = destinationDir + "/" + std::string(entry->d_name); @@ -386,85 +394,88 @@ std::string formatFileName(std::string input) std::string os = "/"; std::string ns = "\\"; findReplace(input, os, ns); -#endif +#endif // ISWINDOWS_TRUE return input; } bool ctype_space(const char c, std::string adddelimiter) { - if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11) { - return true; - } + if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11) { + return true; + } - if (adddelimiter.find(c) != std::string::npos) { - return true; - } + if (adddelimiter.find(c) != std::string::npos) { + return true; + } - return false; + return false; } std::string trim(std::string istring, std::string adddelimiter) { - bool trimmed = false; + bool trimmed = false; - if (ctype_space(istring[istring.length() - 1], adddelimiter)) { - istring.erase(istring.length() - 1); - trimmed = true; - } + if (ctype_space(istring[istring.length() - 1], adddelimiter)) { + istring.erase(istring.length() - 1); + trimmed = true; + } - if (ctype_space(istring[0], adddelimiter)) { - istring.erase(0, 1); - trimmed = true; - } + if (ctype_space(istring[0], adddelimiter)) { + istring.erase(0, 1); + trimmed = true; + } - if ((trimmed == false) || (istring.size() == 0)) { - return istring; - } - else { - return trim(istring, adddelimiter); - } + if ((trimmed == false) || (istring.size() == 0)) { + return istring; + } + else { + return trim(istring, adddelimiter); + } } size_t findDelimiterPos(std::string input, std::string delimiter) { - size_t pos = std::string::npos; - size_t zw; - std::string akt_del; - - for (int anz = 0; anz < delimiter.length(); ++anz) { - akt_del = delimiter[anz]; - if ((zw = input.find(akt_del)) != std::string::npos) { - if (pos != std::string::npos) { - if (zw < pos) - pos = zw; - } - else { - pos = zw; - } - } - } - return pos; + size_t pos = std::string::npos; + size_t zw; + std::string akt_del; + + for (int anz = 0; anz < delimiter.length(); ++anz) { + akt_del = delimiter[anz]; + if ((zw = input.find(akt_del)) != std::string::npos) { + if (pos != std::string::npos) { + if (zw < pos) { + pos = zw; + } + } + else { + pos = zw; + } + } + } + return pos; } std::string toUpper(std::string in) { - for (int i = 0; i < in.length(); ++i) - in[i] = toupper(in[i]); + for (int i = 0; i < in.length(); ++i) { + in[i] = toupper(in[i]); + } - return in; + return in; } std::string toLower(std::string in) { - for (int i = 0; i < in.length(); ++i) - in[i] = tolower(in[i]); + for (int i = 0; i < in.length(); ++i) { + in[i] = tolower(in[i]); + } - return in; + return in; } @@ -473,14 +484,17 @@ void findReplace(std::string &line, std::string &oldString, std::string &newStri const size_t oldSize = oldString.length(); // do nothing if line is shorter than the string to find - if (oldSize > line.length()) - return; + if (oldSize > line.length()) { + return; + } const size_t newSize = newString.length(); - for (size_t pos = 0; ; pos += newSize) { + for (size_t pos = 0;; pos += newSize) { // Locate the substring to replace pos = line.find(oldString, pos); - if (pos == std::string::npos) return; + if (pos == std::string::npos) { + return; + } if (oldSize == newSize) { // if they're same size, use std::string::replace line.replace(pos, oldSize, newString); @@ -499,8 +513,8 @@ void replaceAll(std::string &s, const std::string &toReplace, const std::string { size_t pos = 0; while ((pos = s.find(toReplace, pos)) != std::string::npos) { - s.replace(pos, toReplace.length(), replaceWith); - pos += replaceWith.length(); + s.replace(pos, toReplace.length(), replaceWith); + pos += replaceWith.length(); } } @@ -516,7 +530,8 @@ bool isInString(std::string &s, std::string const &toFind) } -std::vector splitStringAtNewline(const std::string &str) { +std::vector splitStringAtNewline(const std::string &str) +{ std::vector tokens; std::stringstream ss(str); @@ -532,10 +547,11 @@ std::vector splitStringAtNewline(const std::string &str) { std::string to_stringWithPrecision(const double _value, int _decPlace = 6) { - std::ostringstream out; + std::ostringstream out; - if (_decPlace < 0) - _decPlace = 0; + if (_decPlace < 0) { + _decPlace = 0; + } out.precision(_decPlace); out << std::fixed << _value; @@ -545,67 +561,67 @@ std::string to_stringWithPrecision(const double _value, int _decPlace = 6) std::string intToHexString(int _valueInt) { - char valueHex[33]; - sprintf(valueHex,"0x%02x", _valueInt); - return std::string(valueHex); + char valueHex[33]; + sprintf(valueHex, "0x%02x", _valueInt); + return std::string(valueHex); } // Time related helper // ********************************************************** -time_t addDays(time_t startTime, int days) { - struct tm* tm = localtime(&startTime); - tm->tm_mday += days; - return mktime(tm); +time_t addDays(time_t startTime, int days) +{ + struct tm *tm = localtime(&startTime); + tm->tm_mday += days; + return mktime(tm); } time_t getUptime(void) { - return (uint32_t)(esp_timer_get_time()/1000/1000); // in seconds + return (uint32_t)(esp_timer_get_time() / 1000 / 1000); // in seconds } // Returns the current uptime formated ad xxf xxh xxm [xxs] std::string getFormatedUptime(bool compact) { - char buf[20]; - #pragma GCC diagnostic ignored "-Wformat-truncation" + char buf[20]; +#pragma GCC diagnostic ignored "-Wformat-truncation" int uptime = getUptime(); // in seconds - int days = int(floor(uptime / (3600*24))); - int hours = int(floor((uptime - days * 3600*24) / (3600))); - int minutes = int(floor((uptime - days * 3600*24 - hours * 3600) / (60))); - int seconds = uptime - days * 3600*24 - hours * 3600 - minutes * 60; + int days = int(floor(uptime / (3600 * 24))); + int hours = int(floor((uptime - days * 3600 * 24) / (3600))); + int minutes = int(floor((uptime - days * 3600 * 24 - hours * 3600) / (60))); + int seconds = uptime - days * 3600 * 24 - hours * 3600 - minutes * 60; - if (compact) { - snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds); - } - else { - snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds); - } + if (compact) { + snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds); + } + else { + snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds); + } - return std::string(buf); + return std::string(buf); } // URL related helper // ********************************************************** -const char* get404(void) +const char *get404(void) { - return - "
\n\n\n\n"
-		"        _\n"
-		"    .__(.)< ( oh oh! This page does not exist! )\n"
-		"    \\___)\n"
-		"\n\n"
-		"                You could try your luck here!
\n" - ""; // Make sure we load the overview page + return "
\n\n\n\n"
+           "        _\n"
+           "    .__(.)< ( oh oh! This page does not exist! )\n"
+           "    \\___)\n"
+           "\n\n"
+           "                You could try your luck here!
\n" + ""; // Make sure we load the overview page } -std::string urlDecode(const std::string& value) +std::string urlDecode(const std::string &value) { std::string result; result.reserve(value.size()); diff --git a/code/components/misc_helper/helper.h b/code/components/misc_helper/helper.h index 60c9eb2ca..996ed6eb3 100644 --- a/code/components/misc_helper/helper.h +++ b/code/components/misc_helper/helper.h @@ -18,7 +18,7 @@ size_t getFileSize(const std::string &filename); std::string getDirectory(std::string filename); bool makeDir(std::string _what); int makeDirRecursive(const char *dir, const mode_t mode); -int removeFolder(const char* folderPath, const char* logTag); +int removeFolder(const char *folderPath, const char *logTag); void deleteAllFilesInDirectory(std::string directory); void moveAllFilesWithFiletype(std::string sourceDir, std::string destinationDir, std::string filetype); @@ -40,7 +40,7 @@ time_t addDays(time_t startTime, int days); time_t getUptime(void); std::string getFormatedUptime(bool compact); -const char* get404(void); -std::string urlDecode(const std::string& value); +const char *get404(void); +std::string urlDecode(const std::string &value); -#endif //HELPER_H +#endif // HELPER_H diff --git a/code/components/misc_helper/psram.cpp b/code/components/misc_helper/psram.cpp index eaac39370..65934aa7b 100644 --- a/code/components/misc_helper/psram.cpp +++ b/code/components/misc_helper/psram.cpp @@ -2,50 +2,48 @@ #include "ClassLogFile.h" -static const char* TAG = "PSRAM"; +static const char *TAG = "PSRAM"; struct strSTBI STBIObjectPSRAM = {}; struct strcJSON cJSONObjectPSRAM = {}; void *malloc_psram_heap(std::string name, size_t size, uint32_t caps) { - void *ptr; + void *ptr; - ptr = heap_caps_malloc(size, caps); + ptr = heap_caps_malloc(size, caps); if (ptr != NULL) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); - } + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); + } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, name + ": Failed to allocate " + std::to_string(size)); } - return ptr; + return ptr; } -void *remalloc_psram_heap(std::string name, void* p, size_t size, uint32_t caps) +void *remalloc_psram_heap(std::string name, void *p, size_t size, uint32_t caps) { - void *ptr; + void *ptr; - ptr = heap_caps_realloc(p, size, caps); + ptr = heap_caps_realloc(p, size, caps); if (ptr != NULL) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); - } + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); + } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, name + ": Failed to allocate " + std::to_string(size)); } - return ptr; + return ptr; } void *malloc_psram_heap_STBI(std::string name, size_t size, uint32_t caps) { - void *ptr; + void *ptr; - if (STBIObjectPSRAM.usePreallocated && STBIObjectPSRAM.PreallocatedMemorySize == size && - STBIObjectPSRAM.PreallocatedMemory != NULL) - { + if (STBIObjectPSRAM.usePreallocated && STBIObjectPSRAM.PreallocatedMemorySize == size && STBIObjectPSRAM.PreallocatedMemory != NULL) { ptr = STBIObjectPSRAM.PreallocatedMemory; name += ": Use preallocated memory (" + STBIObjectPSRAM.name + ")"; STBIObjectPSRAM.usePreallocated = false; @@ -56,29 +54,29 @@ void *malloc_psram_heap_STBI(std::string name, size_t size, uint32_t caps) if (ptr != NULL) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); - } + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); + } else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, name + ": Failed to allocate " + std::to_string(size)); } - return ptr; + return ptr; } void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps) { - void *ptr; + void *ptr; - ptr = heap_caps_calloc(n, size, caps); + ptr = heap_caps_calloc(n, size, caps); if (ptr != NULL) { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); - } + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Allocated: " + std::to_string(size)); + } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, name + ": Free memory"); } - return ptr; + return ptr; } diff --git a/code/components/misc_helper/psram.h b/code/components/misc_helper/psram.h index 93cab1447..24b739473 100644 --- a/code/components/misc_helper/psram.h +++ b/code/components/misc_helper/psram.h @@ -41,7 +41,7 @@ Block 0x3f9bb2f0 data, size: 2379020 bytes, Free: Yes struct strSTBI { std::string name = ""; bool usePreallocated = false; - uint8_t* PreallocatedMemory = NULL; + uint8_t *PreallocatedMemory = NULL; int PreallocatedMemorySize = 0; int NeededAllocationSize = 0; }; @@ -49,7 +49,7 @@ extern struct strSTBI STBIObjectPSRAM; struct strcJSON { - uint8_t* preallocatedMemory = NULL; + uint8_t *preallocatedMemory = NULL; int preallocatedMemorySize = 0; int usedMemory = 0; bool useDefaultAllocation = false; @@ -59,7 +59,7 @@ extern struct strcJSON cJSONObjectPSRAM; void *malloc_psram_heap(std::string name, size_t size, uint32_t caps); void *malloc_psram_heap_STBI(std::string name, size_t size, uint32_t caps); -void *remalloc_psram_heap(std::string name, void* p, size_t size, uint32_t caps); +void *remalloc_psram_heap(std::string name, void *p, size_t size, uint32_t caps); void *calloc_psram_heap(std::string name, size_t n, size_t size, uint32_t caps); void free_psram_heap(std::string name, void *ptr); @@ -67,4 +67,4 @@ void free_psram_heap(std::string name, void *ptr); void *malloc_psram_heap_cjson(size_t size); void free_psram_heap_cjson(void *ptr); -#endif //PSRAM_H_ \ No newline at end of file +#endif // PSRAM_H_ diff --git a/code/components/misc_helper/sdcard_check.cpp b/code/components/misc_helper/sdcard_check.cpp index f98a8f9fb..f8162b5a0 100644 --- a/code/components/misc_helper/sdcard_check.cpp +++ b/code/components/misc_helper/sdcard_check.cpp @@ -19,18 +19,18 @@ static const char *TAG = "SDCARD"; int checkSdCardRW(void) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Basic R/W check started"); - FILE* pFile = NULL; + FILE *pFile = NULL; int iCRCMessage = 0; - pFile = fopen("/sdcard/sdcheck.txt","w"); + pFile = fopen("/sdcard/sdcheck.txt", "w"); if (pFile == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E1) Not able to open file to write"); return -1; } else { std::string sMessage = "This message is used for a SD-Card basic check!"; - iCRCMessage = esp_rom_crc16_le(0, (uint8_t*)sMessage.c_str(), sMessage.length()); - if (fwrite(sMessage.c_str(), sMessage.length(), 1, pFile) == 0 ) { + iCRCMessage = esp_rom_crc16_le(0, (uint8_t *)sMessage.c_str(), sMessage.length()); + if (fwrite(sMessage.c_str(), sMessage.length(), 1, pFile) == 0) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E2) Not able to write file"); fclose(pFile); unlink("/sdcard/sdcheck.txt"); @@ -39,7 +39,7 @@ int checkSdCardRW(void) fclose(pFile); } - pFile = fopen("/sdcard/sdcheck.txt","r"); + pFile = fopen("/sdcard/sdcheck.txt", "r"); if (pFile == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E3) Not able to open file to read back"); unlink("/sdcard/sdcheck.txt"); @@ -54,7 +54,7 @@ int checkSdCardRW(void) return -4; } else { - if (esp_rom_crc16_le(0, (uint8_t*)cReadBuf, strlen(cReadBuf)) != iCRCMessage) { + if (esp_rom_crc16_le(0, (uint8_t *)cReadBuf, strlen(cReadBuf)) != iCRCMessage) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Basic R/W check: (E5) Read back, but wrong CRC"); fclose(pFile); unlink("/sdcard/sdcheck.txt"); @@ -134,8 +134,9 @@ bool checkSdCardFolderFilePresence() bRetval = false; } - if (bRetval) + if (bRetval) { LogFile.writeToFile(ESP_LOG_INFO, TAG, "Folder/file presence check successful"); + } return bRetval; -} \ No newline at end of file +} diff --git a/code/components/misc_helper/sdcard_check.h b/code/components/misc_helper/sdcard_check.h index 8fbf23713..32d8d0316 100644 --- a/code/components/misc_helper/sdcard_check.h +++ b/code/components/misc_helper/sdcard_check.h @@ -5,4 +5,4 @@ int checkSdCardRW(void); bool checkSdCardFolderFilePresence(void); -#endif /* COMPONENTS_HELPER_SDCARD_CHECK_H */ +#endif // COMPONENTS_HELPER_SDCARD_CHECK_H diff --git a/code/components/misc_helper/statusled.cpp b/code/components/misc_helper/statusled.cpp index 1fd8b3c33..66d214972 100644 --- a/code/components/misc_helper/statusled.cpp +++ b/code/components/misc_helper/statusled.cpp @@ -9,7 +9,7 @@ #include "ClassLogFile.h" -static const char* TAG = "STATUSLED"; +static const char *TAG = "STATUSLED"; TaskHandle_t xHandle_task_StatusLED = NULL; struct StatusLEDData StatusLEDData = {}; @@ -17,159 +17,164 @@ struct StatusLEDData StatusLEDData = {}; void task_StatusLED(void *pvParameter) { - //ESP_LOGD(TAG, "task_StatusLED - create"); - while (StatusLEDData.bProcessingRequest) - { - //ESP_LOGD(TAG, "task_StatusLED - start"); - struct StatusLEDData StatusLEDDataInt = StatusLEDData; - - esp_rom_gpio_pad_select_gpio(GPIO_STATUS_LED_ONBOARD); // Init the GPIO - gpio_set_direction(GPIO_STATUS_LED_ONBOARD, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output + // ESP_LOGD(TAG, "task_StatusLED - create"); + while (StatusLEDData.bProcessingRequest) { + // ESP_LOGD(TAG, "task_StatusLED - start"); + struct StatusLEDData StatusLEDDataInt = StatusLEDData; + + esp_rom_gpio_pad_select_gpio(GPIO_STATUS_LED_ONBOARD); // Init the GPIO + gpio_set_direction(GPIO_STATUS_LED_ONBOARD, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output + #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1);// LED off + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); // LED off #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0);// LED off -#endif + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); // LED off +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE - for (int i=0; i<2; ) // Default: repeat 2 times - { - if (!StatusLEDDataInt.bInfinite) - ++i; + for (int i = 0; i < 2;) { // Default: repeat 2 times + if (!StatusLEDDataInt.bInfinite) { + ++i; + } - for (int j = 0; j < StatusLEDDataInt.iSourceBlinkCnt; ++j) - { + for (int j = 0; j < StatusLEDDataInt.iSourceBlinkCnt; ++j) { #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); -#endif - vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE + + vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); -#endif - vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); - } + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE - vTaskDelay(500 / portTICK_PERIOD_MS); // Delay between module code and error code + vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + } - for (int j = 0; j < StatusLEDDataInt.iCodeBlinkCnt; ++j) - { + vTaskDelay(500 / portTICK_PERIOD_MS); // Delay between module code and error code + + for (int j = 0; j < StatusLEDDataInt.iCodeBlinkCnt; ++j) { #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); -#endif - vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE + + vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); -#endif - vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); - } - vTaskDelay(1500 / portTICK_PERIOD_MS); // Delay to signal new round - } - - StatusLEDData.bProcessingRequest = false; - //ESP_LOGD(TAG, "task_StatusLED - done/wait"); - vTaskDelay(10000 / portTICK_PERIOD_MS); // Wait for an upcoming request otherwise continue and delete task to save memory - } - //ESP_LOGD(TAG, "task_StatusLED - delete"); - xHandle_task_StatusLED = NULL; + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE + + vTaskDelay(StatusLEDDataInt.iBlinkTime / portTICK_PERIOD_MS); + } + vTaskDelay(1500 / portTICK_PERIOD_MS); // Delay to signal new round + } + + StatusLEDData.bProcessingRequest = false; + // ESP_LOGD(TAG, "task_StatusLED - done/wait"); + vTaskDelay(10000 / portTICK_PERIOD_MS); // Wait for an upcoming request otherwise continue and delete task to save memory + } + // ESP_LOGD(TAG, "task_StatusLED - delete"); + xHandle_task_StatusLED = NULL; vTaskDelete(NULL); // Delete this task due to no request } void setStatusLed(StatusLedSource _eSource, int _iCode, bool _bInfinite) { - //ESP_LOGD(TAG, "setStatusLed - start"); + // ESP_LOGD(TAG, "setStatusLed - start"); if (_eSource == WLAN_CONN) { - StatusLEDData.iSourceBlinkCnt = WLAN_CONN; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } - else if (_eSource == WLAN_INIT) { - StatusLEDData.iSourceBlinkCnt = WLAN_INIT; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } - else if (_eSource == SDCARD_NVS_INIT) { - StatusLEDData.iSourceBlinkCnt = SDCARD_NVS_INIT; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } - else if (_eSource == SDCARD_CHECK) { - StatusLEDData.iSourceBlinkCnt = SDCARD_CHECK; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } + StatusLEDData.iSourceBlinkCnt = WLAN_CONN; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } + else if (_eSource == WLAN_INIT) { + StatusLEDData.iSourceBlinkCnt = WLAN_INIT; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } + else if (_eSource == SDCARD_NVS_INIT) { + StatusLEDData.iSourceBlinkCnt = SDCARD_NVS_INIT; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } + else if (_eSource == SDCARD_CHECK) { + StatusLEDData.iSourceBlinkCnt = SDCARD_CHECK; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } else if (_eSource == CAM_INIT) { - StatusLEDData.iSourceBlinkCnt = CAM_INIT; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } + StatusLEDData.iSourceBlinkCnt = CAM_INIT; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } else if (_eSource == PSRAM_INIT) { - StatusLEDData.iSourceBlinkCnt = PSRAM_INIT; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } - else if (_eSource == TIME_CHECK) { - StatusLEDData.iSourceBlinkCnt = TIME_CHECK; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 250; - StatusLEDData.bInfinite = _bInfinite; - } - else if (_eSource == AP_OR_OTA) { - StatusLEDData.iSourceBlinkCnt = AP_OR_OTA; - StatusLEDData.iCodeBlinkCnt = _iCode; - StatusLEDData.iBlinkTime = 350; - StatusLEDData.bInfinite = _bInfinite; - } - - if (xHandle_task_StatusLED && !StatusLEDData.bProcessingRequest) { - StatusLEDData.bProcessingRequest = true; - BaseType_t xReturned = xTaskAbortDelay(xHandle_task_StatusLED); // Reuse still running status LED task - /*if (xReturned == pdPASS) - ESP_LOGD(TAG, "task_StatusLED - abort waiting delay");*/ - } - else if (xHandle_task_StatusLED == NULL) { - StatusLEDData.bProcessingRequest = true; - BaseType_t xReturned = xTaskCreate(&task_StatusLED, "task_StatusLED", 1280, NULL, tskIDLE_PRIORITY + 1, &xHandle_task_StatusLED); - if(xReturned != pdPASS) - { - xHandle_task_StatusLED = NULL; - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "task_StatusLED failed to create"); - LogFile.writeHeapInfo("task_StatusLED failed"); - } - } - else { - ESP_LOGD(TAG, "task_StatusLED still processing, request skipped"); // Requests with high frequency could be skipped, but LED is only helpful for static states - } - //ESP_LOGD(TAG, "setStatusLed - done"); + StatusLEDData.iSourceBlinkCnt = PSRAM_INIT; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } + else if (_eSource == TIME_CHECK) { + StatusLEDData.iSourceBlinkCnt = TIME_CHECK; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 250; + StatusLEDData.bInfinite = _bInfinite; + } + else if (_eSource == AP_OR_OTA) { + StatusLEDData.iSourceBlinkCnt = AP_OR_OTA; + StatusLEDData.iCodeBlinkCnt = _iCode; + StatusLEDData.iBlinkTime = 350; + StatusLEDData.bInfinite = _bInfinite; + } + + if (xHandle_task_StatusLED && !StatusLEDData.bProcessingRequest) { + StatusLEDData.bProcessingRequest = true; + BaseType_t xReturned = xTaskAbortDelay(xHandle_task_StatusLED); // Reuse still running status LED task + + /*if (xReturned == pdPASS) + ESP_LOGD(TAG, "task_StatusLED - abort waiting delay");*/ + } + else if (xHandle_task_StatusLED == NULL) { + StatusLEDData.bProcessingRequest = true; + BaseType_t xReturned = xTaskCreate(&task_StatusLED, "task_StatusLED", 1280, NULL, tskIDLE_PRIORITY + 1, &xHandle_task_StatusLED); + if (xReturned != pdPASS) { + xHandle_task_StatusLED = NULL; + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "task_StatusLED failed to create"); + LogFile.writeHeapInfo("task_StatusLED failed"); + } + } + else { + ESP_LOGD(TAG, "task_StatusLED still processing, request skipped"); // Requests with high frequency could be skipped, but LED is only + // helpful for static states + } + // ESP_LOGD(TAG, "setStatusLed - done"); } void setStatusLedOff(void) { - if (xHandle_task_StatusLED) { - vTaskDelete(xHandle_task_StatusLED); // Delete task for setStatusLed to force stop of blinking - xHandle_task_StatusLED = NULL; - } + if (xHandle_task_StatusLED) { + vTaskDelete(xHandle_task_StatusLED); // Delete task for setStatusLed to force stop of blinking + xHandle_task_StatusLED = NULL; + } - esp_rom_gpio_pad_select_gpio(GPIO_STATUS_LED_ONBOARD); // Init the GPIO - gpio_set_direction(GPIO_STATUS_LED_ONBOARD, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output + esp_rom_gpio_pad_select_gpio(GPIO_STATUS_LED_ONBOARD); // Init the GPIO + gpio_set_direction(GPIO_STATUS_LED_ONBOARD, GPIO_MODE_OUTPUT); // Set the GPIO as a push/pull output #ifdef GPIO_STATUS_LED_ONBOARD_LOWACTIVE - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1);// LED off + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 1); // LED off #else - gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0);// LED off -#endif -} \ No newline at end of file + gpio_set_level(GPIO_STATUS_LED_ONBOARD, 0); // LED off +#endif // GPIO_STATUS_LED_ONBOARD_LOWACTIVE +} diff --git a/code/components/misc_helper/statusled.h b/code/components/misc_helper/statusled.h index 3975484cb..a5229c528 100644 --- a/code/components/misc_helper/statusled.h +++ b/code/components/misc_helper/statusled.h @@ -8,10 +8,10 @@ extern TaskHandle_t xHandle_task_StatusLED; enum StatusLedSource { - WLAN_CONN = 1, + WLAN_CONN = 1, WLAN_INIT = 2, SDCARD_NVS_INIT = 3, - SDCARD_CHECK = 4, + SDCARD_CHECK = 4, CAM_INIT = 5, PSRAM_INIT = 6, TIME_CHECK = 7, @@ -29,4 +29,4 @@ struct StatusLEDData { void setStatusLed(StatusLedSource _eSource, int _iCode, bool _bInfinite); void setStatusLedOff(void); -#endif //STATUSLED_H \ No newline at end of file +#endif // STATUSLED_H diff --git a/code/components/misc_helper/system.cpp b/code/components/misc_helper/system.cpp index 2587d3868..80d68fd3a 100644 --- a/code/components/misc_helper/system.cpp +++ b/code/components/misc_helper/system.cpp @@ -12,7 +12,7 @@ #include "ClassLogFile.h" -static const char* TAG = "SYSTEM"; +static const char *TAG = "SYSTEM"; unsigned int systemStatus = 0; static bool isPlannedReboot = false; @@ -24,7 +24,7 @@ sdmmc_csd_t SDCardCsd; std::string getBoardType(void) { - return std::string(BOARD_TYPE_NAME); + return std::string(BOARD_TYPE_NAME); } @@ -33,15 +33,20 @@ std::string getChipModel(void) esp_chip_info_t chipInfo; esp_chip_info(&chipInfo); - switch((int)chipInfo.model) { - case (int)esp_chip_model_t::CHIP_ESP32 : return std::string("ESP32"); - case (int)esp_chip_model_t::CHIP_ESP32S2 : return std::string("ESP32S2"); - case (int)esp_chip_model_t::CHIP_ESP32C3 : return std::string("ESP32C3"); - case (int)esp_chip_model_t::CHIP_ESP32S3 : return std::string("ESP32S3"); - case (int)esp_chip_model_t::CHIP_ESP32C2 : return std::string("ESP32C2"); - //case (int)esp_chip_model_t::CHIP_ESP32C6 : return std::string("ESP32C6"); - case (int)esp_chip_model_t::CHIP_ESP32H2 : return std::string("ESP32H2"); - //case (int)esp_chip_model_t::CHIP_POSIX_LINUX : return std::string("CHIP_POSIX_LINUX"); + switch ((int)chipInfo.model) { + case (int)esp_chip_model_t::CHIP_ESP32: + return std::string("ESP32"); + case (int)esp_chip_model_t::CHIP_ESP32S2: + return std::string("ESP32S2"); + case (int)esp_chip_model_t::CHIP_ESP32C3: + return std::string("ESP32C3"); + case (int)esp_chip_model_t::CHIP_ESP32S3: + return std::string("ESP32S3"); + case (int)esp_chip_model_t::CHIP_ESP32C2: + return std::string("ESP32C2"); + // case (int)esp_chip_model_t::CHIP_ESP32C6 : return std::string("ESP32C6"); + case (int)esp_chip_model_t::CHIP_ESP32H2: + return std::string("ESP32H2"); } return std::string("Chip model unknown"); @@ -59,8 +64,7 @@ int getChipCoreCount(void) std::string getChipRevision(void) { - return std::to_string(efuse_hal_get_major_chip_version()) + - "." + std::to_string(efuse_hal_get_minor_chip_version()); + return std::to_string(efuse_hal_get_major_chip_version()) + "." + std::to_string(efuse_hal_get_minor_chip_version()); } @@ -69,10 +73,9 @@ void printDeviceInfo(void) esp_chip_info_t chipInfo; esp_chip_info(&chipInfo); - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Device info: Board: " + getBoardType() + - ", SOC: " + getChipModel() + - ", Cores: " + std::to_string(chipInfo.cores) + - ", Revision: " + getChipRevision()); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Device info: Board: " + getBoardType() + ", SOC: " + getChipModel() + + ", Cores: " + std::to_string(chipInfo.cores) + ", Revision: " + getChipRevision()); } @@ -85,11 +88,10 @@ std::string getIDFVersion(void) int getConfigVersion(void) { - return ConfigClass::getInstance()->get()->sectionConfig.version; + return ConfigClass::getInstance()->get()->sectionConfig.version; } - ///////////////////////////////////////////////////////////////////////////////////////////// // SOC temperature sensor #if defined(SOC_TEMP_SENSOR_SUPPORTED) @@ -97,27 +99,27 @@ static float socTemperature = -1; void taskSocTemp(void *pvParameter) { - temperature_sensor_handle_t socTempSensor = NULL; - temperature_sensor_config_t socTempSensorConfig = TEMPERATURE_SENSOR_CONFIG_DEFAULT(20, 100); + temperature_sensor_handle_t socTempSensor = NULL; + temperature_sensor_config_t socTempSensorConfig = TEMPERATURE_SENSOR_CONFIG_DEFAULT(20, 100); temperature_sensor_install(&socTempSensorConfig, &socTempSensor); temperature_sensor_enable(socTempSensor); - while(1) { - if (temperature_sensor_get_celsius(socTempSensor, &socTemperature) != ESP_OK) { - socTemperature = -1; - } + while (1) { + if (temperature_sensor_get_celsius(socTempSensor, &socTemperature) != ESP_OK) { + socTemperature = -1; + } - vTaskDelay(pdMS_TO_TICKS(5000)); - } + vTaskDelay(pdMS_TO_TICKS(5000)); + } } void initSOCTemperatureSensor() { - // Create a dedicated task to ensure access temperature ressource only from a single source - BaseType_t xReturned = xTaskCreate(&taskSocTemp, "taskSocTemp", 2048, NULL, tskIDLE_PRIORITY + 1, NULL); + // Create a dedicated task to ensure access temperature ressource only from a single source + BaseType_t xReturned = xTaskCreate(&taskSocTemp, "taskSocTemp", 2048, NULL, tskIDLE_PRIORITY + 1, NULL); - if( xReturned != pdPASS ) { + if (xReturned != pdPASS) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create taskSocTemp"); } } @@ -125,22 +127,22 @@ void initSOCTemperatureSensor() float getSOCTemperature() { - return socTemperature; + return socTemperature; } #elif defined(CONFIG_IDF_TARGET_ESP32) // Inofficial support of vanilla ESP32. Value might be unreliable extern "C" uint8_t temprature_sens_read(); float getSOCTemperature() { - return (temprature_sens_read() - 32) / 1.8; + return (temprature_sens_read() - 32) / 1.8; } #else #warning "SOC temperature sensor not supported" float getSOCTemperature() { - return -1.0; + return -1.0; } -#endif +#endif // SOC_TEMP_SENSOR_SUPPORTED bool setCPUFrequency(void) @@ -152,7 +154,7 @@ bool setCPUFrequency(void) return false; } - int cpuFrequency = ConfigClass::getInstance()->get()->sectionSystem.cpuFrequency; + int cpuFrequency = ConfigClass::getInstance()->get()->sectionSystem.cpuFrequency; if (cpuFrequency == 160) { // 160 is the default // No change needed } @@ -165,7 +167,7 @@ bool setCPUFrequency(void) } } else { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setCpuFrequency: CPU frequency not supported: " + cpuFrequency); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "setCpuFrequency: CPU frequency not supported: " + cpuFrequency); return false; } @@ -178,114 +180,115 @@ bool setCPUFrequency(void) ///////////////////////////////////////////////////////////////////////////////////////////// -std::string getESPHeapInfo(){ - std::string espInfoResultStr = ""; - char aMsgBuf[80]; +std::string getESPHeapInfo() +{ + std::string espInfoResultStr = ""; + char aMsgBuf[80]; - size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT); + size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT); - 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 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 aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); - size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); - sprintf(aMsgBuf,"Heap Total: %ld", (long) aFreeHeapSize); - espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, "Heap Total: %ld", (long)aFreeHeapSize); + espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | SPI Free: %ld", (long) aFreeSPIHeapSize); - espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | SPI Large Block: %ld", (long) aHeapLargestFreeBlockSize); - espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | SPI Min Free: %ld", (long) aMinFreeHeapSize); - espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | SPI Free: %ld", (long)aFreeSPIHeapSize); + espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | SPI Large Block: %ld", (long)aHeapLargestFreeBlockSize); + espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | SPI Min Free: %ld", (long)aMinFreeHeapSize); + espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | Int Free: %ld", (long) (aFreeInternalHeapSize)); - espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | Int Large Block: %ld", (long) aHeapIntLargestFreeBlockSize); - espInfoResultStr += std::string(aMsgBuf); - sprintf(aMsgBuf," | Int Min Free: %ld", (long) (aMinFreeInternalHeapSize)); - espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | Int Free: %ld", (long)(aFreeInternalHeapSize)); + espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | Int Large Block: %ld", (long)aHeapIntLargestFreeBlockSize); + espInfoResultStr += std::string(aMsgBuf); + sprintf(aMsgBuf, " | Int Min Free: %ld", (long)(aMinFreeInternalHeapSize)); + espInfoResultStr += std::string(aMsgBuf); - return espInfoResultStr; + return espInfoResultStr; } size_t getESPHeapSizeTotalFree() { - return heap_caps_get_free_size(MALLOC_CAP_8BIT); + return heap_caps_get_free_size(MALLOC_CAP_8BIT); } size_t getESPHeapSizeInternalFree() { - return heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL); + return heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); } size_t getESPHeapSizeInternalLargestFree() { - return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); } size_t getESPHeapSizeInternalMinFree() { - return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); + return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL); } size_t getESPHeapSizeSPIRAMFree() { - return heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM); + return heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); } size_t getESPHeapSizeSPIRAMLargestFree() { - return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); } size_t getESPHeapSizeSPIRAMMinFree() { - return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); + return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); } void setSPIRAMCategory(SPIRAMCategory_t category) { - SPIRAMCategory = category; + SPIRAMCategory = category; } SPIRAMCategory_t getSPIRAMCategory() { - return SPIRAMCategory; + return SPIRAMCategory; } ///////////////////////////////////////////////////////////////////////////////////////////// void setSystemStatusFlag(SystemStatusFlag_t flag) { - systemStatus = systemStatus | flag; // set bit + systemStatus = systemStatus | flag; // set bit - char buf[20]; - snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus()); + char buf[20]; + snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus()); LogFile.writeToFile(ESP_LOG_ERROR, TAG, "System status code: " + std::string(buf)); } void clearSystemStatusFlag(SystemStatusFlag_t flag) { - systemStatus = systemStatus | ~flag; // clear bit + systemStatus = systemStatus | ~flag; // clear bit - char buf[20]; - snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus()); + char buf[20]; + snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus()); LogFile.writeToFile(ESP_LOG_ERROR, TAG, "System status code: " + std::string(buf)); } @@ -298,53 +301,73 @@ int getSystemStatus(void) bool isSetSystemStatusFlag(SystemStatusFlag_t flag) { - //ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag)); + // ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag)); - if ((systemStatus & flag) == flag) { - return true; - } - else { - return false; - } + if ((systemStatus & flag) == flag) { + return true; + } + else { + return false; + } } std::string getResetReason(void) { - std::string reasonText; - - switch(esp_reset_reason()) { - case ESP_RST_POWERON: reasonText = "Power-on event (or reset button)"; break; //!< Reset due to power-on event - case ESP_RST_EXT: reasonText = "External pin"; break; //!< Reset by external pin (not applicable for ESP32) - case ESP_RST_SW: reasonText = "Via esp_restart"; break; //!< Software reset via esp_restart - case ESP_RST_PANIC: reasonText = "Exception/panic"; break; //!< Software reset due to exception/panic - case ESP_RST_INT_WDT: reasonText = "Interrupt watchdog"; break; //!< Reset (software or hardware) due to interrupt watchdog - case ESP_RST_TASK_WDT: reasonText = "Task watchdog"; break; //!< Reset due to task watchdog - case ESP_RST_WDT: reasonText = "Other watchdogs"; break; //!< Reset due to other watchdogs - case ESP_RST_DEEPSLEEP: reasonText = "Exiting deep sleep mode"; break; //!< Reset after exiting deep sleep mode - case ESP_RST_BROWNOUT: reasonText = "Brownout"; break; //!< Brownout reset (software or hardware) - case ESP_RST_SDIO: reasonText = "SDIO"; break; //!< Reset over SDIO - - case ESP_RST_UNKNOWN: //!< Reset reason can not be determined - default: - reasonText = "Unknown"; - } + std::string reasonText; + + switch (esp_reset_reason()) { + case ESP_RST_POWERON: + reasonText = "Power-on event (or reset button)"; + break; //!< Reset due to power-on event + case ESP_RST_EXT: + reasonText = "External pin"; + break; //!< Reset by external pin (not applicable for ESP32) + case ESP_RST_SW: + reasonText = "Via esp_restart"; + break; //!< Software reset via esp_restart + case ESP_RST_PANIC: + reasonText = "Exception/panic"; + break; //!< Software reset due to exception/panic + case ESP_RST_INT_WDT: + reasonText = "Interrupt watchdog"; + break; //!< Reset (software or hardware) due to interrupt watchdog + case ESP_RST_TASK_WDT: + reasonText = "Task watchdog"; + break; //!< Reset due to task watchdog + case ESP_RST_WDT: + reasonText = "Other watchdogs"; + break; //!< Reset due to other watchdogs + case ESP_RST_DEEPSLEEP: + reasonText = "Exiting deep sleep mode"; + break; //!< Reset after exiting deep sleep mode + case ESP_RST_BROWNOUT: + reasonText = "Brownout"; + break; //!< Brownout reset (software or hardware) + case ESP_RST_SDIO: + reasonText = "SDIO"; + break; //!< Reset over SDIO + + case ESP_RST_UNKNOWN: //!< Reset reason can not be determined + default: + reasonText = "Unknown"; + } return reasonText; } void checkIsPlannedReboot() { - FILE *pfile; + FILE *pfile; if ((pfile = fopen("/sdcard/reboot.txt", "r")) == NULL) { - //LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Initial boot or not a planned reboot"); + // LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Initial boot or not a planned reboot"); isPlannedReboot = false; - } + } else { - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Planned reboot"); - deleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!! + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Planned reboot"); + deleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!! isPlannedReboot = true; - } + } } @@ -354,9 +377,9 @@ bool getIsPlannedReboot() } -void saveSDCardInfo(sdmmc_card_t* card) +void saveSDCardInfo(sdmmc_card_t *card) { - SDCardCid = card->cid; + SDCardCid = card->cid; SDCardCsd = card->csd; } @@ -365,217 +388,218 @@ void saveSDCardInfo(sdmmc_card_t* card) /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */ /* SD Card Manufacturer Database */ struct SDCard_Manufacturer_database { - std::string type; - int id; - std::string manufacturer; + std::string type; + int id; + std::string manufacturer; }; /* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */ /* SD Card Manufacturer Database */ -struct SDCard_Manufacturer_database database[] = { - { - .type = "sd", - .id = 0x01, - .manufacturer = "Panasonic", - }, - { - .type = "sd", - .id = 0x02, - .manufacturer = "Toshiba/Kingston/Viking", - }, - { - .type = "sd", - .id = 0x03, - .manufacturer = "SanDisk", - }, - { - .type = "sd", - .id = 0x08, - .manufacturer = "Silicon Power", - }, - { - .type = "sd", - .id = 0x18, - .manufacturer = "Infineon", - }, - { - .type = "sd", - .id = 0x1b, - .manufacturer = "Transcend/Samsung", - }, - { - .type = "sd", - .id = 0x1c, - .manufacturer = "Transcend", - }, - { - .type = "sd", - .id = 0x1d, - .manufacturer = "Corsair/AData", - }, - { - .type = "sd", - .id = 0x1e, - .manufacturer = "Transcend", - }, - { - .type = "sd", - .id = 0x1f, - .manufacturer = "Kingston", - }, - { - .type = "sd", - .id = 0x27, - .manufacturer = "Delkin/Phison", - }, - { - .type = "sd", - .id = 0x28, - .manufacturer = "Lexar", - }, - { - .type = "sd", - .id = 0x30, - .manufacturer = "SanDisk", - }, - { - .type = "sd", - .id = 0x31, - .manufacturer = "Silicon Power", - }, - { - .type = "sd", - .id = 0x33, - .manufacturer = "STMicroelectronics", - }, - { - .type = "sd", - .id = 0x41, - .manufacturer = "Kingston", - }, - { - .type = "sd", - .id = 0x6f, - .manufacturer = "STMicroelectronics", - }, - { - .type = "sd", - .id = 0x74, - .manufacturer = "Transcend", - }, - { - .type = "sd", - .id = 0x76, - .manufacturer = "Patriot", - }, - { - .type = "sd", - .id = 0x82, - .manufacturer = "Gobe/Sony", - }, - { - .type = "sd", - .id = 0x89, - .manufacturer = "Unknown", - } -}; +struct SDCard_Manufacturer_database database[] = {{ + .type = "sd", + .id = 0x01, + .manufacturer = "Panasonic", + }, + { + .type = "sd", + .id = 0x02, + .manufacturer = "Toshiba/Kingston/Viking", + }, + { + .type = "sd", + .id = 0x03, + .manufacturer = "SanDisk", + }, + { + .type = "sd", + .id = 0x08, + .manufacturer = "Silicon Power", + }, + { + .type = "sd", + .id = 0x18, + .manufacturer = "Infineon", + }, + { + .type = "sd", + .id = 0x1b, + .manufacturer = "Transcend/Samsung", + }, + { + .type = "sd", + .id = 0x1c, + .manufacturer = "Transcend", + }, + { + .type = "sd", + .id = 0x1d, + .manufacturer = "Corsair/AData", + }, + { + .type = "sd", + .id = 0x1e, + .manufacturer = "Transcend", + }, + { + .type = "sd", + .id = 0x1f, + .manufacturer = "Kingston", + }, + { + .type = "sd", + .id = 0x27, + .manufacturer = "Delkin/Phison", + }, + { + .type = "sd", + .id = 0x28, + .manufacturer = "Lexar", + }, + { + .type = "sd", + .id = 0x30, + .manufacturer = "SanDisk", + }, + { + .type = "sd", + .id = 0x31, + .manufacturer = "Silicon Power", + }, + { + .type = "sd", + .id = 0x33, + .manufacturer = "STMicroelectronics", + }, + { + .type = "sd", + .id = 0x41, + .manufacturer = "Kingston", + }, + { + .type = "sd", + .id = 0x6f, + .manufacturer = "STMicroelectronics", + }, + { + .type = "sd", + .id = 0x74, + .manufacturer = "Transcend", + }, + { + .type = "sd", + .id = 0x76, + .manufacturer = "Patriot", + }, + { + .type = "sd", + .id = 0x82, + .manufacturer = "Gobe/Sony", + }, + { + .type = "sd", + .id = 0x89, + .manufacturer = "Unknown", + }}; /* Parse SD Card Manufacturer Database */ std::string parseSDCardManufacturerID(int id) { - unsigned int id_cnt = sizeof(database) / sizeof(struct SDCard_Manufacturer_database); - std::string ret_val = ""; + unsigned int id_cnt = sizeof(database) / sizeof(struct SDCard_Manufacturer_database); + std::string ret_val = ""; - for (int i = 0; i < id_cnt; i++) { - if (database[i].id == id) { - return database[i].manufacturer; - } - else { - ret_val = "ID unknown (not in DB)"; - } - } - return ret_val; + for (int i = 0; i < id_cnt; i++) { + if (database[i].id == id) { + return database[i].manufacturer; + } + else { + ret_val = "ID unknown (not in DB)"; + } + } + return ret_val; } std::string getSDCardManufacturer() { - std::string SDCardManufacturer = parseSDCardManufacturerID(SDCardCid.mfg_id); - //ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str()); + std::string SDCardManufacturer = parseSDCardManufacturerID(SDCardCid.mfg_id); + // ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str()); - return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")"); + return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")"); } std::string getSDCardName() { - char *SDCardName = SDCardCid.name; - //ESP_LOGD(TAG, "SD Card Name: %s", SDCardName); + char *SDCardName = SDCardCid.name; + // ESP_LOGD(TAG, "SD Card Name: %s", SDCardName); - return std::string(SDCardName); + return std::string(SDCardName); } int getSDCardPartitionSize() { - FATFS *fs; + FATFS *fs; uint32_t fre_clust, tot_sect; /* Get volume information and free clusters of drive 0 */ f_getfree("0:", (DWORD *)&fre_clust, &fs); - tot_sect = ((fs->n_fatent - 2) * fs->csize) /1024 /(1024/SDCardCsd.sector_size); //corrected by SD Card sector size (usually 512 bytes) and convert to MB + tot_sect = ((fs->n_fatent - 2) * fs->csize) / 1024 / + (1024 / SDCardCsd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB - //ESP_LOGD(TAG, "%d MB total drive space (Sector size [bytes]: %d)", (int)tot_sect, (int)fs->ssize); + // ESP_LOGD(TAG, "%d MB total drive space (Sector size [bytes]: %d)", (int)tot_sect, (int)fs->ssize); - return tot_sect; + return tot_sect; } int getSDCardFreePartitionSpace() { - FATFS *fs; + FATFS *fs; uint32_t fre_clust, fre_sect; /* Get volume information and free clusters of drive 0 */ f_getfree("0:", (DWORD *)&fre_clust, &fs); - fre_sect = (fre_clust * fs->csize) / 1024 /(1024/SDCardCsd.sector_size); //corrected by SD Card sector size (usually 512 bytes) and convert to MB + fre_sect = (fre_clust * fs->csize) / 1024 / + (1024 / SDCardCsd.sector_size); // corrected by SD Card sector size (usually 512 bytes) and convert to MB - //ESP_LOGD(TAG, "%d MB free drive space (Sector size [bytes]: %d)", (int)fre_sect, (int)fs->ssize); + // ESP_LOGD(TAG, "%d MB free drive space (Sector size [bytes]: %d)", (int)fre_sect, (int)fs->ssize); - return fre_sect; + return fre_sect; } int getSDCardPartitionAllocationSize() { - FATFS *fs; + FATFS *fs; uint32_t fre_clust, allocation_size; /* Get volume information and free clusters of drive 0 */ f_getfree("0:", (DWORD *)&fre_clust, &fs); allocation_size = fs->ssize; - //ESP_LOGD(TAG, "SD Card Partition Allocation Size: %d bytes", allocation_size); + // ESP_LOGD(TAG, "SD Card Partition Allocation Size: %d bytes", allocation_size); - return allocation_size; + return allocation_size; } int getSDCardCapacity() { - int SDCardCapacity = SDCardCsd.capacity / (1024/SDCardCsd.sector_size) / 1024; // total sectors * sector size --> Byte to MB (1024*1024) - //ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str()); + int SDCardCapacity = SDCardCsd.capacity / (1024 / SDCardCsd.sector_size) / + 1024; // total sectors * sector size --> Byte to MB (1024*1024) + // ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str()); - return SDCardCapacity; + return SDCardCapacity; } int getSDCardSectorSize() { - int SDCardSectorSize = SDCardCsd.sector_size; - //ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str()); + int SDCardSectorSize = SDCardCsd.sector_size; + // ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str()); - return SDCardSectorSize; -} \ No newline at end of file + return SDCardSectorSize; +} diff --git a/code/components/misc_helper/system.h b/code/components/misc_helper/system.h index 5715cecd6..27461b7f3 100644 --- a/code/components/misc_helper/system.h +++ b/code/components/misc_helper/system.h @@ -11,7 +11,7 @@ typedef enum { SPIRAMCategory_16MB = 2, SPIRAMCategory_32MB = 3, SPIRAMCategory_MAX = 4 -}SPIRAMCategory_t; +} SPIRAMCategory_t; std::string getBoardType(void); std::string getChipModel(void); @@ -24,7 +24,7 @@ int getConfigVersion(void); #ifdef SOC_TEMP_SENSOR_SUPPORTED void initSOCTemperatureSensor(); -#endif +#endif // SOC_TEMP_SENSOR_SUPPORTED float getSOCTemperature(); bool setCPUFrequency(void); @@ -44,17 +44,17 @@ SPIRAMCategory_t getSPIRAMCategory(); /* Error bit fields One bit per error Make sure it matches https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes */ -enum SystemStatusFlag_t { // One bit per error +enum SystemStatusFlag_t { // One bit per error // First Byte - SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 1, Critical Error - SYSTEM_STATUS_HEAP_TOO_SMALL = 1 << 1, // 2, Critical Error - SYSTEM_STATUS_CAM_BAD = 1 << 2, // 4, Critical Error - SYSTEM_STATUS_SDCARD_CHECK_BAD = 1 << 3, // 8, Critical Error - SYSTEM_STATUS_FOLDER_CHECK_BAD = 1 << 4, // 16, Critical Error + SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 1, Critical Error + SYSTEM_STATUS_HEAP_TOO_SMALL = 1 << 1, // 2, Critical Error + SYSTEM_STATUS_CAM_BAD = 1 << 2, // 4, Critical Error + SYSTEM_STATUS_SDCARD_CHECK_BAD = 1 << 3, // 8, Critical Error + SYSTEM_STATUS_FOLDER_CHECK_BAD = 1 << 4, // 16, Critical Error // Second Byte - SYSTEM_STATUS_CAM_FB_BAD = 1 << (0+8), // 8, Flow still might work - SYSTEM_STATUS_NTP_BAD = 1 << (1+8), // 9, Flow will work but time will be wrong + SYSTEM_STATUS_CAM_FB_BAD = 1 << (0 + 8), // 8, Flow still might work + SYSTEM_STATUS_NTP_BAD = 1 << (1 + 8), // 9, Flow will work but time will be wrong }; void setSystemStatusFlag(SystemStatusFlag_t flag); @@ -67,7 +67,7 @@ std::string getResetReason(void); void checkIsPlannedReboot(); bool getIsPlannedReboot(); -void saveSDCardInfo(sdmmc_card_t* card); +void saveSDCardInfo(sdmmc_card_t *card); std::string parseSDCardManufacturerID(int); std::string getSDCardManufacturer(void); std::string getSDCardName(void); @@ -77,4 +77,4 @@ int getSDCardPartitionAllocationSize(void); int getSDCardCapacity(void); int getSDCardSectorSize(void); -#endif //ESP_SYSTEM_H +#endif // ESP_SYSTEM_H diff --git a/code/components/mqtt_ctrl/interface_mqtt.cpp b/code/components/mqtt_ctrl/interface_mqtt.cpp index 4815be9ea..4cf3b1b3c 100644 --- a/code/components/mqtt_ctrl/interface_mqtt.cpp +++ b/code/components/mqtt_ctrl/interface_mqtt.cpp @@ -11,7 +11,7 @@ #ifdef DEBUG_DETAIL_ON #include -#endif +#endif // DEBUG_DETAIL_ON #include "MainFlowControl.h" #include "ClassLogFile.h" @@ -21,7 +21,7 @@ static const char *TAG = "MQTT_IF"; -static const CfgData::SectionMqtt* cfgDataPtr; +static const CfgData::SectionMqtt *cfgDataPtr; static std::string LWTTopic; static std::string TLSCACert; @@ -42,8 +42,8 @@ static struct strMqttState { static esp_mqtt_client_handle_t mqttClient = NULL; static const esp_mqtt_event_id_t mqttEventID = MQTT_EVENT_ANY; -static std::map>* connectFunctionMap = NULL; -static std::map>* subscribeFunctionMap = NULL; +static std::map> *connectFunctionMap = NULL; +static std::map> *subscribeFunctionMap = NULL; bool publishMqttData(std::string _key, std::string _content, int _qos, bool _retainFlag) @@ -53,28 +53,28 @@ bool publishMqttData(std::string _key, std::string _content, int _qos, bool _ret } if (mqttState.failedOnCycle == getFlowCycleCounter()) { // Already a failed transmission in this cycle - return true; // Fail quietly + return true; // Fail quietly } startMqttClient(); // Restart client if not started yet/anymore if (mqttState.mqttInitialized && mqttState.mqttConnected) { - #ifdef DEBUG_DETAIL_ON - long long int starttime = esp_timer_get_time(); - #endif +#ifdef DEBUG_DETAIL_ON + long long int starttime = esp_timer_get_time(); +#endif // DEBUG_DETAIL_ON int msg_id = esp_mqtt_client_publish(mqttClient, _key.c_str(), _content.c_str(), 0, _qos, _retainFlag); - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime)/1000); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime) / 1000); +#endif // DEBUG_DETAIL_ON if (msg_id == -1) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Failed to publish topic '" + _key + "', retry"); - #ifdef DEBUG_DETAIL_ON - starttime = esp_timer_get_time(); - #endif +#ifdef DEBUG_DETAIL_ON + starttime = esp_timer_get_time(); +#endif // DEBUG_DETAIL_ON msg_id = esp_mqtt_client_publish(mqttClient, _key.c_str(), _content.c_str(), 0, _qos, _retainFlag); - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime)/1000); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime) / 1000); +#endif // DEBUG_DETAIL_ON if (msg_id == -1) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to publish topic '" + _key + "', retry in next cycle"); mqttState.failedOnCycle = getFlowCycleCounter(); @@ -87,7 +87,8 @@ bool publishMqttData(std::string _key, std::string _content, int _qos, bool _ret _content.append(".."); } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Published topic: " + _key + ", content: " + _content + " | msg_id: " + std::to_string(msg_id)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Published topic: " + _key + ", content: " + _content + " | msg_id: " + std::to_string(msg_id)); return true; } else { @@ -137,14 +138,14 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) case MQTT_EVENT_DATA: ESP_LOGD(TAG, "MQTT_EVENT_DATA"); - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic); - ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "TOPIC=%.*s", event->topic_len, event->topic); + ESP_LOGI(TAG, "DATA=%.*s", event->data_len, event->data); +#endif // DEBUG_DETAIL_ON topic.assign(event->topic, event->topic_len); if (subscribeFunctionMap != NULL) { if (subscribeFunctionMap->find(topic) != subscribeFunctionMap->end()) { - //ESP_LOGD(TAG, "call subcribe function for topic %s", topic.c_str()); + // ESP_LOGD(TAG, "call subcribe function for topic %s", topic.c_str()); (*subscribeFunctionMap)[topic](topic, event->data, event->data_len); } else { @@ -181,20 +182,21 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) // Log any ESP-TLS error: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/error-codes.html if (cfgDataPtr->authMode == AUTH_TLS && (event->error_handle->esp_tls_last_esp_err != ESP_OK)) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Connection refused, TLS error code: " + - intToHexString(event->error_handle->esp_tls_last_esp_err) + + LogFile.writeToFile( + ESP_LOG_ERROR, TAG, + "Connection refused, TLS error code: " + intToHexString(event->error_handle->esp_tls_last_esp_err) + " (More infos: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/error-codes.html"); } - #ifdef DEBUG_DETAIL_ON - ESP_LOGI(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:"); - ESP_LOGI(TAG, "error_type:%d", event->error_handle->error_type); - ESP_LOGI(TAG, "connect_return_code:%d", event->error_handle->connect_return_code); - ESP_LOGI(TAG, "esp_transport_sock_errno:%d", event->error_handle->esp_transport_sock_errno); - ESP_LOGI(TAG, "esp_tls_last_esp_err:%d", event->error_handle->esp_tls_last_esp_err); - ESP_LOGI(TAG, "esp_tls_stack_err:%d", event->error_handle->esp_tls_stack_err); - ESP_LOGI(TAG, "esp_tls_cert_verify_flags:%d", event->error_handle->esp_tls_cert_verify_flags); - #endif +#ifdef DEBUG_DETAIL_ON + ESP_LOGI(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:"); + ESP_LOGI(TAG, "error_type:%d", event->error_handle->error_type); + ESP_LOGI(TAG, "connect_return_code:%d", event->error_handle->connect_return_code); + ESP_LOGI(TAG, "esp_transport_sock_errno:%d", event->error_handle->esp_transport_sock_errno); + ESP_LOGI(TAG, "esp_tls_last_esp_err:%d", event->error_handle->esp_tls_last_esp_err); + ESP_LOGI(TAG, "esp_tls_stack_err:%d", event->error_handle->esp_tls_stack_err); + ESP_LOGI(TAG, "esp_tls_cert_verify_flags:%d", event->error_handle->esp_tls_cert_verify_flags); +#endif // DEBUG_DETAIL_ON break; @@ -208,8 +210,8 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) { - //ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, (int)event_id); - mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data); + // ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, (int)event_id); + mqtt_event_handler_cb((esp_mqtt_event_handle_t)event_data); } @@ -225,19 +227,19 @@ bool configureMqttClient(const CfgData::SectionMqtt *_param, int keepAlive) LWTTopic = cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC; - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "URI: " + cfgDataPtr->uri + ", clientID: " + cfgDataPtr->clientID + - ", username: " + cfgDataPtr->username + ", password: *****, mainTopic: " + cfgDataPtr->mainTopic + - ", last-will-topic: " + LWTTopic + ", keepAlive: " + std::to_string(keepAlive) + - ", RetainProcessData: " + std::to_string(cfgDataPtr->retainProcessData) + - ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "URI: " + cfgDataPtr->uri + ", clientID: " + cfgDataPtr->clientID + ", username: " + cfgDataPtr->username + + ", password: *****, mainTopic: " + cfgDataPtr->mainTopic + ", last-will-topic: " + LWTTopic + ", keepAlive: " + + std::to_string(keepAlive) + ", RetainProcessData: " + std::to_string(cfgDataPtr->retainProcessData) + + ", AuthMode: " + std::to_string(cfgDataPtr->authMode)); if (cfgDataPtr->authMode == AUTH_TLS) { - if (cfgDataPtr->uri.substr(0,8) != "mqtts://") { + if (cfgDataPtr->uri.substr(0, 8) != "mqtts://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "TLS: URI parameter needs to be configured with \'mqtts://\'"); return false; } - if (cfgDataPtr->uri.substr(cfgDataPtr->uri.find_last_of(":")+1, 4) != "8883") { + if (cfgDataPtr->uri.substr(cfgDataPtr->uri.find_last_of(":") + 1, 4) != "8883") { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "TLS: URI parameter not using default MQTT TLS port \'8883\'"); } @@ -272,12 +274,12 @@ bool configureMqttClient(const CfgData::SectionMqtt *_param, int keepAlive) } } else { - if (cfgDataPtr->uri.substr(0,7) != "mqtt://") { + if (cfgDataPtr->uri.substr(0, 7) != "mqtt://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "URI parameter needs to be configured with \'mqtt://\'"); return false; } - if (cfgDataPtr->uri.substr(cfgDataPtr->uri.find_last_of(":")+1, 4) != "1883") { + if (cfgDataPtr->uri.substr(cfgDataPtr->uri.find_last_of(":") + 1, 4) != "1883") { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "URI parameter not using default MQTT port \'1883\'"); } } @@ -306,19 +308,19 @@ int startMqttClient(void) LogFile.writeToFile(ESP_LOG_INFO, TAG, "Init MQTT service"); deinitMqttClient(); - esp_mqtt_client_config_t mqtt_cfg = { }; + esp_mqtt_client_config_t mqtt_cfg = {}; mqtt_cfg.broker.address.uri = cfgDataPtr->uri.c_str(); mqtt_cfg.credentials.client_id = cfgDataPtr->clientID.c_str(); - mqtt_cfg.network.disable_auto_reconnect = false; // Reconnection routine active (Default: false) - mqtt_cfg.network.reconnect_timeout_ms = 15000; // Try to reconnect to broker (Default: 10000ms) - mqtt_cfg.network.timeout_ms = 10000; // Network Timeout (Default: 10000ms) - mqtt_cfg.session.message_retransmit_timeout = 3000; // Time after message resent when broker not acknowledged (QoS1, QoS2) + mqtt_cfg.network.disable_auto_reconnect = false; // Reconnection routine active (Default: false) + mqtt_cfg.network.reconnect_timeout_ms = 15000; // Try to reconnect to broker (Default: 10000ms) + mqtt_cfg.network.timeout_ms = 10000; // Network Timeout (Default: 10000ms) + mqtt_cfg.session.message_retransmit_timeout = 3000; // Time after message resent when broker not acknowledged (QoS1, QoS2) mqtt_cfg.session.last_will.topic = LWTTopic.c_str(); mqtt_cfg.session.last_will.retain = 1; mqtt_cfg.session.last_will.msg = std::string(MQTT_STATUS_OFFLINE).c_str(); mqtt_cfg.session.keepalive = keepAlive; - mqtt_cfg.buffer.size = 1024; // size of MQTT send/receive buffer (Default: 1024) + mqtt_cfg.buffer.size = 1024; // size of MQTT send/receive buffer (Default: 1024) if (cfgDataPtr->authMode == AUTH_BASIC) { mqtt_cfg.credentials.username = cfgDataPtr->username.c_str(); @@ -331,7 +333,7 @@ int startMqttClient(void) if (!TLSCACert.empty()) { mqtt_cfg.broker.verification.certificate = TLSCACert.c_str(); mqtt_cfg.broker.verification.certificate_len = TLSCACert.length() + 1; - mqtt_cfg.broker.verification.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field + mqtt_cfg.broker.verification.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CA Certificate empty, use certification bundle for server verfication"); @@ -352,8 +354,7 @@ int startMqttClient(void) mqttClient = esp_mqtt_client_init(&mqtt_cfg); if (mqttClient) { esp_err_t ret = esp_mqtt_client_register_event(mqttClient, mqttEventID, mqtt_event_handler, mqttClient); - if (ret != ESP_OK) - { + if (ret != ESP_OK) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Could not register event (ret=" + std::to_string(ret) + ")"); mqttState.mqttInitialized = false; return -1; @@ -411,16 +412,17 @@ bool getMqttIsConnected(void) bool getMqttIsEncrypted(void) { - if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) + if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) { return true; + } return false; } -bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) +bool mqtt_handler_flow_start(std::string _topic, char *_data, int _data_len) { - //ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); + // ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); if (_data_len > 0) { triggerFlowStartByMqtt(_topic); @@ -433,20 +435,21 @@ bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) } -bool mqtt_handler_set_fallbackvalue(std::string _topic, char* _data, int _data_len) +bool mqtt_handler_set_fallbackvalue(std::string _topic, char *_data, int _data_len) { - //ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); - //example: {"sequence": "main", "value": 12345.1234567} + // ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data); + // example: {"sequence": "main", "value": 12345.1234567} - if (_data_len > 0) { // Check if data length > 0 + if (_data_len > 0) { // Check if data length > 0 cJSON *jsonData = cJSON_Parse(_data); cJSON *sequenceName = cJSON_GetObjectItemCaseSensitive(jsonData, "sequence"); cJSON *value = cJSON_GetObjectItemCaseSensitive(jsonData, "value"); - if (cJSON_IsString(sequenceName) && (sequenceName->valuestring != NULL)) { // Check if sequenceName is valid - if (cJSON_IsNumber(value)) { // Check if value is a number - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "handler_set_fallbackvalue called: sequence: " + std::string(sequenceName->valuestring) + - ", value: " + std::to_string(value->valuedouble)); + if (cJSON_IsString(sequenceName) && (sequenceName->valuestring != NULL)) { // Check if sequenceName is valid + if (cJSON_IsNumber(value)) { // Check if value is a number + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "handler_set_fallbackvalue called: sequence: " + std::string(sequenceName->valuestring) + + ", value: " + std::to_string(value->valuedouble)); if (flowctrl.setFallbackValue(std::string(sequenceName->valuestring), std::to_string(value->valuedouble))) { cJSON_Delete(jsonData); return true; @@ -476,9 +479,10 @@ void isConnectedState(void) publishMqttData(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, 1, false); // Send MQTT birth message "online" if (connectFunctionMap != NULL) { - for(std::map>::iterator it = connectFunctionMap->begin(); it != connectFunctionMap->end(); ++it) { + for (std::map>::iterator it = connectFunctionMap->begin(); it != connectFunctionMap->end(); + ++it) { it->second(); - //ESP_LOGD(TAG, "call connect function %s", it->first.c_str()); + // ESP_LOGD(TAG, "call connect function %s", it->first.c_str()); } } @@ -486,28 +490,29 @@ void isConnectedState(void) // Note: Further subsriptions are handled in GPIO class //***************************************** // Subcribe to [mainTopic]/process/ctrl/flow_start - std::function subHandler1 = mqtt_handler_flow_start; + std::function subHandler1 = mqtt_handler_flow_start; registerMqttSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/cycle_start", subHandler1); // Subcribe to [mainTopic]/process/ctrl/set_fallbackvalue - std::function subHandler2 = mqtt_handler_set_fallbackvalue; + std::function subHandler2 = mqtt_handler_set_fallbackvalue; registerMqttSubscribeFunction(cfgDataPtr->mainTopic + "/process/ctrl/set_fallbackvalue", subHandler2); // Subcribe to /homeassistant/status if (cfgDataPtr->homeAssistant.discoveryEnabled) { - std::function subHandler3 = mqttServer_schedulePublishHADiscoveryFromMqtt; + std::function subHandler3 = mqttServer_schedulePublishHADiscoveryFromMqtt; registerMqttSubscribeFunction(cfgDataPtr->homeAssistant.statusTopic, subHandler3); } - if (subscribeFunctionMap != NULL) { - for(std::map>::iterator it = subscribeFunctionMap->begin(); - it != subscribeFunctionMap->end(); ++it) - { + if (subscribeFunctionMap != NULL) { + for (std::map>::iterator it = subscribeFunctionMap->begin(); + it != subscribeFunctionMap->end(); ++it) { int retVal = esp_mqtt_client_subscribe(mqttClient, it->first.c_str(), 0); - if (retVal >= 0) + if (retVal >= 0) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Topic subscribed: " + it->first); - else + } + else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to subscribe topic: " + it->first); + } } } } @@ -516,7 +521,7 @@ void isConnectedState(void) void registerMqttConnectFunction(std::string name, std::function func) { - //ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str()); + // ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str()); if (connectFunctionMap == NULL) { connectFunctionMap = new std::map>(); } @@ -543,11 +548,11 @@ void unregisterMqttConnectFunction(std::string name) } -void registerMqttSubscribeFunction(std::string topic, std::function func) +void registerMqttSubscribeFunction(std::string topic, std::function func) { - //ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str()); + // ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str()); if (subscribeFunctionMap == NULL) { - subscribeFunctionMap = new std::map>(); + subscribeFunctionMap = new std::map>(); } if ((*subscribeFunctionMap)[topic] != NULL) { @@ -563,14 +568,15 @@ void unregisterMqttSubscribeFunction() { if (subscribeFunctionMap != NULL) { if (mqttState.mqttConnected) { - for(std::map>::iterator it = subscribeFunctionMap->begin(); - it != subscribeFunctionMap->end(); ++it) - { + for (std::map>::iterator it = subscribeFunctionMap->begin(); + it != subscribeFunctionMap->end(); ++it) { int retVal = esp_mqtt_client_unsubscribe(mqttClient, it->first.c_str()); - if (retVal >= 0) + if (retVal >= 0) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Topic unsubscribed: " + it->first); - else + } + else { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to unsubscribe topic: " + it->first); + } } } @@ -579,4 +585,4 @@ void unregisterMqttSubscribeFunction() subscribeFunctionMap = NULL; } } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT diff --git a/code/components/mqtt_ctrl/interface_mqtt.h b/code/components/mqtt_ctrl/interface_mqtt.h index 43de2a602..b0b5356b0 100644 --- a/code/components/mqtt_ctrl/interface_mqtt.h +++ b/code/components/mqtt_ctrl/interface_mqtt.h @@ -21,11 +21,11 @@ bool getMqttIsEncrypted(void); void registerMqttConnectFunction(std::string name, std::function func); void unregisterMqttConnectFunction(std::string name); -void registerMqttSubscribeFunction(std::string topic, std::function func); +void registerMqttSubscribeFunction(std::string topic, std::function func); void unregisterMqttSubscribeFunction(); void isConnectedState(void); void deinitMqttClient(bool disable = false); -#endif //INTERFACE_MQTT_H -#endif //#ENABLE_MQTT +#endif // INTERFACE_MQTT_H +#endif // ENABLE_MQTT diff --git a/code/components/mqtt_ctrl/server_mqtt.cpp b/code/components/mqtt_ctrl/server_mqtt.cpp index d38e8e94c..7ffc7a716 100644 --- a/code/components/mqtt_ctrl/server_mqtt.cpp +++ b/code/components/mqtt_ctrl/server_mqtt.cpp @@ -22,9 +22,9 @@ static const char *TAG = "SERVER_MQTT"; -extern const char* libfive_git_version(void); -extern const char* libfive_git_revision(void); -extern const char* libfive_git_branch(void); +extern const char *libfive_git_version(void); +extern const char *libfive_git_revision(void); +extern const char *libfive_git_branch(void); static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, int _qos); static bool publishHADiscoveryTopicDeviceInfo = true; @@ -40,8 +40,9 @@ static std::string meterType, valueUnit, timeUnit, rateUnit; // Publish device info topics (common topics, static, retained) bool mqttServer_publishDeviceInfo(int _qos) { - if (!publishDeviceInfoScheduled) + if (!publishDeviceInfoScheduled) { return true; + } if (!getMqttIsConnected()) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip publish device info, not (yet) connected to broker"); @@ -65,16 +66,21 @@ bool mqttServer_publishDeviceInfo(int _qos) retVal = false; } else { - if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "board_type", getBoardType().c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "board_type", getBoardType().c_str()) == NULL) { retVal = false; - if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "chip_model", getChipModel().c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "chip_model", getChipModel().c_str()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObjectHardwareBoard, "chip_cores", getChipCoreCount()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObjectHardwareBoard, "chip_cores", getChipCoreCount()) == NULL) { retVal = false; - if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "chip_revision", getChipRevision().c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObjectHardwareBoard, "chip_revision", getChipRevision().c_str()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObjectHardwareBoard, "chip_frequency", esp_clk_cpu_freq()/1000000) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObjectHardwareBoard, "chip_frequency", esp_clk_cpu_freq() / 1000000) == NULL) { retVal = false; + } } cJSON *cJSONObjectHardwareCamera = cJSON_AddObjectToObject(cJSONObject, "camera"); @@ -82,10 +88,12 @@ bool mqttServer_publishDeviceInfo(int _qos) retVal = false; } else { - if (cJSON_AddStringToObject(cJSONObjectHardwareCamera, "type", cameraCtrl.getCamType().c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObjectHardwareCamera, "type", cameraCtrl.getCamType().c_str()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObjectHardwareCamera, "frequency", cameraCtrl.getCamFrequencyMhz()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObjectHardwareCamera, "frequency", cameraCtrl.getCamFrequencyMhz()) == NULL) { retVal = false; + } } cJSON *cJSONObjectHardwareSDCard = cJSON_AddObjectToObject(cJSONObject, "sdcard"); @@ -93,10 +101,12 @@ bool mqttServer_publishDeviceInfo(int _qos) retVal = false; } else { - if (cJSON_AddNumberToObject(cJSONObjectHardwareSDCard, "capacity", getSDCardCapacity()) == NULL) + if (cJSON_AddNumberToObject(cJSONObjectHardwareSDCard, "capacity", getSDCardCapacity()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObjectHardwareSDCard, "partition_size", getSDCardPartitionSize()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObjectHardwareSDCard, "partition_size", getSDCardPartitionSize()) == NULL) { retVal = false; + } } char *jsonChar = cJSON_PrintBuffered(cJSONObject, 384, 1); // Print to predefined buffer, reduce dynamic allocations @@ -115,12 +125,15 @@ bool mqttServer_publishDeviceInfo(int _qos) LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create JSON object"); return false; } - if (cJSON_AddStringToObject(cJSONObject, "hostname", getHostname().c_str()) == NULL) + if (cJSON_AddStringToObject(cJSONObject, "hostname", getHostname().c_str()) == NULL) { retVal = false; - if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIpAddress().c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "ipv4_address", getIpAddress().c_str()) == NULL) { retVal = false; - if (cJSON_AddStringToObject(cJSONObject, "mac_address", getMac().c_str()) == NULL) + } + if (cJSON_AddStringToObject(cJSONObject, "mac_address", getMac().c_str()) == NULL) { retVal = false; + } jsonChar = cJSON_Print(cJSONObject); cJSON_Delete(cJSONObject); @@ -134,8 +147,9 @@ bool mqttServer_publishDeviceInfo(int _qos) // Prepare topic: device/info/version std::string firmwareVersion = std::string(libfive_git_version()); - if (firmwareVersion == "" || firmwareVersion == "N/A") + if (firmwareVersion == "" || firmwareVersion == "N/A") { firmwareVersion = std::string(libfive_git_branch()) + " (" + std::string(libfive_git_revision()) + ")"; + } retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceInfoTopic + "firmware_version", firmwareVersion, _qos, true); @@ -165,27 +179,35 @@ bool mqttServer_publishDeviceStatus(int _qos) retVal &= publishMqttData(cfgDataPtr->mainTopic + MQTT_STATUS_TOPIC, MQTT_STATUS_ONLINE, _qos, false); retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "device_uptime", std::to_string(getUptime()), _qos, false); retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "wlan_rssi", std::to_string(getWifiRssi()), _qos, false); - retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "chip_temp", to_stringWithPrecision(getSOCTemperature(), 0), _qos, false); + retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "chip_temp", to_stringWithPrecision(getSOCTemperature(), 0), _qos, + false); cJSON *cJSONObject = cJSON_CreateObject(); if (cJSONObject == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Failed to create JSON object"); return false; } - if (cJSON_AddNumberToObject(cJSONObject, "heap_total_free", getESPHeapSizeTotalFree()) == NULL) + if (cJSON_AddNumberToObject(cJSONObject, "heap_total_free", getESPHeapSizeTotalFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_free", getESPHeapSizeInternalFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_free", getESPHeapSizeInternalFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_largest_free", getESPHeapSizeInternalLargestFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_largest_free", getESPHeapSizeInternalLargestFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_min_free", getESPHeapSizeInternalMinFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_internal_min_free", getESPHeapSizeInternalMinFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_free", getESPHeapSizeSPIRAMFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_free", getESPHeapSizeSPIRAMFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_largest_free", getESPHeapSizeSPIRAMLargestFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_largest_free", getESPHeapSizeSPIRAMLargestFree()) == NULL) { retVal = false; - if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_min_free", getESPHeapSizeSPIRAMMinFree()) == NULL) + } + if (cJSON_AddNumberToObject(cJSONObject, "heap_spiram_min_free", getESPHeapSizeSPIRAMMinFree()) == NULL) { retVal = false; + } char *jsonChar = cJSON_Print(cJSONObject); cJSON_Delete(cJSONObject); @@ -195,7 +217,8 @@ bool mqttServer_publishDeviceStatus(int _qos) cJSON_free(jsonChar); } - retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "sd_partition_free", std::to_string(getSDCardFreePartitionSpace()), _qos, false); + retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "sd_partition_free", + std::to_string(getSDCardFreePartitionSpace()), _qos, false); retVal &= publishMqttData(cfgDataPtr->mainTopic + deviceStatusTopic + "ntp_syncstatus", getNTPSyncStatus().c_str(), _qos, false); if (!retVal) { @@ -207,7 +230,8 @@ bool mqttServer_publishDeviceStatus(int _qos) } -void mqttServer_setParameter(const CfgData::SectionMqtt *_cfgDataPtr, const std::vector *_sequenceData, const float _processingInterval) +void mqttServer_setParameter(const CfgData::SectionMqtt *_cfgDataPtr, const std::vector *_sequenceData, + const float _processingInterval) { cfgDataPtr = _cfgDataPtr; sequenceData = _sequenceData; @@ -248,9 +272,9 @@ void mqttServer_schedulePublishHADiscovery() } -bool mqttServer_schedulePublishHADiscoveryFromMqtt(std::string _topic, char* _data, int _data_len) +bool mqttServer_schedulePublishHADiscoveryFromMqtt(std::string _topic, char *_data, int _data_len) { - if (_data_len > 0) { // Check if data length > 0 + if (_data_len > 0) { // Check if data length > 0 if (strncmp("online", _data, _data_len) == 0) { publishHADiscoveryScheduled = true; } @@ -262,20 +286,19 @@ bool mqttServer_schedulePublishHADiscoveryFromMqtt(std::string _topic, char* _da esp_err_t handler_mqtt(httpd_req_t *req) { - const char* APIName = "mqtt:v2"; // API name and version + const char *APIName = "mqtt:v2"; // API name and version char _query[64]; char _valuechar[30]; std::string task; // Default usage message when handler gets called without any parameter - const std::string RESTUsageInfo = - "Handler usage:
" - "1. Schedule publication of Home Assistant discovery MQTT topics:
" - " - '/mqtt?task=publish_ha_discovery'
" - "2. Schedule publication of device info MQTT topics:
" - " - '/mqtt?task=publish_device_info'
" - "3. Print API name and version
" - " - '/mqtt?task=api_name'"; + const std::string RESTUsageInfo = "Handler usage:
" + "1. Schedule publication of Home Assistant discovery MQTT topics:
" + " - '/mqtt?task=publish_ha_discovery'
" + "2. Schedule publication of device info MQTT topics:
" + " - '/mqtt?task=publish_device_info'
" + "3. Print API name and version
" + " - '/mqtt?task=api_name'"; httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*"); httpd_resp_set_type(req, "text/plain"); @@ -285,7 +308,7 @@ esp_err_t handler_mqtt(httpd_req_t *req) task = std::string(_valuechar); } } - else { // if no parameter is provided, print handler usage + else { // if no parameter is provided, print handler usage httpd_resp_set_type(req, "text/html"); httpd_resp_sendstr(req, RESTUsageInfo.c_str()); return ESP_OK; @@ -315,16 +338,18 @@ esp_err_t handler_mqtt(httpd_req_t *req) // Publish HA discovery topics (no retained) bool mqttServer_publishHADiscovery(int _qos) { - if (!cfgDataPtr->homeAssistant.discoveryEnabled || !publishHADiscoveryScheduled) // Continue if enabled and scheduled + if (!cfgDataPtr->homeAssistant.discoveryEnabled || !publishHADiscoveryScheduled) { // Continue if enabled and scheduled return true; + } if (!getMqttIsConnected()) { LogFile.writeToFile(ESP_LOG_WARN, TAG, "Skip publish HA discovery, not (yet) connected to broker"); return false; } - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Publish HA discovery | Sensor device class: " + meterType + - ", Value unit: " + valueUnit + " , Rate unit: " + rateUnit); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "Publish HA discovery | Sensor device class: " + meterType + ", Value unit: " + valueUnit + + " , Rate unit: " + rateUnit); publishHADiscoveryTopicDeviceInfo = true; // Publish full common device info data only once bool publishOK = true; @@ -336,7 +361,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "ipv4_address", .friendlyName = "IP Address", .icon = "network-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -347,7 +372,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "mac_address", .friendlyName = "MAC Address", .icon = "network-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -358,7 +383,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "hostname", .friendlyName = "Hostname", .icon = "network-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -369,7 +394,7 @@ bool mqttServer_publishHADiscovery(int _qos) .friendlyName = "Uptime", .icon = "clock-time-eight-outline", .unit = "s", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -382,7 +407,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "memory", .unit = "B", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -395,7 +420,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "memory", .unit = "B", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -409,7 +434,7 @@ bool mqttServer_publishHADiscovery(int _qos) .unit = "dBm", .deviceClass = "signal_strength", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -422,7 +447,7 @@ bool mqttServer_publishHADiscovery(int _qos) .unit = "°C", .deviceClass = "temperature", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -432,7 +457,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "ntp_syncstatus", .friendlyName = "NTP Sync Status", .icon = "network-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -442,7 +467,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "process_status", .friendlyName = "Process Status", .icon = "list-status", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -453,7 +478,7 @@ bool mqttServer_publishHADiscovery(int _qos) .friendlyName = "Process Interval", .icon = "clock-time-eight-outline", .unit = "min", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -465,7 +490,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "clock-time-eight-outline", .unit = "s", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -475,7 +500,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "process_state", .friendlyName = "Process State", .icon = "list-status", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -485,7 +510,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "process_error", .friendlyName = "Process Error State", .icon = "alert-outline", - .deviceClass = "problem" + .deviceClass = "problem" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -495,7 +520,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "process_error_value", .friendlyName = "Process Error Value", .icon = "alert-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -511,7 +536,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "gauge", .unit = valueUnit, .deviceClass = meterType, - .stateClass = sequence->paramPostProc->allowNegativeRate ? "measurement" : "total_increasing" + .stateClass = sequence->paramPostProc->allowNegativeRate ? "measurement" : "total_increasing" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -527,7 +552,7 @@ bool mqttServer_publishHADiscovery(int _qos) .unit = valueUnit, .deviceClass = meterType, .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); } @@ -543,7 +568,7 @@ bool mqttServer_publishHADiscovery(int _qos) .unit = valueUnit, .deviceClass = meterType, .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -555,7 +580,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topicName = "value_status", .friendlyName = "Value Status", .icon = "alert-circle-outline", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -569,7 +594,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "swap-vertical", .unit = rateUnit, .deviceClass = meterType == "energy" ? "power" : "volume_flow_rate", - .stateClass = "measurement" + .stateClass = "measurement" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -583,7 +608,7 @@ bool mqttServer_publishHADiscovery(int _qos) .icon = "arrow-expand-vertical", .unit = valueUnit != "" ? valueUnit + "/" + to_stringWithPrecision(processingInterval, 1) + "min" : "", .stateClass = "measurement", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -596,7 +621,7 @@ bool mqttServer_publishHADiscovery(int _qos) .friendlyName = "Last Processed", .icon = "clock-time-eight-outline", .deviceClass = "timestamp", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); } @@ -606,7 +631,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topic = "/process/ctrl/cycle_start", .topicName = "cycle_start", .friendlyName = "Manual Cycle Start", - .icon = "timer-play-outline", + .icon = "timer-play-outline" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -626,7 +651,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topic = "/device/gpio/" + gpioName + "/state", .topicName = "state", .friendlyName = "State", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); @@ -638,7 +663,7 @@ bool mqttServer_publishHADiscovery(int _qos) .topic = "/device/gpio/" + gpioName + "/state", .topicName = "pwm_duty", .friendlyName = "PWM Duty", - .entityCategory = "diagnostic" + .entityCategory = "diagnostic" // }; publishOK &= publishHADiscoveryTopic(&HADiscoveryData, _qos); } @@ -658,8 +683,9 @@ static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, const int _ { // Use MQTT maintopic without path structure as nodeID std::string nodeID = cfgDataPtr->mainTopic; - if ((cfgDataPtr->mainTopic.find_last_of('/')) != -1) - nodeID = cfgDataPtr->mainTopic.substr(cfgDataPtr->mainTopic.find_last_of('/')+1); + if ((cfgDataPtr->mainTopic.find_last_of('/')) != -1) { + nodeID = cfgDataPtr->mainTopic.substr(cfgDataPtr->mainTopic.find_last_of('/') + 1); + } // Add name prefix for number sequences to make ID and friendly names unique std::string topicNameID = _data->topicName; @@ -670,45 +696,44 @@ static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, const int _ } // Define configuration topic (default component: sensor) - std::string configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/sensor/" + nodeID + "/" + topicNameID + "/config"; + std::string configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/sensor/" + nodeID + "/" + topicNameID + "/config"; if (_data->topicName == "process_error") { // Special case: Process error configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/binary_sensor/" + nodeID + "/" + topicNameID + "/config"; } else if (_data->topicName == "cycle_start") { // Special case: Cycle start - configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/button/" + nodeID + "/" + topicNameID + "/config"; + configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/button/" + nodeID + "/" + topicNameID + "/config"; } else if (_data->topic.contains("/gpio/")) { // Special case: GPIO - if (_data->topicName == "state") { // State + if (_data->topicName == "state") { // State configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/binary_sensor/" + nodeID + "/" + topicNameID + "/config"; } else { // PWM duty - configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/sensor/" + nodeID + "/" + topicNameID + "/config"; + configurationTopic = cfgDataPtr->homeAssistant.discoveryPrefix + "/sensor/" + nodeID + "/" + topicNameID + "/config"; } } // Define payload for configuration topic // See https://www.home-assistant.io/docs/mqtt/discovery/ // Abbreviations: https://www.home-assistant.io/integrations/mqtt/#supported-abbreviations-in-mqtt-discovery-messages - std::string payload = - "{\"~\":\"" + cfgDataPtr->mainTopic + "\"," + - "\"uniq_id\":\"" + nodeID + "_" + topicNameID + "\"," + - //"\"obj_id\":\"" + nodeID + "_" + topicNameID + "\"," + // This used to generate the entity ID - "\"name\":\"" + friendlyName + "\","; + std::string payload = "{\"~\":\"" + cfgDataPtr->mainTopic + "\"," + "\"uniq_id\":\"" + nodeID + "_" + topicNameID + "\"," + + //"\"obj_id\":\"" + nodeID + "_" + topicNameID + "\"," + // This used to generate the entity ID + "\"name\":\"" + friendlyName + "\","; - if (!_data->icon.empty()) + if (!_data->icon.empty()) { payload += "\"ic\":\"mdi:" + _data->icon + "\","; + } // Define command or status topic - if (_data->topicName == "cycle_start") { // Special case: cyle_start command + if (_data->topicName == "cycle_start") { // Special case: cyle_start command payload += "\"cmd_t\":\"~" + _data->topic + "\","; // Add command topic payload += "\"pl_prs\":\"1\","; } - else if (_data->topic.contains("/gpio/")) { // Special case: GPIO + else if (_data->topic.contains("/gpio/")) { // Special case: GPIO payload += "\"stat_t\":\"~" + _data->topic + "\","; // Add status topic - if (_data->topicName == "state") { // GPIO state - payload += "\"pl_on\":\"1\","; // payload "ON" + if (_data->topicName == "state") { // GPIO state + payload += "\"pl_on\":\"1\","; // payload "ON" payload += "\"pl_off\":\"0\","; // payload "OFF" } } @@ -754,17 +779,12 @@ static bool publishHADiscoveryTopic(const strHADiscoveryData *_data, const int _ firmwareVersion = std::string(libfive_git_branch()) + " (" + std::string(libfive_git_revision()) + ")"; } - payload += std::string(", \"dev\": {") + - "\"ids\":[\"" + nodeID + "\"]," + - "\"name\":\"" + nodeID + "\"," + - "\"mdl\":\"AI-on-the-Edge device [" + getBoardType() + "]\"," + - "\"mf\":\"AI-on-the-Edge\"," + - "\"sw\":\"" + firmwareVersion + " [SLFork]\"," + - "\"cu\":\"http://" + getIpAddress() + "\"}"; + payload += std::string(", \"dev\": {") + "\"ids\":[\"" + nodeID + "\"]," + "\"name\":\"" + nodeID + "\"," + + "\"mdl\":\"AI-on-the-Edge device [" + getBoardType() + "]\"," + "\"mf\":\"AI-on-the-Edge\"," + "\"sw\":\"" + + firmwareVersion + " [SLFork]\"," + "\"cu\":\"http://" + getIpAddress() + "\"}"; } else { // Publish device reference only to group data together - payload += std::string(", \"dev\": {") + - "\"ids\":[\"" + nodeID + "\"]}"; + payload += std::string(", \"dev\": {") + "\"ids\":[\"" + nodeID + "\"]}"; } payload += "}"; @@ -781,13 +801,13 @@ void registerMqttUri(httpd_handle_t server) { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t uri = { }; - uri.method = HTTP_GET; + httpd_uri_t uri = {}; + uri.method = HTTP_GET; - uri.uri = "/mqtt"; - uri.handler = handler_mqtt; - uri.user_ctx = NULL; + uri.uri = "/mqtt"; + uri.handler = handler_mqtt; + uri.user_ctx = NULL; httpd_register_uri_handler(server, &uri); } -#endif //ENABLE_MQTT +#endif // ENABLE_MQTT diff --git a/code/components/mqtt_ctrl/server_mqtt.h b/code/components/mqtt_ctrl/server_mqtt.h index 7a9b88911..2be919221 100644 --- a/code/components/mqtt_ctrl/server_mqtt.h +++ b/code/components/mqtt_ctrl/server_mqtt.h @@ -26,18 +26,19 @@ bool mqttServer_publishHADiscovery(int _qos); bool mqttServer_publishDeviceInfo(int _qos); bool mqttServer_publishDeviceStatus(int _qos); -void mqttServer_setParameter(const CfgData::SectionMqtt *_cfgDataPtr, const std::vector *_sequenceData, const float _processingInterval); -void mqttServer_setMeterType(const std::string _meterType, const std::string _valueUnit, - const std::string _timeUnit, const std::string _rateUnit); +void mqttServer_setParameter(const CfgData::SectionMqtt *_cfgDataPtr, const std::vector *_sequenceData, + const float _processingInterval); +void mqttServer_setMeterType(const std::string _meterType, const std::string _valueUnit, const std::string _timeUnit, + const std::string _rateUnit); std::string mqttServer_getMainTopic(); std::string mqttServer_getTimeUnit(); void mqttServer_schedulePublishDeviceInfo(); void mqttServer_schedulePublishHADiscovery(); -bool mqttServer_schedulePublishHADiscoveryFromMqtt(std::string topic, char* data, int data_len); +bool mqttServer_schedulePublishHADiscoveryFromMqtt(std::string topic, char *data, int data_len); void registerMqttUri(httpd_handle_t server); -#endif //SERVERMQTT_H -#endif //ENABLE_MQTT \ No newline at end of file +#endif // SERVERMQTT_H +#endif // ENABLE_MQTT diff --git a/code/components/openmetrics_ctrl/openmetrics.cpp b/code/components/openmetrics_ctrl/openmetrics.cpp index e04cd4537..938ac0a95 100644 --- a/code/components/openmetrics_ctrl/openmetrics.cpp +++ b/code/components/openmetrics_ctrl/openmetrics.cpp @@ -23,17 +23,12 @@ static const char *TAG = "OPENMETRICS"; **/ std::string createHardwareInfoMetric(const std::string &metricNamePrefix) { - return "# TYPE " + metricNamePrefix + "hardware_info gauge\n" + - "# HELP " + metricNamePrefix + "hardware_info Hardware info\n" + - metricNamePrefix + "hardware_info{board_type=\"" + getBoardType() + - "\",chip_model=\"" + getChipModel() + - "\",chip_cores=\"" + std::to_string(getChipCoreCount()) + - "\",chip_revision=\"" + getChipRevision() + - "\",chip_frequency=\"" + std::to_string(esp_clk_cpu_freq()/1000000) + - "\",camera_type=\"" + cameraCtrl.getCamType() + - "\",camera_frequency=\"" + std::to_string(cameraCtrl.getCamFrequencyMhz()) + - "\",sdcard_capacity=\"" + std::to_string(getSDCardCapacity()) + - "\",sdcard_partition_size=\"" + std::to_string(getSDCardPartitionSize()) + "\"} 1\n"; + return "# TYPE " + metricNamePrefix + "hardware_info gauge\n" + "# HELP " + metricNamePrefix + "hardware_info Hardware info\n" + + metricNamePrefix + "hardware_info{board_type=\"" + getBoardType() + "\",chip_model=\"" + getChipModel() + "\",chip_cores=\"" + + std::to_string(getChipCoreCount()) + "\",chip_revision=\"" + getChipRevision() + "\",chip_frequency=\"" + + std::to_string(esp_clk_cpu_freq() / 1000000) + "\",camera_type=\"" + cameraCtrl.getCamType() + "\",camera_frequency=\"" + + std::to_string(cameraCtrl.getCamFrequencyMhz()) + "\",sdcard_capacity=\"" + std::to_string(getSDCardCapacity()) + + "\",sdcard_partition_size=\"" + std::to_string(getSDCardPartitionSize()) + "\"} 1\n"; } @@ -42,11 +37,9 @@ std::string createHardwareInfoMetric(const std::string &metricNamePrefix) **/ std::string createNetworkInfoMetric(const std::string &metricNamePrefix) { - return "# TYPE " + metricNamePrefix + "network_info gauge\n" + - "# HELP " + metricNamePrefix + "network_info Network info\n" + - metricNamePrefix + "network_info{hostname=\"" + getHostname() + - "\",ipv4_address=\"" + getIpAddress() + - "\",mac_address=\"" + getMac() + "\"} 1\n"; + return "# TYPE " + metricNamePrefix + "network_info gauge\n" + "# HELP " + metricNamePrefix + "network_info Network info\n" + + metricNamePrefix + "network_info{hostname=\"" + getHostname() + "\",ipv4_address=\"" + getIpAddress() + "\",mac_address=\"" + + getMac() + "\"} 1\n"; } @@ -55,8 +48,7 @@ std::string createNetworkInfoMetric(const std::string &metricNamePrefix) **/ std::string createFirmwareInfoMetric(const std::string &metricNamePrefix) { - return "# TYPE " + metricNamePrefix + "firmware_info gauge\n" + - "# HELP " + metricNamePrefix + "firmware_info Firmware info\n" + + return "# TYPE " + metricNamePrefix + "firmware_info gauge\n" + "# HELP " + metricNamePrefix + "firmware_info Firmware info\n" + metricNamePrefix + "firmware_info{firmware_version=\"" + getFwVersion() + "\"} 1\n"; } @@ -66,16 +58,16 @@ std::string createFirmwareInfoMetric(const std::string &metricNamePrefix) **/ std::string createHeapDataMetric(const std::string &metricNamePrefix) { - return "# TYPE " + metricNamePrefix + "heap_data_bytes gauge\n" + - "# UNIT " + metricNamePrefix + "heap_data_bytes bytes\n" + - "# HELP " + metricNamePrefix + "heap_data_bytes Heap data\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_total_free\"} " + std::to_string(getESPHeapSizeTotalFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_internal_free\"} " + std::to_string(getESPHeapSizeInternalFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_internal_largest_free\"} " + std::to_string(getESPHeapSizeInternalLargestFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_internal_min_free\"} " + std::to_string(getESPHeapSizeInternalMinFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_spiram_free\"} " + std::to_string(getESPHeapSizeSPIRAMFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_spiram_largest_free\"} " + std::to_string(getESPHeapSizeSPIRAMLargestFree()) + "\n" + - metricNamePrefix + "heap_data_bytes{heap_data=\"heap_spiram_min_free\"} " + std::to_string(getESPHeapSizeSPIRAMMinFree()) + "\n"; + return "# TYPE " + metricNamePrefix + "heap_data_bytes gauge\n" + "# UNIT " + metricNamePrefix + "heap_data_bytes bytes\n" + "# HELP " + + metricNamePrefix + "heap_data_bytes Heap data\n" + metricNamePrefix + "heap_data_bytes{heap_data=\"heap_total_free\"} " + + std::to_string(getESPHeapSizeTotalFree()) + "\n" + metricNamePrefix + "heap_data_bytes{heap_data=\"heap_internal_free\"} " + + std::to_string(getESPHeapSizeInternalFree()) + "\n" + metricNamePrefix + + "heap_data_bytes{heap_data=\"heap_internal_largest_free\"} " + std::to_string(getESPHeapSizeInternalLargestFree()) + "\n" + + metricNamePrefix + "heap_data_bytes{heap_data=\"heap_internal_min_free\"} " + std::to_string(getESPHeapSizeInternalMinFree()) + + "\n" + metricNamePrefix + "heap_data_bytes{heap_data=\"heap_spiram_free\"} " + std::to_string(getESPHeapSizeSPIRAMFree()) + + "\n" + metricNamePrefix + "heap_data_bytes{heap_data=\"heap_spiram_largest_free\"} " + + std::to_string(getESPHeapSizeSPIRAMLargestFree()) + "\n" + metricNamePrefix + + "heap_data_bytes{heap_data=\"heap_spiram_min_free\"} " + std::to_string(getESPHeapSizeSPIRAMMinFree()) + "\n"; } @@ -85,34 +77,27 @@ std::string createHeapDataMetric(const std::string &metricNamePrefix) std::string createMetric(const std::string &metricName, const std::string &type, const std::string &help, const std::string &value) { if (type == "counter") { - return "# TYPE " + metricName + " " + type + "\n" + - "# HELP " + metricName + " " + help + "\n" + - metricName + "_total " + value + "\n"; + return "# TYPE " + metricName + " " + type + "\n" + "# HELP " + metricName + " " + help + "\n" + metricName + "_total " + value + + "\n"; } - return "# TYPE " + metricName + " " + type + "\n" + - "# HELP " + metricName + " " + help + "\n" + - metricName + " " + value + "\n"; + return "# TYPE " + metricName + " " + type + "\n" + "# HELP " + metricName + " " + help + "\n" + metricName + " " + value + "\n"; } /** * Create a generic single metric with unit **/ -std::string createMetricWithUnit(const std::string &metricName, const std::string &type, const std::string &unit, - const std::string &help, const std::string &value) +std::string createMetricWithUnit(const std::string &metricName, const std::string &type, const std::string &unit, const std::string &help, + const std::string &value) { if (type == "counter") { - return "# TYPE " + metricName + "_" + unit + " " + type + "\n" + - "# UNIT " + metricName + "_" + unit + " " + unit + "\n" + - "# HELP " + metricName + "_" + unit + " " + help + "\n" + - metricName + "_" + unit + "_total " + value + "\n"; + return "# TYPE " + metricName + "_" + unit + " " + type + "\n" + "# UNIT " + metricName + "_" + unit + " " + unit + "\n" + + "# HELP " + metricName + "_" + unit + " " + help + "\n" + metricName + "_" + unit + "_total " + value + "\n"; } - return "# TYPE " + metricName + "_" + unit + " " + type + "\n" + - "# UNIT " + metricName + "_" + unit + " " + unit + "\n" + - "# HELP " + metricName + "_" + unit + " " + help + "\n" + - metricName + "_" + unit + " " + value + "\n"; + return "# TYPE " + metricName + "_" + unit + " " + type + "\n" + "# UNIT " + metricName + "_" + unit + " " + unit + "\n" + "# HELP " + + metricName + "_" + unit + " " + help + "\n" + metricName + "_" + unit + " " + value + "\n"; } @@ -127,33 +112,37 @@ std::string createSequenceMetrics(const std::string &metricNamePrefix, const std for (const auto &sequence : sequenceData) { std::string sequenceName = sequence->sequenceName; - // except newline, double quote, and backslash (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#abnf) - // to keep it simple, these characters are just removed from the label + // except newline, double quote, and backslash + // (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#abnf) to keep it simple, these + // characters are just removed from the label replaceAll(sequenceName, "\\", ""); replaceAll(sequenceName, "\"", ""); replaceAll(sequenceName, "\n", ""); - if (!sequence->sActualValue.empty()) + if (!sequence->sActualValue.empty()) { response += metricNamePrefix + "actual_value{sequence=\"" + sequenceName + "\"} " + sequence->sActualValue + "\n"; + } } // Return if no valid value is available - if (response.empty()) + if (response.empty()) { return response; + } // Add metadata to value data if values are avialbale - response = "# TYPE " + metricNamePrefix + "actual_value gauge\n" + - "# HELP " + metricNamePrefix + "actual_value Actual value of meter\n" + response; + response = "# TYPE " + metricNamePrefix + "actual_value gauge\n" + "# HELP " + metricNamePrefix + + "actual_value Actual value of meter\n" + response; // Add rate per minute - response += "# TYPE " + metricNamePrefix + "rate_per_minute gauge\n" + - "# HELP " + metricNamePrefix + "rate_per_minute Rate per minute of meter\n"; + response += "# TYPE " + metricNamePrefix + "rate_per_minute gauge\n" + "# HELP " + metricNamePrefix + + "rate_per_minute Rate per minute of meter\n"; for (const auto &sequence : sequenceData) { std::string sequenceName = sequence->sequenceName; - // except newline, double quote, and backslash (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#abnf) - // to keep it simple, these characters are just removed from the label + // except newline, double quote, and backslash + // (https://github.com/OpenObservability/OpenMetrics/blob/main/specification/OpenMetrics.md#abnf) to keep it simple, these + // characters are just removed from the label replaceAll(sequenceName, "\\", ""); replaceAll(sequenceName, "\"", ""); replaceAll(sequenceName, "\n", ""); @@ -179,7 +168,7 @@ std::string createSequenceMetrics(const std::string &metricNamePrefix, const std * static_configs: * - targets: ['192.168.1.4'] * -*/ + */ esp_err_t handler_openmetrics(httpd_req_t *req) { if (getTaskAutoFlowState() <= FLOW_TASK_STATE_INIT) { @@ -204,39 +193,39 @@ esp_err_t handler_openmetrics(httpd_req_t *req) response += createFirmwareInfoMetric(metricNamePrefix); // Device uptime - response += createMetricWithUnit(metricNamePrefix + "device_uptime", "gauge", "seconds", - "Device uptime in seconds", std::to_string((long)getUptime())); + response += createMetricWithUnit(metricNamePrefix + "device_uptime", "gauge", "seconds", "Device uptime in seconds", + std::to_string((long)getUptime())); // WLAN signal strength - response += createMetricWithUnit(metricNamePrefix + "wlan_rssi", "gauge", "dBm", - "WLAN signal strength in dBm", std::to_string(getWifiRssi())); + response += createMetricWithUnit(metricNamePrefix + "wlan_rssi", "gauge", "dBm", "WLAN signal strength in dBm", + std::to_string(getWifiRssi())); // CPU temperature - response += createMetricWithUnit(metricNamePrefix + "chip_temp", "gauge", "celsius", - "CPU temperature in celsius", std::to_string((int)getSOCTemperature())); + response += createMetricWithUnit(metricNamePrefix + "chip_temp", "gauge", "celsius", "CPU temperature in celsius", + std::to_string((int)getSOCTemperature())); // Heap data response += createHeapDataMetric(metricNamePrefix); // SD card partition free space - response += createMetricWithUnit(metricNamePrefix + "sd_partition_free", "gauge", "megabytes", - "Free SD partition space in megabytes", std::to_string(getSDCardFreePartitionSpace())); + response += createMetricWithUnit(metricNamePrefix + "sd_partition_free", "gauge", "megabytes", "Free SD partition space in megabytes", + std::to_string(getSDCardFreePartitionSpace())); // Process error state - response += createMetric(metricNamePrefix + "process_error", "gauge", - "Process error state", std::to_string(flowctrl.getFlowStateErrorOrDeviation())); + response += createMetric(metricNamePrefix + "process_error", "gauge", "Process error state", + std::to_string(flowctrl.getFlowStateErrorOrDeviation())); // Processing interval - response += createMetricWithUnit(metricNamePrefix + "process_interval", "gauge", "minutes", - "Processing interval", to_stringWithPrecision(flowctrl.getProcessInterval(), 1)); + response += createMetricWithUnit(metricNamePrefix + "process_interval", "gauge", "minutes", "Processing interval", + to_stringWithPrecision(flowctrl.getProcessInterval(), 1)); // Processing time - response += createMetricWithUnit(metricNamePrefix + "process_time", "gauge", "seconds", - "Processing time of one cycle", std::to_string(getFlowProcessingTime())); + response += createMetricWithUnit(metricNamePrefix + "process_time", "gauge", "seconds", "Processing time of one cycle", + std::to_string(getFlowProcessingTime())); // Process cycles - response += createMetric(metricNamePrefix + "cycle_counter", "counter", - "Process cycles since device startup", std::to_string(getFlowCycleCounter())); + response += createMetric(metricNamePrefix + "cycle_counter", "counter", "Process cycles since device startup", + std::to_string(getFlowCycleCounter())); // Actual measurement values response += createSequenceMetrics(metricNamePrefix, flowctrl.getSequenceData()); @@ -252,11 +241,11 @@ void registerOpenmetricsUri(httpd_handle_t server) { ESP_LOGI(TAG, "Registering URI handlers"); - httpd_uri_t camuri = { }; + httpd_uri_t camuri = {}; camuri.method = HTTP_GET; camuri.uri = "/metrics"; camuri.handler = handler_openmetrics; - camuri.user_ctx = NULL; + camuri.user_ctx = NULL; httpd_register_uri_handler(server, &camuri); } diff --git a/code/components/tflite_ctrl/CTfLiteClass.cpp b/code/components/tflite_ctrl/CTfLiteClass.cpp index 59a819e9b..b33c55637 100644 --- a/code/components/tflite_ctrl/CTfLiteClass.cpp +++ b/code/components/tflite_ctrl/CTfLiteClass.cpp @@ -13,7 +13,7 @@ static const char *TAG = "TFLITE"; float CTfLiteClass::GetOutputValue(int nr) { - TfLiteTensor* output2 = interpreter->output(0); + TfLiteTensor *output2 = interpreter->output(0); if (output2 == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "GetOutputValue failed"); @@ -21,17 +21,20 @@ float CTfLiteClass::GetOutputValue(int nr) } int numeroutput = output2->dims->data[1]; - if ((nr+1) > numeroutput) + if ((nr + 1) > numeroutput) { return -1000; - else + } + else { return output2->data.f[nr]; + } } int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs) { - if (!LoadInputImageBasis(rs)) + if (!LoadInputImageBasis(rs)) { return -1000; + } Invoke(); @@ -41,7 +44,7 @@ int CTfLiteClass::GetClassFromImageBasis(CImageBasis *rs) int CTfLiteClass::GetOutClassification(int _von, int _bis) { - TfLiteTensor* output2 = interpreter->output(0); + TfLiteTensor *output2 = interpreter->output(0); if (output2 == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "GetOutClassification failed"); @@ -53,27 +56,26 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis) int zw_class; int numeroutput = output2->dims->data[1]; - //ESP_LOGD(TAG, "number output neurons: %d", numeroutput); + // ESP_LOGD(TAG, "number output neurons: %d", numeroutput); - if (_bis == -1) - _bis = numeroutput -1; + if (_bis == -1) { + _bis = numeroutput - 1; + } - if (_von == -1) + if (_von == -1) { _von = 0; + } - if (_bis >= numeroutput) - { + if (_bis >= numeroutput) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "GetOutClassification: NUMBER OF OUTPUT NEURONS does not match required classification"); return -1; } zw_max = output2->data.f[_von]; zw_class = _von; - for (int i = _von + 1; i <= _bis; ++i) - { + for (int i = _von + 1; i <= _bis; ++i) { zw = output2->data.f[i]; - if (zw > zw_max) - { + if (zw > zw_max) { zw_max = zw; zw_class = i; } @@ -84,7 +86,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis) bool CTfLiteClass::GetInputDimension(bool silent = false) { - TfLiteTensor* input2 = interpreter->input(0); + TfLiteTensor *input2 = interpreter->input(0); if (input2 == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "GetInputDimension failed"); @@ -92,16 +94,25 @@ bool CTfLiteClass::GetInputDimension(bool silent = false) } int numdim = input2->dims->size; - if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim); + if (!silent) { + ESP_LOGD(TAG, "NumDimension: %d", numdim); + } int sizeofdim; - for (int j = 0; j < numdim; ++j) - { - sizeofdim = input2->dims->data[j]; - if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim); - if (j == 1) im_height = sizeofdim; - if (j == 2) im_width = sizeofdim; - if (j == 3) im_channel = sizeofdim; + for (int j = 0; j < numdim; ++j) { + sizeofdim = input2->dims->data[j]; + if (!silent) { + ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim); + } + if (j == 1) { + im_height = sizeofdim; + } + if (j == 2) { + im_width = sizeofdim; + } + if (j == 3) { + im_channel = sizeofdim; + } } return true; @@ -110,12 +121,15 @@ bool CTfLiteClass::GetInputDimension(bool silent = false) int CTfLiteClass::ReadInputDimenstion(int _dim) { - if (_dim == 0) + if (_dim == 0) { return im_width; - if (_dim == 1) + } + if (_dim == 1) { return im_height; - if (_dim == 2) + } + if (_dim == 2) { return im_channel; + } return -1; } @@ -123,7 +137,7 @@ int CTfLiteClass::ReadInputDimenstion(int _dim) int CTfLiteClass::GetAnzOutPut(bool silent) { - TfLiteTensor* output2 = interpreter->output(0); + TfLiteTensor *output2 = interpreter->output(0); if (output2 == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "GetAnzOutPut failed"); @@ -131,22 +145,26 @@ int CTfLiteClass::GetAnzOutPut(bool silent) } int numdim = output2->dims->size; - if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim); + if (!silent) { + ESP_LOGD(TAG, "NumDimension: %d", numdim); + } int sizeofdim; - for (int j = 0; j < numdim; ++j) - { + for (int j = 0; j < numdim; ++j) { sizeofdim = output2->dims->data[j]; - if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim); + if (!silent) { + ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim); + } } float fo; // Process the inference results. int numeroutput = output2->dims->data[1]; - for (int i = 0; i < numeroutput; ++i) - { + for (int i = 0; i < numeroutput; ++i) { fo = output2->data.f[i]; - if (!silent) ESP_LOGD(TAG, "Result %d: %f", i, fo); + if (!silent) { + ESP_LOGD(TAG, "Result %d: %f", i, fo); + } } return numeroutput; } @@ -154,16 +172,17 @@ int CTfLiteClass::GetAnzOutPut(bool silent) void CTfLiteClass::Invoke() { - if (interpreter != nullptr) - interpreter->Invoke(); + if (interpreter != nullptr) { + interpreter->Invoke(); + } } bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs) { - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("LoadInputImageBasis - Start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("LoadInputImageBasis - Start"); +#endif // DEBUG_DETAIL_ON if (rs == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadInputImageBasis: No image data"); @@ -173,33 +192,33 @@ bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs) unsigned int w = rs->width; unsigned int h = rs->height; unsigned char red, green, blue; -// ESP_LOGD(TAG, "Image: %s size: %d x %d\n", _fn.c_str(), w, h); + // ESP_LOGD(TAG, "Image: %s size: %d x %d\n", _fn.c_str(), w, h); input_i = 0; - float* input_data_ptr = (interpreter->input(0))->data.f; + float *input_data_ptr = (interpreter->input(0))->data.f; if (input_data_ptr == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadInputImageBasis: No input data"); return false; } - for (int y = 0; y < h; ++y) - for (int x = 0; x < w; ++x) - { - 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++; - } - - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("LoadInputImageBasis - done"); - #endif + for (int y = 0; y < h; ++y) { + for (int x = 0; x < w; ++x) { + 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++; + } + } + +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("LoadInputImageBasis - done"); +#endif // DEBUG_DETAIL_ON return true; } @@ -225,7 +244,7 @@ void CTfLiteClass::LoadOpResolver(void) bool CTfLiteClass::MakeAllocate() { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Allocating tensors"); - tensor_arena = (uint8_t*)malloc_psram_heap(std::string(TAG) + "->tensor_arena", kTensorArenaSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + tensor_arena = (uint8_t *)malloc_psram_heap(std::string(TAG) + "->tensor_arena", kTensorArenaSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (tensor_arena == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "Tensor arena: malloc failed"); @@ -258,7 +277,7 @@ void CTfLiteClass::GetInputTensorSize() float *zw = input; int test = sizeof(zw); ESP_LOGD(TAG, "Input Tensor Dimension: %d", test); -#endif +#endif // DEBUG_DETAIL_ON } @@ -266,9 +285,9 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn) { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Read TFLITE model file: " + _fn); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ReadFileToModel: start"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ReadFileToModel: start"); +#endif // DEBUG_DETAIL_ON size_t size = getFileSize(_fn); if (size <= 0) { @@ -276,15 +295,15 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn) return false; } - modelfile = (unsigned char*)malloc_psram_heap(std::string(TAG) + "->modelfile", size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + modelfile = (unsigned char *)malloc_psram_heap(std::string(TAG) + "->modelfile", size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if(modelfile == NULL) { + if (modelfile == NULL) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "ReadFileToModel: Can't allocate enough memory: " + std::to_string(size)); LogFile.writeHeapInfo("ReadFileToModel: Allocation failed"); return false; } - FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r + FILE *f = fopen(_fn.c_str(), "rb"); // previously only "r /* Related to article: https://blog.drorgluska.com/2022/06/esp32-sd-card-optimization.html */ // Set buffer to SD card allocation size of 512 byte (newlib default: 128 byte) -> reduce system read/write calls @@ -298,9 +317,9 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn) } fclose(f); - #ifdef DEBUG_DETAIL_ON - LogFile.writeHeapInfo("ReadFileToModel: done"); - #endif +#ifdef DEBUG_DETAIL_ON + LogFile.writeHeapInfo("ReadFileToModel: done"); +#endif // DEBUG_DETAIL_ON return true; } @@ -311,20 +330,21 @@ bool CTfLiteClass::LoadModel(std::string _fn) LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "Loading TFLITE model"); if (!ReadFileToModel(_fn)) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadModel: TFLITE model file reading failed"); - return false; + LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadModel: TFLITE model file reading failed"); + return false; } model = tflite::GetModel(modelfile); - if(model == nullptr) { + if (model == nullptr) { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadModel: GetModel failed"); return false; } if (model->version() != TFLITE_SCHEMA_VERSION) { - LogFile.writeToFile(ESP_LOG_ERROR, TAG, "LoadModel: Model provided is schema version " + std::to_string(model->version()) + - " not equal to supported version " + std::to_string(TFLITE_SCHEMA_VERSION)); + LogFile.writeToFile(ESP_LOG_ERROR, TAG, + "LoadModel: Model provided is schema version " + std::to_string(model->version()) + + " not equal to supported version " + std::to_string(TFLITE_SCHEMA_VERSION)); return false; } diff --git a/code/components/tflite_ctrl/CTfLiteClass.h b/code/components/tflite_ctrl/CTfLiteClass.h index 48d441583..e28a29012 100644 --- a/code/components/tflite_ctrl/CTfLiteClass.h +++ b/code/components/tflite_ctrl/CTfLiteClass.h @@ -9,39 +9,39 @@ class CTfLiteClass { - protected: - tflite::MicroMutableOpResolver<10> microOpResolver; - const tflite::Model* model; - tflite::MicroInterpreter* interpreter; - TfLiteTensor* output = nullptr; - int kTensorArenaSize; - uint8_t *tensor_arena; - unsigned char *modelfile = NULL; - - float* input; - int input_i; - int im_height, im_width, im_channel; - - bool ReadFileToModel(std::string _fn); - void LoadOpResolver(void); - - public: - CTfLiteClass(); - ~CTfLiteClass(); - void CTfLiteClassDeleteInterpreter(); - bool LoadModel(std::string _fn); - bool MakeAllocate(); - void GetInputTensorSize(); - bool LoadInputImageBasis(CImageBasis *rs); - void Invoke(); - int GetAnzOutPut(bool silent = true); - int GetOutClassification(int _von = -1, int _bis = -1); - - int GetClassFromImageBasis(CImageBasis *rs); - - float GetOutputValue(int nr); - bool GetInputDimension(bool silent); - int ReadInputDimenstion(int _dim); + protected: + tflite::MicroMutableOpResolver<10> microOpResolver; + const tflite::Model *model; + tflite::MicroInterpreter *interpreter; + TfLiteTensor *output = nullptr; + int kTensorArenaSize; + uint8_t *tensor_arena; + unsigned char *modelfile = NULL; + + float *input; + int input_i; + int im_height, im_width, im_channel; + + bool ReadFileToModel(std::string _fn); + void LoadOpResolver(void); + + public: + CTfLiteClass(); + ~CTfLiteClass(); + void CTfLiteClassDeleteInterpreter(); + bool LoadModel(std::string _fn); + bool MakeAllocate(); + void GetInputTensorSize(); + bool LoadInputImageBasis(CImageBasis *rs); + void Invoke(); + int GetAnzOutPut(bool silent = true); + int GetOutClassification(int _von = -1, int _bis = -1); + + int GetClassFromImageBasis(CImageBasis *rs); + + float GetOutputValue(int nr); + bool GetInputDimension(bool silent); + int ReadInputDimenstion(int _dim); }; -#endif //CTFLITECLASS_H \ No newline at end of file +#endif // CTFLITECLASS_H diff --git a/code/components/time_sntp/time_sntp.cpp b/code/components/time_sntp/time_sntp.cpp index 0fa62ecdc..d619529dd 100644 --- a/code/components/time_sntp/time_sntp.cpp +++ b/code/components/time_sntp/time_sntp.cpp @@ -20,7 +20,7 @@ static bool timeWasNotSetAtBoot_PrintStartBlock = false; static bool isTimeSynchonized = false; -std::string convertTimeToString(time_t _time, const char * frm) +std::string convertTimeToString(time_t _time, const char *frm) { struct tm timeinfo; char strftime_buf[64]; @@ -31,7 +31,7 @@ std::string convertTimeToString(time_t _time, const char * frm) } -std::string getCurrentTimeString(const char * frm) +std::string getCurrentTimeString(const char *frm) { time_t now; @@ -76,10 +76,12 @@ bool getTimeIsSynced(void) std::string getNTPSyncStatus(void) { if (timeSyncEnabled) { - if (isTimeSynchonized) + if (isTimeSynchonized) { return "Synchronized"; - else + } + else { return "Not Synchronized"; + } } return "Disabled"; @@ -96,7 +98,7 @@ std::string getServerName(void) { char buf[128]; - if (esp_sntp_getservername(0)){ + if (esp_sntp_getservername(0)) { snprintf(buf, sizeof(buf), "%s", esp_sntp_getservername(0)); return std::string(buf); } @@ -127,8 +129,8 @@ void timeSyncNotificationCallback(struct timeval *tv) LogFile.writeToFile(ESP_LOG_INFO, TAG, "= Before sync: log_1970-01-01.txt ="); timeWasNotSetAtBoot_PrintStartBlock = false; } - LogFile.writeToFile(ESP_LOG_INFO, TAG, "Time is synced with NTP server " + - getServerName() + ": " + getCurrentTimeString("%Y-%m-%d %H:%M:%S")); + LogFile.writeToFile(ESP_LOG_INFO, TAG, + "Time is synced with NTP server " + getServerName() + ": " + getCurrentTimeString("%Y-%m-%d %H:%M:%S")); isTimeSynchonized = true; } @@ -150,7 +152,7 @@ bool initTime() // Configure time server timeServer = ConfigClass::getInstance()->get()->sectionNetwork.time.ntp.timeServer; - if (timeServer.empty()) { // parameter part is empty + if (timeServer.empty()) { // parameter part is empty timeServer = "pool.ntp.org"; // Use Default } @@ -190,8 +192,9 @@ bool initTime() */ void reconfigureTimeZone(std::string _timeZone) { - if (timeZone == _timeZone) + if (timeZone == _timeZone) { return; + } LogFile.writeToFile(ESP_LOG_WARN, TAG, "Time zone has been modified"); @@ -211,7 +214,7 @@ void reconfigureTimeZone(std::string _timeZone) */ void reconfigureTime(bool _timeSyncEnabled, std::string _timeServer, std::string _timeZone) { - if (_timeServer.empty()) { // parameter is empty + if (_timeServer.empty()) { // parameter is empty _timeServer = "pool.ntp.org"; // Use Default } @@ -220,8 +223,9 @@ void reconfigureTime(bool _timeSyncEnabled, std::string _timeServer, std::string LogFile.writeToFile(ESP_LOG_INFO, TAG, "No time zone set, using default: " + timeZone); } - if (timeSyncEnabled == _timeSyncEnabled && timeServer == _timeServer && timeZone == _timeZone) + if (timeSyncEnabled == _timeSyncEnabled && timeServer == _timeServer && timeZone == _timeZone) { return; + } LogFile.writeToFile(ESP_LOG_WARN, TAG, "Time configuration has been modified"); diff --git a/code/components/time_sntp/time_sntp.h b/code/components/time_sntp/time_sntp.h index 0554650de..6ed56da8c 100644 --- a/code/components/time_sntp/time_sntp.h +++ b/code/components/time_sntp/time_sntp.h @@ -5,8 +5,8 @@ #include -std::string getCurrentTimeString(const char * frm); -std::string convertTimeToString(time_t _time, const char * frm); +std::string getCurrentTimeString(const char *frm); +std::string convertTimeToString(time_t _time, const char *frm); bool getTimeIsSet(void); bool getUseNtp(void); @@ -17,4 +17,4 @@ bool getTimeWasNotSetAtBoot(void); bool initTime(); void reconfigureTime(bool _timeSyncEnabled, std::string _timeServer, std::string _timeZone); -#endif //TIMESNTP_H \ No newline at end of file +#endif // TIMESNTP_H diff --git a/code/components/webhook_ctrl/interface_webhook.cpp b/code/components/webhook_ctrl/interface_webhook.cpp index 4431dbd3d..153bc85a3 100644 --- a/code/components/webhook_ctrl/interface_webhook.cpp +++ b/code/components/webhook_ctrl/interface_webhook.cpp @@ -3,7 +3,7 @@ #ifdef ENABLE_WEBHOOK #include -//#include +// #include #include #include @@ -23,20 +23,21 @@ static std::string TLSClientKey; static esp_err_t http_event_handler(esp_http_client_event_t *evt) { - switch(evt->event_id) { + switch (evt->event_id) { case HTTP_EVENT_ERROR: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Error event"); break; case HTTP_EVENT_ON_CONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Connected"); - //ESP_LOGI(TAG, "HTTP Client Connected"); + // ESP_LOGI(TAG, "HTTP Client Connected"); break; case HTTP_EVENT_HEADERS_SENT: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Headers sent"); break; case HTTP_EVENT_ON_HEADER: - LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received header: key: " + std::string(evt->header_key) + - " | value: " + std::string(evt->header_value)); + LogFile.writeToFile(ESP_LOG_DEBUG, TAG, + "HTTP client: Received header: key: " + std::string(evt->header_key) + + " | value: " + std::string(evt->header_value)); break; case HTTP_EVENT_ON_DATA: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Received data: length:" + std::to_string(evt->data_len)); @@ -44,7 +45,7 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt) case HTTP_EVENT_ON_FINISH: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Session finished"); break; - case HTTP_EVENT_DISCONNECTED: + case HTTP_EVENT_DISCONNECTED: LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "HTTP client: Disconnected"); break; case HTTP_EVENT_REDIRECT: @@ -60,7 +61,7 @@ bool webhookInit(const CfgData::SectionWebhook *_cfgDataPtr) cfgDataPtr = _cfgDataPtr; if (cfgDataPtr->authMode == AUTH_TLS) { - if (cfgDataPtr->uri.substr(0,8) != "https://") { + if (cfgDataPtr->uri.substr(0, 8) != "https://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "TLS: URI parameter needs to be configured with \'https://\'"); return false; } @@ -96,7 +97,7 @@ bool webhookInit(const CfgData::SectionWebhook *_cfgDataPtr) } } else { - if (cfgDataPtr->uri.substr(0,7) != "http://") { + if (cfgDataPtr->uri.substr(0, 7) != "http://") { LogFile.writeToFile(ESP_LOG_ERROR, TAG, "URI parameter needs to be configured with \'http://\'"); return false; } @@ -106,14 +107,14 @@ bool webhookInit(const CfgData::SectionWebhook *_cfgDataPtr) } -esp_err_t webhookPublish(const char* _jsonData, ImageData *_imgData, time_t _imageTimeProcessed) +esp_err_t webhookPublish(const char *_jsonData, ImageData *_imgData, time_t _imageTimeProcessed) { esp_http_client_config_t httpConfig = { .url = cfgDataPtr->uri.c_str(), .user_agent = "AI-on-the-Edge Device", .method = HTTP_METHOD_POST, .event_handler = http_event_handler, - .buffer_size = MAX_HTTP_OUTPUT_BUFFER + .buffer_size = MAX_HTTP_OUTPUT_BUFFER // Receive buffer }; if (cfgDataPtr->authMode == AUTH_BASIC) { @@ -130,7 +131,7 @@ esp_err_t webhookPublish(const char* _jsonData, ImageData *_imgData, time_t _ima if (!TLSCACert.empty()) { httpConfig.cert_pem = TLSCACert.c_str(); httpConfig.cert_len = TLSCACert.length() + 1; - httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field + httpConfig.skip_cert_common_name_check = true; // Skip any validation of server certificate CN field } else { LogFile.writeToFile(ESP_LOG_DEBUG, TAG, "CA Certificate empty, use certification bundle for server verification"); @@ -208,10 +209,11 @@ esp_err_t webhookPublish(const char* _jsonData, ImageData *_imgData, time_t _ima bool getWebhookIsEncrypted() { - if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) + if (cfgDataPtr != NULL && cfgDataPtr->authMode == AUTH_TLS) { return true; + } return false; } -#endif //ENABLE_WEBHOOK +#endif // ENABLE_WEBHOOK diff --git a/code/components/webhook_ctrl/interface_webhook.h b/code/components/webhook_ctrl/interface_webhook.h index 13dee798d..e79a0819b 100644 --- a/code/components/webhook_ctrl/interface_webhook.h +++ b/code/components/webhook_ctrl/interface_webhook.h @@ -10,8 +10,8 @@ #include "CImageBasis.h" bool webhookInit(const CfgData::SectionWebhook *_cfgDataPtr); -esp_err_t webhookPublish(const char* _data, ImageData *_imgData = NULL, time_t _imageTimeProcessed = 0L); +esp_err_t webhookPublish(const char *_data, ImageData *_imgData = NULL, time_t _imageTimeProcessed = 0L); bool getWebhookIsEncrypted(); -#endif //INTERFACE_WEBHOOK_H -#endif //ENABLE_WEBHOOK \ No newline at end of file +#endif // INTERFACE_WEBHOOK_H +#endif // ENABLE_WEBHOOK diff --git a/code/components/webserver_softap/softAP.cpp b/code/components/webserver_softap/softAP.cpp index 840ab2d46..49563243a 100644 --- a/code/components/webserver_softap/softAP.cpp +++ b/code/components/webserver_softap/softAP.cpp @@ -34,14 +34,17 @@ esp_err_t main_handler_AP(httpd_req_t *req) if (!credentialsSet) { message = "

1. Configure WLAN network and set credentials

"; message += ""; - message += ""; + message += ""; message += ""; - message += ""; + message += ""; message += ""; message += "
Network Name (SSID)
Network Name (SSID)Enter the name of WLAN network
Network Password
Network PasswordEnter the WLAN network password (NOTE: The password is transmitted to the device as plain text!)


"; message += ""; message += ""; httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str())); credentialsSet = true; @@ -52,7 +55,8 @@ esp_err_t main_handler_AP(httpd_req_t *req) message = "

2. Upload firmware package

"; message += "Upload a firmware package \"AI-on-the-edge-device__{Board Type}__*.zip\" to install the SD card content.

"; message += "

"; - message += "

"; + message += "

"; message += "The upload might take up to 60s. After the package has been successfully uploaded, the page is automatically reloaded."; message += ""; @@ -73,8 +78,10 @@ esp_err_t main_handler_AP(httpd_req_t *req) message += "The device is going to reboot and install the provided package. This process can take up to 3 minutes.
"; message += "The installation process can be controlled using serial console connection (e.g. via web installer web interface).
"; message += "If device is provisioned using web installer, just wait until installation is completed and refresh browser window.
"; - message += "Switch WLAN network and access the device using device name (default: watermeter) or IP address (check router logs).

"; - message += ""; + message += + "Switch WLAN network and access the device using device name (default: watermeter) or IP address (check router logs).

"; + message += ""; message += "