mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-06 03:26:53 +03:00
Release Preparations (#1925)
* Fix for securing wlan.ini (#1509) * Fix for securing wlan.ini * Fixing error with ' instead of " * Changing to errorcode 403 * maybe strcmp instead of regular == Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> * Update Web-Installer * solves #1530 (#1531) * Refactor JSON (#1518) * use correct log level * corrected logging * typo * refactored JSON generagion: removed unused parameters, consolidated into singel function, added "pre" * Wrapped 'rate' into double quotes, like all other JSON values Co-authored-by: CaCO3 <caco@ruinelli.ch> * Various corrections (#1519) * use correct log level * corrected logging * typo * add release to webinstaller * changed logs, added INFO log of raw, value, error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Prevent auto restart on cam framebuffer init error (#1522) * use correct log level * revert autorestart on camera framebuffer init error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * #1524 - ensure the recognized digit is less than 10 (#1525) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 Co-authored-by: github-actions <github-actions@github.com> * fix frozen time in datafile on error (#1534) Co-authored-by: CaCO3 <caco@ruinelli.ch> * log NTP server name (#1497) * log NTP server name * . * . * replace calls to /wasserzaehler.html with calls to /value (#1469) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Fix cookie usage, use correct http response codes, add 404 page (#1495) * replaced some HTTP response code with better matching codes * add custom 404 page, add log entry for debugging * fix cookie * replace non-necessary whitespace * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Don't autofail if NTP server can't be reached during initalization (#1498) This fixes an issue with a restricted network without internet access, where the hardcoded ntp server can't be reached and thus the esp resets, as it's not able to finish initalization. * Update Changelog.md * Update Changelog.md for release * Fix for securing wlan.ini (#1509) * Fix for securing wlan.ini * Fixing error with ' instead of " * Changing to errorcode 403 * maybe strcmp instead of regular == Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> * Update Web-Installer * solves #1530 (#1531) * Refactor JSON (#1518) * use correct log level * corrected logging * typo * refactored JSON generagion: removed unused parameters, consolidated into singel function, added "pre" * Wrapped 'rate' into double quotes, like all other JSON values Co-authored-by: CaCO3 <caco@ruinelli.ch> * Various corrections (#1519) * use correct log level * corrected logging * typo * add release to webinstaller * changed logs, added INFO log of raw, value, error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Prevent auto restart on cam framebuffer init error (#1522) * use correct log level * revert autorestart on camera framebuffer init error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * #1524 - ensure the recognized digit is less than 10 (#1525) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 Co-authored-by: github-actions <github-actions@github.com> * only use sntp_getservername() after init sntp * set default NTP server on dnew installations Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: Ralf Rachinger <git@ralfrachinger.de> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: parhedberg <par.hedberg@gmail.com> Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: Frank Haverland <fspapaping@googlemail.com> * Renamed variables and added debug log (#1537) * add debug logs * renamed variables * renamed TAGs, added flow status logging * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * replaced printf usage in LogFile.WriteToFile() * ENABLE_MQTT c++ macro definition (#1546) * macro * 2 * 2 * delete jomjol_mqtt from CMakeLists * mqtt macro * final * ENABLE_INFLUXDB c++ macro definition (#1547) * macro * 2 * 2 * delete jomjol_mqtt from CMakeLists * mqtt macro * final * ENABLE_INFLUXDB c++ macro definition * Update Changelog.md * Update Changelog.md * Rearange task to CPU (http, camera, mqtt) (#1557) * Streamlined MQTT interlock when not activated & interlock MQTT when WIFI is not connected (#1556) * streamlined mqtt interlock when disabled * Disconnect mqtt client before reboot * Interlock MQTT with WIFI * Update * loglevel to DEBUG * Update * mqtt msg id incremental * new ENABLE_MQTT includes * Loglevel to DEBUG * Loglevel * Update interface_mqtt.cpp * show uptime on overview page, moved labels from firmware to Web UI (#1543) * show uptime on overview page, moved labels from firmware to Web UI * show uptime on info page * also use formated time in log Co-authored-by: CaCO3 <caco@ruinelli.ch> * Continue boot on bad PSRAM (#1558) * add sensor status, show special index/setup page in case of a critical error * continue booting on PSRAM error * Update main.cpp added log messages * init PSRAM and add more log messages * cleanup of init checks * . * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * add sensor status, show special index/setup page in case of a critical error (#1560) * add sensor status, show special index/setup page in case of a critical error * Added Reboot * . * added more buttons Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> * Update Webinstaller to v13.0.7 * remove html-from-11.3.1 in release (#1565) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 * only initial_esp32_setup and update.zip as artefacts * remove unneeded cache * rename step ota-v2 to ota * rename ota-v2 to ota Co-authored-by: github-actions <github-actions@github.com> * make the sidebar on the overviw page wider and show the round counter (#1570) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Create reply-bot.yml * Update ClassFlowPostProcessing.cpp * Add bot (#1581) * Update reply-bot.yml * Create label-commenter-config.yml * added missing html change * extended instructions (#1583) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Fix Rate Problem * removed redundant "Status:" * Bugfix Double Extract ZIP-Files * Update FeatureRequest.md (#1591) in case of position change between the measurments set this state to true, if there is no change set it back to false. In a defined time window this movement can lead into an alarm state / water leak.. haveing this state in the mqtt broker can trigger functions like closing the ater pipe walve and so on... * Update manifest.json * Delete .gitignore * Delete .gitmodules * Delete firmware.bin * Add files via upload * Block REST API calls till resource is ready (#1609) * Block REST API call till ressource is ready * Update * Update * Update * replace relative include of gethost.js with absolute one. This is needed as that file gets incuded on dynamically generated content which can be on different path levels (#1610) Co-authored-by: CaCO3 <caco@ruinelli.ch> * esp_spiram.h has been replaced by esp32/spiram.h (#1605) * esp_spiram.h has been replaced by esp32/spiram.h * Preparations for next Bugfix Release (#1615) * Merge branch 'rolling' (#1559) * Fix for securing wlan.ini (#1509) * Fix for securing wlan.ini * Fixing error with ' instead of " * Changing to errorcode 403 * maybe strcmp instead of regular == Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> * Update Web-Installer * solves #1530 (#1531) * Refactor JSON (#1518) * use correct log level * corrected logging * typo * refactored JSON generagion: removed unused parameters, consolidated into singel function, added "pre" * Wrapped 'rate' into double quotes, like all other JSON values Co-authored-by: CaCO3 <caco@ruinelli.ch> * Various corrections (#1519) * use correct log level * corrected logging * typo * add release to webinstaller * changed logs, added INFO log of raw, value, error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Prevent auto restart on cam framebuffer init error (#1522) * use correct log level * revert autorestart on camera framebuffer init error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * #1524 - ensure the recognized digit is less than 10 (#1525) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 Co-authored-by: github-actions <github-actions@github.com> * fix frozen time in datafile on error (#1534) Co-authored-by: CaCO3 <caco@ruinelli.ch> * log NTP server name (#1497) * log NTP server name * . * . * replace calls to /wasserzaehler.html with calls to /value (#1469) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Fix cookie usage, use correct http response codes, add 404 page (#1495) * replaced some HTTP response code with better matching codes * add custom 404 page, add log entry for debugging * fix cookie * replace non-necessary whitespace * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Don't autofail if NTP server can't be reached during initalization (#1498) This fixes an issue with a restricted network without internet access, where the hardcoded ntp server can't be reached and thus the esp resets, as it's not able to finish initalization. * Update Changelog.md * Update Changelog.md for release * Fix for securing wlan.ini (#1509) * Fix for securing wlan.ini * Fixing error with ' instead of " * Changing to errorcode 403 * maybe strcmp instead of regular == Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> * Update Web-Installer * solves #1530 (#1531) * Refactor JSON (#1518) * use correct log level * corrected logging * typo * refactored JSON generagion: removed unused parameters, consolidated into singel function, added "pre" * Wrapped 'rate' into double quotes, like all other JSON values Co-authored-by: CaCO3 <caco@ruinelli.ch> * Various corrections (#1519) * use correct log level * corrected logging * typo * add release to webinstaller * changed logs, added INFO log of raw, value, error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Prevent auto restart on cam framebuffer init error (#1522) * use correct log level * revert autorestart on camera framebuffer init error * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * #1524 - ensure the recognized digit is less than 10 (#1525) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 Co-authored-by: github-actions <github-actions@github.com> * only use sntp_getservername() after init sntp * set default NTP server on dnew installations Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: Ralf Rachinger <git@ralfrachinger.de> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: parhedberg <par.hedberg@gmail.com> Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: Frank Haverland <fspapaping@googlemail.com> * Renamed variables and added debug log (#1537) * add debug logs * renamed variables * renamed TAGs, added flow status logging * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * replaced printf usage in LogFile.WriteToFile() * ENABLE_MQTT c++ macro definition (#1546) * macro * 2 * 2 * delete jomjol_mqtt from CMakeLists * mqtt macro * final * ENABLE_INFLUXDB c++ macro definition (#1547) * macro * 2 * 2 * delete jomjol_mqtt from CMakeLists * mqtt macro * final * ENABLE_INFLUXDB c++ macro definition * Update Changelog.md Co-authored-by: parhedberg <par.hedberg@gmail.com> Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: Frank Haverland <fspapaping@googlemail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Ralf Rachinger <git@ralfrachinger.de> Co-authored-by: Nicolas Liaudat <nliaudat@users.noreply.github.com> * Update Changelog.md for release Co-authored-by: parhedberg <par.hedberg@gmail.com> Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: Frank Haverland <fspapaping@googlemail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Ralf Rachinger <git@ralfrachinger.de> Co-authored-by: Nicolas Liaudat <nliaudat@users.noreply.github.com> * new model version (#1619) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 * only initial_esp32_setup and update.zip as artefacts * remove unneeded cache * rename step ota-v2 to ota * rename ota-v2 to ota * new models - ana-class100 v1.5.4 - ana-cont-11.0.4 - dig-class100 v1.5.0 Co-authored-by: github-actions <github-actions@github.com> * Update Changelog.md (#1630) * Correct RenameNumber * Update Changelog.md * Fix reloading of data file (#1635) * Update data.html * fixed * show link to graph Co-authored-by: CaCO3 <caco@ruinelli.ch> * Centralizing the defines (#1624) * defines changes * Finish #define move + #define STBI_ONLY_JPEGsave 2% of Flash * remove the defines on the old places * ClassFlowCNNGeneral in define.h * revert to origin * fix translation not ready * Update defines.h * Update WebInstaller * Code translation (#1626) * comment translation * translation part #2 * code translation from DE to ENG #part3 * translation #4 * dismantled =>splitted * bereich => range * Update defines.h Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> * Update manifest.json * Add files via upload * #ifndef in *.h + #pragma once (#1639) * Update defines.h (#1640) comment #define STBI_ONLY_JPEG as you do no want it in rolling but in rolling-minimize-firmware-size delete old reference to DE ''' #define AnalogFehler 3 #define AnalogToDigtalFehler 0.8 #define DigitalUnschaerfe 0.2 #define DigitalBand 3 #define DigitalAnalogerVorgaengerUebergangsbereich 2 #define DigitalUebergangsbereichVorgaenger 0.7 // 9.3 - 0.7 #define DigitalUebergangsbereichVorlauf 9.7 ''' * Trigger a flow start by REST API or MQTT (#1648) * Trigger flow start by Rest API * Increase handlers * Update * Update * Update * Change max handlers * Add debug message * Trigger flow start by MQTT * Update * Remove unused function * Remove handler_doflow + routines * Cleanup * MergeCheck * Optimize logfile write (#1652) * remove no longer needed OpenFileAndWait() * remove WriteToDedicatedFile * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * show release in log instead of branch (#1660) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Update sdkconfig.defaults (#1661) Reverting changes of `sdkconfig.defaults` falsly added within https://github.com/jomjol/AI-on-the-edge-device/pull/1626 * Init GPIO handler before MQTT init (#1663) * Update HTML & Firmware (#1671) * Remove unnecessary null pointer checks #1649 (#1673) * fix kernel panic (vector out of range) in getReadoutRawString * fix key of caches * fix key of caches * fix key caches * fix cache keys * fix cache keys * move set variables to top * debug * fix key * testing * try fix changelog * test * Update Changelog.md for release * Revert "Update Changelog.md for release" This reverts commit4f51ec7962. * remove testing * fix release creation * testing * Update Changelog.md for release * test * Revert "Merge branch 'master' of https://github.com/haverland/AI-on-the-edge-device" This reverts commitf68695a4c0, reversing changes made toa096cf7182. * Revert "test" This reverts commita096cf7182. * revert testing * #1524 - ensure the result of ZeigerEvalHybridNeu is <10 * Fix late digit transition #1503 * only initial_esp32_setup and update.zip as artefacts * remove unneeded cache * rename step ota-v2 to ota * rename ota-v2 to ota * new models - ana-class100 v1.5.4 - ana-cont-11.0.4 - dig-class100 v1.5.0 * Remove unnecessary null pointer checks #1649 Co-authored-by: github-actions <github-actions@github.com> * Improve NTP handling (#1676) * fix special case where number is named "default" (keep all topics in top level instead of in a sub-group) * re-implemented SNTP usage, added way to disable NTP client, added timezone table * minor fixes Co-authored-by: CaCO3 <caco@ruinelli.ch> * fix special case where number is named "default" (keep all topics in top level instead of in a sub-group) (#1664) Co-authored-by: CaCO3 <caco@ruinelli.ch> * prepare docs for deployment through actions (#1688) Co-authored-by: CaCO3 <caco@ruinelli.ch> * make more robust, add log (#1690) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Extend Github Actions (#1680) * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * automate manifest update * Update build.yaml * revert changes to docs folder * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Update build.yaml * Add files via upload * prepare docs for deployment through actions (#1688) Co-authored-by: CaCO3 <caco@ruinelli.ch> * automate manifest update # Conflicts: # docs/binary/firmware.bin # docs/binary/v12.0.1/firmware.bin # docs/binary/v12.0.5/firmware.bin # docs/binary/v13.0.5/firmware.bin # docs/binary/v13.0.7/firmware.bin * revert changes to docs folder * revert changes to docs folder # Conflicts: # docs/releases/download/firmware.bin * Update build.yaml Co-authored-by: CaCO3 <caco@ruinelli.ch> * Improve initial setup proc (#1692) * Initial Test * Initial functional version. * Add Bot Replies (#1701) * Update label-commenter-config.yml * Update reply-bot.yml * Update label-commenter-config.yml * disable remove-labels because they no longer work * delete img_convert.h as included in code\components\tflite-micro-esp-… (#1695) * delete img_convert.h as included in code\components\tflite-micro-esp-examples\components\esp32-camera\conversions\include\img_converters.h * macro definition #ifdef ENABLE_SOFTAP * macro definition #ifdef ENABLE_SOFTAP (#1698) * macro definition #ifdef ENABLE_SOFTAP * Update platformio.ini * softap define in define.h * Update platformio.ini * #define WLAN_CONFIG_FILE "/sdcard/wlan.ini" Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> * Deinit components before reboot (#1704) * Deinit all components before reboot * Update * Update * fetch index.html after reboot -> less 404 (#1705) * Safe optimizations (#1706) * safe optimizations * Merge branch 'rolling' of https://github.com/nliaudat/AI-on-the-edge-device into rolling * Enable SoftAP * Update defines * add a define to configure the logfile handling (#1709) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Move Logfile Switch to define.h * Update Reboot Algo * Update server_ota.cpp * Avoid loading of status infos twice (#1711) * Force a reboot even reboot task cannot be created due to lack of heap (#1713) * Deinit all components before reboot * Update * Update * Force reboot when reboot task cannot be created * Improve log message when web UI is incomplete (#1716) * improve warning if version.txt is missing * typo * show round duration in log Co-authored-by: CaCO3 <caco@ruinelli.ch> * fix static IP in UP, improve explanation for HA (#1719) * fix static IP in UP, improve explanation for HA * Update edit_config_param.html Co-authored-by: CaCO3 <caco@ruinelli.ch> * Create demo folder at startup (if not present) * Update defines.h (#1726) * improve explanations,added example (#1729) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Add demo mode (#1720) * move main part to cam file * added demo mode * . * add a define to configure the logfile handling (#1709) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Move Logfile Switch to define.h * Update Reboot Algo * Update server_ota.cpp * Avoid loading of status infos twice (#1711) * Force a reboot even reboot task cannot be created due to lack of heap (#1713) * Deinit all components before reboot * Update * Update * Force reboot when reboot task cannot be created * Improve log message when web UI is incomplete (#1716) * improve warning if version.txt is missing * typo * show round duration in log Co-authored-by: CaCO3 <caco@ruinelli.ch> * . * . * . * creade demo dir * fix static IP in UP, improve explanation for HA (#1719) * fix static IP in UP, improve explanation for HA * Update edit_config_param.html Co-authored-by: CaCO3 <caco@ruinelli.ch> * Create demo folder at startup (if not present) * move demo files * Update defines.h (#1726) * updated description * moved to expert section * fixed broken enabled state Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: Slider0007 <115730895+Slider0007@users.noreply.github.com> * Fix regression of reboot handler / reboot waiting script (#1725) * Reboot after OTA: Avoid exeception * Overview - optimize reload behaviour after reboot * Update * Update * Moved softAP to the very first checks * Update SoftAP * Update build.yaml (#1737) * Update build.yaml * Update build.yaml * #1649 unnecessary np check (#1736) * consolidate test-ip definition, added missing Access-Control-Allow-Origin, * Revert "consolidate test-ip definition, added missing Access-Control-Allow-Origin," This reverts commit56cfeb732e. * consolidate test-ip definition, added missing Access-Control-Allow-Origin (#1741) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Replace alert boxes with overlay info boxes (#1742) * consolidate test-ip definition, added missing Access-Control-Allow-Origin * replace alert boxes with overlay info boxes * . * . * . * . * . * . * . * . * . * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * compiler optimization (#1749) compiler optimization for tflite-micro-esp-examples * Modify stack sizes + max open files (SD) , add REST handler for heap/(stack) infos (#1751) * Modify stack sizes+max open files,add rest handler * Update * Optimized CImageBasis * Update feature.yaml * cache static files (#1755) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Implemented Reboot for "firmware.bin" as well * new OTA page with progressbar (#1756) * new OTA page with progress bar * improve error message on missing demo files * . * Implemented Reboot for "firmware.bin" as well * Update feature.yaml * cache static files (#1755) Co-authored-by: CaCO3 <caco@ruinelli.ch> * . * . * added filename validation * . * . * . * move * added missing dash to regex * restrict file type * . * . * . * . * cleanup no longer needed mode * only start restart counter if restart is required Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> * Rolling-bot: Only show jomjol repo rollings (#1783) * Update platfromio.ini * Add option to disable brownout detector (#1784) * Update defines.h * Update main.cpp * Improve file server (#1785) * . * . * . * . * . * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Ignore cache on GIT hash change (new commit or release) (#1787) * Add hash to all html, css, and js URLs * Update build.yaml * Update build.yaml * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * fix overview.html * GPIO handler: Deinit before delete (#1795) * Rest handler: Use none chunked transfer (#1797) * Resthandler info,sysinfo,starttime: no chunk trans * flowstart,statusflow,cputemp,rssi,uptime,prevalue * Renamed error messages * STBI_ONLY_JPEG (#1789) * Add error handling for memory intensive tasks (#1798) * tflite model loading: error handling * FlowAlignment: error handling * CImageBasis+GetJPGStream : error handling * Update graph.html (#1802) * Delete demo-images directory Data is now provided in the documentation * REST handler sysinfo + MQTT topic: Free heap memory not reporting (#1815) * REST handler sysinfo: Fix reporting of free memory * MQTT topic freemem: Fix reporting of free memory * Refactor getEspHeapInfo routine (#1816) * Refactor getEspHeapInfo * ClassLogfile: Remove redundandent one * DataGraph: datafiles sorted -> newest on top (#1817) * plaformio [env:esp32cam-dev] : Add task analysis & test for 8m spiram real support (#1818) add support of TASK_ANALYSIS_ON test full support of 8mb spiram board (https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/himem.html) * Improve html roi disablement (#1825) * Improve ROI-Problem * Update * Update common.js * Update links * Store preprocessed image with ROI to RAM (#1809) * tflite model loading: error handling * FlowAlignment: error handling * CImageBasis+GetJPGStream : error handling * store preprocessed ALG_ROI.jpg to memory * Update * Create clean-branch-cache-after-pull-request-got-closed.yml * Clean sdkconfig (not default) (#1828) * Delete sdkconfig - Kopie.defaults * Delete sdkconfig.esp32cam-testing * Delete sdkconfig - Kopie.esp32cam * Update platformio.ini * Delete clean-branch-cache-after-pull-request-got-closed.yml * Update README.md * Esp32 sys info (#1829) * Add files via upload * Update defines.h * Update main.cpp * git ignore + sdkconfig.esp32cam-dev (#1830) * update build actions/cache@v3.2.3 (#1831) * actions/cache@v3.2.3 * Create clear _all_cache.yml * fix typo naming workflow clear_cache.yml * Update tflite * Initial Implementation (#1834) * Fix pointer call in ClassControllCamera.cpp:310 (#1833) ClassControllCamera.cpp:310:67: error: request for member 'rgb_image' in '_zwImage', which is of pointer type 'CImageBasis*' ClassControllCamera.cpp:310:117: error: request for member 'width' in '_zwImage', which is of pointer type 'CImageBasis*' ClassControllCamera.cpp:310:157: error: request for member 'height' in '_zwImage', which is of pointer type 'CImageBasis*' * Initial Implementation (#1835) * improve caching (#1836) * improve caching See https://github.com/actions/cache/blob/main/tips-and-workarounds.md#update-a-cache * Update build.yaml * Update build.yaml * Update build.yaml * Update README.md * Update build.yaml * Update build.yaml * Update README.md * Update build.yaml * Update label-commenter-config.yml * Fix uninitialized filename (#1838) * fix the uninitialized filename. It only got used for the logging in case the file exists but failed to get loaded (eg. /sdcard/log/data/data_2023-01-14.csv) * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Show ways to get notified about new releases * update wiki references * enhance development environment (#1841) * add sdkconfig.defaults per environment https://github.com/platformio/platform-espressif32/issues/638 * add env to platformio * add sdkconfig.<pioenv>.defaults * Update platformio.ini * Update .gitignore * Delete sdkconfig.esp32cam-cpu-freq-240.defaults * Delete sdkconfig.esp32cam-dev-himem.defaults * Delete sdkconfig.esp32cam-dev.defaults * Delete sdkconfig.esp32cam-no-softap.defaults * Add files via upload * Update sdkconfig.esp32cam-cpu-freq-240.defaults * Update platformio.ini * Update platformio.ini * Update CMakeLists.txt * Update sdkconfig.esp32cam-dev.defaults * Update platformio.ini * add HIMEM debugging tools (check free size, and memory test) (#1852) * Update defines.h * Update esp_sys.h * Update esp_sys.cpp * Add files via upload * Update perfmon.c * Update main.cpp * Update main.cpp * Delete himem_memory_check.c * Add files via upload * Update defines.h * Update himem_memory_check.cpp * Update main.cpp * Update himem_memory_check.cpp * Update himem_memory_check.h * Update main.cpp * fix define * Avoid multiple Access-Control-Allow-Origin * (#1859) * Avoid multiple Access-Control-Allow-Origin * * Adapt loglevel to debug * Update build.yaml * Improve data logging on errors (#1839) * use error level for log if "Rate to High" or "Negative Rate" * remove redundant data logging * . * . * update time also in case of an error * move calculation of difference to the top as discussed in PR 1839 Co-authored-by: CaCO3 <caco@ruinelli.ch> * Heap tracing (#1861) * Update sdkconfig.esp32cam-dev-task-analysis.defaults * Update defines.h * Update platformio.ini * Update main.cpp * Update defines.h * Update ClassFlowCNNGeneral.cpp * Update platformio.ini * disable HIMEM (external > 4mb ram) not used (#1864) #force disable HIMEM as not used in default config, can be enabled with [env:esp32cam-dev-himem] #free 256kb of internal memory : #I (2112) esp_himem: Initialized. Using last 8 32KB address blocks for bank switching on 4352 KB of physical memory. CONFIG_SPIRAM_BANKSWITCH_ENABLE=n #CONFIG_SPIRAM_BANKSWITCH_RESERVE is not set * Update ota_page.html (#1866) Fixed the firework to match the actual button text. Fixed other random typos. * add AlignmentAlgo=off option (#1867) * Replace outdated wiki links, wording (#1871) * Revert "add AlignmentAlgo=off option (#1867)" (#1876) This reverts commit3de4cc7c56. * fixed typo (#1881) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Show WIFI signal text labels / Log RSSI value to logfile (#1877) * Overview: WIFI RSSI strength text labels * Log RSSI value (debug level) * Typo * Update config.ini (#1880) * Update Changelog.md for release (#1892) Co-authored-by: github-actions <github-actions@github.com> * Update Changelog.md * Remove newline in version (#1891) * remove newline in version * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * Show alternative images for states "Initialization" and "Take Image" (#1858) * Show image for flow not started + take image * Update * Adding new images * . * Avoid multiple Access-Control-Allow-Origin * (#1859) * Avoid multiple Access-Control-Allow-Origin * * Adapt loglevel to debug * Update build.yaml * . * New state "initialization (delayed)", renaming * Overview: Renamed "Status" + switched position * Improve data logging on errors (#1839) * use error level for log if "Rate to High" or "Negative Rate" * remove redundant data logging * . * . * update time also in case of an error * move calculation of difference to the top as discussed in PR 1839 Co-authored-by: CaCO3 <caco@ruinelli.ch> * Heap tracing (#1861) * Update sdkconfig.esp32cam-dev-task-analysis.defaults * Update defines.h * Update platformio.ini * Update main.cpp * Update defines.h * Update ClassFlowCNNGeneral.cpp * Update platformio.ini * disable HIMEM (external > 4mb ram) not used (#1864) #force disable HIMEM as not used in default config, can be enabled with [env:esp32cam-dev-himem] #free 256kb of internal memory : #I (2112) esp_himem: Initialized. Using last 8 32KB address blocks for bank switching on 4352 KB of physical memory. CONFIG_SPIRAM_BANKSWITCH_ENABLE=n #CONFIG_SPIRAM_BANKSWITCH_RESERVE is not set * Update ota_page.html (#1866) Fixed the firework to match the actual button text. Fixed other random typos. * add AlignmentAlgo=off option (#1867) * Replace outdated wiki links, wording (#1871) * Revert "add AlignmentAlgo=off option (#1867)" (#1876) This reverts commit3de4cc7c56. * fixed typo (#1881) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Show WIFI signal text labels / Log RSSI value to logfile (#1877) * Overview: WIFI RSSI strength text labels * Log RSSI value (debug level) * Typo * Update config.ini (#1880) * Update Changelog.md for release (#1892) Co-authored-by: github-actions <github-actions@github.com> * Update Changelog.md * Remove newline in version (#1891) * remove newline in version * . * . Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: CaCO3 <caco3@ruinelli.ch> Co-authored-by: Nicolas Liaudat <nliaudat@users.noreply.github.com> Co-authored-by: AngryApostrophe <89547888+AngryApostrophe@users.noreply.github.com> Co-authored-by: github-actions <github-actions@github.com> * restructure manual setup zip (#1897) * Update build.yaml * Update build.yaml * Update build.yaml * fix typos and wording on config page (#1898) * Update label-commenter-config.yml * Update label-commenter-config.yml * remove external Web UI dependencies (#1896) Co-authored-by: CaCO3 <caco@ruinelli.ch> * Remove excessive whitespaces and newlines in json (#1904) * . * . * . * . * . * remove newlines in json as it is not needed * . Co-authored-by: CaCO3 <caco@ruinelli.ch> * REST handler CPU temp / RSSI: Remove units (#1908) * REST CPU temp: escape special character * REST CPUTemp+RSSI: remove units, output as int * REST handler sysinfo: CPU tempature as integer * Update Changelog.md (#1893) * Update Changelog.md * Update Changelog.md * Update Changelog.md * Update Changelog.md * Update Index & Index.html * Move Update description to online docu * Update index.html * Update Changelog.md * Update Changelog.md --------- Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> * Update Changelog.md --------- Co-authored-by: parhedberg <par.hedberg@gmail.com> Co-authored-by: Pär Hedberg <par.hedberg@nordicmedtest.se> Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com> Co-authored-by: Christopher Fenner <9592452+CFenner@users.noreply.github.com> Co-authored-by: CaCO3 <caco@ruinelli.ch> Co-authored-by: Frank Haverland <fspapaping@googlemail.com> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Ralf Rachinger <git@ralfrachinger.de> Co-authored-by: Nicolas Liaudat <nliaudat@users.noreply.github.com> Co-authored-by: Slider0007 <115730895+Slider0007@users.noreply.github.com> Co-authored-by: smartboart <38385805+smartboart@users.noreply.github.com> Co-authored-by: AngryApostrophe <89547888+AngryApostrophe@users.noreply.github.com> Co-authored-by: Dave <43378003+dkneisz@users.noreply.github.com>
This commit is contained in:
2
.github/ISSUE_TEMPLATE/feature.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 💡 Feature Request
|
||||
description: Use this form if you have an idea or wish for a new feature
|
||||
labels: feature
|
||||
labels: enhancement
|
||||
body:
|
||||
|
||||
|
||||
|
||||
82
.github/label-commenter-config.yml
vendored
82
.github/label-commenter-config.yml
vendored
@@ -1,7 +1,28 @@
|
||||
# Reply Bot Configuration
|
||||
# See https://github.com/peaceiris/actions-label-commenter
|
||||
# Make sure to also add the response to .github/workflows/reply-bot.yml!
|
||||
# Due to the way it works, you have to add each response twice, once for the issue, once for the discussions!
|
||||
|
||||
labels:
|
||||
labels:
|
||||
#######################################################################
|
||||
# Bot Response: Logfile
|
||||
#######################################################################
|
||||
- name: bot-reply Logfile
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
Please provide a logfile!
|
||||
Make sure to first enable the `DEBUG` level in `Settings->Configuration->Debug->Logfile Log Level`!
|
||||
Then wait until the issue arises again.
|
||||
When you copy the log into here, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
discussion:
|
||||
body: |
|
||||
Please provide a logfile!
|
||||
Make sure to first enable the `DEBUG` level in `Settings->Configuration->Debug->Logfile Log Level`!
|
||||
Then wait until the issue arises again.
|
||||
When you copy the log into here, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Web Console
|
||||
#######################################################################
|
||||
@@ -11,11 +32,41 @@
|
||||
body: |
|
||||
You can use the [Web Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) to get USB log from the device.
|
||||
The USB log contains more information about the startup and operation of the device than the normal Web UI log
|
||||
When you copy the log into herm, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
discussion:
|
||||
body: |
|
||||
You can use the [Web Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) to get USB log from the device.
|
||||
The USB log contains more information about the startup and operation of the device than the normal Web UI log
|
||||
|
||||
When you copy the log into herm, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Properly Format Code
|
||||
#######################################################################
|
||||
- name: bot-reply Properly Format Code
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
Please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
This makes your code or log much easier to read!
|
||||
discussion:
|
||||
body: |
|
||||
Please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
This makes your code or log much easier to read!
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Web Installer
|
||||
#######################################################################
|
||||
- name: bot-reply Web Installer
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
You can use the [Web Installer](https://jomjol.github.io/AI-on-the-edge-device/index.html) install the firmware onto the ESP32.
|
||||
discussion:
|
||||
body: |
|
||||
You can use the [Web Installer](https://jomjol.github.io/AI-on-the-edge-device/index.html) install the firmware onto the ESP32.
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Rolling Build
|
||||
@@ -24,13 +75,24 @@
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
You can use the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling) of the the `rolling` branch. It might already contain a fix for your issue.
|
||||
Pick the most top passing entry (it has a green circle with a tick in it), then scoll down to the **Artifacts** and download the file named `update_*`.
|
||||
You can try the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling+event%3Apush) of the the `rolling` or any other branch. It might already contain a fix for your issue.
|
||||
See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/rolling-installation) for additional information.
|
||||
discussion:
|
||||
body: |
|
||||
You can use the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling) of the the `rolling` branch. It might already contain a fix for your issue.
|
||||
Pick the most top passing entry (it has a green circle with a tick in it), then scoll down to the **Artifacts** and download the file named `update_*`.
|
||||
|
||||
|
||||
|
||||
|
||||
You can try the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling+event%3Apush) of the the `rolling` or any other branch. It might already contain a fix for your issue.
|
||||
See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/rolling-installation) for additional information.
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Show Trained Digits/Pointers
|
||||
#######################################################################
|
||||
- name: bot-reply Show Trained Digits/Pointers
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
See [Digital Digits](https://jomjol.github.io/neural-network-digital-counter-readout) resp. [Analogue Pointers](https://jomjol.github.io/neural-network-analog-needle-readout) for an overview of all trained data.
|
||||
If your type is not contained it can be added to our training material, see [here](https://jomjol.github.io/AI-on-the-edge-device-docs/Learn-models-with-your-own-images/).
|
||||
discussion:
|
||||
body: |
|
||||
See [Digital Digits](https://jomjol.github.io/neural-network-digital-counter-readout) resp. [Analogue Pointers](https://jomjol.github.io/neural-network-analog-needle-readout) for an overview of all trained data.
|
||||
If your type is not contained it can be added to our training material, see [here](https://jomjol.github.io/AI-on-the-edge-device-docs/Learn-models-with-your-own-images/).
|
||||
|
||||
370
.github/workflows/build.yaml
vendored
370
.github/workflows/build.yaml
vendored
@@ -24,16 +24,43 @@ jobs:
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v3
|
||||
- name: Update PIP cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-${{ github.run_id }}
|
||||
restore-keys: pip # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update PlatformIO cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
key: platformio-${{ github.run_id }}
|
||||
restore-keys: platformio # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update Build cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ./code/.pio/
|
||||
key: build-${{ github.run_id }}
|
||||
restore-keys: build # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -43,21 +70,18 @@ jobs:
|
||||
#run: echo "Testing... ${{ github.ref_name }}, ${{ steps.vars.outputs.sha_short }}" > ./sd-card/html/version.txt; mkdir -p ./code/.pio/build/esp32cam/; cd ./code/.pio/build/esp32cam/; echo "${{ steps.vars.outputs.sha_short }}" > firmware.bin; cp firmware.bin partitions.bin; cp firmware.bin bootloader.bin # Testing
|
||||
run: cd code; platformio run --environment esp32cam
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
- name: Prepare Web UI (copy data from repo and update hashes in all files)
|
||||
run: |
|
||||
rm -rf ./html; mkdir html
|
||||
cp ./sd-card/html/* ./html/
|
||||
cd html; find . -type f -exec sed -i 's/$COMMIT_HASH/${{ steps.vars.outputs.sha_short }}/g' {} \;
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for new OTA
|
||||
## Pack for Update
|
||||
#########################################################################################
|
||||
pack-for-OTA:
|
||||
pack-for-update:
|
||||
# New OTA concept
|
||||
# update__version.zip file with following content:
|
||||
# - /firmware.bin
|
||||
@@ -69,15 +93,84 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare update__*.zip artifact
|
||||
run: |
|
||||
mkdir -p ./update
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "update/firmware.bin"
|
||||
|
||||
- name: Add Web UI to update
|
||||
run: cp -r ./html ./update/
|
||||
|
||||
- name: Add CNN to update
|
||||
run: |
|
||||
mkdir -p ./update/config/
|
||||
cp ./sd-card/config/*.tfl ./update/config/ 2>/dev/null || true
|
||||
cp ./sd-card/config/*.tflite ./update/config/ 2>/dev/null || true
|
||||
|
||||
- name: Upload update as update.zip artifact (Firmware + Web UI + CNN)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "AI-on-the-edge-device__update__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./update/*
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for Remote Setup
|
||||
#########################################################################################
|
||||
pack-for-remote_setup:
|
||||
# New Remote Setup concept
|
||||
# remote_setup__version.zip file with following content:
|
||||
# - /firmware.bin
|
||||
# - /html/*
|
||||
# - /config/*
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update remote_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: remote_setup
|
||||
key: remote_setup-${{ github.run_id }}
|
||||
restore-keys: remote_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
@@ -85,39 +178,30 @@ jobs:
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare update.zip artifact
|
||||
- name: Prepare remote_setup__*.zip artifact
|
||||
run: |
|
||||
mkdir -p ./dist
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "dist/firmware.bin"
|
||||
mkdir -p ./remote_setup
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "remote_setup/firmware.bin"
|
||||
|
||||
- name: Add Web UI to dist
|
||||
run: cp -r ./sd-card/html ./dist/
|
||||
- name: Add Web UI to remote_setup
|
||||
run: cp -r ./html ./remote_setup/
|
||||
|
||||
- name: Add CNN to dist
|
||||
- name: Add whole config folder to remote_setup
|
||||
run: |
|
||||
mkdir ./dist/config/
|
||||
cp ./sd-card/config/*.tfl ./dist/config/ 2>/dev/null || true
|
||||
cp ./sd-card/config/*.tflite ./dist/config/ 2>/dev/null || true
|
||||
mkdir -p ./remote_setup/config/
|
||||
cp ./sd-card/config/* ./remote_setup/config/ 2>/dev/null || true
|
||||
|
||||
- name: Upload dist as update.zip artifact (Firmware + Web UI + CNN)
|
||||
- name: Upload remote_setup as remote_setup.zip artifact (Firmware + Web UI + Config)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "update__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./dist/*
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: dist
|
||||
key: ${{ github.run_number }}-pack-for-OTA
|
||||
|
||||
|
||||
name: "AI-on-the-edge-device__remote-setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./remote_setup/*
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for a fresh install (USB flashing) (initial_esp32_setup)
|
||||
## Pack for a fresh install (USB flashing) (manual_setup)
|
||||
#########################################################################################
|
||||
pack-for-fresh-install:
|
||||
pack-for-manual_setup:
|
||||
# creates old style binaries for fresh installation (backward compatible to wiki)
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
@@ -125,15 +209,86 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update manual_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: manual_setup
|
||||
key: manual_setup-${{ github.run_id }}
|
||||
restore-keys: manual_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare manual_setup__*.zip artifact
|
||||
run: |
|
||||
mkdir -p manual_setup
|
||||
rm -rf manual_setup/*.zip
|
||||
mkdir -p release
|
||||
# copy builds to manual_setup folder
|
||||
cp -f "./code/.pio/build/esp32cam/firmware.bin" "manual_setup/firmware.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/bootloader.bin" "manual_setup/bootloader.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/partitions.bin" "manual_setup/partitions.bin"
|
||||
cd sd-card; zip -r ../manual_setup/sd-card.zip *; cd ..
|
||||
cd ./manual_setup
|
||||
|
||||
- name: Upload manual_setup.zip artifact (Firmware + Bootloader + Partitions + Web UI)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "AI-on-the-edge-device__manual-setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./manual_setup
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Prepare and create release
|
||||
#########################################################################################
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pack-for-update, pack-for-manual_setup, pack-for-remote_setup]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow updating the branches
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update remote_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: remote_setup
|
||||
key: remote_setup-${{ github.run_id }}
|
||||
restore-keys: remote_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update manual_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: manual_setup
|
||||
key: manual_setup-${{ github.run_id }}
|
||||
restore-keys: manual_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
@@ -143,70 +298,20 @@ jobs:
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p firmware
|
||||
rm -rf firmware/*.zip
|
||||
mkdir -p release
|
||||
# copy builds to firmware folder
|
||||
cp -f "./code/.pio/build/esp32cam/firmware.bin" "firmware/firmware.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/bootloader.bin" "firmware/bootloader.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/partitions.bin" "firmware/partitions.bin"
|
||||
zip -r ./firmware/sd-card.zip sd-card
|
||||
cd ./firmware
|
||||
|
||||
- name: Upload initial_esp32_setup.zip artifact (Firmware + Bootloader + Partitions + Web UI)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "initial_esp32_setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./firmware
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: firmware
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
# create AI-on-the-edge-device__update__*.zip like "AI-on-the-edge-device__update__v13.0.5.zip"
|
||||
cd ./update
|
||||
zip -r ../release/AI-on-the-edge-device__update__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
# create AI-on-the-edge-device__manual-setup__*.zip like "AI-on-the-edge-device__manual-setup__v13.0.5.zip"
|
||||
cd ../manual_setup
|
||||
zip -r ../release/AI-on-the-edge-device__manual-setup__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
# create AI-on-the-edge-device__remote-setup__*.zip like "AI-on-the-edge-device__remote-setup__v13.0.5.zip"
|
||||
cd ../manual_setup
|
||||
zip -r ../release/AI-on-the-edge-device__remote-setup__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Prepare and create release
|
||||
#########################################################################################
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pack-for-OTA, pack-for-fresh-install]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
# import the changes from
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: dist
|
||||
key: ${{ github.run_number }}-pack-for-OTA
|
||||
|
||||
# import cached artifacts from pack-for-fresh-install
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: firmware
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p release
|
||||
mkdir -p dist
|
||||
# create a update.zip like "update__rolling"
|
||||
pwd
|
||||
cd ./dist
|
||||
zip -r ../release/update.zip .
|
||||
cd ../firmware
|
||||
zip -r ../release/initial_esp32_setup.zip .
|
||||
# extract the version used in next step
|
||||
- id: get_version
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -233,13 +338,16 @@ jobs:
|
||||
# all artifacts in firmware folder pushed to the release
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
# Note:
|
||||
# If you get the error "Resource not accessible by integration",
|
||||
# The access rights are not sufficient, see
|
||||
# https://github.com/softprops/action-gh-release/issues/232#issuecomment-1131379440
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
name: ${{ steps.get_version.outputs.version-without-v }}
|
||||
body: ${{ steps.extract-release-notes.outputs.release_notes }}
|
||||
files: |
|
||||
release/*
|
||||
|
||||
|
||||
# Commit&Push Changelog to master branch. Must be manually merged back to rolling
|
||||
- name: Commit changes and push changes
|
||||
@@ -250,3 +358,57 @@ jobs:
|
||||
git add Changelog.md
|
||||
git commit Changelog.md -m "Update Changelog.md for ${{github.event.inputs.versionIncrement}} release"
|
||||
git push origin HEAD:master
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Update the Web Installer on a release
|
||||
#########################################################################################
|
||||
update-web-installer:
|
||||
needs: [release]
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Add binary to Web Installer and update manifest
|
||||
run: |
|
||||
rm -f docs/binary/firmware.bin
|
||||
cp -f update/firmware.bin docs/binary/firmware.bin
|
||||
cp -f docs/manifest_template.json docs/manifest.json
|
||||
sed -i 's/VERSION/${{ steps.vars.outputs.branch }}/g' docs/manifest.json
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v2
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: 'docs'
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
|
||||
30
.github/workflows/clear_cache.yml
vendored
Normal file
30
.github/workflows/clear_cache.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Clear cache
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
clear-cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clear cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
console.log("About to clear")
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
console.log(cache)
|
||||
github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
}
|
||||
console.log("Clear completed")
|
||||
65
.github/workflows/reply-bot.yml
vendored
65
.github/workflows/reply-bot.yml
vendored
@@ -22,20 +22,57 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Remove 'Web Console' label again (issues only)
|
||||
if: github.event.label.name == 'bot-reply Web Console'
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
labels: 'bot-reply Web Console'
|
||||
|
||||
- name: Remove 'Rolling Build' label again (issues only)
|
||||
if: github.event.label.name == 'bot-reply Rolling Build'
|
||||
uses: actions-cool/issues-helper@v2
|
||||
with:
|
||||
actions: 'remove-labels'
|
||||
labels: 'bot-reply Rolling Build'
|
||||
|
||||
|
||||
####################################################################
|
||||
## Remove labels again (issues only)
|
||||
## Make sure to also add the reply message to .github/label-commenter-config.yml!
|
||||
## This currently seems no longer to work due to changes on the actions-cool/issues-helper!
|
||||
####################################################################
|
||||
# - name: Remove 'Logfile' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Logfile'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Logfile'
|
||||
#
|
||||
# - name: Remove 'Web Console' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Web Console'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Web Console'
|
||||
#
|
||||
# - name: Remove 'Properly Format Code' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Properly Format Code'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Properly Format Code'
|
||||
#
|
||||
# - name: Remove 'Web Installer' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Web Installer'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Web Installer'
|
||||
#
|
||||
# - name: Remove 'Rolling Build' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Rolling Build'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Rolling Build'
|
||||
#
|
||||
# - name: Remove 'Show Trained Digits/Pointers' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Show Trained Digits/Pointers'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Show Trained Digits/Pointers'
|
||||
|
||||
####################################################################
|
||||
## Write the response
|
||||
####################################################################
|
||||
- name: Write Response
|
||||
uses: peaceiris/actions-label-commenter@c2d00660c86f2b9ed0fb35b372c451558eba85b3
|
||||
with:
|
||||
|
||||
77
Changelog.md
77
Changelog.md
@@ -2,40 +2,57 @@
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
**Stabilization and Improved User Experience**
|
||||
|
||||
Thanks to over 80 Pull Requests from 6 contributors, we can anounce another great release with many many improvements and new features:
|
||||
|
||||
### Update Procedure
|
||||
Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update)
|
||||
|
||||
### Changes
|
||||
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v13.0.8...v14.0.0)
|
||||
|
||||
#### Added
|
||||
- [1877](https://github.com/jomjol/AI-on-the-edge-device/pull/1877) Show WIFI signal text labels / Log RSSI value to logfile
|
||||
- Web UI caching of static files
|
||||
- Added various debug tools
|
||||
- [1798](https://github.com/jomjol/AI-on-the-edge-device/pull/1798) Add error handling for memory intensive tasks
|
||||
- [1784](https://github.com/jomjol/AI-on-the-edge-device/pull/1784) Add option to disable brownout detector
|
||||
- Added full web browser based installation mode (including initial setup of SD-card) - see [WebInstaller](https://jomjol.github.io/AI-on-the-edge-device/index.html)
|
||||
- Added [Demo Mode](https://jomjol.github.io/AI-on-the-edge-device-docs/Demo-Mode)
|
||||
- [1648](https://github.com/jomjol/AI-on-the-edge-device/pull/1648) Added trigger to start a flow by [REST](https://jomjol.github.io/AI-on-the-edge-device-docs/REST-API) API or [MQTT](https://jomjol.github.io/AI-on-the-edge-device-docs/MQTT-API/)
|
||||
- Show special images during steps `Initializing` and `Take Image` as the current camera image might be incomplete or outdated
|
||||
|
||||
#### Changed
|
||||
- Migrated documentation (Wiki) to [https://jomjol.github.io/AI-on-the-edge-device-docs](https://jomjol.github.io/AI-on-the-edge-device-docs). Please help us to make it even better.
|
||||
- New OTA Update page with progress indication
|
||||
- Various memory optimizations
|
||||
- Cleanup code/Web UI
|
||||
- Updated models
|
||||
- [1809](https://github.com/jomjol/AI-on-the-edge-device/pull/1809) Store preprocessed image with ROI to RAM
|
||||
- Better log messages on some errors/issues
|
||||
- [1742](https://github.com/jomjol/AI-on-the-edge-device/pull/1742) Replace alert boxes with overlay info boxes
|
||||
- Improve log message when web UI is installed incomplete
|
||||
- [1676](https://github.com/jomjol/AI-on-the-edge-device/pull/1676) Improve NTP handling
|
||||
- HTML: improved user informations (info boxes, error hints, ...)
|
||||
- [1904](https://github.com/jomjol/AI-on-the-edge-device/pull/1904) Removed newlines in JSON and replaced all whitespaces where there was more than one
|
||||
|
||||
#### Fixed
|
||||
- Fixed many many things
|
||||
- [1509](https://github.com/jomjol/AI-on-the-edge-device/pull/1509) Protect `wifi.ini` from beeing deleted.
|
||||
- [1530](https://github.com/jomjol/AI-on-the-edge-device/pull/1530) Homeassistant `Problem Sensor`
|
||||
- [1518](https://github.com/jomjol/AI-on-the-edge-device/pull/1518) JSON Strings
|
||||
- [1817](https://github.com/jomjol/AI-on-the-edge-device/pull/1817) DataGraph: datafiles sorted -> newest on top
|
||||
|
||||
#### Removed
|
||||
- n.a.
|
||||
|
||||
|
||||
## [13.0.8] - 2022-12-19
|
||||
|
||||
**Home Assistant MQTT Discovery Support**
|
||||
|
||||
### Update Procedure
|
||||
|
||||
:bangbang: **Make sure to read the instructions below carfully!**
|
||||
|
||||
1. Backup your configuration (use the `System -> Backup/Restore` page)!
|
||||
|
||||
2. You should update to `12.0.1` before you update to this release. All other migrations are untested.
|
||||
|
||||
3. Upload and update the `update-*.zip` file from this release.
|
||||
|
||||
4. Let it restart and check on the `System -> Info` page that the Firmware as well as the Web UI got updated. If only one got updated, redo the update. If it fails several times, you also can update the Firmware and the Web UI separately.
|
||||
|
||||
5. Safe way:
|
||||
1. Update first the `firmware.bin` (extract it from one of the provided zip files) and do the Reboot
|
||||
2. Update with the full zip file (`update-*.zip`, ignore the version warning after the reboot)
|
||||
|
||||
6. Please go to `Settings -> Configuration` and address the changed parameters:
|
||||
- DataLogging (storing the values for data graph)
|
||||
- Debug (extended by different debug reporting levels)
|
||||
|
||||
7. Make sure it starts to do the digitalization (check the Error field on the overview page). If it does not start a round within a minute, restart the device.
|
||||
|
||||
If anything breaks you can try to enforce manual update as following:
|
||||
|
||||
**OTA:**
|
||||
1\. Make sure the last run of the update completed the **Uploading** step.
|
||||
1\. Call `http://<IP>/ota?task=update&file=<UPLOAD_FILENAME>` to enforce the extraction/flashing.
|
||||
|
||||
**Initial Setup:**
|
||||
1\. Use the initial_esp32_setup.zip ( <https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation> ) as alternative to have a clean install.
|
||||
### Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update)
|
||||
|
||||
### Added
|
||||
|
||||
|
||||
21
README.md
21
README.md
@@ -6,18 +6,21 @@ Here this edge computing is brought into a practical oriented example, where a A
|
||||
|
||||
This projects allows you to digitalize your **analoge** water, gas, power and other meters using cheap and easily available hardware.
|
||||
|
||||
All you need is an [ESP32 board with a supported camera](https://github.com/jomjol/AI-on-the-edge-device/wiki/Hardware-Compatibility) and a bit of a practical hand.
|
||||
All you need is an [ESP32 board with a supported camera](https://jomjol.github.io/AI-on-the-edge-device-docs/Hardware-Compatibility/) and a bit of a practical hand.
|
||||
|
||||
<img src="images/esp32-cam.png" width="200px">
|
||||
|
||||
## Key features
|
||||
- Tensorflow Lite (TFlite) integration - including easy to use wrapper
|
||||
- Inline Image processing (feature detection, alignment, ROI extraction)
|
||||
- **Small** and **cheap** device (3x4.5x2 cm³, < 10 EUR)
|
||||
- camera and illumination integrated
|
||||
- Web surface for administration and control
|
||||
- Web surface to administrate and control
|
||||
- OTA-Interface to update directly through the web interface
|
||||
- API for easy integration
|
||||
- Inline Image processing (feature detection, alignment, ROI extraction)
|
||||
- Tensorflow Lite (TFlite) integration - including easy to use wrapper
|
||||
- Full integration into Homeassistant
|
||||
- Support for Influx DB 1
|
||||
- MQTT
|
||||
- REST API
|
||||
|
||||
## Workflow
|
||||
The device takes a photo of your meter at a defined interval. It then extracts the Regions of Interest (ROI's) out of it and runs them through an artificial inteligence. As a result, you get the digitalized value of your meter.
|
||||
@@ -38,7 +41,7 @@ There are several options what to do with that value. Either send it to a MQTT b
|
||||
|
||||
|
||||
## Setup
|
||||
There is a growing [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki) which provides you with a lot of information.
|
||||
There is a growing [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/) which provides you with a lot of information.
|
||||
Head there to get a start, set it up and configure it.
|
||||
|
||||
There are also a articles in the German Heise magazine "make:" about the setup and the technical background (behind a paywall) : [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296)
|
||||
@@ -56,10 +59,10 @@ There are different ways to flash your ESP32:
|
||||
- Flash Tool from Espressif
|
||||
- ESPtool (Command Line Tool)
|
||||
|
||||
See the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation) for more information.
|
||||
See the [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/) for more information.
|
||||
|
||||
### Flashing the SD-Card
|
||||
The SD-Card must be flashed separately, see the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation) for details.
|
||||
The SD-Card must be flashed separately, see the [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/) for details.
|
||||
|
||||
## Casing
|
||||
|
||||
@@ -90,7 +93,7 @@ See [Changelog](Changelog.md)
|
||||
## Tools
|
||||
|
||||
* Logfile downloader and combiner (Thx to [reserve85](https://github.com/reserve85))
|
||||
* Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
|
||||
* Files see ['/tools/logfile-tool'](tbd), How-to see [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/outdated--Gasmeter-Log-Downloader/)
|
||||
|
||||
## Additional Ideas
|
||||
There are some ideas and feature requests which are not followed currently - mainly due to capacity reasons on side of the developer. They are collected here: [FeatureRequest.md](FeatureRequest.md)
|
||||
|
||||
8
code/.gitignore
vendored
8
code/.gitignore
vendored
@@ -5,3 +5,11 @@
|
||||
.vscode/ipch
|
||||
version.cpp
|
||||
sdkconfig.esp32cam
|
||||
sdkconfig.esp32cam-dev
|
||||
sdkconfig.esp32cam-debug
|
||||
sdkconfig.esp32cam-board-rev3
|
||||
sdkconfig.esp32cam-cpu-freq-240
|
||||
sdkconfig.esp32cam-board-rev3-cpu-freq-240
|
||||
sdkconfig.esp32cam-dev-himem
|
||||
sdkconfig.esp32cam-dev-task-analysis
|
||||
sdkconfig.esp32cam-no-softap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common components/tflite-micro-esp-examples/components/tflite-lib)
|
||||
|
||||
@@ -8,6 +8,15 @@ ADD_CUSTOM_COMMAND(
|
||||
COMMAND ${CMAKE_COMMAND} -P
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.cmake)
|
||||
|
||||
if(EXISTS "${SDKCONFIG}.defaults")
|
||||
if(EXISTS "sdkconfig.defaults")
|
||||
set(SDKCONFIG_DEFAULTS "${SDKCONFIG}.defaults;sdkconfig.defaults")
|
||||
message(STATUS "-- Using defaults: ${SDKCONFIG_DEFAULTS} + sdkconfig.defaults")
|
||||
else()
|
||||
set(SDKCONFIG_DEFAULTS "${SDKCONFIG}.defaults")
|
||||
endif()
|
||||
message(STATUS "-- Using defaults: ${SDKCONFIG_DEFAULTS}")
|
||||
endif()
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(esp32cam-server-only)
|
||||
project(AI-on-the-edge)
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
#include "configFile.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "CONFIG";
|
||||
|
||||
ConfigFile::ConfigFile(std::string filePath)
|
||||
{
|
||||
std::string config = FormatFileName(filePath);
|
||||
pFile = OpenFileAndWait(config.c_str(), "r");
|
||||
pFile = fopen(config.c_str(), "r");
|
||||
}
|
||||
|
||||
ConfigFile::~ConfigFile()
|
||||
@@ -65,7 +67,7 @@ bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
|
||||
}
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CONFIGFILE_H
|
||||
#define CONFIGFILE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -9,7 +14,10 @@ public:
|
||||
bool isNewParagraph(std::string input);
|
||||
bool GetNextParagraph(std::string& aktparamgraph, bool &disabled, bool &eof);
|
||||
bool getNextLine(std::string* rt, bool &disabled, bool &eof);
|
||||
bool ConfigFileExists(){return pFile;};
|
||||
|
||||
private:
|
||||
FILE* pFile;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //CONFIGFILE_H
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "esp_attr.h"
|
||||
union Hsv;
|
||||
@@ -67,3 +70,5 @@ union Hsv {
|
||||
bool operator==( Hsv in ) const { return in.value == value; }
|
||||
void swap( Hsv& o ) { value = o.value; }
|
||||
};
|
||||
|
||||
#endif //COLOR_H
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SMARTLEDS_H
|
||||
#define SMARTLEDS_H
|
||||
|
||||
/*
|
||||
* A C++ driver for the WS2812 LEDs using the RMT peripheral on the ESP32.
|
||||
*
|
||||
@@ -528,3 +531,5 @@ private:
|
||||
int _latchFrames;
|
||||
uint8_t _latchBuffer[ LATCH_FRAME_SIZE_BYTES ];
|
||||
};
|
||||
|
||||
#endif //SMARTLEDS_H
|
||||
|
||||
@@ -10,15 +10,12 @@
|
||||
|
||||
#include "server_tflite.h"
|
||||
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
//#include "errno.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
//#include <regex>
|
||||
|
||||
#include "defines.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "server_GPIO.h"
|
||||
|
||||
@@ -29,11 +26,10 @@
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
static const char *TAG = "GPIO";
|
||||
QueueHandle_t gpio_queue_handle = NULL;
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable)
|
||||
{
|
||||
_gpio = gpio;
|
||||
@@ -254,7 +250,7 @@ void GpioHandler::init()
|
||||
|
||||
if (xHandleTaskGpio == NULL) {
|
||||
gpio_queue_handle = xQueueCreate(10,sizeof(GpioResult));
|
||||
BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", configMINIMAL_STACK_SIZE * 8, (void *)this, tskIDLE_PRIORITY + 2, &xHandleTaskGpio);
|
||||
BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", 3 * 1024, (void *)this, tskIDLE_PRIORITY + 4, &xHandleTaskGpio);
|
||||
if(xReturned == pdPASS ) {
|
||||
ESP_LOGD(TAG, "xHandletaskGpioHandler started");
|
||||
} else {
|
||||
@@ -310,7 +306,7 @@ bool GpioHandler::readConfig()
|
||||
|
||||
ConfigFile configFile = ConfigFile(_configFile);
|
||||
|
||||
std::vector<std::string> zerlegt;
|
||||
std::vector<std::string> splitted;
|
||||
std::string line = "";
|
||||
bool disabledLine = false;
|
||||
bool eof = false;
|
||||
@@ -344,31 +340,31 @@ bool GpioHandler::readConfig()
|
||||
bool registerISR = false;
|
||||
while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(line);
|
||||
splitted = ZerlegeZeile(line);
|
||||
// const std::regex pieces_regex("IO([0-9]{1,2})");
|
||||
// std::smatch pieces_match;
|
||||
// if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
|
||||
// if (std::regex_match(splitted[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
|
||||
// {
|
||||
// std::string gpioStr = pieces_match[1];
|
||||
ESP_LOGD(TAG, "conf param %s", toUpper(zerlegt[0]).c_str());
|
||||
if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") {
|
||||
ESP_LOGD(TAG, "conf param %s", toUpper(splitted[0]).c_str());
|
||||
if (toUpper(splitted[0]) == "MAINTOPICMQTT") {
|
||||
// ESP_LOGD(TAG, "MAINTOPICMQTT found");
|
||||
// mainTopicMQTT = zerlegt[1];
|
||||
} else if ((zerlegt[0].rfind("IO", 0) == 0) && (zerlegt.size() >= 6))
|
||||
// mainTopicMQTT = splitted[1];
|
||||
} else if ((splitted[0].rfind("IO", 0) == 0) && (splitted.size() >= 6))
|
||||
{
|
||||
ESP_LOGI(TAG,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str());
|
||||
std::string gpioStr = zerlegt[0].substr(2, 2);
|
||||
ESP_LOGI(TAG,"Enable GP%s in %s mode", splitted[0].c_str(), splitted[1].c_str());
|
||||
std::string gpioStr = splitted[0].substr(2, 2);
|
||||
gpio_num_t gpioNr = (gpio_num_t)atoi(gpioStr.c_str());
|
||||
gpio_pin_mode_t pinMode = resolvePinMode(toLower(zerlegt[1]));
|
||||
gpio_int_type_t intType = resolveIntType(toLower(zerlegt[2]));
|
||||
uint16_t dutyResolution = (uint8_t)atoi(zerlegt[3].c_str());
|
||||
gpio_pin_mode_t pinMode = resolvePinMode(toLower(splitted[1]));
|
||||
gpio_int_type_t intType = resolveIntType(toLower(splitted[2]));
|
||||
uint16_t dutyResolution = (uint8_t)atoi(splitted[3].c_str());
|
||||
#ifdef ENABLE_MQTT
|
||||
bool mqttEnabled = toLower(zerlegt[4]) == "true";
|
||||
bool mqttEnabled = toLower(splitted[4]) == "true";
|
||||
#endif // ENABLE_MQTT
|
||||
bool httpEnabled = toLower(zerlegt[5]) == "true";
|
||||
bool httpEnabled = toLower(splitted[5]) == "true";
|
||||
char gpioName[100];
|
||||
if (zerlegt.size() >= 7) {
|
||||
strcpy(gpioName, trim(zerlegt[6]).c_str());
|
||||
if (splitted.size() >= 7) {
|
||||
strcpy(gpioName, trim(splitted[6]).c_str());
|
||||
} else {
|
||||
sprintf(gpioName, "GPIO%d", gpioNr);
|
||||
}
|
||||
@@ -390,28 +386,28 @@ bool GpioHandler::readConfig()
|
||||
registerISR = true;
|
||||
}
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDNUMBERS")
|
||||
if (toUpper(splitted[0]) == "LEDNUMBERS")
|
||||
{
|
||||
LEDNumbers = stoi(zerlegt[1]);
|
||||
LEDNumbers = stoi(splitted[1]);
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDCOLOR")
|
||||
if (toUpper(splitted[0]) == "LEDCOLOR")
|
||||
{
|
||||
uint8_t _r, _g, _b;
|
||||
_r = stoi(zerlegt[1]);
|
||||
_g = stoi(zerlegt[2]);
|
||||
_b = stoi(zerlegt[3]);
|
||||
_r = stoi(splitted[1]);
|
||||
_g = stoi(splitted[2]);
|
||||
_b = stoi(splitted[3]);
|
||||
|
||||
LEDColor = Rgb{_r, _g, _b};
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDTYPE")
|
||||
if (toUpper(splitted[0]) == "LEDTYPE")
|
||||
{
|
||||
if (zerlegt[1] == "WS2812")
|
||||
if (splitted[1] == "WS2812")
|
||||
LEDType = LED_WS2812;
|
||||
if (zerlegt[1] == "WS2812B")
|
||||
if (splitted[1] == "WS2812B")
|
||||
LEDType = LED_WS2812B;
|
||||
if (zerlegt[1] == "SK6812")
|
||||
if (splitted[1] == "SK6812")
|
||||
LEDType = LED_SK6812;
|
||||
if (zerlegt[1] == "WS2813")
|
||||
if (splitted[1] == "WS2813")
|
||||
LEDType = LED_WS2813;
|
||||
}
|
||||
}
|
||||
@@ -696,6 +692,7 @@ void gpio_handler_deinit() {
|
||||
void gpio_handler_destroy()
|
||||
{
|
||||
if (gpioHandler != NULL) {
|
||||
gpio_handler_deinit();
|
||||
delete gpioHandler;
|
||||
gpioHandler = NULL;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVER_GPIO_H
|
||||
#define SERVER_GPIO_H
|
||||
|
||||
@@ -9,11 +11,6 @@
|
||||
|
||||
#include "SmartLeds.h"
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
|
||||
// wenn __LEDGLOBAL definiert ist, wird eine globale Variable für die LED-Ansteuerung verwendet, ansonsten lokal und jedesmal neu
|
||||
#define __LEDGLOBAL
|
||||
|
||||
typedef enum {
|
||||
GPIO_PIN_MODE_DISABLED = 0x0,
|
||||
GPIO_PIN_MODE_INPUT = 0x1,
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "server_ota.h"
|
||||
#include "server_GPIO.h"
|
||||
|
||||
|
||||
#define BOARD_ESP32CAM_AITHINKER
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <esp_event.h>
|
||||
#include <esp_log.h>
|
||||
@@ -28,45 +26,8 @@
|
||||
|
||||
#include "esp_camera.h"
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
#define USE_PWM_LEDFLASH
|
||||
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
|
||||
//// PWM für Flash-LED
|
||||
#define LEDC_TIMER LEDC_TIMER_1 // LEDC_TIMER_0
|
||||
#define LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_OUTPUT_IO (4) // Define the output GPIO
|
||||
#define LEDC_CHANNEL LEDC_CHANNEL_1
|
||||
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
|
||||
//#define LEDC_DUTY (195) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095
|
||||
#define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN 32
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 0
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 21
|
||||
#define CAM_PIN_D2 19
|
||||
#define CAM_PIN_D1 18
|
||||
#define CAM_PIN_D0 5
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#include "driver/ledc.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
static const char *TAG = "CAM";
|
||||
|
||||
@@ -90,8 +51,8 @@ static camera_config_t camera_config = {
|
||||
.pin_pclk = CAM_PIN_PCLK,
|
||||
|
||||
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
|
||||
.xclk_freq_hz = 20000000, // Orginalwert
|
||||
// .xclk_freq_hz = 5000000, // Test, um die Bildfehler los zu werden !!!! Hängt in Version 9.2 !!!!
|
||||
.xclk_freq_hz = 20000000, // Orginal value
|
||||
// .xclk_freq_hz = 5000000, // Test to get rid of the image errors !!!! Hangs in version 9.2 !!!!
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
@@ -101,18 +62,16 @@ static camera_config_t camera_config = {
|
||||
.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_WHEN_EMPTY,
|
||||
.grab_mode = CAMERA_GRAB_LATEST, // erst ab neuer esp32cam-version
|
||||
.grab_mode = CAMERA_GRAB_LATEST, // only from new esp32cam version
|
||||
|
||||
};
|
||||
|
||||
|
||||
#include "driver/ledc.h"
|
||||
|
||||
CCamera Camera;
|
||||
|
||||
#define FLASH_GPIO GPIO_NUM_4
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
uint8_t *demoImage = NULL; // Buffer holding the demo image in bytes
|
||||
|
||||
#define DEMO_IMAGE_SIZE 30000 // Max size of demo image in bytes
|
||||
|
||||
typedef struct {
|
||||
httpd_req_t *req;
|
||||
@@ -120,6 +79,21 @@ typedef struct {
|
||||
} jpg_chunking_t;
|
||||
|
||||
|
||||
bool CCamera::testCamera(void) {
|
||||
bool success;
|
||||
camera_fb_t *fb = esp_camera_fb_get();
|
||||
if (fb) {
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
esp_camera_fb_return(fb);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void CCamera::ledc_init(void)
|
||||
{
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
@@ -222,39 +196,17 @@ void CCamera::SetQualitySize(int qual, framesize_t resol)
|
||||
image_height = 480;
|
||||
image_width = 640;
|
||||
}
|
||||
// No higher Mode than VGA, damit der Kameraspeicher ausreicht.
|
||||
/*
|
||||
if (resol == FRAMESIZE_SVGA)
|
||||
{
|
||||
image_height = 600;
|
||||
image_width = 800;
|
||||
}
|
||||
if (resol == FRAMESIZE_XGA)
|
||||
{
|
||||
image_height = 768;
|
||||
image_width = 1024;
|
||||
}
|
||||
if (resol == FRAMESIZE_SXGA)
|
||||
{
|
||||
image_height = 1024;
|
||||
image_width = 1280;
|
||||
}
|
||||
if (resol == FRAMESIZE_UXGA)
|
||||
{
|
||||
image_height = 1200;
|
||||
image_width = 1600;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CCamera::EnableAutoExposure(int flashdauer)
|
||||
void CCamera::EnableAutoExposure(int flash_duration)
|
||||
{
|
||||
ESP_LOGD(TAG, "EnableAutoExposure");
|
||||
LEDOnOff(true);
|
||||
if (flashdauer > 0)
|
||||
if (flash_duration > 0)
|
||||
LightOnOff(true);
|
||||
const TickType_t xDelay = flashdauer / portTICK_PERIOD_MS;
|
||||
const TickType_t xDelay = flash_duration / portTICK_PERIOD_MS;
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
@@ -278,23 +230,20 @@ void CCamera::EnableAutoExposure(int flashdauer)
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
isFixedExposure = true;
|
||||
waitbeforepicture_org = flashdauer;
|
||||
waitbeforepicture_org = flash_duration;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
{
|
||||
string ftype;
|
||||
|
||||
uint8_t *zwischenspeicher = NULL;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start");
|
||||
#endif
|
||||
|
||||
_Image->EmptyImage(); //Delete previous stored raw image -> black image
|
||||
|
||||
LEDOnOff(true);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start");
|
||||
#endif
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
LightOnOff(true);
|
||||
@@ -302,18 +251,18 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn");
|
||||
#endif
|
||||
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAG, "CaptureToBasisImage: Capture Failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
|
||||
ESP_LOGE(TAG, "CaptureToBasisImage: Capture Failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "is not working anymore (CCamera::CaptureToBasisImage) - most probably caused by a hardware problem (instablility, ...). "
|
||||
"System will reboot.");
|
||||
doReboot();
|
||||
@@ -321,20 +270,18 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int _size = fb->len;
|
||||
zwischenspeicher = (uint8_t*) malloc(_size);
|
||||
if (!zwischenspeicher)
|
||||
{
|
||||
ESP_LOGE(TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
if (demoMode) { // Use images stored on SD-Card instead of camera image
|
||||
/* Replace Framebuffer with image from SD-Card */
|
||||
loadNextDemoImage(fb);
|
||||
}
|
||||
for (int i = 0; i < _size; ++i)
|
||||
*(zwischenspeicher + i) = *(fb->buf + i);
|
||||
|
||||
CImageBasis* _zwImage = new CImageBasis();
|
||||
_zwImage->LoadFromMemory(fb->buf, fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get");
|
||||
#endif
|
||||
|
||||
LEDOnOff(false);
|
||||
|
||||
@@ -344,15 +291,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
// TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
// vTaskDelay( xDelay ); // wait for power to recover
|
||||
|
||||
uint8_t * buf = NULL;
|
||||
|
||||
CImageBasis _zwImage;
|
||||
_zwImage.LoadFromMemory(zwischenspeicher, _size);
|
||||
free(zwischenspeicher);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LoadFromMemory");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LoadFromMemory");
|
||||
#endif
|
||||
|
||||
stbi_uc* p_target;
|
||||
stbi_uc* p_source;
|
||||
@@ -360,31 +301,27 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
int width = image_width;
|
||||
int height = image_height;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
|
||||
_zw = _zw + " _zwImage: " + std::to_string((int) _zwImage.rgb_image) + " Size: " + std::to_string(_zwImage.width) + ", " + std::to_string(_zwImage.height);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
|
||||
_zw = _zw + " _zwImage: " + std::to_string((int) _zwImage->rgb_image) + " Size: " + std::to_string(_zwImage->width) + ", " + std::to_string(_zwImage->height);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
#endif
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
p_target = _Image->rgb_image + (channels * (y * width + x));
|
||||
p_source = _zwImage.rgb_image + (channels * (y * width + x));
|
||||
p_source = _zwImage->rgb_image + (channels * (y * width + x));
|
||||
p_target[0] = p_source[0];
|
||||
p_target[1] = p_source[1];
|
||||
p_target[2] = p_source[2];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After Copy To Target");
|
||||
#endif
|
||||
delete _zwImage;
|
||||
|
||||
free(buf);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -394,7 +331,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
{
|
||||
string ftype;
|
||||
|
||||
LEDOnOff(true); // Abgeschaltet, um Strom zu sparen !!!!!!
|
||||
LEDOnOff(true); // Switched off to save power !
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
@@ -418,21 +355,21 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
}
|
||||
LEDOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
#endif
|
||||
|
||||
nm = FormatFileName(nm);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Save Camera to: %s", nm.c_str());
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Save Camera to: %s", nm.c_str());
|
||||
#endif
|
||||
|
||||
ftype = toUpper(getFileType(nm));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filetype: %s", ftype.c_str());
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filetype: %s", ftype.c_str());
|
||||
#endif
|
||||
|
||||
uint8_t * buf = NULL;
|
||||
size_t buf_len = 0;
|
||||
@@ -457,7 +394,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
}
|
||||
}
|
||||
|
||||
FILE * fp = OpenFileAndWait(nm.c_str(), "wb");
|
||||
FILE * fp = fopen(nm.c_str(), "wb");
|
||||
if (fp == NULL) /* If an error occurs during the file creation */
|
||||
{
|
||||
fprintf(stderr, "fopen() failed for '%s'\n", nm.c_str());
|
||||
@@ -520,14 +457,23 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
}
|
||||
|
||||
if(res == ESP_OK){
|
||||
if(fb->format == PIXFORMAT_JPEG){
|
||||
fb_len = fb->len;
|
||||
if (demoMode) { // Use images stored on SD-Card instead of camera image
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using Demo image!");
|
||||
/* Replace Framebuffer with image from SD-Card */
|
||||
loadNextDemoImage(fb);
|
||||
|
||||
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
|
||||
} else {
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
fb_len = jchunk.len;
|
||||
}
|
||||
else {
|
||||
if(fb->format == PIXFORMAT_JPEG){
|
||||
fb_len = fb->len;
|
||||
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
|
||||
} else {
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
fb_len = jchunk.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
@@ -637,7 +583,7 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
|
||||
if (qual < 0)
|
||||
qual = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -706,3 +652,86 @@ bool CCamera::getCameraInitSuccessful()
|
||||
{
|
||||
return CameraInitSuccessful;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> demoFiles;
|
||||
|
||||
void CCamera::useDemoMode()
|
||||
{
|
||||
char line[50];
|
||||
|
||||
FILE *fd = fopen("/sdcard/demo/files.txt", "r");
|
||||
if (!fd) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can not start Demo mode, the folder '/sdcard/demo/' does not contain the needed files!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "See Details on https://jomjol.github.io/AI-on-the-edge-device-docs/Demo-Mode!");
|
||||
return;
|
||||
}
|
||||
|
||||
demoImage = (uint8_t*)malloc(DEMO_IMAGE_SIZE);
|
||||
if (demoImage == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to acquire required memory for demo image!");
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
demoFiles.push_back(line);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Using Demo mode (" + std::to_string(demoFiles.size()) +
|
||||
" files) instead of real camera image!");
|
||||
|
||||
for (auto file : demoFiles) {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, file);
|
||||
}
|
||||
|
||||
demoMode = true;
|
||||
}
|
||||
|
||||
|
||||
bool CCamera::loadNextDemoImage(camera_fb_t *fb) {
|
||||
char filename[50];
|
||||
int readBytes;
|
||||
long fileSize;
|
||||
|
||||
snprintf(filename, sizeof(filename), "/sdcard/demo/%s", demoFiles[getCountFlowRounds() % demoFiles.size()].c_str());
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using " + std::string(filename) + " as demo image");
|
||||
|
||||
/* Inject saved image */
|
||||
|
||||
FILE * fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filename) +"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
fileSize = GetFileSize(filename);
|
||||
if (fileSize > DEMO_IMAGE_SIZE) {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "Demo Image (%d bytes) is larger than provided buffer (%d bytes)!",
|
||||
(int)fileSize, DEMO_IMAGE_SIZE);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, std::string(buf));
|
||||
return false;
|
||||
}
|
||||
|
||||
readBytes = fread(demoImage, 1, DEMO_IMAGE_SIZE, fp);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "read " + std::to_string(readBytes) + " bytes");
|
||||
fclose(fp);
|
||||
|
||||
fb->buf = demoImage; // Update pointer
|
||||
fb->len = readBytes;
|
||||
// ToDo do we also need to set height, width, format and timestamp?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
long CCamera::GetFileSize(std::string filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
long rc = stat(filename.c_str(), &stat_buf);
|
||||
return rc == 0 ? stat_buf.st_size : -1;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSCONTROLLCAMERA_H
|
||||
#define CLASSCONTROLLCAMERA_H
|
||||
|
||||
@@ -11,10 +13,7 @@
|
||||
#include <string>
|
||||
#include <esp_http_server.h>
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
class CCamera {
|
||||
protected:
|
||||
@@ -27,6 +26,10 @@ class CCamera {
|
||||
|
||||
void ledc_init(void);
|
||||
bool CameraInitSuccessful = false;
|
||||
bool demoMode = false;
|
||||
|
||||
bool loadNextDemoImage(camera_fb_t *fb);
|
||||
long GetFileSize(std::string filename);
|
||||
|
||||
public:
|
||||
int image_height, image_width;
|
||||
@@ -41,10 +44,11 @@ class CCamera {
|
||||
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
|
||||
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
|
||||
void SetLEDIntensity(float _intrel);
|
||||
|
||||
void EnableAutoExposure(int flashdauer);
|
||||
bool testCamera(void);
|
||||
void EnableAutoExposure(int flash_duration);
|
||||
bool getCameraInitSuccessful();
|
||||
|
||||
void useDemoMode(void);
|
||||
|
||||
|
||||
framesize_t TextToFramesize(const char * text);
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _IMG_CONVERTERS_H_
|
||||
#define _IMG_CONVERTERS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_camera.h"
|
||||
|
||||
typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG buffer
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to BMP buffer
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to BMP buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to RGB888 buffer (used for face detection)
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param format Format of the source image
|
||||
* @param rgb_buf Pointer to the output buffer (width * height * 3)
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IMG_CONVERTERS_H_ */
|
||||
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Sensor abstraction layer.
|
||||
*
|
||||
*/
|
||||
#ifndef __SENSOR_H__
|
||||
#define __SENSOR_H__
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OV9650_PID = 0x96,
|
||||
OV7725_PID = 0x77,
|
||||
OV2640_PID = 0x26,
|
||||
OV3660_PID = 0x3660,
|
||||
OV5640_PID = 0x5640,
|
||||
OV7670_PID = 0x76,
|
||||
NT99141_PID = 0x1410,
|
||||
GC2145_PID = 0x2145,
|
||||
GC032A_PID = 0x232a,
|
||||
GC0308_PID = 0x9b,
|
||||
} camera_pid_t;
|
||||
|
||||
typedef enum {
|
||||
CAMERA_OV7725,
|
||||
CAMERA_OV2640,
|
||||
CAMERA_OV3660,
|
||||
CAMERA_OV5640,
|
||||
CAMERA_OV7670,
|
||||
CAMERA_NT99141,
|
||||
CAMERA_GC2145,
|
||||
CAMERA_GC032A,
|
||||
CAMERA_GC0308,
|
||||
CAMERA_MODEL_MAX,
|
||||
CAMERA_NONE,
|
||||
} camera_model_t;
|
||||
|
||||
typedef enum {
|
||||
OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1
|
||||
OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1
|
||||
GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
} camera_sccb_addr_t;
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
PIXFORMAT_YUV422, // 2BPP/YUV422
|
||||
PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
|
||||
PIXFORMAT_JPEG, // JPEG/COMPRESSED
|
||||
PIXFORMAT_RGB888, // 3BPP/RGB888
|
||||
PIXFORMAT_RAW, // RAW
|
||||
PIXFORMAT_RGB444, // 3BP2P/RGB444
|
||||
PIXFORMAT_RGB555, // 3BP2P/RGB555
|
||||
} pixformat_t;
|
||||
|
||||
typedef enum {
|
||||
FRAMESIZE_96X96, // 96x96
|
||||
FRAMESIZE_QQVGA, // 160x120
|
||||
FRAMESIZE_QCIF, // 176x144
|
||||
FRAMESIZE_HQVGA, // 240x176
|
||||
FRAMESIZE_240X240, // 240x240
|
||||
FRAMESIZE_QVGA, // 320x240
|
||||
FRAMESIZE_CIF, // 400x296
|
||||
FRAMESIZE_HVGA, // 480x320
|
||||
FRAMESIZE_VGA, // 640x480
|
||||
FRAMESIZE_SVGA, // 800x600
|
||||
FRAMESIZE_XGA, // 1024x768
|
||||
FRAMESIZE_HD, // 1280x720
|
||||
FRAMESIZE_SXGA, // 1280x1024
|
||||
FRAMESIZE_UXGA, // 1600x1200
|
||||
// 3MP Sensors
|
||||
FRAMESIZE_FHD, // 1920x1080
|
||||
FRAMESIZE_P_HD, // 720x1280
|
||||
FRAMESIZE_P_3MP, // 864x1536
|
||||
FRAMESIZE_QXGA, // 2048x1536
|
||||
// 5MP Sensors
|
||||
FRAMESIZE_QHD, // 2560x1440
|
||||
FRAMESIZE_WQXGA, // 2560x1600
|
||||
FRAMESIZE_P_FHD, // 1080x1920
|
||||
FRAMESIZE_QSXGA, // 2560x1920
|
||||
FRAMESIZE_INVALID
|
||||
} framesize_t;
|
||||
|
||||
typedef struct {
|
||||
const camera_model_t model;
|
||||
const char *name;
|
||||
const camera_sccb_addr_t sccb_addr;
|
||||
const camera_pid_t pid;
|
||||
const framesize_t max_size;
|
||||
const bool support_jpeg;
|
||||
} camera_sensor_info_t;
|
||||
|
||||
typedef enum {
|
||||
ASPECT_RATIO_4X3,
|
||||
ASPECT_RATIO_3X2,
|
||||
ASPECT_RATIO_16X10,
|
||||
ASPECT_RATIO_5X3,
|
||||
ASPECT_RATIO_16X9,
|
||||
ASPECT_RATIO_21X9,
|
||||
ASPECT_RATIO_5X4,
|
||||
ASPECT_RATIO_1X1,
|
||||
ASPECT_RATIO_9X16
|
||||
} aspect_ratio_t;
|
||||
|
||||
typedef enum {
|
||||
GAINCEILING_2X,
|
||||
GAINCEILING_4X,
|
||||
GAINCEILING_8X,
|
||||
GAINCEILING_16X,
|
||||
GAINCEILING_32X,
|
||||
GAINCEILING_64X,
|
||||
GAINCEILING_128X,
|
||||
} gainceiling_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t max_width;
|
||||
uint16_t max_height;
|
||||
uint16_t start_x;
|
||||
uint16_t start_y;
|
||||
uint16_t end_x;
|
||||
uint16_t end_y;
|
||||
uint16_t offset_x;
|
||||
uint16_t offset_y;
|
||||
uint16_t total_x;
|
||||
uint16_t total_y;
|
||||
} ratio_settings_t;
|
||||
|
||||
typedef struct {
|
||||
const uint16_t width;
|
||||
const uint16_t height;
|
||||
const aspect_ratio_t aspect_ratio;
|
||||
} resolution_info_t;
|
||||
|
||||
// Resolution table (in sensor.c)
|
||||
extern const resolution_info_t resolution[];
|
||||
// camera sensor table (in sensor.c)
|
||||
extern const camera_sensor_info_t camera_sensor[];
|
||||
|
||||
typedef struct {
|
||||
uint8_t MIDH;
|
||||
uint8_t MIDL;
|
||||
uint16_t PID;
|
||||
uint8_t VER;
|
||||
} sensor_id_t;
|
||||
|
||||
typedef struct {
|
||||
framesize_t framesize;//0 - 10
|
||||
bool scale;
|
||||
bool binning;
|
||||
uint8_t quality;//0 - 63
|
||||
int8_t brightness;//-2 - 2
|
||||
int8_t contrast;//-2 - 2
|
||||
int8_t saturation;//-2 - 2
|
||||
int8_t sharpness;//-2 - 2
|
||||
uint8_t denoise;
|
||||
uint8_t special_effect;//0 - 6
|
||||
uint8_t wb_mode;//0 - 4
|
||||
uint8_t awb;
|
||||
uint8_t awb_gain;
|
||||
uint8_t aec;
|
||||
uint8_t aec2;
|
||||
int8_t ae_level;//-2 - 2
|
||||
uint16_t aec_value;//0 - 1200
|
||||
uint8_t agc;
|
||||
uint8_t agc_gain;//0 - 30
|
||||
uint8_t gainceiling;//0 - 6
|
||||
uint8_t bpc;
|
||||
uint8_t wpc;
|
||||
uint8_t raw_gma;
|
||||
uint8_t lenc;
|
||||
uint8_t hmirror;
|
||||
uint8_t vflip;
|
||||
uint8_t dcw;
|
||||
uint8_t colorbar;
|
||||
} camera_status_t;
|
||||
|
||||
typedef struct _sensor sensor_t;
|
||||
typedef struct _sensor {
|
||||
sensor_id_t id; // Sensor ID.
|
||||
uint8_t slv_addr; // Sensor I2C slave address.
|
||||
pixformat_t pixformat;
|
||||
camera_status_t status;
|
||||
int xclk_freq_hz;
|
||||
|
||||
// Sensor function pointers
|
||||
int (*init_status) (sensor_t *sensor);
|
||||
int (*reset) (sensor_t *sensor);
|
||||
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
|
||||
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
|
||||
int (*set_contrast) (sensor_t *sensor, int level);
|
||||
int (*set_brightness) (sensor_t *sensor, int level);
|
||||
int (*set_saturation) (sensor_t *sensor, int level);
|
||||
int (*set_sharpness) (sensor_t *sensor, int level);
|
||||
int (*set_denoise) (sensor_t *sensor, int level);
|
||||
int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling);
|
||||
int (*set_quality) (sensor_t *sensor, int quality);
|
||||
int (*set_colorbar) (sensor_t *sensor, int enable);
|
||||
int (*set_whitebal) (sensor_t *sensor, int enable);
|
||||
int (*set_gain_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_exposure_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_hmirror) (sensor_t *sensor, int enable);
|
||||
int (*set_vflip) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_aec2) (sensor_t *sensor, int enable);
|
||||
int (*set_awb_gain) (sensor_t *sensor, int enable);
|
||||
int (*set_agc_gain) (sensor_t *sensor, int gain);
|
||||
int (*set_aec_value) (sensor_t *sensor, int gain);
|
||||
|
||||
int (*set_special_effect) (sensor_t *sensor, int effect);
|
||||
int (*set_wb_mode) (sensor_t *sensor, int mode);
|
||||
int (*set_ae_level) (sensor_t *sensor, int level);
|
||||
|
||||
int (*set_dcw) (sensor_t *sensor, int enable);
|
||||
int (*set_bpc) (sensor_t *sensor, int enable);
|
||||
int (*set_wpc) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_raw_gma) (sensor_t *sensor, int enable);
|
||||
int (*set_lenc) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*get_reg) (sensor_t *sensor, int reg, int mask);
|
||||
int (*set_reg) (sensor_t *sensor, int reg, int mask, int value);
|
||||
int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning);
|
||||
int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk);
|
||||
int (*set_xclk) (sensor_t *sensor, int timer, int xclk);
|
||||
} sensor_t;
|
||||
|
||||
camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SENSOR_H__ */
|
||||
@@ -9,16 +9,13 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "server_cam";
|
||||
|
||||
#define SCRATCH_BUFSIZE2 8192
|
||||
char scratch2[SCRATCH_BUFSIZE2];
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
void PowerResetCamera(){
|
||||
|
||||
|
||||
void PowerResetCamera()
|
||||
{
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
gpio_config_t conf;
|
||||
conf.intr_type = GPIO_INTR_DISABLE;
|
||||
@@ -51,7 +48,7 @@ esp_err_t handler_lightOn(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera Light On API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lighton not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -78,7 +75,7 @@ esp_err_t handler_lightOff(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera Light Off API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lightoff not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -120,16 +117,16 @@ esp_err_t handler_capture(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera Capture API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_capture_with_ligth(httpd_req_t *req)
|
||||
esp_err_t handler_capture_with_light(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_ligth - Start");
|
||||
LogFile.WriteHeapInfo("handler_capture_with_light - Start");
|
||||
#endif
|
||||
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
@@ -173,14 +170,14 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req)
|
||||
Camera.LightOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_ligth - Done");
|
||||
LogFile.WriteHeapInfo("handler_capture_with_light - Done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera Capture + flashlight API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture_with_flashlight not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
@@ -251,7 +248,7 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera Capture + save API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /save not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
@@ -282,7 +279,7 @@ void register_server_camera_uri(httpd_handle_t server)
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/capture_with_flashlight";
|
||||
camuri.handler = handler_capture_with_ligth;
|
||||
camuri.handler = handler_capture_with_light;
|
||||
camuri.user_ctx = NULL;
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef JOMJOL_CONTROLCAMERA_H
|
||||
#define JOMJOL_CONTROLCAMERA_H
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ extern "C" {
|
||||
#include <esp_spiffs.h>
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#include "defines.h"
|
||||
#include "../../include/defines.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "server_tflite.h"
|
||||
@@ -47,30 +47,15 @@ extern "C" {
|
||||
#include "Helper.h"
|
||||
#include "miniz.h"
|
||||
|
||||
|
||||
static const char *TAG = "OTA FILE";
|
||||
|
||||
/* Max length a file path can have on storage */
|
||||
// #define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
|
||||
#define FILE_PATH_MAX (255)
|
||||
|
||||
/* Max size of an individual file. Make sure this
|
||||
* value is same as that set in upload_script.html */
|
||||
#define MAX_FILE_SIZE (8000*1024) // 8 MB
|
||||
#define MAX_FILE_SIZE_STR "8MB"
|
||||
|
||||
|
||||
/* Scratch buffer size */
|
||||
#define SCRATCH_BUFSIZE 4096
|
||||
|
||||
/* Size of partial log file to return */
|
||||
#define LOGFILE_LAST_PART_BYTES SCRATCH_BUFSIZE * 20 /* 80 kBytes */
|
||||
|
||||
struct file_server_data {
|
||||
/* Base path of file storage */
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
|
||||
/* Scratch buffer for temporary storage during file transfer */
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
char scratch[SERVER_FILER_SCRATCH_BUFSIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -227,16 +212,18 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
/* Send HTML file header */
|
||||
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
if (!readonly) {
|
||||
FILE *fd = OpenFileAndWait("/sdcard/html/upload_script.html", "r");
|
||||
FILE *fd = fopen("/sdcard/html/file_server.html", "r");
|
||||
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
size_t chunksize;
|
||||
do {
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
// ESP_LOGD(TAG, "Chunksize %d", chunksize);
|
||||
if (chunksize > 0){
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -258,11 +245,11 @@ 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,
|
||||
"<table class=\"fixed\" border=\"1\">"
|
||||
"<table id=\"files_table\">"
|
||||
"<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th>");
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size</th>");
|
||||
if (!readonly) {
|
||||
httpd_resp_sendstr_chunk(req, "<th>Delete<br>"
|
||||
httpd_resp_sendstr_chunk(req, "<th>"
|
||||
"<form method=\"post\" action=\"");
|
||||
httpd_resp_sendstr_chunk(req, _zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req,
|
||||
@@ -283,7 +270,19 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
ESP_LOGE(TAG, "Failed to stat %s: %s", entrytype, entry->d_name);
|
||||
continue;
|
||||
}
|
||||
sprintf(entrysize, "%ld", entry_stat.st_size);
|
||||
|
||||
if (entry->d_type == DT_DIR) {
|
||||
strcpy(entrysize, "-\0");
|
||||
}
|
||||
else {
|
||||
if (entry_stat.st_size >= 1024) {
|
||||
sprintf(entrysize, "%ld KiB", entry_stat.st_size / 1024); // kBytes
|
||||
}
|
||||
else {
|
||||
sprintf(entrysize, "%ld B", entry_stat.st_size); // Bytes
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Found %s: %s (%s bytes)", entrytype, entry->d_name, entrysize);
|
||||
|
||||
/* Send chunk of HTML file containing table entries with file name and size */
|
||||
@@ -322,10 +321,10 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
|
||||
*/
|
||||
|
||||
static esp_err_t logfileact_get_full_handler(httpd_req_t *req) {
|
||||
return send_logfile(req, true);
|
||||
@@ -348,22 +347,17 @@ static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req) {
|
||||
static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "data_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
const char* filename = "";
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileNameData();
|
||||
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, currentfilename.c_str(), currentfilename.c_str());
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
fd = fopen(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read existing file: " + std::string(filepath) +"!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(currentfilename) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
@@ -372,7 +366,7 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
// ESP_LOGI(TAG, "Sending file: %s (%ld bytes)...", &filename, file_stat.st_size);
|
||||
set_content_type_from_file(req, filename);
|
||||
set_content_type_from_file(req, currentfilename.c_str());
|
||||
|
||||
if (!send_full_file) { // Send only last part of file
|
||||
ESP_LOGD(TAG, "Sending last %d bytes of the actual datafile!", LOGFILE_LAST_PART_BYTES);
|
||||
@@ -405,7 +399,7 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -434,7 +428,6 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
ESP_LOGI(TAG, "uri: %s", req->uri);
|
||||
@@ -443,12 +436,14 @@ static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileName();
|
||||
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, currentfilename.c_str());
|
||||
|
||||
// Since the log file is still could open for writing, we need to close it first
|
||||
LogFile.CloseLogFileAppendHandle();
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
fd = fopen(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read existing file: " + std::string(filepath) +"!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(currentfilename.c_str()) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
@@ -490,7 +485,7 @@ static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -574,9 +569,9 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fd = OpenFileAndWait(filepath, "r");
|
||||
fd = fopen(filepath, "r");
|
||||
if (!fd) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read existing file: " + std::string(filepath) +"!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filepath) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
@@ -592,7 +587,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -625,6 +620,8 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
FILE *fd = NULL;
|
||||
struct stat file_stat;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
/* Skip leading "/upload" from URI to get filename */
|
||||
/* Note sizeof() counts NULL termination hence the -1 */
|
||||
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
@@ -662,7 +659,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fd = OpenFileAndWait(filepath, "w");
|
||||
fd = fopen(filepath, "w");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to create file: %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
@@ -684,7 +681,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
ESP_LOGI(TAG, "Remaining size: %d", remaining);
|
||||
/* Receive the file part by part into a buffer */
|
||||
if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) {
|
||||
if ((received = httpd_req_recv(req, buf, MIN(remaining, SERVER_FILER_SCRATCH_BUFSIZE))) <= 0) {
|
||||
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
/* Retry if timeout occurred */
|
||||
continue;
|
||||
@@ -775,6 +772,8 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
std::string directory;
|
||||
std::string zw;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
@@ -906,7 +905,7 @@ void delete_all_in_directory(std::string _directory)
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main)
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main, bool _initial_setup)
|
||||
{
|
||||
int i, sort_iter;
|
||||
mz_bool status;
|
||||
@@ -916,13 +915,9 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
char archive_filename[64];
|
||||
std::string zw, ret = "";
|
||||
std::string directory = "";
|
||||
// static const char* s_Test_archive_filename = "testhtml.zip";
|
||||
|
||||
ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION);
|
||||
ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir ZIP: %s", _target_zip.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir BIN: %s", _target_bin.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir main: %s", _main.c_str());
|
||||
|
||||
// Now try to open the archive.
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
@@ -935,11 +930,9 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
|
||||
// Get and print information about each file in the archive.
|
||||
int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
|
||||
ESP_LOGI(TAG, "Numbers of files to be extrated: %d", numberoffiles);
|
||||
|
||||
ESP_LOGI(TAG, "Numbers of files to be extracted: %d", numberoffiles);
|
||||
|
||||
sort_iter = 0;
|
||||
// for (sort_iter = 0; sort_iter < 2; sort_iter++)
|
||||
{
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
|
||||
@@ -977,6 +970,16 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
else
|
||||
{
|
||||
std::string _dir = getDirectory(zw);
|
||||
if ((_dir == "config-initial") && !_initial_setup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dir = "config";
|
||||
std::string _s1 = "config-initial";
|
||||
FindReplace(zw, _s1, _dir);
|
||||
}
|
||||
|
||||
if (_dir.length() > 0)
|
||||
{
|
||||
@@ -995,7 +998,7 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
|
||||
// extrahieren in zwischendatei
|
||||
DeleteFile(filename_zw);
|
||||
FILE* fpTargetFile = OpenFileAndWait(filename_zw.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(filename_zw.c_str(), "wb");
|
||||
uint writtenbytes = fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
@@ -1017,9 +1020,6 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
isokay = isokay && RenameFile(filename_zw, zw);
|
||||
if (!isokay)
|
||||
ESP_LOGE(TAG, "ERROR in Rename \"%s\" to \"%s\"", filename_zw.c_str(), zw.c_str());
|
||||
// isokay = isokay && DeleteFile(filename_zw);
|
||||
// if (!isokay)
|
||||
// ESP_LOGE(TAG, "ERROR in Delete \"%s\"", filename_zw.c_str());
|
||||
|
||||
if (isokay)
|
||||
ESP_LOGI(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
@@ -1094,7 +1094,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
zw = std::string(archive_filename);
|
||||
zw = _target_directory + zw;
|
||||
ESP_LOGD(TAG, "Filename to extract: %s", zw.c_str());
|
||||
FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(zw.c_str(), "wb");
|
||||
fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERFILE_H
|
||||
#define SERVERFILE_H
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include <string>
|
||||
|
||||
void register_server_file_uri(httpd_handle_t server, const char *base_path);
|
||||
|
||||
void unzip(std::string _in_zip_file, std::string _target_directory);
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/");
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/", bool _initial_setup = false);
|
||||
|
||||
|
||||
void delete_all_in_directory(std::string _directory);
|
||||
@@ -13,3 +18,4 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_data_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_numbers_file_handler(httpd_req_t *req);
|
||||
|
||||
#endif //SERVERFILE_H
|
||||
@@ -21,22 +21,27 @@ extern "C" {
|
||||
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
static const char *TAG = "SERVER HELP";
|
||||
|
||||
#define SCRATCH_BUFSIZE 8192
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
char scratch[SERVER_HELPER_SCRATCH_BUFSIZE];
|
||||
|
||||
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
bool endsWith(std::string const &str, std::string const &suffix) {
|
||||
if (str.length() < suffix.length()) {
|
||||
return false;
|
||||
}
|
||||
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
{
|
||||
FILE *fd = OpenFileAndWait(filename.c_str(), "r");
|
||||
FILE *fd = fopen(filename.c_str(), "r");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to read existing file: %s", filename.c_str());
|
||||
ESP_LOGE(TAG, "Failed to read file: %s", filename.c_str());
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
@@ -44,6 +49,21 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
|
||||
ESP_LOGD(TAG, "Sending file: %s ...", filename.c_str());
|
||||
// httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
/* For all files with the following file extention tell
|
||||
the webbrowser to cache them for 24h */
|
||||
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, ".png")) {
|
||||
httpd_resp_set_hdr(req, "Cache-Control", "max-age=86400");
|
||||
}
|
||||
|
||||
set_content_type_from_file(req, filename.c_str());
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
@@ -51,7 +71,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_HELPER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERHELP_H
|
||||
#define SERVERHELP_H
|
||||
|
||||
#include <string>
|
||||
//#include <sys/param.h>
|
||||
#include "esp_http_server.h"
|
||||
@@ -7,4 +12,6 @@ const char* get_path_from_uri(char *dest, const char *base_path, const char *uri
|
||||
|
||||
esp_err_t send_file(httpd_req_t *req, std::string filename);
|
||||
|
||||
esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);
|
||||
esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);
|
||||
|
||||
#endif //SERVERHELP_H
|
||||
@@ -32,31 +32,25 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
#include "ClassControllCamera.h"
|
||||
#include "connect_wlan.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
#define BUFFSIZE 1024
|
||||
#define HASH_LEN 32 /* SHA-256 digest length */
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
/*an ota data write buffer ready to write to the flash*/
|
||||
static char ota_write_data[BUFFSIZE + 1] = { 0 };
|
||||
static char ota_write_data[SERVER_OTA_SCRATCH_BUFSIZE + 1] = { 0 };
|
||||
|
||||
|
||||
#define OTA_URL_SIZE 256
|
||||
static const char *TAG = "OTA";
|
||||
|
||||
esp_err_t handler_reboot(httpd_req_t *req);
|
||||
static bool ota_update_task(std::string fn);
|
||||
|
||||
std::string _file_name_update;
|
||||
|
||||
bool initial_setup = false;
|
||||
|
||||
|
||||
static void infinite_loop(void)
|
||||
@@ -84,7 +78,7 @@ void task_do_Update_ZIP(void *pvParameter)
|
||||
out = "/sdcard/html";
|
||||
outbin = "/sdcard/firmware";
|
||||
|
||||
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/");
|
||||
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/", "/sdcard/", initial_setup);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Files unzipped.");
|
||||
|
||||
if (retfirmware.length() > 0)
|
||||
@@ -92,8 +86,15 @@ void task_do_Update_ZIP(void *pvParameter)
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Found firmware.bin");
|
||||
ota_update_task(retfirmware);
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doReboot();
|
||||
doRebootOTA();
|
||||
} else if (filetype == "BIN")
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Do firmware update - file: " + _file_name_update);
|
||||
ota_update_task(_file_name_update);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doRebootOTA();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -114,22 +115,27 @@ void CheckUpdate()
|
||||
char zw[1024] = "";
|
||||
fgets(zw, 1024, pfile);
|
||||
_file_name_update = std::string(zw);
|
||||
if (fgets(zw, 1024, pfile))
|
||||
{
|
||||
std::string _szw = std::string(zw);
|
||||
if (_szw == "init")
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Inital Setup triggered.");
|
||||
initial_setup = true; }
|
||||
}
|
||||
|
||||
fclose(pfile);
|
||||
DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update during boot triggered - Update File: " + _file_name_update);
|
||||
|
||||
|
||||
BaseType_t xReturned;
|
||||
int _i = configMINIMAL_STACK_SIZE;
|
||||
xReturned = xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
while(1) { // wait until reboot within task_do_Update_ZIP
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static bool ota_update_task(std::string fn)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -163,13 +169,13 @@ static bool ota_update_task(std::string fn)
|
||||
|
||||
int data_read;
|
||||
|
||||
FILE* f = OpenFileAndWait(fn.c_str(), "rb"); // vorher nur "r"
|
||||
FILE* f = fopen(fn.c_str(), "rb"); // previously only "r
|
||||
|
||||
if (f == NULL) { // File does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
data_read = fread(ota_write_data, 1, BUFFSIZE, f);
|
||||
data_read = fread(ota_write_data, 1, SERVER_OTA_SCRATCH_BUFSIZE, f);
|
||||
|
||||
while (data_read > 0) {
|
||||
if (data_read < 0) {
|
||||
@@ -239,7 +245,7 @@ static bool ota_update_task(std::string fn)
|
||||
break;
|
||||
}
|
||||
}
|
||||
data_read = fread(ota_write_data, 1, BUFFSIZE, f);
|
||||
data_read = fread(ota_write_data, 1, SERVER_OTA_SCRATCH_BUFSIZE, f);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
@@ -282,6 +288,7 @@ static bool diagnostic(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CheckOTAUpdate(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Start CheckOTAUpdateCheck...");
|
||||
@@ -354,7 +361,6 @@ void CheckOTAUpdate(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -391,7 +397,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "Delete Default File: %s", fn.c_str());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
if (_task.compare("emptyfirmwaredir") == 0)
|
||||
{
|
||||
@@ -436,7 +442,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
if (filetype == "ZIP")
|
||||
if ((filetype == "ZIP") || (filetype == "BIN"))
|
||||
{
|
||||
FILE *pfile;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update for reboot.");
|
||||
@@ -450,32 +456,9 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "Send reboot");
|
||||
return ESP_OK;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
std::string in, out, outbin, zw, retfirmware;
|
||||
|
||||
out = "/sdcard/html";
|
||||
outbin = "/sdcard/firmware";
|
||||
|
||||
retfirmware = unzip_new(fn, out+"/", outbin+"/");
|
||||
|
||||
if (retfirmware.length() > 0)
|
||||
{
|
||||
filetype = "BIN";
|
||||
fn = retfirmware;
|
||||
}
|
||||
else
|
||||
{
|
||||
zw = "Web Interface Update Successfull!\nNo reboot necessary.\n";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (filetype == "BIN")
|
||||
{
|
||||
const char* resp_str;
|
||||
@@ -500,7 +483,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
std::string zw = "Update failed - no valid file specified (zip, bin, tfl, tlite)!";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
@@ -571,68 +554,118 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
}
|
||||
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Done");
|
||||
#endif
|
||||
*/
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Done");
|
||||
#endif
|
||||
|
||||
void hard_restart() {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void hard_restart()
|
||||
{
|
||||
esp_task_wdt_init(1,true);
|
||||
esp_task_wdt_add(NULL);
|
||||
while(true);
|
||||
}
|
||||
|
||||
void task_reboot(void *pvParameter)
|
||||
|
||||
void task_reboot(void *KillAutoFlow)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
// write a reboot, to identify a reboot by purpouse
|
||||
FILE* pfile = fopen("/sdcard/reboot.txt", "w");
|
||||
std::string _s_zw= "reboot";
|
||||
fwrite(_s_zw.c_str(), strlen(_s_zw.c_str()), 1, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
|
||||
if ((bool)KillAutoFlow) {
|
||||
KillTFliteTasks(); // Kill autoflow task if executed in extra task, if not don't kill parent task
|
||||
}
|
||||
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
/* Stop service tasks */
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTdestroy_client(true);
|
||||
#endif //ENABLE_MQTT
|
||||
gpio_handler_destroy();
|
||||
esp_camera_deinit();
|
||||
WIFIDestroy();
|
||||
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
hard_restart(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated)
|
||||
|
||||
ESP_LOGE(TAG, "Reboot failed!");
|
||||
vTaskDelete(NULL); //Delete this task if it comes to this point
|
||||
}
|
||||
|
||||
void doReboot(){
|
||||
|
||||
void doReboot()
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reboot triggered by Software (5s).");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
|
||||
xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
|
||||
// KillTFliteTasks(); // kills itself
|
||||
gpio_handler_destroy();
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTdestroy_client();
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 3, (void*) true, 10, NULL);
|
||||
if( xReturned != pdPASS )
|
||||
{
|
||||
ESP_LOGE(TAG, "task_reboot not created -> force reboot without killing flow");
|
||||
task_reboot((void*) false);
|
||||
}
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS); // Prevent serving web client fetch response until system is shuting down
|
||||
}
|
||||
|
||||
|
||||
void doRebootOTA()
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
|
||||
|
||||
esp_camera_deinit();
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
hard_restart(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_reboot(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_reboot");
|
||||
ESP_LOGI(TAG, "!!! System will restart within 5 sec!!!");
|
||||
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload in around 25..60s<br>(in case of a firmware update it can take up to 180s).<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{parent.location.href=('/index.html');})}, 1000);</script>";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
std::string response =
|
||||
"<html><head><script>"
|
||||
"function m(h) {"
|
||||
"document.getElementById('t').innerHTML=h;"
|
||||
"setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h;"
|
||||
"fetch('reboot_page.html',{mode: 'no-cors'}).then(r=>{parent.location.href=('index.html');})}, 1000);"
|
||||
"}</script></head></html><body style='font-family: arial'><h3 id=t></h3>"
|
||||
"<script>m('Rebooting!<br>The page will automatically reload in around 25..60s.<br><br>');</script>"
|
||||
"</body></html>";
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, response.c_str(), strlen(response.c_str()));
|
||||
|
||||
doReboot();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server)
|
||||
{
|
||||
ESP_LOGI(TAG, "Registering URI handlers");
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVEROTA_H
|
||||
#define SERVEROTA_H
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <esp_http_server.h>
|
||||
@@ -8,6 +13,8 @@
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server);
|
||||
void CheckOTAUpdate();
|
||||
void doReboot();
|
||||
void doRebootOTA();
|
||||
void hard_restart();
|
||||
void CheckUpdate();
|
||||
static bool ota_update_task(std::string fn);
|
||||
|
||||
#endif //SERVEROTA_H
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "CLASS";
|
||||
|
||||
@@ -105,7 +106,7 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))
|
||||
{
|
||||
*rt = "";
|
||||
if (!fgets(zw, 1024, pfile))
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOW_H
|
||||
#define CLASSFLOW_H
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -9,10 +12,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define LOGFILE_TIME_FORMAT "%Y%m%d-%H%M%S"
|
||||
#define LOGFILE_TIME_FORMAT_DATE_EXTR substr(0, 8)
|
||||
#define LOGFILE_TIME_FORMAT_HOUR_EXTR substr(9, 2)
|
||||
|
||||
struct HTMLInfo
|
||||
{
|
||||
float val;
|
||||
@@ -52,3 +51,4 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#endif //CLASSFLOW_H
|
||||
@@ -1,18 +1,18 @@
|
||||
#include "ClassFlowAlignment.h"
|
||||
#include "ClassFlowMakeImage.h"
|
||||
#include "ClassFlow.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
#include "CRotateImage.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
static const char *TAG = "ALIGN";
|
||||
|
||||
bool AlignmentExtendedDebugging = true;
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
@@ -30,11 +30,15 @@ void ClassFlowAlignment::SetInitialParameter(void)
|
||||
AlignAndCutImage = NULL;
|
||||
ImageBasis = NULL;
|
||||
ImageTMP = NULL;
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
AlgROI = (ImageData*)heap_caps_malloc(sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
#endif
|
||||
previousElement = NULL;
|
||||
disabled = false;
|
||||
SAD_criteria = 0.05;
|
||||
}
|
||||
|
||||
|
||||
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
{
|
||||
SetInitialParameter();
|
||||
@@ -48,9 +52,9 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImageBasis) // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN
|
||||
if (!ImageBasis) // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
|
||||
{
|
||||
if (AlignmentExtendedDebugging) ESP_LOGD(TAG, "CImageBasis had to be created");
|
||||
ESP_LOGD(TAG, "CImageBasis had to be created");
|
||||
ImageBasis = new CImageBasis(namerawimage);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +62,7 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
|
||||
bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
int suchex = 40;
|
||||
int suchey = 40;
|
||||
int alg_algo = 0;
|
||||
@@ -70,61 +74,61 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (aktparamgraph.compare("[Alignment]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[Alignment]") != 0) //Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "FLIPIMAGESIZE") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
initialflip = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "INITIALMIRROR") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "INITIALMIRROR") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
initialmirror = true;
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "INITALROTATE") || (toUpper(zerlegt[0]) == "INITIALROTATE")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "INITALROTATE") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
|
||||
{
|
||||
this->initalrotate = std::stod(zerlegt[1]);
|
||||
this->initalrotate = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SEARCHFIELDX") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
|
||||
{
|
||||
suchex = std::stod(zerlegt[1]);
|
||||
suchex = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SEARCHFIELDY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
|
||||
{
|
||||
suchey = std::stod(zerlegt[1]);
|
||||
suchey = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "ANTIALIASING") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
use_antialiasing = true;
|
||||
}
|
||||
if ((zerlegt.size() == 3) && (anz_ref < 2))
|
||||
if ((splitted.size() == 3) && (anz_ref < 2))
|
||||
{
|
||||
References[anz_ref].image_file = FormatFileName("/sdcard" + zerlegt[0]);
|
||||
References[anz_ref].target_x = std::stod(zerlegt[1]);
|
||||
References[anz_ref].target_y = std::stod(zerlegt[2]);
|
||||
References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
|
||||
References[anz_ref].target_x = std::stod(splitted[1]);
|
||||
References[anz_ref].target_y = std::stod(splitted[2]);
|
||||
anz_ref++;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "ALIGNMENTALGO") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus gewählt: " + zerlegt[1];
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
if (toUpper(zerlegt[1]) == "HIGHACCURACY")
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignment mode selected: " + splitted[1];
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
if (toUpper(splitted[1]) == "HIGHACCURACY")
|
||||
alg_algo = 1;
|
||||
if (toUpper(zerlegt[1]) == "FAST")
|
||||
if (toUpper(splitted[1]) == "FAST")
|
||||
alg_algo = 2;
|
||||
}
|
||||
}
|
||||
@@ -135,10 +139,10 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
References[i].search_y = suchey;
|
||||
References[i].fastalg_SAD_criteria = SAD_criteria;
|
||||
References[i].alignment_algo = alg_algo;
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus geschrieben: " + std::to_string(alg_algo);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
}
|
||||
|
||||
LoadReferenceAlignmentValues();
|
||||
@@ -147,6 +151,7 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowAlignment::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result;
|
||||
@@ -160,12 +165,42 @@ string ClassFlowAlignment::getHTMLSingleStep(string host)
|
||||
|
||||
bool ClassFlowAlignment::doFlow(string time)
|
||||
{
|
||||
if (!ImageTMP)
|
||||
ImageTMP = new CImageBasis(ImageBasis, 5);
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
if (!AlgROI) // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
|
||||
{
|
||||
AlgROI = (ImageData*)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
if (!AlgROI)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
}
|
||||
}
|
||||
|
||||
if (AlignAndCutImage)
|
||||
delete AlignAndCutImage;
|
||||
AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);
|
||||
if (AlgROI)
|
||||
{
|
||||
ImageBasis->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ImageTMP)
|
||||
{
|
||||
ImageTMP = new CImageBasis(ImageBasis);
|
||||
if (!ImageTMP)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate ImageTMP -> Exec this round aborted!");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete AlignAndCutImage;
|
||||
AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);
|
||||
if (!AlignAndCutImage)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
return false;
|
||||
}
|
||||
|
||||
CRotateImage rt(AlignAndCutImage, ImageTMP, initialflip);
|
||||
if (initialflip)
|
||||
@@ -175,10 +210,13 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
ImageBasis->width = _zw;
|
||||
}
|
||||
|
||||
if (initialmirror){
|
||||
if (initialmirror)
|
||||
{
|
||||
ESP_LOGD(TAG, "do mirror");
|
||||
rt.Mirror();
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
|
||||
if (SaveAllFiles)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
}
|
||||
|
||||
if ((initalrotate != 0) || initialflip)
|
||||
@@ -187,7 +225,9 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
rt.RotateAntiAliasing(initalrotate);
|
||||
else
|
||||
rt.Rotate(initalrotate);
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
|
||||
|
||||
if (SaveAllFiles)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
|
||||
}
|
||||
|
||||
if (!AlignAndCutImage->Align(&References[0], &References[1]))
|
||||
@@ -195,8 +235,15 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
SaveReferenceAlignmentValues();
|
||||
}
|
||||
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
if (AlgROI) {
|
||||
DrawRef(ImageTMP);
|
||||
tfliteflow.DigitalDrawROI(ImageTMP);
|
||||
tfliteflow.AnalogDrawROI(ImageTMP);
|
||||
ImageTMP->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SaveAllFiles)
|
||||
{
|
||||
if (initialflip)
|
||||
@@ -205,15 +252,14 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
ImageTMP->width = ImageTMP->height;
|
||||
ImageTMP->height = _zw;
|
||||
}
|
||||
DrawRef(ImageTMP);
|
||||
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
|
||||
ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
|
||||
}
|
||||
|
||||
if (ImageTMP) // nuss gelöscht werden, um Speicherplatz für das Laden von tflite zu haben
|
||||
{
|
||||
delete ImageTMP;
|
||||
ImageTMP = NULL;
|
||||
}
|
||||
// must be deleted to have memory space for loading tflite
|
||||
delete ImageTMP;
|
||||
ImageTMP = NULL;
|
||||
|
||||
LoadReferenceAlignmentValues();
|
||||
|
||||
@@ -221,7 +267,6 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowAlignment::SaveReferenceAlignmentValues()
|
||||
{
|
||||
FILE* pFile;
|
||||
@@ -261,92 +306,74 @@ void ClassFlowAlignment::SaveReferenceAlignmentValues()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
|
||||
{
|
||||
FILE* pFile;
|
||||
char zw[1024];
|
||||
string zwvalue;
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues01");
|
||||
|
||||
pFile = fopen(FileStoreRefAlignment.c_str(), "r");
|
||||
if (pFile == NULL)
|
||||
return false;
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues01");
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
|
||||
// zwvalue = "LoadReferenceAlignmentValues Time: " + std::string(zw);
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zwvalue);
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues02");
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
zerlegt = ZerlegeZeile(std::string(zw), " \t");
|
||||
if (zerlegt.size() < 6)
|
||||
splitted = ZerlegeZeile(std::string(zw), " \t");
|
||||
if (splitted.size() < 6)
|
||||
{
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "Exit 01");
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues03");
|
||||
|
||||
References[0].fastalg_x = stoi(zerlegt[0]);
|
||||
References[0].fastalg_y = stoi(zerlegt[1]);
|
||||
References[0].fastalg_SAD = stof(zerlegt[2]);
|
||||
References[0].fastalg_min = stoi(zerlegt[3]);
|
||||
References[0].fastalg_max = stoi(zerlegt[4]);
|
||||
References[0].fastalg_avg = stof(zerlegt[5]);
|
||||
References[0].fastalg_x = stoi(splitted[0]);
|
||||
References[0].fastalg_y = stoi(splitted[1]);
|
||||
References[0].fastalg_SAD = stof(splitted[2]);
|
||||
References[0].fastalg_min = stoi(splitted[3]);
|
||||
References[0].fastalg_max = stoi(splitted[4]);
|
||||
References[0].fastalg_avg = stof(splitted[5]);
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
zerlegt = ZerlegeZeile(std::string(zw));
|
||||
if (zerlegt.size() < 6)
|
||||
splitted = ZerlegeZeile(std::string(zw));
|
||||
if (splitted.size() < 6)
|
||||
{
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "Exit 02");
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues03");
|
||||
|
||||
References[1].fastalg_x = stoi(zerlegt[0]);
|
||||
References[1].fastalg_y = stoi(zerlegt[1]);
|
||||
References[1].fastalg_SAD = stof(zerlegt[2]);
|
||||
References[1].fastalg_min = stoi(zerlegt[3]);
|
||||
References[1].fastalg_max = stoi(zerlegt[4]);
|
||||
References[1].fastalg_avg = stof(zerlegt[5]);
|
||||
References[1].fastalg_x = stoi(splitted[0]);
|
||||
References[1].fastalg_y = stoi(splitted[1]);
|
||||
References[1].fastalg_SAD = stof(splitted[2]);
|
||||
References[1].fastalg_min = stoi(splitted[3]);
|
||||
References[1].fastalg_max = stoi(splitted[4]);
|
||||
References[1].fastalg_avg = stof(splitted[5]);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
#endif
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
#endif*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
|
||||
{
|
||||
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
|
||||
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
|
||||
if (_zw->ImageOkay())
|
||||
{
|
||||
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
|
||||
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWALIGNMENT_H
|
||||
#define CLASSFLOWALIGNMENT_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "Helper.h"
|
||||
#include "CAlignAndCutImage.h"
|
||||
@@ -31,6 +34,9 @@ protected:
|
||||
|
||||
public:
|
||||
CImageBasis *ImageBasis, *ImageTMP;
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
ImageData *AlgROI;
|
||||
#endif
|
||||
|
||||
ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
|
||||
|
||||
@@ -44,3 +50,5 @@ public:
|
||||
string name(){return "ClassFlowAlignment";};
|
||||
};
|
||||
|
||||
|
||||
#endif //CLASSFLOWALIGNMENT_H
|
||||
|
||||
@@ -8,9 +8,16 @@
|
||||
#include "CTfLiteClass.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "CNN";
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
#include <esp_heap_trace.h>
|
||||
#define NUM_RECORDS 300
|
||||
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
|
||||
#endif
|
||||
|
||||
|
||||
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
|
||||
@@ -30,7 +37,8 @@ ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNTy
|
||||
logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _vorgaengerAnalog, float analogDigitalTransitionStart)
|
||||
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _before_narrow_Analog, float analogDigitalTransitionStart)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
@@ -40,19 +48,19 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
|
||||
float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
int result_after_decimal_point = ((int) floor(number * 10) + 10) % 10;
|
||||
|
||||
prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
prev = PointerEvalAnalogNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(analog) number=" + std::to_string(number) + ", result_after_decimal_point=" + std::to_string(result_after_decimal_point) + ", prev=" + std::to_string(prev));
|
||||
result = std::to_string(prev);
|
||||
|
||||
if (_extendedResolution && (CNNType != Digital))
|
||||
result = result + std::to_string(ergebnis_nachkomma);
|
||||
result = result + std::to_string(result_after_decimal_point);
|
||||
|
||||
for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i)
|
||||
{
|
||||
prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[i]->result_float, prev);
|
||||
prev = PointerEvalAnalogNew(GENERAL[_analog]->ROI[i]->result_float, prev);
|
||||
result = std::to_string(prev) + result;
|
||||
}
|
||||
return result;
|
||||
@@ -73,25 +81,24 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
if ((CNNType == DoubleHyprid10) || (CNNType == Digital100))
|
||||
{
|
||||
|
||||
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
if (zahl >= 0) // NaN?
|
||||
float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
if (number >= 0) // NaN?
|
||||
{
|
||||
if (_extendedResolution) // ist nur gesetzt, falls es die erste Ziffer ist (kein Analog vorher!)
|
||||
if (_extendedResolution) // is only set if it is the first digit (no analogue before!)
|
||||
{
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl)) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number)) % 10;
|
||||
|
||||
result = std::to_string(ergebnis_vorkomma) + std::to_string(ergebnis_nachkomma);
|
||||
prev = ergebnis_vorkomma;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) ergebnis_vorkomma=" + std::to_string(ergebnis_vorkomma) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
result = std::to_string(result_before_decimal_point) + std::to_string(result_after_decimal_point);
|
||||
prev = result_before_decimal_point;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) result_before_decimal_point=" + std::to_string(result_before_decimal_point) + ", result_after_decimal_point=" + std::to_string(result_after_decimal_point) + ", prev=" + std::to_string(prev));
|
||||
}
|
||||
else
|
||||
{
|
||||
// prev = ZeigerEval(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
if (_vorgaengerAnalog >= 0)
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _vorgaengerAnalog, prev, true, analogDigitalTransitionStart);
|
||||
if (_before_narrow_Analog >= 0)
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _before_narrow_Analog, prev, true, analogDigitalTransitionStart);
|
||||
else
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
|
||||
result = std::to_string(prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100) prev=" + std::to_string(prev));
|
||||
|
||||
@@ -108,8 +115,8 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
{
|
||||
if (GENERAL[_analog]->ROI[i]->result_float >= 0)
|
||||
{
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#ZeigerEvalHybridNeu()= " + std::to_string(prev));
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#PointerEvalHybridNew()= " + std::to_string(prev));
|
||||
result = std::to_string(prev) + result;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#result= " + result);
|
||||
|
||||
@@ -124,120 +131,119 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger, float digitalAnalogTransitionStart)
|
||||
|
||||
int ClassFlowCNNGeneral::PointerEvalHybridNew(float number, float number_of_predecessors, int eval_predecessors, bool Analog_Predecessors, float digitalAnalogTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number) + 10) % 10;
|
||||
|
||||
if (eval_vorgaenger < 0)
|
||||
if (eval_predecessors < 0)
|
||||
{
|
||||
if ((ergebnis_nachkomma <= DigitalUnschaerfe * 10) || (ergebnis_nachkomma >= DigitalUnschaerfe * 10)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = (int) (round(zahl) + 10) % 10;
|
||||
if ((result_after_decimal_point <= Digital_Uncertainty * 10) || (result_after_decimal_point >= Digital_Uncertainty * 10)) // Band around the digit --> Rounding, as digit reaches inaccuracy in the frame
|
||||
result = (int) (round(number) + 10) % 10;
|
||||
else
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
result = (int) ((int) trunc(number) + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - No predecessor - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (AnalogerVorgaenger)
|
||||
if (Analog_Predecessors)
|
||||
{
|
||||
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger, digitalAnalogTransitionStart);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
result = PointerEvalAnalogToDigitNew(number, number_of_predecessors, eval_predecessors, digitalAnalogTransitionStart);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - Analog predecessor, evaluation over PointerEvalAnalogNew = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((zahl_vorgaenger >= DigitalUebergangsbereichVorgaenger ) && (zahl_vorgaenger <= (10.0 - DigitalUebergangsbereichVorgaenger)))
|
||||
if ((number_of_predecessors >= Digital_Transition_Area_Predecessor ) && (number_of_predecessors <= (10.0 - Digital_Transition_Area_Predecessor)))
|
||||
{
|
||||
// kein Ziffernwechsel, da Vorgänger weit genug weg ist (0+/-DigitalUebergangsbereichVorgaenger) --> zahl wird gerundet
|
||||
if ((ergebnis_nachkomma <= DigitalBand) || (ergebnis_nachkomma >= (10-DigitalBand))) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = ((int) round(zahl) + 10) % 10;
|
||||
// no digit change, because predecessor is far enough away (0+/-DigitalTransitionRangePredecessor) --> number is rounded
|
||||
if ((result_after_decimal_point <= DigitalBand) || (result_after_decimal_point >= (10-DigitalBand))) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|
||||
result = ((int) round(number) + 10) % 10;
|
||||
else
|
||||
result = ((int) trunc(zahl) + 10) % 10;
|
||||
result = ((int) trunc(number) + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - NO analogue predecessor, no change of digits, as pre-decimal point far enough away = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (eval_vorgaenger <= 1) // Nulldurchgang beim Vorgänger hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
|
||||
if (eval_predecessors <= 1) // Zero crossing at the predecessor has taken place (! evaluation via Prev_value and not number!) --> round up here (2.8 --> 3, but also 3.1 --> 3)
|
||||
{
|
||||
// Wir nehmen einfach an, dass das aktuelle Digit nach dem Nulldurchgang des Vorgängers
|
||||
// mindestens zur Hälfte (x.5) durchlaufen hat
|
||||
if (ergebnis_nachkomma > 5)
|
||||
// Das akt. digit hat noch keinen Nulldurchgang, aber der Vorgänger schon.
|
||||
result = (ergebnis_vorkomma + 1) % 10;
|
||||
// We simply assume that the current digit after the zero crossing of the predecessor
|
||||
// has passed through at least half (x.5)
|
||||
if (result_after_decimal_point > 5)
|
||||
// The current digit does not yet have a zero crossing, but the predecessor does..
|
||||
result = (result_before_decimal_point + 1) % 10;
|
||||
else
|
||||
// Akt. digit und Vorgänger haben Nulldurchgang
|
||||
result = ergebnis_vorkomma % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, Nulldurchgang hat stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
// Act. digit and predecessor have zero crossing
|
||||
result = result_before_decimal_point % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - NO analogue predecessor, zero crossing has taken placen = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// bleibt nur >= 9.x --> noch kein Nulldurchgang --> 2.8 --> 2,
|
||||
// und ab 9.7(DigitalUebergangsbereichVorlauf) 3.1 --> 2
|
||||
// alles >=x.4 kann als aktuelle Zahl gelten im Übergang. Bei 9.x Vorgänger kann die aktuelle
|
||||
// Zahl noch x.6 - x.7 sein.
|
||||
// Vorlauf (else - Zweig) passiert nicht bereits ab 9.
|
||||
if (DigitalUebergangsbereichVorlauf>=zahl_vorgaenger || ergebnis_nachkomma >= 4)
|
||||
// aktuelles digit hat genauso wie das Vorgängerdigit noch keinen Nulldurchgang.
|
||||
result = ergebnis_vorkomma % 10;
|
||||
// remains only >= 9.x --> no zero crossing yet --> 2.8 --> 2,
|
||||
// and from 9.7(DigitalTransitionRangeLead) 3.1 --> 2
|
||||
// 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 (Digital_Transition_Area_Forward>=number_of_predecessors || result_after_decimal_point >= 4)
|
||||
// The current digit, like the previous digit, does not yet have a zero crossing.
|
||||
result = result_before_decimal_point % 10;
|
||||
else
|
||||
// aktuelles digit läuft dem kleineren digit (9.x) vor. Also schon >=x.0 während das vorherige Digit noch
|
||||
// keinen Nulldurchgang hat. Daher wird um 1 reduziert.
|
||||
result = (ergebnis_vorkomma - 1 + 10) % 10;
|
||||
// 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 = (result_before_decimal_point - 1 + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe) + " ergebnis_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - O analogue predecessor, >= 9.5 --> no zero crossing yet = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty) + " result_after_decimal_point = " + std::to_string(result_after_decimal_point));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart)
|
||||
int ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew(float number, float numeral_preceder, int eval_predecessors, float analogDigitalTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number) + 10) % 10;
|
||||
bool roundedUp = false;
|
||||
|
||||
// Innerhalb der digitalen Unschaefe
|
||||
if ((ergebnis_nachkomma >= (10-DigitalUnschaerfe * 10)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
|| (eval_vorgaenger <= 4 && ergebnis_nachkomma>=6)) { // oder digit läuft nach (analog =0..4, digit >=6)
|
||||
result = (int) (round(zahl) + 10) % 10;
|
||||
// Within the digital inequalities
|
||||
if ((result_after_decimal_point >= (10-Digital_Uncertainty * 10)) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|
||||
|| (eval_predecessors <= 4 && result_after_decimal_point>=6)) { // or digit runs after (analogue =0..4, digit >=6)
|
||||
result = (int) (round(number) + 10) % 10;
|
||||
roundedUp = true;
|
||||
// vor/nachkomma neu berechnen, da wir anhand der Unschaefe die Zahl anpassen.
|
||||
ergebnis_nachkomma = ((int) floor(result * 10)) % 10;
|
||||
ergebnis_vorkomma = ((int) floor(result) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger: " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_vorkomma: " + std::to_string(ergebnis_vorkomma) +
|
||||
" erg_nachkomma: " + std::to_string(ergebnis_nachkomma));
|
||||
// before/ after decimal point, because we adjust the number based on the uncertainty.
|
||||
result_after_decimal_point = ((int) floor(result * 10)) % 10;
|
||||
result_before_decimal_point = ((int) floor(result) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Digital Uncertainty - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder: " + std::to_string(numeral_preceder) +
|
||||
" erg before comma: " + std::to_string(result_before_decimal_point) +
|
||||
" erg after comma: " + std::to_string(result_after_decimal_point));
|
||||
} else {
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - KEINE digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger));
|
||||
result = (int) ((int) trunc(number) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - NO digital Uncertainty - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder));
|
||||
}
|
||||
|
||||
// Kein Nulldurchgang hat stattgefunden.
|
||||
// Nur eval_vorgaenger verwendet, da ziffer_vorgaenger hier falsch sein könnte.
|
||||
// ziffer_vorgaenger<=0.1 & eval_vorgaenger=9 entspricht analog wurde zurückgesetzt wegen vorhergehender analog, die noch nicht auf 0 sind.
|
||||
if ((eval_vorgaenger>=6 && (ziffer_vorgaenger>analogDigitalTransitionStart || ziffer_vorgaenger<=0.2) && roundedUp))
|
||||
// No zero crossing has taken place.
|
||||
// Only eval_predecessors used because numeral_preceder could be wrong here.
|
||||
// numeral_preceder<=0.1 & eval_predecessors=9 corresponds to analogue was reset because of previous analogue that are not yet at 0.
|
||||
if ((eval_predecessors>=6 && (numeral_preceder>analogDigitalTransitionStart || numeral_preceder<=0.2) && roundedUp))
|
||||
{
|
||||
result = ((ergebnis_vorkomma+10) - 1) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) +
|
||||
" ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
result = ((result_before_decimal_point+10) - 1) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) +
|
||||
" numeral_preceder = " + std::to_string(numeral_preceder) +
|
||||
" eerg after comma = " + std::to_string(result_after_decimal_point));
|
||||
|
||||
}
|
||||
|
||||
@@ -245,53 +251,53 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vor
|
||||
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
|
||||
int ClassFlowCNNGeneral::PointerEvalAnalogNew(float number, int numeral_preceder)
|
||||
{
|
||||
float zahl_min, zahl_max;
|
||||
float number_min, number_max;
|
||||
int result;
|
||||
|
||||
if (ziffer_vorgaenger == -1)
|
||||
if (numeral_preceder == -1)
|
||||
{
|
||||
result = (int) floor(zahl);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = (int) floor(number);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - No predecessor - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
|
||||
zahl_min = zahl - AnalogFehler / 10.0;
|
||||
zahl_max = zahl + AnalogFehler / 10.0;
|
||||
number_min = number - Analog_error / 10.0;
|
||||
number_max = number + Analog_error / 10.0;
|
||||
|
||||
if ((int) floor(zahl_max) - (int) floor(zahl_min) != 0)
|
||||
if ((int) floor(number_max) - (int) floor(number_min) != 0)
|
||||
{
|
||||
if (ziffer_vorgaenger <= AnalogFehler)
|
||||
if (numeral_preceder <= Analog_error)
|
||||
{
|
||||
result = ((int) floor(zahl_max) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach oben - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number_max) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number ambiguous, correction upwards - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
if (ziffer_vorgaenger >= 10 - AnalogFehler)
|
||||
if (numeral_preceder >= 10 - Analog_error)
|
||||
{
|
||||
result = ((int) floor(zahl_min) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach unten - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number_min) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number ambiguous, downward correction - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result = ((int) floor(zahl) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl eindeutig, keine Korrektur notwendig - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number unambiguous, no correction necessary - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -317,53 +323,53 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "LOGIMAGELOCATION") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "LOGIMAGELOCATION") && (splitted.size() > 1))
|
||||
{
|
||||
this->LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
this->LogImageLocation = "/sdcard" + splitted[1];
|
||||
this->isLogImage = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGIMAGESELECT") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGIMAGESELECT") && (splitted.size() > 1))
|
||||
{
|
||||
LogImageSelect = zerlegt[1];
|
||||
LogImageSelect = splitted[1];
|
||||
isLogImageSelect = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
|
||||
this->logfileRetentionInDays = std::stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "MODEL") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "MODEL") && (splitted.size() > 1))
|
||||
{
|
||||
this->cnnmodelfile = zerlegt[1];
|
||||
this->cnnmodelfile = splitted[1];
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CNNGOODTHRESHOLD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CNNGOODTHRESHOLD") && (splitted.size() > 1))
|
||||
{
|
||||
CNNGoodThreshold = std::stof(zerlegt[1]);
|
||||
CNNGoodThreshold = std::stof(splitted[1]);
|
||||
}
|
||||
if (zerlegt.size() >= 5)
|
||||
if (splitted.size() >= 5)
|
||||
{
|
||||
general* _analog = GetGENERAL(zerlegt[0], true);
|
||||
general* _analog = GetGENERAL(splitted[0], true);
|
||||
roi* neuroi = _analog->ROI[_analog->ROI.size()-1];
|
||||
neuroi->posx = std::stoi(zerlegt[1]);
|
||||
neuroi->posy = std::stoi(zerlegt[2]);
|
||||
neuroi->deltax = std::stoi(zerlegt[3]);
|
||||
neuroi->deltay = std::stoi(zerlegt[4]);
|
||||
neuroi->posx = std::stoi(splitted[1]);
|
||||
neuroi->posy = std::stoi(splitted[2]);
|
||||
neuroi->deltax = std::stoi(splitted[3]);
|
||||
neuroi->deltay = std::stoi(splitted[4]);
|
||||
neuroi->CCW = false;
|
||||
if (zerlegt.size() >= 6)
|
||||
if (splitted.size() >= 6)
|
||||
{
|
||||
neuroi->CCW = toUpper(zerlegt[5]) == "TRUE";
|
||||
neuroi->CCW = toUpper(splitted[5]) == "TRUE";
|
||||
}
|
||||
neuroi->result_float = -1;
|
||||
neuroi->image = NULL;
|
||||
neuroi->image_org = NULL;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
}
|
||||
@@ -382,6 +388,7 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
general* ClassFlowCNNGeneral::FindGENERAL(string _name_number)
|
||||
{
|
||||
for (int i = 0; i < GENERAL.size(); ++i)
|
||||
@@ -413,7 +420,7 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
|
||||
if (GENERAL[i]->name == _analog)
|
||||
_ret = GENERAL[i];
|
||||
|
||||
if (!_create) // nicht gefunden und soll auch nicht erzeugt werden
|
||||
if (!_create) // not found and should not be created
|
||||
return _ret;
|
||||
|
||||
if (_ret == NULL)
|
||||
@@ -434,7 +441,6 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result, zw;
|
||||
@@ -459,9 +465,16 @@ string ClassFlowCNNGeneral::getHTMLSingleStep(string host)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doFlow(string time)
|
||||
{
|
||||
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
//register a buffer to record the memory trace
|
||||
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
|
||||
// start tracing
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
if (disabled)
|
||||
return true;
|
||||
|
||||
@@ -469,14 +482,21 @@ bool ClassFlowCNNGeneral::doFlow(string time)
|
||||
return false;
|
||||
};
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow nach Alignment");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow after alignment");
|
||||
|
||||
doNeuralNetwork(time);
|
||||
|
||||
RemoveOldLogs();
|
||||
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doAlignAndCut(string time)
|
||||
{
|
||||
if (disabled)
|
||||
@@ -502,40 +522,45 @@ bool ClassFlowCNNGeneral::doAlignAndCut(string time)
|
||||
if (SaveAllFiles)
|
||||
{
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowCNNGeneral::DrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
int r = 0;
|
||||
int g = 255;
|
||||
int b = 0;
|
||||
if (_zw->ImageOkay())
|
||||
{
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
int r = 0;
|
||||
int g = 255;
|
||||
int b = 0;
|
||||
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
_zw->drawRect(GENERAL[_ana]->ROI[i]->posx, GENERAL[_ana]->ROI[i]->posy, GENERAL[_ana]->ROI[i]->deltax, GENERAL[_ana]->ROI[i]->deltay, r, g, b, 1);
|
||||
_zw->drawEllipse( (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) (GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
_zw->drawLine((int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) GENERAL[_ana]->ROI[i]->posy, (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay), r, g, b, 2);
|
||||
_zw->drawLine((int) GENERAL[_ana]->ROI[i]->posx, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); ++_dig)
|
||||
for (int i = 0; i < GENERAL[_dig]->ROI.size(); ++i)
|
||||
_zw->drawRect(GENERAL[_dig]->ROI[i]->posx, GENERAL[_dig]->ROI[i]->posy, GENERAL[_dig]->ROI[i]->deltax, GENERAL[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2);
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
_zw->drawRect(GENERAL[_ana]->ROI[i]->posx, GENERAL[_ana]->ROI[i]->posy, GENERAL[_ana]->ROI[i]->deltax, GENERAL[_ana]->ROI[i]->deltay, r, g, b, 1);
|
||||
_zw->drawEllipse( (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) (GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
_zw->drawLine((int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) GENERAL[_ana]->ROI[i]->posy, (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay), r, g, b, 2);
|
||||
_zw->drawLine((int) GENERAL[_ana]->ROI[i]->posx, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); ++_dig)
|
||||
for (int i = 0; i < GENERAL[_dig]->ROI.size(); ++i)
|
||||
_zw->drawRect(GENERAL[_dig]->ROI[i]->posx, GENERAL[_dig]->ROI[i]->posy, GENERAL[_dig]->ROI[i]->deltax, GENERAL[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
{
|
||||
if (disabled)
|
||||
@@ -546,11 +571,18 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnnmodelfile + " -> Init aborted!");
|
||||
LogFile.WriteHeapInfo("getNetworkParameter-LoadModel");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
tflite->MakeAllocate();
|
||||
|
||||
if (!tflite->MakeAllocate()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tflite model -> Init aborted!");
|
||||
LogFile.WriteHeapInfo("getNetworkParameter-MakeAllocate");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CNNType == AutoDetect)
|
||||
{
|
||||
@@ -593,7 +625,7 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite passt nicht zur Firmware (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite does not fit the firmware (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,6 +633,7 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
if (disabled)
|
||||
@@ -612,13 +645,20 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
string zwcnn = "/sdcard" + cnnmodelfile;
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnnmodelfile + " -> Exec aborted this round!");
|
||||
LogFile.WriteHeapInfo("doNeuralNetwork-LoadModel");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
tflite->MakeAllocate();
|
||||
}
|
||||
|
||||
if (!tflite->MakeAllocate()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tfilte model -> Exec aborted this round!");
|
||||
LogFile.WriteHeapInfo("doNeuralNetwork-MakeAllocate");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int n = 0; n < GENERAL.size(); ++n) // For each NUMBER
|
||||
{
|
||||
@@ -637,7 +677,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After Invoke");
|
||||
|
||||
f1 = tflite->GetOutputValue(0);
|
||||
f2 = tflite->GetOutputValue(1);
|
||||
@@ -648,7 +688,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
else
|
||||
GENERAL[n]->ROI[roi]->result_float = result * 10;
|
||||
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", roi, GENERAL[n]->ROI[roi]->CCW, GENERAL[n]->ROI[roi]->result_float);
|
||||
ESP_LOGD(TAG, "General result (Analog)%i - CCW: %d - %f", roi, GENERAL[n]->ROI[roi]->CCW, GENERAL[n]->ROI[roi]->result_float);
|
||||
if (isLogImage)
|
||||
LogImage(logPath, GENERAL[n]->ROI[roi]->name, &GENERAL[n]->ROI[roi]->result_float, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
} break;
|
||||
@@ -658,7 +698,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
GENERAL[n]->ROI[roi]->result_klasse = 0;
|
||||
GENERAL[n]->ROI[roi]->result_klasse = tflite->GetClassFromImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
ESP_LOGD(TAG, "Result General(Digit)%i: %d", roi, GENERAL[n]->ROI[roi]->result_klasse);
|
||||
ESP_LOGD(TAG, "General result (Digit)%i: %d", roi, GENERAL[n]->ROI[roi]->result_klasse);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -674,85 +714,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
}
|
||||
}
|
||||
} break;
|
||||
/*
|
||||
case DigitalHyprid:
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: DigitalHyprid");
|
||||
int _num, _nachkomma;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 10);
|
||||
_nachkomma = tflite->GetOutClassification(11, 21);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if ((_num == 10) || (_nachkomma == 10)) // NaN detektiert
|
||||
GENERAL[_ana]->ROI[i]->result_float = -1;
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
*/
|
||||
/*
|
||||
case DigitalHyprid10:
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: DigitalHyprid10");
|
||||
int _num, _nachkomma;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_nachkomma = tflite->GetOutClassification(10, 19);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
*/
|
||||
|
||||
case DoubleHyprid10:
|
||||
{
|
||||
@@ -764,7 +726,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_numplus = (_num + 1) % 10;
|
||||
@@ -804,8 +766,8 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
GENERAL[n]->ROI[roi]->isReject = true;
|
||||
result = -1;
|
||||
_result_save_file+= 100; // Für den Fall, dass fit nicht ausreichend, soll trotzdem das Ergebnis mit "-10x.y" abgespeichert werden.
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + "Threshold: " + to_string(CNNGoodThreshold) + ")";
|
||||
_result_save_file+= 100; // In case fit is not sufficient, the result should still be saved with "-10x.y".
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + ", Threshold: " + to_string(CNNGoodThreshold) + ")";
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, zw);
|
||||
}
|
||||
else
|
||||
@@ -883,6 +845,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::isExtendedResolution(int _number)
|
||||
{
|
||||
if (!(CNNType == Digital))
|
||||
@@ -892,7 +855,6 @@ bool ClassFlowCNNGeneral::isExtendedResolution(int _number)
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
{
|
||||
std::vector<HTMLInfo*> result;
|
||||
@@ -904,20 +866,20 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
if (GENERAL[_ana]->ROI[i]->image)
|
||||
{
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
}
|
||||
|
||||
HTMLInfo *zw = new HTMLInfo;
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
{
|
||||
zw->filename = GENERAL[_ana]->ROI[i]->name + ".bmp";
|
||||
zw->filename = GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
zw->filename_org = GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
zw->filename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp";
|
||||
zw->filename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
zw->filename_org = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
}
|
||||
|
||||
@@ -934,11 +896,13 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::getAnzahlGENERAL()
|
||||
|
||||
int ClassFlowCNNGeneral::getNumberGENERAL()
|
||||
{
|
||||
return GENERAL.size();
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getNameGENERAL(int _analog)
|
||||
{
|
||||
if (_analog < GENERAL.size())
|
||||
@@ -947,6 +911,7 @@ string ClassFlowCNNGeneral::getNameGENERAL(int _analog)
|
||||
return "GENERAL DOES NOT EXIST";
|
||||
}
|
||||
|
||||
|
||||
general* ClassFlowCNNGeneral::GetGENERAL(int _analog)
|
||||
{
|
||||
if (_analog < GENERAL.size())
|
||||
@@ -956,7 +921,6 @@ general* ClassFlowCNNGeneral::GetGENERAL(int _analog)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numbers)
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); _dig++)
|
||||
@@ -973,6 +937,7 @@ void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numb
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getReadoutRawString(int _analog)
|
||||
{
|
||||
string rt = "";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CLASSCNNGENERAL__
|
||||
#define __CLASSCNNGENERAL__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWCNNGENERAL_H
|
||||
#define CLASSFLOWCNNGENERAL_H
|
||||
|
||||
#include"ClassFlowDefineTypes.h"
|
||||
#include "ClassFlowAlignment.h"
|
||||
@@ -23,13 +25,15 @@ protected:
|
||||
t_CNNType CNNType;
|
||||
std::vector<general*> GENERAL;
|
||||
float CNNGoodThreshold;
|
||||
float AnalogFehler = 3.0;
|
||||
float AnalogToDigtalFehler = 0.8;
|
||||
float DigitalUnschaerfe = 0.2;
|
||||
int DigitalBand = 3;
|
||||
float DigitalAnalogerVorgaengerUebergangsbereich = 2;
|
||||
float DigitalUebergangsbereichVorgaenger = 0.7; // 9.3 - 0.7
|
||||
float DigitalUebergangsbereichVorlauf = 9.7; // Vorlauf-Nulldurchgang passiert erst ab ca. 9.7
|
||||
|
||||
//moved to define.h
|
||||
//float Analog_error = 3.0;
|
||||
//float AnalogToDigtalFehler = 0.8;
|
||||
//float Digital_Uncertainty = 0.2;
|
||||
//int DigitalBand = 3;
|
||||
//float Digital_Transition_Range_Predecessor = 2;
|
||||
//float Digital_Transition_Area_Predecessor = 0.7; // 9.3 - 0.7
|
||||
//float Digital_Transition_Area_Forward = 9.7; // Pre-run zero crossing only happens from approx. 9.7 onwards
|
||||
|
||||
string cnnmodelfile;
|
||||
int modelxsize, modelysize, modelchannel;
|
||||
@@ -39,9 +43,9 @@ protected:
|
||||
|
||||
bool SaveAllFiles;
|
||||
|
||||
int ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger);
|
||||
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart);
|
||||
int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false, float analogDigitalTransitionStart=9.2);
|
||||
int PointerEvalAnalogNew(float zahl, int numeral_preceder);
|
||||
int PointerEvalAnalogToDigitNew(float zahl, float numeral_preceder, int eval_predecessors, float analogDigitalTransitionStart);
|
||||
int PointerEvalHybridNew(float zahl, float number_of_predecessors, int eval_predecessors, bool Analog_Predecessors = false, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +61,7 @@ public:
|
||||
bool doFlow(string time);
|
||||
|
||||
string getHTMLSingleStep(string host);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _vorgaengerAnalog = -1, float analogDigitalTransitionStart=9.2);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _before_narrow_Analog = -1, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
string getReadoutRawString(int _analog);
|
||||
|
||||
@@ -65,7 +69,7 @@ public:
|
||||
|
||||
std::vector<HTMLInfo*> GetHTMLInfo();
|
||||
|
||||
int getAnzahlGENERAL();
|
||||
int getNumberGENERAL();
|
||||
general* GetGENERAL(int _analog);
|
||||
general* GetGENERAL(string _name, bool _create);
|
||||
general* FindGENERAL(string _name_number);
|
||||
|
||||
@@ -24,14 +24,13 @@ extern "C" {
|
||||
#include "server_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
//#include "CImg.h"
|
||||
|
||||
#include "server_help.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "CTRL";
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
|
||||
std::string _classname = "";
|
||||
@@ -51,21 +50,21 @@ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _
|
||||
if ((_stepname.compare("[Analog]") == 0) || (_stepname.compare(";[Analog]") == 0)){
|
||||
_classname = "ClassFlowCNNGeneral";
|
||||
}
|
||||
#ifdef ENABLE_MQTT
|
||||
#ifdef ENABLE_MQTT
|
||||
if ((_stepname.compare("[MQTT]") == 0) || (_stepname.compare(";[MQTT]") == 0)){
|
||||
_classname = "ClassFlowMQTT";
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if ((_stepname.compare("[InfluxDB]") == 0) || (_stepname.compare(";[InfluxDB]") == 0)){
|
||||
_classname = "ClassFlowInfluxDB";
|
||||
}
|
||||
#endif //ENABLE_INFLUXDB
|
||||
#endif //ENABLE_INFLUXDB
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
if (FlowControll[i]->name().compare(_classname) == 0){
|
||||
if (!(FlowControll[i]->name().compare("ClassFlowMakeImage") == 0)) // falls es ein MakeImage ist, braucht das Bild nicht extra aufgenommen zu werden, dass passiert bei html-Abfrage automatisch
|
||||
if (!(FlowControll[i]->name().compare("ClassFlowMakeImage") == 0)) // if it is a MakeImage, the image does not need to be included, this happens automatically with the html query.
|
||||
FlowControll[i]->doFlow("");
|
||||
result = FlowControll[i]->getHTMLSingleStep(_host);
|
||||
}
|
||||
@@ -84,14 +83,14 @@ std::string ClassFlowControll::TranslateAktstatus(std::string _input)
|
||||
return ("Aligning");
|
||||
if (_input.compare("ClassFlowCNNGeneral") == 0)
|
||||
return ("Digitalization of ROIs");
|
||||
#ifdef ENABLE_MQTT
|
||||
if (_input.compare("ClassFlowMQTT") == 0)
|
||||
return ("Sending MQTT");
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if (_input.compare("ClassFlowInfluxDB") == 0)
|
||||
return ("Sending InfluxDB");
|
||||
#endif //ENABLE_INFLUXDB
|
||||
#ifdef ENABLE_MQTT
|
||||
if (_input.compare("ClassFlowMQTT") == 0)
|
||||
return ("Sending MQTT");
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if (_input.compare("ClassFlowInfluxDB") == 0)
|
||||
return ("Sending InfluxDB");
|
||||
#endif //ENABLE_INFLUXDB
|
||||
if (_input.compare("ClassFlowPostProcessing") == 0)
|
||||
return ("Post-Processing");
|
||||
if (_input.compare("ClassFlowWriteList") == 0)
|
||||
@@ -113,6 +112,7 @@ std::vector<HTMLInfo*> ClassFlowControll::GetAllDigital()
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
std::vector<HTMLInfo*> ClassFlowControll::GetAllAnalog()
|
||||
{
|
||||
if (flowanalog)
|
||||
@@ -122,6 +122,7 @@ std::vector<HTMLInfo*> ClassFlowControll::GetAllAnalog()
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
t_CNNType ClassFlowControll::GetTypeDigital()
|
||||
{
|
||||
if (flowdigit)
|
||||
@@ -130,6 +131,7 @@ t_CNNType ClassFlowControll::GetTypeDigital()
|
||||
return t_CNNType::None;
|
||||
}
|
||||
|
||||
|
||||
t_CNNType ClassFlowControll::GetTypeAnalog()
|
||||
{
|
||||
if (flowanalog)
|
||||
@@ -139,6 +141,21 @@ t_CNNType ClassFlowControll::GetTypeAnalog()
|
||||
}
|
||||
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
void ClassFlowControll::DigitalDrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (flowdigit)
|
||||
flowdigit->DrawROI(_zw);
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::AnalogDrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (flowanalog)
|
||||
flowanalog->DrawROI(_zw);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
string ClassFlowControll::GetMQTTMainTopic()
|
||||
@@ -161,6 +178,7 @@ bool ClassFlowControll::StartMQTTService() {
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
void ClassFlowControll::SetInitialParameter(void)
|
||||
{
|
||||
AutoStart = false;
|
||||
@@ -171,15 +189,17 @@ void ClassFlowControll::SetInitialParameter(void)
|
||||
flowpostprocessing = NULL;
|
||||
disabled = false;
|
||||
aktRunNr = 0;
|
||||
aktstatus = "Booting ...";
|
||||
aktstatus = "Flow task not yet created";
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::isAutoStart(long &_intervall)
|
||||
{
|
||||
_intervall = AutoIntervall * 60 * 1000; // AutoIntervall: Minuten -> ms
|
||||
_intervall = AutoIntervall * 60 * 1000; // AutoInterval: minutes -> ms
|
||||
return AutoStart;
|
||||
}
|
||||
|
||||
|
||||
ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
{
|
||||
ClassFlow* cfc = NULL;
|
||||
@@ -206,14 +226,14 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
cfc = new ClassFlowCNNGeneral(flowalignment);
|
||||
flowdigit = (ClassFlowCNNGeneral*) cfc;
|
||||
}
|
||||
#ifdef ENABLE_MQTT
|
||||
#ifdef ENABLE_MQTT
|
||||
if (toUpper(_type).compare("[MQTT]") == 0)
|
||||
cfc = new ClassFlowMQTT(&FlowControll);
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if (toUpper(_type).compare("[INFLUXDB]") == 0)
|
||||
cfc = new ClassFlowInfluxDB(&FlowControll);
|
||||
#endif //ENABLE_INFLUXDB
|
||||
#endif //ENABLE_INFLUXDB
|
||||
if (toUpper(_type).compare("[WRITELIST]") == 0)
|
||||
cfc = new ClassFlowWriteList(&FlowControll);
|
||||
|
||||
@@ -223,7 +243,7 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
flowpostprocessing = (ClassFlowPostProcessing*) cfc;
|
||||
}
|
||||
|
||||
if (cfc) // Wird nur angehangen, falls es nicht [AutoTimer] ist, denn dieses ist für FlowControll
|
||||
if (cfc) // Attached only if it is not [AutoTimer], because this is for FlowControll
|
||||
FlowControll.push_back(cfc);
|
||||
|
||||
if (toUpper(_type).compare("[AUTOTIMER]") == 0)
|
||||
@@ -241,16 +261,21 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
return cfc;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::InitFlow(std::string config)
|
||||
{
|
||||
aktstatus = "Initialization";
|
||||
//#ifdef ENABLE_MQTT
|
||||
//MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization", false); // Right now, not possible -> MQTT Service is going to be started later
|
||||
//#endif //ENABLE_MQTT
|
||||
|
||||
string line;
|
||||
|
||||
flowpostprocessing = NULL;
|
||||
|
||||
ClassFlow* cfc;
|
||||
FILE* pFile;
|
||||
config = FormatFileName(config);
|
||||
pFile = OpenFileAndWait(config.c_str(), "r");
|
||||
pFile = fopen(config.c_str(), "r");
|
||||
|
||||
line = "";
|
||||
|
||||
@@ -282,73 +307,83 @@ void ClassFlowControll::InitFlow(std::string config)
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
}
|
||||
|
||||
std::string* ClassFlowControll::getActStatus(){
|
||||
|
||||
std::string* ClassFlowControll::getActStatus()
|
||||
{
|
||||
return &aktstatus;
|
||||
}
|
||||
|
||||
void ClassFlowControll::doFlowMakeImageOnly(string time){
|
||||
|
||||
void ClassFlowControll::setActStatus(std::string _aktstatus)
|
||||
{
|
||||
aktstatus = _aktstatus;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::doFlowMakeImageOnly(string time)
|
||||
{
|
||||
std::string zw_time;
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
{
|
||||
if (FlowControll[i]->name() == "ClassFlowMakeImage") {
|
||||
// zw_time = gettimestring("%Y%m%d-%H%M%S");
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
FlowControll[i]->doFlow(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::doFlow(string time)
|
||||
{
|
||||
// CleanTempFolder(); // dazu muss man noch eine Rolling einführen
|
||||
|
||||
bool result = true;
|
||||
std::string zw_time;
|
||||
int repeat = 0;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
|
||||
#endif
|
||||
|
||||
/* Check if we have a valid date/time and if not restart the NTP client */
|
||||
if (! getTimeIsSet()) {
|
||||
/* if (! getTimeIsSet()) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Time not set, restarting NTP Client!");
|
||||
restartNtpClient();
|
||||
}
|
||||
}*/
|
||||
|
||||
//checkNtpStatus(0);
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
{
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
//LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatus);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
|
||||
LogFile.WriteHeapInfo(zw);
|
||||
#endif
|
||||
|
||||
if (!FlowControll[i]->doFlow(time)){
|
||||
repeat++;
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
|
||||
if (i) i -= 1; // vorheriger Schritt muss wiederholt werden (vermutlich Bilder aufnehmen)
|
||||
if (i) i -= 1; // vPrevious step must be repeated (probably take pictures)
|
||||
result = false;
|
||||
if (repeat > 5) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Wiederholung 5x nicht erfolgreich --> reboot");
|
||||
doReboot();
|
||||
// Schritt wurde 5x wiederholt --> reboot
|
||||
//Step was repeated 5x --> reboot
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -356,17 +391,19 @@ bool ClassFlowControll::doFlow(string time)
|
||||
result = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow");
|
||||
#endif
|
||||
}
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = "Flow finished";
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
//LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatus);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -436,6 +473,7 @@ string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = fal
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowControll::GetPrevalue(std::string _number)
|
||||
{
|
||||
if (flowpostprocessing)
|
||||
@@ -446,6 +484,7 @@ string ClassFlowControll::GetPrevalue(std::string _number)
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
|
||||
std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern)
|
||||
{
|
||||
float zw;
|
||||
@@ -475,9 +514,10 @@ std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -492,23 +532,23 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph, " =");
|
||||
if ((toUpper(zerlegt[0]) == "AUTOSTART") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph, " =");
|
||||
if ((toUpper(splitted[0]) == "AUTOSTART") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
AutoStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "INTERVALL") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "INTERVALL") && (splitted.size() > 1))
|
||||
{
|
||||
AutoIntervall = std::stof(zerlegt[1]);
|
||||
AutoIntervall = std::stof(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGACTIVE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "DATALOGACTIVE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
LogFile.SetDataLogToSD(true);
|
||||
}
|
||||
@@ -517,53 +557,56 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGRETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "DATALOGRETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
LogFile.SetDataLogRetention(std::stoi(zerlegt[1]));
|
||||
LogFile.SetDataLogRetention(std::stoi(splitted[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILE") && (splitted.size() > 1))
|
||||
{
|
||||
/* matches esp_log_level_t */
|
||||
if ((toUpper(zerlegt[1]) == "TRUE") || (toUpper(zerlegt[1]) == "2"))
|
||||
if ((toUpper(splitted[1]) == "TRUE") || (toUpper(splitted[1]) == "2"))
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_WARN);
|
||||
}
|
||||
else if ((toUpper(zerlegt[1]) == "FALSE") || (toUpper(zerlegt[1]) == "0") || (toUpper(zerlegt[1]) == "1"))
|
||||
else if ((toUpper(splitted[1]) == "FALSE") || (toUpper(splitted[1]) == "0") || (toUpper(splitted[1]) == "1"))
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_ERROR);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "3")
|
||||
else if (toUpper(splitted[1]) == "3")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_INFO);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "4")
|
||||
else if (toUpper(splitted[1]) == "4")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
LogFile.SetLogFileRetention(std::stoi(zerlegt[1]));
|
||||
LogFile.SetLogFileRetention(std::stoi(splitted[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "TIMEZONE") && (zerlegt.size() > 1))
|
||||
{
|
||||
string zw = "Set TimeZone: " + zerlegt[1];
|
||||
setTimeZone(zerlegt[1]);
|
||||
}
|
||||
/* TimeServer and TimeZone got already read from the config, see setupTime () */
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "TIMESERVER") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "RSSITHREASHOLD") && (splitted.size() > 1))
|
||||
{
|
||||
string zw = "Set TimeZone: " + zerlegt[1];
|
||||
reset_servername(zerlegt[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "HOSTNAME") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (ChangeHostName("/sdcard/wlan.ini", zerlegt[1]))
|
||||
if (ChangeRSSIThreashold(WLAN_CONFIG_FILE, atoi(splitted[1].c_str())))
|
||||
{
|
||||
// reboot notwendig damit die neue wlan.ini auch benutzt wird !!!
|
||||
// reboot necessary so that the new wlan.ini is also used !!!
|
||||
fclose(pfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new RSSITHREASHOLD ...");
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
doReboot();
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(splitted[0]) == "HOSTNAME") && (splitted.size() > 1))
|
||||
{
|
||||
if (ChangeHostName(WLAN_CONFIG_FILE, splitted[1]))
|
||||
{
|
||||
// reboot necessary so that the new wlan.ini is also used !!!
|
||||
fclose(pfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new HOSTNAME...");
|
||||
esp_restart();
|
||||
@@ -572,9 +615,9 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SETUPMODE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SETUPMODE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
SetupModeActive = true;
|
||||
}
|
||||
@@ -625,90 +668,228 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGD(TAG, "ClassFlowControll::GetJPGStream %s", _fn.c_str());
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - Start");
|
||||
#endif
|
||||
|
||||
CImageBasis *_send = NULL;
|
||||
esp_err_t result = ESP_FAIL;
|
||||
bool Dodelete = false;
|
||||
bool _sendDelete = false;
|
||||
|
||||
if (flowalignment == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "Can't continue, flowalignment is NULL");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (_fn == "alg.jpg")
|
||||
{
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fn == "alg_roi.jpg")
|
||||
{
|
||||
CImageBasis* _imgzw = new CImageBasis(flowalignment->ImageBasis);
|
||||
flowalignment->DrawRef(_imgzw);
|
||||
if (flowdigit) flowdigit->DrawROI(_imgzw);
|
||||
if (flowanalog) flowanalog->DrawROI(_imgzw);
|
||||
_send = _imgzw;
|
||||
Dodelete = true;
|
||||
if (_fn == "alg.jpg") {
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<HTMLInfo*> htmlinfo;
|
||||
htmlinfo = GetAllDigital();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllDigital");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
if (!_send)
|
||||
{
|
||||
htmlinfo = GetAllAnalog();
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg.jpg cannot be served");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
else if (_fn == "alg_roi.jpg") {
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG // no CImageBasis needed to create alg_roi.jpg (ca. 790kB less RAM)
|
||||
if (aktstatus.find("Initialization (delayed)") != -1) {
|
||||
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");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long fileSize = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
unsigned char* fileBuffer = (unsigned char*) malloc(fileSize);
|
||||
|
||||
if (!fileBuffer) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(fileBuffer, fileSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)fileBuffer, fileSize);
|
||||
delete fileBuffer;
|
||||
}
|
||||
else if (aktstatus.find("Initialization") != -1) {
|
||||
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");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long fileSize = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
unsigned char* fileBuffer = (unsigned char*) malloc(fileSize);
|
||||
|
||||
if (!fileBuffer) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(fileBuffer, fileSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)fileBuffer, fileSize);
|
||||
delete fileBuffer;
|
||||
}
|
||||
else if (aktstatus.find("Take Image") != -1) {
|
||||
if (flowalignment && flowalignment->AlgROI) {
|
||||
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");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
flowalignment->AlgROI->size = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
if (flowalignment->AlgROI->size > MAX_JPG_SIZE) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/Flowstate_take_image.jpg too large: " + std::to_string(flowalignment->AlgROI->size));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(flowalignment->AlgROI->data, flowalignment->AlgROI->size, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served!");
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (flowalignment && flowalignment->AlgROI) {
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served!");
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!flowalignment) {
|
||||
ESP_LOGD(TAG, "ClassFloDControll::GetJPGStream: FlowAlignment is not (yet) initialized. Interrupt serving!");
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
_send = new CImageBasis(flowalignment->ImageBasis);
|
||||
|
||||
if (_send->ImageOkay()) {
|
||||
if (flowalignment) flowalignment->DrawRef(_send);
|
||||
if (flowdigit) flowdigit->DrawROI(_send);
|
||||
if (flowanalog) flowanalog->DrawROI(_send);
|
||||
_sendDelete = true; // delete temporary _send element after sending
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create alg_roi.jpg -> alg.jpg is going to be served!");
|
||||
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std::vector<HTMLInfo*> htmlinfo;
|
||||
|
||||
htmlinfo = GetAllDigital();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllDigital");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
if (!_send)
|
||||
{
|
||||
htmlinfo = GetAllAnalog();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllAnalog");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - before send");
|
||||
#endif
|
||||
|
||||
if (_send)
|
||||
{
|
||||
ESP_LOGD(TAG, "Sending file: %s ...", _fn.c_str());
|
||||
set_content_type_from_file(req, _fn.c_str());
|
||||
result = _send->SendJPGtoHTTP(req);
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
|
||||
if (_sendDelete)
|
||||
delete _send;
|
||||
|
||||
_send = NULL;
|
||||
}
|
||||
|
||||
if (Dodelete)
|
||||
{
|
||||
delete _send;
|
||||
}
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -719,6 +900,7 @@ string ClassFlowControll::getNumbersName()
|
||||
return flowpostprocessing->getNumbersName();
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowControll::getJSON()
|
||||
{
|
||||
return flowpostprocessing->GetJSON();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifndef __FLOWCONTROLL__
|
||||
#define __FLOWCONTROLL__
|
||||
#ifndef CLASSFLOWCONTROLL_H
|
||||
#define CLASSFLOWCONTROLL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -19,13 +19,6 @@
|
||||
#include "ClassFlowCNNGeneral.h"
|
||||
#include "ClassFlowWriteList.h"
|
||||
|
||||
|
||||
#define READOUT_TYPE_VALUE 0
|
||||
#define READOUT_TYPE_PREVALUE 1
|
||||
#define READOUT_TYPE_RAWVALUE 2
|
||||
#define READOUT_TYPE_ERROR 3
|
||||
|
||||
|
||||
class ClassFlowControll :
|
||||
public ClassFlow
|
||||
{
|
||||
@@ -60,9 +53,15 @@ public:
|
||||
string getNumbersName();
|
||||
|
||||
string TranslateAktstatus(std::string _input);
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
string GetMQTTMainTopic();
|
||||
#endif //ENABLE_MQTT
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
void DigitalDrawROI(CImageBasis *_zw);
|
||||
void AnalogDrawROI(CImageBasis *_zw);
|
||||
#endif
|
||||
|
||||
esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req);
|
||||
esp_err_t SendRawJPG(httpd_req_t *req);
|
||||
@@ -72,15 +71,17 @@ public:
|
||||
bool isAutoStart(long &_intervall);
|
||||
|
||||
std::string* getActStatus();
|
||||
void setActStatus(std::string _aktstatus);
|
||||
|
||||
std::vector<HTMLInfo*> GetAllDigital();
|
||||
std::vector<HTMLInfo*> GetAllAnalog();
|
||||
|
||||
t_CNNType GetTypeDigital();
|
||||
t_CNNType GetTypeAnalog();
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
bool StartMQTTService();
|
||||
#endif //ENABLE_MQTT
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
int CleanTempFolder();
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CLASSFLOWIMAGE_CLASS__
|
||||
#define __CLASSFLOWIMAGE_CLASS__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWDEFINETYPES_H
|
||||
#define CLASSFLOWDEFINETYPES_H
|
||||
|
||||
#include "ClassFlowImage.h"
|
||||
|
||||
@@ -33,20 +35,20 @@ struct NumberPost {
|
||||
bool checkDigitIncreaseConsistency;
|
||||
time_t lastvalue;
|
||||
string timeStamp;
|
||||
double FlowRateAct; // m3 / min
|
||||
double PreValue; // letzter Wert, der gut ausgelesen wurde
|
||||
double Value; // letzer ausgelesener Wert, inkl. Korrekturen
|
||||
string ReturnRateValue; // RückgabewertRate
|
||||
string ReturnChangeAbsolute; // RückgabewertRate
|
||||
string ReturnRawValue; // Rohwert (mit N & führenden 0)
|
||||
string ReturnValue; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
string ReturnPreValue; // korrigierter Rückgabewert ohne Fehlermeldung
|
||||
string ErrorMessageText; // Fehlermeldung bei Consistency Check
|
||||
double FlowRateAct; // m3 / min
|
||||
double PreValue; // last value that was read out well
|
||||
double Value; // last value read out, incl. corrections
|
||||
string ReturnRateValue; // return value rate
|
||||
string ReturnChangeAbsolute; // return value rate
|
||||
string ReturnRawValue; // Raw value (with N & leading 0)
|
||||
string ReturnValue; // corrected return value, if necessary with error message
|
||||
string ReturnPreValue; // corrected return value without error message
|
||||
string ErrorMessageText; // Error message for consistency check
|
||||
int AnzahlAnalog;
|
||||
int AnzahlDigital;
|
||||
int DecimalShift;
|
||||
int DecimalShiftInitial;
|
||||
float AnalogDigitalTransitionStart; // Wann ist das digit > x.1, also wann fängt es an zu kippen
|
||||
float AnalogDigitalTransitionStart; // When is the digit > x.1, i.e. when does it start to tilt?
|
||||
int Nachkomma;
|
||||
|
||||
bool isExtendedResolution;
|
||||
|
||||
@@ -15,6 +15,7 @@ extern "C" {
|
||||
#include "ClassLogFile.h"
|
||||
#include "CImageBasis.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "IMG";
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWIMAGE_H
|
||||
#define CLASSFLOWIMAGE_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -22,3 +26,5 @@ public:
|
||||
|
||||
void RemoveOldLogs();
|
||||
};
|
||||
|
||||
#endif //CLASSFLOWIMAGE_H
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -68,7 +69,7 @@ ClassFlowInfluxDB::ClassFlowInfluxDB(std::vector<ClassFlow*>* lfc, ClassFlow *_p
|
||||
|
||||
bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -82,26 +83,26 @@ bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str());
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
this->user = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "PASSWORD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
|
||||
{
|
||||
this->password = zerlegt[1];
|
||||
this->password = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "URI") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
|
||||
{
|
||||
this->uri = zerlegt[1];
|
||||
this->uri = splitted[1];
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "MEASUREMENT")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "MEASUREMENT")) && (splitted.size() > 1))
|
||||
{
|
||||
this->measurement = zerlegt[1];
|
||||
this->measurement = splitted[1];
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "DATABASE")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "DATABASE")) && (splitted.size() > 1))
|
||||
{
|
||||
this->database = zerlegt[1];
|
||||
this->database = splitted[1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFINFLUXDB_H
|
||||
#define CLASSFINFLUXDB_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
@@ -30,4 +35,5 @@ public:
|
||||
string name(){return "ClassFlowInfluxDB";};
|
||||
};
|
||||
|
||||
#endif //CLASSFINFLUXDB_H
|
||||
#endif //ENABLE_INFLUXDB
|
||||
@@ -15,14 +15,9 @@
|
||||
#include "server_mqtt.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "MQTT";
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
extern const char* libfive_git_version(void);
|
||||
extern const char* libfive_git_revision(void);
|
||||
@@ -92,7 +87,7 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev)
|
||||
|
||||
bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -100,76 +95,76 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
this->user = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "PASSWORD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
|
||||
{
|
||||
this->password = zerlegt[1];
|
||||
this->password = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "URI") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
|
||||
{
|
||||
this->uri = zerlegt[1];
|
||||
this->uri = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SETRETAINFLAG") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SETRETAINFLAG") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE") {
|
||||
if (toUpper(splitted[1]) == "TRUE") {
|
||||
SetRetainFlag = 1;
|
||||
setMqtt_Server_Retain(SetRetainFlag);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "HOMEASSISTANTDISCOVERY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SetHomeassistantDiscoveryEnabled(true);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "METERTYPE") && (zerlegt.size() > 1)) {
|
||||
if ((toUpper(splitted[0]) == "METERTYPE") && (splitted.size() > 1)) {
|
||||
/* Use meter type for the device class
|
||||
Make sure it is a listed one on https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes */
|
||||
if (toUpper(zerlegt[1]) == "WATER_M3") {
|
||||
if (toUpper(splitted[1]) == "WATER_M3") {
|
||||
mqttServer_setMeterType("water", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_L") {
|
||||
else if (toUpper(splitted[1]) == "WATER_L") {
|
||||
mqttServer_setMeterType("water", "L", "h", "L/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_FT3") {
|
||||
else if (toUpper(splitted[1]) == "WATER_FT3") {
|
||||
mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_GAL") {
|
||||
else if (toUpper(splitted[1]) == "WATER_GAL") {
|
||||
mqttServer_setMeterType("water", "gal", "h", "gal/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_M3") {
|
||||
else if (toUpper(splitted[1]) == "GAS_M3") {
|
||||
mqttServer_setMeterType("gas", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_FT3") {
|
||||
else if (toUpper(splitted[1]) == "GAS_FT3") {
|
||||
mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_WH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_WH") {
|
||||
mqttServer_setMeterType("energy", "Wh", "h", "W");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_KWH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_KWH") {
|
||||
mqttServer_setMeterType("energy", "kWh", "h", "kW");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_MWH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_MWH") {
|
||||
mqttServer_setMeterType("energy", "MWh", "h", "MW");
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CLIENTID") && (splitted.size() > 1))
|
||||
{
|
||||
this->clientname = zerlegt[1];
|
||||
this->clientname = splitted[1];
|
||||
}
|
||||
|
||||
if (((toUpper(zerlegt[0]) == "TOPIC") || (toUpper(zerlegt[0]) == "MAINTOPIC")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
|
||||
{
|
||||
maintopic = zerlegt[1];
|
||||
maintopic = splitted[1];
|
||||
mqttServer_setMainTopic(maintopic);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWMQTT_H
|
||||
#define CLASSFFLOWMQTT_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
@@ -33,5 +38,5 @@ public:
|
||||
bool doFlow(string time);
|
||||
string name(){return "ClassFlowMQTT";};
|
||||
};
|
||||
|
||||
#endif //CLASSFFLOWMQTT_H
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -25,14 +26,14 @@ esp_err_t ClassFlowMakeImage::camera_capture(){
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
|
||||
void ClassFlowMakeImage::takePictureWithFlash(int flash_duration)
|
||||
{
|
||||
// für den Fall, dass das Bild geflippt wird, muss es hier zurück gesetzt werden ////
|
||||
// in case the image is flipped, it must be reset here //
|
||||
rawImage->width = image_width;
|
||||
rawImage->height = image_height;
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
ESP_LOGD(TAG, "Flashdauer: %d", flashdauer);
|
||||
Camera.CaptureToBasisImage(rawImage, flashdauer);
|
||||
ESP_LOGD(TAG, "flash_duration: %d", flash_duration);
|
||||
Camera.CaptureToBasisImage(rawImage, flash_duration);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
@@ -51,7 +52,7 @@ void ClassFlowMakeImage::SetInitialParameter(void)
|
||||
SaveAllFiles = false;
|
||||
disabled = false;
|
||||
FixedExposure = false;
|
||||
namerawimage = "/sdcard/img_tmp/raw.jpg";
|
||||
namerawimage = "/sdcard/img_tmp/raw.jpg";
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +63,10 @@ ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlow
|
||||
SetInitialParameter();
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
int _brightness = -100;
|
||||
@@ -75,70 +77,76 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (aktparamgraph.compare("[MakeImage]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[MakeImage]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((splitted[0] == "LogImageLocation") && (splitted.size() > 1))
|
||||
{
|
||||
LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
LogImageLocation = "/sdcard" + splitted[1];
|
||||
isLogImage = true;
|
||||
}
|
||||
if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1))
|
||||
ImageQuality = std::stod(zerlegt[1]);
|
||||
if ((splitted[0] == "ImageQuality") && (splitted.size() > 1))
|
||||
ImageQuality = std::stod(splitted[1]);
|
||||
|
||||
if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1))
|
||||
if ((splitted[0] == "ImageSize") && (splitted.size() > 1))
|
||||
{
|
||||
ImageSize = Camera.TextToFramesize(zerlegt[1].c_str());
|
||||
ImageSize = Camera.TextToFramesize(splitted[1].c_str());
|
||||
isImageSize = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "WAITBEFORETAKINGPICTURE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
|
||||
{
|
||||
waitbeforepicture = stoi(zerlegt[1]);
|
||||
waitbeforepicture = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
|
||||
this->logfileRetentionInDays = std::stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "BRIGHTNESS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "BRIGHTNESS") && (splitted.size() > 1))
|
||||
{
|
||||
_brightness = stoi(zerlegt[1]);
|
||||
_brightness = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CONTRAST") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CONTRAST") && (splitted.size() > 1))
|
||||
{
|
||||
_contrast = stoi(zerlegt[1]);
|
||||
_contrast = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SATURATION") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SATURATION") && (splitted.size() > 1))
|
||||
{
|
||||
_saturation = stoi(zerlegt[1]);
|
||||
_saturation = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "FIXEDEXPOSURE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "FIXEDEXPOSURE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
FixedExposure = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LEDINTENSITY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
|
||||
{
|
||||
float ledintensity = stof(zerlegt[1]);
|
||||
float ledintensity = stof(splitted[1]);
|
||||
ledintensity = min((float) 100, ledintensity);
|
||||
ledintensity = max((float) 0, ledintensity);
|
||||
Camera.SetLEDIntensity(ledintensity);
|
||||
}
|
||||
|
||||
if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
Camera.useDemoMode();
|
||||
}
|
||||
}
|
||||
|
||||
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation);
|
||||
@@ -153,17 +161,18 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (FixedExposure && (waitbeforepicture > 0))
|
||||
{
|
||||
// ESP_LOGD(TAG, "Fixed Exposure enabled!");
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
Camera.EnableAutoExposure(flashdauer);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
Camera.EnableAutoExposure(flash_duration);
|
||||
waitbeforepicture = 0.2;
|
||||
// flashdauer = (int) (waitbeforepicture * 1000);
|
||||
// takePictureWithFlash(flashdauer);
|
||||
// flash_duration = (int) (waitbeforepicture * 1000);
|
||||
// takePictureWithFlash(flash_duration);
|
||||
// rawImage->SaveToFile("/sdcard/init2.jpg");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowMakeImage::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result;
|
||||
@@ -171,50 +180,52 @@ string ClassFlowMakeImage::getHTMLSingleStep(string host)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMakeImage::doFlow(string zwtime)
|
||||
{
|
||||
string logPath = CreateLogFolder(zwtime);
|
||||
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_stop(); // to save power usage and
|
||||
#endif
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_stop(); // to save power usage and
|
||||
#endif
|
||||
|
||||
takePictureWithFlash(flashdauer);
|
||||
takePictureWithFlash(flash_duration);
|
||||
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_start();
|
||||
#endif
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_start();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash");
|
||||
#endif
|
||||
|
||||
LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
|
||||
|
||||
RemoveOldLogs();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t ClassFlowMakeImage::SendRawJPG(httpd_req_t *req)
|
||||
{
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
return Camera.CaptureToHTTP(req, flashdauer);
|
||||
return Camera.CaptureToHTTP(req, flash_duration);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +233,8 @@ ImageData* ClassFlowMakeImage::SendRawImage()
|
||||
{
|
||||
CImageBasis *zw = new CImageBasis(rawImage);
|
||||
ImageData *id;
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
Camera.CaptureToBasisImage(zw, flashdauer);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
Camera.CaptureToBasisImage(zw, flash_duration);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWMAKEIMAGE_H
|
||||
#define CLASSFFLOWMAKEIMAGE_H
|
||||
|
||||
#include "ClassFlowImage.h"
|
||||
#include "ClassControllCamera.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_4
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
|
||||
|
||||
class ClassFlowMakeImage :
|
||||
public ClassFlowImage
|
||||
{
|
||||
@@ -30,7 +29,7 @@ protected:
|
||||
void CopyFile(string input, string output);
|
||||
|
||||
esp_err_t camera_capture();
|
||||
void takePictureWithFlash(int flashdauer);
|
||||
void takePictureWithFlash(int flash_duration);
|
||||
|
||||
|
||||
void SetInitialParameter(void);
|
||||
@@ -53,3 +52,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif //CLASSFFLOWMAKEIMAGE_H
|
||||
@@ -11,16 +11,10 @@
|
||||
#include "time_sntp.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "POSTPROC";
|
||||
|
||||
//#define SERIAL_DEBUG // testing debug on serial enabled
|
||||
|
||||
|
||||
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
|
||||
#define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
|
||||
|
||||
|
||||
std::string ClassFlowPostProcessing::getNumbersName()
|
||||
{
|
||||
std::string ret="";
|
||||
@@ -128,13 +122,13 @@ void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _exte
|
||||
|
||||
bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
FILE* pFile;
|
||||
char zw[1024];
|
||||
string zwtime, zwvalue, name;
|
||||
bool _done = false;
|
||||
|
||||
UpdatePreValueINI = false; // Konvertierung ins neue Format
|
||||
UpdatePreValueINI = false; // Conversion to the new format
|
||||
|
||||
|
||||
pFile = fopen(FilePreValue.c_str(), "r");
|
||||
@@ -147,21 +141,21 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
if (zwtime.length() == 0)
|
||||
return false;
|
||||
|
||||
zerlegt = HelperZerlegeZeile(zwtime, "\t");
|
||||
if (zerlegt.size() > 1) // neues Format
|
||||
splitted = HelperZerlegeZeile(zwtime, "\t");
|
||||
if (splitted.size() > 1) // Conversion to the new format
|
||||
{
|
||||
while ((zerlegt.size() > 1) && !_done)
|
||||
while ((splitted.size() > 1) && !_done)
|
||||
{
|
||||
name = trim(zerlegt[0]);
|
||||
zwtime = trim(zerlegt[1]);
|
||||
zwvalue = trim(zerlegt[2]);
|
||||
name = trim(splitted[0]);
|
||||
zwtime = trim(splitted[1]);
|
||||
zwvalue = trim(splitted[2]);
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
if (NUMBERS[j]->name == name)
|
||||
{
|
||||
NUMBERS[j]->PreValue = stod(zwvalue.c_str());
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // SIcherheitshalber 1 Stelle mehr, da ggf. Exgtended Resolution an ist (wird erst beim ersten Durchlauf gesetzt)
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // To be on the safe side, 1 digit more, as Exgtended Resolution may be on (will only be set during the first run).
|
||||
|
||||
time_t tStart;
|
||||
int yy, month, dd, hh, mm, ss;
|
||||
@@ -194,18 +188,18 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
else
|
||||
{
|
||||
ESP_LOGD(TAG, "Read line Prevalue.ini: %s", zw);
|
||||
zerlegt = HelperZerlegeZeile(trim(std::string(zw)), "\t");
|
||||
if (zerlegt.size() > 1)
|
||||
splitted = HelperZerlegeZeile(trim(std::string(zw)), "\t");
|
||||
if (splitted.size() > 1)
|
||||
{
|
||||
name = trim(zerlegt[0]);
|
||||
zwtime = trim(zerlegt[1]);
|
||||
zwvalue = trim(zerlegt[2]);
|
||||
name = trim(splitted[0]);
|
||||
zwtime = trim(splitted[1]);
|
||||
zwvalue = trim(splitted[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(pFile);
|
||||
}
|
||||
else // altes Format
|
||||
else // Old Format
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
fclose(pFile);
|
||||
@@ -245,7 +239,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
NUMBERS[0]->ReturnValue = RundeOutput(NUMBERS[0]->Value, NUMBERS[0]->Nachkomma);
|
||||
}
|
||||
|
||||
UpdatePreValueINI = true; // Konvertierung ins neue Format
|
||||
UpdatePreValueINI = true; // Conversion to the new format
|
||||
SavePreValue();
|
||||
}
|
||||
|
||||
@@ -257,7 +251,7 @@ void ClassFlowPostProcessing::SavePreValue()
|
||||
FILE* pFile;
|
||||
string _zw;
|
||||
|
||||
if (!UpdatePreValueINI) // PreValues unverändert --> File muss nicht neu geschrieben werden
|
||||
if (!UpdatePreValueINI) // PreValues unchanged --> File does not have to be rewritten
|
||||
return;
|
||||
|
||||
pFile = fopen(FilePreValue.c_str(), "w");
|
||||
@@ -271,7 +265,7 @@ void ClassFlowPostProcessing::SavePreValue()
|
||||
// ESP_LOGD(TAG, "SaverPreValue %d, Value: %f, Nachkomma %d", j, NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
|
||||
_zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + "\n";
|
||||
ESP_LOGD(TAG, "Write PreValue Zeile: %s", _zw.c_str());
|
||||
ESP_LOGD(TAG, "Write PreValue line: %s", _zw.c_str());
|
||||
if (pFile) {
|
||||
fputs(_zw.c_str(), pFile);
|
||||
}
|
||||
@@ -323,7 +317,7 @@ void ClassFlowPostProcessing::handleDecimalExtendedResolution(string _decsep, st
|
||||
if (toUpper(_value) == "TRUE")
|
||||
_zwdc = true;
|
||||
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->isExtendedResolution = _zwdc;
|
||||
}
|
||||
@@ -359,7 +353,7 @@ void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _val
|
||||
ESP_LOGD(TAG, "ERROR - Decimalshift is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->DecimalShift = _zwdc;
|
||||
NUMBERS[j]->DecimalShiftInitial = _zwdc;
|
||||
@@ -391,7 +385,7 @@ void ClassFlowPostProcessing::handleAnalogDigitalTransitionStart(string _decsep,
|
||||
{
|
||||
_zwdc = stof(_value);
|
||||
}
|
||||
if (_digit == "default" || NUMBERS[j]->name == _digit) // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default" || NUMBERS[j]->name == _digit) // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->AnalogDigitalTransitionStart = _zwdc;
|
||||
|
||||
@@ -399,6 +393,36 @@ void ClassFlowPostProcessing::handleAnalogDigitalTransitionStart(string _decsep,
|
||||
}
|
||||
}
|
||||
|
||||
void ClassFlowPostProcessing::handleAllowNegativeRate(string _decsep, string _value)
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
_digit = "default";
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
bool _rt = false;
|
||||
|
||||
if (toUpper(_value) == "TRUE")
|
||||
_rt = true;
|
||||
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->AllowNegativeRates = _rt;
|
||||
}
|
||||
|
||||
if (NUMBERS[j]->name == _digit)
|
||||
{
|
||||
NUMBERS[j]->AllowNegativeRates = _rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
{
|
||||
@@ -417,7 +441,7 @@ void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
if (toUpper(_value) == "RATECHANGE")
|
||||
_rt = RateChange;
|
||||
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->RateType = _rt;
|
||||
}
|
||||
@@ -453,7 +477,7 @@ void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
|
||||
ESP_LOGD(TAG, "ERROR - MaxRateValue is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->useMaxRateValue = true;
|
||||
NUMBERS[j]->MaxRateValue = _zwdc;
|
||||
@@ -469,7 +493,7 @@ void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
|
||||
|
||||
bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
int _n;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
@@ -479,7 +503,7 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
return false;
|
||||
|
||||
|
||||
if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
InitNUMBERS();
|
||||
@@ -487,65 +511,68 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
std::string _param = GetParameterName(zerlegt[0]);
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
std::string _param = GetParameterName(splitted[0]);
|
||||
|
||||
if ((toUpper(_param) == "EXTENDEDRESOLUTION") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "EXTENDEDRESOLUTION") && (splitted.size() > 1))
|
||||
{
|
||||
handleDecimalExtendedResolution(zerlegt[0], zerlegt[1]);
|
||||
handleDecimalExtendedResolution(splitted[0], splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(_param) == "DECIMALSHIFT") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "DECIMALSHIFT") && (splitted.size() > 1))
|
||||
{
|
||||
handleDecimalSeparator(zerlegt[0], zerlegt[1]);
|
||||
handleDecimalSeparator(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "ANALOGDIGITALTRANSITIONSTART") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ANALOGDIGITALTRANSITIONSTART") && (splitted.size() > 1))
|
||||
{
|
||||
handleAnalogDigitalTransitionStart(zerlegt[0], zerlegt[1]);
|
||||
handleAnalogDigitalTransitionStart(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "MAXRATEVALUE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "MAXRATEVALUE") && (splitted.size() > 1))
|
||||
{
|
||||
handleMaxRateValue(zerlegt[0], zerlegt[1]);
|
||||
handleMaxRateValue(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "MAXRATETYPE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "MAXRATETYPE") && (splitted.size() > 1))
|
||||
{
|
||||
handleMaxRateType(zerlegt[0], zerlegt[1]);
|
||||
handleMaxRateType(splitted[0], splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(_param) == "PREVALUEUSE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "PREVALUEUSE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
PreValueUse = true;
|
||||
}
|
||||
}
|
||||
if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
for (_n = 0; _n < NUMBERS.size(); ++_n)
|
||||
NUMBERS[_n]->checkDigitIncreaseConsistency = true;
|
||||
}
|
||||
if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
handleAllowNegativeRate(splitted[0], splitted[1]);
|
||||
/* Updated to allow individual Settings
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
for (_n = 0; _n < NUMBERS.size(); ++_n)
|
||||
NUMBERS[_n]->AllowNegativeRates = true;
|
||||
*/
|
||||
}
|
||||
if ((toUpper(_param) == "ERRORMESSAGE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ERRORMESSAGE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
ErrorMessage = true;
|
||||
}
|
||||
if ((toUpper(_param) == "IGNORELEADINGNAN") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "IGNORELEADINGNAN") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
IgnoreLeadingNaN = true;
|
||||
}
|
||||
|
||||
|
||||
if ((toUpper(_param) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "PREVALUEAGESTARTUP") && (splitted.size() > 1))
|
||||
{
|
||||
PreValueAgeStartup = std::stoi(zerlegt[1]);
|
||||
PreValueAgeStartup = std::stoi(splitted[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -564,12 +591,12 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
|
||||
if (flowDigit)
|
||||
{
|
||||
anzDIGIT = flowDigit->getAnzahlGENERAL();
|
||||
anzDIGIT = flowDigit->getNumberGENERAL();
|
||||
flowDigit->UpdateNameNumbers(&name_numbers);
|
||||
}
|
||||
if (flowAnalog)
|
||||
{
|
||||
anzANALOG = flowAnalog->getAnzahlGENERAL();
|
||||
anzANALOG = flowAnalog->getNumberGENERAL();
|
||||
flowAnalog->UpdateNameNumbers(&name_numbers);
|
||||
}
|
||||
|
||||
@@ -600,9 +627,9 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
else
|
||||
_number->AnzahlAnalog = 0;
|
||||
|
||||
_number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0)
|
||||
_number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
_number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check
|
||||
_number->ReturnRawValue = ""; // Raw value (with N & leading 0).
|
||||
_number->ReturnValue = ""; // corrected return value, possibly with error message
|
||||
_number->ErrorMessageText = ""; // Error message for consistency check
|
||||
_number->ReturnPreValue = "";
|
||||
_number->PreValueOkay = false;
|
||||
_number->AllowNegativeRates = false;
|
||||
@@ -616,12 +643,12 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
_number->AnalogDigitalTransitionStart=9.2;
|
||||
|
||||
|
||||
_number->FlowRateAct = 0; // m3 / min
|
||||
_number->PreValue = 0; // letzter Wert, der gut ausgelesen wurde
|
||||
_number->Value = 0; // letzer ausgelesener Wert, inkl. Korrekturen
|
||||
_number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0)
|
||||
_number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
_number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check
|
||||
_number->FlowRateAct = 0; // m3 / min
|
||||
_number->PreValue = 0; // last value read out well
|
||||
_number->Value = 0; // last value read out, incl. corrections
|
||||
_number->ReturnRawValue = ""; // raw value (with N & leading 0)
|
||||
_number->ReturnValue = ""; // corrected return value, possibly with error message
|
||||
_number->ErrorMessageText = ""; // Error message for consistency check
|
||||
|
||||
_number->Nachkomma = _number->AnzahlAnalog;
|
||||
|
||||
@@ -653,7 +680,7 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
|
||||
|
||||
_pos_dec_neu = _pos_dec_org + _decShift;
|
||||
|
||||
if (_pos_dec_neu <= 0) { // Komma ist vor der ersten Ziffer
|
||||
if (_pos_dec_neu <= 0) { // comma is before the first digit
|
||||
for (int i = 0; i > _pos_dec_neu; --i){
|
||||
in = in.insert(0, "0");
|
||||
}
|
||||
@@ -661,7 +688,7 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
|
||||
return in;
|
||||
}
|
||||
|
||||
if (_pos_dec_neu > in.length()){ // Komma soll hinter String (123 --> 1230)
|
||||
if (_pos_dec_neu > in.length()){ // Comma should be after string (123 --> 1230)
|
||||
for (int i = in.length(); i < _pos_dec_neu; ++i){
|
||||
in = in.insert(in.length(), "0");
|
||||
}
|
||||
@@ -686,7 +713,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
time_t imagetime = 0;
|
||||
string rohwert;
|
||||
|
||||
// Update Nachkomma, da sich beim Wechsel von CNNType Auto --> xyz auch die Nachkommastellen ändern können:
|
||||
// Update decimal point, as the decimal places can also change when changing from CNNType Auto --> xyz:
|
||||
|
||||
imagetime = flowMakeImage->getTimeImageTaken();
|
||||
if (imagetime == 0)
|
||||
@@ -698,7 +725,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
zwtime = std::string(strftime_buf);
|
||||
|
||||
ESP_LOGD(TAG, "Anzahl NUMBERS: %d", NUMBERS.size());
|
||||
ESP_LOGD(TAG, "Quantity NUMBERS: %d", NUMBERS.size());
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
@@ -707,8 +734,13 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->ErrorMessageText = "";
|
||||
NUMBERS[j]->Value = -1;
|
||||
/* TODO to be discussed, see https://github.com/jomjol/AI-on-the-edge-device/issues/1617 */
|
||||
// NUMBERS[j]->lastvalue = imagetime; // must only be set in case of good value !!! --> move to the end
|
||||
|
||||
/* calculate time difference BEFORE we overwrite the 'lastvalue' */
|
||||
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in seconds
|
||||
|
||||
/* TODO:
|
||||
* We could call `NUMBERS[j]->lastvalue = imagetime;` here and remove all other such calls further down.
|
||||
* But we should check nothing breaks! */
|
||||
|
||||
UpdateNachkommaDecimalShift();
|
||||
|
||||
@@ -735,7 +767,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
if (NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float, NUMBERS[j]->AnalogDigitalTransitionStart) + NUMBERS[j]->ReturnRawValue;
|
||||
else
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution nur falls es keine analogen Ziffern gibt
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution only if there are no analogue digits
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After digital->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
@@ -769,13 +801,13 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
WriteDataLog(j);
|
||||
continue; // es gibt keinen Zahl, da noch ein N vorhanden ist.
|
||||
continue; // there is no number because there is still an N.
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After findDelimiterPos: ReturnValue %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
// Lösche führende Nullen (außer es ist nur noch einen 0)
|
||||
// Delete leading zeros (unless there is only one 0 left)
|
||||
while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0'))
|
||||
NUMBERS[j]->ReturnValue.erase(0, 1);
|
||||
#ifdef SERIAL_DEBUG
|
||||
@@ -806,7 +838,6 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After checkDigitIncreaseConsistency: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
|
||||
|
||||
if (!NUMBERS[j]->AllowNegativeRates)
|
||||
{
|
||||
@@ -817,7 +848,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))
|
||||
) ;
|
||||
#endif
|
||||
// Bei isExtendedResolution Ungenauigkeit von 0.2 mit einrechnen.
|
||||
// Include inaccuracy of 0.2 for isExtendedResolution.
|
||||
if (NUMBERS[j]->Value >= (NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))) && NUMBERS[j]->isExtendedResolution) {
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = to_string(NUMBERS[j]->PreValue);
|
||||
@@ -825,19 +856,21 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " ";
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After AllowNegativeRates: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden
|
||||
|
||||
difference /= 60;
|
||||
NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference;
|
||||
NUMBERS[j]->ReturnRateValue = to_string(NUMBERS[j]->FlowRateAct);
|
||||
@@ -852,29 +885,28 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
|
||||
if (abs(_ratedifference) > abs(NUMBERS[j]->MaxRateValue))
|
||||
{
|
||||
WriteDataLog(j);
|
||||
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " - Rate: " + RundeOutput(_ratedifference, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->ReturnRateValue = "";
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After MaxRateCheck: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
|
||||
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->PreValue = NUMBERS[j]->Value;
|
||||
NUMBERS[j]->PreValueOkay = true;
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
|
||||
|
||||
NUMBERS[j]->ReturnValue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
|
||||
@@ -882,7 +914,6 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
UpdatePreValueINI = true;
|
||||
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
}
|
||||
@@ -922,22 +953,22 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
{
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi) // es gibt nur digitale ziffern
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi) // There are only digital digits
|
||||
{
|
||||
// ESP_LOGD(TAG, "Nurdigital");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
|
||||
if (NUMBERS[j]->isExtendedResolution && flowDigit->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowDigit->isExtendedResolution()) // Extended resolution is on and should also be used for this digit.
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShift-1;
|
||||
|
||||
NUMBERS[j]->Nachkomma = -NUMBERS[j]->DecimalShift;
|
||||
}
|
||||
|
||||
if (!NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) // es gibt nur analoge ziffern
|
||||
if (!NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
|
||||
{
|
||||
// ESP_LOGD(TAG, "Nur analog");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution())
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShift-1;
|
||||
|
||||
NUMBERS[j]->Nachkomma = -NUMBERS[j]->DecimalShift;
|
||||
@@ -950,7 +981,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
NUMBERS[j]->Nachkomma = NUMBERS[j]->analog_roi->ROI.size() - NUMBERS[j]->DecimalShift;
|
||||
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // Extended resolution is on and should also be used for this digit.
|
||||
NUMBERS[j]->Nachkomma = NUMBERS[j]->Nachkomma+1;
|
||||
|
||||
}
|
||||
@@ -1014,7 +1045,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
bool no_nulldurchgang = false;
|
||||
|
||||
pot = _decilamshift;
|
||||
if (!_isanalog) // falls es keine analogwerte gibt, kann die letzte nicht bewertet werden
|
||||
if (!_isanalog) // if there are no analogue values, the last one cannot be evaluated
|
||||
{
|
||||
pot++;
|
||||
}
|
||||
@@ -1040,14 +1071,14 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
{
|
||||
if (aktdigit != olddigit)
|
||||
{
|
||||
input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // Neue Digit wird durch alte Digit ersetzt;
|
||||
input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // New Digit is replaced by old Digit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aktdigit == olddigit) // trotz Nulldurchgang wurde Stelle nicht hochgezählt --> addiere 1
|
||||
if (aktdigit == olddigit) // despite zero crossing, digit was not incremented --> add 1
|
||||
{
|
||||
input = input + ((float) (1)) * pow(10, pot); // addiere 1 an der Stelle
|
||||
input = input + ((float) (1)) * pow(10, pot); // add 1 at the point
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __FLOWPOSTPROCESSING__
|
||||
#define __FLOWPOSTPROCESSING__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWPOSTPROCESSING_H
|
||||
#define CLASSFFLOWPOSTPROCESSING_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "ClassFlowMakeImage.h"
|
||||
@@ -18,7 +20,7 @@ protected:
|
||||
|
||||
int PreValueAgeStartup;
|
||||
bool ErrorMessage;
|
||||
bool IgnoreLeadingNaN; // SPEZIALFALL für User Gustl
|
||||
bool IgnoreLeadingNaN; // SPECIAL CASE for User Gustl ???
|
||||
|
||||
|
||||
ClassFlowCNNGeneral* flowAnalog;
|
||||
@@ -41,6 +43,8 @@ protected:
|
||||
void handleDecimalExtendedResolution(string _decsep, string _value);
|
||||
void handleMaxRateType(string _decsep, string _value);
|
||||
void handleAnalogDigitalTransitionStart(string _decsep, string _value);
|
||||
void handleAllowNegativeRate(string _decsep, string _value);
|
||||
|
||||
std::string GetStringReadouts(general);
|
||||
|
||||
void WriteDataLog(int _index);
|
||||
@@ -76,4 +80,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif //CLASSFFLOWPOSTPROCESSING_H
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "Helper.h"
|
||||
|
||||
#include "time_sntp.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -37,7 +37,7 @@ ClassFlowWriteList::ClassFlowWriteList(std::vector<ClassFlow*>* lfc)
|
||||
|
||||
bool ClassFlowWriteList::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -45,18 +45,12 @@ bool ClassFlowWriteList::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0)
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
/*
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
}
|
||||
*/
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWPWRITELIST_H
|
||||
#define CLASSFFLOWPWRITELIST_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
|
||||
@@ -20,3 +24,4 @@ public:
|
||||
string name(){return "ClassFlowWriteList";};
|
||||
};
|
||||
|
||||
#endif //CLASSFFLOWPWRITELIST_H
|
||||
@@ -1,101 +0,0 @@
|
||||
#ifndef CAMERADEFINED
|
||||
#define CAMERADEFINED
|
||||
|
||||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM GPIO_NUM_32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM GPIO_NUM_0
|
||||
#define SIOD_GPIO_NUM GPIO_NUM_26
|
||||
#define SIOC_GPIO_NUM GPIO_NUM_27
|
||||
|
||||
#define Y9_GPIO_NUM GPIO_NUM_35
|
||||
#define Y8_GPIO_NUM GPIO_NUM_34
|
||||
#define Y7_GPIO_NUM GPIO_NUM_39
|
||||
#define Y6_GPIO_NUM GPIO_NUM_36
|
||||
#define Y5_GPIO_NUM GPIO_NUM_21
|
||||
#define Y4_GPIO_NUM GPIO_NUM_19
|
||||
#define Y3_GPIO_NUM GPIO_NUM_18
|
||||
#define Y2_GPIO_NUM GPIO_NUM_5
|
||||
#define VSYNC_GPIO_NUM GPIO_NUM_25
|
||||
#define HREF_GPIO_NUM GPIO_NUM_23
|
||||
#define PCLK_GPIO_NUM GPIO_NUM_22
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static camera_config_t camera_config = {
|
||||
.pin_pwdn = PWDN_GPIO_NUM,
|
||||
.pin_reset = RESET_GPIO_NUM,
|
||||
.pin_xclk = XCLK_GPIO_NUM,
|
||||
.pin_sscb_sda = SIOD_GPIO_NUM,
|
||||
.pin_sscb_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 20MHz or 10MHz for OV2640 double FPS (Experimental)
|
||||
.xclk_freq_hz = 20000000,
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
.pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG
|
||||
// .pixel_format = PIXFORMAT_RGB888,//YUV422,GRAYSCALE,RGB565,JPEG
|
||||
// .frame_size = FRAMESIZE_QVGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
|
||||
.frame_size = FRAMESIZE_SVGA,//QQVGA-QXGA 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
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,7 @@ extern "C" {
|
||||
|
||||
#include <string.h>
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
@@ -31,9 +32,6 @@ extern "C" {
|
||||
|
||||
static const char* TAG = "HELPER";
|
||||
|
||||
//#define ISWINDOWS_TRUE
|
||||
#define PATH_MAX_STRING_SIZE 256
|
||||
|
||||
using namespace std;
|
||||
|
||||
unsigned int systemStatus = 0;
|
||||
@@ -41,52 +39,59 @@ unsigned int systemStatus = 0;
|
||||
sdmmc_cid_t SDCardCid;
|
||||
sdmmc_csd_t SDCardCsd;
|
||||
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
string getESPHeapInfo(){
|
||||
string espInfoResultStr = "";
|
||||
char aMsgBuf[80];
|
||||
|
||||
multi_heap_info_t aMultiHead_info ;
|
||||
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
|
||||
sprintf(aMsgBuf," Free Heap Size: %ld", (long) aFreeHeapSize);
|
||||
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
|
||||
sprintf(aMsgBuf," Heap: %ld", (long) aFreeHeapSize);
|
||||
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 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);
|
||||
|
||||
|
||||
sprintf(aMsgBuf,"Heap Total: %ld", (long) aFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Min Free: %ld", (long) aMinFreeHeapSize);
|
||||
|
||||
sprintf(aMsgBuf," | SPI Free: %ld", (long) aFreeSPIHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," larg. Block: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf," | SPI Larg Block: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," SPI Heap: %ld", (long) aFreeSPIHeapSize);
|
||||
sprintf(aMsgBuf," | SPI Min Free: %ld", (long) aMinFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Min Free Heap Size: %ld", (long) aMinFreeHeadSize);
|
||||
sprintf(aMsgBuf," NOT_SPI Heap: %ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
|
||||
|
||||
sprintf(aMsgBuf," | Int Free: %ld", (long) (aFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," largest Block Size: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf," Internal Heap: %ld", (long) (aFreeInternalHeapSize));
|
||||
sprintf(aMsgBuf," | Int Larg Block: %ld", (long) aHeapIntLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Internal Min Heap free: %ld", (long) (aMinFreeInternalHeapSize));
|
||||
sprintf(aMsgBuf," | Int Min Free: %ld", (long) (aMinFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
|
||||
size_t getESPHeapSize(){
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
return aFreeHeapSize;
|
||||
size_t getESPHeapSize()
|
||||
{
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
}
|
||||
|
||||
size_t getInternalESPHeapSize() {
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
return aFreeInternalHeapSize;
|
||||
|
||||
size_t getInternalESPHeapSize()
|
||||
{
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardPartitionSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, tot_sect;
|
||||
@@ -100,6 +105,7 @@ string getSDCardPartitionSize(){
|
||||
return std::to_string(tot_sect);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardFreePartitionSpace(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, fre_sect;
|
||||
@@ -113,6 +119,7 @@ string getSDCardFreePartitionSpace(){
|
||||
return std::to_string(fre_sect);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardPartitionAllocationSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, allocation_size;
|
||||
@@ -132,6 +139,7 @@ void SaveSDCardInfo(sdmmc_card_t* card) {
|
||||
SDCardCsd = card->csd;
|
||||
}
|
||||
|
||||
|
||||
string getSDCardManufacturer(){
|
||||
string SDCardManufacturer = SDCardParseManufacturerIDs(SDCardCid.mfg_id);
|
||||
//ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str());
|
||||
@@ -139,6 +147,7 @@ string getSDCardManufacturer(){
|
||||
return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")");
|
||||
}
|
||||
|
||||
|
||||
string getSDCardName(){
|
||||
char *SDCardName = SDCardCid.name;
|
||||
//ESP_LOGD(TAG, "SD Card Name: %s", SDCardName);
|
||||
@@ -146,6 +155,7 @@ string getSDCardName(){
|
||||
return std::string(SDCardName);
|
||||
}
|
||||
|
||||
|
||||
string 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());
|
||||
@@ -153,6 +163,7 @@ string getSDCardCapacity(){
|
||||
return std::to_string(SDCardCapacity);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardSectorSize(){
|
||||
int SDCardSectorSize = SDCardCsd.sector_size;
|
||||
//ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str());
|
||||
@@ -169,24 +180,6 @@ void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec, bool silent)
|
||||
{
|
||||
FILE *pfile;
|
||||
|
||||
ESP_LOGD(TAG, "open file %s in mode %s", nm, _mode);
|
||||
|
||||
if ((pfile = fopen(nm, _mode)) != NULL) {
|
||||
if (!silent) ESP_LOGE(TAG, "File %s successfully opened", nm);
|
||||
}
|
||||
else {
|
||||
if (!silent) ESP_LOGE(TAG, "Error: file %s does not exist!", nm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pfile;
|
||||
}
|
||||
|
||||
std::string FormatFileName(std::string input)
|
||||
{
|
||||
#ifdef ISWINDOWS_TRUE
|
||||
@@ -230,6 +223,7 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MakeDir(std::string _what)
|
||||
{
|
||||
int mk_ret = mkdir(_what.c_str(), 0775);
|
||||
@@ -242,7 +236,6 @@ bool MakeDir(std::string _what)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ctype_space(const char c, string adddelimiter)
|
||||
{
|
||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11)
|
||||
@@ -255,6 +248,7 @@ bool ctype_space(const char c, string adddelimiter)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
string trim(string istring, string adddelimiter)
|
||||
{
|
||||
bool trimmed = false;
|
||||
@@ -281,6 +275,7 @@ string trim(string istring, string adddelimiter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t findDelimiterPos(string input, string delimiter)
|
||||
{
|
||||
size_t pos = std::string::npos;
|
||||
@@ -309,7 +304,7 @@ bool RenameFile(string from, string to)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(from.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(from.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
|
||||
@@ -322,11 +317,23 @@ bool RenameFile(string from, string to)
|
||||
}
|
||||
|
||||
|
||||
bool FileExists(string filename)
|
||||
{
|
||||
FILE* fpSourceFile = fopen(filename.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fclose(fpSourceFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DeleteFile(string fn)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(fn.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(fn.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", fn.c_str());
|
||||
@@ -344,21 +351,21 @@ bool CopyFile(string input, string output)
|
||||
input = FormatFileName(input);
|
||||
output = FormatFileName(output);
|
||||
|
||||
if (toUpper(input).compare("/SDCARD/WLAN.INI") == 0)
|
||||
if (toUpper(input).compare(WLAN_CONFIG_FILE) == 0)
|
||||
{
|
||||
ESP_LOGD(TAG, "wlan.ini kann nicht kopiert werden!");
|
||||
return false;
|
||||
}
|
||||
|
||||
char cTemp;
|
||||
FILE* fpSourceFile = OpenFileAndWait(input.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(input.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* fpTargetFile = OpenFileAndWait(output.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(output.c_str(), "wb");
|
||||
|
||||
// Code Section
|
||||
|
||||
@@ -376,6 +383,7 @@ bool CopyFile(string input, string output)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
string getFileFullFileName(string filename)
|
||||
{
|
||||
size_t lastpos = filename.find_last_of('/');
|
||||
@@ -390,6 +398,7 @@ string getFileFullFileName(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
string getDirectory(string filename)
|
||||
{
|
||||
size_t lastpos = filename.find('/');
|
||||
@@ -406,6 +415,7 @@ string getDirectory(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
string getFileType(string filename)
|
||||
{
|
||||
size_t lastpos = filename.rfind(".", filename.length());
|
||||
@@ -424,16 +434,17 @@ string getFileType(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
/* recursive mkdir */
|
||||
int mkdir_r(const char *dir, const mode_t mode) {
|
||||
char tmp[PATH_MAX_STRING_SIZE];
|
||||
char tmp[FILE_PATH_MAX];
|
||||
char *p = NULL;
|
||||
struct stat sb;
|
||||
size_t len;
|
||||
|
||||
/* copy path */
|
||||
len = strnlen (dir, PATH_MAX_STRING_SIZE);
|
||||
if (len == 0 || len == PATH_MAX_STRING_SIZE) {
|
||||
len = strnlen (dir, FILE_PATH_MAX);
|
||||
if (len == 0 || len == FILE_PATH_MAX) {
|
||||
return -1;
|
||||
}
|
||||
memcpy (tmp, dir, len);
|
||||
@@ -481,6 +492,7 @@ int mkdir_r(const char *dir, const mode_t mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
string toUpper(string in)
|
||||
{
|
||||
for (int i = 0; i < in.length(); ++i)
|
||||
@@ -489,6 +501,7 @@ string toUpper(string in)
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
string toLower(string in)
|
||||
{
|
||||
for (int i = 0; i < in.length(); ++i)
|
||||
@@ -497,6 +510,7 @@ string toLower(string in)
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
// CPU Temp
|
||||
extern "C" uint8_t temprature_sens_read();
|
||||
float temperatureRead()
|
||||
@@ -504,12 +518,14 @@ float temperatureRead()
|
||||
return (temprature_sens_read() - 32) / 1.8;
|
||||
}
|
||||
|
||||
|
||||
time_t addDays(time_t startTime, int days) {
|
||||
struct tm* tm = localtime(&startTime);
|
||||
tm->tm_mday += days;
|
||||
return mktime(tm);
|
||||
}
|
||||
|
||||
|
||||
int removeFolder(const char* folderPath, const char* logTag) {
|
||||
//ESP_LOGD(logTag, "Delete content in path %s", folderPath);
|
||||
|
||||
@@ -557,7 +573,6 @@ std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
|
||||
{
|
||||
std::vector<string> Output;
|
||||
@@ -602,6 +617,17 @@ std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
|
||||
}
|
||||
|
||||
|
||||
std::string ReplaceString(std::string subject, const std::string& search,
|
||||
const std::string& replace) {
|
||||
size_t pos = 0;
|
||||
while ((pos = subject.find(search, pos)) != std::string::npos) {
|
||||
subject.replace(pos, search.length(), replace);
|
||||
pos += replace.length();
|
||||
}
|
||||
return subject;
|
||||
}
|
||||
|
||||
|
||||
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
|
||||
/* SD Card Manufacturer Database */
|
||||
struct SDCard_Manufacturer_database {
|
||||
@@ -610,6 +636,7 @@ struct SDCard_Manufacturer_database {
|
||||
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[] = {
|
||||
@@ -720,6 +747,7 @@ struct SDCard_Manufacturer_database database[] = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Parse SD Card Manufacturer Database */
|
||||
string SDCardParseManufacturerIDs(int id)
|
||||
{
|
||||
@@ -782,6 +810,7 @@ void setSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
|
||||
}
|
||||
|
||||
|
||||
void clearSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
systemStatus = systemStatus | ~flag; // clear bit
|
||||
|
||||
@@ -790,10 +819,12 @@ void clearSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
|
||||
}
|
||||
|
||||
|
||||
int getSystemStatus(void) {
|
||||
return systemStatus;
|
||||
}
|
||||
|
||||
|
||||
bool isSetSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
//ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
|
||||
|
||||
@@ -805,11 +836,17 @@ bool isSetSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t getUpTime(void) {
|
||||
return (uint32_t)(esp_timer_get_time()/1000/1000); // in seconds
|
||||
}
|
||||
|
||||
|
||||
string getResetReason(void) {
|
||||
std::string reasonText;
|
||||
|
||||
switch(esp_reset_reason()) {
|
||||
case ESP_RST_POWERON: reasonText = "Power-on event"; break; //!< Reset due to power-on event
|
||||
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
|
||||
@@ -827,6 +864,7 @@ string getResetReason(void) {
|
||||
return reasonText;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current uptime formated ad xxf xxh xxm [xxs]
|
||||
*/
|
||||
@@ -834,7 +872,7 @@ std::string getFormatedUptime(bool compact) {
|
||||
char buf[20];
|
||||
#pragma GCC diagnostic ignored "-Wformat-truncation"
|
||||
|
||||
int uptime = (uint32_t)(esp_timer_get_time()/1000/1000); // in seconds
|
||||
int uptime = getUpTime(); // in seconds
|
||||
|
||||
int days = int(floor(uptime / (3600*24)));
|
||||
int hours = int(floor((uptime - days * 3600*24) / (3600)));
|
||||
@@ -851,6 +889,7 @@ std::string getFormatedUptime(bool compact) {
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
|
||||
const char* get404(void) {
|
||||
return
|
||||
"<pre>\n\n\n\n"
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef HELPER_H
|
||||
#define HELPER_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
@@ -14,13 +18,11 @@ bool CopyFile(string input, string output);
|
||||
bool DeleteFile(string fn);
|
||||
bool RenameFile(string from, string to);
|
||||
bool MakeDir(std::string _what);
|
||||
bool FileExists(string filename);
|
||||
|
||||
|
||||
string RundeOutput(double _in, int _anzNachkomma);
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1, bool silent = true);
|
||||
|
||||
size_t findDelimiterPos(string input, string delimiter);
|
||||
//string trim(string istring);
|
||||
string trim(string istring, string adddelimiter = "");
|
||||
@@ -30,6 +32,7 @@ string getFileType(string filename);
|
||||
string getFileFullFileName(string filename);
|
||||
string getDirectory(string filename);
|
||||
|
||||
|
||||
int mkdir_r(const char *dir, const mode_t mode);
|
||||
int removeFolder(const char* folderPath, const char* logTag);
|
||||
|
||||
@@ -67,7 +70,7 @@ string getMac(void);
|
||||
|
||||
/* Error bit fields
|
||||
One bit per error
|
||||
Make sure it matches https://github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes */
|
||||
Make sure it matches https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes */
|
||||
enum SystemStatusFlag_t { // One bit per error
|
||||
// First Byte
|
||||
SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 1, Critical Error
|
||||
@@ -84,7 +87,10 @@ void clearSystemStatusFlag(SystemStatusFlag_t flag);
|
||||
int getSystemStatus(void);
|
||||
bool isSetSystemStatusFlag(SystemStatusFlag_t flag);
|
||||
|
||||
time_t getUpTime(void);
|
||||
string getResetReason(void);
|
||||
std::string getFormatedUptime(bool compact);
|
||||
|
||||
const char* get404(void);
|
||||
|
||||
#endif //HELPER_H
|
||||
|
||||
178
code/components/jomjol_helper/esp_sys.cpp
Normal file
178
code/components/jomjol_helper/esp_sys.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#include "esp_sys.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "esp_chip_info.h"
|
||||
|
||||
|
||||
void Restart() {
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
//source : https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/misc_system_api.html#_CPPv416esp_chip_model_t
|
||||
|
||||
//https://github.com/espressif/esp-idf/blob/8464186e67e34b417621df6b6f1f289a6c60b859/components/esp_hw_support/include/esp_chip_info.h
|
||||
/*
|
||||
typedef enum {
|
||||
CHIP_ESP32 = 1, //!< ESP32
|
||||
CHIP_ESP32S2 = 2, //!< ESP32-S2
|
||||
CHIP_ESP32S3 = 9, //!< ESP32-S3
|
||||
CHIP_ESP32C3 = 5, //!< ESP32-C3
|
||||
CHIP_ESP32H4 = 6, //!< ESP32-H4
|
||||
CHIP_ESP32C2 = 12, //!< ESP32-C2
|
||||
CHIP_ESP32C6 = 13, //!< ESP32-C6
|
||||
CHIP_ESP32H2 = 16, //!< ESP32-H2
|
||||
CHIP_POSIX_LINUX = 999, //!< The code is running on POSIX/Linux simulator
|
||||
} esp_chip_model_t;
|
||||
*/
|
||||
|
||||
char* GetChipModel(){
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
switch((int)chipInfo.model) {
|
||||
case 0 : return (char*)"ESP8266";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32 : return (char*)"ESP32";
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
|
||||
case (int)esp_chip_model_t::CHIP_ESP32S2 : return (char*)"ESP32-S2";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32S3 : return (char*)"ESP32-S3";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32C3 : return (char*)"ESP32-C3";
|
||||
case 6 : return (char*)"ESP32-H4";
|
||||
case 12 : return (char*)"ESP32-C2";
|
||||
case 13 : return (char*)"ESP32-C6";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32H4 : return (char*)"ESP32-H4";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32C2 : return (char*)"ESP32-C2";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32C6 : return (char*)"ESP32-C6";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32H2 : return (char*)"ESP32-H2";
|
||||
case 16 : return (char*)"ESP32-H2";
|
||||
//case (int)esp_chip_model_t::CHIP_POSIX_LINUX : return (char*)"CHIP_POSIX_LINUX";
|
||||
|
||||
#endif
|
||||
}
|
||||
return (char*)"Chip Unknown";
|
||||
}
|
||||
|
||||
uint8_t GetChipCoreCount() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.cores;
|
||||
}
|
||||
|
||||
uint16_t GetChipRevision() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.revision;
|
||||
}
|
||||
|
||||
uint32_t GetChipfeatures() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.features;
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetFreeHeap() {
|
||||
return esp_get_free_heap_size();
|
||||
}
|
||||
|
||||
uint32_t GetLeastHeapFreeSinceBoot() {
|
||||
return esp_get_minimum_free_heap_size();
|
||||
}
|
||||
|
||||
|
||||
std::string get_device_info()
|
||||
{
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
|
||||
std::string espInfoResultStr = "";
|
||||
char aMsgBuf[40];
|
||||
|
||||
espInfoResultStr += "Device Info:";
|
||||
espInfoResultStr += "---------------\n";
|
||||
espInfoResultStr += "Chip Model: " + std::string(GetChipModel()) +"\n";
|
||||
sprintf(aMsgBuf,"Chip Revision: %d\n", chip_info.revision);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"CPU Cores: %d\n", chip_info.cores);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"Flash Memory: %dMB\n", spi_flash_get_chip_size()/(1024*1024));
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
if(chip_info.features & CHIP_FEATURE_WIFI_BGN)
|
||||
//espInfoResultStr += "Base MAC: " + std::string(getMac()) +"\n";
|
||||
espInfoResultStr += "ESP-IDF version: " + std::string(esp_get_idf_version()) +"\n";
|
||||
if((chip_info.features & CHIP_FEATURE_WIFI_BGN) || (chip_info.features & CHIP_FEATURE_BT) ||
|
||||
(chip_info.features & CHIP_FEATURE_BLE) || (chip_info.features & CHIP_FEATURE_EMB_FLASH))
|
||||
{
|
||||
espInfoResultStr += "Characteristics:\n";
|
||||
if(chip_info.features & CHIP_FEATURE_WIFI_BGN)
|
||||
espInfoResultStr += " WiFi 2.4GHz\n";
|
||||
if(chip_info.features & CHIP_FEATURE_BT)
|
||||
espInfoResultStr += " Bluetooth Classic\n";
|
||||
if(chip_info.features & CHIP_FEATURE_BLE)
|
||||
espInfoResultStr += " Bluetooth Low Energy\n";
|
||||
if(chip_info.features & CHIP_FEATURE_EMB_FLASH)
|
||||
espInfoResultStr += " Embedded Flash memory\n";
|
||||
else
|
||||
espInfoResultStr += " External Flash memory\n";
|
||||
}
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
sprintf(aMsgBuf,"spiram size %u\n", esp_spiram_get_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem free %u\n", esp_himem_get_free_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem phys %u\n", esp_himem_get_phys_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem reserved %u\n", esp_himem_reserved_area_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
#endif
|
||||
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
|
||||
size_t getFreeMemoryInternal(){ //Current Free Memory
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT) - heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
size_t getFreeMemorySPIRAM(){ //Current Free Memory
|
||||
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
|
||||
size_t getLargestFreeBlockInternal(){ //Largest Free Block
|
||||
return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
size_t getLargestFreeBlockSPIRAM(){ //Largest Free Block
|
||||
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
|
||||
size_t getMinEverFreeMemInternal(){ //Min. Ever Free Size
|
||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
size_t getMinEverFreeMemSPIRAM(){ //Min. Ever Free Size
|
||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
size_t getHimemTotSpace(){
|
||||
return esp_himem_get_phys_size();
|
||||
}
|
||||
|
||||
size_t getHimemFreeSpace(){
|
||||
return esp_himem_get_free_size();
|
||||
}
|
||||
|
||||
size_t getHimemReservedArea(){
|
||||
return esp_himem_reserved_area_size();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
54
code/components/jomjol_helper/esp_sys.h
Normal file
54
code/components/jomjol_helper/esp_sys.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#ifndef ESP_SYS_H
|
||||
#define ESP_SYS_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
// Device libraries (ESP-IDF)
|
||||
#include <esp_system.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
// for esp_spiram_get_size
|
||||
extern "C" {
|
||||
#include <esp32/spiram.h>
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#include <esp32/himem.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Restart();
|
||||
char *GetChipModel();
|
||||
uint8_t GetChipCoreCount();
|
||||
uint16_t GetChipRevision();
|
||||
uint32_t GetChipfeatures();
|
||||
uint32_t GetFreeHeap();
|
||||
uint32_t GetLeastHeapFreeSinceBoot();
|
||||
|
||||
std::string get_device_info();
|
||||
|
||||
size_t getFreeMemoryInternal();
|
||||
size_t getFreeMemorySPIRAM();
|
||||
size_t getLargestFreeBlockInternal();
|
||||
size_t getLargestFreeBlockSPIRAM();
|
||||
size_t getMinEverFreeMemInternal();
|
||||
size_t getMinEverFreeMemSPIRAM();
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
size_t getHimemTotSpace();
|
||||
size_t getHimemFreeSpace();
|
||||
size_t getHimemReservedArea();
|
||||
#endif
|
||||
|
||||
|
||||
#endif //ESP_SYS_H
|
||||
|
||||
#endif // DEBUG_ENABLE_SYSINFO
|
||||
115
code/components/jomjol_helper/himem_memory_check.cpp
Normal file
115
code/components/jomjol_helper/himem_memory_check.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
|
||||
#include "himem_memory_check.h"
|
||||
|
||||
//source adapted from : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c
|
||||
|
||||
|
||||
//Fill memory with pseudo-random data generated from the given seed.
|
||||
//Fills the memory in 32-bit words for speed.
|
||||
static void fill_mem_seed(int seed, void *mem, int len)
|
||||
{
|
||||
uint32_t *p = (uint32_t *)mem;
|
||||
unsigned int rseed = seed ^ 0xa5a5a5a5;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
*p++ = rand_r(&rseed);
|
||||
}
|
||||
}
|
||||
|
||||
//Check the memory filled by fill_mem_seed. Returns true if the data matches the data
|
||||
//that fill_mem_seed wrote (when given the same seed).
|
||||
//Returns true if there's a match, false when the region differs from what should be there.
|
||||
static bool check_mem_seed(int seed, void *mem, int len, int phys_addr)
|
||||
{
|
||||
uint32_t *p = (uint32_t *)mem;
|
||||
unsigned int rseed = seed ^ 0xa5a5a5a5;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
uint32_t ex = rand_r(&rseed);
|
||||
if (ex != *p) {
|
||||
//printf("check_mem_seed: %x has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", phys_addr+((char*)p-(char*)mem), *p, ex);
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Allocate a himem region, fill it with data, check it and release it.
|
||||
static bool test_region(int check_size, int seed)
|
||||
{
|
||||
esp_himem_handle_t mh; //Handle for the address space we're using
|
||||
esp_himem_rangehandle_t rh; //Handle for the actual RAM.
|
||||
bool ret = true;
|
||||
|
||||
//Allocate the memory we're going to check.
|
||||
ESP_ERROR_CHECK(esp_himem_alloc(check_size, &mh));
|
||||
//Allocate a block of address range
|
||||
ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ, &rh));
|
||||
for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
|
||||
uint32_t *ptr = NULL;
|
||||
//Map in block, write pseudo-random data, unmap block.
|
||||
ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
|
||||
fill_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ); //
|
||||
ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
|
||||
}
|
||||
vTaskDelay(5); //give the OS some time to do things so the task watchdog doesn't bark
|
||||
for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
|
||||
uint32_t *ptr;
|
||||
//Map in block, check against earlier written pseudo-random data, unmap block.
|
||||
ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
|
||||
if (!check_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ, i)) {
|
||||
//printf("Error in block %d\n", i / ESP_HIMEM_BLKSZ);
|
||||
ret = false;
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
|
||||
if (!ret) break; //don't check rest of blocks if error occurred
|
||||
}
|
||||
//Okay, all done!
|
||||
ESP_ERROR_CHECK(esp_himem_free(mh));
|
||||
ESP_ERROR_CHECK(esp_himem_free_map_range(rh));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string himem_memory_check()
|
||||
{
|
||||
size_t memcnt=esp_himem_get_phys_size();
|
||||
size_t memfree=esp_himem_get_free_size();
|
||||
|
||||
std::string espInfoResultStr = "";
|
||||
char aMsgBuf[40];
|
||||
|
||||
espInfoResultStr += "Running HIMEM memory check";
|
||||
|
||||
sprintf(aMsgBuf,"Himem has %dKiB of memory", (int)memcnt/1024);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
|
||||
sprintf(aMsgBuf,"%dKiB of which is free", (int)memfree/1024);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
|
||||
espInfoResultStr += "\n please wait ....\n";
|
||||
|
||||
//running memory checks
|
||||
//assert(test_region(memfree, 0xaaaa));
|
||||
|
||||
if(test_region(memfree, 0xaaaa)) {
|
||||
espInfoResultStr += "Himem check Failed!\n";
|
||||
} else {
|
||||
espInfoResultStr += "Himem check Done!\n";
|
||||
}
|
||||
|
||||
return espInfoResultStr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUG_HIMEM_MEMORY_CHECK
|
||||
41
code/components/jomjol_helper/himem_memory_check.h
Normal file
41
code/components/jomjol_helper/himem_memory_check.h
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
|
||||
#ifndef HIMEM_MEMORY_CHECK_H
|
||||
#define HIMEM_MEMORY_CHECK_H
|
||||
|
||||
|
||||
|
||||
//source : //source : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp32/himem.h"
|
||||
|
||||
#include <string>
|
||||
#include "esp32/himem.h"
|
||||
|
||||
|
||||
std::string himem_memory_check();
|
||||
|
||||
#endif //HIMEM_MEMORY_CHECK_H
|
||||
|
||||
#endif // DEBUG_HIMEM_MEMORY_CHECK
|
||||
87
code/components/jomjol_helper/perfmon.c
Normal file
87
code/components/jomjol_helper/perfmon.c
Normal file
@@ -0,0 +1,87 @@
|
||||
//source : https://github.com/Carbon225/esp32-perfmon
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
/*
|
||||
ESP32 CPU usage monitor
|
||||
Gives you a rough idea of how the Xtensa cores are utilized.
|
||||
|
||||
Works by attaching idle hooks and measuring how often they get called. The core usage is calculated: usage% = idle ticks since last measurement / expected idle ticks if core were idle * 100%. The expected idle tick count was measured by running an empty program.
|
||||
|
||||
Limitations:
|
||||
Should only be used for user information, not in logic that needs accurate values
|
||||
New IDF versions could optimize performance and therefore introduce an error to usage estimation.
|
||||
When one core is at 100% the other might report a negative value
|
||||
|
||||
Usage:
|
||||
#include "perfmon.h"
|
||||
Call perfmon_start() once
|
||||
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_ENABLE_PERFMON
|
||||
|
||||
#include "perfmon.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
static const char *TAG = "perfmon";
|
||||
|
||||
static uint64_t idle0Calls = 0;
|
||||
static uint64_t idle1Calls = 0;
|
||||
|
||||
#if defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_240)
|
||||
static const uint64_t MaxIdleCalls = 1855000;
|
||||
#elif defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_160)
|
||||
static const uint64_t MaxIdleCalls = 1233100;
|
||||
#else
|
||||
#error "Unsupported CPU frequency"
|
||||
#endif
|
||||
|
||||
static bool idle_task_0()
|
||||
{
|
||||
idle0Calls += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool idle_task_1()
|
||||
{
|
||||
idle1Calls += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void perfmon_task(void *args)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
float idle0 = idle0Calls;
|
||||
float idle1 = idle1Calls;
|
||||
idle0Calls = 0;
|
||||
idle1Calls = 0;
|
||||
|
||||
int cpu0 = 100.f - idle0 / MaxIdleCalls * 100.f;
|
||||
int cpu1 = 100.f - idle1 / MaxIdleCalls * 100.f;
|
||||
|
||||
ESP_LOGI(TAG, "Core 0 at %d%%", cpu0);
|
||||
ESP_LOGI(TAG, "Core 1 at %d%%", cpu1);
|
||||
// TODO configurable delay
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t perfmon_start()
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_task_0, 0));
|
||||
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_task_1, 1));
|
||||
// TODO calculate optimal stack size
|
||||
xTaskCreate(perfmon_task, "perfmon", 2048, NULL, 1, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUG_ENABLE_PERFMON
|
||||
24
code/components/jomjol_helper/perfmon.h
Normal file
24
code/components/jomjol_helper/perfmon.h
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_PERFMON
|
||||
|
||||
#ifndef COMPONENTS_PERFMON_INCLUDE_PERFMON_H_
|
||||
#define COMPONENTS_PERFMON_INCLUDE_PERFMON_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
esp_err_t perfmon_start();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPONENTS_PERFMON_INCLUDE_PERFMON_H_ */
|
||||
|
||||
#endif //DEBUG_ENABLE_PERFMON
|
||||
@@ -2,19 +2,13 @@
|
||||
#include "CRotateImage.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "c_align_and_cut_image";
|
||||
|
||||
//#define GET_MEMORY malloc
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp)
|
||||
{
|
||||
rgb_image = _org->rgb_image;
|
||||
@@ -47,14 +41,14 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
|
||||
r0_x = _temp1->target_x;
|
||||
r0_y = _temp1->target_y;
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Before ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str());
|
||||
isSimilar1 = ft->FindTemplate(_temp1);
|
||||
_temp1->width = ft->tpl_width;
|
||||
_temp1->height = ft->tpl_height;
|
||||
|
||||
r1_x = _temp2->target_x;
|
||||
r1_y = _temp2->target_y;
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Before ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str());
|
||||
isSimilar2 = ft->FindTemplate(_temp2);
|
||||
_temp2->width = ft->tpl_width;
|
||||
_temp2->height = ft->tpl_height;
|
||||
@@ -78,14 +72,14 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
|
||||
d_winkel = (w_ist - w_org) * 180 / M_PI;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\tdx:\t" + std::to_string(dx) + "\tdy:\t" + std::to_string(dy) + "\td_winkel:\t" + std::to_string(d_winkel);
|
||||
zw = zw + "\tt1_x_y:\t" + std::to_string(_temp1->found_x) + "\t" + std::to_string(_temp1->found_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(_temp1->fastalg_min) + "\t" + std::to_string(_temp1->fastalg_avg) + "\t" + std::to_string(_temp1->fastalg_max) + "\t"+ std::to_string(_temp1->fastalg_SAD);
|
||||
zw = zw + "\tt2_x_y:\t" + std::to_string(_temp2->found_x) + "\t" + std::to_string(_temp2->found_y);
|
||||
zw = zw + "\tpara2_found_min_avg_max:\t" + std::to_string(_temp2->fastalg_min) + "\t" + std::to_string(_temp2->fastalg_avg) + "\t" + std::to_string(_temp2->fastalg_max) + "\t"+ std::to_string(_temp2->fastalg_SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
CRotateImage rt(this, ImageTMP);
|
||||
rt.Translate(dx, dy);
|
||||
@@ -129,8 +123,12 @@ void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int d
|
||||
p_target[_channels] = p_source[_channels];
|
||||
}
|
||||
|
||||
// stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 0);
|
||||
#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
|
||||
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CALIGNANDCUTIMAGE_H
|
||||
#define CALIGNANDCUTIMAGE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
#include "CFindTemplate.h"
|
||||
|
||||
@@ -19,3 +24,4 @@ class CAlignAndCutImage : public CImageBasis
|
||||
void GetRefSize(int *ref_dx, int *ref_dy);
|
||||
};
|
||||
|
||||
#endif //CALIGNANDCUTIMAGE_H
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
@@ -67,11 +68,11 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
if ((_ref->alignment_algo == 2) && (_ref->fastalg_x > -1) && (_ref->fastalg_y > -1)) // für Testzwecke immer Berechnen
|
||||
{
|
||||
isSimilar = CalculateSimularities(rgb_template, _ref->fastalg_x, _ref->fastalg_y, ow, oh, min, avg, max, SAD, _ref->fastalg_SAD, _ref->fastalg_SAD_criteria);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\t" + _ref->image_file + "\tt1_x_y:\t" + std::to_string(_ref->fastalg_x) + "\t" + std::to_string(_ref->fastalg_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(min) + "\t" + std::to_string(avg) + "\t" + std::to_string(max) + "\t"+ std::to_string(SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
}
|
||||
|
||||
// ESP_LOGD(TAG, "FindTemplate 03");
|
||||
@@ -143,11 +144,11 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
_ref->fastalg_SAD = SAD;
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\t" + _ref->image_file + "\tt1_x_y:\t" + std::to_string(_ref->fastalg_x) + "\t" + std::to_string(_ref->fastalg_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(min) + "\t" + std::to_string(avg) + "\t" + std::to_string(max) + "\t"+ std::to_string(SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
RGBImageRelease();
|
||||
stbi_image_free(rgb_template);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CFINDTEMPLATE_CLASS
|
||||
#define __CFINDTEMPLATE_CLASS
|
||||
#pragma once
|
||||
|
||||
#ifndef CFINDTEMPLATE_H
|
||||
#define CFINDTEMPLATE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
@@ -37,4 +39,4 @@ class CFindTemplate : public CImageBasis
|
||||
bool CalculateSimularities(uint8_t* _rgb_tmpl, int _startx, int _starty, int _sizex, int _sizey, int &min, float &avg, int &max, float &SAD, float _SADold, float _SADcrit);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif //CFINDTEMPLATE_H
|
||||
@@ -4,33 +4,30 @@
|
||||
#include "server_ota.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define _ESP32_PSRAM
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *TAG = "C IMG BASIS";
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
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
|
||||
TickType_t xDelay;
|
||||
xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
for (int i = 0; i <= _waitmaxsec; ++i)
|
||||
@@ -47,18 +44,19 @@ uint8_t * CImageBasis::RGBImageLock(int _waitmaxsec)
|
||||
return rgb_image;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::RGBImageRelease()
|
||||
{
|
||||
islocked = false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t * CImageBasis::RGBImageGet()
|
||||
{
|
||||
return rgb_image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void writejpghelp(void *context, void *data, int size)
|
||||
{
|
||||
// ESP_LOGD(TAG, "Size all: %d, size %d", ((ImageData*)context)->size, size);
|
||||
@@ -74,8 +72,6 @@ void writejpghelp(void *context, void *data, int size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
|
||||
{
|
||||
ImageData* ii = new ImageData;
|
||||
@@ -87,7 +83,19 @@ ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
|
||||
return ii;
|
||||
}
|
||||
|
||||
#define HTTP_BUFFER_SENT 1024
|
||||
|
||||
void CImageBasis::writeToMemoryAsJPG(ImageData* i, const int quality)
|
||||
{
|
||||
ImageData* ii = new ImageData;
|
||||
|
||||
RGBImageLock();
|
||||
stbi_write_jpg_to_func(writejpghelp, ii, width, height, channels, rgb_image, quality);
|
||||
RGBImageRelease();
|
||||
|
||||
memCopy((uint8_t*) ii, (uint8_t*) i, sizeof(ImageData));
|
||||
delete ii;
|
||||
}
|
||||
|
||||
|
||||
struct SendJPGHTTP
|
||||
{
|
||||
@@ -97,13 +105,13 @@ struct SendJPGHTTP
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
|
||||
inline void writejpgtohttphelp(void *context, void *data, int size)
|
||||
{
|
||||
SendJPGHTTP* _send = (SendJPGHTTP*) context;
|
||||
if ((_send->size + size) >= HTTP_BUFFER_SENT) // data passt nich mehr in buffer
|
||||
if ((_send->size + size) >= HTTP_BUFFER_SENT) // data no longer fits in buffer
|
||||
{
|
||||
httpd_req_t *_req = _send->req;
|
||||
if (httpd_resp_send_chunk(_req, _send->buf, _send->size) != ESP_OK)
|
||||
if (httpd_resp_send_chunk(_send->req, _send->buf, _send->size) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
_send->res = ESP_FAIL;
|
||||
@@ -115,7 +123,6 @@ inline void writejpgtohttphelp(void *context, void *data, int size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality)
|
||||
{
|
||||
SendJPGHTTP ii;
|
||||
@@ -125,28 +132,28 @@ esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality)
|
||||
|
||||
RGBImageLock();
|
||||
stbi_write_jpg_to_func(writejpgtohttphelp, &ii, width, height, channels, rgb_image, quality);
|
||||
RGBImageRelease();
|
||||
|
||||
if (ii.size > 0)
|
||||
{
|
||||
if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) // verschicke noch den Rest
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
return ii.res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
|
||||
{
|
||||
int gr = height * width * channels;
|
||||
if (gr != _size) // Größe passt nicht
|
||||
if (gr != _size) // Size does not fit
|
||||
{
|
||||
ESP_LOGD(TAG, "Cannot copy image from memory - sizes do not match: should be %d, but is %d", _size, gr);
|
||||
ESP_LOGE(TAG, "Cannot copy image from memory - sizes do not match: should be %d, but is %d", _size, gr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,6 +164,7 @@ bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t CImageBasis::GetPixelColor(int x, int y, int ch)
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -175,6 +183,7 @@ void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageBasis::isInImage(int x, int y)
|
||||
{
|
||||
if ((x < 0) || (x > width - 1))
|
||||
@@ -186,6 +195,7 @@ bool CImageBasis::isInImage(int x, int y)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -201,6 +211,7 @@ void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness)
|
||||
{
|
||||
int zwx1, zwx2, zwy1, zwy2;
|
||||
@@ -210,6 +221,9 @@ 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;
|
||||
zwy2 = y;
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (_thick = 0; _thick < thickness; _thick++)
|
||||
for (_x = zwx1; _x <= zwx2; ++_x)
|
||||
for (_y = zwy1; _y <= zwy2; _y++)
|
||||
@@ -246,14 +260,18 @@ void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, in
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x + _thick, _y, r, g, b);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness)
|
||||
{
|
||||
int _x, _y, _thick;
|
||||
int _zwy1, _zwy2;
|
||||
thickness = (thickness-1) / 2;
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (_thick = 0; _thick <= thickness; ++_thick)
|
||||
for (_x = x1 - _thick; _x <= x2 + _thick; ++_x)
|
||||
{
|
||||
@@ -272,8 +290,11 @@ void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b,
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g, int b, int thickness)
|
||||
{
|
||||
float deltarad, aktrad;
|
||||
@@ -285,6 +306,8 @@ void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g,
|
||||
|
||||
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
|
||||
for (_thick = 0; _thick < thickness; ++_thick)
|
||||
{
|
||||
@@ -293,6 +316,8 @@ void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g,
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +328,8 @@ void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int t
|
||||
|
||||
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
|
||||
for (_thick = 0; _thick < thickness; ++_thick)
|
||||
{
|
||||
@@ -311,8 +338,11 @@ void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int t
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis()
|
||||
{
|
||||
externalImage = false;
|
||||
@@ -323,6 +353,7 @@ CImageBasis::CImageBasis()
|
||||
islocked = false;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
{
|
||||
bpp = _channels;
|
||||
@@ -332,10 +363,21 @@ void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CreateEmptyImage");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
//ESP_LOGE(TAG, "CImageBasis::CreateEmptyImage: No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CreateEmptyImage: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CreateEmptyImage");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
stbi_uc* p_source;
|
||||
|
||||
@@ -348,30 +390,55 @@ void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::EmptyImage()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::EmptyImage");
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
|
||||
{
|
||||
RGBImageLock();
|
||||
|
||||
if (rgb_image)
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
|
||||
bpp = channels;
|
||||
ESP_LOGD(TAG, "Image loaded from memory: %d, %d, %d", width, height, channels);
|
||||
|
||||
if ((width * height * channels) == 0)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Image with size 0 loaded --> reboot to be done! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
LogFile.WriteHeapInfo("CImageBasis::LoadFromMemory");
|
||||
|
||||
doReboot();
|
||||
|
||||
}
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
|
||||
CImageBasis::CImageBasis(CImageBasis *_copyfrom)
|
||||
{
|
||||
islocked = false;
|
||||
externalImage = false;
|
||||
@@ -382,30 +449,30 @@ CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_copyfrom - Start");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
int anz = 1;
|
||||
while (!rgb_image && (anz < _anzrepeat))
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "Create Image from Copy - Memory is full - try again: %d", anz);
|
||||
rgb_image = (unsigned char*) malloc(memsize);
|
||||
anz++;
|
||||
}
|
||||
|
||||
|
||||
if (!rgb_image)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-Copyfrom: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-Copyfrom");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
memCopy(_copyfrom->rgb_image, rgb_image, memsize);
|
||||
RGBImageRelease();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_copyfrom - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis(int _width, int _height, int _channels)
|
||||
{
|
||||
islocked = false;
|
||||
@@ -415,15 +482,28 @@ CImageBasis::CImageBasis(int _width, int _height, int _channels)
|
||||
height = _height;
|
||||
bpp = _channels;
|
||||
|
||||
int memsize = width * height * channels;
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_width,height,ch - Start");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
if (!rgb_image)
|
||||
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-width,height,ch: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-width,height,ch");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_width,height,ch - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -433,8 +513,6 @@ CImageBasis::CImageBasis(std::string _image)
|
||||
channels = 3;
|
||||
externalImage = false;
|
||||
filename = _image;
|
||||
long zwld = esp_get_free_heap_size();
|
||||
ESP_LOGD(TAG, "freeheapsize before: %ld", zwld);
|
||||
|
||||
if (file_size(_image.c_str()) == 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _image + " is empty!");
|
||||
@@ -442,32 +520,39 @@ CImageBasis::CImageBasis(std::string _image)
|
||||
}
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_image - Start");
|
||||
#endif
|
||||
|
||||
rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
|
||||
|
||||
if (rgb_image == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to load " + _image + "! Is it corrupted?");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-image: Failed to load " + _image + "! Is it corrupted?");
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-image");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
zwld = esp_get_free_heap_size();
|
||||
ESP_LOGD(TAG, "freeheapsize after: %ld", zwld);
|
||||
|
||||
std::string zw = "Image Load failed:" + _image;
|
||||
if (rgb_image == NULL)
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "CImageBasis after load " + _image;
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
zw = "CImageBasis after load " + _image + "\n";
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels);
|
||||
ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_image - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageBasis::ImageOkay(){
|
||||
return rgb_image != NULL;
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp)
|
||||
{
|
||||
islocked = false;
|
||||
@@ -479,6 +564,7 @@ CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _he
|
||||
externalImage = true;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Contrast(float _contrast) //input range [-100..100]
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -500,28 +586,35 @@ void CImageBasis::Contrast(float _contrast) //input range [-100..100]
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::~CImageBasis()
|
||||
{
|
||||
RGBImageLock();
|
||||
|
||||
if (!externalImage)
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::SaveToFile(std::string _imageout)
|
||||
{
|
||||
string typ = getFileType(_imageout);
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM 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
|
||||
if ((typ == "bmp") || (typ == "BMP"))
|
||||
{
|
||||
stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image);
|
||||
}
|
||||
#endif
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
@@ -533,25 +626,24 @@ void CImageBasis::Resize(int _new_dx, int _new_dy)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
|
||||
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
|
||||
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
memCopy(odata, rgb_image, memsize);
|
||||
RGBImageRelease();
|
||||
|
||||
width = _new_dx;
|
||||
height = _new_dy;
|
||||
stbi_image_free(odata);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
|
||||
{
|
||||
if ((_target->height != _new_dy) || (_target->width != _new_dx) || (_target->channels != channels))
|
||||
{
|
||||
ESP_LOGD(TAG, "CImageBasis::Resize - Target image size does not fit!");
|
||||
ESP_LOGE(TAG, "CImageBasis::Resize - Target image size does not fit!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -559,6 +651,7 @@ void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
|
||||
|
||||
uint8_t* odata = _target->rgb_image;
|
||||
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __CIMAGEBASIS
|
||||
#define __CIMAGEBASIS
|
||||
#ifndef CIMAGEBASIS_H
|
||||
#define CIMAGEBASIS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <esp_http_server.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "stb_image.h"
|
||||
@@ -16,13 +17,6 @@
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
//#define GET_MEMORY malloc
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
|
||||
#define MAX_JPG_SIZE 128000
|
||||
|
||||
|
||||
struct ImageData
|
||||
{
|
||||
uint8_t data[MAX_JPG_SIZE];
|
||||
@@ -67,20 +61,22 @@ class CImageBasis
|
||||
void SetIndepended(){externalImage = false;};
|
||||
|
||||
void CreateEmptyImage(int _width, int _height, int _channels);
|
||||
void EmptyImage();
|
||||
|
||||
|
||||
CImageBasis();
|
||||
CImageBasis(std::string _image);
|
||||
CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp);
|
||||
CImageBasis(int _width, int _height, int _channels);
|
||||
CImageBasis(CImageBasis *_copyfrom, int _anzrepeat = 0);
|
||||
CImageBasis(CImageBasis *_copyfrom);
|
||||
|
||||
void Resize(int _new_dx, int _new_dy);
|
||||
void Resize(int _new_dx, int _new_dy, CImageBasis *_target);
|
||||
|
||||
void LoadFromMemory(stbi_uc *_buffer, int len);
|
||||
|
||||
ImageData* writeToMemoryAsJPG(const int quality = 90);
|
||||
ImageData* writeToMemoryAsJPG(const int quality = 90);
|
||||
void writeToMemoryAsJPG(ImageData* ii, const int quality = 90);
|
||||
|
||||
esp_err_t SendJPGtoHTTP(httpd_req_t *req, const int quality = 90);
|
||||
|
||||
@@ -92,5 +88,5 @@ class CImageBasis
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif //CIMAGEBASIS_H
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CROTATEIMAGE_H
|
||||
#define CROTATEIMAGE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
@@ -19,3 +24,5 @@ class CRotateImage: public CImageBasis
|
||||
void Translate(int _dx, int _dy);
|
||||
void Mirror();
|
||||
};
|
||||
|
||||
#endif //CROTATEIMAGE_H
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#include "interface_influxdb.h"
|
||||
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
#include <time.h>
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||
|
||||
static const char *TAG = "INFLUXDB";
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
|
||||
#pragma once
|
||||
#ifndef INTERFACE_INFLUXDB_H
|
||||
#define INTERFACE_INFLUXDB_H
|
||||
|
||||
|
||||
@@ -15,55 +15,22 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "LOGFILE";
|
||||
|
||||
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt", "/sdcard/log/data", "data_%Y-%m-%d.csv");
|
||||
|
||||
|
||||
void ClassLogFile::WriteHeapInfo(std::string _id)
|
||||
{
|
||||
std::string _zw = _id;
|
||||
if (loglevel >= ESP_LOG_DEBUG) {
|
||||
_zw = _zw + "\t" + getESPHeapInfo();
|
||||
std::string _zw = _id + "\t" + getESPHeapInfo();
|
||||
WriteToFile(ESP_LOG_DEBUG, "HEAP", _zw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLogFile::getESPHeapInfo(){
|
||||
string espInfoResultStr = "";
|
||||
char aMsgBuf[80];
|
||||
|
||||
multi_heap_info_t aMultiHead_info ;
|
||||
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
|
||||
sprintf(aMsgBuf,"Free Heap Size: \t%ld", (long) aFreeHeapSize);
|
||||
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
|
||||
sprintf(aMsgBuf,"\tHeap:\t%ld", (long) aFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tMin Free:\t%ld", (long) aMinFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tlarg. Block: \t%ld", (long) aHeapLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tSPI Heap:\t%ld", (long) aFreeSPIHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tMin Free Heap Size:\t%ld", (long) aMinFreeHeadSize);
|
||||
sprintf(aMsgBuf,"\tNOT_SPI Heap:\t%ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tlargest Block Size: \t%ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf,"\tInternal Heap:\t%ld", (long) (aFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tInternal Min Heap free:\t%ld", (long) (aMinFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::string _ReturnRawValue, std::string _ReturnValue, std::string _ReturnPreValue, std::string _ReturnRateValue, std::string _ReturnChangeAbsolute, std::string _ErrorMessageText, std::string _digital, std::string _analog)
|
||||
{
|
||||
ESP_LOGD(TAG, "Start WriteToData");
|
||||
@@ -111,69 +78,6 @@ void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::s
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time)
|
||||
{
|
||||
FILE* pFile;
|
||||
std::string zwtime;
|
||||
std::string ntpTime = "";
|
||||
|
||||
if (level > loglevel) {// Only write to file if loglevel is below threshold
|
||||
return;
|
||||
}
|
||||
|
||||
// pFile = OpenFileAndWait(_fn.c_str(), "a");
|
||||
pFile = fopen(_fn.c_str(), "a+");
|
||||
// ESP_LOGD(TAG, "Logfile opened: %s", _fn.c_str());
|
||||
|
||||
if (pFile!=NULL) {
|
||||
if (_time)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[80];
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
|
||||
zwtime = std::string(buffer);
|
||||
ntpTime = zwtime;
|
||||
}
|
||||
|
||||
std::string loglevelString;
|
||||
switch(level) {
|
||||
case ESP_LOG_ERROR:
|
||||
loglevelString = "ERR";
|
||||
break;
|
||||
case ESP_LOG_WARN:
|
||||
loglevelString = "WRN";
|
||||
break;
|
||||
case ESP_LOG_INFO:
|
||||
loglevelString = "INF";
|
||||
break;
|
||||
case ESP_LOG_DEBUG:
|
||||
loglevelString = "DBG";
|
||||
break;
|
||||
case ESP_LOG_VERBOSE:
|
||||
loglevelString = "VER";
|
||||
break;
|
||||
case ESP_LOG_NONE:
|
||||
default:
|
||||
loglevelString = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string formatedUptime = getFormatedUptime(true);
|
||||
|
||||
ntpTime = "[" + formatedUptime + "] " + ntpTime + "\t<" + loglevelString + ">\t" + message + "\n";
|
||||
fputs(ntpTime.c_str(), pFile);
|
||||
fclose(pFile);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Can't open log file %s", _fn.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
|
||||
loglevel = _logLevel;
|
||||
|
||||
@@ -207,43 +111,46 @@ void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetLogFileRetention(unsigned short _LogFileRetentionInDays){
|
||||
logFileRetentionInDays = _LogFileRetentionInDays;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetDataLogRetention(unsigned short _DataLogRetentionInDays){
|
||||
dataLogRetentionInDays = _DataLogRetentionInDays;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetDataLogToSD(bool _doDataLogToSD){
|
||||
doDataLogToSD = _doDataLogToSD;
|
||||
}
|
||||
|
||||
|
||||
bool ClassLogFile::GetDataLogToSD(){
|
||||
return doDataLogToSD;
|
||||
}
|
||||
|
||||
|
||||
static FILE* logFileAppendHandle = NULL;
|
||||
std::string fileNameDate;
|
||||
|
||||
void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::string message, bool _time)
|
||||
{
|
||||
/*
|
||||
struct stat path_stat;
|
||||
if (stat(logroot.c_str(), &path_stat) != 0) {
|
||||
ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str());
|
||||
if (mkdir_r(logroot.c_str(), S_IRWXU) == -1) {
|
||||
ESP_LOGE(TAG, "Can't create log folder");
|
||||
}
|
||||
}
|
||||
*/
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[30];
|
||||
std::string fileNameDateNew;
|
||||
|
||||
std::string zwtime;
|
||||
std::string ntpTime = "";
|
||||
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
char buf[30];
|
||||
strftime(buf, sizeof(buf), logfile.c_str(), timeinfo);
|
||||
fileNameDateNew = std::string(buf);
|
||||
|
||||
strftime(buffer, 30, logfile.c_str(), timeinfo);
|
||||
std::string logpath = logroot + "/" + buffer;
|
||||
|
||||
std::replace(message.begin(), message.end(), '\n', ' '); // Replace all newline characters
|
||||
|
||||
if (tag != "") {
|
||||
@@ -253,7 +160,89 @@ void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::stri
|
||||
else {
|
||||
ESP_LOG_LEVEL(level, "", "%s", message.c_str());
|
||||
}
|
||||
WriteToDedicatedFile(logpath, level, message, _time);
|
||||
|
||||
|
||||
if (level > loglevel) {// Only write to file if loglevel is below threshold
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_time)
|
||||
{
|
||||
char logLineDate[30];
|
||||
strftime(logLineDate, sizeof(logLineDate), "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
ntpTime = std::string(logLineDate);
|
||||
}
|
||||
|
||||
std::string loglevelString;
|
||||
switch(level) {
|
||||
case ESP_LOG_ERROR:
|
||||
loglevelString = "ERR";
|
||||
break;
|
||||
case ESP_LOG_WARN:
|
||||
loglevelString = "WRN";
|
||||
break;
|
||||
case ESP_LOG_INFO:
|
||||
loglevelString = "INF";
|
||||
break;
|
||||
case ESP_LOG_DEBUG:
|
||||
loglevelString = "DBG";
|
||||
break;
|
||||
case ESP_LOG_VERBOSE:
|
||||
loglevelString = "VER";
|
||||
break;
|
||||
case ESP_LOG_NONE:
|
||||
default:
|
||||
loglevelString = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string formatedUptime = getFormatedUptime(true);
|
||||
|
||||
std::string fullmessage = "[" + formatedUptime + "] " + 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 = logroot + "/" + fileNameDateNew;
|
||||
|
||||
ESP_LOGI(TAG, "Opening logfile %s for appending", logpath.c_str());
|
||||
logFileAppendHandle = fopen(logpath.c_str(), "a+");
|
||||
if (logFileAppendHandle==NULL) {
|
||||
ESP_LOGE(TAG, "Can't open log file %s", logpath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
fileNameDate = fileNameDateNew;
|
||||
}
|
||||
#else
|
||||
std::string logpath = logroot + "/" + fileNameDateNew;
|
||||
logFileAppendHandle = fopen(logpath.c_str(), "a+");
|
||||
if (logFileAppendHandle==NULL) {
|
||||
ESP_LOGE(TAG, "Can't open log file %s", logpath.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fputs(fullmessage.c_str(), logFileAppendHandle);
|
||||
|
||||
#ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING
|
||||
fflush(logFileAppendHandle);
|
||||
fsync(fileno(logFileAppendHandle));
|
||||
#else
|
||||
CloseLogFileAppendHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::CloseLogFileAppendHandle() {
|
||||
if (logFileAppendHandle != NULL) {
|
||||
fclose(logFileAppendHandle);
|
||||
logFileAppendHandle = NULL;
|
||||
fileNameDate = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,6 +250,7 @@ void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::stri
|
||||
LogFile.WriteToFile(level, tag, message, true);
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLogFile::GetCurrentFileNameData()
|
||||
{
|
||||
time_t rawtime;
|
||||
@@ -292,6 +282,7 @@ std::string ClassLogFile::GetCurrentFileName()
|
||||
return logpath;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::RemoveOldLogFile()
|
||||
{
|
||||
if (logFileRetentionInDays == 0) {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSLOGFILE_H
|
||||
#define CLASSLOGFILE_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "esp_log.h"
|
||||
@@ -17,8 +22,6 @@ private:
|
||||
public:
|
||||
ClassLogFile(std::string _logpath, std::string _logfile, std::string _logdatapath, std::string _datafile);
|
||||
|
||||
std::string getESPHeapInfo();
|
||||
|
||||
void WriteHeapInfo(std::string _id);
|
||||
|
||||
void setLogLevel(esp_log_level_t _logLevel);
|
||||
@@ -30,7 +33,7 @@ public:
|
||||
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 WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time = true);
|
||||
void CloseLogFileAppendHandle();
|
||||
|
||||
void CreateLogDirectories();
|
||||
void RemoveOldLogFile();
|
||||
@@ -44,4 +47,6 @@ public:
|
||||
std::string GetCurrentFileNameData();
|
||||
};
|
||||
|
||||
extern ClassLogFile LogFile;
|
||||
extern ClassLogFile LogFile;
|
||||
|
||||
#endif //CLASSLOGFILE_H
|
||||
@@ -6,16 +6,12 @@
|
||||
#include "mqtt_client.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "MQTT IF";
|
||||
|
||||
std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;
|
||||
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
|
||||
|
||||
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
|
||||
|
||||
int failedOnRound = -1;
|
||||
|
||||
@@ -89,7 +85,6 @@ bool MQTTPublish(std::string _key, std::string _content, int retained_flag)
|
||||
|
||||
|
||||
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
|
||||
int msg_id;
|
||||
std::string topic = "";
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_BEFORE_CONNECT:
|
||||
@@ -109,8 +104,6 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
|
||||
ESP_LOGD(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
@@ -120,12 +113,12 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_DATA");
|
||||
ESP_LOGD(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
ESP_LOGD(TAG, "DATA=%.*s\r\n", event->data_len, event->data);
|
||||
ESP_LOGD(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
|
||||
ESP_LOGD(TAG, "DATA=%.*s", event->data_len, event->data);
|
||||
topic.assign(event->topic, event->topic_len);
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
|
||||
ESP_LOGD(TAG, "call handler function\r\n");
|
||||
ESP_LOGD(TAG, "call subcribe function for topic %s", topic.c_str());
|
||||
(*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
|
||||
}
|
||||
} else {
|
||||
@@ -151,6 +144,7 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
|
||||
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||||
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
|
||||
@@ -212,7 +206,7 @@ int MQTT_Init() {
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init");
|
||||
MQTTdestroy_client();
|
||||
MQTTdestroy_client(false);
|
||||
|
||||
esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.uri = uri.c_str(),
|
||||
@@ -276,27 +270,76 @@ int MQTT_Init() {
|
||||
}
|
||||
|
||||
|
||||
void MQTTdestroy_client() {
|
||||
void MQTTdestroy_client(bool _disable = false) {
|
||||
if (client) {
|
||||
if (mqtt_connected) {
|
||||
MQTTdestroySubscribeFunction();
|
||||
esp_mqtt_client_disconnect(client);
|
||||
mqtt_connected = false;
|
||||
}
|
||||
}
|
||||
esp_mqtt_client_stop(client);
|
||||
esp_mqtt_client_destroy(client);
|
||||
client = NULL;
|
||||
mqtt_initialized = false;
|
||||
}
|
||||
|
||||
if (_disable) // Disable MQTT service, avoid restart with MQTTPublish
|
||||
mqtt_configOK = false;
|
||||
}
|
||||
|
||||
|
||||
bool getMQTTisEnabled() {
|
||||
return mqtt_enabled;
|
||||
}
|
||||
|
||||
|
||||
bool getMQTTisConnected() {
|
||||
return mqtt_connected;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
|
||||
if (_data_len > 0) {
|
||||
MQTTCtrlFlowStart(_topic);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void MQTTconnected(){
|
||||
if (mqtt_connected) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
|
||||
MQTTPublish(lwt_topic, lwt_connected, true); // Publish "connected" to maintopic/connection
|
||||
|
||||
if (connectFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
|
||||
it->second();
|
||||
ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Subcribe to topics */
|
||||
std::function<bool(std::string topic, char* data, int data_len)> subHandler = mqtt_handler_flow_start;
|
||||
MQTTregisterSubscribeFunction(maintopic + "/ctrl/flow_start", subHandler); // subcribe to maintopic/ctrl/flow_start
|
||||
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS); // Delay execution of callback routine after connection got established
|
||||
if (callbackOnConnected) { // Call onConnected callback routine --> mqtt_server
|
||||
callbackOnConnected(maintopic, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str());
|
||||
if (connectFunktionMap == NULL) {
|
||||
@@ -315,6 +358,7 @@ void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTTunregisterConnectFunction(std::string name){
|
||||
ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str());
|
||||
if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
|
||||
@@ -322,8 +366,9 @@ void MQTTunregisterConnectFunction(std::string name){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
|
||||
ESP_LOGD(TAG, "registerSubscribeFunction %s\r\n", topic.c_str());
|
||||
ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str());
|
||||
if (subscribeFunktionMap == NULL) {
|
||||
subscribeFunktionMap = new std::map<std::string, std::function<bool(std::string, char*, int)>>();
|
||||
}
|
||||
@@ -334,45 +379,15 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
|
||||
}
|
||||
|
||||
(*subscribeFunktionMap)[topic] = func;
|
||||
|
||||
if (mqtt_connected) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, topic.c_str(), 0);
|
||||
ESP_LOGD(TAG, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTconnected(){
|
||||
if (mqtt_connected) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
|
||||
|
||||
MQTTPublish(lwt_topic, lwt_connected, true);
|
||||
|
||||
if (connectFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
|
||||
it->second();
|
||||
ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackOnConnected) {
|
||||
callbackOnConnected(maintopic, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTdestroySubscribeFunction(){
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
if (mqtt_connected) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_unsubscribe(client, it->first.c_str());
|
||||
ESP_LOGI(TAG, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
ESP_LOGD(TAG, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef INTERFACE_MQTT_H
|
||||
#define INTERFACE_MQTT_H
|
||||
|
||||
@@ -10,7 +13,7 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
|
||||
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
|
||||
int _keepalive, int SetRetainFlag, void *callbackOnConnected);
|
||||
int MQTT_Init();
|
||||
void MQTTdestroy_client();
|
||||
void MQTTdestroy_client(bool _disable);
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag = 1); // retained Flag as Standart
|
||||
|
||||
@@ -23,6 +26,5 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
|
||||
void MQTTdestroySubscribeFunction();
|
||||
void MQTTconnected();
|
||||
|
||||
void MQTTdisable();
|
||||
#endif //INTERFACE_MQTT_H
|
||||
#endif //#ENABLE_MQTT
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "server_mqtt.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "time_sntp.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +57,6 @@ void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
|
||||
std::string topicFull;
|
||||
std::string configTopic;
|
||||
std::string payload;
|
||||
std::string nl = "\n";
|
||||
|
||||
configTopic = field;
|
||||
|
||||
@@ -73,57 +73,62 @@ void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
|
||||
}
|
||||
|
||||
/* See https://www.home-assistant.io/docs/mqtt/discovery/ */
|
||||
payload = "{" + nl +
|
||||
"\"~\": \"" + maintopic + "\"," + nl +
|
||||
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," + nl +
|
||||
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + nl + // This used to generate the Entity ID
|
||||
"\"name\": \"" + name + "\"," + nl +
|
||||
"\"icon\": \"mdi:" + icon + "\"," + nl;
|
||||
payload = string("{") +
|
||||
"\"~\": \"" + maintopic + "\"," +
|
||||
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," +
|
||||
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + // This used to generate the Entity ID
|
||||
"\"name\": \"" + name + "\"," +
|
||||
"\"icon\": \"mdi:" + icon + "\",";
|
||||
|
||||
if (group != "") {
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
payload += "\"state_topic\": \"~/" + group + "/error\"," + nl;
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\"," + nl;
|
||||
payload += "\"state_topic\": \"~/" + group + "/error\",";
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + group + "/" + field + "\"," + nl;
|
||||
payload += "\"state_topic\": \"~/" + group + "/" + field + "\",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + field + "\"," + nl;
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
payload += "\"state_topic\": \"~/error\",";
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + field + "\",";
|
||||
}
|
||||
}
|
||||
|
||||
if (unit != "") {
|
||||
payload += "\"unit_of_meas\": \"" + unit + "\"," + nl;
|
||||
payload += "\"unit_of_meas\": \"" + unit + "\",";
|
||||
}
|
||||
|
||||
if (deviceClass != "") {
|
||||
payload += "\"device_class\": \"" + deviceClass + "\"," + nl;
|
||||
payload += "\"device_class\": \"" + deviceClass + "\",";
|
||||
}
|
||||
|
||||
if (stateClass != "") {
|
||||
payload += "\"state_class\": \"" + stateClass + "\"," + nl;
|
||||
payload += "\"state_class\": \"" + stateClass + "\",";
|
||||
}
|
||||
|
||||
if (entityCategory != "") {
|
||||
payload += "\"entity_category\": \"" + entityCategory + "\"," + nl;
|
||||
payload += "\"entity_category\": \"" + entityCategory + "\",";
|
||||
}
|
||||
|
||||
payload +=
|
||||
"\"availability_topic\": \"~/" + std::string(LWT_TOPIC) + "\"," + nl +
|
||||
"\"payload_available\": \"" + LWT_CONNECTED + "\"," + nl +
|
||||
"\"payload_not_available\": \"" + LWT_DISCONNECTED + "\"," + nl;
|
||||
"\"availability_topic\": \"~/" + std::string(LWT_TOPIC) + "\"," +
|
||||
"\"payload_available\": \"" + LWT_CONNECTED + "\"," +
|
||||
"\"payload_not_available\": \"" + LWT_DISCONNECTED + "\",";
|
||||
|
||||
payload +=
|
||||
"\"device\": {" + nl +
|
||||
"\"identifiers\": [\"" + maintopic + "\"]," + nl +
|
||||
"\"name\": \"" + maintopic + "\"," + nl +
|
||||
"\"model\": \"Meter Digitizer\"," + nl +
|
||||
"\"manufacturer\": \"AI on the Edge Device\"," + nl +
|
||||
"\"sw_version\": \"" + version + "\"," + nl +
|
||||
"\"configuration_url\": \"http://" + *getIPAddress() + "\"" + nl +
|
||||
"}" + nl +
|
||||
"}" + nl;
|
||||
payload += string("\"device\": {") +
|
||||
"\"identifiers\": [\"" + maintopic + "\"]," +
|
||||
"\"name\": \"" + maintopic + "\"," +
|
||||
"\"model\": \"Meter Digitizer\"," +
|
||||
"\"manufacturer\": \"AI on the Edge Device\"," +
|
||||
"\"sw_version\": \"" + version + "\"," +
|
||||
"\"configuration_url\": \"http://" + *getIPAddress() + "\"" +
|
||||
"}" +
|
||||
"}";
|
||||
|
||||
MQTTPublish(topicFull, payload, true);
|
||||
}
|
||||
@@ -148,7 +153,11 @@ void MQTThomeassistantDiscovery() {
|
||||
|
||||
|
||||
for (int i = 0; i < (*NUMBERS).size(); ++i) {
|
||||
std::string group = (*NUMBERS)[i]->name;
|
||||
std::string group = (*NUMBERS)[i]->name;
|
||||
if (group == "default") {
|
||||
group = "";
|
||||
}
|
||||
|
||||
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
|
||||
sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", "");
|
||||
sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, "", "total_increasing", "diagnostic");
|
||||
@@ -174,7 +183,7 @@ void publishSystemData() {
|
||||
sprintf(tmp_char, "%ld", (long)getUpTime());
|
||||
MQTTPublish(maintopic + "/" + "uptime", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%zu", esp_get_free_heap_size());
|
||||
sprintf(tmp_char, "%lu", (long) getESPHeapSize());
|
||||
MQTTPublish(maintopic + "/" + "freeMem", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%d", get_WIFI_RSSI());
|
||||
@@ -213,7 +222,6 @@ esp_err_t sendDiscovery_and_static_Topics(httpd_req_t *req) {
|
||||
}
|
||||
|
||||
void GotConnected(std::string maintopic, int retainFlag) {
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS); // Delay execution by 10s after connection got established
|
||||
if (HomeassistantDiscovery) {
|
||||
MQTThomeassistantDiscovery();
|
||||
}
|
||||
@@ -255,4 +263,4 @@ std::string mqttServer_getMainTopic() {
|
||||
return maintopic;
|
||||
}
|
||||
|
||||
#endif //ENABLE_MQTT
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERMQTT_H
|
||||
#define SERVERMQTT_H
|
||||
|
||||
#include "ClassFlowDefineTypes.h"
|
||||
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
|
||||
void SetHomeassistantDiscoveryEnabled(bool enabled);
|
||||
void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int interval, float roundInterval);
|
||||
void mqttServer_setMeterType(std::string meterType, std::string valueUnit, std::string timeUnit,std::string rateUnit);
|
||||
@@ -21,4 +21,6 @@ void publishSystemData();
|
||||
std::string getTimeUnit(void);
|
||||
void GotConnected(std::string maintopic, int SetRetainFlag);
|
||||
|
||||
|
||||
#endif //SERVERMQTT_H
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -55,7 +56,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
|
||||
if (_bis >= numeroutput)
|
||||
{
|
||||
ESP_LOGD(TAG, "ANZAHL OUTPUT NEURONS passt nicht zu geforderter Classifizierung!");
|
||||
ESP_LOGD(TAG, "NUMBER OF OUTPUT NEURONS does not match required classification!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -73,6 +74,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
return (zw_class - _von);
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::GetInputDimension(bool silent = false)
|
||||
{
|
||||
TfLiteTensor* input2 = this->interpreter->input(0);
|
||||
@@ -91,6 +93,7 @@ void CTfLiteClass::GetInputDimension(bool silent = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CTfLiteClass::ReadInputDimenstion(int _dim)
|
||||
{
|
||||
if (_dim == 0)
|
||||
@@ -104,7 +107,6 @@ int CTfLiteClass::ReadInputDimenstion(int _dim)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
{
|
||||
TfLiteTensor* output2 = this->interpreter->output(0);
|
||||
@@ -132,6 +134,7 @@ int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
return numeroutput;
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::Invoke()
|
||||
{
|
||||
if (interpreter != nullptr)
|
||||
@@ -139,10 +142,11 @@ void CTfLiteClass::Invoke()
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
{
|
||||
std::string zw = "ClassFlowCNNGeneral::doNeuralNetwork after LoadInputResizeImage: ";
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - Start");
|
||||
#endif
|
||||
|
||||
unsigned int w = rs->width;
|
||||
unsigned int h = rs->height;
|
||||
@@ -166,36 +170,54 @@ bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
input_data_ptr++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach dem Laden in input");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - done");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::MakeAllocate()
|
||||
bool CTfLiteClass::MakeAllocate()
|
||||
{
|
||||
static tflite::AllOpsResolver resolver;
|
||||
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Make Allocate");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::MakeAllocate");
|
||||
this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
|
||||
TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
|
||||
if (this->interpreter)
|
||||
{
|
||||
TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
|
||||
|
||||
this->GetInputDimension();
|
||||
return;
|
||||
}
|
||||
// ESP_LOGD(TAG, "Allocate Done");
|
||||
this->GetInputDimension();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "new tflite::MicroInterpreter failed");
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::MakeAllocate-new tflite::MicroInterpreter failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc done");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTfLiteClass::GetInputTensorSize(){
|
||||
|
||||
void CTfLiteClass::GetInputTensorSize()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
float *zw = this->input;
|
||||
int test = sizeof(zw);
|
||||
@@ -203,6 +225,7 @@ void CTfLiteClass::GetInputTensorSize(){
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
long CTfLiteClass::GetFileSize(std::string filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
@@ -211,90 +234,95 @@ long CTfLiteClass::GetFileSize(std::string filename)
|
||||
}
|
||||
|
||||
|
||||
unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
|
||||
bool CTfLiteClass::ReadFileToModel(std::string _fn)
|
||||
{
|
||||
long size;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::ReadFileToModel: " + _fn);
|
||||
|
||||
size = GetFileSize(_fn);
|
||||
long size = GetFileSize(_fn);
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
ESP_LOGD(TAG, "File doesn't exist");
|
||||
return NULL;
|
||||
ESP_LOGE(TAG, "CTfLiteClass::ReadFileToModel: Model file doesn't exist: %s", _fn.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char *result = (unsigned char*) malloc(size);
|
||||
int anz = 1;
|
||||
while (!result && (anz < 6)) // maximal 5x versuchen (= 5s)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Speicher ist voll - Versuche es erneut: %d", anz);
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start");
|
||||
#endif
|
||||
result = (unsigned char*) malloc(size);
|
||||
anz++;
|
||||
}
|
||||
|
||||
modelfile = (unsigned char*)GET_MEMORY(size);
|
||||
|
||||
if(result != NULL) {
|
||||
FILE* f = OpenFileAndWait(_fn.c_str(), "rb"); // vorher nur "r"
|
||||
fread(result, 1, size, f);
|
||||
if(modelfile != NULL)
|
||||
{
|
||||
FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r
|
||||
fread(modelfile, 1, size, f);
|
||||
fclose(f);
|
||||
}else {
|
||||
ESP_LOGD(TAG, "No free memory available");
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile successful");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CTfLiteClass::ReadFileToModel: Can't allocate enough memory: " + std::to_string(size));
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::ReadFileToModel");
|
||||
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTfLiteClass::LoadModel(std::string _fn){
|
||||
|
||||
bool CTfLiteClass::LoadModel(std::string _fn)
|
||||
{
|
||||
#ifdef SUPRESS_TFLITE_ERRORS
|
||||
this->error_reporter = new tflite::OwnMicroErrorReporter;
|
||||
#else
|
||||
this->error_reporter = new tflite::MicroErrorReporter;
|
||||
#endif
|
||||
|
||||
modelload = ReadFileToCharArray(_fn.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::LoadModel");
|
||||
|
||||
if (modelload == NULL)
|
||||
if (!ReadFileToModel(_fn.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
model = tflite::GetModel(modelload);
|
||||
// free(rd);
|
||||
TFLITE_MINIMAL_CHECK(model != nullptr);
|
||||
model = tflite::GetModel(modelfile);
|
||||
|
||||
if(model == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CTfLiteClass::CTfLiteClass()
|
||||
{
|
||||
this->model = nullptr;
|
||||
this->modelfile = NULL;
|
||||
this->interpreter = nullptr;
|
||||
this->input = nullptr;
|
||||
this->output = nullptr;
|
||||
this->kTensorArenaSize = 800 * 1024; /// laut testfile: 108000 - bisher 600;; 2021-09-11: 200 * 1024
|
||||
this->tensor_arena = new uint8_t[kTensorArenaSize];
|
||||
this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024
|
||||
this->tensor_arena = (uint8_t*)GET_MEMORY(kTensorArenaSize);
|
||||
}
|
||||
|
||||
|
||||
CTfLiteClass::~CTfLiteClass()
|
||||
{
|
||||
delete this->tensor_arena;
|
||||
free(modelfile);
|
||||
|
||||
free(this->tensor_arena);
|
||||
delete this->interpreter;
|
||||
delete this->error_reporter;
|
||||
if (modelload)
|
||||
free(modelload);
|
||||
}
|
||||
|
||||
|
||||
namespace tflite {
|
||||
|
||||
int OwnMicroErrorReporter::Report(const char* format, va_list args) {
|
||||
namespace tflite
|
||||
{
|
||||
int OwnMicroErrorReporter::Report(const char* format, va_list args)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define TFLITE_MINIMAL_CHECK(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
}
|
||||
#ifndef CTFLITECLASS_H
|
||||
#define CTFLITECLASS_H
|
||||
|
||||
#include "tensorflow/lite/micro/all_ops_resolver.h"
|
||||
#include "tensorflow/lite/micro/micro_error_reporter.h"
|
||||
@@ -15,10 +13,6 @@
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
|
||||
#define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE
|
||||
|
||||
#ifdef SUPRESS_TFLITE_ERRORS
|
||||
#include "tensorflow/lite/core/api/error_reporter.h"
|
||||
#include "tensorflow/lite/micro/compatibility.h"
|
||||
@@ -45,7 +39,7 @@ class CTfLiteClass
|
||||
int kTensorArenaSize;
|
||||
uint8_t *tensor_arena;
|
||||
|
||||
unsigned char *modelload = NULL;
|
||||
unsigned char *modelfile = NULL;
|
||||
|
||||
|
||||
float* input;
|
||||
@@ -53,13 +47,13 @@ class CTfLiteClass
|
||||
int im_height, im_width, im_channel;
|
||||
|
||||
long GetFileSize(std::string filename);
|
||||
unsigned char* ReadFileToCharArray(std::string _fn);
|
||||
|
||||
bool ReadFileToModel(std::string _fn);
|
||||
|
||||
public:
|
||||
CTfLiteClass();
|
||||
~CTfLiteClass();
|
||||
bool LoadModel(std::string _fn);
|
||||
void MakeAllocate();
|
||||
bool MakeAllocate();
|
||||
void GetInputTensorSize();
|
||||
bool LoadInputImageBasis(CImageBasis *rs);
|
||||
void Invoke();
|
||||
@@ -74,3 +68,4 @@ class CTfLiteClass
|
||||
int ReadInputDimenstion(int _dim);
|
||||
};
|
||||
|
||||
#endif //CTFLITECLASS_H
|
||||
@@ -8,7 +8,7 @@
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "defines.h"
|
||||
#include "../../include/defines.h"
|
||||
#include "Helper.h"
|
||||
|
||||
#include "esp_camera.h"
|
||||
@@ -23,27 +23,43 @@
|
||||
#include "server_file.h"
|
||||
#include "connect_wlan.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
ClassFlowControll tfliteflow;
|
||||
|
||||
TaskHandle_t xHandleblink_task_doFlow = NULL;
|
||||
TaskHandle_t xHandletask_autodoFlow = NULL;
|
||||
|
||||
bool FlowInitDone = false;
|
||||
bool bTaskAutoFlowCreated = false;
|
||||
bool flowisrunning = false;
|
||||
|
||||
long auto_intervall = 0;
|
||||
bool auto_isrunning = false;
|
||||
|
||||
|
||||
int countRounds = 0;
|
||||
bool isPlannedReboot = false;
|
||||
|
||||
static const char *TAG = "TFLITE SERVER";
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
int getCountFlowRounds() {
|
||||
|
||||
void CheckIsPlannedReboot()
|
||||
{
|
||||
FILE *pfile;
|
||||
if ((pfile = fopen("/sdcard/reboot.txt", "r")) == NULL)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Not a planned reboot.");
|
||||
isPlannedReboot = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Planned reboot.");
|
||||
DeleteFile("/sdcard/reboot.txt"); // Prevent Boot Loop!!!
|
||||
isPlannedReboot = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int getCountFlowRounds()
|
||||
{
|
||||
return countRounds;
|
||||
}
|
||||
|
||||
@@ -68,32 +84,17 @@ bool isSetupModusActive() {
|
||||
|
||||
void KillTFliteTasks()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Handle: xHandleblink_task_doFlow: %ld", (long) xHandleblink_task_doFlow);
|
||||
#endif
|
||||
if (xHandleblink_task_doFlow != NULL)
|
||||
{
|
||||
TaskHandle_t xHandleblink_task_doFlowTmp = xHandleblink_task_doFlow;
|
||||
xHandleblink_task_doFlow = NULL;
|
||||
vTaskDelete(xHandleblink_task_doFlowTmp);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Killed: xHandleblink_task_doFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Handle: xHandletask_autodoFlow: %ld", (long) xHandletask_autodoFlow);
|
||||
ESP_LOGD(TAG, "KillTFliteTasks: xHandletask_autodoFlow: %ld", (long) xHandletask_autodoFlow);
|
||||
#endif
|
||||
if (xHandletask_autodoFlow != NULL)
|
||||
if( xHandletask_autodoFlow != NULL )
|
||||
{
|
||||
TaskHandle_t xHandletask_autodoFlowTmp = xHandletask_autodoFlow;
|
||||
vTaskDelete(xHandletask_autodoFlow);
|
||||
xHandletask_autodoFlow = NULL;
|
||||
vTaskDelete(xHandletask_autodoFlowTmp);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -103,11 +104,13 @@ void doInit(void)
|
||||
ESP_LOGD(TAG, "Start tfliteflow.InitFlow(config);");
|
||||
#endif
|
||||
tfliteflow.InitFlow(CONFIG_FILE);
|
||||
FlowInitDone = true;
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Finished tfliteflow.InitFlow(config);");
|
||||
#endif
|
||||
|
||||
/* GPIO handler has to be initialized before MQTT init to ensure proper topic subscription */
|
||||
gpio_handler_init();
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
tfliteflow.StartMQTTService();
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -116,7 +119,7 @@ void doInit(void)
|
||||
|
||||
bool doflow(void)
|
||||
{
|
||||
std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
|
||||
std::string zw_time = getCurrentTimeString(LOGFILE_TIME_FORMAT);
|
||||
ESP_LOGD(TAG, "doflow - start %s", zw_time.c_str());
|
||||
flowisrunning = true;
|
||||
tfliteflow.doFlow(zw_time);
|
||||
@@ -124,24 +127,50 @@ bool doflow(void)
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "doflow - end %s", zw_time.c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void blink_task_doFlow(void *pvParameter)
|
||||
esp_err_t handler_get_heap(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "blink_task_doFlow");
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_get_heap - Start");
|
||||
ESP_LOGD(TAG, "handler_get_heap uri: %s", req->uri);
|
||||
#endif
|
||||
if (!flowisrunning)
|
||||
|
||||
std::string zw = "Heap info:<br>" + getESPHeapInfo();
|
||||
|
||||
#ifdef TASK_ANALYSIS_ON
|
||||
char* pcTaskList = (char*) heap_caps_calloc(1, sizeof(char) * 768, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
if (pcTaskList) {
|
||||
vTaskList(pcTaskList);
|
||||
zw = zw + "<br><br>Task info:<br><pre>Name | State | Prio | Lowest stacksize | Creation order | CPU (-1=NoAffinity)<br>"
|
||||
+ std::string(pcTaskList) + "</pre>";
|
||||
heap_caps_free(pcTaskList);
|
||||
}
|
||||
else {
|
||||
zw = zw + "<br><br>Task info:<br>ERROR - Allocation of TaskList buffer in PSRAM failed";
|
||||
}
|
||||
#endif
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (zw.length() > 0)
|
||||
{
|
||||
flowisrunning = true;
|
||||
doflow();
|
||||
flowisrunning = false;
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
xHandleblink_task_doFlow = NULL;
|
||||
else
|
||||
{
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_get_heap - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,15 +181,14 @@ esp_err_t handler_init(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "handler_doinit uri: %s", req->uri);
|
||||
#endif
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
const char* resp_str = "Init started<br>";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
|
||||
doInit();
|
||||
|
||||
resp_str = "Init done<br>";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_init - Done");
|
||||
@@ -170,37 +198,64 @@ esp_err_t handler_init(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_doflow(httpd_req_t *req)
|
||||
{
|
||||
esp_err_t handler_flow_start(httpd_req_t *req) {
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_doflow - Start");
|
||||
LogFile.WriteHeapInfo("handler_flow_start - Start");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "handler_doFlow uri: %s", req->uri);
|
||||
ESP_LOGD(TAG, "handler_flow_start uri: %s", req->uri);
|
||||
|
||||
if (flowisrunning)
|
||||
{
|
||||
const char* resp_str = "doFlow is already running and cannot be started again";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
return 2;
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (auto_isrunning) {
|
||||
xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state. If task is already running, no action
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Flow start triggered by REST API /flow_start");
|
||||
const char* resp_str = "The flow is going to be started immediately or is already running";
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
xTaskCreate(&blink_task_doFlow, "blink_doFlow", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, &xHandleblink_task_doFlow);
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Flow start triggered by REST API, but flow is not active!");
|
||||
const char* resp_str = "WARNING: Flow start triggered by REST API, but flow is not active";
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
const char* resp_str = "doFlow started - takes about 60 seconds";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_doflow - Done");
|
||||
LogFile.WriteHeapInfo("handler_flow_start - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
esp_err_t MQTTCtrlFlowStart(std::string _topic) {
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTTCtrlFlowStart - Start");
|
||||
#endif
|
||||
|
||||
ESP_LOGD(TAG, "MQTTCtrlFlowStart: topic %s", _topic.c_str());
|
||||
|
||||
if (auto_isrunning)
|
||||
{
|
||||
xTaskAbortDelay(xHandletask_autodoFlow); // Delay will be aborted if task is in blocked (waiting) state. If task is already running, no action
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Flow start triggered by MQTT topic " + _topic);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Flow start triggered by MQTT topic " + _topic + ", but flow is not active!");
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTTCtrlFlowStart - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
esp_err_t handler_json(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -209,7 +264,7 @@ esp_err_t handler_json(httpd_req_t *req)
|
||||
|
||||
ESP_LOGD(TAG, "handler_JSON uri: %s", req->uri);
|
||||
|
||||
if (FlowInitDone)
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
@@ -226,13 +281,14 @@ esp_err_t handler_json(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "JSON API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flow not (yet) started: REST API /json not yet available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_JSON - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -240,10 +296,10 @@ esp_err_t handler_json(httpd_req_t *req)
|
||||
esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_wasserzaehler - Start");
|
||||
LogFile.WriteHeapInfo("handler water counter - Start");
|
||||
#endif
|
||||
|
||||
if (FlowInitDone)
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
bool _rawValue = false;
|
||||
bool _noerror = false;
|
||||
@@ -251,7 +307,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
std::string _type = "value";
|
||||
string zw;
|
||||
|
||||
ESP_LOGD(TAG, "handler_wasserzaehler uri: %s", req->uri);
|
||||
ESP_LOGD(TAG, "handler water counter uri: %s", req->uri);
|
||||
|
||||
char _query[100];
|
||||
char _size[10];
|
||||
@@ -309,8 +365,8 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
zw = tfliteflow.getReadoutAll(_intype);
|
||||
ESP_LOGD(TAG, "ZW: %s", zw.c_str());
|
||||
if (zw.length() > 0)
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -379,13 +435,14 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Value API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flow not (yet) started: REST API /value not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_wasserzaehler - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -415,13 +472,13 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
|
||||
if (_task.compare("namenumbers") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Get NUMBER list");
|
||||
ESP_LOGD(TAG, "Get NUMBER list");
|
||||
return get_numbers_file_handler(req);
|
||||
}
|
||||
|
||||
if (_task.compare("data") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Get data list");
|
||||
ESP_LOGD(TAG, "Get data list");
|
||||
return get_data_file_handler(req);
|
||||
}
|
||||
|
||||
@@ -451,7 +508,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
|
||||
CopyFile(in, out);
|
||||
zw = "Copy Done";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
|
||||
|
||||
@@ -520,7 +578,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
delete cim;
|
||||
|
||||
zw = "CutImage Done";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
}
|
||||
|
||||
@@ -564,7 +623,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "test_take - vor MakeImage");
|
||||
std::string zw = tfliteflow.doSingleStep("[MakeImage]", _host);
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
|
||||
|
||||
@@ -578,12 +637,10 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
|
||||
// string zwzw = "Do " + _task + " start\n"; ESP_LOGD(TAG, zwzw.c_str());
|
||||
std::string zw = tfliteflow.doSingleStep("[Alignment]", _host);
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_editflow - Done");
|
||||
#endif
|
||||
@@ -598,10 +655,11 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_prevalue - Start");
|
||||
#endif
|
||||
|
||||
if (FlowInitDone)
|
||||
{
|
||||
const char* resp_str;
|
||||
const char* resp_str;
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (bTaskAutoFlowCreated)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
|
||||
#endif
|
||||
@@ -609,16 +667,13 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
string* zw = tfliteflow.getActStatus();
|
||||
resp_str = zw->c_str();
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flowstatus API not yet initialized. Please retry later...");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
resp_str = "Flow task not yet created";
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_prevalue - Done");
|
||||
@@ -634,17 +689,8 @@ esp_err_t handler_cputemp(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_cputemp - Start");
|
||||
#endif
|
||||
|
||||
const char* resp_str;
|
||||
char cputemp[20];
|
||||
|
||||
sprintf(cputemp, "%4.1f°C", temperatureRead());
|
||||
|
||||
resp_str = cputemp;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, std::to_string((int)temperatureRead()).c_str(), HTTPD_RESP_USE_STRLEN);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_cputemp - End");
|
||||
@@ -662,21 +708,12 @@ esp_err_t handler_rssi(httpd_req_t *req)
|
||||
|
||||
if (getWIFIisConnected())
|
||||
{
|
||||
const char* resp_str;
|
||||
char rssi[20];
|
||||
|
||||
sprintf(rssi, "%idBm", get_WIFI_RSSI());
|
||||
|
||||
resp_str = rssi;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, std::to_string(get_WIFI_RSSI()).c_str(), HTTPD_RESP_USE_STRLEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "RSSI API not yet initialized. Please retry later...");
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "WIFI not (yet) connected: REST API /rssi not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
@@ -691,20 +728,18 @@ esp_err_t handler_rssi(httpd_req_t *req)
|
||||
esp_err_t handler_uptime(httpd_req_t *req)
|
||||
{
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_uptime - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_uptime - Start");
|
||||
#endif
|
||||
|
||||
std::string formatedUptime = getFormatedUptime(false);
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, formatedUptime.c_str(), strlen(formatedUptime.c_str()));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, formatedUptime.c_str(), formatedUptime.length());
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_uptime - End");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_uptime - End");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -729,9 +764,9 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "value", _size, 10) == ESP_OK)
|
||||
{
|
||||
@@ -755,11 +790,8 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
resp_str = zw.c_str();
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
httpd_resp_send(req, resp_str, HTTPD_RESP_USE_STRLEN);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_prevalue - End");
|
||||
@@ -773,29 +805,40 @@ void task_autodoFlow(void *pvParameter)
|
||||
{
|
||||
int64_t fr_start, fr_delta_ms;
|
||||
|
||||
if (esp_reset_reason() == ESP_RST_PANIC) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Restarted due to an Exception/panic! Postponing first round start by 5 minutes to allow for an OTA or to fetch the log!");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Setting logfile level to DEBUG until the next reboot!");
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
//MQTTPublish(GetMQTTMainTopic() + "/" + "status", "Postponing first round", false);
|
||||
vTaskDelay(60*5000 / portTICK_RATE_MS); // Wait 5 minutes to give time to do an OTA or fetch the log
|
||||
bTaskAutoFlowCreated = true;
|
||||
|
||||
if (!isPlannedReboot)
|
||||
{
|
||||
if (esp_reset_reason() == ESP_RST_PANIC) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Restarted due to an Exception/panic! Postponing first round start by 5 minutes to allow for an OTA Update or to fetch the log!");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Setting logfile level to DEBUG until the next reboot!");
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
tfliteflow.setActStatus("Initialization (delayed)");
|
||||
//#ifdef ENABLE_MQTT
|
||||
//MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization (delayed)", false); // Right now, not possible -> MQTT Service is going to be started later
|
||||
//#endif //ENABLE_MQTT
|
||||
vTaskDelay(60*5000 / portTICK_RATE_MS); // Wait 5 minutes to give time to do an OTA Update or fetch the log
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ESP_LOGD(TAG, "task_autodoFlow: start");
|
||||
doInit();
|
||||
gpio_handler_init();
|
||||
|
||||
auto_isrunning = tfliteflow.isAutoStart(auto_intervall);
|
||||
if (isSetupModusActive()) {
|
||||
auto_isrunning = false;
|
||||
std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
|
||||
tfliteflow.doFlowMakeImageOnly(zw_time);
|
||||
|
||||
if (isSetupModusActive())
|
||||
{
|
||||
auto_isrunning = false;
|
||||
std::string zw_time = getCurrentTimeString(LOGFILE_TIME_FORMAT);
|
||||
tfliteflow.doFlowMakeImageOnly(zw_time);
|
||||
}
|
||||
|
||||
while (auto_isrunning)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "----------------------------------------------------------------"); // Clear separation between runs
|
||||
std::string _zw = "Round #" + std::to_string(++countRounds) + " started";
|
||||
time_t roundStartTime = getUpTime();
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
fr_start = esp_timer_get_time();
|
||||
|
||||
@@ -819,14 +862,15 @@ void task_autodoFlow(void *pvParameter)
|
||||
LogFile.RemoveOldDataLog();
|
||||
}
|
||||
|
||||
//CPU Temp
|
||||
float cputmp = temperatureRead();
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << cputmp;
|
||||
string zwtemp = "CPU Temperature: " + stream.str();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zwtemp);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Round #" + std::to_string(countRounds) + " completed");
|
||||
//CPU Temp -> Logfile
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CPU Temperature: " + std::to_string((int)temperatureRead()) + "°C");
|
||||
|
||||
// WIFI Signal Strength (RSSI) -> Logfile
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "WIFI Signal (RSSI): " + std::to_string(get_WIFI_RSSI()) + "dBm");
|
||||
|
||||
//Round finished -> Logfile
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Round #" + std::to_string(countRounds) +
|
||||
" completed (" + std::to_string(getUpTime() - roundStartTime) + " seconds)");
|
||||
|
||||
fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000;
|
||||
if (auto_intervall > fr_delta_ms)
|
||||
@@ -846,16 +890,12 @@ void TFliteDoAutoStart()
|
||||
{
|
||||
BaseType_t xReturned;
|
||||
|
||||
int _i = configMINIMAL_STACK_SIZE;
|
||||
|
||||
ESP_LOGD(TAG, "task_autodoFlow configMINIMAL_STACK_SIZE: %d", _i);
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
|
||||
xReturned = xTaskCreate(&task_autodoFlow, "task_autodoFlow", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, &xHandletask_autodoFlow);
|
||||
xReturned = xTaskCreatePinnedToCore(&task_autodoFlow, "task_autodoFlow", 16 * 1024, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow, 0);
|
||||
//xReturned = xTaskCreate(&task_autodoFlow, "task_autodoFlow", 16 * 1024, NULL, tskIDLE_PRIORITY+2, &xHandletask_autodoFlow);
|
||||
if( xReturned != pdPASS )
|
||||
{
|
||||
|
||||
//Memory: 64 --> 48 --> 35 --> 25
|
||||
ESP_LOGD(TAG, "ERROR task_autodoFlow konnte nicht erzeugt werden!");
|
||||
}
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
@@ -893,15 +933,15 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
camuri.user_ctx = (void*) "Prevalue";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/doflow";
|
||||
camuri.handler = handler_doflow;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
camuri.uri = "/flow_start";
|
||||
camuri.handler = handler_flow_start;
|
||||
camuri.user_ctx = (void*) "Flow Start";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/statusflow.html";
|
||||
camuri.handler = handler_statusflow;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/statusflow";
|
||||
camuri.handler = handler_statusflow;
|
||||
@@ -917,13 +957,13 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
camuri.uri = "/cpu_temperature";
|
||||
camuri.handler = handler_cputemp;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
// Legacy API => New: "/rssi"
|
||||
camuri.uri = "/rssi.html";
|
||||
camuri.handler = handler_rssi;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/rssi";
|
||||
camuri.handler = handler_rssi;
|
||||
@@ -938,7 +978,7 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
camuri.uri = "/editflow";
|
||||
camuri.handler = handler_editflow;
|
||||
camuri.user_ctx = (void*) "EditFlow";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
// Legacy API => New: "/value"
|
||||
camuri.uri = "/value.html";
|
||||
@@ -949,17 +989,21 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
camuri.uri = "/value";
|
||||
camuri.handler = handler_wasserzaehler;
|
||||
camuri.user_ctx = (void*) "Value";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
// Legacy API => New: "/value"
|
||||
camuri.uri = "/wasserzaehler.html";
|
||||
camuri.handler = handler_wasserzaehler;
|
||||
camuri.user_ctx = (void*) "Wasserzaehler";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/json";
|
||||
camuri.handler = handler_json;
|
||||
camuri.user_ctx = (void*) "JSON";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/heap";
|
||||
camuri.handler = handler_get_heap;
|
||||
camuri.user_ctx = (void*) "Heap";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERTFLITE_H
|
||||
#define SERVERTFLITE_H
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <string>
|
||||
|
||||
@@ -7,22 +12,22 @@
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
|
||||
extern ClassFlowControll tfliteflow;
|
||||
void register_server_tflite_uri(httpd_handle_t server);
|
||||
|
||||
void KillTFliteTasks();
|
||||
|
||||
void TFliteDoAutoStart();
|
||||
|
||||
bool isSetupModusActive();
|
||||
int getCountFlowRounds();
|
||||
|
||||
void CheckIsPlannedReboot();
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
|
||||
esp_err_t GetRawJPG(httpd_req_t *req);
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
std::string GetMQTTMainTopic();
|
||||
esp_err_t MQTTCtrlFlowStart(std::string);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
int getCountFlowRounds();
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
|
||||
|
||||
esp_err_t GetRawJPG(httpd_req_t *req);
|
||||
|
||||
extern ClassFlowControll tfliteflow;
|
||||
#endif //SERVERTFLITE_H
|
||||
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES tflite-lib jomjol_logfile)
|
||||
REQUIRES tflite-lib jomjol_logfile jomjol_configfile)
|
||||
|
||||
|
||||
|
||||
@@ -12,21 +12,24 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_sntp.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "configFile.h"
|
||||
#include "Helper.h"
|
||||
|
||||
|
||||
static const char *TAG = "SNTP";
|
||||
|
||||
time_t bootTime;
|
||||
static std::string timeZone = "";
|
||||
static std::string timeServer = "undefined";
|
||||
static bool useNtp = true;
|
||||
|
||||
static bool obtain_time(void);
|
||||
static void initialize_sntp(void);
|
||||
static void logNtpStatus(sntp_sync_status_t status);
|
||||
std::string getNtpStatusText(sntp_sync_status_t status);
|
||||
static void setTimeZone(std::string _tzstring);
|
||||
static std::string getServerName(void);
|
||||
|
||||
void time_sync_notification_cb(struct timeval *tv)
|
||||
{
|
||||
ESP_LOGI(TAG, "Notification of a time synchronization event");
|
||||
}
|
||||
|
||||
std::string ConvertTimeToString(time_t _time, const char * frm)
|
||||
{
|
||||
@@ -39,7 +42,8 @@ std::string ConvertTimeToString(time_t _time, const char * frm)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string gettimestring(const char * frm)
|
||||
|
||||
std::string getCurrentTimeString(const char * frm)
|
||||
{
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
@@ -52,40 +56,14 @@ std::string gettimestring(const char * frm)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool setup_time()
|
||||
|
||||
void time_sync_notification_cb(struct timeval *tv)
|
||||
{
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
bool success = true;
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if (!getTimeIsSet()) {
|
||||
initialize_sntp();
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is not set yet. Getting time over NTP server " + std::string(sntp_getservername(0)));
|
||||
if (!obtain_time()) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
// update 'now' variable with current time
|
||||
time(&now);
|
||||
|
||||
setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3");
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
}
|
||||
else {
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "Time is already set (%s)", strftime_buf);
|
||||
}
|
||||
return success;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is now successfully synced with NTP Server " +
|
||||
getServerName() + ": " + getCurrentTimeString("%Y-%m-%d %H:%M:%S"));
|
||||
}
|
||||
|
||||
|
||||
void setTimeZone(std::string _tzstring)
|
||||
{
|
||||
setenv("TZ", _tzstring.c_str(), 1);
|
||||
@@ -94,100 +72,25 @@ void setTimeZone(std::string _tzstring)
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _tzstring);
|
||||
}
|
||||
|
||||
static bool obtain_time(void)
|
||||
{
|
||||
time_t now = 0;
|
||||
struct tm timeinfo = {};
|
||||
int retry = 0;
|
||||
const int retry_count = 10;
|
||||
bool success = true;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Waiting until we get a time from the NTP server " + std::string(sntp_getservername(0)));
|
||||
while (true) {
|
||||
retry++;
|
||||
|
||||
if (retry == retry_count) {
|
||||
ESP_LOGW(TAG, "NTP time fetching seems to take longer, will check again on next round!"); // The NTP client will automatically retry periodically!
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sntp_sync_status_t status = sntp_get_sync_status();
|
||||
logNtpStatus(status);
|
||||
if (status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is synced with NTP Server " + std::string(sntp_getservername(0)));
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void logNtpStatus(sntp_sync_status_t status) {
|
||||
std::string getNtpStatusText(sntp_sync_status_t status) {
|
||||
if (status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Status OK");
|
||||
return "Synchronized";
|
||||
}
|
||||
else if (status == SNTP_SYNC_STATUS_IN_PROGRESS) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Status: In Progress");
|
||||
return "In Progress";
|
||||
}
|
||||
else { // SNTP_SYNC_STATUS_RESET
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Status: Reset");
|
||||
return "Reset";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_servername(std::string _servername)
|
||||
{
|
||||
sntp_stop();
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, _servername.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Set SNTP-Server to " + std::string(sntp_getservername(0)));
|
||||
sntp_init();
|
||||
obtain_time();
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
ESP_LOGD(TAG, "Time ist %s", zw.c_str());
|
||||
}
|
||||
|
||||
static void initialize_sntp(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing SNTP");
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, "pool.ntp.org");
|
||||
// sntp_set_time_sync_notification_cb(time_sync_notification_cb);
|
||||
sntp_init();
|
||||
}
|
||||
|
||||
void setBootTime()
|
||||
{
|
||||
time(&bootTime);
|
||||
}
|
||||
|
||||
time_t getUpTime()
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
return now - bootTime;
|
||||
}
|
||||
|
||||
bool getTimeIsSet(void) {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGD(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if ((timeinfo.tm_year < (2022 - 1900))) {
|
||||
@@ -198,7 +101,132 @@ bool getTimeIsSet(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void restartNtpClient(void) {
|
||||
sntp_restart();
|
||||
obtain_time();
|
||||
/*void restartNtpClient(void) {
|
||||
// sntp_restart();
|
||||
// obtain_time();
|
||||
}*/
|
||||
|
||||
|
||||
bool getUseNtp(void) {
|
||||
return useNtp;
|
||||
}
|
||||
|
||||
|
||||
std::string getServerName(void) {
|
||||
char buf[100];
|
||||
|
||||
if (sntp_getservername(0)){
|
||||
snprintf(buf, sizeof(buf), "%s", sntp_getservername(0));
|
||||
return std::string(buf);
|
||||
}
|
||||
else { // we have either IPv4 or IPv6 address
|
||||
ip_addr_t const *ip = sntp_getserver(0);
|
||||
if (ipaddr_ntoa_r(ip, buf, sizeof(buf)) != NULL) {
|
||||
return std::string(buf);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load the TimeZone and TimeServer from the config file and initialize the NTP client
|
||||
*/
|
||||
bool setupTime() {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
char strftime_buf[64];
|
||||
|
||||
ConfigFile configFile = ConfigFile(CONFIG_FILE);
|
||||
|
||||
if (!configFile.ConfigFileExists()){
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "No ConfigFile defined - exit setupTime() ");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> splitted;
|
||||
std::string line = "";
|
||||
bool disabledLine = false;
|
||||
bool eof = false;
|
||||
|
||||
/* Load config from config file */
|
||||
while ((!configFile.GetNextParagraph(line, disabledLine, eof) ||
|
||||
(line.compare("[System]") != 0)) && !eof) {}
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (disabledLine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (configFile.getNextLine(&line, disabledLine, eof) &&
|
||||
!configFile.isNewParagraph(line)) {
|
||||
splitted = ZerlegeZeile(line);
|
||||
|
||||
if (toUpper(splitted[0]) == "TIMEZONE") {
|
||||
timeZone = splitted[1];
|
||||
}
|
||||
|
||||
if (toUpper(splitted[0]) == "TIMESERVER") {
|
||||
if (splitted.size() <= 1) { // Key has no value => we use this to show it as disabled
|
||||
timeServer = "";
|
||||
}
|
||||
else {
|
||||
timeServer = splitted[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Setup NTP Server and Timezone */
|
||||
if (timeServer == "undefined") {
|
||||
timeServer = "pool.ntp.org";
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer not defined, using default: " + timeServer);
|
||||
}
|
||||
else if (timeServer == "") {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer config empty, disabling NTP");
|
||||
useNtp = false;
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer: " + timeServer);
|
||||
}
|
||||
|
||||
if (timeZone == "") {
|
||||
timeZone = "CET-1CEST,M3.5.0,M10.5.0/3";
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeZone not set, using default: " + timeZone);
|
||||
}
|
||||
|
||||
|
||||
if (useNtp) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Configuring NTP Client...");
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, timeServer.c_str());
|
||||
sntp_init();
|
||||
|
||||
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
|
||||
|
||||
setTimeZone(timeZone);
|
||||
}
|
||||
|
||||
|
||||
/* The RTC keeps the time after a restart (Except on Power On or Pin Reset)
|
||||
* There should only be a minor correction through NTP */
|
||||
|
||||
// Get current time from RTC
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||
|
||||
if (getTimeIsSet()) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is already set: " + std::string(strftime_buf));
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "The local time is unknown, starting with " + std::string(strftime_buf));
|
||||
if (useNtp) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Once the NTP server provides a time, we will switch to that one");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef TIMESNTP_H
|
||||
#define TIMESNTP_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
@@ -9,18 +15,15 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
// #include "nvs_flash.h"
|
||||
#include "esp_sntp.h"
|
||||
|
||||
bool setup_time(void);
|
||||
|
||||
std::string gettimestring(const char * frm);
|
||||
std::string getCurrentTimeString(const char * frm);
|
||||
std::string ConvertTimeToString(time_t _time, const char * frm);
|
||||
|
||||
void setTimeZone(std::string _tzstring);
|
||||
void reset_servername(std::string _servername);
|
||||
|
||||
void setBootTime();
|
||||
time_t getUpTime();
|
||||
bool getTimeIsSet(void);
|
||||
void restartNtpClient(void);
|
||||
|
||||
bool getUseNtp(void);
|
||||
bool setupTime();
|
||||
|
||||
#endif //TIMESNTP_H
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES nvs_flash jomjol_helper jomjol_mqtt)
|
||||
REQUIRES nvs_flash jomjol_helper jomjol_mqtt wpa_supplicant)
|
||||
|
||||
|
||||
|
||||
@@ -23,28 +23,36 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
//////////////////////
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wnm.h"
|
||||
#include "esp_rrm.h"
|
||||
#include "esp_mbo.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
|
||||
/////////////////////
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY 1000
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static const char *TAG = "WIFI";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
bool WIFIConnected = false;
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
int BlinkDauer;
|
||||
int BlinkAnzahl;
|
||||
@@ -55,12 +63,248 @@ std::string hostname = "";
|
||||
std::string std_hostname = "watermeter";
|
||||
std::string ipadress = "";
|
||||
std::string ssid = "";
|
||||
int RSSIThreashold;
|
||||
|
||||
/////////////////////////////////
|
||||
/////////////////////////////////
|
||||
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
|
||||
int RSSI_Threshold = WLAN_WIFI_RSSI_THRESHOLD;
|
||||
|
||||
/* rrm ctx */
|
||||
int rrm_ctx = 0;
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected & ready to make a request */
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
|
||||
/* esp netif object representing the WIFI station */
|
||||
static esp_netif_t *sta_netif = NULL;
|
||||
|
||||
//static const char *TAG = "roaming_example";
|
||||
|
||||
static inline uint32_t WPA_GET_LE32(const uint8_t *a)
|
||||
{
|
||||
return ((uint32_t) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
|
||||
}
|
||||
|
||||
|
||||
#ifndef WLAN_EID_MEASURE_REPORT
|
||||
#define WLAN_EID_MEASURE_REPORT 39
|
||||
#endif
|
||||
#ifndef MEASURE_TYPE_LCI
|
||||
#define MEASURE_TYPE_LCI 9
|
||||
#endif
|
||||
#ifndef MEASURE_TYPE_LOCATION_CIVIC
|
||||
#define MEASURE_TYPE_LOCATION_CIVIC 11
|
||||
#endif
|
||||
#ifndef WLAN_EID_NEIGHBOR_REPORT
|
||||
#define WLAN_EID_NEIGHBOR_REPORT 52
|
||||
#endif
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
#endif
|
||||
|
||||
#define MAX_NEIGHBOR_LEN 512
|
||||
static char * get_btm_neighbor_list(uint8_t *report, size_t report_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
const uint8_t *data;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Neighbor Report element (IEEE P802.11-REVmc/D5.0)
|
||||
* BSSID[6]
|
||||
* BSSID Information[4]
|
||||
* Operating Class[1]
|
||||
* Channel Number[1]
|
||||
* PHY Type[1]
|
||||
* Optional Subelements[variable]
|
||||
*/
|
||||
#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
|
||||
|
||||
if (!report || report_len == 0) {
|
||||
ESP_LOGI(TAG, "RRM neighbor report is not valid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *buf = (char*) calloc(1, MAX_NEIGHBOR_LEN);
|
||||
data = report;
|
||||
|
||||
while (report_len >= 2 + NR_IE_MIN_LEN) {
|
||||
const uint8_t *nr;
|
||||
char lci[256 * 2 + 1];
|
||||
char civic[256 * 2 + 1];
|
||||
uint8_t nr_len = data[1];
|
||||
const uint8_t *pos = data, *end;
|
||||
|
||||
if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
|
||||
nr_len < NR_IE_MIN_LEN) {
|
||||
ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%u",
|
||||
data[0], nr_len);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (2U + nr_len > report_len) {
|
||||
ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
|
||||
data[0], report_len, nr_len);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
pos += 2;
|
||||
end = pos + nr_len;
|
||||
|
||||
nr = pos;
|
||||
pos += NR_IE_MIN_LEN;
|
||||
|
||||
lci[0] = '\0';
|
||||
civic[0] = '\0';
|
||||
while (end - pos > 2) {
|
||||
uint8_t s_id, s_len;
|
||||
|
||||
s_id = *pos++;
|
||||
s_len = *pos++;
|
||||
if (s_len > end - pos) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
|
||||
/* Measurement Token[1] */
|
||||
/* Measurement Report Mode[1] */
|
||||
/* Measurement Type[1] */
|
||||
/* Measurement Report[variable] */
|
||||
switch (pos[2]) {
|
||||
case MEASURE_TYPE_LCI:
|
||||
if (lci[0])
|
||||
break;
|
||||
memcpy(lci, pos, s_len);
|
||||
break;
|
||||
case MEASURE_TYPE_LOCATION_CIVIC:
|
||||
if (civic[0])
|
||||
break;
|
||||
memcpy(civic, pos, s_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos += s_len;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "RMM neigbor report bssid=" MACSTR
|
||||
" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
|
||||
MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
|
||||
nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
|
||||
nr[ETH_ALEN + 6],
|
||||
lci[0] ? " lci=" : "", lci,
|
||||
civic[0] ? " civic=" : "", civic);
|
||||
|
||||
/* neighbor start */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, " neighbor=");
|
||||
/* bssid */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, MACSTR, MAC2STR(nr));
|
||||
/* , */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* bssid info */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "0x%04x", WPA_GET_LE32(nr + ETH_ALEN));
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* operating class */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 4]);
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* channel number */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 5]);
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* phy type */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 6]);
|
||||
/* optional elements, skip */
|
||||
|
||||
data = end;
|
||||
report_len -= 2 + nr_len;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void neighbor_report_recv_cb(void *ctx, const uint8_t *report, size_t report_len)
|
||||
{
|
||||
int *val = (int*) ctx;
|
||||
uint8_t *pos = (uint8_t *)report;
|
||||
int cand_list = 0;
|
||||
|
||||
if (!report) {
|
||||
ESP_LOGE(TAG, "report is null");
|
||||
return;
|
||||
}
|
||||
if (*val != rrm_ctx) {
|
||||
ESP_LOGE(TAG, "rrm_ctx value didn't match, not initiated by us");
|
||||
return;
|
||||
}
|
||||
/* dump report info */
|
||||
ESP_LOGI(TAG, "rrm: neighbor report len=%d", report_len);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, pos, report_len, ESP_LOG_INFO);
|
||||
|
||||
/* create neighbor list */
|
||||
char *neighbor_list = get_btm_neighbor_list(pos + 1, report_len - 1);
|
||||
|
||||
/* In case neighbor list is not present issue a scan and get the list from that */
|
||||
if (!neighbor_list) {
|
||||
/* issue scan */
|
||||
wifi_scan_config_t params;
|
||||
memset(¶ms, 0, sizeof(wifi_scan_config_t));
|
||||
if (esp_wifi_scan_start(¶ms, true) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* cleanup from net802.11 */
|
||||
uint16_t number = 1;
|
||||
wifi_ap_record_t ap_records;
|
||||
esp_wifi_scan_get_ap_records(&number, &ap_records);
|
||||
cand_list = 1;
|
||||
}
|
||||
/* send AP btm query, this will cause STA to roam as well */
|
||||
esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, neighbor_list, cand_list);
|
||||
|
||||
cleanup:
|
||||
if (neighbor_list)
|
||||
free(neighbor_list);
|
||||
}
|
||||
|
||||
|
||||
static void esp_bss_rssi_low_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
wifi_event_bss_rssi_low_t *event = (wifi_event_bss_rssi_low_t*) event_data;
|
||||
|
||||
ESP_LOGI(TAG, "%s:bss rssi is=%d", __func__, event->rssi);
|
||||
/* Lets check channel conditions */
|
||||
rrm_ctx++;
|
||||
if (esp_rrm_send_neighbor_rep_request(neighbor_report_recv_cb, &rrm_ctx) < 0) {
|
||||
/* failed to send neighbor report request */
|
||||
ESP_LOGI(TAG, "failed to send neighbor report request");
|
||||
if (esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, NULL, 0) < 0) {
|
||||
ESP_LOGI(TAG, "failed to send btm query");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////
|
||||
//////////////////////////////////
|
||||
|
||||
|
||||
std::string* getIPAddress()
|
||||
{
|
||||
return &ipadress;
|
||||
}
|
||||
|
||||
|
||||
std::string* getSSID()
|
||||
{
|
||||
return &ssid;
|
||||
@@ -103,16 +347,18 @@ void task_doBlink(void *pvParameter)
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
}
|
||||
|
||||
|
||||
void LEDBlinkTask(int _dauer, int _anz, bool _off)
|
||||
{
|
||||
BlinkDauer = _dauer;
|
||||
BlinkAnzahl = _anz;
|
||||
BlinkOff = _off;
|
||||
|
||||
xTaskCreate(&task_doBlink, "task_doBlink", configMINIMAL_STACK_SIZE * 8, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
xTaskCreate(&task_doBlink, "task_doBlink", 4 * 1024, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
@@ -148,6 +394,7 @@ static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) {
|
||||
std::string zw = std::string(ip);
|
||||
std::stringstream s(zw);
|
||||
@@ -156,8 +403,9 @@ void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) {
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns)
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreashold)
|
||||
{
|
||||
RSSI_Threshold = _rssithreashold;
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
@@ -167,20 +415,6 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
|
||||
if ((_ipadr != NULL) && (_gw != NULL) && (_netmask != NULL))
|
||||
{
|
||||
/*
|
||||
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
int a, b, c, d;
|
||||
strinttoip4(_ipadr, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.ip, a, b, c, d);
|
||||
strinttoip4(_gw, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.gw, a, b, c, d);
|
||||
strinttoip4(_netmask, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.netmask, a, b, c, d);
|
||||
|
||||
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
|
||||
*/
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "set IP %s, GW %s, Netmask %s manual", _ipadr, _gw, _netmask);
|
||||
esp_netif_dhcpc_stop(my_sta);
|
||||
@@ -213,11 +447,9 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(my_sta, ESP_NETIF_DNS_MAIN, &dns_info));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
esp_event_handler_instance_t instance_bss_rssi_low;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&event_handler,
|
||||
@@ -228,6 +460,15 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_got_ip));
|
||||
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
WIFI_EVENT_STA_BSS_RSSI_LOW,
|
||||
&esp_bss_rssi_low_handler,
|
||||
NULL,
|
||||
&instance_bss_rssi_low));
|
||||
#endif
|
||||
|
||||
wifi_config_t wifi_config = { };
|
||||
|
||||
strcpy((char*)wifi_config.sta.ssid, (const char*)_ssid);
|
||||
@@ -242,10 +483,10 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
esp_err_t ret = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA , _hostname);
|
||||
hostname = std::string(_hostname);
|
||||
if(ret != ESP_OK ){
|
||||
ESP_LOGE(TAG,"failed to set hostname:%d",ret);
|
||||
ESP_LOGE(TAG,"Failed to set hostname: %d",ret);
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG,"Set Hostname to:%s", _hostname);
|
||||
ESP_LOGI(TAG,"Set hostname to: %s", _hostname);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -264,15 +505,15 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
* happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "connected to ap SSID: %s, password: XXXXXXX", _ssid);
|
||||
ESP_LOGI(TAG, "Connected with AP: %s, password: XXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "connected to ap SSID: %s, password: %s", _ssid, _password);
|
||||
ESP_LOGI(TAG, "Connected with AP: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID: %s, password: XXXXXXXX", _ssid);
|
||||
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: XXXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID: %s, password: %s", _ssid, _password);
|
||||
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||
@@ -286,6 +527,7 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
// vEventGroupDelete(s_wifi_event_group);
|
||||
}
|
||||
|
||||
|
||||
int get_WIFI_RSSI()
|
||||
{
|
||||
wifi_ap_record_t ap;
|
||||
@@ -293,17 +535,34 @@ int get_WIFI_RSSI()
|
||||
return ap.rssi;
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname)
|
||||
{
|
||||
wifi_init_sta(_ssid, _password, _hostname, NULL, NULL, NULL, NULL);
|
||||
wifi_init_sta(_ssid, _password, _hostname, NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password)
|
||||
{
|
||||
wifi_init_sta(_ssid, _password, NULL, NULL, NULL, NULL, NULL);
|
||||
wifi_init_sta(_ssid, _password, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
bool getWIFIisConnected() {
|
||||
|
||||
bool getWIFIisConnected()
|
||||
{
|
||||
return WIFIConnected;
|
||||
}
|
||||
|
||||
|
||||
void WIFIDestroy()
|
||||
{
|
||||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler);
|
||||
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler);
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, esp_bss_rssi_low_handler);
|
||||
#endif
|
||||
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CONNECT_WLAN_H
|
||||
#define CONNECT_WLAN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreashold);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password);
|
||||
|
||||
@@ -11,8 +13,10 @@ std::string* getIPAddress();
|
||||
std::string* getSSID();
|
||||
int get_WIFI_RSSI();
|
||||
bool getWIFIisConnected();
|
||||
void WIFIDestroy();
|
||||
|
||||
extern std::string hostname;
|
||||
extern std::string std_hostname;
|
||||
extern int RSSIThreashold;
|
||||
|
||||
#endif
|
||||
#endif //CONNECT_WLAN_H
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "WLAN.INI";
|
||||
|
||||
@@ -25,7 +26,7 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
|
||||
input = trim(input, delimiter);
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
if (pos != std::string::npos) // Zerlegt nur bis ersten Gleichheitszeichen !!! Sonderfall für WLAN.ini
|
||||
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);
|
||||
@@ -40,7 +41,7 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
|
||||
|
||||
|
||||
|
||||
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns)
|
||||
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold)
|
||||
{
|
||||
std::string ssid = "";
|
||||
std::string passphrase = "";
|
||||
@@ -48,19 +49,23 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
std::string gw = "";
|
||||
std::string netmask = "";
|
||||
std::string dns = "";
|
||||
int rssithreshold = 0;
|
||||
|
||||
std::string line = "";
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
hostname = std_hostname;
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
if (!pFile)
|
||||
return false;
|
||||
|
||||
ESP_LOGD(TAG, "file loaded");
|
||||
|
||||
if (pFile == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
char zw[1024];
|
||||
fgets(zw, 1024, pFile);
|
||||
@@ -69,53 +74,62 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
// ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "HOSTNAME")){
|
||||
hostname = trim(zerlegt[1]);
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
|
||||
hostname = trim(splitted[1]);
|
||||
if ((hostname[0] == '"') && (hostname[hostname.length()-1] == '"')){
|
||||
hostname = hostname.substr(1, hostname.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "SSID")){
|
||||
ssid = trim(zerlegt[1]);
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "SSID")){
|
||||
ssid = trim(splitted[1]);
|
||||
if ((ssid[0] == '"') && (ssid[ssid.length()-1] == '"')){
|
||||
ssid = ssid.substr(1, ssid.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "PASSWORD")){
|
||||
passphrase = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHREASHOLD")){
|
||||
string _s = trim(splitted[1]);
|
||||
if ((_s[0] == '"') && (_s[_s.length()-1] == '"')){
|
||||
_s = _s.substr(1, ssid.length()-2);
|
||||
}
|
||||
rssithreshold = atoi(_s.c_str());
|
||||
}
|
||||
|
||||
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "PASSWORD")){
|
||||
passphrase = splitted[1];
|
||||
if ((passphrase[0] == '"') && (passphrase[passphrase.length()-1] == '"')){
|
||||
passphrase = passphrase.substr(1, passphrase.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "IP")){
|
||||
ipaddress = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
|
||||
ipaddress = splitted[1];
|
||||
if ((ipaddress[0] == '"') && (ipaddress[ipaddress.length()-1] == '"')){
|
||||
ipaddress = ipaddress.substr(1, ipaddress.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "GATEWAY")){
|
||||
gw = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
|
||||
gw = splitted[1];
|
||||
if ((gw[0] == '"') && (gw[gw.length()-1] == '"')){
|
||||
gw = gw.substr(1, gw.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "NETMASK")){
|
||||
netmask = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
|
||||
netmask = splitted[1];
|
||||
if ((netmask[0] == '"') && (netmask[netmask.length()-1] == '"')){
|
||||
netmask = netmask.substr(1, netmask.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "DNS")){
|
||||
dns = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
|
||||
dns = splitted[1];
|
||||
if ((dns[0] == '"') && (dns[dns.length()-1] == '"')){
|
||||
dns = dns.substr(1, dns.length()-2);
|
||||
}
|
||||
@@ -179,6 +193,10 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
}
|
||||
else
|
||||
_dns = NULL;
|
||||
|
||||
_rssithreashold = rssithreshold;
|
||||
RSSIThreashold = rssithreshold;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +208,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
return false;
|
||||
|
||||
string line = "";
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
bool found = false;
|
||||
|
||||
@@ -198,7 +216,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
ESP_LOGD(TAG, "file loaded\n");
|
||||
|
||||
@@ -212,10 +230,10 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "HOSTNAME")){
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
|
||||
line = "hostname = \"" + _newhostname + "\"\n";
|
||||
found = true;
|
||||
}
|
||||
@@ -240,7 +258,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = OpenFileAndWait(fn.c_str(), "w+");
|
||||
pFile = fopen(fn.c_str(), "w+");
|
||||
|
||||
for (int i = 0; i < neuesfile.size(); ++i)
|
||||
{
|
||||
@@ -255,3 +273,75 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ChangeRSSIThreashold(std::string fn, int _newrssithreashold)
|
||||
{
|
||||
if (RSSIThreashold == _newrssithreashold)
|
||||
return false;
|
||||
|
||||
string line = "";
|
||||
std::vector<string> splitted;
|
||||
|
||||
bool found = false;
|
||||
|
||||
std::vector<string> neuesfile;
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
ESP_LOGD(TAG, "file loaded\n");
|
||||
|
||||
if (pFile == NULL)
|
||||
return false;
|
||||
|
||||
char zw[1024];
|
||||
fgets(zw, 1024, pFile);
|
||||
line = std::string(zw);
|
||||
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", line.c_str());
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHREASHOLD")){
|
||||
line = "RSSIThreashold = " + to_string(_newrssithreashold) + "\n";
|
||||
found = true;
|
||||
}
|
||||
|
||||
neuesfile.push_back(line);
|
||||
|
||||
if (fgets(zw, 1024, pFile) == NULL)
|
||||
{
|
||||
line = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
line = std::string(zw);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
line = "RSSIThreashold = " + to_string(_newrssithreashold) + "\n";
|
||||
neuesfile.push_back(line);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = fopen(fn.c_str(), "w+");
|
||||
|
||||
for (int i = 0; i < neuesfile.size(); ++i)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
|
||||
fputs(neuesfile[i].c_str(), pFile);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
ESP_LOGD(TAG, "*** RSSIThreashold update done ***");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef READ_WLANINI_H
|
||||
#define READ_WLANINI_H
|
||||
|
||||
#include <string>
|
||||
|
||||
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns);
|
||||
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold);
|
||||
|
||||
bool ChangeHostName(std::string fn, std::string _newhostname);
|
||||
bool ChangeRSSIThreashold(std::string fn, int _newrssithreashold);
|
||||
|
||||
|
||||
#endif
|
||||
#endif //READ_WLANINI_H
|
||||
@@ -1,6 +1,321 @@
|
||||
#pragma once
|
||||
#ifndef defines_h
|
||||
#define defines_h
|
||||
|
||||
#define CONFIG_FILE "/sdcard/config/config.ini"
|
||||
/////////////////////////////////////////////
|
||||
//// Global definitions ////
|
||||
/////////////////////////////////////////////
|
||||
|
||||
#endif // ifndef defines_h
|
||||
//********* debug options : *************
|
||||
|
||||
//can be set in platformio with -D OPTION_TO_ACTIVATE
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
//#define DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
//#define DEBUG_ENABLE_SYSINFO
|
||||
//#define DEBUG_ENABLE_PERFMON
|
||||
//#define DEBUG_HIMEM_MEMORY_CHECK
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//=> CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//=> CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
|
||||
// use himem //https://github.com/jomjol/AI-on-the-edge-device/issues/1842
|
||||
#define USE_HIMEM_IF_AVAILABLE
|
||||
|
||||
/* Uncomment this to generate task list with stack sizes using the /heap handler
|
||||
PLEASE BE AWARE: The following CONFIG parameters have to to be set in
|
||||
sdkconfig.defaults before use of this function is possible!!
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=1
|
||||
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
*/
|
||||
// server_tflite.cpp
|
||||
//#define TASK_ANALYSIS_ON
|
||||
|
||||
|
||||
//Memory leak tracing
|
||||
//https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/heap_debug.html#heap-information
|
||||
//need CONFIG_HEAP_TRACING_STANDALONE=y or #define CONFIG_HEAP_TRACING_STANDALONE
|
||||
//all setup is predifined in [env:esp32cam-dev-task-analysis]
|
||||
//#define HEAP_TRACING_MAIN_WIFI || HEAP_TRACING_MAIN_START //enable heap tracing per function in main.cpp
|
||||
//all defines in [env:esp32cam-dev-task-analysis]
|
||||
//#define HEAP_TRACING_MAIN_WIFI
|
||||
//#define HEAP_TRACING_MAIN_START
|
||||
//#define HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
|
||||
/* Uncomment this to keep the logfile open for appending.
|
||||
* If commented out, the logfile gets opened/closed for each log measage (old behaviour) */
|
||||
// ClassLogFile
|
||||
//#define KEEP_LOGFILE_OPEN_FOR_APPENDING
|
||||
|
||||
//****************************************
|
||||
|
||||
//compiler optimization for tflite-micro-esp-examples
|
||||
#define XTENSA
|
||||
//#define CONFIG_IDF_TARGET_ARCH_XTENSA //not needed with platformio/espressif32 @ 5.2.0
|
||||
|
||||
|
||||
//ClassControllCamera + ClassFlowMakeImage + connect_wlan + main
|
||||
#define FLASH_GPIO GPIO_NUM_4
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
//ClassFlowMQTT + interface_mqtt + connect_wlan + main
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
//ClassControllCamera
|
||||
#define USE_PWM_LEDFLASH // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
|
||||
|
||||
//server_GPIO
|
||||
#define __LEDGLOBAL
|
||||
|
||||
//ClassControllCamera + ClassFlowMakeImage
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
#define BOARD_ESP32CAM_AITHINKER
|
||||
|
||||
//server_GPIO + server_file + SoftAP
|
||||
#define CONFIG_FILE "/sdcard/config/config.ini"
|
||||
|
||||
//ClassFlowControll + Main + SoftAP
|
||||
#define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
|
||||
|
||||
//main
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
|
||||
// server_file + Helper
|
||||
#define FILE_PATH_MAX (255) //Max length a file path can have on storage
|
||||
|
||||
//server_file +(ota_page.html + upload_script.html)
|
||||
#define MAX_FILE_SIZE (8000*1024) // 8 MB Max size of an individual file. Make sure this value is same as that set in upload_script.html and ota_page.html!
|
||||
#define MAX_FILE_SIZE_STR "8MB"
|
||||
|
||||
#define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes // Size of partial log file to return
|
||||
|
||||
#define SERVER_FILER_SCRATCH_BUFSIZE 4096
|
||||
#define SERVER_HELPER_SCRATCH_BUFSIZE 8192
|
||||
#define SERVER_OTA_SCRATCH_BUFSIZE 1024
|
||||
|
||||
//server_file + server_help
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
|
||||
//server_ota
|
||||
#define HASH_LEN 32 // SHA-256 digest length
|
||||
#define OTA_URL_SIZE 256
|
||||
|
||||
//ClassFlow + ClassFlowImage + server_tflite
|
||||
#define LOGFILE_TIME_FORMAT "%Y%m%d-%H%M%S"
|
||||
#define LOGFILE_TIME_FORMAT_DATE_EXTR substr(0, 8)
|
||||
#define LOGFILE_TIME_FORMAT_HOUR_EXTR substr(9, 2)
|
||||
|
||||
//ClassFlowControll
|
||||
#define READOUT_TYPE_VALUE 0
|
||||
#define READOUT_TYPE_PREVALUE 1
|
||||
#define READOUT_TYPE_RAWVALUE 2
|
||||
#define READOUT_TYPE_ERROR 3
|
||||
|
||||
//ClassFlowControll: Serve alg_roi.jpg from memory as JPG
|
||||
#define ALGROI_LOAD_FROM_MEM_AS_JPG // Load ALG_ROI.JPG as rendered JPG from RAM
|
||||
#define ALGROI_LOAD_FROM_MEM_AS_JPG__SHOW_TAKE_IMAGE_PROCESS // Show take image image processing on webinterface (overview.html)
|
||||
|
||||
//ClassFlowMQTT
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
//ClassFlowPostProcessing
|
||||
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
|
||||
#define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
|
||||
|
||||
//CImageBasis
|
||||
#define HTTP_BUFFER_SENT 1024
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
#define MAX_JPG_SIZE 128000
|
||||
|
||||
|
||||
//CAlignAndCutImage + CImageBasis
|
||||
#define _USE_MATH_DEFINES
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
//make_stb + stb_image_resize + stb_image_write + stb_image //do not work if not in make_stb.cpp
|
||||
//#define STB_IMAGE_IMPLEMENTATION
|
||||
//#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
//#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STBI_ONLY_JPEG // (save 2% of Flash, but breaks the alignment mark generation, see https://github.com/jomjol/AI-on-the-edge-device/issues/1721)
|
||||
|
||||
//interface_influxdb
|
||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||
|
||||
//server_mqtt
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
//CTfLiteClass
|
||||
#define TFLITE_MINIMAL_CHECK(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
}
|
||||
#define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE
|
||||
|
||||
//connect_wlan
|
||||
#define WLAN_USE_MESH_ROAMING
|
||||
#define WLAN_WIFI_RSSI_THRESHOLD -50
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY 1000
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
//ClassFlowCNNGeneral
|
||||
#define Analog_error 3
|
||||
#define AnalogToDigtalFehler 0.8
|
||||
#define Digital_Uncertainty 0.2
|
||||
#define DigitalBand 3
|
||||
#define Digital_Transition_Range_Predecessor 2
|
||||
#define Digital_Transition_Area_Predecessor 0.7 // 9.3 - 0.7
|
||||
#define Digital_Transition_Area_Forward 9.7 // Pre-run zero crossing only happens from approx. 9.7 onwards
|
||||
|
||||
|
||||
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//// Conditionnal definitions ////
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//******* camera model
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM GPIO_NUM_32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM GPIO_NUM_0
|
||||
#define SIOD_GPIO_NUM GPIO_NUM_26
|
||||
#define SIOC_GPIO_NUM GPIO_NUM_27
|
||||
|
||||
#define Y9_GPIO_NUM GPIO_NUM_35
|
||||
#define Y8_GPIO_NUM GPIO_NUM_34
|
||||
#define Y7_GPIO_NUM GPIO_NUM_39
|
||||
#define Y6_GPIO_NUM GPIO_NUM_36
|
||||
#define Y5_GPIO_NUM GPIO_NUM_21
|
||||
#define Y4_GPIO_NUM GPIO_NUM_19
|
||||
#define Y3_GPIO_NUM GPIO_NUM_18
|
||||
#define Y2_GPIO_NUM GPIO_NUM_5
|
||||
#define VSYNC_GPIO_NUM GPIO_NUM_25
|
||||
#define HREF_GPIO_NUM GPIO_NUM_23
|
||||
#define PCLK_GPIO_NUM GPIO_NUM_22
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif //camera model
|
||||
|
||||
// ******* Board type
|
||||
#ifdef BOARD_WROVER_KIT // WROVER-KIT PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN -1 //power down is not used
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 21
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 19
|
||||
#define CAM_PIN_D2 18
|
||||
#define CAM_PIN_D1 5
|
||||
#define CAM_PIN_D0 4
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#endif //// WROVER-KIT PIN Map
|
||||
|
||||
|
||||
#ifdef BOARD_ESP32CAM_AITHINKER // ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN 32
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 0
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 21
|
||||
#define CAM_PIN_D2 19
|
||||
#define CAM_PIN_D1 18
|
||||
#define CAM_PIN_D0 5
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#endif // ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
// ******* LED definition
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
|
||||
//// PWM für Flash-LED
|
||||
#define LEDC_TIMER LEDC_TIMER_1 // LEDC_TIMER_0
|
||||
#define LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_OUTPUT_IO FLASH_GPIO // Define the output GPIO
|
||||
#define LEDC_CHANNEL LEDC_CHANNEL_1
|
||||
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
|
||||
//#define LEDC_DUTY (195) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095
|
||||
#define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz
|
||||
|
||||
#endif //USE_PWM_LEDFLASH
|
||||
|
||||
//softAP
|
||||
#ifdef ENABLE_SOFTAP
|
||||
#define EXAMPLE_ESP_WIFI_SSID "AI-on-the-Edge"
|
||||
#define EXAMPLE_ESP_WIFI_PASS ""
|
||||
#define EXAMPLE_ESP_WIFI_CHANNEL 11
|
||||
#define EXAMPLE_MAX_STA_CONN 1
|
||||
#endif // ENABLE_SOFTAP
|
||||
|
||||
#endif // ifndef defines_h
|
||||
|
||||
@@ -1,21 +1,24 @@
|
||||
#include <string>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
//#include <string>
|
||||
//#include "freertos/FreeRTOS.h"
|
||||
//#include "freertos/task.h"
|
||||
//#include "freertos/event_groups.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "sdkconfig.h"
|
||||
//#include "driver/gpio.h"
|
||||
//#include "sdkconfig.h"
|
||||
//#include "esp_psram.h" // Comming in IDF 5.0, see https://docs.espressif.com/projects/esp-idf/en/v5.0-beta1/esp32/migration-guides/release-5.x/system.html?highlight=esp_psram_get_size
|
||||
//#include "spiram.h"
|
||||
#include "esp32/spiram.h"
|
||||
|
||||
|
||||
// SD-Card ////////////////////
|
||||
#include "nvs_flash.h"
|
||||
//#include "nvs_flash.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
//#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
//#include "driver/sdmmc_defs.h"
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "connect_wlan.h"
|
||||
@@ -26,39 +29,57 @@
|
||||
#include "server_file.h"
|
||||
#include "server_ota.h"
|
||||
#include "time_sntp.h"
|
||||
#include "ClassControllCamera.h"
|
||||
//#include "ClassControllCamera.h"
|
||||
#include "server_main.h"
|
||||
#include "server_camera.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "server_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
#include "Helper.h"
|
||||
//#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
//#include "server_GPIO.h"
|
||||
|
||||
#ifdef ENABLE_SOFTAP
|
||||
#include "softAP.h"
|
||||
#endif //ENABLE_SOFTAP
|
||||
|
||||
#ifdef DISABLE_BROWNOUT_DETECTOR
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
|
||||
#include "esp_sys.h"
|
||||
#endif
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#include "esp32/himem.h"
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
#include "himem_memory_check.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
|
||||
#include <esp_heap_trace.h>
|
||||
#define NUM_RECORDS 300
|
||||
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
|
||||
#endif
|
||||
|
||||
extern const char* GIT_TAG;
|
||||
extern const char* GIT_REV;
|
||||
extern const char* GIT_BRANCH;
|
||||
extern const char* BUILD_TIME;
|
||||
|
||||
extern std::string getFwVersion(void);
|
||||
extern std::string getHTMLversion(void);
|
||||
extern std::string getHTMLcommit(void);
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
// #include "jomjol_WS2812Slow.h"
|
||||
#include "SmartLeds.h"
|
||||
|
||||
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
|
||||
#include "server_GPIO.h"
|
||||
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
//#define FLASH_GPIO GPIO_NUM_4
|
||||
|
||||
bool Init_NVS_SDCard()
|
||||
{
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
@@ -97,7 +118,7 @@ bool Init_NVS_SDCard()
|
||||
// formatted in case when mounting fails.
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 7, // anstatt 5 (2022-09-21)
|
||||
.max_files = 12, // previously -> 2022-09-21: 5, 2023-01-02: 7
|
||||
.allocation_unit_size = 16 * 1024
|
||||
};
|
||||
|
||||
@@ -148,7 +169,19 @@ void task_MainInitError_blink(void *pvParameter)
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
|
||||
//register a buffer to record the memory trace
|
||||
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
|
||||
#endif
|
||||
|
||||
TickType_t xDelay;
|
||||
|
||||
#ifdef DISABLE_BROWNOUT_DETECTOR
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
|
||||
#endif
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted
|
||||
|
||||
@@ -165,8 +198,9 @@ extern "C" void app_main(void)
|
||||
return; // No way to continue without SD-Card!
|
||||
}
|
||||
|
||||
string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \
|
||||
"', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \
|
||||
setupTime();
|
||||
|
||||
string versionFormated = getFwVersion() + ", Date/Time: " + std::string(BUILD_TIME) + \
|
||||
", Web UI: " + getHTMLversion();
|
||||
|
||||
if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix
|
||||
@@ -174,18 +208,44 @@ extern "C" void app_main(void)
|
||||
}
|
||||
|
||||
LogFile.CreateLogDirectories();
|
||||
MakeDir("/sdcard/demo"); // needed for demo mode
|
||||
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Startup ====================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device Info : " + get_device_info() );
|
||||
ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str());
|
||||
#endif
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Himem mem check : " + himem_memory_check() );
|
||||
ESP_LOGD(TAG, "Himem mem check %s", himem_memory_check().c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CheckIsPlannedReboot();
|
||||
CheckOTAUpdate();
|
||||
CheckUpdate();
|
||||
#ifdef ENABLE_SOFTAP
|
||||
CheckStartAPMode(); // if no wlan.ini and/or config.ini --> AP ist startet and this function does not exit anymore until reboot
|
||||
#endif
|
||||
|
||||
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL;
|
||||
LoadWlanFromFile("/sdcard/wlan.ini", ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
#ifdef HEAP_TRACING_MAIN_WIFI
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL; int rssithreashold = 0;
|
||||
LoadWlanFromFile(WLAN_CONFIG_FILE, ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreashold);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN-Settings - RSSI-Threashold: " + to_string(rssithreashold));
|
||||
|
||||
if (ssid != NULL && passwd != NULL)
|
||||
#ifdef __HIDE_PASSWORD
|
||||
@@ -208,19 +268,21 @@ extern "C" void app_main(void)
|
||||
ESP_LOGD(TAG, "DNS IP: %s", dns);
|
||||
|
||||
|
||||
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreashold);
|
||||
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
#ifdef HEAP_TRACING_MAIN_WIFI
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
if (!setup_time()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed!");
|
||||
setSystemStatusFlag(SYSTEM_STATUS_NTP_BAD);
|
||||
}
|
||||
|
||||
setBootTime();
|
||||
#ifdef HEAP_TRACING_MAIN_START
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================== Main Started =================");
|
||||
@@ -228,10 +290,16 @@ extern "C" void app_main(void)
|
||||
|
||||
if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7)) { // Compare the first 7 characters of both hashes
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Web UI version (") + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ") !");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Please make sure to setup the SD-Card properly (check the documentation) or re-install using the AI-on-the-edge-device__update__*.zip!");
|
||||
}
|
||||
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
std::string zw = getCurrentTimeString("%Y%m%d-%H%M%S");
|
||||
ESP_LOGD(TAG, "time %s", zw.c_str());
|
||||
|
||||
#ifdef HEAP_TRACING_MAIN_START
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
/* Check if PSRAM can be initalized */
|
||||
esp_err_t ret;
|
||||
@@ -274,9 +342,8 @@ extern "C" void app_main(void)
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
|
||||
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
|
||||
}
|
||||
} else { // Test Camera
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
} else { // Test Camera
|
||||
if (!Camera.testCamera()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
|
||||
/* Easiest would be to simply restart here and try again,
|
||||
how ever there seem to be systems where it fails at startup but still work corectly later.
|
||||
@@ -284,7 +351,6 @@ extern "C" void app_main(void)
|
||||
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
|
||||
}
|
||||
else {
|
||||
esp_camera_fb_return(fb);
|
||||
Camera.LightOnOff(false);
|
||||
}
|
||||
}
|
||||
@@ -307,7 +373,7 @@ extern "C" void app_main(void)
|
||||
|
||||
gpio_handler_create(server);
|
||||
|
||||
ESP_LOGD(TAG, "vor reg server main");
|
||||
ESP_LOGD(TAG, "Before reg server main");
|
||||
register_server_main_uri(server, "/sdcard");
|
||||
|
||||
|
||||
@@ -318,16 +384,17 @@ extern "C" void app_main(void)
|
||||
/* Main Init has successed or only an error which allows to continue operation */
|
||||
if (getSystemStatus() == 0) { // No error flag is set
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!");
|
||||
ESP_LOGD(TAG, "vor do autostart");
|
||||
ESP_LOGD(TAG, "Before do autostart");
|
||||
TFliteDoAutoStart();
|
||||
}
|
||||
else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue...
|
||||
isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors, but trying to continue...");
|
||||
ESP_LOGD(TAG, "vor do autostart");
|
||||
ESP_LOGD(TAG, "Before do autostart");
|
||||
TFliteDoAutoStart();
|
||||
}
|
||||
else { // Any other error is critical and makes running the flow impossible.
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Not starting flows!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
#include "server_tflite.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
std::string starttime = "";
|
||||
|
||||
@@ -48,163 +46,139 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "type is found: %s", _valuechar);
|
||||
_task = std::string(_valuechar);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (_task.compare("GitBranch") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_branch());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_branch());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("GitTag") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_version());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_version());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("GitRevision") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_revision());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_revision());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("BuildTime") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, build_time());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, build_time());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("FirmwareVersion") == 0)
|
||||
{
|
||||
string buf;
|
||||
if (std::string(GIT_TAG) == "") { // Tag not set, show branch
|
||||
buf = "Development-Branch: " + std::string(GIT_BRANCH);
|
||||
}
|
||||
else { // Tag is set, ignore branch
|
||||
buf = "Release: " + std::string(GIT_TAG);
|
||||
}
|
||||
buf = buf + " (Commit: " + std::string(GIT_REV) + ")";
|
||||
httpd_resp_sendstr_chunk(req, buf.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, getFwVersion().c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("HTMLVersion") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, getHTMLversion().c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, getHTMLversion().c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("Hostname") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string(hostname);
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("IP") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getIPAddress();
|
||||
httpd_resp_sendstr_chunk(req, zw->c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw->c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SSID") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getSSID();
|
||||
httpd_resp_sendstr_chunk(req, zw->c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw->c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("FlowStatus") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string("FlowStatus");
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("Round") == 0)
|
||||
{
|
||||
char formated[10] = "";
|
||||
snprintf(formated, sizeof(formated), "%d", getCountFlowRounds());
|
||||
httpd_resp_sendstr_chunk(req, formated);
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, formated);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardFreePartitionSpace") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardFreePartitionSpace();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionAllocationSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionAllocationSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardManufacturer") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardManufacturer();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardName") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardName();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardCapacity") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardCapacity();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardSectorSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardSectorSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t starttime_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_send(req, starttime.c_str(), strlen(starttime.c_str()));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
httpd_resp_send(req, starttime.c_str(), starttime.length());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -253,7 +227,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
message += "<br>Please check <a href=\"https://github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes\" target=_blank>github.com/jomjol/AI-on-the-edge-device/wiki/Error-Codes</a> for more information!";
|
||||
message += "<br>Please check <a href=\"https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes\" target=_blank>jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes</a> for more information!";
|
||||
message += "<br><br><button onclick=\"window.location.href='/reboot';\">Reboot</button>";
|
||||
message += " <button onclick=\"window.open('/ota_page.html');\">OTA Update</button>";
|
||||
message += " <button onclick=\"window.open('/log.html');\">Log Viewer</button>";
|
||||
@@ -296,6 +270,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t img_tmp_handler(httpd_req_t *req)
|
||||
{
|
||||
char filepath[50];
|
||||
@@ -320,11 +295,12 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start");
|
||||
#endif
|
||||
|
||||
char filepath[50];
|
||||
|
||||
@@ -340,33 +316,27 @@ esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
|
||||
filetosend = std::string(filename);
|
||||
ESP_LOGD(TAG, "File to upload: %s", filetosend.c_str());
|
||||
|
||||
// Serve raw.jpg
|
||||
if (filetosend == "raw.jpg")
|
||||
{
|
||||
return GetRawJPG(req);
|
||||
}
|
||||
|
||||
esp_err_t zw = GetJPG(filetosend, req);
|
||||
|
||||
if (zw == ESP_OK)
|
||||
// Serve alg.jpg, alg_roi.jpg or digital and analog ROIs
|
||||
if (ESP_OK == GetJPG(filetosend, req))
|
||||
return ESP_OK;
|
||||
|
||||
// File wird nicht intern bereit gestellt --> klassischer weg:
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done");
|
||||
#endif
|
||||
|
||||
// File was not served already --> serve with img_tmp_handler
|
||||
return img_tmp_handler(req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t sysinfo_handler(httpd_req_t *req)
|
||||
{
|
||||
const char* resp_str;
|
||||
std::string zw;
|
||||
std::string cputemp = std::to_string(temperatureRead());
|
||||
std::string cputemp = std::to_string((int)temperatureRead());
|
||||
std::string gitversion = libfive_git_version();
|
||||
std::string buildtime = build_time();
|
||||
std::string gitbranch = libfive_git_branch();
|
||||
@@ -374,38 +344,33 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
|
||||
std::string gitrevision = libfive_git_revision();
|
||||
std::string htmlversion = getHTMLversion();
|
||||
char freeheapmem[11];
|
||||
sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
|
||||
sprintf(freeheapmem, "%lu", (long) getESPHeapSize());
|
||||
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
|
||||
const char *hostname;
|
||||
ESP_ERROR_CHECK(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname));
|
||||
|
||||
zw = "[\
|
||||
{\
|
||||
\"firmware\" : \"" + gitversion + "\",\
|
||||
\"buildtime\" : \"" + buildtime + "\",\
|
||||
\"gitbranch\" : \"" + gitbranch + "\",\
|
||||
\"gittag\" : \"" + gittag + "\",\
|
||||
\"gitrevision\" : \"" + gitrevision + "\",\
|
||||
\"html\" : \"" + htmlversion + "\",\
|
||||
\"cputemp\" : \"" + cputemp + "\",\
|
||||
\"hostname\" : \"" + hostname + "\",\
|
||||
\"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\",\
|
||||
\"freeHeapMem\" : \"" + freeheapmem + "\"\
|
||||
}\
|
||||
]";
|
||||
|
||||
resp_str = zw.c_str();
|
||||
zw = string("[{") +
|
||||
"\"firmware\": \"" + gitversion + "\"," +
|
||||
"\"buildtime\": \"" + buildtime + "\"," +
|
||||
"\"gitbranch\": \"" + gitbranch + "\"," +
|
||||
"\"gittag\": \"" + gittag + "\"," +
|
||||
"\"gitrevision\": \"" + gitrevision + "\"," +
|
||||
"\"html\": \"" + htmlversion + "\"," +
|
||||
"\"cputemp\": \"" + cputemp + "\"," +
|
||||
"\"hostname\": \"" + hostname + "\"," +
|
||||
"\"IPv4\": \"" + ip4addr_ntoa(&ip_info.ip) + "\"," +
|
||||
"\"freeHeapMem\": \"" + freeheapmem + "\"" +
|
||||
"}]";
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
{
|
||||
httpd_uri_t info_get_handle = {
|
||||
@@ -432,7 +397,6 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
};
|
||||
httpd_register_uri_handler(server, &starttime_tmp_handle);
|
||||
|
||||
|
||||
httpd_uri_t img_tmp_handle = {
|
||||
.uri = "/img_tmp/*", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
@@ -441,7 +405,6 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
};
|
||||
httpd_register_uri_handler(server, &img_tmp_handle);
|
||||
|
||||
|
||||
httpd_uri_t main_rest_handle = {
|
||||
.uri = "/*", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
@@ -453,24 +416,23 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
}
|
||||
|
||||
|
||||
|
||||
httpd_handle_t start_webserver(void)
|
||||
{
|
||||
httpd_handle_t server = NULL;
|
||||
httpd_config_t config = { };
|
||||
|
||||
config.task_priority = tskIDLE_PRIORITY+3; //20221211: before: tskIDLE_PRIORITY+1; // 20210924 --> vorher +5
|
||||
config.stack_size = 32768; //20210921 --> vorher 32768 // bei 32k stürzt das Programm beim Bilderaufnehmen ab
|
||||
config.core_id = 0; //20221211 --> force all not flow related tasks to CPU0, before: tskNO_AFFINITY;
|
||||
config.server_port = 80;
|
||||
config.ctrl_port = 32768;
|
||||
config.max_open_sockets = 5; //20210921 --> vorher 7
|
||||
config.max_uri_handlers = 37; // vorher 24, 20220511: 35
|
||||
config.max_resp_headers = 8;
|
||||
config.backlog_conn = 5;
|
||||
config.lru_purge_enable = true; // dadurch werden alte Verbindungen gekappt, falls neue benögt werden.
|
||||
config.recv_wait_timeout = 5; // default: 5 20210924 --> vorher 30
|
||||
config.send_wait_timeout = 5; // default: 5 20210924 --> vorher 30
|
||||
config.task_priority = tskIDLE_PRIORITY+3; // previously -> 2022-12-11: tskIDLE_PRIORITY+1; 2021-09-24: tskIDLE_PRIORITY+5
|
||||
config.stack_size = 12288; // previously -> 2023-01-02: 32768
|
||||
config.core_id = 1; // previously -> 2023-01-02: 0, 2022-12-11: tskNO_AFFINITY;
|
||||
config.server_port = 80;
|
||||
config.ctrl_port = 32768;
|
||||
config.max_open_sockets = 5; //20210921 --> previously 7
|
||||
config.max_uri_handlers = 38; // previously 24, 20220511: 35, 20221220: 37, 2023-01-02:38
|
||||
config.max_resp_headers = 8;
|
||||
config.backlog_conn = 5;
|
||||
config.lru_purge_enable = true; // this cuts old connections if new ones are needed.
|
||||
config.recv_wait_timeout = 5; // default: 5 20210924 --> previously 30
|
||||
config.send_wait_timeout = 5; // default: 5 20210924 --> previously 30
|
||||
config.global_user_ctx = NULL;
|
||||
config.global_user_ctx_free_fn = NULL;
|
||||
config.global_transport_ctx = NULL;
|
||||
@@ -480,7 +442,7 @@ httpd_handle_t start_webserver(void)
|
||||
// config.uri_match_fn = NULL;
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
|
||||
starttime = gettimestring("%Y%m%d-%H%M%S");
|
||||
starttime = getCurrentTimeString("%Y%m%d-%H%M%S");
|
||||
|
||||
// Start the httpd server
|
||||
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
||||
@@ -494,6 +456,7 @@ httpd_handle_t start_webserver(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void stop_webserver(httpd_handle_t server)
|
||||
{
|
||||
httpd_stop(server);
|
||||
@@ -511,6 +474,7 @@ void disconnect_handler(void* arg, esp_event_base_t event_base,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void connect_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
|
||||
490
code/main/softAP.cpp
Normal file
490
code/main/softAP.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
#ifdef ENABLE_SOFTAP
|
||||
//if ENABLE_SOFTAP = disabled, set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n in sdkconfig.defaults to save 28k of flash
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
#include "softAP.h"
|
||||
|
||||
/* WiFi softAP Example
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "server_help.h"
|
||||
#include "defines.h"
|
||||
#include "Helper.h"
|
||||
#include "server_ota.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* The examples use WiFi configuration that you can set via project configuration menu.
|
||||
If you'd rather not, just change the below entries to strings with
|
||||
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
|
||||
*/
|
||||
|
||||
bool isConfigINI = false;
|
||||
bool isWlanINI = false;
|
||||
|
||||
static const char *TAG = "wifi softAP";
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_init_softAP(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_ap();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = { };
|
||||
|
||||
strcpy((char*)wifi_config.ap.ssid, (const char*) EXAMPLE_ESP_WIFI_SSID);
|
||||
strcpy((char*)wifi_config.ap.password, (const char*) EXAMPLE_ESP_WIFI_PASS);
|
||||
wifi_config.ap.channel = EXAMPLE_ESP_WIFI_CHANNEL;
|
||||
wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
|
||||
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
|
||||
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
|
||||
}
|
||||
|
||||
|
||||
void SendHTTPResponse(httpd_req_t *req)
|
||||
{
|
||||
std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
|
||||
message += "This mode is always startet if one of the following files is missing: /wlan.ini or the /config/config.ini.<p>";
|
||||
message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN acces information, 3. reboot (and connect to WLANs)<p><p>";
|
||||
message += "Please follow the below instructions.<p>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
isWlanINI = FileExists(WLAN_CONFIG_FILE);
|
||||
|
||||
if (!isConfigINI)
|
||||
{
|
||||
message = "<h3>1. Upload initial configuration to sd-card</h3><p>";
|
||||
message += "The configuration file config.ini is missing and most propably the full configuration and html folder on the sd-card. ";
|
||||
message += "This is normal after the first flashing of the firmware and an empty sd-card. Please upload \"remote_setup.zip\", which contains an full inital configuration.<p>";
|
||||
message += "<input id=\"newfile\" type=\"file\"><br>";
|
||||
message += "<button class=\"button\" style=\"width:300px\" id=\"doUpdate\" type=\"button\" onclick=\"upload()\">Upload File</button><p>";
|
||||
message += "The upload might take up to 60s. After a succesfull upload the page will be updated.";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
message = "<script language=\"JavaScript\">";
|
||||
message += "function upload() {";
|
||||
message += "var xhttp = new XMLHttpRequest();";
|
||||
message += "xhttp.onreadystatechange = function() {if (xhttp.readyState == 4) {if (xhttp.status == 200) {location.reload();}}};";
|
||||
message += "var filePath = document.getElementById(\"newfile\").value.split(/[\\\\/]/).pop();";
|
||||
message += "var file = document.getElementById(\"newfile\").files[0];";
|
||||
message += "if (!file.name.includes(\"remote-setup\")){if (!confirm(\"The zip file name should contain '...remote-setup...'. Are you sure that you have downloaded the correct file?\"))return;};";
|
||||
message += "var upload_path = \"/upload/firmware/\" + filePath; xhttp.open(\"POST\", upload_path, true); xhttp.send(file);document.reload();";
|
||||
message += "document.getElementById(\"doUpdate\").disabled = true;}";
|
||||
message += "</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
return;
|
||||
}
|
||||
if (!isWlanINI)
|
||||
{
|
||||
message = "<h3>2. WLAN access credentials</h3><p>";
|
||||
message += "<table>";
|
||||
message += "<tr><td>WLAN-SSID</td><td><input type=\"text\" name=\"ssid\" id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
|
||||
message += "<tr><td>WLAN-Password</td><td><input type=\"text\" name=\"password\" id=\"password\"></td><td>ATTENTION: the password will not be encrypted during the sending.</td><tr>";
|
||||
message += "</table><p>";
|
||||
message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reseted afterwards. If ssid or password is wrong, you need to take out the sd-card and manually change them in \"wlan.ini\"!<p>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
// message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
|
||||
// message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router</td>";
|
||||
// message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>RSSI Threashold</td><td><input type=\"number\" name=\"name\" id=\"threashold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threashold for RSSI value to check for start switching access point in a mesh system.Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
|
||||
// httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
|
||||
message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
|
||||
message += "<script language=\"JavaScript\">async function wr(){";
|
||||
message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
|
||||
// message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssi=\"+document.getElementById(\"threashold\").value;";
|
||||
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
message = "<h3>3. Reboot</h3><p>";
|
||||
message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
|
||||
message += "The first update and initialization process can take up to 3 minutes before you find it in the wlan. Error logs can be found on the console / serial logout.<p>Have fun!<p>";
|
||||
message += "<button class=\"button\" type=\"button\" onclick=\"rb()\")>Reboot to first setup.</button>";
|
||||
message += "<script language=\"JavaScript\">async function rb(){";
|
||||
message += "api = \"/reboot\";";
|
||||
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t test_handler(httpd_req_t *req)
|
||||
{
|
||||
SendHTTPResponse(req);
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t reboot_handlerAP(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Start");
|
||||
#endif
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doRebootOTA();
|
||||
return ESP_OK;
|
||||
};
|
||||
|
||||
|
||||
esp_err_t config_ini_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "config_ini_handler");
|
||||
char _query[400];
|
||||
char _valuechar[100];
|
||||
std::string fn = "/sdcard/firmware/";
|
||||
std::string _task = "";
|
||||
std::string ssid = "";
|
||||
std::string pwd = "";
|
||||
std::string hn = ""; // hostname
|
||||
std::string ip = "";
|
||||
std::string gw = ""; // gateway
|
||||
std::string nm = ""; // nm
|
||||
std::string dns = "";
|
||||
std::string rssi = "";
|
||||
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
|
||||
ssid = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "pwd", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "pwd is found: %s", _valuechar);
|
||||
pwd = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
|
||||
ssid = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "hn", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "hostname is found: %s", _valuechar);
|
||||
hn = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "ip", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ip is found: %s", _valuechar);
|
||||
ip = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "gw", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "gateway is found: %s", _valuechar);
|
||||
gw = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "nm", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "netmask is found: %s", _valuechar);
|
||||
nm = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "dns", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "dns is found: %s", _valuechar);
|
||||
dns = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "rssi", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "rssi is found: %s", _valuechar);
|
||||
rssi = std::string(_valuechar);
|
||||
}
|
||||
};
|
||||
|
||||
FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
|
||||
|
||||
if (ssid.length())
|
||||
ssid = "ssid = \"" + ssid + "\"\n";
|
||||
else
|
||||
ssid = ";ssid = \"\"\n";
|
||||
|
||||
fputs(ssid.c_str(), configfilehandle);
|
||||
|
||||
if (pwd.length())
|
||||
pwd = "password = \"" + pwd + "\"\n";
|
||||
else
|
||||
pwd = ";password = \"\"\n";
|
||||
fputs(pwd.c_str(), configfilehandle);
|
||||
|
||||
if (hn.length())
|
||||
hn = "hostname = \"" + hn + "\"\n";
|
||||
else
|
||||
hn = ";hostname = \"\"\n";
|
||||
fputs(hn.c_str(), configfilehandle);
|
||||
|
||||
if (ip.length())
|
||||
ip = "ip = \"" + ip + "\"\n";
|
||||
else
|
||||
ip = ";ip = \"\"\n";
|
||||
fputs(ip.c_str(), configfilehandle);
|
||||
|
||||
if (gw.length())
|
||||
gw = "gateway = \"" + gw + "\"\n";
|
||||
else
|
||||
gw = ";gateway = \"\"\n";
|
||||
fputs(gw.c_str(), configfilehandle);
|
||||
|
||||
if (nm.length())
|
||||
nm = "netmask = \"" + nm + "\"\n";
|
||||
else
|
||||
nm = ";netmask = \"\"\n";
|
||||
fputs(nm.c_str(), configfilehandle);
|
||||
|
||||
if (dns.length())
|
||||
dns = "dns = \"" + dns + "\"\n";
|
||||
else
|
||||
dns = ";dns = \"\"\n";
|
||||
fputs(dns.c_str(), configfilehandle);
|
||||
|
||||
if (rssi.length())
|
||||
rssi = "RSSIThreashold = \"" + rssi + "\"\n";
|
||||
else
|
||||
rssi = ";rssi = \"\"\n";
|
||||
fputs(rssi.c_str(), configfilehandle);
|
||||
|
||||
fflush(configfilehandle);
|
||||
fclose(configfilehandle);
|
||||
|
||||
std::string zw = "ota without parameter - should not be the case!";
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGE(TAG, "end config.ini");
|
||||
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
|
||||
|
||||
esp_err_t upload_post_handlerAP(httpd_req_t *req)
|
||||
{
|
||||
printf("Start des Post Handlers\n");
|
||||
MakeDir("/sdcard/config");
|
||||
MakeDir("/sdcard/firmware");
|
||||
MakeDir("/sdcard/html");
|
||||
MakeDir("/sdcard/img_tmp");
|
||||
MakeDir("/sdcard/log");
|
||||
MakeDir("/sdcard/demo");
|
||||
printf("Nach Start des Post Handlers\n");
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handlerAP");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, "/sdcard",
|
||||
req->uri + sizeof("/upload") - 1, sizeof(filepath));
|
||||
if (!filename) {
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
printf("filepath: %s, filename: %s\n", filepath, filename);
|
||||
|
||||
DeleteFile(std::string(filepath));
|
||||
|
||||
|
||||
|
||||
fd = fopen(filepath, "w");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to create file: %s", filepath);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Receiving file: %s...", filename);
|
||||
|
||||
char buf[1024];
|
||||
int received;
|
||||
|
||||
int remaining = req->content_len;
|
||||
|
||||
printf("remaining: %d\n", remaining);
|
||||
|
||||
|
||||
|
||||
while (remaining > 0) {
|
||||
|
||||
ESP_LOGI(TAG, "Remaining size: %d", remaining);
|
||||
if ((received = httpd_req_recv(req, buf, MIN(remaining, 1024))) <= 0) {
|
||||
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG, "File reception failed!");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (received && (received != fwrite(buf, 1, received, fd))) {
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG, "File write failed!");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
remaining -= received;
|
||||
}
|
||||
fclose(fd);
|
||||
isConfigINI = true;
|
||||
|
||||
FILE* pfile = fopen("/sdcard/update.txt", "w");
|
||||
std::string _s_zw= "/sdcard" + std::string(filename);
|
||||
fwrite(_s_zw.c_str(), strlen(_s_zw.c_str()), 1, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "File reception complete");
|
||||
httpd_resp_set_hdr(req, "Location", "/test");
|
||||
httpd_resp_set_status(req, "303 See Other");
|
||||
httpd_resp_set_hdr(req, "Location", "/test");
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGI(TAG, "Update page send out");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
httpd_handle_t start_webserverAP(void)
|
||||
{
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
httpd_handle_t server = NULL;
|
||||
if (httpd_start(&server, &config) == ESP_OK) {
|
||||
// Do something
|
||||
}
|
||||
|
||||
httpd_uri_t reboot_handle = {
|
||||
.uri = "/reboot", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = reboot_handlerAP,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &reboot_handle);
|
||||
|
||||
httpd_uri_t config_ini_handle = {
|
||||
.uri = "/config", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = config_ini_handler,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_ini_handle);
|
||||
|
||||
/* URI handler for uploading files to server */
|
||||
httpd_uri_t file_uploadAP = {
|
||||
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
|
||||
.method = HTTP_POST,
|
||||
.handler = upload_post_handlerAP,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_uploadAP);
|
||||
|
||||
httpd_uri_t test_uri = {
|
||||
.uri = "*",
|
||||
.method = HTTP_GET,
|
||||
.handler = test_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_register_uri_handler(server, &test_uri);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CheckStartAPMode()
|
||||
{
|
||||
isConfigINI = FileExists(CONFIG_FILE);
|
||||
isWlanINI = FileExists(WLAN_CONFIG_FILE);
|
||||
|
||||
if (!isConfigINI or !isWlanINI)
|
||||
{
|
||||
wifi_init_softAP();
|
||||
start_webserverAP();
|
||||
while(1) { // wait until reboot within task_do_Update_ZIP
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //#ifdef ENABLE_SOFTAP
|
||||
23
code/main/softAP.h
Normal file
23
code/main/softAP.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifdef ENABLE_SOFTAP
|
||||
|
||||
#ifndef SOFTAP_H
|
||||
#define SOFTAP_H
|
||||
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_event.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_system.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <sys/param.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_eth.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_tls_crypto.h"
|
||||
#include <esp_http_server.h>
|
||||
|
||||
void CheckStartAPMode();
|
||||
|
||||
#endif //SOFTAP_H
|
||||
|
||||
#endif //#ifdef ENABLE_SOFTAP
|
||||
@@ -15,6 +15,7 @@ extern "C"
|
||||
#include <string.h>
|
||||
#include "Helper.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
const char* build_time(void)
|
||||
@@ -38,6 +39,19 @@ const char* libfive_git_branch(void)
|
||||
}
|
||||
|
||||
|
||||
std::string getFwVersion(void) {
|
||||
std::string buf;
|
||||
if (std::string(GIT_TAG) == "") { // Tag not set, show branch
|
||||
buf = "Development-Branch: " + std::string(GIT_BRANCH);
|
||||
}
|
||||
else { // Tag is set, ignore branch
|
||||
buf = "Release: " + std::string(GIT_TAG);
|
||||
}
|
||||
buf = buf + " (Commit: " + std::string(GIT_REV) + ")";
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string getHTMLversion(void){
|
||||
char buf[100]="?\0";
|
||||
FILE* pFile;
|
||||
@@ -50,7 +64,10 @@ std::string getHTMLversion(void){
|
||||
fgets(buf, sizeof(buf), pFile); // Line 1: Version
|
||||
fclose(pFile);
|
||||
|
||||
return std::string(buf);
|
||||
string value = string(buf);
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); // Remove any newlines
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string getHTMLcommit(void){
|
||||
@@ -66,7 +83,10 @@ std::string getHTMLcommit(void){
|
||||
fgets(buf, sizeof(buf), pFile); // Line 2: Commit
|
||||
fclose(pFile);
|
||||
|
||||
return std::string(buf);
|
||||
string value = string(buf);
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); // Remove any newlines
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif // _VERSION_H
|
||||
@@ -8,45 +8,207 @@
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
|
||||
[platformio]
|
||||
src_dir = main
|
||||
src_dir = main
|
||||
default_envs = esp32cam
|
||||
|
||||
[common:idf]
|
||||
build_flags =
|
||||
-DUSE_ESP_IDF
|
||||
lib_deps =
|
||||
|
||||
[common:esp32-idf]
|
||||
extends = common:idf
|
||||
platform = platformio/espressif32 @ 5.2.0
|
||||
framework = espidf
|
||||
lib_deps =
|
||||
${common:idf.lib_deps}
|
||||
build_flags =
|
||||
${common:idf.build_flags}
|
||||
-Wno-nonnull-compare
|
||||
-DUSE_ESP32
|
||||
-DUSE_ESP32_FRAMEWORK_ESP_IDF
|
||||
|
||||
|
||||
[flags:runtime]
|
||||
build_flags =
|
||||
-Wno-nonnull-compare
|
||||
-Wno-sign-compare
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-unused-variable
|
||||
-fno-exceptions
|
||||
|
||||
[flags:clangtidy]
|
||||
build_flags =
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wunreachable-code
|
||||
;-Wshadow-compatible-local
|
||||
-fno-exceptions
|
||||
|
||||
; The main env - default
|
||||
[env:esp32cam]
|
||||
platform = espressif32@5.2.0
|
||||
extends = common:esp32-idf
|
||||
board = esp32cam
|
||||
;board = m5stack-core-esp32
|
||||
framework = espidf
|
||||
|
||||
;Add macro definition ENABLE_MQTT, ENABLE_INFLUXDB
|
||||
build_flags = -D ENABLE_MQTT -D ENABLE_INFLUXDB
|
||||
|
||||
;board_build.partitions = partitions_singleapp.csv
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:runtime.build_flags}
|
||||
; ### Sofware options : (can be set in defines.h)
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
-D ENABLE_SOFTAP
|
||||
board_build.partitions = partitions.csv
|
||||
|
||||
;lib_deps not needed
|
||||
;lib_deps =
|
||||
; jomjol_configfile
|
||||
; jomjol_helper
|
||||
; jomjol_wlan
|
||||
; jomjol_image_proc
|
||||
; jomjol_controlcamera
|
||||
; jomjol_flowcontroll
|
||||
; jomjol_tfliteclass
|
||||
; tflite-lib
|
||||
; jomjol_fileserver_ota
|
||||
; jomjol_time_sntp
|
||||
; jomjol_logfile
|
||||
; jomjol_mqtt
|
||||
; jomjol_influxdb
|
||||
; jomjol_controlGPIO
|
||||
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_rts = 0
|
||||
monitor_dtr = 0
|
||||
|
||||
debug_tool = esp-prog
|
||||
; full standalone dev mode
|
||||
; As sample, the board is nod32s instead of esp32cam (do not change nothing in fact :)
|
||||
; You can test newer platform_packages
|
||||
; or flash mode (board_build.flash_mode = qio)
|
||||
[env:esp32cam-dev]
|
||||
extends = common:esp32-idf
|
||||
board = esp32cam ; node32s
|
||||
;board_build.flash_mode = qio ;generate SPI_FAST_FLASH_BOOT boot loop
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Sofware options : (can be set in defines.h)
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
;-D ENABLE_SOFTAP
|
||||
; ### Debug options :
|
||||
;-D DEBUG_DETAIL_ON
|
||||
;-D DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
;-D DEBUG_ENABLE_SYSINFO
|
||||
;-D DEBUG_ENABLE_PERFMON
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;### test options
|
||||
-D CONFIG_ESP_TASK_WDT
|
||||
;-D CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
-D CONFIG_ESP_TASK_WDT_TIMEOUT_S ; fix for CONFIG_ESP_INT_WDT_TIMEOUT_MS
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
framework = espidf
|
||||
lib_ldf_mode = deep+
|
||||
platform = platformio/espressif32 @ 5.2.0
|
||||
platform_packages =
|
||||
;platformio/framework-espidf @ 3.40402.0 (4.4.2)
|
||||
;platformio/framework-espidf@^3.50000.0
|
||||
;platformio/tool-cmake @ 3.16.4
|
||||
;platformio/tool-cmake@^3.21.3
|
||||
;platformio/tool-esptoolpy @ 1.40201.0 (4.2.1)
|
||||
;platformio/tool-esptoolpy@^1.40400.0
|
||||
;platformio/tool-idf @ 1.0.1
|
||||
;platformio/tool-mconf @ 1.4060000.20190628 (406.0.0)
|
||||
;platformio/tool-ninja @ 1.9.0
|
||||
;platformio/tool-ninja @ 1.10.2
|
||||
;platformio/toolchain-esp32ulp @ 1.22851.191205 (2.28.51)
|
||||
;espressif/toolchain-esp32ulp @ 2.35.0-20220830
|
||||
;platformio/toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
|
||||
;platformio/toolchain-xtensa-esp32 @ 11.2.0+2022r1
|
||||
|
||||
; Enable and adapt for logging over USB
|
||||
;upload_port = /dev/ttyUSB0
|
||||
; platformio/espressif32 @ 5.3.0 dependencies :
|
||||
;platformio/framework-espidf @ 3.40403.0
|
||||
;platformio/tool-cmake @ 3.16.4
|
||||
;platformio/tool-esptoolpy@^1.40400.0
|
||||
;platformio/tool-idf @ 1.0.1
|
||||
;platformio/tool-mconf @ 1.4060000.20190628
|
||||
;platformio/tool-ninja @ 1.9.0
|
||||
;espressif/toolchain-esp32ulp @ 2.35.0-20220830
|
||||
;;;;espressif/toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
|
||||
board_build.partitions = partitions.csv
|
||||
monitor_speed = 115200
|
||||
monitor_rts = 0
|
||||
monitor_dtr = 0
|
||||
|
||||
|
||||
; Activate all debug mode
|
||||
; Cannot be used alone, but must be added at the end of extends = env:esp32cam-dev, esp32cam-debug
|
||||
;If multiple items specified in the extends field then only values from the latter one will be used in the final configuration
|
||||
;https://docs.platformio.org/en/stable/projectconf/section_env_advanced.html
|
||||
[env:esp32cam-debug] ; activate all debug
|
||||
;extends nothing, only apply sdkconfig.esp32-debug.defaults, enable debug options and clangtidy
|
||||
build_flags =
|
||||
; ### clangtidy build flags:
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Debug options :
|
||||
-D DEBUG_DETAIL_ON
|
||||
;-D DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
-D DEBUG_ENABLE_SYSINFO
|
||||
-D DEBUG_ENABLE_PERFMON
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
lib_ldf_mode = deep+
|
||||
|
||||
; Power management enabled
|
||||
;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/power_management.html
|
||||
;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-pm-enable
|
||||
[env:esp32cam-power-management]
|
||||
build_flags =
|
||||
-D TCONFIG_PM_ENABLE
|
||||
-D CONFIG_PM_DFS_INIT_AUTO
|
||||
-D CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
;-D FREERTOS_IDLE_TIME_BEFORE_SLEEP=3
|
||||
|
||||
;**********************
|
||||
; next section use modified version CMakeLists.txt of to use sdkconfig.<pioenv>.defaults + sdkconfig.defaults
|
||||
; https://github.com/platformio/platform-espressif32/issues/638
|
||||
|
||||
|
||||
; set board to rev3
|
||||
[env:esp32cam-board-rev3]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
|
||||
; set CPU frequency to 240 instead of 160 default
|
||||
[env:esp32cam-cpu-freq-240]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-board-rev3.defaults override some sdkconfig.defaults
|
||||
|
||||
; set board to rev3 + CPU frequency to 240
|
||||
; look at the extends : it takes esp32cam-dev and add env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , esp32cam-debug parameters
|
||||
[env:esp32cam-board-rev3-cpu-freq-240]
|
||||
extends = env:esp32cam-dev, env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , esp32cam-debug
|
||||
|
||||
; set board to rev3 + CPU frequency to 240 + power management
|
||||
[env:esp32cam-board-rev3-cpu-freq-240-pow]
|
||||
extends = env:esp32cam-dev, env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , env:esp32cam-power-management, esp32cam-debug
|
||||
|
||||
; Enable use of 8 MB PSRAM boards
|
||||
;https://github.com/espressif/esp-idf/blob/master/examples/system/himem/README.md
|
||||
[env:esp32cam-dev-himem]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-dev-himem.defaults override some sdkconfig.defaults
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
|
||||
; set options for task analysis (PR #1751)
|
||||
[env:esp32cam-dev-task-analysis]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-dev-task-analysis.defaults override some sdkconfig.defaults
|
||||
build_flags =
|
||||
;-D DEBUG_DETAIL_ON ; if esp32cam-debug not in extends
|
||||
-D TASK_ANALYSIS_ON
|
||||
;please use only one HEAP tracing at time.
|
||||
-D HEAP_TRACING_MAIN_WIFI
|
||||
;-D HEAP_TRACING_MAIN_START
|
||||
;-D HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
|
||||
|
||||
; Overwrite espcam build_flags to not include ENABLE_SOFTAP
|
||||
; Nor the -U ENABLE_SOFTAP nor -D ENABLE_SOFTAP=0 works to unset defines actually
|
||||
; Set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n in sdkconfig.esp32cam-no-softap.defaults to disable softap in the esp-idf compilation
|
||||
[env:esp32cam-no-softap] ;CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n saves 28k of flash
|
||||
extends = env:esp32cam
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Sofware options :
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
;-D ENABLE_SOFTAP ; disabled
|
||||
|
||||
@@ -1,16 +1,78 @@
|
||||
##################################################
|
||||
##################################################
|
||||
# Application specific configuration
|
||||
# Edit this file instead of sdkconfig.esp32cam!
|
||||
# After editting, make sure to explicitly delete
|
||||
# sdkconfig.esp32cam to apply your changes!
|
||||
##################################################
|
||||
|
||||
#if ENABLE_SOFTAP = disabled, set
|
||||
#CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
#to save 28k of flash
|
||||
|
||||
CONFIG_TASK_WDT=n
|
||||
CONFIG_TASK_WDT_CHECK_IDLE_TASK=n
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_DEFAULT=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
|
||||
###### safe optimizations
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
|
||||
#disable bootloader logging
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=0
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
||||
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=0
|
||||
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y
|
||||
#CONFIG_LOG_DEFAULT_LEVEL=0
|
||||
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
||||
CONFIG_LWIP_ESP_LWIP_ASSERT=n
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y
|
||||
CONFIG_OPTIMIZATION_ASSERTION_LEVEL=0
|
||||
# CONFIG_LOG_COLORS is not set
|
||||
|
||||
#set default loggin to
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=1
|
||||
|
||||
#disable lookup function
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
|
||||
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
|
||||
|
||||
#no panic message
|
||||
ESP_SYSTEM_PANIC_SILENT_REBOOT=y
|
||||
|
||||
#disable ADC calibration (needed for external sensors)
|
||||
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=n
|
||||
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=n
|
||||
CONFIG_ADC_CAL_LUT_ENABLE=needed
|
||||
|
||||
#disable IPV6
|
||||
CONFIG_LWIP_IPV6=n
|
||||
|
||||
#Newlib format
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
|
||||
|
||||
# ESP-NN
|
||||
#
|
||||
# CONFIG_NN_ANSI_C is not set
|
||||
CONFIG_NN_OPTIMIZED=y
|
||||
CONFIG_NN_OPTIMIZATIONS=1
|
||||
# end of ESP-NN
|
||||
|
||||
# ESP HTTP client
|
||||
#
|
||||
# CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS is not set
|
||||
|
||||
###### end safe optimizations
|
||||
|
||||
CONFIG_ESP32_REV_MIN_0=y
|
||||
|
||||
CONFIG_ESP32_DPORT_WORKAROUND=y
|
||||
@@ -69,4 +131,16 @@ CONFIG_OV5640_SUPPORT=n
|
||||
CONFIG_GC2145_SUPPORT=n
|
||||
CONFIG_GC032A_SUPPORT=n
|
||||
CONFIG_GC0308_SUPPORT=n
|
||||
CONFIG_BF3005_SUPPORT=n
|
||||
CONFIG_BF3005_SUPPORT=n
|
||||
|
||||
#only necessary for task analysis (include/defines -> TASK_ANALYSIS_ON)
|
||||
#set in [env:esp32cam-dev-task-analysis]
|
||||
#CONFIG_FREERTOS_USE_TRACE_FACILITY=1
|
||||
#CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
#CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
|
||||
#force disable HIMEM as not used in default config, can be enabled with [env:esp32cam-dev-himem]
|
||||
#free 256kb of internal memory :
|
||||
#I (2112) esp_himem: Initialized. Using last 8 32KB address blocks for bank switching on 4352 KB of physical memory.
|
||||
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
|
||||
#CONFIG_SPIRAM_BANKSWITCH_RESERVE is not set
|
||||
|
||||
7
code/sdkconfig.esp32cam-board-rev3.defaults
Normal file
7
code/sdkconfig.esp32cam-board-rev3.defaults
Normal file
@@ -0,0 +1,7 @@
|
||||
CONFIG_ESP32_REV_MIN_0=n
|
||||
|
||||
ESP32_REV_MIN_3=y
|
||||
CONFIG_ESP32_REV_MIN_3=y
|
||||
|
||||
#https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-spiram-cache-workaround
|
||||
CONFIG_ESP32_DPORT_WORKAROUND=n
|
||||
4
code/sdkconfig.esp32cam-cpu-freq-240.defaults
Normal file
4
code/sdkconfig.esp32cam-cpu-freq-240.defaults
Normal file
@@ -0,0 +1,4 @@
|
||||
CONFIG_FREERTOS_UNICORE=n
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
33
code/sdkconfig.esp32cam-debug.defaults
Normal file
33
code/sdkconfig.esp32cam-debug.defaults
Normal file
@@ -0,0 +1,33 @@
|
||||
#enable bootloader logging
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=n
|
||||
CONFIG_FREERTOS_ASSERT_DISABLE=yn
|
||||
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=n
|
||||
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y
|
||||
#CONFIG_LOG_DEFAULT_LEVEL=0
|
||||
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
||||
CONFIG_LWIP_ESP_LWIP_ASSERT=n
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=n
|
||||
CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2
|
||||
# CONFIG_LOG_COLORS is not set
|
||||
|
||||
#set default loggin to
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||
|
||||
#disable lookup function
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
|
||||
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
|
||||
|
||||
#no panic message
|
||||
ESP_SYSTEM_PANIC_SILENT_REBOOT=n
|
||||
|
||||
#disable ADC calibration (needed for external sensors)
|
||||
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y
|
||||
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y
|
||||
CONFIG_ADC_CAL_LUT_ENABLE=needed
|
||||
34
code/sdkconfig.esp32cam-dev-himem.defaults
Normal file
34
code/sdkconfig.esp32cam-dev-himem.defaults
Normal file
@@ -0,0 +1,34 @@
|
||||
#### https://github.com/espressif/esp-idf/blob/master/examples/system/himem/sdkconfig.defaults
|
||||
CONFIG_SPIRAM=y
|
||||
CONFIG_SPIRAM_SUPPORT=y
|
||||
CONFIG_SPIRAM_BOOT_INIT=y
|
||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=n
|
||||
CONFIG_SPIRAM_USE_MALLOC=y
|
||||
CONFIG_SPIRAM_TYPE_AUTO=y
|
||||
CONFIG_SPIRAM_SIZE=-1
|
||||
CONFIG_SPIRAM_SPEED_40M=y
|
||||
CONFIG_SPIRAM_MEMTEST=y
|
||||
CONFIG_SPIRAM_CACHE_WORKAROUND=y
|
||||
CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
|
||||
|
||||
/* some references for testing
|
||||
|
||||
# https://github.com/platformio/platform-espressif32/issues/185
|
||||
|
||||
#define CONFIG_SPIRAM_SUPPORT 1
|
||||
#define CONFIG_PICO_PSRAM_CS_IO 10
|
||||
#define CONFIG_ESP32_SPIRAM_SUPPORT 1
|
||||
#define CONFIG_SPIRAM_BOOT_INIT 1
|
||||
#define CONFIG_SPIRAM_IGNORE_NOTFOUND 0
|
||||
#define CONFIG_SPIRAM_TYPE_AUTO 1
|
||||
#define CONFIG_SPIRAM_SIZE -1
|
||||
#define CONFIG_SPIRAM_USE_MEMMAP 1
|
||||
#define CONFIG_SPIRAM_SPEED_40M 1
|
||||
#define SPIRAM_USE_MALLOC 1
|
||||
#define CONFIG_SPIRAM_CACHE_WORKAROUND 1
|
||||
#define CONFIG_SPIRAM_BANKSWITCH_ENABLE 1
|
||||
#define CONFIG_SPIRAM_BANKSWITCH_RESERVE 8
|
||||
*/
|
||||
18
code/sdkconfig.esp32cam-dev-task-analysis.defaults
Normal file
18
code/sdkconfig.esp32cam-dev-task-analysis.defaults
Normal file
@@ -0,0 +1,18 @@
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=1
|
||||
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
|
||||
CONFIG_HEAP_TRACING_STANDALONE=y
|
||||
CONFIG_HEAP_POISONING_LIGHT=y
|
||||
CONFIG_HEAP_TASK_TRACKING=y
|
||||
|
||||
|
||||
# General options for additional checks
|
||||
CONFIG_HEAP_POISONING_COMPREHENSIVE=y
|
||||
CONFIG_COMPILER_WARN_WRITE_STRINGS=y
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
|
||||
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
|
||||
CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y
|
||||
CONFIG_COMPILER_STACK_CHECK=y
|
||||
|
||||
CONFIG_ESP_TASK_WDT=n
|
||||
36
code/sdkconfig.esp32cam-dev.defaults
Normal file
36
code/sdkconfig.esp32cam-dev.defaults
Normal file
@@ -0,0 +1,36 @@
|
||||
### nothing actually
|
||||
|
||||
|
||||
/* #disabled
|
||||
|
||||
#### recommended optimizations to test
|
||||
#https://docs.espressif.com/projects/esp-at/en/latest/esp32/Compile_and_Develop/How_to_optimize_throughput.html
|
||||
|
||||
# System
|
||||
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
|
||||
CONFIG_FREERTOS_UNICORE=n
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
#CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
#CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
#CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
||||
#CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
|
||||
|
||||
# LWIP
|
||||
CONFIG_LWIP_TCP_SND_BUF_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_WND_DEFAULT=65534
|
||||
CONFIG_LWIP_TCP_RECVMBOX_SIZE=12
|
||||
CONFIG_LWIP_UDP_RECVMBOX_SIZE=12
|
||||
CONFIG_LWIP_TCPIP_RECVMBOX_SIZE=64
|
||||
|
||||
# Wi-Fi
|
||||
#CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=16
|
||||
#CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=64
|
||||
#CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=64
|
||||
#CONFIG_ESP32_WIFI_TX_BA_WIN=32
|
||||
#CONFIG_ESP32_WIFI_RX_BA_WIN=32
|
||||
#CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
|
||||
#CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
|
||||
|
||||
## end of recommended optimizations
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <unity.h>
|
||||
#include <ClassFlowCNNGeneral.h>
|
||||
|
||||
class UnderTestCNNGeneral : public ClassFlowCNNGeneral {
|
||||
public:
|
||||
UnderTestCNNGeneral( ClassFlowAlignment *_flowalign, t_CNNType _cnntype) :
|
||||
ClassFlowCNNGeneral(_flowalign, _cnntype) {};
|
||||
|
||||
using ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Transition = x.8 - x.2 here no transition in the test cases.
|
||||
* Offset = dig=x.n, ana= n.y: no offset, because both "n" are the same
|
||||
*/
|
||||
void test_analogToDigit_Standard() {
|
||||
|
||||
UnderTestCNNGeneral* undertest = new UnderTestCNNGeneral(nullptr, Digital100);
|
||||
|
||||
// 4.8 is a "hanging" 5, i.e. it has not jumped over to 5.0.
|
||||
// A "hanging digit" should still be rounded from Transition.
|
||||
// Transition = yes
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(5, undertest->PointerEvalAnalogToDigitNew(4.8, 8.0, 8, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issue-1344032217
|
||||
// Default: dig=9.6, ana=6.8 => erg=9
|
||||
// Transition = no
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(9, undertest->PointerEvalAnalogToDigitNew( 9.6, 6.8, 6, 9.2));
|
||||
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1220365920
|
||||
// Default: dig=4.6, ana=6.2 => erg=4
|
||||
// Transition = no
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(4, undertest->PointerEvalAnalogToDigitNew( 4.6, 6.2, 6, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
|
||||
// Hanging digit ()
|
||||
// Default: dig=6.8, ana=8.6 => erg=7
|
||||
// Transition = no
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(7, undertest->PointerEvalAnalogToDigitNew( 6.8, 8.6, 6, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
|
||||
// Also hanging digit () with small pointer after 0 pass.
|
||||
// Default: dig=6.8, ana=1.0 => erg=7
|
||||
// Transition = no
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(7, undertest->PointerEvalAnalogToDigitNew( 6.8, 1.0, 1, 9.2));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void test_analogToDigit_Transition() {
|
||||
UnderTestCNNGeneral* undertest = new UnderTestCNNGeneral(nullptr, Digital100);
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1222672175
|
||||
// Default: dig=3.9, ana=9.7 => erg=3
|
||||
// Transition = yes
|
||||
// Zero crossing = no
|
||||
// Offset = no
|
||||
TEST_ASSERT_EQUAL_INT(3, undertest->PointerEvalAnalogToDigitNew( 3.9, 9.7, 9, 9.2));
|
||||
|
||||
// without reference
|
||||
// Default: dig=4.0, ana=9.1 => erg=4
|
||||
// Transition = yes
|
||||
// Zero crossing = no
|
||||
// Offset = no
|
||||
// Special feature: Digit has not yet started at analogue 9.1
|
||||
TEST_ASSERT_EQUAL_INT(4, undertest->PointerEvalAnalogToDigitNew( 4.0, 9.1, 9, 9.2));
|
||||
|
||||
// without reference
|
||||
// Default: dig=9.8, ana=0.1, ana_2=9.9 => erg=9
|
||||
// transition = yes
|
||||
// Zero crossing = no
|
||||
// Offset = no
|
||||
// Special feature: analogue is set back to 9 by previous analogue
|
||||
TEST_ASSERT_EQUAL_INT(9, undertest->PointerEvalAnalogToDigitNew( 9.8, 0.1, 9, 9.2));
|
||||
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1277425333
|
||||
// Default: dig=5.9, ana=9.4 => erg=9
|
||||
// Transition = yes
|
||||
// Zero crossing = no
|
||||
// Offset = no
|
||||
// Special feature:
|
||||
TEST_ASSERT_EQUAL_INT(5, undertest->PointerEvalAnalogToDigitNew( 5.9, 9.4, 9, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1282168030
|
||||
// Default: dig=1.8, ana=7.8 => erg=9
|
||||
// Transition = yes
|
||||
// Zero crossing = no
|
||||
// Offset = no
|
||||
// Special feature: Digit runs with analogue. Therefore 1.8 (vs. 7.8)
|
||||
TEST_ASSERT_EQUAL_INT(1, undertest->PointerEvalAnalogToDigitNew( 1.8, 7.8, 7, 7.7));
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user