Compare commits

..

189 Commits

Author SHA1 Message Date
CaCO3
9ab4e806bd added and activated espressif mDNS service (#3499)
Co-authored-by: Frank <f.sck@web.de>
2025-01-15 22:28:08 +01:00
jomjol
6e474441f6 Create License-DRAFT.md 2025-01-05 20:06:09 +01:00
jomjol
bf2a2f553f Create dig-class11_1910_s2_q.tflite 2025-01-05 19:53:25 +01:00
jomjol
21ab5cb203 additional tflite v0810 2025-01-05 19:20:48 +01:00
SybexX
1af1796ee0 Update ClassControllCamera.cpp
.jpeg_quality = 6 can cause problems with some cameras
2025-01-04 13:30:25 +01:00
michael
095cf984c4 remove_soc_temperature_for_s3_support 2025-01-03 18:36:11 +01:00
michael
b72d809e59 fix_soc_sdmmc_and_add_soc_temperature_for_s3_support 2025-01-02 16:39:26 +01:00
SybexX
c6a593ba0d fix for incorrect decimal shift? (#3446)
* Update ClassFlowCNNGeneral.cpp

* Update ClassFlowCNNGeneral.cpp

* Update ClassFlowCNNGeneral.cpp

* Update ClassFlowCNNGeneral.cpp

* Update code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp

* Update code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp

* Update code/components/jomjol_flowcontroll/ClassFlowCNNGeneral.cpp

* Update ClassFlowCNNGeneral.cpp

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-12-31 12:01:02 +01:00
jomjol
c68463359b Update tflite 2024-12-27 16:52:03 +01:00
CaCO3
a1c2145e77 Update Changelog.md 2024-12-25 20:53:25 +01:00
CaCO3
2986c6122d Add Web Interface and REST auth (#3436)
* Ported https://github.com/jomjol/AI-on-the-edge-device/pull/2241 to latest main and extended it for all REST APIs

* .

* fix compile errors

* .

* .

* Update Changelog.md

* Update Changelog.md

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: michael <Heinrich-Tuning@web.de>
2024-12-25 20:49:47 +01:00
CaCO3
a348a51f14 Update NUMBER.ChangeRateThreshold.md 2024-12-25 10:27:47 +01:00
CaCO3
26ca15e18a fix crash fue to empty CAM parameters in migration (#3450)
Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-12-22 22:12:49 +01:00
CaCO3
f4dccc1d52 Update Interval.md 2024-12-05 23:21:01 +01:00
CaCO3
a07c2cf46d Update AutoStart.md 2024-12-05 23:20:30 +01:00
CaCO3
2f39d9bdd4 Update Interval.md 2024-12-05 23:14:02 +01:00
CaCO3
7836323fbc Prepare RC5 (#3422)
* Update Changelog.md

* Update Changelog.md

* Update Changelog.md

* Update Changelog.md
2024-12-05 01:05:38 +01:00
CaCO3
708fd68cf5 Remove Autostart parameter and make the flow to be always enabled (#3423)
* removed Autostart parameter and make it enabled by default

* .

* show menu entry in UI

* cleanup migration

* .

* .

* .

* .

* .

* .

* .

* .
2024-12-05 01:04:24 +01:00
github-actions[bot]
1b5ff2ef1a docs(contributor): contrib-readme-action has updated readme 2024-12-04 22:40:54 +00:00
CaCO3
1701aaed42 Update README.md (#3421) 2024-12-04 23:40:24 +01:00
CaCO3
c07e5a740a Add files via upload 2024-12-04 23:36:29 +01:00
SURYANSH RAI
3868cf98f6 Better Footer with social links #3311 (#3361)
* Added footer

* Update README.md

* Update index.html

* Update index.html

* Add files via upload

* Delete images/mail.jpg

* Update README.md

* Update sd-card/html/index.html

* Update docs/index.html

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-12-04 23:33:58 +01:00
CaCO3
179005f4ce Extend Homeassistant discovery with button for flow start (#3415)
* feat(homeassistant discovery): Add button for flow start

* Update

* Update

* Allow Flow Start MQTT topic to have a zero-length payload

* remove unused payload

---------

Co-authored-by: Slider0007 <jobbelle@gmx.net>
2024-12-04 23:17:06 +01:00
SybexX
50ada0a5a8 fix (#3418) 2024-12-04 22:57:43 +01:00
SybexX
be7146c886 fix (#3417) 2024-12-03 21:12:19 +01:00
CaCO3
8f89a396f8 typo 2024-12-02 23:03:48 +01:00
SybexX
9e84d28ee9 overview_add_date_and_time (#3398)
* overview_add_date_and_time

* Update overview.html

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-12-02 00:26:54 +01:00
CaCO3
3f4aaf303f Revert ec00e94
See https://github.com/jomjol/AI-on-the-edge-device/issues/3305#issuecomment-2510295853
2024-12-02 00:14:52 +01:00
gneluka
08baf1824c Add support for Domoticz MQTT integration (#3359)
* initial changes to add domoticz support

* error correction

* further changes

* further changes

* Refactoring

* further refactoring

* further refactoring

* Update DomoticzTopicIn.md

* Update NUMBER.DomoticzIDX.md

* Update DomoticzTopicIn.md

* Update NUMBER.DomoticzIDX.md

* Update config.ini

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update DomoticzTopicIn.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-12-02 00:07:02 +01:00
SybexX
2c7740ec16 Update CTfLiteClass.cpp (#3397) 2024-11-21 22:01:57 +01:00
SybexX
3ee32d8cf0 Merge pull request #3393 from tkopczuk/patch-1
Fix 'AnalogToDigitTransitionStart' always using 9.2 regardless of the configured value.
2024-11-20 03:33:23 +01:00
Tomek Kopczuk
25ae0465d8 Fix 'AnalogToDigitTransitionStart' always using 9.2 regardless of the configured value.
After the recent parameter rename we're trying to compare the toUpper version of the config parameter against "AnalogToDigitTransitionStart" - which will always fail - hence always using the default value of 9.2.
2024-11-19 23:14:24 +01:00
CaCO3
14e9d6a9cc renamed issue templates 2024-11-15 17:45:40 +01:00
CaCO3
94c2de1c2a Rename blank.yaml to x_blank.yaml 2024-11-15 17:27:48 +01:00
CaCO3
541e9841c2 Rename x_plain.yaml to blank.yaml 2024-11-15 17:27:23 +01:00
jomjol
fc3c70c63a Update dig-cont tlite to v712
Minor errata in quantization
2024-11-01 18:23:17 +01:00
github-actions[bot]
bfde8316ce docs(contributor): contrib-readme-action has updated readme 2024-10-19 08:36:57 +00:00
Bilal Mirza
fe0fec7fac Allow to Add a Move to Top button to enhance the ease of navigation for README readers. (#3344)
* Allow to Add a Move to Top button to enhance the ease of navigation for README readers.

* totally top of readme

* .

* Update README.md

* Update README.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-10-19 10:36:19 +02:00
jomjol
56abefe3df Update esp-nn and tflite to newest version (#3346)
* Pulled down update esp-nn

* Pulled tflite to master

* Update from main
2024-10-18 21:48:59 +02:00
CaCO3
43f15fcba3 Fix HA menu entry (#3342)
* Fix HA menu entry

* Update index.html

* Update index.html

* Update index.html

* Update index.html

* Update index.html
2024-10-18 10:45:05 +02:00
Bilal Mirza
dadf18f5c9 Fix: Broken Links i.e 404 page not found #3335 (#3336)
* Fix: Broken Links

* Update README.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-10-14 22:07:14 +02:00
CaCO3
c448ece680 Update the Homeasistant Discovery topics (#3332)
Update the Homeassistant Discovery topics
2024-10-13 23:04:28 +02:00
CaCO3
07d6eca456 Update README.md 2024-10-13 16:12:24 +02:00
CaCO3
4083d35b61 Update README.md 2024-10-13 15:55:30 +02:00
CaCO3
2319f8d302 Update README.md 2024-10-13 14:51:24 +02:00
Ranjana761
224e4380a8 Add batches to README.md (#3330)
* Update README.md

* Update README.md
2024-10-13 12:00:24 +02:00
jomjol
14d0c88a28 Update dig-cont_0711_s3_q.tflite
Error corrected version ov 0710 (adjusted quantization)
2024-10-13 10:13:06 +02:00
Farookh Zaheer Siddiqui
3c9b2c46c8 Update FeatureRequest.md (#3328) 2024-10-09 21:29:12 +02:00
jomjol
0752694600 Return vo v0700 2024-10-09 21:28:58 +02:00
github-actions[bot]
cf0ed268dd docs(contributor): contrib-readme-action has updated readme 2024-10-08 22:14:26 +00:00
CaCO3
f1979a142e Manual update of contributors list (#3325)
* Create manually-update-contributors-list

* Update and rename manually-update-contributors-list to manual-update-contributors-li.yamlst

* Update build.yaml

* Rename manual-update-contributors-li.yamlst to manual-update-contributors-li.yaml

* Rename manual-update-contributors-li.yaml to manual-update-contributors-list.yaml

* Update README.md
2024-10-09 00:13:43 +02:00
Austin Drenski
2a4f0f4a2d Update softAP.cpp (#3324) 2024-10-08 23:34:25 +02:00
KrishCode
45269bf45b Fixed docs README.md (#3323)
* Fixed docs README.md

I improved the file and enhanced its readability

* Update README.md

* Update README.md

* Update README.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-10-08 23:33:14 +02:00
Naman Tyagi
57db60fee4 fix: corrected grammatical and typographical errors in changelog (#3321) 2024-10-07 21:40:11 +02:00
Naman Tyagi
e1c49f39f0 Update README.md (#3322) 2024-10-07 21:39:09 +02:00
jomjol
7bebae3776 Clean up of old tflite files 2024-10-07 19:52:18 +02:00
CaCO3
0a4560ea95 Update Changelog.md 2024-10-07 00:21:07 +02:00
CaCO3
b44db21714 Update esp32-camera submodule to v2.0.13 (#3316)
Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-10-07 00:20:38 +02:00
CaCO3
34796ed091 Update build.yaml 2024-10-07 00:19:47 +02:00
CaCO3
a46dfd1c23 Add demo files (#3315)
* updated changelog

* add demo files

* Update build.yaml

* Update build.yaml

* Update build.yaml

* added missing files

* .

* .

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-10-07 00:06:03 +02:00
CaCO3
32eb583036 Add contributor list (#3317)
* feat: #3310 Automatically Update Contributor List  (#3312)

* Create main.yml

* Update README.md

* docs(contributor): contrib-readme-action has updated readme

* Update main.yml

* docs(contributor): contrib-readme-action has updated readme

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>

* Update build.yaml

* docs(contributor): contrib-readme-action has updated readme

* Delete .github/workflows/main.yml

* Update README.md

* docs(contributor): contrib-readme-action has updated readme

* Update README.md

* docs(contributor): contrib-readme-action has updated readme

* Update build.yaml

* Update README.md

---------

Co-authored-by: Ayush Jhawar <111112495+Ayushjhawar8@users.noreply.github.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2024-10-06 23:25:19 +02:00
michael
6ee83b8413 Update ClassControllCamera.cpp (#3313)
https://github.com/jomjol/AI-on-the-edge-device/issues/3300#issuecomment-2395561022
2024-10-06 22:42:27 +02:00
CaCO3
f034232f36 Update config.ini 2024-10-06 22:33:24 +02:00
CaCO3
b80e43dfe9 Update config.ini 2024-10-06 22:31:56 +02:00
CaCO3
40c7c253ea Update config.ini 2024-10-06 22:29:06 +02:00
CaCO3
d11b312a96 Typos (#3309)
* Update edit_reference.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_reference.html
2024-10-06 16:57:26 +02:00
Naman Tyagi
2c1e531ed2 Fix grammar and typos in README.md for clarity and consistency (#3308) 2024-10-06 16:53:16 +02:00
CaCO3
c352e539bc Update build.yaml 2024-10-05 23:15:38 +02:00
CaCO3
a0333d906f use lower case for MQTT topic rate_per_digitization_round 2024-10-05 22:32:50 +02:00
CaCO3
ec00e943da Allow earlier start for AnalogToDigitTransitionStart 2024-10-05 22:26:26 +02:00
CaCO3
6175471a00 typo 2024-10-05 22:20:24 +02:00
CaCO3
948e76876f revert TFlite submodule update as certain modules crash with it, see #3269 (2nd attempt) 2024-10-05 22:18:37 +02:00
CaCO3
f4edb206d8 Master (#3297)
* fix pipeline (#3294)

* Create dig-cont_0640_s3_q.tflite

* Update edit_reference.html (#2924)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist

* Update edit_config_template.html (#2925)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen

* The parameter "negative" is processed on the MCU

* Renamed menu entry Alignment -> References

* renamed model file to make naming consistent

* Fix test (#2933)

* always reset change absolute (#2956)

* Create dig-class11_1701_s2.tflite

* Update tflite

* Update tflite

* Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Fix minor typo and harmonize spaces (#3030)

* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>

* Source code formatting, ClassFlowPostProcessing.cpp

* fix edit_config_template.html

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix readconfigparam.js

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix edit_config_template.html

TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.

* Update info.html

function loadWLANSSID() was present three times

* Update overview.html

CamFrameSize is no longer needed/used for zoom

* Update reply-bot.yaml

* homeassistant service discovery: derive node_id when using nested topics (#3088)

* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery

* add Prometheus/OpenMetrics exporter (#3081)

* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Typo

* update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)

* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Update reply-bot.yaml (#3107)

* Fix actions-label-commenter

* Update Helper.cpp

* Update Helper.h

* Update Helper.cpp

* Update readconfigparam.js

fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!

* proposal for renaming and documentation (#3115)

* Update server_camera.cpp

 Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowAlignment.cpp

* Fix building with `-D DEBUG_DETAIL_ON` (#3160)

Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Handle empty prevalue.ini gracefully (#3162)

Fixes #2149.

* Bugfix for boot loop (#3175)

* Add files via upload

* Add files via upload

* Add files via upload

* Delete param-docs/parameter-pages/TakeImage/Aec2.md

has been replaced by CamAec2.md

* Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md

has been replaced by CamAeLevel.md

* Delete param-docs/parameter-pages/TakeImage/Brightness.md

has been replaced by CamBrightness.md

* Delete param-docs/parameter-pages/TakeImage/Contrast.md

has been replaced by CamContrast.md

* Delete param-docs/parameter-pages/TakeImage/Grayscale.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Negative.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Saturation.md

has been replaced by CamSaturation.md

* Delete param-docs/parameter-pages/TakeImage/Sharpness.md

has been replaced by CamSharpness.md

* Delete param-docs/parameter-pages/TakeImage/ImageQuality.md

has been replaced by CamQuality.md

* Delete param-docs/parameter-pages/TakeImage/Zoom.md

has been replaced by CamZoom.md

* Delete param-docs/parameter-pages/TakeImage/ZoomMode.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md

has been replaced by CamZoomOffsetX.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md

has been replaced by CamZoomOffsetY.md

* Delete param-docs/parameter-pages/TakeImage/ImageSize.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/FixedExposure.md

has been replaced by CamAec.md

* Delete param-docs/parameter-pages/Alignment/FlipImageSize.md

has been replaced by CamVflip.md

* Delete param-docs/parameter-pages/Alignment/InitialMirror.md

has been replaced by CamHmirror.md

* CamParameter documentation update

https://github.com/jomjol/AI-on-the-edge-device/issues/3185

* typo

* add Webhook #3148 (#3163)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Bugfix for time stamp (#3180)

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp

* Update readconfigcommon.js

fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".

* fix svg favicon 

The svg one got added in 33893eb566 but does not work on Firefox

* Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)

* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: michael <Heinrich-Tuning@web.de>

* Update MainFlowControl.cpp

* Add support for OV5640 camera (#3063)

* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors

* Update MainFlowControl.cpp

* Add rate threshold parameter (#3195)

* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Update main.cpp

* Update config.ini

Adjusted camera settings to make the image brighter.

* Update readconfigparam.js

Adjusted camera settings to make the image brighter.

* add optional ImageUpload for Webhook (#3174)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Add files via upload (#3207)

* Update ClassFlowPostProcessing.cpp

deleted some unnecessary double entries
RateType renamed to MaxRateType

* Update ClassFlowDefineTypes.h

RateType renamed to MaxRateType

* Update text on recognition page

* Update digital CNN

* add a Delay between the WiFi reconnections (#3068)

* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log

* cleanup

* cleanup

* cleanup

* Update edit_alignment.html

* cleanup

* cleanup

* Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)

* Handle crash on corrupted model (#3220)

* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* new dig-class100-173-s2-q on 23.800 images (#3257)

* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.

* moved number edit box styles into new file edit_style.css (#3262)

changed input[type=number] from 60px to 3em, to show 3 digits with current font size.

* added note about only TLS 1.2 is supported (#3213)

* Renamed digital to digit (#3219)

* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Update Changelog.md

* Update Changelog.md

* Prepare next release (#3267) (#3270)

* Create dig-cont_0640_s3_q.tflite

* Update edit_reference.html (#2924)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist

* Update edit_config_template.html (#2925)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen

* The parameter "negative" is processed on the MCU

* Renamed menu entry Alignment -> References

* renamed model file to make naming consistent

* Fix test (#2933)

* always reset change absolute (#2956)

* Create dig-class11_1701_s2.tflite

* Update tflite

* Update tflite

* Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Fix minor typo and harmonize spaces (#3030)

* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------



* Source code formatting, ClassFlowPostProcessing.cpp

* fix edit_config_template.html

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix readconfigparam.js

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix edit_config_template.html

TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.

* Update info.html

function loadWLANSSID() was present three times

* Update overview.html

CamFrameSize is no longer needed/used for zoom

* Update reply-bot.yaml

* homeassistant service discovery: derive node_id when using nested topics (#3088)

* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery

* add Prometheus/OpenMetrics exporter (#3081)

* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------



* Typo

* update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)

* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------



* Update reply-bot.yaml (#3107)

* Fix actions-label-commenter

* Update Helper.cpp

* Update Helper.h

* Update Helper.cpp

* Update readconfigparam.js

fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!

* proposal for renaming and documentation (#3115)

* Update server_camera.cpp

 Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowAlignment.cpp

* Fix building with `-D DEBUG_DETAIL_ON` (#3160)

Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.



* Handle empty prevalue.ini gracefully (#3162)

Fixes #2149.

* Bugfix for boot loop (#3175)

* Add files via upload

* Add files via upload

* Add files via upload

* Delete param-docs/parameter-pages/TakeImage/Aec2.md

has been replaced by CamAec2.md

* Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md

has been replaced by CamAeLevel.md

* Delete param-docs/parameter-pages/TakeImage/Brightness.md

has been replaced by CamBrightness.md

* Delete param-docs/parameter-pages/TakeImage/Contrast.md

has been replaced by CamContrast.md

* Delete param-docs/parameter-pages/TakeImage/Grayscale.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Negative.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Saturation.md

has been replaced by CamSaturation.md

* Delete param-docs/parameter-pages/TakeImage/Sharpness.md

has been replaced by CamSharpness.md

* Delete param-docs/parameter-pages/TakeImage/ImageQuality.md

has been replaced by CamQuality.md

* Delete param-docs/parameter-pages/TakeImage/Zoom.md

has been replaced by CamZoom.md

* Delete param-docs/parameter-pages/TakeImage/ZoomMode.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md

has been replaced by CamZoomOffsetX.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md

has been replaced by CamZoomOffsetY.md

* Delete param-docs/parameter-pages/TakeImage/ImageSize.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/FixedExposure.md

has been replaced by CamAec.md

* Delete param-docs/parameter-pages/Alignment/FlipImageSize.md

has been replaced by CamVflip.md

* Delete param-docs/parameter-pages/Alignment/InitialMirror.md

has been replaced by CamHmirror.md

* CamParameter documentation update

https://github.com/jomjol/AI-on-the-edge-device/issues/3185

* typo

* add Webhook #3148 (#3163)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------



* Bugfix for time stamp (#3180)

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp

* Update readconfigcommon.js

fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".

* fix svg favicon 

The svg one got added in 33893eb566 but does not work on Firefox

* Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)

* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------




* Update MainFlowControl.cpp

* Add support for OV5640 camera (#3063)

* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors

* Update MainFlowControl.cpp

* Add rate threshold parameter (#3195)

* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------



* Update main.cpp

* Update config.ini

Adjusted camera settings to make the image brighter.

* Update readconfigparam.js

Adjusted camera settings to make the image brighter.

* add optional ImageUpload for Webhook (#3174)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------



* Add files via upload (#3207)

* Update ClassFlowPostProcessing.cpp

deleted some unnecessary double entries
RateType renamed to MaxRateType

* Update ClassFlowDefineTypes.h

RateType renamed to MaxRateType

* Update text on recognition page

* Update digital CNN

* add a Delay between the WiFi reconnections (#3068)

* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log

* cleanup

* cleanup

* cleanup

* Update edit_alignment.html

* cleanup

* cleanup

* Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)

* Handle crash on corrupted model (#3220)

* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------



* new dig-class100-173-s2-q on 23.800 images (#3257)

* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.

* moved number edit box styles into new file edit_style.css (#3262)

changed input[type=number] from 60px to 3em, to show 3 digits with current font size.

* added note about only TLS 1.2 is supported (#3213)

* Renamed digital to digit (#3219)

* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------



* Update Changelog.md

* Update Changelog.md

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>

* revert TFlite submodule update as certain modules crash with it, see https://github.com/jomjol/AI-on-the-edge-device/issues/3269

* Rename NUMBER.AnalogDigitTransitionStart.md to NUMBER.AnalogToDigitTransitionStart.md

* Update NUMBER.AnalogToDigitTransitionStart.md

* Update edit_config_template.html

* changed the webhook UploadImg to false

* changed the webhook UploadImg to false (#3279)

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Show boolean option in settings page (#3285)

* changed the webhook UploadImg to false

* show boolean value on boolean drop down boxes

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* changed default value from boolean to numeric value in parameter camDenoise documentation

* Update edit_explain_7.html

https://github.com/jomjol/AI-on-the-edge-device/issues/3284?notification_referrer_id=NT_kwDOAAj1wbIxMjY3MDI1Njk3MDo1ODcyMDE#issuecomment-2387102786

* docs: update README.md (#3290)

prefered -> preferred

* rename/remove unused parameters (#3291)

* migrate-cam-parameters (#3288)

* Update main.cpp

* remove commented out code

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Update Changelog.md

* cleanup

* Skip release jobs on non-release changes

* Update build.yaml

* Update build.yaml

* Update build.yaml

* Update build.yaml

* Update build.yaml

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>
Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>

* update pipeline (#3296)

* Create dig-cont_0640_s3_q.tflite

* Update edit_reference.html (#2924)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist

* Update edit_config_template.html (#2925)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen

* The parameter "negative" is processed on the MCU

* Renamed menu entry Alignment -> References

* renamed model file to make naming consistent

* Fix test (#2933)

* always reset change absolute (#2956)

* Create dig-class11_1701_s2.tflite

* Update tflite

* Update tflite

* Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Fix minor typo and harmonize spaces (#3030)

* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>

* Source code formatting, ClassFlowPostProcessing.cpp

* fix edit_config_template.html

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix readconfigparam.js

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix edit_config_template.html

TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.

* Update info.html

function loadWLANSSID() was present three times

* Update overview.html

CamFrameSize is no longer needed/used for zoom

* Update reply-bot.yaml

* homeassistant service discovery: derive node_id when using nested topics (#3088)

* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery

* add Prometheus/OpenMetrics exporter (#3081)

* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Typo

* update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)

* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Update reply-bot.yaml (#3107)

* Fix actions-label-commenter

* Update Helper.cpp

* Update Helper.h

* Update Helper.cpp

* Update readconfigparam.js

fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!

* proposal for renaming and documentation (#3115)

* Update server_camera.cpp

 Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowAlignment.cpp

* Fix building with `-D DEBUG_DETAIL_ON` (#3160)

Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Handle empty prevalue.ini gracefully (#3162)

Fixes #2149.

* Bugfix for boot loop (#3175)

* Add files via upload

* Add files via upload

* Add files via upload

* Delete param-docs/parameter-pages/TakeImage/Aec2.md

has been replaced by CamAec2.md

* Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md

has been replaced by CamAeLevel.md

* Delete param-docs/parameter-pages/TakeImage/Brightness.md

has been replaced by CamBrightness.md

* Delete param-docs/parameter-pages/TakeImage/Contrast.md

has been replaced by CamContrast.md

* Delete param-docs/parameter-pages/TakeImage/Grayscale.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Negative.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Saturation.md

has been replaced by CamSaturation.md

* Delete param-docs/parameter-pages/TakeImage/Sharpness.md

has been replaced by CamSharpness.md

* Delete param-docs/parameter-pages/TakeImage/ImageQuality.md

has been replaced by CamQuality.md

* Delete param-docs/parameter-pages/TakeImage/Zoom.md

has been replaced by CamZoom.md

* Delete param-docs/parameter-pages/TakeImage/ZoomMode.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md

has been replaced by CamZoomOffsetX.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md

has been replaced by CamZoomOffsetY.md

* Delete param-docs/parameter-pages/TakeImage/ImageSize.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/FixedExposure.md

has been replaced by CamAec.md

* Delete param-docs/parameter-pages/Alignment/FlipImageSize.md

has been replaced by CamVflip.md

* Delete param-docs/parameter-pages/Alignment/InitialMirror.md

has been replaced by CamHmirror.md

* CamParameter documentation update

https://github.com/jomjol/AI-on-the-edge-device/issues/3185

* typo

* add Webhook #3148 (#3163)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Bugfix for time stamp (#3180)

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp

* Update readconfigcommon.js

fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".

* fix svg favicon 

The svg one got added in 33893eb566 but does not work on Firefox

* Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)

* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: michael <Heinrich-Tuning@web.de>

* Update MainFlowControl.cpp

* Add support for OV5640 camera (#3063)

* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors

* Update MainFlowControl.cpp

* Add rate threshold parameter (#3195)

* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Update main.cpp

* Update config.ini

Adjusted camera settings to make the image brighter.

* Update readconfigparam.js

Adjusted camera settings to make the image brighter.

* add optional ImageUpload for Webhook (#3174)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Add files via upload (#3207)

* Update ClassFlowPostProcessing.cpp

deleted some unnecessary double entries
RateType renamed to MaxRateType

* Update ClassFlowDefineTypes.h

RateType renamed to MaxRateType

* Update text on recognition page

* Update digital CNN

* add a Delay between the WiFi reconnections (#3068)

* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log

* cleanup

* cleanup

* cleanup

* Update edit_alignment.html

* cleanup

* cleanup

* Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)

* Handle crash on corrupted model (#3220)

* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* new dig-class100-173-s2-q on 23.800 images (#3257)

* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.

* moved number edit box styles into new file edit_style.css (#3262)

changed input[type=number] from 60px to 3em, to show 3 digits with current font size.

* added note about only TLS 1.2 is supported (#3213)

* Renamed digital to digit (#3219)

* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Update Changelog.md

* Update Changelog.md

* Prepare next release (#3267) (#3270)

* Create dig-cont_0640_s3_q.tflite

* Update edit_reference.html (#2924)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist

* Update edit_config_template.html (#2925)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen

* The parameter "negative" is processed on the MCU

* Renamed menu entry Alignment -> References

* renamed model file to make naming consistent

* Fix test (#2933)

* always reset change absolute (#2956)

* Create dig-class11_1701_s2.tflite

* Update tflite

* Update tflite

* Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Fix minor typo and harmonize spaces (#3030)

* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------



* Source code formatting, ClassFlowPostProcessing.cpp

* fix edit_config_template.html

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix readconfigparam.js

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix edit_config_template.html

TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.

* Update info.html

function loadWLANSSID() was present three times

* Update overview.html

CamFrameSize is no longer needed/used for zoom

* Update reply-bot.yaml

* homeassistant service discovery: derive node_id when using nested topics (#3088)

* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery

* add Prometheus/OpenMetrics exporter (#3081)

* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------



* Typo

* update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)

* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------



* Update reply-bot.yaml (#3107)

* Fix actions-label-commenter

* Update Helper.cpp

* Update Helper.h

* Update Helper.cpp

* Update readconfigparam.js

fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!

* proposal for renaming and documentation (#3115)

* Update server_camera.cpp

 Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowAlignment.cpp

* Fix building with `-D DEBUG_DETAIL_ON` (#3160)

Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.



* Handle empty prevalue.ini gracefully (#3162)

Fixes #2149.

* Bugfix for boot loop (#3175)

* Add files via upload

* Add files via upload

* Add files via upload

* Delete param-docs/parameter-pages/TakeImage/Aec2.md

has been replaced by CamAec2.md

* Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md

has been replaced by CamAeLevel.md

* Delete param-docs/parameter-pages/TakeImage/Brightness.md

has been replaced by CamBrightness.md

* Delete param-docs/parameter-pages/TakeImage/Contrast.md

has been replaced by CamContrast.md

* Delete param-docs/parameter-pages/TakeImage/Grayscale.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Negative.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Saturation.md

has been replaced by CamSaturation.md

* Delete param-docs/parameter-pages/TakeImage/Sharpness.md

has been replaced by CamSharpness.md

* Delete param-docs/parameter-pages/TakeImage/ImageQuality.md

has been replaced by CamQuality.md

* Delete param-docs/parameter-pages/TakeImage/Zoom.md

has been replaced by CamZoom.md

* Delete param-docs/parameter-pages/TakeImage/ZoomMode.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md

has been replaced by CamZoomOffsetX.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md

has been replaced by CamZoomOffsetY.md

* Delete param-docs/parameter-pages/TakeImage/ImageSize.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/FixedExposure.md

has been replaced by CamAec.md

* Delete param-docs/parameter-pages/Alignment/FlipImageSize.md

has been replaced by CamVflip.md

* Delete param-docs/parameter-pages/Alignment/InitialMirror.md

has been replaced by CamHmirror.md

* CamParameter documentation update

https://github.com/jomjol/AI-on-the-edge-device/issues/3185

* typo

* add Webhook #3148 (#3163)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------



* Bugfix for time stamp (#3180)

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp

* Update readconfigcommon.js

fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".

* fix svg favicon 

The svg one got added in 33893eb566 but does not work on Firefox

* Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)

* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------




* Update MainFlowControl.cpp

* Add support for OV5640 camera (#3063)

* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors

* Update MainFlowControl.cpp

* Add rate threshold parameter (#3195)

* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------



* Update main.cpp

* Update config.ini

Adjusted camera settings to make the image brighter.

* Update readconfigparam.js

Adjusted camera settings to make the image brighter.

* add optional ImageUpload for Webhook (#3174)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------



* Add files via upload (#3207)

* Update ClassFlowPostProcessing.cpp

deleted some unnecessary double entries
RateType renamed to MaxRateType

* Update ClassFlowDefineTypes.h

RateType renamed to MaxRateType

* Update text on recognition page

* Update digital CNN

* add a Delay between the WiFi reconnections (#3068)

* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log

* cleanup

* cleanup

* cleanup

* Update edit_alignment.html

* cleanup

* cleanup

* Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)

* Handle crash on corrupted model (#3220)

* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------



* new dig-class100-173-s2-q on 23.800 images (#3257)

* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.

* moved number edit box styles into new file edit_style.css (#3262)

changed input[type=number] from 60px to 3em, to show 3 digits with current font size.

* added note about only TLS 1.2 is supported (#3213)

* Renamed digital to digit (#3219)

* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------



* Update Changelog.md

* Update Changelog.md

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>

* revert TFlite submodule update as certain modules crash with it, see https://github.com/jomjol/AI-on-the-edge-device/issues/3269

* Rename NUMBER.AnalogDigitTransitionStart.md to NUMBER.AnalogToDigitTransitionStart.md

* Update NUMBER.AnalogToDigitTransitionStart.md

* Update edit_config_template.html

* changed the webhook UploadImg to false

* changed the webhook UploadImg to false (#3279)

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* Show boolean option in settings page (#3285)

* changed the webhook UploadImg to false

* show boolean value on boolean drop down boxes

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>

* changed default value from boolean to numeric value in parameter camDenoise documentation

* Update edit_explain_7.html

https://github.com/jomjol/AI-on-the-edge-device/issues/3284?notification_referrer_id=NT_kwDOAAj1wbIxMjY3MDI1Njk3MDo1ODcyMDE#issuecomment-2387102786

* docs: update README.md (#3290)

prefered -> preferred

* rename/remove unused parameters (#3291)

* migrate-cam-parameters (#3288)

* Update main.cpp

* remove commented out code

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>

* Update Changelog.md

* cleanup

* Skip release jobs on non-release changes

* Update build.yaml

* Update build.yaml

* Update build.yaml

* Update build.yaml

* Update build.yaml

* fix pipeline

* Update build.yaml

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>
Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>
Co-authored-by: Ikko Eltociear Ashimine <eltociear@gmail.com>
2024-10-04 23:25:59 +02:00
CaCO3
a9db769595 Update build.yaml 2024-10-04 23:19:24 +02:00
CaCO3
f0497eb924 fix pipeline 2024-10-04 23:07:36 +02:00
CaCO3
e53af6de0d Merge branch 'master' into rolling 2024-10-04 23:06:44 +02:00
CaCO3
3b7fe93d02 Update build.yaml 2024-10-04 23:05:46 +02:00
CaCO3
2a7247abfe Update build.yaml 2024-10-04 22:55:07 +02:00
CaCO3
37ba85717f Update build.yaml 2024-10-04 22:54:11 +02:00
CaCO3
97656114b6 Update build.yaml 2024-10-04 22:36:58 +02:00
CaCO3
6cf1d5ad98 Update build.yaml 2024-10-04 22:22:53 +02:00
CaCO3
fed729bcee Skip release jobs on non-release changes 2024-10-04 22:20:38 +02:00
CaCO3
bb69929247 cleanup 2024-10-04 22:03:41 +02:00
CaCO3
e1ea09c501 Merge branch 'master' into rolling 2024-10-04 22:00:28 +02:00
CaCO3
39a827258d Update Changelog.md 2024-10-04 21:55:45 +02:00
michael
1d8c6fa257 migrate-cam-parameters (#3288)
* Update main.cpp

* remove commented out code

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-10-04 21:43:06 +02:00
CaCO3
a9aadbdb06 rename/remove unused parameters (#3291) 2024-10-04 21:31:57 +02:00
Ikko Eltociear Ashimine
a5927f98d2 docs: update README.md (#3290)
prefered -> preferred
2024-10-04 21:14:47 +02:00
michael
c708e2374a Update edit_explain_7.html
https://github.com/jomjol/AI-on-the-edge-device/issues/3284?notification_referrer_id=NT_kwDOAAj1wbIxMjY3MDI1Njk3MDo1ODcyMDE#issuecomment-2387102786
2024-10-02 01:43:50 +02:00
CaCO3
4c3dcd8c29 changed default value from boolean to numeric value in parameter camDenoise documentation 2024-10-02 00:43:32 +02:00
CaCO3
be93567956 Merge branch 'rolling' of https://github.com/jomjol/AI-on-the-edge-device into rolling 2024-10-02 00:40:35 +02:00
CaCO3
d4406f47ea Show boolean option in settings page (#3285)
* changed the webhook UploadImg to false

* show boolean value on boolean drop down boxes

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-10-02 00:38:59 +02:00
CaCO3
52efedcfa0 Merge branch 'rolling' of https://github.com/jomjol/AI-on-the-edge-device into rolling 2024-10-01 18:52:19 +02:00
CaCO3
28d93253f0 changed the webhook UploadImg to false (#3279)
Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-09-30 21:16:22 +02:00
CaCO3
c7fdc46df2 changed the webhook UploadImg to false 2024-09-30 21:08:48 +02:00
CaCO3
74491e9bde Update edit_config_template.html 2024-09-30 20:50:20 +02:00
CaCO3
a092142c65 Update NUMBER.AnalogToDigitTransitionStart.md 2024-09-30 20:46:29 +02:00
CaCO3
f6a3dc5851 Rename NUMBER.AnalogDigitTransitionStart.md to NUMBER.AnalogToDigitTransitionStart.md 2024-09-30 20:40:02 +02:00
CaCO3
d027adf006 revert TFlite submodule update as certain modules crash with it, see https://github.com/jomjol/AI-on-the-edge-device/issues/3269 2024-09-30 19:48:49 +02:00
CaCO3
bd5be5c5ec Prepare next release (#3267) (#3270)
* Create dig-cont_0640_s3_q.tflite

* Update edit_reference.html (#2924)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist

* Update edit_config_template.html (#2925)

Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen

* The parameter "negative" is processed on the MCU

* Renamed menu entry Alignment -> References

* renamed model file to make naming consistent

* Fix test (#2933)

* always reset change absolute (#2956)

* Create dig-class11_1701_s2.tflite

* Update tflite

* Update tflite

* Camera settings (#3029)

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Fix minor typo and harmonize spaces (#3030)

* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------



* Source code formatting, ClassFlowPostProcessing.cpp

* fix edit_config_template.html

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix readconfigparam.js

Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^

* fix edit_config_template.html

TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.

* Update info.html

function loadWLANSSID() was present three times

* Update overview.html

CamFrameSize is no longer needed/used for zoom

* Update reply-bot.yaml

* homeassistant service discovery: derive node_id when using nested topics (#3088)

* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery

* add Prometheus/OpenMetrics exporter (#3081)

* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------



* Typo

* update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)

* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------



* Update reply-bot.yaml (#3107)

* Fix actions-label-commenter

* Update Helper.cpp

* Update Helper.h

* Update Helper.cpp

* Update readconfigparam.js

fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!

* proposal for renaming and documentation (#3115)

* Update server_camera.cpp

 Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowAlignment.cpp

* Fix building with `-D DEBUG_DETAIL_ON` (#3160)

Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.



* Handle empty prevalue.ini gracefully (#3162)

Fixes #2149.

* Bugfix for boot loop (#3175)

* Add files via upload

* Add files via upload

* Add files via upload

* Delete param-docs/parameter-pages/TakeImage/Aec2.md

has been replaced by CamAec2.md

* Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md

has been replaced by CamAeLevel.md

* Delete param-docs/parameter-pages/TakeImage/Brightness.md

has been replaced by CamBrightness.md

* Delete param-docs/parameter-pages/TakeImage/Contrast.md

has been replaced by CamContrast.md

* Delete param-docs/parameter-pages/TakeImage/Grayscale.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Negative.md

has been replaced by CamSpecialEffect.md

* Delete param-docs/parameter-pages/TakeImage/Saturation.md

has been replaced by CamSaturation.md

* Delete param-docs/parameter-pages/TakeImage/Sharpness.md

has been replaced by CamSharpness.md

* Delete param-docs/parameter-pages/TakeImage/ImageQuality.md

has been replaced by CamQuality.md

* Delete param-docs/parameter-pages/TakeImage/Zoom.md

has been replaced by CamZoom.md

* Delete param-docs/parameter-pages/TakeImage/ZoomMode.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md

has been replaced by CamZoomOffsetX.md

* Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md

has been replaced by CamZoomOffsetY.md

* Delete param-docs/parameter-pages/TakeImage/ImageSize.md

has been replaced by CamZoomSize.md

* Delete param-docs/parameter-pages/TakeImage/FixedExposure.md

has been replaced by CamAec.md

* Delete param-docs/parameter-pages/Alignment/FlipImageSize.md

has been replaced by CamVflip.md

* Delete param-docs/parameter-pages/Alignment/InitialMirror.md

has been replaced by CamHmirror.md

* CamParameter documentation update

https://github.com/jomjol/AI-on-the-edge-device/issues/3185

* typo

* add Webhook #3148 (#3163)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------



* Bugfix for time stamp (#3180)

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp

* Update readconfigcommon.js

fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".

* fix svg favicon 

The svg one got added in 33893eb566 but does not work on Firefox

* Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)

* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------




* Update MainFlowControl.cpp

* Add support for OV5640 camera (#3063)

* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors

* Update MainFlowControl.cpp

* Add rate threshold parameter (#3195)

* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------



* Update main.cpp

* Update config.ini

Adjusted camera settings to make the image brighter.

* Update readconfigparam.js

Adjusted camera settings to make the image brighter.

* add optional ImageUpload for Webhook (#3174)

* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------



* Add files via upload (#3207)

* Update ClassFlowPostProcessing.cpp

deleted some unnecessary double entries
RateType renamed to MaxRateType

* Update ClassFlowDefineTypes.h

RateType renamed to MaxRateType

* Update text on recognition page

* Update digital CNN

* add a Delay between the WiFi reconnections (#3068)

* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log

* cleanup

* cleanup

* cleanup

* Update edit_alignment.html

* cleanup

* cleanup

* Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)

* Handle crash on corrupted model (#3220)

* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------



* new dig-class100-173-s2-q on 23.800 images (#3257)

* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.

* moved number edit box styles into new file edit_style.css (#3262)

changed input[type=number] from 60px to 3em, to show 3 digits with current font size.

* added note about only TLS 1.2 is supported (#3213)

* Renamed digital to digit (#3219)

* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------



* Update Changelog.md

* Update Changelog.md

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
Co-authored-by: michael <Heinrich-Tuning@web.de>
Co-authored-by: Frank Haverland <fspapaping@googlemail.com>
Co-authored-by: kub3let <95883234+kub3let@users.noreply.github.com>
Co-authored-by: Marco H <myxor@users.noreply.github.com>
Co-authored-by: Henry Thasler <henrythasler@users.noreply.github.com>
Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: Sebastian Lövdahl <slovdahl@hibox.fi>
Co-authored-by: Raphael Hehl <raphael@rhehl.de>
Co-authored-by: jasaw <jasaw@dius.com.au>
Co-authored-by: Francesco Carnielli <hex7c0@gmail.com>
Co-authored-by: kalwados <kalwados@gmx.de>
2024-09-29 23:22:55 +02:00
CaCO3
3b3a3ebcc9 Update Changelog.md 2024-09-29 23:20:15 +02:00
CaCO3
7d62cf67fe Update Changelog.md 2024-09-29 23:00:30 +02:00
CaCO3
f6bdd48bca Renamed digital to digit (#3219)
* renamed Digital to Digit

* added param migration

* Update .github/label-commenter-config.yaml

* renamed AnalogDigitTransition* to AnalogToDigitTransition*

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-09-29 22:10:10 +02:00
CaCO3
5496573369 added note about only TLS 1.2 is supported (#3213) 2024-09-29 22:01:38 +02:00
kalwados
4522ba087f moved number edit box styles into new file edit_style.css (#3262)
changed input[type=number] from 60px to 3em, to show 3 digits with current font size.
2024-09-29 21:08:45 +02:00
Frank Haverland
d370ba5fe6 new dig-class100-173-s2-q on 23.800 images (#3257)
* new dig-class100-173-s2-q on 23.800 images

* platformio/espressif32 @ 6.8.1 for esp32cam-dev

* Revert "platformio/espressif32 @ 6.8.1 for esp32cam-dev"

This reverts commit cc9297d483.

* not using platformio 6.1.16

* Revert "not using platformio 6.1.16"

This reverts commit ef18e4fae7.
2024-09-28 15:40:24 +02:00
CaCO3
f39dacc1c5 Handle crash on corrupted model (#3220)
* Upgrade esp-tflite-micro to 1.3.1

* Added log message to hint in case it crashes on loading a corrupted model

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-09-28 15:29:15 +02:00
michael
aad1a0e78d Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1) 2024-09-26 21:22:22 +02:00
michael
276efef783 cleanup 2024-09-26 17:34:12 +02:00
michael
79476a8458 cleanup 2024-09-26 16:29:31 +02:00
michael
2b7da5b44e Update edit_alignment.html 2024-09-26 14:41:25 +02:00
michael
ebcec97d1d cleanup 2024-09-24 03:12:27 +02:00
michael
85375b6505 cleanup 2024-09-24 02:53:36 +02:00
michael
085c47b651 cleanup 2024-09-23 15:44:30 +02:00
Francesco Carnielli
20a04b888f add a Delay between the WiFi reconnections (#3068)
* add a Delay between the WiFi reconnections

* log the delay between the WiFi reconnections

move the delay after the log
2024-09-22 21:50:38 +02:00
jomjol
098b1bd025 Update digital CNN 2024-09-17 20:47:13 +02:00
CaCO3
d1c815ce69 Update text on recognition page 2024-09-03 23:10:15 +02:00
michael
67c3020d7d Update ClassFlowDefineTypes.h
RateType renamed to MaxRateType
2024-09-01 16:36:51 +02:00
michael
61bca4ebb8 Update ClassFlowPostProcessing.cpp
deleted some unnecessary double entries
RateType renamed to MaxRateType
2024-09-01 16:36:40 +02:00
michael
3219202c53 Add files via upload (#3207) 2024-09-01 08:34:29 +02:00
Raphael Hehl
cd29690b96 add optional ImageUpload for Webhook (#3174)
* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: add img upload

* webhoop added config for imgupload

* webhook html fixes

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

* add checkbox for Webhook_UploadImg

* Update sd-card/html/edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* Update edit_config_template.html

* added a long timestamp to both webhook requests

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-09-01 08:33:46 +02:00
michael
3a34564ee2 Update readconfigparam.js
Adjusted camera settings to make the image brighter.
2024-08-31 16:09:29 +02:00
michael
174743ae7f Update config.ini
Adjusted camera settings to make the image brighter.
2024-08-31 16:08:48 +02:00
michael
e5eca6a53f Update main.cpp 2024-08-31 15:33:06 +02:00
michael
d8e37dce48 Add rate threshold parameter (#3195)
* still needs to be tested

https://github.com/jomjol/AI-on-the-edge-device/issues/3143

* Update ClassFlowPostProcessing.cpp

code formatting

* Update ClassFlowDefineTypes.h

code formatting

* Update ClassFlowPostProcessing.h

code formatting

* Update edit_config_template.html

* fix

* Update config.ini

* Update edit_config_template.html

* Updated param doc

* Rename parameters

* Update edit_config_template.html

* Update NUMBER.ChangeRateThreshold.md

* Update NUMBER.ChangeRateThreshold.md

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-08-30 19:29:57 +02:00
michael
822753bb4f Update MainFlowControl.cpp 2024-08-30 00:18:35 +02:00
jasaw
7225792b4b Add support for OV5640 camera (#3063)
* Add support for OV5640 camera

* clean up sharpness handling

* limit sharpness range to -2 and +2

* refactor

* Fix OV3660 sharpness handling

* refactor sharpness handling

* fix OV3660 zoom mode

* reinstate aspect ratio via imageSize

* Changed OV5640 full frame size to match datasheet

* various fixes

* add denoise config and general clean up

* fix line endings to LF

* Support enabling red blue swap via web interface

* update jpeg quality limits

* remove color swap config; color swap workaround dependent on vflip

* fix missing commit

* fix gain ceiling

* Update cam vflip param page

* fix typo: camdenoise, not camsdenoise

* fix compile errors
2024-08-29 21:57:26 +02:00
michael
b4f6b1a4fb Update MainFlowControl.cpp 2024-08-29 18:45:35 +02:00
CaCO3
21ec58daa0 Update platformIO to 6.8.1 (Contains ESP IDF 5.3) (#3196)
* Update platformIO to 6.8.1 (ESP IDF 5.3)

* removed now redundant typedef

* updated IDF manifest hash

* Add files via upload

so it should work now

* Update server_main.cpp

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
Co-authored-by: michael <Heinrich-Tuning@web.de>
2024-08-28 22:26:44 +02:00
CaCO3
2c69e90fac fix svg favicon
The svg one got added in 33893eb566 but does not work on Firefox
2024-08-27 21:01:56 +02:00
michael
5c57522b71 Update readconfigcommon.js
fix for: The same message("Image Contrast got enhanced") came up with "Update Marker" and "Enhance Image Contrast".
2024-08-27 16:56:23 +02:00
michael
f8eb4db171 Bugfix for time stamp (#3180)
* Update ClassFlowPostProcessing.cpp

* Update ClassFlowDefineTypes.h

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update ClassFlowPostProcessing.cpp

* Update interface_webhook.cpp
2024-08-24 13:19:21 +02:00
Raphael Hehl
c9a3df4eec add Webhook #3148 (#3163)
* WIP add Webhook

* fix config html for webhook
add tooltips for webhook

* webhook: fix not enabling webhook

* send webhook as json

* Update ApiKey.md

* webhook: fix only sending last "Number"

* webhook JSON is now closer to the data log in CSV format

* webhook: drop timeStampTimeUTC and switch from timeStamp to lastvalue like lokal csv to fix no timestamp on error

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-08-24 00:05:16 +02:00
CaCO3
acf669900f typo 2024-08-20 23:00:24 +02:00
michael
cb3f082218 CamParameter documentation update
https://github.com/jomjol/AI-on-the-edge-device/issues/3185
2024-08-19 00:42:33 +02:00
michael
20980b2bcd Delete param-docs/parameter-pages/Alignment/InitialMirror.md
has been replaced by CamHmirror.md
2024-08-18 04:39:21 +02:00
michael
773d21a875 Delete param-docs/parameter-pages/Alignment/FlipImageSize.md
has been replaced by CamVflip.md
2024-08-18 04:38:07 +02:00
michael
3a9c9ac2a4 Delete param-docs/parameter-pages/TakeImage/FixedExposure.md
has been replaced by CamAec.md
2024-08-18 04:36:01 +02:00
michael
c7e340d3a5 Delete param-docs/parameter-pages/TakeImage/ImageSize.md
has been replaced by CamZoomSize.md
2024-08-18 04:29:11 +02:00
michael
0441753a33 Delete param-docs/parameter-pages/TakeImage/ZoomOffsetY.md
has been replaced by CamZoomOffsetY.md
2024-08-18 04:27:18 +02:00
michael
fb6cb44728 Delete param-docs/parameter-pages/TakeImage/ZoomOffsetX.md
has been replaced by CamZoomOffsetX.md
2024-08-18 04:26:32 +02:00
michael
ae69942dd9 Delete param-docs/parameter-pages/TakeImage/ZoomMode.md
has been replaced by CamZoomSize.md
2024-08-18 04:25:47 +02:00
michael
65437727f7 Delete param-docs/parameter-pages/TakeImage/Zoom.md
has been replaced by CamZoom.md
2024-08-18 04:24:42 +02:00
michael
ccefe57795 Delete param-docs/parameter-pages/TakeImage/ImageQuality.md
has been replaced by CamQuality.md
2024-08-18 04:22:49 +02:00
michael
e3ff049720 Delete param-docs/parameter-pages/TakeImage/Sharpness.md
has been replaced by CamSharpness.md
2024-08-18 04:21:41 +02:00
michael
39e84baf8b Delete param-docs/parameter-pages/TakeImage/Saturation.md
has been replaced by CamSaturation.md
2024-08-18 04:20:44 +02:00
michael
eb7d078a1a Delete param-docs/parameter-pages/TakeImage/Negative.md
has been replaced by CamSpecialEffect.md
2024-08-18 04:19:42 +02:00
michael
b6c6805a08 Delete param-docs/parameter-pages/TakeImage/Grayscale.md
has been replaced by CamSpecialEffect.md
2024-08-18 04:19:22 +02:00
michael
d567a5d7f2 Delete param-docs/parameter-pages/TakeImage/Contrast.md
has been replaced by CamContrast.md
2024-08-18 04:17:35 +02:00
michael
6922970185 Delete param-docs/parameter-pages/TakeImage/Brightness.md
has been replaced by CamBrightness.md
2024-08-18 04:16:33 +02:00
michael
9a4b51d6de Delete param-docs/parameter-pages/TakeImage/AutoExposureLevel.md
has been replaced by CamAeLevel.md
2024-08-18 04:15:42 +02:00
michael
2546ab81ff Delete param-docs/parameter-pages/TakeImage/Aec2.md
has been replaced by CamAec2.md
2024-08-18 04:14:09 +02:00
michael
7b7544079f Bugfix for boot loop (#3175)
* Add files via upload

* Add files via upload

* Add files via upload
2024-08-17 23:02:21 +02:00
Sebastian Lövdahl
17fe87b349 Handle empty prevalue.ini gracefully (#3162)
Fixes #2149.
2024-08-09 01:01:58 +02:00
Sebastian Lövdahl
f99dc8fdfc Fix building with -D DEBUG_DETAIL_ON (#3160)
Building with `-D DEBUG_DETAIL_ON` has been broken since #3029.

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-08-09 01:00:38 +02:00
michael
cce992754c Update ClassFlowAlignment.cpp 2024-08-06 00:59:39 +02:00
michael
eefccf6e11 Update ClassFlowPostProcessing.cpp 2024-08-06 00:56:55 +02:00
michael
64bb4f0ff6 Update server_camera.cpp
Fix building with -D DEBUG_DETAIL_ON 

better alternative to:
https://github.com/jomjol/AI-on-the-edge-device/pull/3160
2024-08-05 23:57:17 +02:00
Henry Thasler
f534741205 proposal for renaming and documentation (#3115) 2024-07-21 14:09:51 +02:00
michael
ee38bc7dc6 Update readconfigparam.js
fix for:
In the selected field the value '1' in the section 'TakeImage' in the field 'CamGainceiling' is invalid. PLEASE CHECK BEFORE SAVING!
2024-07-20 15:53:16 +02:00
michael
132834c3fd Update Helper.cpp 2024-07-17 16:07:23 +02:00
michael
d3d9c64f3b Update Helper.h 2024-07-17 13:14:00 +02:00
michael
aa2a4edf7e Update Helper.cpp 2024-07-17 13:12:15 +02:00
CaCO3
8012b7f43e Fix actions-label-commenter 2024-06-09 23:20:13 +02:00
CaCO3
009ab4c896 Update reply-bot.yaml (#3107) 2024-06-09 23:13:34 +02:00
CaCO3
c54ca18e4e update platformIO to 6.7.0 (ESP IDF 5.2.1) (#3098)
* update to platformio/espressif32 @ 6.7.0

* remove unused getReadout() as it throws errors (error: 'virtual std::string ClassFlow::getReadout()' was hidden).

---------

Co-authored-by: CaCO3 <caco@ruinelli.ch>
2024-06-03 23:36:14 +02:00
CaCO3
beb09593eb Typo 2024-06-02 23:04:42 +02:00
Henry Thasler
1a76ae121c add Prometheus/OpenMetrics exporter (#3081)
* add prometheus endpoint

* refine metrics implementation

* move metrics generator to ClassFlowControll

* add more metrics
align prefix

* add more metrics
clean up

* refine documentation

* revert dependencies change

* sanitize labels

* create separate module for openmetrics

* move openmetrics to separate folder

* clean up

* add basic unit-tests

* work with const numbers
add replaceAll for string replacement
avoid opening std namespace
adapt unit-tests

* Update code/main/server_main.cpp

---------

Co-authored-by: CaCO3 <caco3@ruinelli.ch>
2024-06-02 21:13:15 +02:00
Henry Thasler
1300242d4a homeassistant service discovery: derive node_id when using nested topics (#3088)
* derive correct node_id for homeassistant service discovery in nested topics (fixes #1792)

* explicit use of std::string

* move nodeId creation to separate function
add unit-tests

* add documentation about node_id generation for Home Assistant MQTT Service Discovery
2024-06-02 21:00:44 +02:00
CaCO3
79543df23b Update reply-bot.yaml 2024-05-07 23:57:02 +02:00
michael
4049d752ba Update overview.html
CamFrameSize is no longer needed/used for zoom
2024-04-27 00:03:26 +02:00
michael
dc90972659 Update info.html
function loadWLANSSID() was present three times
2024-04-24 07:25:14 +02:00
michael
32282ecfe2 fix edit_config_template.html
TakeImage_CamZoomMode_value1 was replaced by TakeImage_CamZoomSize_value1, but not deleted.
This caused problems when saving the camera settings.
2024-04-16 13:14:27 +02:00
michael
ae6a94544b fix readconfigparam.js
Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^
2024-04-16 04:26:35 +02:00
michael
70b031eacc fix edit_config_template.html
Unfortunately, I didn't take out some entries from other experiments because I overlooked/forgot them^^
2024-04-16 04:25:51 +02:00
michael
c3fadf5c2a Source code formatting, ClassFlowPostProcessing.cpp 2024-04-15 22:12:02 +02:00
Marco H
7e5f6bf4a5 Fix minor typo and harmonize spaces (#3030)
* Update edit_digits.html

* Update edit_analog.html

* Update overview.html

* Update edit_reference.html

---------

Co-authored-by: jomjol <30766535+jomjol@users.noreply.github.com>
2024-04-11 21:28:33 +02:00
michael
88b531ae8b Camera settings (#3029)
* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload

* Add files via upload
2024-04-11 21:12:40 +02:00
jomjol
8481cc4b26 Update tflite 2024-03-30 14:47:26 +01:00
jomjol
ecaed38c1d Update tflite 2024-03-30 09:07:42 +01:00
jomjol
d6a1838d47 Create dig-class11_1701_s2.tflite 2024-03-25 08:25:47 +01:00
kub3let
5194c466be always reset change absolute (#2956) 2024-03-22 21:55:11 +01:00
Frank Haverland
043de9265a Fix test (#2933) 2024-03-20 19:22:33 +01:00
CaCO3
08a350172d renamed model file to make naming consistent 2024-03-13 22:28:41 +01:00
CaCO3
7e806df64d Renamed menu entry Alignment -> References 2024-02-18 09:52:24 +01:00
CaCO3
dccfb5e91e The parameter "negative" is processed on the MCU 2024-02-17 22:01:31 +01:00
michael
fbe4609bb9 Update edit_config_template.html (#2925)
Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist +
Kameraeinstellungen nicht nur in der config.ini speichern, sondern auch setzen
2024-02-17 10:17:08 +01:00
michael
3e85cfb456 Update edit_reference.html (#2924)
Zoom-Einstellungen ausblenden, wenn zoom deaktiviert ist
2024-02-17 10:17:00 +01:00
jomjol
5dff4ca8cf Create dig-cont_0640_s3_q.tflite 2024-02-17 08:25:12 +01:00
99 changed files with 2261 additions and 510 deletions

View File

@@ -53,6 +53,7 @@ jobs:
./code/.pio/build/esp32cam/partitions.bin
./code/.pio/build/esp32cam/bootloader.bin
./html/*
./demo/*
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
@@ -87,6 +88,11 @@ jobs:
echo "Replacing variables..."
cd html; find . -type f -exec sed -i 's/$COMMIT_HASH/${{ steps.vars.outputs.sha_short }}/g' {} \;
- name: Prepare Demo mode files
run: |
rm -rf ./demo
mkdir demo
cp -r ./sd-card/demo/* ./demo/
#########################################################################################
## Pack for Update
@@ -97,6 +103,7 @@ jobs:
# - /firmware.bin
# - (optional) /html/* (inkl. subfolders)
# - (optional) /config/*.tfl
# - (optional) /demo/*
runs-on: ubuntu-latest
needs: build
@@ -111,6 +118,7 @@ jobs:
./code/.pio/build/esp32cam/partitions.bin
./code/.pio/build/esp32cam/bootloader.bin
./html/*
./demo/*
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
@@ -135,6 +143,9 @@ jobs:
- name: Add Web UI to update
run: cp -r ./html ./update/
- name: Add Demo mode files to update
run: cp -r ./demo ./update/
- name: Add CNN to update
run: |
@@ -158,6 +169,7 @@ jobs:
# remote_setup__version.zip file with following content:
# - /firmware.bin
# - /html/* (inkl. subfolders)
# - /demo/*
# - /config/*
runs-on: ubuntu-latest
needs: build
@@ -173,6 +185,7 @@ jobs:
./code/.pio/build/esp32cam/partitions.bin
./code/.pio/build/esp32cam/bootloader.bin
./html/*
./demo/*
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
@@ -197,6 +210,9 @@ jobs:
- name: Add Web UI to remote_setup
run: cp -r ./html ./remote_setup/
- name: Add Demo mode files to update
run: cp -r ./demo ./update/
- name: Add whole config folder to remote_setup
run: |
rm -rf ./remote_setup/config/
@@ -229,6 +245,7 @@ jobs:
./code/.pio/build/esp32cam/partitions.bin
./code/.pio/build/esp32cam/bootloader.bin
./html/*
./demo/*
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
@@ -257,7 +274,9 @@ jobs:
cp -f "./code/.pio/build/esp32cam/bootloader.bin" "manual_setup/bootloader.bin"
cp -f "./code/.pio/build/esp32cam/partitions.bin" "manual_setup/partitions.bin"
rm -rf ./sd-card/html
rm -rf ./sd-card/demo
cp -r ./html ./sd-card/ # Overwrite the Web UI with the preprocessed files
cp -r ./demo ./sd-card/
cd sd-card; zip -r ../manual_setup/sd-card.zip *; cd ..
cd ./manual_setup
@@ -271,7 +290,7 @@ jobs:
#########################################################################################
## Prepare and create release
#########################################################################################
release:
prepare-release:
runs-on: ubuntu-latest
needs: [pack-for-update, pack-for-manual_setup, pack-for-remote_setup]
if: startsWith(github.ref, 'refs/tags/')
@@ -331,7 +350,7 @@ jobs:
# extract the version used in next step
- id: get_version
uses: dhkatz/get-version-action@v3.0.0
uses: drewg13/get-version-action@98dda2a47a257e202c2e6c2ed2e6072ec23f448e
# # the changelog [unreleased] will now be changed to the release version
# - name: Update changelog
@@ -377,7 +396,7 @@ jobs:
# Make sure to also update update-webinstaller.yml!
update-web-installer:
if: github.event_name == 'release' && github.event.action == 'published' # Only run on release but not on prerelease
needs: [release]
needs: [prepare-release]
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

View File

@@ -0,0 +1,21 @@
# This updates the Contributors list in the README.md
# it only gets run on:
# - Manually triggered
name: Manually update contributors list
on:
workflow_dispatch: # Run on manual trigger
jobs:
manually-update-contributors-list:
runs-on: ubuntu-latest
name: A job to automatically update the contributors list in the README.md
permissions:
contents: write
pull-requests: write
steps:
- name: Contribute List
uses: akhilmhdh/contributors-readme-action@v2.3.10
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

3
.gitmodules vendored
View File

@@ -10,3 +10,6 @@
[submodule "code/components/stb"]
path = code/components/stb
url = https://github.com/nothings/stb.git
[submodule "code/esp-protocols"]
path = code/esp-protocols
url = https://github.com/espressif/esp-protocols.git

View File

@@ -1,3 +1,89 @@
## [16.0.0-RC6] - 2024-xx-xx
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0)
#### Known issues
Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and
[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue.
#### Core Changes
Only changes since RC5 are listed:
- [#3436](https://github.com/jomjol/AI-on-the-edge-device/pull/3436) Added basic authentification of the Web Interface and the REST API, see https://jomjol.github.io/AI-on-the-edge-device-docs/Password-Protection
- xxx
**:warning: Please check your Homeassistant instance to make sure it is handled correctly!**
#### Bug Fixes
Only changes since RC5 are listed:
- xxx
## [16.0.0-RC5] - 2024-12-05
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0)
#### Known issues
Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and
[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue.
#### Core Changes
Only changes since RC4 are listed:
- [#3423](https://github.com/jomjol/AI-on-the-edge-device/pull/3423) Removed `Autostart` parameter and make the flow to be always enabled
- [#3423](https://github.com/jomjol/AI-on-the-edge-device/pull/3423) Enable `Flow start` menu entry in UI
- [#3332](https://github.com/jomjol/AI-on-the-edge-device/pull/3332) Updated the Homeassistant Discovery topics :
- `raw` has now set the `State Class` to `measurement`. Before it was always set to `""`.
- `value` has now only set the `State Class` to `total_increasing` if the parameter `Allow Negative Rates` is **not** set. Else it uses `measurement` since the rate could also be negative. Before it was always set to `total_increasing`.
- The `rate_per_time_unit` topic of an **Energy** meter needs a `Device Class`=`power`. For `gas` and `water` it should be `volume_flow_rate`. Before it was always set to `""`.
- [#3415](https://github.com/jomjol/AI-on-the-edge-device/pull/3415) Added button for `flow start`
- [#3359](https://github.com/jomjol/AI-on-the-edge-device/pull/3359) Added support for Domoticz MQTT integration
- Added Date and time to overview page
- Updated submodules and models
**:warning: Please check your Homeassistant instance to make sure it is handled correctly!**
#### Bug Fixes
Only changes since RC4 are listed:
- [#3418](https://github.com/jomjol/AI-on-the-edge-device/pull/3418) Added fix for ledintensity
- [#3417](https://github.com/jomjol/AI-on-the-edge-device/pull/3417) Added fix for OV2640 brightness contrast saturation
- [#3393](https://github.com/jomjol/AI-on-the-edge-device/pull/3393) Added fix for 'AnalogToDigitTransitionStart' always using 9.2 regardless of the configured value
- [#3342](https://github.com/jomjol/AI-on-the-edge-device/pull/3342) Added fix for HA menu entry
## [16.0.0-RC4] - 2024-10-06
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0-RC1)
#### Known issues
Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and
[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue.
#### Core Changes
Only changes since RC3 are listed:
- [#3316](https://github.com/jomjol/AI-on-the-edge-device/pull/3316) Update esp32-camera submodule to `v2.0.13`
- [#3317](https://github.com/jomjol/AI-on-the-edge-device/pull/3317) Added contributor list
- [#3315](https://github.com/jomjol/AI-on-the-edge-device/pull/3315) Added files for demo mode
#### Bug Fixes
Only changes since RC2 are listed:
- [#3313](https://github.com/jomjol/AI-on-the-edge-device/pull/3313) Added delay in InitCam to fix `Camera not detected` issues
## [16.0.0-RC3] - 2024-10-05
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0-RC1)
#### Known issues
Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and
[discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions) before reporting a new issue.
#### Core Changes
Only changes since RC2 are listed:
- Renamed MQTT topic from `rate_per_digitalization_round` to `rate_per_digitization_round` (change happened already in RC1)
#### Bug Fixes
Only changes since RC2 are listed:
- [#3269](https://github.com/jomjol/AI-on-the-edge-device/pull/3269) Re-did revertion of TFlite submodule update as certain modules crash with it (change was lost)
## [16.0.0-RC2] - 2024-10-04
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v15.7.0...v16.0.0-RC1)
@@ -9,13 +95,13 @@ Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues
#### Core Changes
Only changes since RC1 are listed:
- Updated parameter documentation pages
- Rename/remove unused parameters (#3291)
- Migrate-cam-parameters (#3288)
- [#3291](https://github.com/jomjol/AI-on-the-edge-device/pull/3291) Rename/remove unused parameters
- [#3288](https://github.com/jomjol/AI-on-the-edge-device/pull/3288) Migrate-cam-parameters
#### Bug Fixes
Only changes since RC1 are listed:
- Reverted TFlite submodule update as certain modules crash with it (#3269)
- Changed the webhook UploadImg to false (#3279)
- [#3269](https://github.com/jomjol/AI-on-the-edge-device/pull/3269) Reverted TFlite submodule update as certain modules crash with it
- [#3279](https://github.com/jomjol/AI-on-the-edge-device/pull/3279) Changed the webhook UploadImg to false
- Changed default value from boolean to numeric value in parameter camDenoise documentation
- Updated config page
@@ -29,24 +115,24 @@ Please check the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues
#### Core Changes
Those are just the major changes:
- Add support for OV5640 camera (#3063)
- [#3063](https://github.com/jomjol/AI-on-the-edge-device/pull/3063) Add support for OV5640 camera
- New tflite-Models
- Homeassistant service discovery: derive node_id when using nested topics (#3088)
- Added Prometheus/OpenMetrics exporter (#3081)
- Added Webhook (#3148, #3163, #3174)
- Add rate threshold parameter (#3195)
- Added a Delay between the WiFi reconnections (#3068)
- [#3088](https://github.com/jomjol/AI-on-the-edge-device/pull/3088) Homeassistant service discovery: derive node_id when using nested topics
- [#3081](https://github.com/jomjol/AI-on-the-edge-device/pull/3081) Added Prometheus/OpenMetrics exporter
- [#3148](https://github.com/jomjol/AI-on-the-edge-device/pull/3148), [#3163](https://github.com/jomjol/AI-on-the-edge-device/pull/3163), [#3174](https://github.com/jomjol/AI-on-the-edge-device/pull/3148), [#3163](https://github.com/jomjol/AI-on-the-edge-device/pull/3163), [#3174](https://github.com/jomjol/AI-on-the-edge-device/pull/3174) Added Webhook
- [#3195](https://github.com/jomjol/AI-on-the-edge-device/pull/3195) Add rate threshold parameter
- [#3068](https://github.com/jomjol/AI-on-the-edge-device/pull/3068) Added a Delay between the WiFi reconnections
- Web UI improvements
- Various minor changes
- Update platformIO to 6.9.0 (Contains ESP IDF 5.3.1)
#### Bug Fixes
Those are just the major changes:
- Handle crash on corrupted model (#3220)
- Bugfix for boot loop (#3175)
- Bugfix for time stamp (#3180)
- Handle empty prevalue.ini gracefully (#3162)
- Added note about only TLS 1.2 is supported (#3213)
- [#3220](https://github.com/jomjol/AI-on-the-edge-device/pull/3220) Handle crash on corrupted model
- [#3175](https://github.com/jomjol/AI-on-the-edge-device/pull/3175) Bugfix for boot loop
- [#3180](https://github.com/jomjol/AI-on-the-edge-device/pull/3180) Bugfix for time stamp
- [#3162](https://github.com/jomjol/AI-on-the-edge-device/pull/3162) Handle empty prevalue.ini gracefully
- [#3213](https://github.com/jomjol/AI-on-the-edge-device/pull/3213) Added note about only TLS 1.2 is supported
## [15.7.0] - 2024-02-17
@@ -545,16 +631,16 @@ Intermediate Digits
- Implementation of new CNN types to detect intermediate values of digits with rolling numbers
- By default the old algo (0, 1, ..., 9, "N") is active (due to the limited types of digits trained so far)
- Activation can be done by selection a tflite file with the new trained model in the 'config.ini'
- Activation can be done by selecting a tflite file with the new trained model in the 'config.ini'
- **Details can be found in the [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Neural-Network-Types)** (different types, trained image types, naming convention)
- Updated neural network files (and adaption to new naming convention)
- Updated neural network files (and adaptation to new naming convention)
- Published a tool to download and combine log files - **Thanks to **
- Published a tool to download and combine log files - Thanks to [Contributor]
- Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
- Bug Fix: InfluxDB enabling in grahic configuration
- Bug Fix: InfluxDB enabling in graphic configuration
## [10.6.2](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v10.6.2), 2022-07-24
@@ -568,7 +654,7 @@ Stability Increase
- **NEW 10.6.1**: Bug Fix: tflite-filename with ".", HTML spelling error
- IndluxDB: direct injection into InfluxDB - thanks to **[wetneb](https://github.com/wetneb)**
- InfluxDB: direct injection into InfluxDB - thanks to **[wetneb](https://github.com/wetneb)**
- MQTT: implemented "Retain Flag" and extend with absolute Change (in addition to rate)
@@ -1083,7 +1169,7 @@ External Illumination
- Bug in configuration of analog ROIs corrected
- minor bug correction
- minor Bug correction
## [1.0.1](2020-09-05)
@@ -1092,7 +1178,7 @@ External Illumination
- preValue.ini Bug corrected
- minor bug correction
- minor Bug correction
## [1.0.0](2020-09-04)

View File

@@ -40,16 +40,16 @@ ____
Demo mode requires a working camera (if not, one receives a 'Cam bad' error). Would be nice to demo or play around on other ESP32 boards (or on ESP32-CAM boards when you broke the camera cable...).
#### #35 Use the same model, but provide the image from a Smartphone Camera
as reading the Electricity or Water meter every few minutues only delivers apparent accuracy (DE: "Scheingenauigkeit") you could just as well take a picture with your Smartphone evey so often (e.g. once a week when you are in the Basement anyway), then with some "semi clever" tricks pass this image to the model developed here, and the values then on to who ever needs them e.g. via MQTT.
as reading the Electricity or Water meter every few minutes only delivers apparent accuracy (DE: "Scheingenauigkeit") you could just as well take a picture with your Smartphone every so often (e.g. once a week when you are in the Basement anyway), then with some "semi clever" tricks pass this image to the model developed here, and the values than on to whoever needs them e.g. via MQTT.
IMO: It is not needed to have that many readings (datapoints) as our behaviour (Use of electricity or water) doesn't vary that much, say, over a weeks time. The interpolation between weekly readings will give sufficient information on the power and/or water usage.
#### #34 implement state and Roi for water leak detection
for example see Roi on the next picture..
for example see Roi in the next picture..
![grafik](https://user-images.githubusercontent.com/38385805/207858812-2a6ba41d-1a8c-4fa1-9b6a-53cdd113c106.png)
in case of position change between the measurments set this state to true, if there is no change set it back to false.
in case of position change between the measurements 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...
having this state in the mqtt broker can trigger functions like closing the water pipe valve and so on...
@@ -65,7 +65,7 @@ haveing this state in the mqtt broker can trigger functions like closing the ate
#### #31 Implement InfluxDB v2.x interface
* Currently only InfluxDB v1.x is supportet, extend to v2.x
* Currently only InfluxDB v1.x is supported, extend to v2.x
* Remark: interface has changed
* see [#1160](https://github.com/jomjol/AI-on-the-edge-device/issues/1160)
@@ -82,7 +82,7 @@ haveing this state in the mqtt broker can trigger functions like closing the ate
#### #28 Improved error handling for ROIs
* In case a ROI is out of the image, there is no error message, but a non sense image is used
* Implement a error message for wrong configuratioin of ROI
* Implement a error message for wrong configuration of ROI
#### #27 Use Homie Spec for Mqtt binding

68
License-DRAFT.md Normal file
View File

@@ -0,0 +1,68 @@
# **Dual Use License for AI-on-the-Edge Device**
Version: 1.0 - Draft Version
Date: 2025-01-05 (5th January 2025)
## **Preamble**
This license allows individuals to use, modify, and share AI-on-the-Edge freely for private, non-commercial purposes. Any commercial use requires a separate licensing agreement with the rights holder.
------
## **1. Grant of License**
### 1.1 **Private Use**
The licensor grants the licensee a free, non-exclusive, worldwide license to use, modify, and distribute the software for private, non-commercial purposes.
### 1.2 **Commercial Use**
The use of the software or any derivative works in any commercial context (including, but not limited to, selling, renting, providing as a service, or integrating into commercial products) is prohibited without a separate commercial license.
------
## **2. Obligation to Private Derivatives**
In modified private versions of the software, the unchanged license as well as the reference to the original source and authors must always be stated (https://github.com/jomjol/AI-on-the-edge-device).
Modified versions of the software must be clearly marked as such and must not imply they are provided by the original licensor.
------
## **3. Commercial Licensing**
Companies, organizations, or individuals wishing to use the software for commercial purposes must obtain a separate commercial license. Please contact mueller.josef(@)gmail.com for further details.
------
## **4. Terms of Cooperation**
By contributing to the AI-on-the-Edge software, this license is considered accepted. This applies to, but is not limited to, code, error corrections, extensions, artwork, documentation, and new features. Any contribution, including libraries and sources, must comply with the terms of this license.
The contributor agrees that the added code and functionality may also be used in commercial versions without compensation to the contributor.
------
## **5. Disclaimer of Liability**
### 5.1 **General Disclaimer**
The software is provided "as is", without any express or implied warranties. The licensor is not liable for any damages resulting from the use of the software.
### 5.2 **No Usage in Safety or Security Environments**
The image processing uses neural networks, among other algorithms, whose results can produce incorrect or unexpected outcomes due to their functionality and the underlying training data. Therefore, this system must not be used or offered for safety-relevant systems or systems with high reliability requirements.
------
## **6. General Provisions**
### 6.1 **Severability Clause**
If any provision of this license is deemed invalid, the remaining provisions shall remain in full force and effect.
------
## **Acceptance**
By using this software, the licensee agrees to the terms of this license.

721
README.md
View File

@@ -1,108 +1,667 @@
# Welcome to the AI-on-the-edge-device
<img src="images/icon/watermeter.svg" width="100px">
<h1 align="center">AI on the Edge Device: Digitizing Your non-digital meters with an ESP32-CAM</h1>
<br>
<br>
Artificial intelligence based systems have become established in our everyday lives. Just think of speech or image recognition. Most of the systems rely on either powerful processors or a direct connection to the cloud for doing the calculations there. With the increasing power of modern processors, the AI systems are coming closer to the end user which is usually called **edge computing**.
Here, this edge computing is put into a practically oriented example, where an AI network is implemented on an ESP32 device so: **AI on the edge**.
## Table of Contents
- [Key Features 🚀](#key-features-)
- [Workflow 🔧](#workflow-)
- [Impressions 📷](#impressions-)
- [AI-on-the-edge-device on a Water Meter 💧](#ai-on-the-edge-device-on-a-water-meter-)
- [Web Interface (Water Meter) 💻](#web-interface-water-meter-)
- [AI-on-the-edge-device on an Electrical Power Meter ⚡](#ai-on-the-edge-device-on-an-electrical-power-meter-)
- [Setup 🛠️](#setup-%EF%B8%8F)
- [Download 🔽](#download-)
- [Flashing the ESP32 💾](#flashing-the-esp32-)
- [Flashing the SD Card 💾](#flashing-the-sd-card-)
- [Casing 🛠️](#casing-%EF%B8%8F)
- [Donate ☕](#donate-)
- [Support 💬](#support-)
- [Changes and History 📜](#changes-and-history-)
- [Build It Yourself 🔨](#build-it-yourself-)
- [Tools 🛠️](#tools-%EF%B8%8F)
- [Additional Ideas 💡](#additional-ideas-)
- [Our Contributors ❤️](#our-contributors-%EF%B8%8F)
This project allows you to digitize your **analog** water, gas, power and other meters using cheap and easily available hardware.
All you need is an [ESP32 board with a supported camera](https://jomjol.github.io/AI-on-the-edge-device-docs/Hardware-Compatibility/) and something 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 (3 x 4.5 x 2 cm³, < 10 EUR)
- Integrated camera and illumination
- Web interface for administration and control
- OTA interface for updating directly via the web interface
- Full integration into Homeassistant
- Support for Influx DB 1 and 2
- MQTT
- REST API
## Workflow
The device takes a photo of your meter at a defined interval. It then extracts the Regions of Interest (ROIs) from the image and runs them through artificial intelligence. As a result, you get the digitized value of your meter.
There are several options for what to do with that value. Either send it to an MQTT broker, write it to an InfluxDb or simply provide access to it via a REST API.
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/idea.jpg" width="600">
## Impressions
### AI-on-the-edge-device on a Water Meter
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter_all.jpg" width="200"><img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/main.jpg" width="200"><img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/size.png" width="200">
### Web Interface (Water Meter)
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/watermeter.jpg" width="600">
### AI-on-the-edge-device on a Electrical Power Meter
<img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/powermeter.jpg" width="600">
<p align="center">
<a href="#top">
<img src="https://img.shields.io/badge/Back%20to%20Top-000000?style=for-the-badge&logo=github&logoColor=white" alt="Back to Top">
</a>
</p>
## Setup
There is 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 articles in the German Heise magazine "make:" about the setup and technical background (behind a paywall): [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296)
A lot of people created useful Youtube videos which might help you getting started.
Here a small selection:
[![made-with-c++](https://img.shields.io/badge/Made%20with-C++-1f425f.svg)](https://github.com/jomjol/AI-on-the-edge-device/tree/main/code)
[![Doc](https://img.shields.io/badge/Doc-MkDocs-526CFE.svg)](https://jomjol.github.io/AI-on-the-edge-device-docs/)
[![Total downloads](https://img.shields.io/github/downloads/jomjol/AI-on-the-edge-device/total.svg)](https://GitHub.com/jomjol/AI-on-the-edge-device/releases/)
[![GitHub release](https://img.shields.io/github/release/jomjol/AI-on-the-edge-device.svg)](https://GitHub.com/jomjol/AI-on-the-edge-device/releases/)
[![GitHub forks](https://img.shields.io/github/forks/jomjol/AI-on-the-edge-device.svg?style=social&label=Fork&maxAge=2592000)](https://GitHub.com/jomjol/AI-on-the-edge-device/network/)
[![GitHub stars](https://img.shields.io/github/stars/jomjol/AI-on-the-edge-device.svg?style=social&label=Star&maxAge=2592000)](https://GitHub.com/jomjol/AI-on-the-edge-device/stargazers/)
- [youtube.com/watch?v=HKBofb1cnNc](https://www.youtube.com/watch?v=HKBofb1cnNc)
- [youtube.com/watch?v=yyf0ORNLCk4](https://www.youtube.com/watch?v=yyf0ORNLCk4)
- [youtube.com/watch?v=XxmTubGek6M](https://www.youtube.com/watch?v=XxmTubGek6M)
- [youtube.com/watch?v=mDIJEyElkAU](https://www.youtube.com/watch?v=mDIJEyElkAU)
- [youtube.com/watch?v=SssiPkyKVVs](https://www.youtube.com/watch?v=SssiPkyKVVs)
- [youtube.com/watch?v=MAHE_QyHZFQ](https://www.youtube.com/watch?v=MAHE_QyHZFQ)
- [youtube.com/watch?v=Uap_6bwtILQ](https://www.youtube.com/watch?v=Uap_6bwtILQ)
<p align="center" id="top">
<img src="images/icon/watermeter.svg" width="150px">
</p>
For further background information, head to [Neural Networks](https://www.heise.de/select/make/2021/6/2126410443385102621), [Training Neural Networks](https://www.heise.de/select/make/2022/1/2134114065999161585) and [Programming on the ESP32](https://www.heise.de/select/make/2022/2/2204010051597422030).
Artificial intelligence is everywhere, from speech to image recognition. While most AI systems rely on powerful processors or cloud computing, **edge computing** brings AI closer to the end user by utilizing the capabilities of modern processors.
This project demonstrates edge computing using the **ESP32**, a low-cost, AI-capable device, to digitize your analog meters—whether water, gas, or electricity. With affordable hardware and simple instructions, you can turn any standard meter into a smart device.
### Download
Let's explore how to make **AI on the Edge** a reality! 🌟
All you need is an [ESP32 board with a supported camera](https://jomjol.github.io/AI-on-the-edge-device-docs/Hardware-Compatibility/) and some practical skills. 🛠️
---
<br>
## Key Features 🚀
- 🔗 **Tensorflow Lite (TFLite) integration** including an easy-to-use wrapper.
- 📸 **Inline image processing** (feature detection, alignment, ROI extraction).
- 💡 **Small** and **affordable** device (3 x 4.5 x 2 cm³, less than 10 EUR).
- 📷 Integrated camera and illumination.
- 🌐 Web interface for administration and control.
- 🔄 OTA interface for updating directly via the web interface.
- 🏠 Full integration with Home Assistant.
- 📊 Support for **Influx DB 1** and **2**.
- 📡 **MQTT protocol** support.
- 📥 **REST API** available for data access.
<br>
## Workflow 🔧
The device captures a photo of your meter at set intervals. It then extracts the Regions of Interest (ROIs) from the image and runs them through artificial intelligence. As a result, you get the digitized value of your meter.
There are several options for what to do with that value:
- 📤 Send it to a **MQTT broker**.
- 📝 Write it to an **InfluxDb**.
- 🔗 Provide access via a **REST API**.
<p align="center">
<img src="images/idea.jpg" width="600">
</p>
---
<br>
## Impressions 📷
+ ### AI-on-the-edge-device on a Water Meter 💧
<p align="center">
<img src="images/watermeter_all.jpg" width="200"><img
src="images/main.jpg" width="200"><img
src="images/size.png" width="200">
</p>
+ ### Web Interface (Water Meter) 💻
<p align="center">
<img src="images/watermeter.jpg" width="600">
</p>
+ ### AI-on-the-edge-device on an Electrical Power Meter ⚡
<p align="center">
<img src="images/powermeter.jpg" width="600">
</p>
---
<br>
## Setup 🛠️
There is growing [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/) which provides you with a lot of information. Head there to get started, set it up, and configure it.
There are also articles in the German Heise magazine "make:" about the setup and technical background (behind a paywall): [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296) 📰
A lot of people have created useful YouTube videos that might help you get started:
- 🎥 [youtube.com/watch?v=HKBofb1cnNc](https://www.youtube.com/watch?v=HKBofb1cnNc)
- 🎥 [youtube.com/watch?v=yyf0ORNLCk4](https://www.youtube.com/watch?v=yyf0ORNLCk4)
- 🎥 [youtube.com/watch?v=XxmTubGek6M](https://www.youtube.com/watch?v=XxmTubGek6M)
- 🎥 [youtube.com/watch?v=mDIJEyElkAU](https://www.youtube.com/watch?v=mDIJEyElkAU)
- 🎥 [youtube.com/watch?v=SssiPkyKVVs](https://www.youtube.com/watch?v=SssiPkyKVVs)
- 🎥 [youtube.com/watch?v=MAHE_QyHZFQ](https://www.youtube.com/watch?v=MAHE_QyHZFQ)
- 🎥 [youtube.com/watch?v=Uap_6bwtILQ](https://www.youtube.com/watch?v=Uap_6bwtILQ)
For further background information, head to:
- [Neural Networks](https://www.heise.de/select/make/2021/6/2126410443385102621)
- [Training Neural Networks](https://www.heise.de/select/make/2022/1/2134114065999161585)
- [Programming on the ESP32](https://www.heise.de/select/make/2022/2/2204010051597422030)
---
<br>
## Download 🔽
The latest available version can be found on the [Releases page](https://github.com/jomjol/AI-on-the-edge-device/releases).
### Flashing the ESP32
Initially you will have to flash the ESP32 via a USB connection. Later updates are possible directly over the air (OTA using WIFI).
---
<br>
## Flashing the ESP32 💾
Initially, you will have to flash the ESP32 via a USB connection. Later updates are possible directly over the air (OTA using Wi-Fi).
There are different ways to flash your ESP32:
- The preferred way is the [Web Installer and Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) which is a browser-based tool to flash the ESP32 and extract the log over USB:
![](images/web-installer.png)
- The preferred way is the [Web Installer and Console](https://jomjol.github.io/AI-on-the-edge-device/index.html), a browser-based tool to flash the ESP32 and extract the log over USB:
![](images/web-installer.png)
- Flash Tool from Espressif
- ESPtool (command-line tool)
See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/) for more information.
### Flashing the SD Card
The SD card can be setup automatically after the firmware got installed. See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#remote-setup-using-the-built-in-access-point) for details. For this to work, the SD card must be FAT formated (which is the default on a new SD card).
Alternatively the SD card still can be setup manually, see the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#3-sd-card) for details!
---
## Casing
Various 3D-printable housing can be found here:
- https://www.thingiverse.com/thing:4573481 (Water Meter)
- https://www.thingiverse.com/thing:5028229 (Power Meter)
- https://www.thingiverse.com/thing:5224101 (Gas Meter)
- https://www.thingiverse.com/thing:4571627 (ESP32-cam housing only)
<br>
## Donate
If you would like to support the developer with a cup of coffee, you can do that via [PayPal](https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL).
## Flashing the SD Card 💾
The SD card can be set up automatically after the firmware is installed. See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#remote-setup-using-the-built-in-access-point) for details. For this to work, the SD card must be FAT formatted (which is the default on a new SD card).
<a href="https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL"><img border="0" src="images/paypal.png" width="200px" target="_blank"></a>
Alternatively, the SD card can still be set up manually. See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#3-sd-card) for details.
## Support
If you have any technical problems please search the [discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions). In case you found a ug or have a feature request, please open an [issue](https://github.com/jomjol/AI-on-the-edge-device/issues).
---
In other cases you can contact the developer via email: <img src="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/mail.jpg" height="25">
<br>
## Changes and History
See [Changelog](Changelog.md).
## Casing 🛠️
Various 3D-printable housings can be found here:
- 💧 [Water Meter](https://www.thingiverse.com/thing:4573481)
- ⚡ [Power Meter](https://www.thingiverse.com/thing:5028229)
- 🔥 [Gas Meter](https://www.thingiverse.com/thing:5224101)
- 📷 [ESP32-cam housing only](https://www.thingiverse.com/thing:4571627)
## Build It Yourself
See [Build Instructions](code/README.md).
---
## Tools
* Logfile downloader and combiner (Thx to [reserve85](https://github.com/reserve85))
* Files see ['/tools/logfile-tool'](tbd), how-to see [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/outdated--Gasmeter-Log-Downloader/)
<br>
## Additional Ideas
There are some ideas and feature requests which are not currently being pursued mainly due to capacity reasons on the part of the developers.
They features are collected in the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and in [FeatureRequest.md](FeatureRequest.md).
## Donate ☕
If you'd like to support the developer with a cup of coffee, you can do so via [PayPal](https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL).
<p align="center">
<a href="https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL"><img border="0" src="images/paypal.png" width="200px" target="_blank"></a>
</p>
---
<br>
## Support 💬
If you have any technical problems, please search the [discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions). In case you find a bug or have a feature request, please open an [issue](https://github.com/jomjol/AI-on-the-edge-device/issues).
For any other issues, you can contact the developer via email:
<p align="center">
<img src="images/mail.jpg" height="25">
</p>
---
<br>
## Changes and History 📜
See the [Changelog](Changelog.md) for detailed information.
---
<br>
## Build It Yourself 🔨
See the [Build Instructions](code/README.md) for step-by-step guidance.
---
<br>
## Tools 🛠️
* Logfile downloader and combiner (Thanks to [reserve85](https://github.com/reserve85))
* It can be found at ['/tools/logfile-tool'](https://github.com/jomjol/AI-on-the-edge-device/tree/main/tools/logfile-tool).
---
<br>
## Additional Ideas 💡
There are some ideas and feature requests which are not currently being pursued—mainly due to capacity constraints on the part of the developers. These features are collected in the [issues](https://github.com/jomjol/AI-on-the-edge-device/issues) and in [FeatureRequest.md](FeatureRequest.md).
---
<br>
## Our Contributors ❤️
<!-- Do not manually edit this section! It should get updated using the Github action "Manually update contributors list" -->
<!-- readme: contributors -start -->
<table>
<tbody>
<tr>
<td align="center">
<a href="https://github.com/jomjol">
<img src="https://avatars.githubusercontent.com/u/30766535?v=4" width="100;" alt="jomjol"/>
<br />
<sub><b>jomjol</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/caco3">
<img src="https://avatars.githubusercontent.com/u/1783586?v=4" width="100;" alt="caco3"/>
<br />
<sub><b>CaCO3</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/haverland">
<img src="https://avatars.githubusercontent.com/u/412645?v=4" width="100;" alt="haverland"/>
<br />
<sub><b>Frank Haverland</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Slider0007">
<img src="https://avatars.githubusercontent.com/u/115730895?v=4" width="100;" alt="Slider0007"/>
<br />
<sub><b>Slider0007</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/SybexX">
<img src="https://avatars.githubusercontent.com/u/587201?v=4" width="100;" alt="SybexX"/>
<br />
<sub><b>michael</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/nliaudat">
<img src="https://avatars.githubusercontent.com/u/6782613?v=4" width="100;" alt="nliaudat"/>
<br />
<sub><b>Nicolas Liaudat</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/Zwer2k">
<img src="https://avatars.githubusercontent.com/u/10438794?v=4" width="100;" alt="Zwer2k"/>
<br />
<sub><b>Zwer2k</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/phlupp">
<img src="https://avatars.githubusercontent.com/u/6304863?v=4" width="100;" alt="phlupp"/>
<br />
<sub><b>phlupp</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jasaw">
<img src="https://avatars.githubusercontent.com/u/721280?v=4" width="100;" alt="jasaw"/>
<br />
<sub><b>jasaw</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dockSquadron">
<img src="https://avatars.githubusercontent.com/u/11964767?v=4" width="100;" alt="dockSquadron"/>
<br />
<sub><b>dockSquadron</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/rdmueller">
<img src="https://avatars.githubusercontent.com/u/1856308?v=4" width="100;" alt="rdmueller"/>
<br />
<sub><b>Ralf D. Müller</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/cristianmitran">
<img src="https://avatars.githubusercontent.com/u/36613624?v=4" width="100;" alt="cristianmitran"/>
<br />
<sub><b>cristianmitran</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/michaeljoos72">
<img src="https://avatars.githubusercontent.com/u/20517474?v=4" width="100;" alt="michaeljoos72"/>
<br />
<sub><b>michaeljoos72</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/henrythasler">
<img src="https://avatars.githubusercontent.com/u/6277203?v=4" width="100;" alt="henrythasler"/>
<br />
<sub><b>Henry Thasler</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/amantyagiprojects">
<img src="https://avatars.githubusercontent.com/u/174239452?v=4" width="100;" alt="amantyagiprojects"/>
<br />
<sub><b>Naman Tyagi</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/pixeldoc2000">
<img src="https://avatars.githubusercontent.com/u/376715?v=4" width="100;" alt="pixeldoc2000"/>
<br />
<sub><b>pixel::doc</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mad2xlc">
<img src="https://avatars.githubusercontent.com/u/37449746?v=4" width="100;" alt="mad2xlc"/>
<br />
<sub><b>Stefan</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/jochenchrist">
<img src="https://avatars.githubusercontent.com/u/2930448?v=4" width="100;" alt="jochenchrist"/>
<br />
<sub><b>jochenchrist</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/parhedberg">
<img src="https://avatars.githubusercontent.com/u/13777521?v=4" width="100;" alt="parhedberg"/>
<br />
<sub><b>parhedberg</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/slovdahl">
<img src="https://avatars.githubusercontent.com/u/1417619?v=4" width="100;" alt="slovdahl"/>
<br />
<sub><b>Sebastian Lövdahl</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/RaHehl">
<img src="https://avatars.githubusercontent.com/u/7577984?v=4" width="100;" alt="RaHehl"/>
<br />
<sub><b>Raphael Hehl</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/LordGuilly">
<img src="https://avatars.githubusercontent.com/u/13271835?v=4" width="100;" alt="LordGuilly"/>
<br />
<sub><b>LordGuilly</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/bilalmirza74">
<img src="https://avatars.githubusercontent.com/u/84387676?v=4" width="100;" alt="bilalmirza74"/>
<br />
<sub><b>Bilal Mirza</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/muggenhor">
<img src="https://avatars.githubusercontent.com/u/484066?v=4" width="100;" alt="muggenhor"/>
<br />
<sub><b>Giel van Schijndel</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/ppisljar">
<img src="https://avatars.githubusercontent.com/u/13629809?v=4" width="100;" alt="ppisljar"/>
<br />
<sub><b>Peter Pisljar</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ralf1307">
<img src="https://avatars.githubusercontent.com/u/46164027?v=4" width="100;" alt="ralf1307"/>
<br />
<sub><b>Ralf Rachinger</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Ranjana761">
<img src="https://avatars.githubusercontent.com/u/129291313?v=4" width="100;" alt="Ranjana761"/>
<br />
<sub><b>Ranjana761</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/SkylightXD">
<img src="https://avatars.githubusercontent.com/u/16561545?v=4" width="100;" alt="SkylightXD"/>
<br />
<sub><b>SkylightXD</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/ottk3">
<img src="https://avatars.githubusercontent.com/u/5236802?v=4" width="100;" alt="ottk3"/>
<br />
<sub><b>Sven Rojek</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Turbo87">
<img src="https://avatars.githubusercontent.com/u/141300?v=4" width="100;" alt="Turbo87"/>
<br />
<sub><b>Tobias Bieniek</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/tkopczuk">
<img src="https://avatars.githubusercontent.com/u/101632?v=4" width="100;" alt="tkopczuk"/>
<br />
<sub><b>Tomek Kopczuk</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/yonz2">
<img src="https://avatars.githubusercontent.com/u/13886257?v=4" width="100;" alt="yonz2"/>
<br />
<sub><b>Yonz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Yveaux">
<img src="https://avatars.githubusercontent.com/u/7716005?v=4" width="100;" alt="Yveaux"/>
<br />
<sub><b>Yveaux</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/flooxo">
<img src="https://avatars.githubusercontent.com/u/93255373?v=4" width="100;" alt="flooxo"/>
<br />
<sub><b>flox_x</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/gneluka">
<img src="https://avatars.githubusercontent.com/u/32097881?v=4" width="100;" alt="gneluka"/>
<br />
<sub><b>gneluka</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/kalwados">
<img src="https://avatars.githubusercontent.com/u/11840444?v=4" width="100;" alt="kalwados"/>
<br />
<sub><b>kalwados</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/kub3let">
<img src="https://avatars.githubusercontent.com/u/95883234?v=4" width="100;" alt="kub3let"/>
<br />
<sub><b>kub3let</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/pfeifferch">
<img src="https://avatars.githubusercontent.com/u/73090220?v=4" width="100;" alt="pfeifferch"/>
<br />
<sub><b>pfeifferch</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/rstephan">
<img src="https://avatars.githubusercontent.com/u/8532364?v=4" width="100;" alt="rstephan"/>
<br />
<sub><b>rstephan</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/smartboart">
<img src="https://avatars.githubusercontent.com/u/38385805?v=4" width="100;" alt="smartboart"/>
<br />
<sub><b>smartboart</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/AngryApostrophe">
<img src="https://avatars.githubusercontent.com/u/89547888?v=4" width="100;" alt="AngryApostrophe"/>
<br />
<sub><b>AngryApostrophe</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/wetneb">
<img src="https://avatars.githubusercontent.com/u/309908?v=4" width="100;" alt="wetneb"/>
<br />
<sub><b>Antonin Delpeuch</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/adarazs">
<img src="https://avatars.githubusercontent.com/u/6269603?v=4" width="100;" alt="adarazs"/>
<br />
<sub><b>Attila Darazs</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/austindrenski">
<img src="https://avatars.githubusercontent.com/u/21338699?v=4" width="100;" alt="austindrenski"/>
<br />
<sub><b>Austin Drenski</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/PLCHome">
<img src="https://avatars.githubusercontent.com/u/29116097?v=4" width="100;" alt="PLCHome"/>
<br />
<sub><b>PLCHome</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/CFenner">
<img src="https://avatars.githubusercontent.com/u/9592452?v=4" width="100;" alt="CFenner"/>
<br />
<sub><b>Christopher Fenner</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/dkneisz">
<img src="https://avatars.githubusercontent.com/u/43378003?v=4" width="100;" alt="dkneisz"/>
<br />
<sub><b>Dave</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/FarukhS52">
<img src="https://avatars.githubusercontent.com/u/129654632?v=4" width="100;" alt="FarukhS52"/>
<br />
<sub><b>Farookh Zaheer Siddiqui</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/hex7c0">
<img src="https://avatars.githubusercontent.com/u/4419146?v=4" width="100;" alt="hex7c0"/>
<br />
<sub><b>Francesco Carnielli</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/040medien">
<img src="https://avatars.githubusercontent.com/u/115072?v=4" width="100;" alt="040medien"/>
<br />
<sub><b>Frederik Kemner</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/eltociear">
<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="100;" alt="eltociear"/>
<br />
<sub><b>Ikko Eltociear Ashimine</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/queeek">
<img src="https://avatars.githubusercontent.com/u/9533371?v=4" width="100;" alt="queeek"/>
<br />
<sub><b>Ina</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/joergrosenkranz">
<img src="https://avatars.githubusercontent.com/u/310438?v=4" width="100;" alt="joergrosenkranz"/>
<br />
<sub><b>Joerg Rosenkranz</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/Innovatorcloudy">
<img src="https://avatars.githubusercontent.com/u/183274513?v=4" width="100;" alt="Innovatorcloudy"/>
<br />
<sub><b>KrishCode</b></sub>
</a>
</td>
</tr>
<tr>
<td align="center">
<a href="https://github.com/myxor">
<img src="https://avatars.githubusercontent.com/u/1397377?v=4" width="100;" alt="myxor"/>
<br />
<sub><b>Marco H</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/rainman110">
<img src="https://avatars.githubusercontent.com/u/3213107?v=4" width="100;" alt="rainman110"/>
<br />
<sub><b>Martin Siggel</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/mkelley88">
<img src="https://avatars.githubusercontent.com/u/5567324?v=4" width="100;" alt="mkelley88"/>
<br />
<sub><b>Matthew T. Kelley</b></sub>
</a>
</td>
<td align="center">
<a href="https://github.com/toolsfactory">
<img src="https://avatars.githubusercontent.com/u/7744975?v=4" width="100;" alt="toolsfactory"/>
<br />
<sub><b>Michael Geissler</b></sub>
</a>
</td>
</tr>
<tbody>
</table>
<!-- readme: contributors -end -->
---
<div align="center">
<a href="#top">
<img src="https://img.shields.io/badge/Back%20to%20Top-000000?style=for-the-badge&logo=github&logoColor=white" alt="Back to Top">
</a>
</div>

View File

@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.16.0)
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common components/esp-tflite-micro)
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common components/esp-tflite-micro esp-protocols/components/mdns)
ADD_CUSTOM_COMMAND(
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/version.cpp

View File

@@ -25,6 +25,7 @@
#include "server_mqtt.h"
#endif //ENABLE_MQTT
#include "basic_auth.h"
static const char *TAG = "GPIO";
QueueHandle_t gpio_queue_handle = NULL;
@@ -458,7 +459,7 @@ void GpioHandler::registerGpioUri()
httpd_uri_t camuri = { };
camuri.method = HTTP_GET;
camuri.uri = "/GPIO";
camuri.handler = callHandleHttpRequest;
camuri.handler = APPLY_BASIC_AUTH_FILTER(callHandleHttpRequest);
camuri.user_ctx = (void*)this;
httpd_register_uri_handler(_httpServer, &camuri);
}

View File

@@ -32,6 +32,8 @@
#include "MainFlowControl.h"
#include "ov2640_sharpness.h"
#include "ov2640_specialEffect.h"
#include "ov2640_contrast_brightness.h"
#if (ESP_IDF_VERSION_MAJOR >= 5)
#include "soc/periph_defs.h"
@@ -96,7 +98,7 @@ static camera_config_t camera_config = {
.pixel_format = PIXFORMAT_JPEG, // YUV422,GRAYSCALE,RGB565,JPEG
.frame_size = FRAMESIZE_VGA, // QQVGA-UXGA Do not use sizes above QVGA when not JPEG
// .frame_size = FRAMESIZE_UXGA, //QQVGA-UXGA Do not use sizes above QVGA when not JPEG
.jpeg_quality = 6, // 0-63 lower number means higher quality
.jpeg_quality = 12, // 0-63 lower number means higher quality
.fb_count = 1, // if more than one, i2s runs in continuous mode. Use only with JPEG
.fb_location = CAMERA_FB_IN_PSRAM, /*!< The location where the frame buffer will be allocated */
.grab_mode = CAMERA_GRAB_LATEST, // only from new esp32cam version
@@ -122,12 +124,18 @@ esp_err_t CCamera::InitCam(void)
{
ESP_LOGD(TAG, "Init Camera");
TickType_t cam_xDelay = 100 / portTICK_PERIOD_MS;
CCstatus.ImageQuality = camera_config.jpeg_quality;
CCstatus.ImageFrameSize = camera_config.frame_size;
// De-init in case it was already initialized
esp_camera_deinit();
vTaskDelay(cam_xDelay);
// initialize the camera
esp_camera_deinit(); // De-init in case it was already initialized
esp_err_t err = esp_camera_init(&camera_config);
vTaskDelay(cam_xDelay);
if (err != ESP_OK)
{
@@ -221,13 +229,12 @@ void CCamera::ledc_init(void)
#endif
}
void CCamera::SetLEDIntensity(float _intrel)
int CCamera::SetLEDIntensity(int _intrel)
{
_intrel = min(_intrel, (float)100);
_intrel = max(_intrel, (float)0);
_intrel = _intrel / 100;
CCstatus.ImageLedIntensity = (int)(_intrel * 8191);
ESP_LOGD(TAG, "Set led_intensity to %d of 8191", CCstatus.ImageLedIntensity);
// CCstatus.ImageLedIntensity = (int)(std::min(std::max((float)0, _intrel), (float)100) / 100 * 8191)
Camera.LedIntensity = (int)((float)(std::min(std::max(0, _intrel), 100)) / 100 * 8191);
ESP_LOGD(TAG, "Set led_intensity to %i of 8191", Camera.LedIntensity);
return Camera.LedIntensity;
}
bool CCamera::getCameraInitSuccessful(void)
@@ -242,46 +249,46 @@ esp_err_t CCamera::setSensorDatenFromCCstatus(void)
if (s != NULL)
{
s->set_framesize(s, CCstatus.ImageFrameSize);
s->set_quality(s, CCstatus.ImageQuality); // 0 - 63
s->set_brightness(s, CCstatus.ImageBrightness); // -2 to 2
s->set_contrast(s, CCstatus.ImageContrast); // -2 to 2
// s->set_contrast(s, CCstatus.ImageContrast); // -2 to 2
// s->set_brightness(s, CCstatus.ImageBrightness); // -2 to 2
SetCamContrastBrightness(s, CCstatus.ImageContrast, CCstatus.ImageBrightness);
s->set_saturation(s, CCstatus.ImageSaturation); // -2 to 2
// s->set_sharpness(s, CCstatus.ImageSharpness); // auto-sharpness is not officially supported, default to 0
SetCamSharpness(CCstatus.ImageAutoSharpness, CCstatus.ImageSharpness);
s->set_denoise(s, CCstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
s->set_special_effect(s, CCstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_wb_mode(s, CCstatus.ImageWbMode); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_ae_level(s, CCstatus.ImageAeLevel); // -2 to 2
s->set_aec_value(s, CCstatus.ImageAecValue); // 0 to 1200
s->set_agc_gain(s, CCstatus.ImageAgcGain); // 0 to 30
s->set_quality(s, CCstatus.ImageQuality); // 0 - 63
// s->set_gainceiling(s, CCstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
ov5640_set_gainceiling(s, CCstatus.ImageGainceiling);
s->set_lenc(s, CCstatus.ImageLenc); // 0 = disable , 1 = enable
SetCamGainceiling(s, CCstatus.ImageGainceiling);
s->set_gain_ctrl(s, CCstatus.ImageAgc); // 0 = disable , 1 = enable
s->set_exposure_ctrl(s, CCstatus.ImageAec); // 0 = disable , 1 = enable
s->set_hmirror(s, CCstatus.ImageHmirror); // 0 = disable , 1 = enable
s->set_vflip(s, CCstatus.ImageVflip); // 0 = disable , 1 = enable
s->set_whitebal(s, CCstatus.ImageAwb); // 0 = disable , 1 = enable
s->set_aec2(s, CCstatus.ImageAec2); // 0 = disable , 1 = enable
s->set_aec_value(s, CCstatus.ImageAecValue); // 0 to 1200
// s->set_special_effect(s, CCstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
SetCamSpecialEffect(s, CCstatus.ImageSpecialEffect);
s->set_wb_mode(s, CCstatus.ImageWbMode); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_ae_level(s, CCstatus.ImageAeLevel); // -2 to 2
s->set_dcw(s, CCstatus.ImageDcw); // 0 = disable , 1 = enable
s->set_bpc(s, CCstatus.ImageBpc); // 0 = disable , 1 = enable
s->set_wpc(s, CCstatus.ImageWpc); // 0 = disable , 1 = enable
s->set_raw_gma(s, CCstatus.ImageRawGma); // 0 = disable , 1 = enable
s->set_awb_gain(s, CCstatus.ImageAwbGain); // 0 = disable , 1 = enable
s->set_whitebal(s, CCstatus.ImageAwb); // 0 = disable , 1 = enable
s->set_agc_gain(s, CCstatus.ImageAgcGain); // 0 to 30
s->set_raw_gma(s, CCstatus.ImageRawGma); // 0 = disable , 1 = enable
s->set_lenc(s, CCstatus.ImageLenc); // 0 = disable , 1 = enable
s->set_dcw(s, CCstatus.ImageDcw); // 0 = disable , 1 = enable
// s->set_sharpness(s, CCstatus.ImageSharpness); // auto-sharpness is not officially supported, default to 0
SetCamSharpness(CCstatus.ImageAutoSharpness, CCstatus.ImageSharpness);
s->set_denoise(s, CCstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
TickType_t xDelay2 = 100 / portTICK_PERIOD_MS;
vTaskDelay(xDelay2);
TickType_t cam_xDelay = 100 / portTICK_PERIOD_MS;
vTaskDelay(cam_xDelay);
return ESP_OK;
}
@@ -300,30 +307,37 @@ esp_err_t CCamera::getSensorDatenToCCstatus(void)
CCstatus.CamSensor_id = s->id.PID;
CCstatus.ImageFrameSize = (framesize_t)s->status.framesize;
CCstatus.ImageContrast = s->status.contrast;
CCstatus.ImageBrightness = s->status.brightness;
CCstatus.ImageSaturation = s->status.saturation;
CCstatus.ImageQuality = s->status.quality;
CCstatus.ImageGainceiling = (gainceiling_t)s->status.gainceiling;
CCstatus.ImageQuality = s->status.quality;
CCstatus.ImageBrightness = s->status.brightness;
CCstatus.ImageContrast = s->status.contrast;
CCstatus.ImageSaturation = s->status.saturation;
// CCstatus.ImageSharpness = s->status.sharpness; // gibt -1 zurück, da es nicht unterstützt wird
CCstatus.ImageWbMode = s->status.wb_mode;
CCstatus.ImageAwb = s->status.awb;
CCstatus.ImageAwbGain = s->status.awb_gain;
CCstatus.ImageAec = s->status.aec;
CCstatus.ImageAec2 = s->status.aec2;
CCstatus.ImageAeLevel = s->status.ae_level;
CCstatus.ImageAecValue = s->status.aec_value;
CCstatus.ImageAgc = s->status.agc;
CCstatus.ImageAgcGain = s->status.agc_gain;
CCstatus.ImageBpc = s->status.bpc;
CCstatus.ImageWpc = s->status.wpc;
CCstatus.ImageRawGma = s->status.raw_gma;
CCstatus.ImageLenc = s->status.lenc;
CCstatus.ImageSpecialEffect = s->status.special_effect;
CCstatus.ImageAec = s->status.aec;
CCstatus.ImageHmirror = s->status.hmirror;
CCstatus.ImageVflip = s->status.vflip;
CCstatus.ImageAwb = s->status.awb;
CCstatus.ImageAec2 = s->status.aec2;
CCstatus.ImageAecValue = s->status.aec_value;
CCstatus.ImageSpecialEffect = s->status.special_effect;
CCstatus.ImageWbMode = s->status.wb_mode;
CCstatus.ImageAeLevel = s->status.ae_level;
CCstatus.ImageDcw = s->status.dcw;
CCstatus.ImageBpc = s->status.bpc;
CCstatus.ImageWpc = s->status.wpc;
CCstatus.ImageAwbGain = s->status.awb_gain;
CCstatus.ImageAgcGain = s->status.agc_gain;
CCstatus.ImageRawGma = s->status.raw_gma;
CCstatus.ImageLenc = s->status.lenc;
// CCstatus.ImageSharpness = s->status.sharpness; // gibt -1 zurück, da es nicht unterstützt wird
CCstatus.ImageDenoiseLevel = s->status.denoise;
return ESP_OK;
@@ -334,31 +348,96 @@ esp_err_t CCamera::getSensorDatenToCCstatus(void)
}
}
// on the OV5640, gainceiling must be set with the real value (x2>>>level = 2, .... x128>>>level = 128)
int CCamera::ov5640_set_gainceiling(sensor_t *s, gainceiling_t level)
// on the OV5640, gainceiling must be set with the real value (x2>>>gainceilingLevel = 2, .... x128>>>gainceilingLevel = 128)
int CCamera::SetCamGainceiling(sensor_t *s, gainceiling_t gainceilingLevel)
{
int ret = 0;
if (CCstatus.CamSensor_id == OV2640_PID)
{
ret = s->set_gainceiling(s, CCstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
ret = s->set_gainceiling(s, gainceilingLevel); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
}
else
{
int _level = (1 << ((int)level + 1));
int _level = (1 << ((int)gainceilingLevel + 1));
ret = s->set_reg(s, 0x3A18, 0xFF, (_level >> 8) & 3) || s->set_reg(s, 0x3A19, 0xFF, _level & 0xFF);
ret = s->set_reg(s, 0x3A18, 0xFF, (_level >> 8) & 3) || s->set_reg(s, 0x3A19, 0xFF, _level & 0xFF);
if (ret == 0)
{
// ESP_LOGD(TAG, "Set gainceiling to: %d", level);
s->status.gainceiling = level;
}
if (ret == 0)
{
// ESP_LOGD(TAG, "Set gainceiling to: %d", gainceilingLevel);
s->status.gainceiling = gainceilingLevel;
}
}
return ret;
}
void CCamera::SetCamSharpness(bool autoSharpnessEnabled, int sharpnessLevel)
{
sensor_t *s = esp_camera_sensor_get();
if (s != NULL)
{
if (CCstatus.CamSensor_id == OV2640_PID)
{
sharpnessLevel = min(2, max(-2, sharpnessLevel));
// The OV2640 does not officially support sharpness, so the detour is made with the ov2640_sharpness.cpp.
if (autoSharpnessEnabled)
{
ov2640_enable_auto_sharpness(s);
}
else
{
ov2640_set_sharpness(s, sharpnessLevel);
}
}
else
{
sharpnessLevel = min(3, max(-3, sharpnessLevel));
// for CAMERA_OV5640 and CAMERA_OV3660
if (autoSharpnessEnabled)
{
// autoSharpness is not supported, default to zero
s->set_sharpness(s, 0);
}
else
{
s->set_sharpness(s, sharpnessLevel);
}
}
}
else
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetCamSharpness, Failed to get Cam control structure");
}
}
void CCamera::SetCamSpecialEffect(sensor_t *s, int specialEffect)
{
if (CCstatus.CamSensor_id == OV2640_PID)
{
ov2640_set_special_effect(s, specialEffect);
}
else
{
s->set_special_effect(s, specialEffect);
}
}
void CCamera::SetCamContrastBrightness(sensor_t *s, int _contrast, int _brightness)
{
if (CCstatus.CamSensor_id == OV2640_PID)
{
ov2640_set_contrast_brightness(s, _contrast, _brightness);
}
else
{
s->set_contrast(s, _contrast); // -2 to 2
s->set_brightness(s, _brightness); // -2 to 2
}
}
// - It always zooms to the image center when offsets are zero
// - if imageSize = 0 then the image is not zoomed
// - if imageSize = max value, then the image is fully zoomed in
@@ -512,46 +591,6 @@ void CCamera::SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled,
}
}
void CCamera::SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel)
{
sensor_t *s = esp_camera_sensor_get();
if (s != NULL)
{
if (CCstatus.CamSensor_id == OV2640_PID)
{
_sharpnessLevel = min(2, max(-2, _sharpnessLevel));
// The OV2640 does not officially support sharpness, so the detour is made with the ov2640_sharpness.cpp.
if (_autoSharpnessEnabled)
{
ov2640_enable_auto_sharpness(s);
}
else
{
ov2640_set_sharpness(s, _sharpnessLevel);
}
}
else
{
_sharpnessLevel = min(3, max(-3, _sharpnessLevel));
// for CAMERA_OV5640 and CAMERA_OV3660
if (_autoSharpnessEnabled)
{
// autoSharpness is not supported, default to zero
s->set_sharpness(s, 0);
}
else
{
s->set_sharpness(s, _sharpnessLevel);
}
}
}
else
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "SetCamSharpness, Failed to get Cam control structure");
}
}
void CCamera::SetCamWindow(sensor_t *s, int frameSizeX, int frameSizeY, int xOffset, int yOffset, int xTotal, int yTotal, int xOutput, int yOutput, int imageVflip)
{
if (CCstatus.CamSensor_id == OV2640_PID)
@@ -904,6 +943,7 @@ esp_err_t CCamera::CaptureToStream(httpd_req_t *req, bool FlashlightOn)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize, CCstatus.ImageVflip);
Camera.LedIntensity = CCstatus.ImageLedIntensity;
CFstatus.changedCameraSettings = false;
}
@@ -994,8 +1034,8 @@ void CCamera::LightOnOff(bool status)
#ifdef USE_PWM_LEDFLASH
if (status)
{
ESP_LOGD(TAG, "Internal Flash-LED turn on with PWM %d", CCstatus.ImageLedIntensity);
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, CCstatus.ImageLedIntensity));
ESP_LOGD(TAG, "Internal Flash-LED turn on with PWM %d", Camera.LedIntensity);
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, Camera.LedIntensity));
// Update duty to apply the new value
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
}
@@ -1049,38 +1089,58 @@ void CCamera::SetImageWidthHeightFromResolution(framesize_t resol)
{
if (resol == FRAMESIZE_QVGA)
{
CCstatus.ImageHeight = 240;
CCstatus.ImageWidth = 320;
CCstatus.ImageHeight = 240;
}
else if (resol == FRAMESIZE_VGA)
{
CCstatus.ImageHeight = 480;
CCstatus.ImageWidth = 640;
CCstatus.ImageHeight = 480;
}
else if (resol == FRAMESIZE_SVGA)
{
CCstatus.ImageHeight = 600;
CCstatus.ImageWidth = 800;
CCstatus.ImageHeight = 600;
}
else if (resol == FRAMESIZE_XGA)
{
CCstatus.ImageHeight = 768;
CCstatus.ImageWidth = 1024;
CCstatus.ImageHeight = 768;
}
else if (resol == FRAMESIZE_HD)
{
CCstatus.ImageHeight = 720;
CCstatus.ImageWidth = 1280;
CCstatus.ImageHeight = 720;
}
else if (resol == FRAMESIZE_SXGA)
{
CCstatus.ImageHeight = 1024;
CCstatus.ImageWidth = 1280;
CCstatus.ImageHeight = 1024;
}
else if (resol == FRAMESIZE_UXGA)
{
CCstatus.ImageHeight = 1200;
CCstatus.ImageWidth = 1600;
CCstatus.ImageHeight = 1200;
}
else if (resol == FRAMESIZE_QXGA)
{
CCstatus.ImageWidth = 2048;
CCstatus.ImageHeight = 1536;
}
else if (resol == FRAMESIZE_WQXGA)
{
CCstatus.ImageWidth = 2560;
CCstatus.ImageHeight = 1600;
}
else if (resol == FRAMESIZE_QSXGA)
{
CCstatus.ImageWidth = 2560;
CCstatus.ImageHeight = 1920;
}
else
{
CCstatus.ImageWidth = 640;
CCstatus.ImageHeight = 480;
}
}
@@ -1110,8 +1170,24 @@ framesize_t CCamera::TextToFramesize(const char *_size)
{
return FRAMESIZE_UXGA; // 1600x1200
}
else if (strcmp(_size, "QXGA") == 0)
{
return FRAMESIZE_QXGA; // 2048x1536
}
else if (strcmp(_size, "WQXGA") == 0)
{
return FRAMESIZE_WQXGA; // 2560x1600
}
else if (strcmp(_size, "QSXGA") == 0)
{
return FRAMESIZE_QSXGA; // 2560x1920
}
else
{
return FRAMESIZE_VGA; // 640x480
}
return CCstatus.ImageFrameSize;
// return CCstatus.ImageFrameSize;
}
std::vector<std::string> demoFiles;

View File

@@ -80,6 +80,8 @@ protected:
void SanitizeZoomParams(int imageSize, int frameSizeX, int frameSizeY, int &imageWidth, int &imageHeight, int &zoomOffsetX, int &zoomOffsetY);
public:
int LedIntensity = 4096;
CCamera(void);
esp_err_t InitCam(void);
@@ -89,16 +91,18 @@ public:
esp_err_t setSensorDatenFromCCstatus(void);
esp_err_t getSensorDatenToCCstatus(void);
int ov5640_set_gainceiling(sensor_t *s, gainceiling_t level);
int SetCamGainceiling(sensor_t *s, gainceiling_t gainceilingLevel);
void SetCamSharpness(bool autoSharpnessEnabled, int sharpnessLevel);
void SetCamSpecialEffect(sensor_t *s, int specialEffect);
void SetCamContrastBrightness(sensor_t *s, int _contrast, int _brightness);
esp_err_t CaptureToHTTP(httpd_req_t *req, int delay = 0);
esp_err_t CaptureToStream(httpd_req_t *req, bool FlashlightOn);
void SetQualityZoomSize(int qual, framesize_t resol, bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize, int imageVflip);
void SetZoomSize(bool zoomEnabled, int zoomOffsetX, int zoomOffsetY, int imageSize, int imageVflip);
void SetCamSharpness(bool _autoSharpnessEnabled, int _sharpnessLevel);
void SetLEDIntensity(float _intrel);
int SetLEDIntensity(int _intrel);
bool testCamera(void);
bool getCameraInitSuccessful(void);
void useDemoMode(void);

View File

@@ -0,0 +1,88 @@
// Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used
// Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178
/* The memory structure is as follows for
byte_0 = enable_bits
byte_0->bit0 = enable saturation and hue --> OK
byte_0->bit1 = enable saturation --> OK
byte_0->bit2 = enable brightness and contrast --> OK
byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and reddish and b&w) enable
byte_0->bit4 = anable gray -> red spitial effect (Antique and blunish and greenish and reddish and b&w) enable
byte_0->bit5 = remove (UV) in YUV color system
byte_0->bit6 = enable negative
byte_0->bit7 = remove (Y) in YUV color system
byte_1 = saturation1 0-255 --> ?
byte_2 = hue 0-255 --> OK
byte_3 = saturation2 0-255 --> OK
byte_4 = reenter saturation2 in documents --> ?
byte_5 = spital effect green -> blue 0-255 --> ?
byte_6 = spital effect gray -> red 0-255 --> ?
byte_7 = contrast lower byte 0-255 --> OK
byte_8 = contrast higher byte 0-255 --> OK
byte_9 = brightness 0-255 --> OK
byte_10 = if byte_10==4 contrast effective --> ?
*/
#include <stdint.h>
#include "esp_camera.h"
#include "ov2640_contrast_brightness.h"
static const uint8_t brightness_regs[6][5] = {
{0x7C, 0x7D, 0x7C, 0x7D, 0x7D },
{0x00, 0x04, 0x09, 0x00, 0x00 }, /* -2 */
{0x00, 0x04, 0x09, 0x10, 0x00 }, /* -1 */
{0x00, 0x04, 0x09, 0x20, 0x00 }, /* 0 */
{0x00, 0x04, 0x09, 0x30, 0x00 }, /* +1 */
{0x00, 0x04, 0x09, 0x40, 0x00 }, /* +2 */
};
static const uint8_t contrast_regs[6][7] = {
{0x7C, 0x7D, 0x7C, 0x7D, 0x7D, 0x7D, 0x7D },
{0x00, 0x04, 0x07, 0x20, 0x18, 0x34, 0x06 }, /* -2 */
{0x00, 0x04, 0x07, 0x20, 0x1c, 0x2a, 0x06 }, /* -1 */
{0x00, 0x04, 0x07, 0x20, 0x20, 0x20, 0x06 }, /* 0 */
{0x00, 0x04, 0x07, 0x20, 0x24, 0x16, 0x06 }, /* +1 */
{0x00, 0x04, 0x07, 0x20, 0x28, 0x0c, 0x06 }, /* +2 */
};
int ov2640_set_contrast_brightness(sensor_t *sensor, int _contrast, int _brightness)
{
int ret=0;
_contrast += 3;
if (_contrast <= 0) {
_contrast = 3;
}
else if (_contrast > 5)
{
_contrast = 5;
}
sensor->status.contrast = _contrast-3;
_brightness += 3;
if (_brightness <= 0) {
_brightness = 3;
}
else if (_brightness > 5)
{
_brightness = 5;
}
int brightness = brightness_regs[_brightness][3];
sensor->status.brightness = _brightness-3;
// sensor->set_reg(sensor, int reg, int mask, int value)
sensor->set_reg(sensor, 0xFF, 0x01, 0x00); // Select DSP bank
for (int i=0; i<7; i++)
{
if (i == 5)
{
sensor->set_reg(sensor, contrast_regs[0][i], 0xFF, (brightness | contrast_regs[_contrast][i]));
}
else
{
sensor->set_reg(sensor, contrast_regs[0][i], 0xFF, contrast_regs[_contrast][i]);
}
}
return ret;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#ifndef OV2640_CONTRAST_BRIGHTNESS_H
#define OV2640_CONTRAST_BRIGHTNESS_H
#include "esp_camera.h"
int ov2640_set_contrast_brightness(sensor_t *sensor, int _contrast, int _brightness);
#endif

View File

@@ -2,10 +2,9 @@
#include "esp_camera.h"
#include "ov2640_sharpness.h"
const static uint8_t OV2640_SHARPNESS_AUTO[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0x20, 0x20,
@@ -14,7 +13,7 @@ const static uint8_t OV2640_SHARPNESS_AUTO[]=
const static uint8_t OV2640_SHARPNESS_MANUAL[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0x00, 0x20,
@@ -23,7 +22,7 @@ const static uint8_t OV2640_SHARPNESS_MANUAL[]=
const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC0, 0x1F,
@@ -31,7 +30,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL0[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC1, 0x1F,
@@ -39,7 +38,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL1[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC2, 0x1F,
@@ -47,7 +46,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL2[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC4, 0x1F,
@@ -55,7 +54,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL3[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xC8, 0x1F,
@@ -63,7 +62,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL4[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xD0, 0x1F,
@@ -71,7 +70,7 @@ const static uint8_t OV2640_SHARPNESS_LEVEL5[]=
};
const static uint8_t OV2640_SHARPNESS_LEVEL6[]=
{
//reg, val, mask
//reg, val, mask
0xFF, 0x00, 0xFF,
0x92, 0x01, 0xFF,
0x93, 0xDF, 0x1F,
@@ -91,7 +90,6 @@ const static uint8_t *OV2640_SETTING_SHARPNESS[]=
#define OV2640_MAXLEVEL_SHARPNESS 6
static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
{
uint8_t address;
@@ -101,9 +99,9 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
const uint8_t *pdata = ptab;
if (pdata == NULL)
{
{
return -1;
}
}
while (1)
{
@@ -112,9 +110,9 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
mask = *pdata++;
if ((address == 0) && (value == 0) && (mask == 0))
{
{
break;
}
}
sensor->set_reg(sensor, address, mask, value);
}
@@ -122,31 +120,32 @@ static int table_mask_write(sensor_t *sensor, const uint8_t* ptab)
return 0;
}
int ov2640_enable_auto_sharpness(sensor_t *sensor)
{
table_mask_write(sensor, OV2640_SHARPNESS_AUTO);
sensor->status.sharpness = 0;
return 0;
}
int ov2640_set_sharpness(sensor_t *sensor, int sharpness)
{
int sharpness_temp = 0;
int sharpness_temp = 0;
if (sharpness < -3)
{
{
sharpness_temp = -3;
}
}
if (sharpness > OV2640_MAXLEVEL_SHARPNESS - 3)
{
{
sharpness_temp = OV2640_MAXLEVEL_SHARPNESS - 3;
}
}
table_mask_write(sensor, OV2640_SHARPNESS_MANUAL);
table_mask_write(sensor, OV2640_SETTING_SHARPNESS[sharpness_temp + 3]);
sensor->status.sharpness = sharpness;
return 0;
}

View File

@@ -0,0 +1,66 @@
// Workaround - bug in cam library - enable bits are set without using bitwise OR logic -> only latest enable setting is used
// Reference: https://esp32.com/viewtopic.php?f=19&t=14376#p93178
/* The memory structure is as follows for
byte_0 = enable_bits
byte_0->bit0 = enable saturation and hue --> OK
byte_0->bit1 = enable saturation --> OK
byte_0->bit2 = enable brightness and contrast --> OK
byte_0->bit3 = enable green -> blue spitial effect (Antique and blunish and greenish and reddish and b&w) enable
byte_0->bit4 = anable gray -> red spitial effect (Antique and blunish and greenish and reddish and b&w) enable
byte_0->bit5 = remove (UV) in YUV color system
byte_0->bit6 = enable negative
byte_0->bit7 = remove (Y) in YUV color system
byte_1 = saturation1 0-255 --> ?
byte_2 = hue 0-255 --> OK
byte_3 = saturation2 0-255 --> OK
byte_4 = reenter saturation2 in documents --> ?
byte_5 = spital effect green -> blue 0-255 --> ?
byte_6 = spital effect gray -> red 0-255 --> ?
byte_7 = contrast lower byte 0-255 --> OK
byte_8 = contrast higher byte 0-255 --> OK
byte_9 = brightness 0-255 --> OK
byte_10 = if byte_10==4 contrast effective --> ?
*/
#include <stdint.h>
#include "esp_camera.h"
#include "ov2640_specialEffect.h"
static const uint8_t special_effects_regs[8][5] = {
{0x7C, 0x7D, 0x7C, 0x7D, 0x7D},
{0x00, 0X00, 0x05, 0X80, 0X80}, /* no effect */
{0x00, 0X40, 0x05, 0X80, 0X80}, /* negative */
{0x00, 0X18, 0x05, 0X80, 0X80}, /* black and white */
{0x00, 0X18, 0x05, 0X40, 0XC0}, /* reddish */
{0x00, 0X18, 0x05, 0X40, 0X40}, /* greenish */
{0x00, 0X18, 0x05, 0XA0, 0X40}, /* blue */
{0x00, 0X18, 0x05, 0X40, 0XA6}, /* retro */
};
int ov2640_set_special_effect(sensor_t *sensor, int effect)
{
int ret = 0;
effect++;
if (effect <= 0 || effect > 7)
{
effect = 1;
}
sensor->status.special_effect = effect - 1;
int registerValue = 0x06; // enable saturation, contrast, brightness
registerValue |= special_effects_regs[effect][1];
// sensor->set_reg(sensor, int reg, int mask, int value)
sensor->set_reg(sensor, 0xFF, 0x01, 0x00); // Select DSP bank
sensor->set_reg(sensor, special_effects_regs[0][0], 0xFF, 0x00);
sensor->set_reg(sensor, special_effects_regs[0][1], 0x5E, registerValue);
for (int i = 2; i < 5; i++)
{
sensor->set_reg(sensor, special_effects_regs[0][i], 0xFF, special_effects_regs[effect][i]);
}
return ret;
}

View File

@@ -0,0 +1,10 @@
#pragma once
#ifndef OV2640_SPECIALEFFECT_H
#define OV2640_SPECIALEFFECT_H
#include "esp_camera.h"
int ov2640_set_special_effect(sensor_t *sensor, int effect);
#endif

View File

@@ -10,6 +10,8 @@
#include "ClassLogFile.h"
#include "esp_log.h"
#include "basic_auth.h"
#include "../../include/defines.h"
static const char *TAG = "server_cam";
@@ -101,6 +103,7 @@ esp_err_t handler_capture(httpd_req_t *req)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize, CCstatus.ImageVflip);
Camera.LedIntensity = CCstatus.ImageLedIntensity;
CFstatus.changedCameraSettings = false;
}
@@ -159,6 +162,7 @@ esp_err_t handler_capture_with_light(httpd_req_t *req)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize, CCstatus.ImageVflip);
Camera.LedIntensity = CCstatus.ImageLedIntensity;
CFstatus.changedCameraSettings = false;
}
@@ -241,6 +245,7 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize, CCstatus.ImageVflip);
Camera.LedIntensity = CCstatus.ImageLedIntensity;
CFstatus.changedCameraSettings = false;
}
@@ -277,27 +282,27 @@ void register_server_camera_uri(httpd_handle_t server)
camuri.method = HTTP_GET;
camuri.uri = "/lighton";
camuri.handler = handler_lightOn;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_lightOn);
camuri.user_ctx = (void *)"Light On";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/lightoff";
camuri.handler = handler_lightOff;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_lightOff);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture";
camuri.handler = handler_capture;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture);
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/capture_with_flashlight";
camuri.handler = handler_capture_with_light;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture_with_light);
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/save";
camuri.handler = handler_capture_save_to_file;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_capture_save_to_file);
camuri.user_ctx = NULL;
httpd_register_uri_handler(server, &camuri);
}

View File

@@ -46,6 +46,7 @@ extern "C" {
#include "Helper.h"
#include "miniz.h"
#include "basic_auth.h"
static const char *TAG = "OTA FILE";
@@ -1174,7 +1175,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_download = {
.uri = "/fileserver*", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = download_get_handler,
.handler = APPLY_BASIC_AUTH_FILTER(download_get_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_download);
@@ -1183,7 +1184,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_datafileact = {
.uri = "/datafileact", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = datafileact_get_full_handler,
.handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_full_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_datafileact);
@@ -1192,7 +1193,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_datafile_last_part_handle = {
.uri = "/data", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = datafileact_get_last_part_handler,
.handler = APPLY_BASIC_AUTH_FILTER(datafileact_get_last_part_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_datafile_last_part_handle);
@@ -1200,7 +1201,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_logfileact = {
.uri = "/logfileact", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = logfileact_get_full_handler,
.handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_full_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_logfileact);
@@ -1209,7 +1210,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_logfile_last_part_handle = {
.uri = "/log", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = logfileact_get_last_part_handler,
.handler = APPLY_BASIC_AUTH_FILTER(logfileact_get_last_part_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_logfile_last_part_handle);
@@ -1219,7 +1220,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_upload = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handler,
.handler = APPLY_BASIC_AUTH_FILTER(upload_post_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_upload);
@@ -1228,7 +1229,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t file_delete = {
.uri = "/delete/*", // Match all URIs of type /delete/path/to/file
.method = HTTP_POST,
.handler = delete_post_handler,
.handler = APPLY_BASIC_AUTH_FILTER(delete_post_handler),
.user_ctx = server_data // Pass server data as context
};
httpd_register_uri_handler(server, &file_delete);

View File

@@ -42,6 +42,7 @@ https://docs.espressif.com/projects/esp-idf/en/latest/esp32/migration-guides/rel
#include "Helper.h"
#include "statusled.h"
#include "basic_auth.h"
#include "../../include/defines.h"
/*an ota data write buffer ready to write to the flash*/
@@ -690,13 +691,13 @@ void register_server_ota_sdcard_uri(httpd_handle_t server)
httpd_uri_t camuri = { };
camuri.method = HTTP_GET;
camuri.uri = "/ota";
camuri.handler = handler_ota_update;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_ota_update);
camuri.user_ctx = (void*) "Do OTA";
httpd_register_uri_handler(server, &camuri);
camuri.method = HTTP_GET;
camuri.uri = "/reboot";
camuri.handler = handler_reboot;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_reboot);
camuri.user_ctx = (void*) "Reboot";
httpd_register_uri_handler(server, &camuri);

View File

@@ -65,11 +65,11 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
if (CNNType == Digit) {
for (int i = 0; i < GENERAL[_analog]->ROI.size(); ++i) {
if (GENERAL[_analog]->ROI[i]->result_klasse >= 10) {
result = result + "N";
if ((GENERAL[_analog]->ROI[i]->result_klasse >= 0) && (GENERAL[_analog]->ROI[i]->result_klasse < 10)) {
result = result + std::to_string(GENERAL[_analog]->ROI[i]->result_klasse);
}
else {
result = result + std::to_string(GENERAL[_analog]->ROI[i]->result_klasse);
result = result + "N";
}
}
return result;
@@ -78,7 +78,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
if ((CNNType == DoubleHyprid10) || (CNNType == Digit100)) {
float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
// NaN?
if (number >= 0) {
if ((number >= 0) && (number < 10)) {
// is only set if it is the first digit (no analogue before!)
if (_extendedResolution) {
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
@@ -95,8 +95,15 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
else {
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));
// is necessary because a number greater than 9.994999 returns a 10! (for further details see check in PointerEvalHybridNew)
if ((prev >= 0) && (prev < 10)) {
result = std::to_string(prev);
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100) prev=" + std::to_string(prev));
}
else {
result = "N";
}
}
}
else {
@@ -107,7 +114,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
}
for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i) {
if (GENERAL[_analog]->ROI[i]->result_float >= 0) {
if ((GENERAL[_analog]->ROI[i]->result_float >= 0) && (GENERAL[_analog]->ROI[i]->result_float < 10)) {
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;
@@ -117,7 +124,6 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
prev = -1;
result = "N" + result;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(result_float<0 /'N') result_float=" + std::to_string(GENERAL[_analog]->ROI[i]->result_float));
}
}
return result;
@@ -150,6 +156,9 @@ int ClassFlowCNNGeneral::PointerEvalHybridNew(float number, float number_of_pred
// on first digit is no spezial logic for transition needed
// we use the recognition as given. The result is the int value of the recognition
// add precisition of 2 digits and round before trunc
// a number greater than 9.994999 is returned as 10, this leads to an error during the decimal shift because the NUMBERS[j]->ReturnRawValue is one digit longer.
// To avoid this, an additional test must be carried out, see "if ((CNNType == DoubleHyprid10) || (CNNType == Digit100))" check in getReadout()
// Another alternative would be "result = (int) ((int) trunc(round((number+10 % 10)*1000))) / 1000;", which could, however, lead to other errors?
result = (int) ((int) trunc(round((number+10 % 10)*100)) ) / 100;
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - No predecessor - Result = " + std::to_string(result) +

View File

@@ -26,6 +26,7 @@ extern "C" {
#include "server_help.h"
#include "MainFlowControl.h"
#include "basic_auth.h"
#include "../../include/defines.h"
static const char* TAG = "FLOWCTRL";
@@ -196,7 +197,7 @@ bool ClassFlowControll::StartMQTTService()
void ClassFlowControll::SetInitialParameter(void)
{
AutoStart = false;
AutoStart = true;
SetupModeActive = false;
AutoInterval = 10; // Minutes
flowdigit = NULL;
@@ -210,7 +211,8 @@ void ClassFlowControll::SetInitialParameter(void)
bool ClassFlowControll::getIsAutoStart(void)
{
return AutoStart;
//return AutoStart;
return true; // Flow must always be enabled, else the manual trigger (REST, MQTT) will not work!
}
@@ -557,10 +559,6 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph)) {
splitted = ZerlegeZeile(aktparamgraph, " =");
if ((toUpper(splitted[0]) == "AUTOSTART") && (splitted.size() > 1)) {
AutoStart = alphanumericToBoolean(splitted[1]);
}
if ((toUpper(splitted[0]) == "INTERVAL") && (splitted.size() > 1)) {
if (isStringNumeric(splitted[1]))

View File

@@ -66,6 +66,8 @@ struct NumberPost {
float AnalogToDigitTransitionStart; // AnalogToDigitTransitionStartValue; FIXME: need a better description; When is the digit > x.1, i.e. when does it start to tilt?
int Nachkomma; // decimalPlaces; usually defined by the number of analog ROIs; affected by DecimalShift
string DomoticzIdx; // Domoticz counter Idx
string FieldV1; // influxdbFieldName_v1; Name of the Field in InfluxDBv1
string MeasurementV1; // influxdbMeasurementName_v1; Name of the Measurement in InfluxDBv1

View File

@@ -51,6 +51,7 @@ void ClassFlowMQTT::SetInitialParameter(void)
ListFlowControll = NULL;
disabled = false;
keepAlive = 25*60;
domoticzintopic = "";
}
ClassFlowMQTT::ClassFlowMQTT()
@@ -105,43 +106,44 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
{
splitted = ZerlegeZeile(aktparamgraph);
if ((toUpper(splitted[0]) == "CACERT") && (splitted.size() > 1))
std::string _param = GetParameterName(splitted[0]);
if ((toUpper(_param) == "CACERT") && (splitted.size() > 1))
{
this->caCertFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "CLIENTCERT") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTCERT") && (splitted.size() > 1))
{
this->clientCertFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "CLIENTKEY") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTKEY") && (splitted.size() > 1))
{
this->clientKeyFilename = splitted[1];
}
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
if ((toUpper(_param) == "USER") && (splitted.size() > 1))
{
this->user = splitted[1];
}
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
if ((toUpper(_param) == "PASSWORD") && (splitted.size() > 1))
{
this->password = splitted[1];
}
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
if ((toUpper(_param) == "URI") && (splitted.size() > 1))
{
this->uri = splitted[1];
}
if ((toUpper(splitted[0]) == "RETAINMESSAGES") && (splitted.size() > 1))
if ((toUpper(_param) == "RETAINMESSAGES") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE") {
SetRetainFlag = true;
setMqtt_Server_Retain(SetRetainFlag);
}
}
if ((toUpper(splitted[0]) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
if ((toUpper(_param) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
{
if (toUpper(splitted[1]) == "TRUE")
SetHomeassistantDiscoveryEnabled(true);
}
if ((toUpper(splitted[0]) == "METERTYPE") && (splitted.size() > 1)) {
if ((toUpper(_param) == "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(splitted[1]) == "WATER_M3") {
@@ -151,7 +153,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
mqttServer_setMeterType("water", "L", "h", "L/h");
}
else if (toUpper(splitted[1]) == "WATER_FT3") {
mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // Minutes
mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // m = Minutes
}
else if (toUpper(splitted[1]) == "WATER_GAL") {
mqttServer_setMeterType("water", "gal", "h", "gal/h");
@@ -160,7 +162,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
mqttServer_setMeterType("gas", "", "h", "m³/h");
}
else if (toUpper(splitted[1]) == "GAS_FT3") {
mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // Minutes
mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // m = Minutes
}
else if (toUpper(splitted[1]) == "ENERGY_WH") {
mqttServer_setMeterType("energy", "Wh", "h", "W");
@@ -176,15 +178,26 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
}
}
if ((toUpper(splitted[0]) == "CLIENTID") && (splitted.size() > 1))
if ((toUpper(_param) == "CLIENTID") && (splitted.size() > 1))
{
this->clientname = splitted[1];
}
if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
if (((toUpper(_param) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
{
maintopic = splitted[1];
}
if (((toUpper(_param) == "DOMOTICZTOPICIN")) && (splitted.size() > 1))
{
this->domoticzintopic = splitted[1];
}
if (((toUpper(_param) == "DOMOTICZIDX")) && (splitted.size() > 1))
{
handleIdx(splitted[0], splitted[1]);
}
}
/* Note:
@@ -193,6 +206,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
* To work around this, we delay the start and trigger it from ClassFlowControll::ReadParameter() */
mqttServer_setMainTopic(maintopic);
mqttServer_setDmoticzInTopic(domoticzintopic);
return true;
}
@@ -210,7 +224,7 @@ bool ClassFlowMQTT::Start(float AutoInterval)
mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval);
bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, LWT_TOPIC, LWT_CONNECTED,
bool MQTTConfigCheck = MQTT_Configure(uri, clientname, user, password, maintopic, domoticzintopic, LWT_TOPIC, LWT_CONNECTED,
LWT_DISCONNECTED, caCertFilename, clientCertFilename, clientKeyFilename,
keepAlive, SetRetainFlag, (void *)&GotConnected);
@@ -235,6 +249,8 @@ bool ClassFlowMQTT::doFlow(string zwtime)
std::string resultchangabs = "";
string zw = "";
string namenumber = "";
string domoticzpayload = "";
string DomoticzIdx = "";
int qos = 1;
/* Send the the Homeassistant Discovery and the Static Topics in case they where scheduled */
@@ -258,16 +274,20 @@ bool ClassFlowMQTT::doFlow(string zwtime)
resultchangabs = (*NUMBERS)[i]->ReturnChangeAbsolute; // Units per round
resulttimestamp = (*NUMBERS)[i]->timeStamp;
DomoticzIdx = (*NUMBERS)[i]->DomoticzIdx;
domoticzpayload = "{\"command\":\"udevice\",\"idx\":" + DomoticzIdx + ",\"svalue\":\""+ result + "\"}";
namenumber = (*NUMBERS)[i]->name;
if (namenumber == "default")
namenumber = maintopic + "/";
else
namenumber = maintopic + "/" + namenumber + "/";
if ((domoticzintopic.length() > 0) && (result.length() > 0))
success |= MQTTPublish(domoticzintopic, domoticzpayload, qos, SetRetainFlag);
if (result.length() > 0)
if (result.length() > 0)
success |= MQTTPublish(namenumber + "value", result, qos, SetRetainFlag);
if (resulterror.length() > 0)
success |= MQTTPublish(namenumber + "error", resulterror, qos, SetRetainFlag);
@@ -286,7 +306,7 @@ bool ClassFlowMQTT::doFlow(string zwtime)
if (resultchangabs.length() > 0) {
success |= MQTTPublish(namenumber + "changeabsolut", resultchangabs, qos, SetRetainFlag); // Legacy API
success |= MQTTPublish(namenumber + "rate_per_Digitization_round", resultchangabs, qos, SetRetainFlag);
success |= MQTTPublish(namenumber + "rate_per_digitization_round", resultchangabs, qos, SetRetainFlag);
}
if (resultraw.length() > 0)
@@ -325,6 +345,26 @@ bool ClassFlowMQTT::doFlow(string zwtime)
return true;
}
void ClassFlowMQTT::handleIdx(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 < flowpostprocessing->NUMBERS.size(); ++j)
{
if (_digit == "default") // Set to default first (if nothing else is set)
{
flowpostprocessing->NUMBERS[j]->DomoticzIdx = _value;
}
if (flowpostprocessing->NUMBERS[j]->name == _digit)
{
flowpostprocessing->NUMBERS[j]->DomoticzIdx = _value;
}
}
}
#endif //ENABLE_MQTT

View File

@@ -23,9 +23,9 @@ protected:
bool SetRetainFlag;
int keepAlive; // Seconds
float roundInterval; // Minutes
std::string maintopic;
std::string maintopic, domoticzintopic;
void SetInitialParameter(void);
void handleIdx(string _decsep, string _value);
public:
ClassFlowMQTT();

View File

@@ -564,7 +564,7 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
handleDecimalSeparator(splitted[0], splitted[1]);
}
if ((toUpper(_param) == "AnalogToDigitTransitionStart") && (splitted.size() > 1)) {
if ((toUpper(_param) == "ANALOGTODIGITTRANSITIONSTART") && (splitted.size() > 1)) {
handleAnalogToDigitTransitionStart(splitted[0], splitted[1]);
}

View File

@@ -499,8 +499,8 @@ bool ClassFlowTakeImage::ReadParameter(FILE *pfile, string &aktparamgraph)
{
if (isStringNumeric(splitted[1]))
{
float ledintensity = std::stof(splitted[1]);
Camera.SetLEDIntensity(ledintensity);
int ledintensity = std::stoi(splitted[1]);
CCstatus.ImageLedIntensity = Camera.SetLEDIntensity(ledintensity);
}
}
@@ -559,6 +559,7 @@ bool ClassFlowTakeImage::doFlow(string zwtime)
{
Camera.setSensorDatenFromCCstatus(); // CCstatus >>> Kamera
Camera.SetQualityZoomSize(CCstatus.ImageQuality, CCstatus.ImageFrameSize, CCstatus.ImageZoomEnabled, CCstatus.ImageZoomOffsetX, CCstatus.ImageZoomOffsetY, CCstatus.ImageZoomSize, CCstatus.ImageVflip);
Camera.LedIntensity = CCstatus.ImageLedIntensity;
CFstatus.changedCameraSettings = false;
}

View File

@@ -27,6 +27,7 @@
#include "read_wlanini.h"
#include "connect_wlan.h"
#include "psram.h"
#include "basic_auth.h"
// support IDF 5.x
#ifndef portTICK_RATE_MS
@@ -148,31 +149,39 @@ esp_err_t setCCstatusToCFstatus(void)
CFstatus.CamSensor_id = CCstatus.CamSensor_id;
CFstatus.ImageFrameSize = CCstatus.ImageFrameSize;
CFstatus.ImageGainceiling = CCstatus.ImageGainceiling;
CFstatus.ImageContrast = CCstatus.ImageContrast;
CFstatus.ImageBrightness = CCstatus.ImageBrightness;
CFstatus.ImageSaturation = CCstatus.ImageSaturation;
CFstatus.ImageQuality = CCstatus.ImageQuality;
CFstatus.ImageBrightness = CCstatus.ImageBrightness;
CFstatus.ImageContrast = CCstatus.ImageContrast;
CFstatus.ImageSaturation = CCstatus.ImageSaturation;
CFstatus.ImageSharpness = CCstatus.ImageSharpness;
CFstatus.ImageAutoSharpness = CCstatus.ImageAutoSharpness;
CFstatus.ImageWbMode = CCstatus.ImageWbMode;
CFstatus.ImageAwb = CCstatus.ImageAwb;
CFstatus.ImageAwbGain = CCstatus.ImageAwbGain;
CFstatus.ImageAec = CCstatus.ImageAec;
CFstatus.ImageAec2 = CCstatus.ImageAec2;
CFstatus.ImageAeLevel = CCstatus.ImageAeLevel;
CFstatus.ImageAecValue = CCstatus.ImageAecValue;
CFstatus.ImageGainceiling = CCstatus.ImageGainceiling;
CFstatus.ImageAgc = CCstatus.ImageAgc;
CFstatus.ImageAgcGain = CCstatus.ImageAgcGain;
CFstatus.ImageBpc = CCstatus.ImageBpc;
CFstatus.ImageWpc = CCstatus.ImageWpc;
CFstatus.ImageRawGma = CCstatus.ImageRawGma;
CFstatus.ImageLenc = CCstatus.ImageLenc;
CFstatus.ImageSpecialEffect = CCstatus.ImageSpecialEffect;
CFstatus.ImageAec = CCstatus.ImageAec;
CFstatus.ImageHmirror = CCstatus.ImageHmirror;
CFstatus.ImageVflip = CCstatus.ImageVflip;
CFstatus.ImageAwb = CCstatus.ImageAwb;
CFstatus.ImageAec2 = CCstatus.ImageAec2;
CFstatus.ImageAecValue = CCstatus.ImageAecValue;
CFstatus.ImageSpecialEffect = CCstatus.ImageSpecialEffect;
CFstatus.ImageWbMode = CCstatus.ImageWbMode;
CFstatus.ImageAeLevel = CCstatus.ImageAeLevel;
CFstatus.ImageDcw = CCstatus.ImageDcw;
CFstatus.ImageBpc = CCstatus.ImageBpc;
CFstatus.ImageWpc = CCstatus.ImageWpc;
CFstatus.ImageAwbGain = CCstatus.ImageAwbGain;
CFstatus.ImageAgcGain = CCstatus.ImageAgcGain;
CFstatus.ImageRawGma = CCstatus.ImageRawGma;
CFstatus.ImageLenc = CCstatus.ImageLenc;
CFstatus.ImageSharpness = CCstatus.ImageSharpness;
CFstatus.ImageAutoSharpness = CCstatus.ImageAutoSharpness;
CFstatus.ImageDenoiseLevel = CCstatus.ImageDenoiseLevel;
CFstatus.ImageLedIntensity = CCstatus.ImageLedIntensity;
@@ -192,31 +201,39 @@ esp_err_t setCFstatusToCCstatus(void)
// CCstatus.CamSensor_id = CFstatus.CamSensor_id;
CCstatus.ImageFrameSize = CFstatus.ImageFrameSize;
CCstatus.ImageGainceiling = CFstatus.ImageGainceiling;
CCstatus.ImageContrast = CFstatus.ImageContrast;
CCstatus.ImageBrightness = CFstatus.ImageBrightness;
CCstatus.ImageSaturation = CFstatus.ImageSaturation;
CCstatus.ImageQuality = CFstatus.ImageQuality;
CCstatus.ImageBrightness = CFstatus.ImageBrightness;
CCstatus.ImageContrast = CFstatus.ImageContrast;
CCstatus.ImageSaturation = CFstatus.ImageSaturation;
CCstatus.ImageSharpness = CFstatus.ImageSharpness;
CCstatus.ImageAutoSharpness = CFstatus.ImageAutoSharpness;
CCstatus.ImageWbMode = CFstatus.ImageWbMode;
CCstatus.ImageAwb = CFstatus.ImageAwb;
CCstatus.ImageAwbGain = CFstatus.ImageAwbGain;
CCstatus.ImageAec = CFstatus.ImageAec;
CCstatus.ImageAec2 = CFstatus.ImageAec2;
CCstatus.ImageAeLevel = CFstatus.ImageAeLevel;
CCstatus.ImageAecValue = CFstatus.ImageAecValue;
CCstatus.ImageGainceiling = CFstatus.ImageGainceiling;
CCstatus.ImageAgc = CFstatus.ImageAgc;
CCstatus.ImageAgcGain = CFstatus.ImageAgcGain;
CCstatus.ImageBpc = CFstatus.ImageBpc;
CCstatus.ImageWpc = CFstatus.ImageWpc;
CCstatus.ImageRawGma = CFstatus.ImageRawGma;
CCstatus.ImageLenc = CFstatus.ImageLenc;
CCstatus.ImageSpecialEffect = CFstatus.ImageSpecialEffect;
CCstatus.ImageAec = CFstatus.ImageAec;
CCstatus.ImageHmirror = CFstatus.ImageHmirror;
CCstatus.ImageVflip = CFstatus.ImageVflip;
CCstatus.ImageAwb = CFstatus.ImageAwb;
CCstatus.ImageAec2 = CFstatus.ImageAec2;
CCstatus.ImageAecValue = CFstatus.ImageAecValue;
CCstatus.ImageSpecialEffect = CFstatus.ImageSpecialEffect;
CCstatus.ImageWbMode = CFstatus.ImageWbMode;
CCstatus.ImageAeLevel = CFstatus.ImageAeLevel;
CCstatus.ImageDcw = CFstatus.ImageDcw;
CCstatus.ImageBpc = CFstatus.ImageBpc;
CCstatus.ImageWpc = CFstatus.ImageWpc;
CCstatus.ImageAwbGain = CFstatus.ImageAwbGain;
CCstatus.ImageAgcGain = CFstatus.ImageAgcGain;
CCstatus.ImageRawGma = CFstatus.ImageRawGma;
CCstatus.ImageLenc = CFstatus.ImageLenc;
CCstatus.ImageSharpness = CFstatus.ImageSharpness;
CCstatus.ImageAutoSharpness = CFstatus.ImageAutoSharpness;
CCstatus.ImageDenoiseLevel = CFstatus.ImageDenoiseLevel;
CCstatus.ImageLedIntensity = CFstatus.ImageLedIntensity;
@@ -238,43 +255,43 @@ esp_err_t setCFstatusToCam(void)
if (s != NULL)
{
s->set_framesize(s, CFstatus.ImageFrameSize);
// s->set_contrast(s, CFstatus.ImageContrast); // -2 to 2
// s->set_brightness(s, CFstatus.ImageBrightness); // -2 to 2
Camera.SetCamContrastBrightness(s, CFstatus.ImageContrast, CFstatus.ImageBrightness);
s->set_saturation(s, CFstatus.ImageSaturation); // -2 to 2
s->set_quality(s, CFstatus.ImageQuality); // 0 - 63
s->set_brightness(s, CFstatus.ImageBrightness); // -2 to 2
s->set_contrast(s, CFstatus.ImageContrast); // -2 to 2
s->set_saturation(s, CFstatus.ImageSaturation); // -2 to 2
// s->set_sharpness(s, CFstatus.ImageSharpness); // auto-sharpness is not officially supported, default to 0
Camera.SetCamSharpness(CFstatus.ImageAutoSharpness, CFstatus.ImageSharpness);
s->set_denoise(s, CFstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
s->set_special_effect(s, CFstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
s->set_wb_mode(s, CFstatus.ImageWbMode); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_ae_level(s, CFstatus.ImageAeLevel); // -2 to 2
s->set_aec_value(s, CFstatus.ImageAecValue); // 0 to 1200
s->set_agc_gain(s, CFstatus.ImageAgcGain); // 0 to 30
// s->set_gainceiling(s, CFstatus.ImageGainceiling); // Image gain (GAINCEILING_x2, x4, x8, x16, x32, x64 or x128)
Camera.ov5640_set_gainceiling(s, CFstatus.ImageGainceiling);
Camera.SetCamGainceiling(s, CFstatus.ImageGainceiling);
s->set_lenc(s, CFstatus.ImageLenc); // 0 = disable , 1 = enable
s->set_gain_ctrl(s, CFstatus.ImageAgc); // 0 = disable , 1 = enable
s->set_exposure_ctrl(s, CFstatus.ImageAec); // 0 = disable , 1 = enable
s->set_hmirror(s, CFstatus.ImageHmirror); // 0 = disable , 1 = enable
s->set_vflip(s, CFstatus.ImageVflip); // 0 = disable , 1 = enable
s->set_hmirror(s, CFstatus.ImageHmirror); // 0 = disable , 1 = enable
s->set_vflip(s, CFstatus.ImageVflip); // 0 = disable , 1 = enable
s->set_aec2(s, CFstatus.ImageAec2); // 0 = disable , 1 = enable
s->set_whitebal(s, CFstatus.ImageAwb); // 0 = disable , 1 = enable
s->set_aec2(s, CFstatus.ImageAec2); // 0 = disable , 1 = enable
s->set_aec_value(s, CFstatus.ImageAecValue); // 0 to 1200
// s->set_special_effect(s, CFstatus.ImageSpecialEffect); // 0 to 6 (0 - No Effect, 1 - Negative, 2 - Grayscale, 3 - Red Tint, 4 - Green Tint, 5 - Blue Tint, 6 - Sepia)
Camera.SetCamSpecialEffect(s, CFstatus.ImageSpecialEffect);
s->set_wb_mode(s, CFstatus.ImageWbMode); // 0 to 4 - if awb_gain enabled (0 - Auto, 1 - Sunny, 2 - Cloudy, 3 - Office, 4 - Home)
s->set_ae_level(s, CFstatus.ImageAeLevel); // -2 to 2
s->set_bpc(s, CFstatus.ImageBpc); // 0 = disable , 1 = enable
s->set_wpc(s, CFstatus.ImageWpc); // 0 = disable , 1 = enable
s->set_dcw(s, CFstatus.ImageDcw); // 0 = disable , 1 = enable
s->set_bpc(s, CFstatus.ImageBpc); // 0 = disable , 1 = enable
s->set_wpc(s, CFstatus.ImageWpc); // 0 = disable , 1 = enable
s->set_awb_gain(s, CFstatus.ImageAwbGain); // 0 = disable , 1 = enable
s->set_agc_gain(s, CFstatus.ImageAgcGain); // 0 to 30
s->set_raw_gma(s, CFstatus.ImageRawGma); // 0 = disable , 1 = enable
s->set_lenc(s, CFstatus.ImageLenc); // 0 = disable , 1 = enable
s->set_awb_gain(s, CFstatus.ImageAwbGain); // 0 = disable , 1 = enable
s->set_whitebal(s, CFstatus.ImageAwb); // 0 = disable , 1 = enable
s->set_dcw(s, CFstatus.ImageDcw); // 0 = disable , 1 = enable
// s->set_sharpness(s, CFstatus.ImageSharpness); // auto-sharpness is not officially supported, default to 0
Camera.SetCamSharpness(CFstatus.ImageAutoSharpness, CFstatus.ImageSharpness);
s->set_denoise(s, CFstatus.ImageDenoiseLevel); // The OV2640 does not support it, OV3660 and OV5640 (0 to 8)
TickType_t xDelay2 = 100 / portTICK_PERIOD_MS;
vTaskDelay(xDelay2);
@@ -406,8 +423,7 @@ esp_err_t handler_flow_start(httpd_req_t *req)
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);
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Flow start triggered by REST API, but flow is not active");
}
#ifdef DEBUG_DETAIL_ON
@@ -1348,9 +1364,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
std::string _ledi = std::string(_valuechar);
if (isStringNumeric(_ledi))
{
float _ImageLedIntensity = std::stof(_valuechar);
Camera.SetLEDIntensity(_ImageLedIntensity);
CFstatus.ImageLedIntensity = CCstatus.ImageLedIntensity;
int _ImageLedIntensity = std::stoi(_valuechar);
CFstatus.ImageLedIntensity = Camera.SetLEDIntensity(_ImageLedIntensity);
}
}
@@ -1487,6 +1502,28 @@ esp_err_t handler_rssi(httpd_req_t *req)
return ESP_OK;
}
esp_err_t handler_current_date(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_uptime - Start");
#endif
std::string formatedDateAndTime = getCurrentTimeString("%Y-%m-%d %H:%M:%S");
// std::string formatedDate = getCurrentTimeString("%Y-%m-%d");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
httpd_resp_send(req, formatedDateAndTime.c_str(), formatedDateAndTime.length());
/* Respond with an empty chunk to signal HTTP response completion */
httpd_resp_sendstr_chunk(req, NULL);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("handler_uptime - End");
#endif
return ESP_OK;
}
esp_err_t handler_uptime(httpd_req_t *req)
{
#ifdef DEBUG_DETAIL_ON
@@ -1746,103 +1783,108 @@ void register_server_main_flow_task_uri(httpd_handle_t server)
camuri.method = HTTP_GET;
camuri.uri = "/doinit";
camuri.handler = handler_init;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_init);
camuri.user_ctx = (void *)"Light On";
httpd_register_uri_handler(server, &camuri);
// Legacy API => New: "/setPreValue"
camuri.uri = "/setPreValue.html";
camuri.handler = handler_prevalue;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_prevalue);
camuri.user_ctx = (void *)"Prevalue";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/setPreValue";
camuri.handler = handler_prevalue;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_prevalue);
camuri.user_ctx = (void *)"Prevalue";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/flow_start";
camuri.handler = handler_flow_start;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_flow_start);
camuri.user_ctx = (void *)"Flow Start";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/statusflow.html";
camuri.handler = handler_statusflow;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_statusflow);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/statusflow";
camuri.handler = handler_statusflow;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_statusflow);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
// Legacy API => New: "/cpu_temperature"
camuri.uri = "/cputemp.html";
camuri.handler = handler_cputemp;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_cputemp);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/cpu_temperature";
camuri.handler = handler_cputemp;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_cputemp);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
// Legacy API => New: "/rssi"
camuri.uri = "/rssi.html";
camuri.handler = handler_rssi;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_rssi);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/rssi";
camuri.handler = handler_rssi;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_rssi);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/date";
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_current_date);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/uptime";
camuri.handler = handler_uptime;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_uptime);
camuri.user_ctx = (void *)"Light Off";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/editflow";
camuri.handler = handler_editflow;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_editflow);
camuri.user_ctx = (void *)"EditFlow";
httpd_register_uri_handler(server, &camuri);
// Legacy API => New: "/value"
camuri.uri = "/value.html";
camuri.handler = handler_wasserzaehler;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler);
camuri.user_ctx = (void *)"Value";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/value";
camuri.handler = handler_wasserzaehler;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler);
camuri.user_ctx = (void *)"Value";
httpd_register_uri_handler(server, &camuri);
// Legacy API => New: "/value"
camuri.uri = "/wasserzaehler.html";
camuri.handler = handler_wasserzaehler;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_wasserzaehler);
camuri.user_ctx = (void *)"Wasserzaehler";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/json";
camuri.handler = handler_json;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_json);
camuri.user_ctx = (void *)"JSON";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/heap";
camuri.handler = handler_get_heap;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_get_heap);
camuri.user_ctx = (void *)"Heap";
httpd_register_uri_handler(server, &camuri);
camuri.uri = "/stream";
camuri.handler = handler_stream;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_stream);
camuri.user_ctx = (void *)"stream";
httpd_register_uri_handler(server, &camuri);
/** will handle metrics requests */
camuri.uri = "/metrics";
camuri.handler = handler_openmetrics;
camuri.handler = APPLY_BASIC_AUTH_FILTER(handler_openmetrics);
camuri.user_ctx = (void *)"metrics";
httpd_register_uri_handler(server, &camuri);

View File

@@ -40,6 +40,7 @@ string toUpper(string in);
float temperatureRead();
std::string intToHexString(int _valueInt);
time_t addDays(time_t startTime, int days);
void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);

View File

@@ -34,7 +34,7 @@ bool mqtt_initialized = false;
bool mqtt_connected = false;
esp_mqtt_client_handle_t client = NULL;
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic;
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic, domoticz_in_topic;
std::string caCert, clientCert, clientKey;
int keepalive;
bool SetRetainFlag;
@@ -205,7 +205,7 @@ static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_
bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool _SetRetainFlag, void *_callbackOnConnected) {
if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0))
@@ -222,6 +222,7 @@ bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
keepalive = _keepalive;
SetRetainFlag = _SetRetainFlag;
maintopic = _maintopic;
domoticz_in_topic = _domoticz_in_topic;
callbackOnConnected = ( void (*)(std::string, bool) )(_callbackOnConnected);
if (_clientcertfilename.length() && _clientkeyfilename.length()){
@@ -388,13 +389,7 @@ 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);
}
else {
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "handler_flow_start: handler called, but no data");
}
MQTTCtrlFlowStart(_topic);
return ESP_OK;
}

View File

@@ -10,7 +10,7 @@
#include <functional>
bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _maintopic, std::string _domoticz_in_topic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
std::string _cacertfilename, std::string _clientcertfilename, std::string _clientkeyfilename,
int _keepalive, bool SetRetainFlag, void *callbackOnConnected);
int MQTT_Init();

View File

@@ -12,6 +12,7 @@
#include "interface_mqtt.h"
#include "time_sntp.h"
#include "../../include/defines.h"
#include "basic_auth.h"
@@ -32,10 +33,11 @@ std::string rateUnit = "Unit/Minute";
float roundInterval; // Minutes
int keepAlive = 0; // Seconds
bool retainFlag;
static std::string maintopic;
static std::string maintopic, domoticzintopic;
bool sendingOf_DiscoveryAndStaticTopics_scheduled = true; // Set it to true to make sure it gets sent at least once after startup
void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int _keepAlive, float _roundInterval) {
NUMBERS = _NUMBERS;
keepAlive = _keepAlive;
@@ -85,9 +87,12 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
* This means a maintopic "home/test/watermeter" is transformed to the discovery topic "homeassistant/sensor/watermeter/..."
*/
std::string node_id = createNodeId(maintopic);
if (field == "problem") { // Special binary sensor which is based on error topic
if (field == "problem") { // Special case: Binary sensor which is based on error topic
topicFull = "homeassistant/binary_sensor/" + node_id + "/" + configTopic + "/config";
}
else if (field == "flowstart") { // Special case: Button
topicFull = "homeassistant/button/" + node_id + "/" + configTopic + "/config";
}
else {
topicFull = "homeassistant/sensor/" + node_id + "/" + configTopic + "/config";
}
@@ -101,7 +106,7 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
"\"icon\": \"mdi:" + icon + "\",";
if (group != "") {
if (field == "problem") { // Special binary sensor which is based on error topic
if (field == "problem") { // Special case: Binary sensor which is based on error topic
payload += "\"state_topic\": \"~/" + group + "/error\",";
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
}
@@ -110,10 +115,13 @@ bool sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
}
}
else {
if (field == "problem") { // Special binary sensor which is based on error topic
if (field == "problem") { // Special case: Binary sensor which is based on error topic
payload += "\"state_topic\": \"~/error\",";
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
}
else if (field == "flowstart") { // Special case: Button
payload += "\"cmd_t\":\"~/ctrl/flow_start\","; // Add command topic
}
else {
payload += "\"state_topic\": \"~/" + field + "\",";
}
@@ -176,6 +184,7 @@ bool MQTThomeassistantDiscovery(int qos) {
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "" , "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "IP", "IP", "network-outline", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "status", "Status", "list-status", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic("", "flowstart", "Manual Flow Start", "timer-play-outline", "", "", "", "", qos);
for (int i = 0; i < (*NUMBERS).size(); ++i) {
@@ -184,14 +193,26 @@ bool MQTThomeassistantDiscovery(int qos) {
group = "";
}
/* If "Allow neg. rate" is true, use "measurement" instead of "total_increasing" for the State Class, see https://github.com/jomjol/AI-on-the-edge-device/issues/3331 */
std::string value_state_class = "total_increasing";
if ((*NUMBERS)[i]->AllowNegativeRates) {
value_state_class = "measurement";
}
/* Energy meters need a different Device Class, see https://github.com/jomjol/AI-on-the-edge-device/issues/3333 */
std::string rate_device_class = "volume_flow_rate";
if (meterType == "energy") {
rate_device_class = "power";
}
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", "", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, value_state_class, "", qos); // State Class = "total_increasing" if <NUMBERS>.AllowNegativeRates = false, else use "measurement"
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, meterType, "measurement", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic", qos);
/* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_Digitization_round */
/* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_digitization_round */
// allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", ""); // Legacy, always Unit per Minute
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, "", "measurement", "", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_Digitization_round", "Change since last Digitization round", "arrow-expand-vertical", valueUnit, "", "measurement", "", qos); // correctly the Unit is Unit/Interval!
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, rate_device_class, "measurement", "", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "rate_per_digitization_round", "Change since last Digitization round", "arrow-expand-vertical", valueUnit, "", "measurement", "", qos); // correctly the Unit is Unit/Interval!
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic", qos);
allSendsSuccessed |= sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", "", qos); // Special binary sensor which is based on error topic
@@ -327,7 +348,7 @@ void register_server_mqtt_uri(httpd_handle_t server) {
uri.method = HTTP_GET;
uri.uri = "/mqtt_publish_discovery";
uri.handler = scheduleSendingDiscovery_and_static_Topics;
uri.handler = APPLY_BASIC_AUTH_FILTER(scheduleSendingDiscovery_and_static_Topics);
uri.user_ctx = (void*) "";
httpd_register_uri_handler(server, &uri);
}
@@ -355,4 +376,9 @@ std::string mqttServer_getMainTopic() {
return maintopic;
}
void mqttServer_setDmoticzInTopic( std::string _domoticzintopic) {
domoticzintopic = _domoticzintopic;
}
#endif //ENABLE_MQTT

View File

@@ -12,6 +12,9 @@ void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int interval, f
void mqttServer_setMeterType(std::string meterType, std::string valueUnit, std::string timeUnit,std::string rateUnit);
void setMqtt_Server_Retain(bool SetRetainFlag);
void mqttServer_setMainTopic( std::string maintopic);
void mqttServer_setDmoticzInTopic( std::string domoticzintopic);
std::string mqttServer_getMainTopic();
void register_server_mqtt_uri(httpd_handle_t server);

View File

@@ -246,9 +246,18 @@ void CTfLiteClass::GetInputTensorSize()
long CTfLiteClass::GetFileSize(std::string filename)
{
struct stat stat_buf;
long rc = stat(filename.c_str(), &stat_buf);
return rc == 0 ? stat_buf.st_size : -1;
struct stat stat_buf;
long rc = -1;
FILE *pFile = fopen(filename.c_str(), "rb"); // previously only "rb
if (pFile != NULL)
{
rc = stat(filename.c_str(), &stat_buf);
fclose(pFile);
}
return rc == 0 ? stat_buf.st_size : -1;
}
@@ -270,25 +279,33 @@ bool CTfLiteClass::ReadFileToModel(std::string _fn)
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Loading Model " + _fn + " /size: " + std::to_string(size) + " bytes...");
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start");
#endif
modelfile = (unsigned char*)psram_get_shared_model_memory();
if(modelfile != NULL)
if (modelfile != NULL)
{
FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r
fread(modelfile, 1, size, f);
fclose(f);
FILE *pFile = fopen(_fn.c_str(), "rb"); // previously only "rb
if (pFile != NULL)
{
fread(modelfile, 1, size, pFile);
fclose(pFile);
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile successful");
#endif
#ifdef DEBUG_DETAIL_ON
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile successful");
#endif
return true;
}
return true;
}
else
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CTfLiteClass::ReadFileToModel: Model does not exist");
return false;
}
}
else
{
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CTfLiteClass::ReadFileToModel: Can't allocate enough memory: " + std::to_string(size));

View File

@@ -0,0 +1,107 @@
#include "basic_auth.h"
#include "read_wlanini.h"
#include <esp_tls_crypto.h>
#include <esp_log.h>
#define HTTPD_401 "401 UNAUTHORIZED"
static const char *TAG = "HTTPAUTH";
typedef struct {
const char *username;
const char *password;
} basic_auth_info_t;
basic_auth_info_t basic_auth_info = { NULL, NULL };
void init_basic_auth() {
if (!wlan_config.http_username.empty() && !wlan_config.http_password.empty()) {
basic_auth_info.username = wlan_config.http_username.c_str();
basic_auth_info.password = wlan_config.http_password.c_str();
}
}
static char *http_auth_basic(const char *username, const char *password)
{
int out;
char *user_info = NULL;
char *digest = NULL;
size_t n = 0;
asprintf(&user_info, "%s:%s", username, password);
if (!user_info) {
ESP_LOGE(TAG, "No enough memory for user information");
return NULL;
}
esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info));
/* 6: The length of the "Basic " string
* n: Number of bytes for a base64 encode format
* 1: Number of bytes for a reserved which be used to fill zero
*/
digest = static_cast<char*>(calloc(1, 6 + n + 1));
if (digest) {
strcpy(digest, "Basic ");
esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info));
}
free(user_info);
return digest;
}
esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler(httpd_req_t *))
{
char *buf = NULL;
size_t buf_len = 0;
esp_err_t ret = ESP_OK;
char unauthorized[] = "You are not authorized to use this website!";
if (basic_auth_info.username == NULL || basic_auth_info.password == NULL) {
ret = original_handler(req);
} else {
buf_len = httpd_req_get_hdr_value_len(req, "Authorization") + 1;
if (buf_len > 1) {
buf = static_cast<char*>(calloc(1, buf_len));
if (!buf) {
ESP_LOGE(TAG, "No enough memory for basic authorization");
return ESP_ERR_NO_MEM;
}
if (httpd_req_get_hdr_value_str(req, "Authorization", buf, buf_len) == ESP_OK) {
ESP_LOGI(TAG, "Found header => Authorization: %s", buf);
} else {
ESP_LOGE(TAG, "No auth value received");
}
char *auth_credentials = http_auth_basic(basic_auth_info.username, basic_auth_info.password);
if (!auth_credentials) {
ESP_LOGE(TAG, "No enough memory for basic authorization credentials");
free(buf);
return ESP_ERR_NO_MEM;
}
if (strncmp(auth_credentials, buf, buf_len)) {
ESP_LOGE(TAG, "Not authenticated");
httpd_resp_set_status(req, HTTPD_401);
httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
httpd_resp_set_hdr(req, "Connection", "keep-alive");
httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\"");
httpd_resp_send(req, unauthorized, strlen(unauthorized));
} else {
ESP_LOGI(TAG, "Authenticated calling http handler now!");
ret=original_handler(req);
}
free(auth_credentials);
free(buf);
} else {
ESP_LOGE(TAG, "No auth header received");
httpd_resp_set_status(req, HTTPD_401);
httpd_resp_set_type(req, HTTPD_TYPE_TEXT);
httpd_resp_set_hdr(req, "Connection", "keep-alive");
httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"AIOTED\"");
httpd_resp_send(req, unauthorized, strlen(unauthorized));
}
}
return ret;
}

View File

@@ -0,0 +1,8 @@
#pragma once
#include <esp_http_server.h>
void init_basic_auth();
esp_err_t basic_auth_request_filter(httpd_req_t *req, esp_err_t original_handler(httpd_req_t *));
#define APPLY_BASIC_AUTH_FILTER(method) [](httpd_req_t *req){ return basic_auth_request_filter(req, method); }

View File

@@ -49,6 +49,9 @@
#define ets_delay_us(a) esp_rom_delay_us(a)
#endif
#include "../../esp-protocols/components/mdns/include/mdns.h"
static const char *TAG = "WIFI";
static bool APWithBetterRSSI = false;
@@ -657,6 +660,14 @@ esp_err_t wifi_init_sta(void)
else {
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Set hostname to: " + wlan_config.hostname);
}
//initialize mDNS service
retval = mdns_init();
if (retval != ESP_OK) {
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "mdns_init failed! Error: " + std::to_string(retval));
} else {
//set mdns hostname
mdns_hostname_set(wlan_config.hostname.c_str());
}
}
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init successful");

View File

@@ -145,6 +145,29 @@ int LoadWlanFromFile(std::string fn)
wlan_config.dns = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "DNS: " + wlan_config.dns);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_USERNAME")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.http_username = tmp;
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_USERNAME: " + wlan_config.http_username);
}
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HTTP_PASSWORD")){
tmp = splitted[1];
if ((tmp[0] == '"') && (tmp[tmp.length()-1] == '"')){
tmp = tmp.substr(1, tmp.length()-2);
}
wlan_config.http_password = tmp;
#ifndef __HIDE_PASSWORD
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: " + wlan_config.http_password);
#else
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "HTTP_PASSWORD: XXXXXXXX");
#endif
}
#if (defined WLAN_USE_ROAMING_BY_SCANNING || (defined WLAN_USE_MESH_ROAMING && defined WLAN_USE_MESH_ROAMING_ACTIVATE_CLIENT_TRIGGERED_QUERIES))
else if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHRESHOLD")){
tmp = trim(splitted[1]);

View File

@@ -13,6 +13,8 @@ struct wlan_config {
std::string gateway = "";
std::string netmask = "";
std::string dns = "";
std::string http_username = "";
std::string http_password = "";
int rssi_threshold = 0; // Default: 0 -> ROAMING disabled
};
extern struct wlan_config wlan_config;

View File

@@ -1,16 +1,15 @@
dependencies:
espressif/esp-nn:
component_hash: b32869798bdb40dec6bc99caca48cd65d42f8a9f506b9ab9c598a076f891ede9
component_hash: f6f2851ce82137a66e4265071c9b852bbe0130b882a18dea9f03faea7bf1295a
source:
pre_release: true
service_url: https://api.components.espressif.com/
type: service
version: 1.0.2
version: 1.1.0
idf:
component_hash: null
source:
type: idf
version: 5.3.0
manifest_hash: 6995555b9b41e897235448c868ca92c0c3401fd2ff90df084be9bb8629958f2c
version: 5.3.1
manifest_hash: 7350b157da8e1eb3cf21d0ea99443ec18c94cb2e0b22af07e20f286a9d15ec7a
target: esp32
version: 1.0.0

1
code/esp-protocols Submodule

Submodule code/esp-protocols added at 4394f845fc

View File

@@ -33,6 +33,8 @@
#include "configFile.h"
#include "server_main.h"
#include "server_camera.h"
#include "basic_auth.h"
#ifdef ENABLE_MQTT
#include "server_mqtt.h"
#endif //ENABLE_MQTT
@@ -77,10 +79,10 @@
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 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);
@@ -107,27 +109,51 @@ bool Init_NVS_SDCard()
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
host.max_freq_khz = SDMMC_FREQ_HIGHSPEED;
// For SoCs where the SD power can be supplied both via an internal or external (e.g. on-board LDO) power supply.
// When using specific IO pins (which can be used for ultra high-speed SDMMC) to connect to the SD card
// and the internal LDO power supply, we need to initialize the power supply first.
#if SD_PWR_CTRL_LDO_INTERNAL_IO
sd_pwr_ctrl_ldo_config_t ldo_config = {
.ldo_chan_id = CONFIG_EXAMPLE_SD_PWR_CTRL_LDO_IO_ID,
};
sd_pwr_ctrl_handle_t pwr_ctrl_handle = NULL;
ret = sd_pwr_ctrl_new_on_chip_ldo(&ldo_config, &pwr_ctrl_handle);
if (ret != ESP_OK)
{
ESP_LOGE(TAG, "Failed to create a new on-chip LDO power control driver");
return ret;
}
host.pwr_ctrl_handle = pwr_ctrl_handle;
#endif
// This initializes the slot without card detect (CD) and write protect (WP) signals.
// Modify slot_config.gpio_cd and slot_config.gpio_wp if your board has these signals.
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
sdmmc_slot_config_t slot_config = {
.cd = SDMMC_SLOT_NO_CD,
.wp = SDMMC_SLOT_NO_WP,
};
#else
sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT();
#endif
// Set bus width to use:
#ifdef __SD_USE_ONE_LINE_MODE__
slot_config.width = 1;
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.clk = GPIO_SDCARD_CLK;
slot_config.cmd = GPIO_SDCARD_CMD;
slot_config.d0 = GPIO_SDCARD_D0;
#endif
#else
#endif // end CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
#else // else __SD_USE_ONE_LINE_MODE__
slot_config.width = 4;
#ifdef SOC_SDMMC_USE_GPIO_MATRIX
#ifdef CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
slot_config.d1 = GPIO_SDCARD_D1;
slot_config.d2 = GPIO_SDCARD_D2;
slot_config.d3 = GPIO_SDCARD_D3;
#endif
#endif
#endif // end CONFIG_SOC_SDMMC_USE_GPIO_MATRIX
#endif // end __SD_USE_ONE_LINE_MODE__
// Enable internal pullups on enabled pins. The internal pullups
// are insufficient however, please make sure 10k external pullups are
@@ -429,6 +455,8 @@ extern "C" void app_main(void)
StatusLED(WLAN_INIT, 3, true);
return;
}
init_basic_auth();
}
else if (iWLANStatus == -1) { // wlan.ini not available, potentially empty or content not readable
StatusLED(WLAN_INIT, 1, true);
@@ -600,27 +628,57 @@ void migrateConfiguration(void) {
}
else if ((isInString(configLines[i], "Zoom")) && (!isInString(configLines[i], "CamZoom")) && (!isInString(configLines[i], "ZoomMode")) && (!isInString(configLines[i], "ZoomOffsetX")) && (!isInString(configLines[i], "ZoomOffsetY"))) {
CamZoom_lines = i;
CamZoom_value = alphanumericToBoolean(splitted[1]);
if (splitted.size() < 2) {
CamZoom_value = false;
}
else {
ESP_LOGE(TAG, "splitted[1]: %s", splitted[1].c_str());
CamZoom_value = alphanumericToBoolean(splitted[1]);
}
CamZoom_found = true;
}
else if ((isInString(configLines[i], "ZoomMode")) && (!isInString(configLines[i], "CamZoom"))) {
CamZoomSize_lines = i;
if (isStringNumeric(splitted[1])) {
CamZoomSize_value = std::stof(splitted[1]);
if (splitted.size() < 2) {
CamZoomSize_value = 0;
}
else {
if (isStringNumeric(splitted[1])) {
CamZoomSize_value = std::stof(splitted[1]);
}
else {
CamZoomSize_value = 0;
}
}
CamZoom_found = true;
}
else if ((isInString(configLines[i], "ZoomOffsetX")) && (!isInString(configLines[i], "CamZoom")) && (!isInString(configLines[i], "ZoomOffsetY"))) {
CamZoomOffsetX_lines = i;
if (isStringNumeric(splitted[1])) {
CamZoomOffsetX_value = std::stof(splitted[1]);
if (splitted.size() < 2) {
CamZoomOffsetX_value = 0;
}
else {
if (isStringNumeric(splitted[1])) {
CamZoomOffsetX_value = std::stof(splitted[1]);
}
else {
CamZoomOffsetX_value = 0;
}
}
CamZoom_found = true;
}
else if ((isInString(configLines[i], "ZoomOffsetY")) && (!isInString(configLines[i], "CamZoom")) && (!isInString(configLines[i], "ZoomOffsetX"))) {
CamZoomOffsetY_lines = i;
if (isStringNumeric(splitted[1])) {
CamZoomOffsetY_value = std::stof(splitted[1]);
if (splitted.size() < 2) {
CamZoomOffsetY_value = 0;
}
else {
if (isStringNumeric(splitted[1])) {
CamZoomOffsetY_value = std::stof(splitted[1]);
}
else {
CamZoomOffsetY_value = 0;
}
}
CamZoom_found = true;
}
@@ -727,8 +785,7 @@ void migrateConfiguration(void) {
}
else if (section == "[AutoTimer]") {
migrated = migrated | replaceString(configLines[i], "Intervall", "Interval");
migrated = migrated | replaceString(configLines[i], ";AutoStart = true", ";AutoStart = false"); // Set it to its default value
migrated = migrated | replaceString(configLines[i], ";AutoStart", "AutoStart"); // Enable it
migrated = migrated | replaceString(configLines[i], "Autostart", ";UNUSED_PARAMETER"); // This parameter is no longer used
}
else if (section == "[Debug]") {
migrated = migrated | replaceString(configLines[i], "Logfile ", "LogLevel "); // Whitespace needed so it does not match `LogfileRetentionInDays`
@@ -741,7 +798,7 @@ void migrateConfiguration(void) {
else if (section == "[System]") {
migrated = migrated | replaceString(configLines[i], "RSSIThreashold", "RSSIThreshold");
migrated = migrated | replaceString(configLines[i], "AutoAdjustSummertime", ";UNUSED_PARAMETER"); // This parameter is no longer used
migrated = migrated | replaceString(configLines[i], ";SetupMode = true", ";SetupMode = false"); // Set it to its default value
migrated = migrated | replaceString(configLines[i], ";SetupMode", "SetupMode"); // Enable it
}
@@ -910,7 +967,12 @@ bool setCpuFrequency(void) {
splitted = ZerlegeZeile(line);
if (toUpper(splitted[0]) == "CPUFREQUENCY") {
cpuFrequency = splitted[1];
if (splitted.size() < 2) {
cpuFrequency = 160;
}
else {
cpuFrequency = splitted[1];
}
break;
}
}

View File

@@ -17,6 +17,7 @@
#include "MainFlowControl.h"
#include "esp_log.h"
#include "basic_auth.h"
#include "esp_chip_info.h"
#include <stdio.h>
@@ -408,7 +409,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t info_get_handle = {
.uri = "/info", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = info_get_handler,
.handler = APPLY_BASIC_AUTH_FILTER(info_get_handler),
.user_ctx = (void*) base_path // Pass server data as context
};
httpd_register_uri_handler(server, &info_get_handle);
@@ -416,7 +417,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t sysinfo_handle = {
.uri = "/sysinfo", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = sysinfo_handler,
.handler = APPLY_BASIC_AUTH_FILTER(sysinfo_handler),
.user_ctx = (void*) base_path // Pass server data as context
};
httpd_register_uri_handler(server, &sysinfo_handle);
@@ -424,7 +425,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t starttime_tmp_handle = {
.uri = "/starttime", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = starttime_get_handler,
.handler = APPLY_BASIC_AUTH_FILTER(starttime_get_handler),
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &starttime_tmp_handle);
@@ -432,7 +433,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t img_tmp_handle = {
.uri = "/img_tmp/*", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = img_tmp_virtual_handler,
.handler = APPLY_BASIC_AUTH_FILTER(img_tmp_virtual_handler),
.user_ctx = (void*) base_path // Pass server data as context
};
httpd_register_uri_handler(server, &img_tmp_handle);
@@ -440,7 +441,7 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
httpd_uri_t main_rest_handle = {
.uri = "/*", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = hello_main_handler,
.handler = APPLY_BASIC_AUTH_FILTER(hello_main_handler),
.user_ctx = (void*) base_path // Pass server data as context
};
httpd_register_uri_handler(server, &main_rest_handle);
@@ -459,7 +460,7 @@ httpd_handle_t start_webserver(void)
config.server_port = 80;
config.ctrl_port = 32768;
config.max_open_sockets = 5; //20210921 --> previously 7
config.max_uri_handlers = 40; // Make sure this fits all URI handlers. Memory usage in bytes: 6*max_uri_handlers
config.max_uri_handlers = 41; // Make sure this fits all URI handlers. Memory usage in bytes: 6*max_uri_handlers
config.max_resp_headers = 8;
config.backlog_conn = 5;
config.lru_purge_enable = true; // this cuts old connections if new ones are needed.

View File

@@ -29,6 +29,7 @@
#include "Helper.h"
#include "statusled.h"
#include "server_ota.h"
#include "basic_auth.h"
#include "lwip/err.h"
#include "lwip/sys.h"
@@ -98,8 +99,8 @@ void wifi_init_softAP(void)
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 += "This mode is always started 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 access 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()));
@@ -109,7 +110,7 @@ void SendHTTPResponse(httpd_req_t *req)
{
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 += "This is normal after the first flashing of the firmware and an empty sd-card. Please upload \"remote_setup.zip\", which contains a 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.";
@@ -135,7 +136,7 @@ void SendHTTPResponse(httpd_req_t *req)
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>";
message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reset 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>";
@@ -468,7 +469,7 @@ httpd_handle_t start_webserverAP(void)
httpd_uri_t reboot_handle = {
.uri = "/reboot", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = reboot_handlerAP,
.handler = APPLY_BASIC_AUTH_FILTER(reboot_handlerAP),
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &reboot_handle);
@@ -476,7 +477,7 @@ httpd_handle_t start_webserverAP(void)
httpd_uri_t config_ini_handle = {
.uri = "/config", // Match all URIs of type /path/to/file
.method = HTTP_GET,
.handler = config_ini_handler,
.handler = APPLY_BASIC_AUTH_FILTER(config_ini_handler),
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &config_ini_handle);
@@ -485,7 +486,7 @@ httpd_handle_t start_webserverAP(void)
httpd_uri_t file_uploadAP = {
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
.method = HTTP_POST,
.handler = upload_post_handlerAP,
.handler = APPLY_BASIC_AUTH_FILTER(upload_post_handlerAP),
.user_ctx = NULL // Pass server data as context
};
httpd_register_uri_handler(server, &file_uploadAP);
@@ -493,7 +494,7 @@ httpd_handle_t start_webserverAP(void)
httpd_uri_t test_uri = {
.uri = "*",
.method = HTTP_GET,
.handler = test_handler,
.handler = APPLY_BASIC_AUTH_FILTER(test_handler),
.user_ctx = NULL
};
httpd_register_uri_handler(server, &test_uri);

View File

@@ -3,6 +3,29 @@
<link rel="icon" href="https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/icon/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.3.1/dist/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script type="module" src="https://unpkg.com/esp-web-tools@9.0.3/dist/web/install-button.js?module"></script>
<style>
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background-color: #d8d8d8;
margin-top: 20px;
}
.footer-section {
display: flex;
align-items: center;
}
.footer-section img {
width: 24px;
height: 24px;
margin-left: 10px;
}
.donation-cards img {
height: 20px;
margin-right: 5px;
}
</style>
<body style="padding: 20px; padding-left: 60px; padding-right: 60px;">
<table>
@@ -34,5 +57,27 @@
<p><esp-web-install-button manifest="manifest.json"></esp-web-install-button></p>
<hr>
<p style="font-size: small;">Installer and Console powered by <a href=https://esphome.github.io/esp-web-tools/ target=_blank>ESP Web Tools</a></p>
<div class="footer">
<div class="footer-section">
<span>Support & Contact Us</span>
<a href="https://github.com/jomjol/AI-on-the-edge-device" target="_blank" title="GitHub">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/github-logo.png" alt="GitHub">
</a>
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/gmail-logo.png" alt="Email">
</a>
<a href="https://github.com/jomjol/AI-on-the-edge-device/discussions" target="_blank" title="GitHub">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/discussion-logo" alt="GitHub">
</a>
</div>
<div class="footer-section">
<span>Donations</span>
<a href="https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL" target="_blank" title="Donate via PayPal">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/paypal.png" alt="PayPal" style="width: 60px; height: auto;">
</a>
</div>
</div>
</body>
</html>

BIN
images/discussion-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
images/github-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 509 B

BIN
images/gmail-logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 514 B

View File

@@ -2,11 +2,4 @@
Default Value: `true`
!!! Warning
This is an **Expert Parameter**! Only change it if you understand what it does!
Automatically start the Flow (Digitization Rounds) immediately after power up.
!!! Note
Typically this is set to `true`.
The main reasons to set it to `false` is when you want to trigger it manually using the
[REST API](../REST-API) or [MQTT-API](../MQTT-API) or for debugging.
This parameter is no longer available. The flow is now always enabled. If you want it to be disabled, set an interval which is high enough (eg. 1440 = 24h).

View File

@@ -4,4 +4,10 @@ Default Value: `5`
Unit: Minutes
Interval in which the Flow (Digitization Round) is run.
It will run immediately on startup and then the next time after the given interval.
If a round takes longer than this interval, the next round gets postponed until the current round completes.
If the flow gets started by a MQTT message or the REST API call, the interval automatically gets reset.
!!! Note
If you want the flow to be disabled, set an interval which is high enough (eg. 1440 = 24h).

View File

@@ -0,0 +1,6 @@
# Parameter `DomoticzTopicIn`
Default Value: `domoticz/in`
Domoticz "in" topic as configured on the "MQTT Client Gateway" setup page on the Domoticz system. Used to publish counter/s value/s.
Parameter &lt;NUMBER&gt;.DomoticzIDX is required (see below).

View File

@@ -0,0 +1,4 @@
# Parameter `<NUMBER>.DomoticzIDX`
Default Value: `0`
The Idx number for the counter device. Can be obtained from the devices setup page on the Domoticz system.

View File

@@ -9,17 +9,17 @@ This parameter is intended to compensate for small reading fluctuations that occ
It is only applied to the last digit of the read value (See example below).
If the read value is within PreValue +/- Threshold, no further calculation is carried out and the Value/Prevalue remains at the old value.
Example:
## Example
Smallest ROI provides value for 0.000x
ChangeRateThreshold = 2
- Smallest ROI provides value for `0.000'x` (Eg. a water meter with 4 pointers behind the decimal point)
- ChangeRateThreshold = 2
Extended Resolution disabled:
PreValue: 123.456'7 >>> Threshold = +/- 0.000'2
Comparative value >>> max = 123.456'9 and min = 123.456'5
#### With `Extended Resolution` **disabled**
PreValue: `123.456'7` -> Threshold = `+/-0.000'2`.<br>
All changes between `123.456'5` and `123.456'9` get ignored
Extended Resolution enabled:
PreValue: 123.456'78 >>> Threshold = +/- 0.000'02
Comparative value >>> max = 123.456'80 and min = 123.456'76
#### With `Extended Resolution` **enabled**
PreValue: `123.456'78` -> Threshold = `+/-0.000'02`.<br>
All changes between `123.456'76` and `123.456'80` get ignored.
![](img/ChangeRateThreshold.png)

Binary file not shown.

View File

@@ -38,12 +38,12 @@ Demo = false
InitialRotate = 0.0
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = Default
AlignmentAlgo = default
/config/ref0.jpg 103 271
/config/ref1.jpg 442 142
[Digits]
Model = /config/dig-cont_0710_s3_q.tflite
Model = /config/dig-cont_0712_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
@@ -87,20 +87,23 @@ HomeassistantDiscovery = false
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;DomoticzTopicIn = domoticz/in
;main.DomoticzIDX = 0
;[InfluxDB]
;Uri = undefined
;Database = undefined
;Measurement = undefined
;user = undefined
;password = undefined
;main.Measurement = undefined
;main.Field = undefined
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Measurement = undefined
;Org = undefined
;Token = undefined
;main.Measurement = undefined
;main.Field = undefined
;[Webhook]
@@ -115,13 +118,12 @@ HomeassistantDiscovery = false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
;IO12 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 2
LEDColor = 150 150 150
[AutoTimer]
AutoStart = true
Interval = 5
[DataLogging]
@@ -138,4 +140,5 @@ TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
Tooltip = true
SetupMode = true

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
sd-card/demo/530.07077.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.07325.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.12067.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.21419.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.48435.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.70265.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/530.95675.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/531.10877.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/531.24108.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/531.38301.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/531.63071.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
sd-card/demo/531.82235.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

136
sd-card/demo/config.ini Normal file
View File

@@ -0,0 +1,136 @@
[TakeImage]
;RawImagesLocation = /log/source
;RawImagesRetention = 15
WaitBeforeTakingPicture = 2
CamGainceiling = x8
CamQuality = 10
CamBrightness = 0
CamContrast = 0
CamSaturation = 0
CamSharpness = 0
CamAutoSharpness = false
CamSpecialEffect = no_effect
CamWbMode = auto
CamAwb = true
CamAwbGain = true
CamAec = true
CamAec2 = true
CamAeLevel = 2
CamAecValue = 600
CamAgc = true
CamAgcGain = 8
CamBpc = true
CamWpc = true
CamRawGma = true
CamLenc = true
CamHmirror = false
CamVflip = false
CamDcw = true
CamDenoise = 0
CamZoom = false
CamZoomOffsetX = 0
CamZoomOffsetY = 0
CamZoomSize = 0
LEDIntensity = 0
Demo = true
[Alignment]
InitialRotate = -34.6
SearchFieldX = 20
SearchFieldY = 20
AlignmentAlgo = default
/config/ref0.jpg 30 189
/config/ref1.jpg 536 113
[Digits]
Model = /config/dig-cont_0710_s3_q.tflite
CNNGoodThreshold = 0.5
;ROIImagesLocation = /log/digit
;ROIImagesRetention = 3
main.dig1 438 62 49 71 false
[Analog]
Model = /config/ana-cont_1300_s2.tflite
;ROIImagesLocation = /log/analog
;ROIImagesRetention = 3
main.ana1 452 199 120 120 false
[PostProcessing]
main.DecimalShift = 0
;main.AnalogToDigitTransitionStart =
main.ChangeRateThreshold = 2
PreValueUse = true
PreValueAgeStartup = 720
main.AllowNegativeRates = true
;main.MaxRateValue = 0
;main.MaxRateType = AbsoluteChange
main.ExtendedResolution = true
main.IgnoreLeadingNaN = false
ErrorMessage = true
CheckDigitIncreaseConsistency = false
;[MQTT]
;Uri = mqtt://IP-ADRESS:1883
;MainTopic = watermeter
;ClientID = watermeter
;user = USERNAME
;password = PASSWORD
RetainMessages = false
HomeassistantDiscovery = false
;MeterType = other
;CACert = /config/certs/RootCA.pem
;ClientCert = /config/certs/client.pem.crt
;ClientKey = /config/certs/client.pem.key
;[InfluxDB]
;Uri = undefined
;Database = undefined
;user = undefined
;password = undefined
;main.Measurement = undefined
;main.Field =
;[InfluxDBv2]
;Uri = undefined
;Bucket = undefined
;Org = undefined
;Token = undefined
;main.Measurement = undefined
;main.Field = undefined
;[Webhook]
;Uri = undefined
;ApiKey = undefined
;UploadImg = 0
;[GPIO]
;IO0 = input disabled 10 false false
;IO1 = input disabled 10 false false
;IO3 = input disabled 10 false false
;IO4 = built-in-led disabled 10 false false
;IO12 = input-pullup disabled 10 false false
;IO13 = input-pullup disabled 10 false false
LEDType = WS2812
LEDNumbers = 2
LEDColor = 150 150 150
[AutoTimer]
Interval = 1
[DataLogging]
DataLogActive = false
DataFilesRetention = 3
[Debug]
LogLevel = 3
LogfilesRetention = 3
[System]
Tooltip = true
TimeZone = CET-1CEST,M3.5.0,M10.5.0/3
;TimeServer = pool.ntp.org
;Hostname = undefined
RSSIThreshold = -75
CPUFrequency = 160
SetupMode = false

12
sd-card/demo/files.txt Normal file
View File

@@ -0,0 +1,12 @@
530.07077.jpg
530.07325.jpg
530.12067.jpg
530.21419.jpg
530.48435.jpg
530.70265.jpg
530.95675.jpg
531.10877.jpg
531.24108.jpg
531.38301.jpg
531.63071.jpg
531.82235.jpg

View File

View File

@@ -0,0 +1 @@
main 2024-10-06T23:02:42+0200 0.05

12
sd-card/demo/readme.txt Normal file
View File

@@ -0,0 +1,12 @@
This folder contains a prepared demo setup.
All you need to do is:
1. Copy the following files to the config folder of your SD-Card:
- config.ini
- ref0.jpg
- ref1.jpg
- reference.jpg
- prevalue.ini
1. Restart the device
More details at https://jomjol.github.io/AI-on-the-edge-device-docs/Demo-Mode

BIN
sd-card/demo/ref0.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
sd-card/demo/ref1.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
sd-card/demo/reference.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -504,7 +504,7 @@
<tr class="expert" unused_id="TakeImage_CamAgcGain_ex3">
<td class="indent1">
<class id="TakeImage_CamAgcGain_text" style="color:black;">Gain Manuall Value</class>
<class id="TakeImage_CamAgcGain_text" style="color:black;">Gain Manual Value</class>
</td>
<td>
<input required type="number" id="TakeImage_CamAgcGain_value1" size="13" min="0" max="30" onchange="cameraParameterChanged()"
@@ -933,7 +933,7 @@
<tr>
<td class="indent2">
<input type="checkbox" id="PostProcessing_AnalogToDigitTransitionStart_enabled" value="1" onclick = 'InvertEnableItem("PostProcessing", "AnalogToDigitTransitionStart")' unchecked >
<label for=PostProcessing_AnalogToDigitTransitionStart_enabled><class id="PostProcessing_AnalogToDigitTransitionStart_text" style="color:black;">Analogto Digit Transition Start</class></label>
<label for=PostProcessing_AnalogToDigitTransitionStart_enabled><class id="PostProcessing_AnalogToDigitTransitionStart_text" style="color:black;">Analog to Digit Transition Start</class></label>
</td>
<td>
<input required type="number" id="PostProcessing_AnalogToDigitTransitionStart_value1" step="0.1" min="5.0" max="9.9" value="9.2"
@@ -1178,6 +1178,36 @@
<td>$TOOLTIP_MQTT_MeterType</td>
</tr>
<tr class="MQTTItem">
<td class="indent1">
<input type="checkbox" id="MQTT_DomoticzTopicIn_enabled" value="1" onclick = 'InvertEnableItem("MQTT", "DomoticzTopicIn")' unchecked >
<label for=MQTT_DomoticzTopicIn_enabled><class id="MQTT_DomoticzTopicIn_text" style="color:black;">Domoticz "in" topic</class></label>
</td>
<td>
<input type="text" id="MQTT_DomoticzTopicIn_value1">
</td>
<td>$TOOLTIP_MQTT_DomoticzTopicIn</td>
</tr>
<tr class="MQTTItem" style="margin-top:12px">
<td class="indent1" style="padding-top:25px" colspan="3">
<b>Parameter per number sequence:</b>
<select
style="font-weight: bold; margin-left:17px" id="NumbersMQTTIdx_value1" onchange="numberMQTTIdxChanged()">
</select>
</td>
</tr>
<tr class="MQTTItem">
<td class="indent2">
<input type="checkbox" id="MQTT_DomoticzIDX_enabled" value="1" onclick = 'InvertEnableItem("MQTT", "DomoticzIDX")' unchecked >
<label for=MQTT_DomoticzIDX_enabled><class id="MQTT_DomoticzIDX_text" style="color:black;">Domoticz Counter Idx:</class></label>
</td>
<td>
<input type="text" id="MQTT_DomoticzIDX_value1">
</td>
<td>$TOOLTIP_MQTT_NUMBER.DomoticzIDX</td>
</tr>
<!------------- INFLUXDB v1 ------------------>
<tr style="border-bottom: 2px solid lightgray;">
@@ -1890,6 +1920,7 @@
<!------------- Autotimer ------------------>
<!--
<tr style="border-bottom: 2px solid lightgray;">
<td colspan="3" style="padding-left: 0px; padding-bottom: 3px;"><h4>Auto Timer</h4></td>
</tr>
@@ -1906,6 +1937,7 @@
</td>
<td>$TOOLTIP_AutoTimer_AutoStart</td>
</tr>
-->
<tr>
<td class="indent1">
@@ -2120,6 +2152,7 @@ function LoadConfigNeu() {
UpdateInput();
var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
UpdateExpertModus();
UpdateTooltipModus();
document.getElementById("divall").style.display = '';
@@ -2162,6 +2195,11 @@ function InitIndivParameter() {
_indexInfluxv1.remove(0);
}
var _indexMQTTIdx = document.getElementById("NumbersMQTTIdx_value1");
while (_indexMQTTIdx.length) {
_indexMQTTIdx.remove(0);
}
for (var i = 0; i < NUMBERS.length; ++i) {
var option = document.createElement("option");
option.text = NUMBERS[i]["name"];
@@ -2177,11 +2215,17 @@ function InitIndivParameter() {
optionInfluxv1.text = NUMBERS[i]["name"];
optionInfluxv1.value = i;
_indexInfluxv1.add(optionInfluxv1);
var optionMQTTIdx = document.createElement("option");
optionMQTTIdx.text = NUMBERS[i]["name"];
optionMQTTIdx.value = i;
_indexMQTTIdx.add(optionMQTTIdx);
}
_index.selectedIndex = 0;
_indexInflux.selectedIndex = 0;
_indexInfluxv1.selectedIndex = 0;
_indexMQTTIdx.selectedIndex = 0;
}
function UpdateInputIndividual(sel) {
@@ -2200,6 +2244,7 @@ function UpdateInputIndividual(sel) {
ReadParameter(param, "InfluxDBv2", "Field", true, NUNBERSAkt);
ReadParameter(param, "InfluxDB", "Measurement", true, NUNBERSAkt);
ReadParameter(param, "InfluxDBv2", "Measurement", true, NUNBERSAkt);
ReadParameter(param, "MQTT", "DomoticzIDX", true, NUNBERSAkt);
}
// var sel = document.getElementById("Numbers_value1");
@@ -2218,6 +2263,8 @@ function UpdateInputIndividual(sel) {
WriteParameter(param, category, "InfluxDBv2", "Field", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDB", "Measurement", true, NUNBERSAkt);
WriteParameter(param, category, "InfluxDBv2", "Measurement", true, NUNBERSAkt);
WriteParameter(param, category, "MQTT", "DomoticzIDX", true, NUNBERSAkt);
}
function UpdateInput() {
@@ -2306,6 +2353,7 @@ function UpdateInput() {
WriteParameter(param, category, "MQTT", "CACert", true);
WriteParameter(param, category, "MQTT", "ClientCert", true);
WriteParameter(param, category, "MQTT", "ClientKey", true);
WriteParameter(param, category, "MQTT", "DomoticzTopicIn", true);
WriteParameter(param, category, "InfluxDB", "Uri", true);
WriteParameter(param, category, "InfluxDB", "Database", true);
@@ -2335,7 +2383,7 @@ function UpdateInput() {
WriteParameter(param, category, "GPIO", "LEDNumbers", false);
WriteParameter(param, category, "GPIO", "LEDColor", false);
WriteParameter(param, category, "AutoTimer", "AutoStart", false);
//WriteParameter(param, category, "AutoTimer", "AutoStart", false);
WriteParameter(param, category, "AutoTimer", "Interval", false);
WriteParameter(param, category, "DataLogging", "DataLogActive", false);
@@ -2473,6 +2521,7 @@ function ReadParameterAll() {
ReadParameter(param, "MQTT", "CACert", true);
ReadParameter(param, "MQTT", "ClientCert", true);
ReadParameter(param, "MQTT", "ClientKey", true);
ReadParameter(param, "MQTT", "DomoticzTopicIn", true);
ReadParameter(param, "InfluxDB", "Uri", true);
ReadParameter(param, "InfluxDB", "Database", true);
@@ -2509,7 +2558,7 @@ function ReadParameterAll() {
param["GPIO"]["LEDNumbers"]["found"] = true;
param["GPIO"]["LEDColor"]["found"] = true;
ReadParameter(param, "AutoTimer", "AutoStart", false);
//ReadParameter(param, "AutoTimer", "AutoStart", false);
ReadParameter(param, "AutoTimer", "Interval", false);
ReadParameter(param, "DataLogging", "DataLogActive", false);
@@ -2527,7 +2576,7 @@ function ReadParameterAll() {
var sel = document.getElementById("Numbers_value1");
UpdateInputIndividual(sel);
// FormatDecimalValue(param, "PostProcessing", "MaxRateValue");
}
@@ -2555,7 +2604,7 @@ function UpdateExpertModus() {
_style_pur = '';
_hidden = false;
document.getElementById("Button_Edit_Config_Raw").style.display = "";
firework.launch("Expert view activated. Please use carefully", 'warning', 5000);
firework.launch("Expert view activated. Please use it carefully", 'warning', 5000);
}
else {
document.getElementById("Button_Edit_Config_Raw").style.display = "none";
@@ -2821,7 +2870,7 @@ function camSettingsSet(){
}
catch (error){}
document.getElementById("overlaytext").innerHTML = "Device is busy, plase waiting...<br><br>Current step: " + _xhttp.responseText;
document.getElementById("overlaytext").innerHTML = "Device is busy, please wait.<br><br>Current step: " + _xhttp.responseText;
console.log("Device is busy, waiting 2s then checking again...");
await sleep(2000);
}
@@ -2871,6 +2920,38 @@ function numberChanged() {
if (_selInflux.selectedIndex != _neu) {
_selInflux.selectedIndex = _neu
}
var _sel3 = document.getElementById("NumbersInfluxDB_value1");
if (_sel3.selectedIndex != _neu) {
_sel3.selectedIndex = _neu
}
var _sel4 = document.getElementById("NumbersMQTTIdx_value1");
if (_sel4.selectedIndex != _neu) {
_sel4.selectedIndex = _neu
}
}
function numberMQTTIdxChanged() {
var sel = document.getElementById("NumbersMQTTIdx_value1");
_neu = sel.selectedIndex;
UpdateInputIndividual(sel);
var _sel2 = document.getElementById("Numbers_value1");
if (_sel2.selectedIndex != _neu) {
_sel2.selectedIndex = _neu
}
var _sel3 = document.getElementById("NumbersInfluxDB_value1");
if (_sel3.selectedIndex != _neu) {
_sel3.selectedIndex = _neu
}
var _sel4 = document.getElementById("NumbersInfluxDBv2_value1");
if (_sel4.selectedIndex != _neu) {
_sel4.selectedIndex = _neu
}
}
function numberInfluxDBv2Changed() {
@@ -2887,6 +2968,11 @@ function numberInfluxDBv2Changed() {
if (_sel3.selectedIndex != _neu) {
_sel3.selectedIndex = _neu
}
var _sel4 = document.getElementById("NumbersMQTTIdx_value1");
if (_sel4.selectedIndex != _neu) {
_sel4.selectedIndex = _neu
}
}
function numberInfluxDBChanged() {
@@ -2903,6 +2989,11 @@ function numberInfluxDBChanged() {
if (_sel3.selectedIndex != _neu) {
_sel3.selectedIndex = _neu
}
var _sel4 = document.getElementById("NumbersMQTTIdx_value1");
if (_sel4.selectedIndex != _neu) {
_sel4.selectedIndex = _neu
}
}
function getParameterByName(name, url = window.location.href) {

View File

@@ -617,7 +617,7 @@
}
catch (error){}
document.getElementById("overlaytext").innerHTML = "Device is busy, plase waiting...<br><br>Current step: " + _xhttp.responseText;
document.getElementById("overlaytext").innerHTML = "Device is busy, please wait.<br><br>Current step: " + _xhttp.responseText;
console.log("Device is busy, waiting 5s then checking again...");
await sleep(2000);
}
@@ -1053,7 +1053,7 @@
if (document.getElementById("ExpertModus_enabled").checked) {
_style_pur = '';
_hidden = false;
firework.launch("Expert parameter view activated. Please use carefully", 'warning', 5000);
firework.launch("Expert parameter view activated. Please use it carefully", 'warning', 5000);
}
const expert = document.querySelectorAll(".expert");

View File

@@ -69,6 +69,30 @@
return "";
}
</script>
<style>
/* Add these styles to your existing CSS file or in a <style> tag in the head */
.footer {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
background-color: #d8d8d8;
margin-top: 20px;
}
.footer-section {
display: flex;
align-items: center;
}
.footer-section img {
width: 24px;
height: 24px;
margin-left: 10px;
}
.donation-cards img {
height: 20px;
margin-right: 5px;
}
</style>
</head>
<body>
@@ -134,9 +158,9 @@
</ul>
</li>
<li id="ManualControl" style="display:none;"><a>Manual Control <i class="arrow down"></i></a> <!-- Workaround: Hide menu if no entry is available -->
<ul class="submenu">
<!--<li><a href="#" onclick="flow_start()">Start Round</a></li>--> <!-- Needs to be adapted on code side first to ensure proper user feedback -->
<li id="HASendDiscovery" style="display:none;"><a href="#" onclick="HA_send_discovery()">Resend HA Discovery</a></li>
<ul class="submenu" style="width: 300px">
<li><a href="#" onclick="flow_start()">Start Round</a></li>
<li id="HASendDiscovery" style="width: 300px" style="display:none;"><a href="#" onclick="HA_send_discovery()">Resend Homeassistant Discovery</a></li>
</ul>
</li>
</ul>
@@ -146,6 +170,28 @@
<span id="Version" style="font-size: 10px; margin-top: -5px;padding-left: 10px;">Loading version...</span>
<!-- # Disabled footer, since it wastes a lot of space and the images are broken
<div class="footer">
<div class="footer-section">
<span>Support & Contact Us</span>
<a href="https://github.com/jomjol/AI-on-the-edge-device" target="_blank" title="GitHub">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/github-logo.png" alt="GitHub">
</a>
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/gmail-logo.png" alt="Email">
</a>
<a href="https://github.com/jomjol/AI-on-the-edge-device/discussions" target="_blank" title="GitHub">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/discussion-logo" alt="GitHub">
</a>
</div>
<div class="footer-section">
<span>Donations</span>
<a href="https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL" target="_blank" title="Donate via PayPal">
<img src="https://github.com/jomjol/AI-on-the-edge-device/images/paypal.png" alt="PayPal" style="width: 60px; height: auto;">
</a>
</div>
</div> -->
<script type="text/javascript">
LoadHostname();
LoadFwVersion();
@@ -158,13 +204,14 @@
console.log("Loading page: " + getCookie("page"));
document.getElementById('maincontent').src = getCookie("page");
/*
function flow_start() {
var url = getDomainname() + '/flow_start';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
if (xhttp.responseText.substring(0,3) == "001") {
firework.launch(xhttp.responseText, 'success', 5000);
/*if (xhttp.responseText.substring(0,3) == "001") {
firework.launch('Flow start triggered', 'success', 5000);
window.location.reload();
}
@@ -173,13 +220,13 @@
}
else if (xhttp.responseText.substring(0,3) == "099") {
firework.launch('Flow start triggered, but start not possible (no flow task available)', 'danger', 5000);
}
}*/
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
*/
function HA_send_discovery_visibility() {
loadConfig(domainname);
@@ -187,19 +234,19 @@
category = getConfigCategory();
param = getConfigParameters();
if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"].value == "true") {
if (category["MQTT"]["enabled"] && param["MQTT"]["HomeassistantDiscovery"].value1 == "true") {
document.getElementById("ManualControl").style.display="";
document.getElementById("HASendDiscovery").style.display="";
}
}
function HA_send_discovery() {
console.log("HA Discovery scheduled");
console.log("Homeassistant Discovery topic sending scheduled");
var url = getDomainname() + '/mqtt_publish_discovery';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
firework.launch('Sending HA discovery topics scheduled. The sending will be processed in state "Publish to MQTT"', 'success', 5000);
firework.launch('Sending Homeassistant discovery topics scheduled. It will get sent in the step "Publish to MQTT" of the next digitization round', 'success', 5000);
}
}
xhttp.open("GET", url, true);

View File

@@ -118,6 +118,7 @@
</tr>
<tr>
<td class="tg-4">
<div id="sntp_date" ></div>
<div id="timestamp" ></div>
<div id="cputemp" ></div>
<div id="rssi" ></div>
@@ -153,6 +154,7 @@
loadValue("prevalue", "prevalue", "border-collapse: collapse; width: 100%");
loadValue("error", "error", "border-collapse: collapse; width: 100%");
loadStatus();
loadSntpDate();
loadCPUTemp();
loadRSSI();
loadUptime();
@@ -234,6 +236,20 @@
xhttp.send();
}
function loadSntpDate() {
url = domainname + '/date';
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var _rsp = xhttp.responseText;
$('#sntp_date').html("Date/Time on device: " + _rsp);
}
}
xhttp.open("GET", url, true);
xhttp.send();
}
function loadUptime() {
url = domainname + '/uptime';
var xhttp = new XMLHttpRequest();

View File

@@ -198,6 +198,8 @@ function ParseConfig() {
ParamAddValue(param, catname, "user");
ParamAddValue(param, catname, "password");
ParamAddValue(param, catname, "RetainMessages");
ParamAddValue(param, catname, "DomoticzTopicIn");
ParamAddValue(param, catname, "DomoticzIDX", 1, true);
ParamAddValue(param, catname, "HomeassistantDiscovery");
ParamAddValue(param, catname, "MeterType");
ParamAddValue(param, catname, "CACert");
@@ -265,7 +267,7 @@ function ParseConfig() {
category[catname]["enabled"] = false;
category[catname]["found"] = false;
param[catname] = new Object();
ParamAddValue(param, catname, "AutoStart");
//ParamAddValue(param, catname, "AutoStart");
ParamAddValue(param, catname, "Interval");
var catname = "DataLogging";

View File

@@ -36,3 +36,14 @@ password = ""
; Default: 0 = Disable client requested roaming query
RSSIThreshold = 0
;++++++++++++++++++++++++++++++++++
; Password Protection of the Web Interface and the REST API
; When those parameters are active, the Web Interface and the REST API are protected by a username and password.
; Note: This is be a WEAK and INSECURE way to protect the Web Interface and the REST API.
; There was no audit nor a security review to check the correct implementation of the protection!
; The password gets transmitted unencrypted (plain text), this means it is very easy to extract it
; for somebody who has access to your WIFI!
; USE AT YOUR OWN RISK!
;http_username = "myusername"
;http_password = "mypassword"