mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-09 13:06:54 +03:00
Compare commits
316 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e9e13588f6 | ||
|
|
6c8a45f2dc | ||
|
|
e7d28f9bde | ||
|
|
33015351d6 | ||
|
|
0a461b2bd0 | ||
|
|
ecf1e78208 | ||
|
|
a8b9acf170 | ||
|
|
45a3138d28 | ||
|
|
7e997889aa | ||
|
|
6c51af7107 | ||
|
|
8be7beab9a | ||
|
|
62ec8d76c6 | ||
|
|
7a634797c4 | ||
|
|
575d59dad2 | ||
|
|
524d800a0a | ||
|
|
7b0e6200d6 | ||
|
|
65d011c9aa | ||
|
|
dc3604f144 | ||
|
|
1eb2dd4efa | ||
|
|
f4d345b902 | ||
|
|
a38837c61b | ||
|
|
b50be7e825 | ||
|
|
74f45bee28 | ||
|
|
47b3b0c708 | ||
|
|
9c390f3026 | ||
|
|
069aac5723 | ||
|
|
9335cd73d5 | ||
|
|
e90beffb44 | ||
|
|
55a06dbe1d | ||
|
|
ae07159afe | ||
|
|
1fff655ef1 | ||
|
|
3815f9cf0a | ||
|
|
e36490c89e | ||
|
|
d4f02f971f | ||
|
|
ec326d9a11 | ||
|
|
6e4df0ef87 | ||
|
|
3aa0411676 | ||
|
|
9f20c126be | ||
|
|
2707e8c9f4 | ||
|
|
0d467d8ad1 | ||
|
|
66be09c98e | ||
|
|
60e9a427a5 | ||
|
|
f72bdb7c45 | ||
|
|
a53188e697 | ||
|
|
0dd63b9b7a | ||
|
|
513e300676 | ||
|
|
dd28859a9f | ||
|
|
ecc43edbba | ||
|
|
bf8ab423e3 | ||
|
|
8116a546b5 | ||
|
|
5c512367e2 | ||
|
|
e15ea561bc | ||
|
|
9e4332314a | ||
|
|
880d9eae20 | ||
|
|
72fcd791db | ||
|
|
39960b15ed | ||
|
|
395b9a4c5b | ||
|
|
5a2753a50b | ||
|
|
57c5c19cca | ||
|
|
c64ed36fa4 | ||
|
|
754981c67f | ||
|
|
5c22986e2e | ||
|
|
1746920f61 | ||
|
|
d33380d2a0 | ||
|
|
889ed9e6be | ||
|
|
2b0e0f7d4e | ||
|
|
2314d7ef18 | ||
|
|
bec3a5ee3b | ||
|
|
c738a9a4da | ||
|
|
e7c8706b1b | ||
|
|
f725adf5ba | ||
|
|
7bb1b08bdb | ||
|
|
d1e7ef1fce | ||
|
|
08f7e1275e | ||
|
|
529690ec60 | ||
|
|
59431a7eaf | ||
|
|
23b5ffbb92 | ||
|
|
9b8594c040 | ||
|
|
3e082ed06e | ||
|
|
22fe50f80a | ||
|
|
885cd71b80 | ||
|
|
8c6805ec7c | ||
|
|
1fc0b41fca | ||
|
|
7e26744e2e | ||
|
|
1d9ef7e634 | ||
|
|
1be49a75b1 | ||
|
|
b6b7587f0a | ||
|
|
e3017c25a9 | ||
|
|
d914e69e7a | ||
|
|
edf9f11048 | ||
|
|
44afd138c5 | ||
|
|
d2b93a7110 | ||
|
|
ff726485ba | ||
|
|
de46cd899e | ||
|
|
37263bb239 | ||
|
|
d21a38f42f | ||
|
|
9b9a7537f1 | ||
|
|
56d8c65008 | ||
|
|
fc24db7d59 | ||
|
|
0867dcc6da | ||
|
|
b9f57edb92 | ||
|
|
7ebbba3cf2 | ||
|
|
5188734c8b | ||
|
|
4e476a75ca | ||
|
|
7a037a3254 | ||
|
|
f6b44ac905 | ||
|
|
deecc128be | ||
|
|
18f2b5824e | ||
|
|
45084bab70 | ||
|
|
6cdbe38717 | ||
|
|
fe0d0c2590 | ||
|
|
44f61c7c91 | ||
|
|
af8b7d6824 | ||
|
|
170583f8fe | ||
|
|
648a35e4d7 | ||
|
|
99849063d9 | ||
|
|
5b22007a1e | ||
|
|
80cf89c9d5 | ||
|
|
45d37ea957 | ||
|
|
f935c38571 | ||
|
|
bfc7c2b8b7 | ||
|
|
08f90de683 | ||
|
|
32748e3182 | ||
|
|
7a280bc7c6 | ||
|
|
f4ae688527 | ||
|
|
ca45d0a278 | ||
|
|
8f66fcf2a6 | ||
|
|
30549ac5af | ||
|
|
06ab14a6c9 | ||
|
|
72e3570dc4 | ||
|
|
724169b059 | ||
|
|
6e58f5eebb | ||
|
|
96b3d7cc2f | ||
|
|
74c9eada47 | ||
|
|
9d65889824 | ||
|
|
98451c8fc7 | ||
|
|
6b47eef4cd | ||
|
|
158ec65e57 | ||
|
|
c4bbd7c545 | ||
|
|
cb323eb715 | ||
|
|
1aa23aa14a | ||
|
|
41abc19a97 | ||
|
|
99e03dde06 | ||
|
|
9d73c5475e | ||
|
|
25ae9a045f | ||
|
|
dabe66819d | ||
|
|
4ad7b97764 | ||
|
|
083aeb42ec | ||
|
|
a13d1d0692 | ||
|
|
c12645ab4d | ||
|
|
116c99e55c | ||
|
|
43b65d6b2e | ||
|
|
bc7a0e46b7 | ||
|
|
455962bd94 | ||
|
|
86c515bcb8 | ||
|
|
f09067a142 | ||
|
|
8ce24df304 | ||
|
|
279a59d019 | ||
|
|
d88e286696 | ||
|
|
d07aa2a72d | ||
|
|
bf30872439 | ||
|
|
12dc4eb460 | ||
|
|
ab67d1ff35 | ||
|
|
86809d8bf8 | ||
|
|
85adf70394 | ||
|
|
290e7f3835 | ||
|
|
e9e0eed871 | ||
|
|
4ab0f632b7 | ||
|
|
1a33834b3f | ||
|
|
1d367a58d5 | ||
|
|
ec4ce66bcc | ||
|
|
4a0f5eadc2 | ||
|
|
f955f8786b | ||
|
|
38f6e49d00 | ||
|
|
4394d832b8 | ||
|
|
9e68380814 | ||
|
|
c8bb95a852 | ||
|
|
9c2de84ee4 | ||
|
|
d4b1c2c883 | ||
|
|
550d9e1c87 | ||
|
|
3f687a7233 | ||
|
|
c1369ca0ff | ||
|
|
76c8bce7b4 | ||
|
|
e0ae9b8e4f | ||
|
|
9de573c15e | ||
|
|
716c23fed3 | ||
|
|
8e22bd06e9 | ||
|
|
b78929745b | ||
|
|
6986f2186c | ||
|
|
3743ac18f5 | ||
|
|
13f1d40ca3 | ||
|
|
63f28097bd | ||
|
|
ff7fec1de4 | ||
|
|
f65b2850a2 | ||
|
|
3a999358b9 | ||
|
|
d3e195df9f | ||
|
|
dbf8e634d9 | ||
|
|
2b810ca32d | ||
|
|
0adfc45d36 | ||
|
|
2a54d9b889 | ||
|
|
4150c31b98 | ||
|
|
803e8f2bff | ||
|
|
b215345f11 | ||
|
|
98d35e0412 | ||
|
|
437e8e4d25 | ||
|
|
e05085ddf0 | ||
|
|
495b5de38c | ||
|
|
c2b89dd199 | ||
|
|
f15b1e5dfc | ||
|
|
e308a1b5d9 | ||
|
|
1e698440f9 | ||
|
|
98bf7e5387 | ||
|
|
e1f8ac59cb | ||
|
|
0a2b6b71ca | ||
|
|
5daae7b47c | ||
|
|
4951fc9b80 | ||
|
|
0bf8182728 | ||
|
|
a512d82793 | ||
|
|
4f305a8705 | ||
|
|
46daa4cb79 | ||
|
|
485363d7a2 | ||
|
|
c8d2d9d4fd | ||
|
|
0880213342 | ||
|
|
8d4fb74173 | ||
|
|
f10adb3383 | ||
|
|
3be33820d9 | ||
|
|
83f638c64f | ||
|
|
35d77a3925 | ||
|
|
a33da0c750 | ||
|
|
cd2350140d | ||
|
|
bd125b249b | ||
|
|
33b9a15f73 | ||
|
|
0e55fc7f7e | ||
|
|
fc0bbc57cb | ||
|
|
bc46149573 | ||
|
|
be8598bcaa | ||
|
|
ace1936a78 | ||
|
|
e5649d03b2 | ||
|
|
426d6bae3f | ||
|
|
5d35df65f3 | ||
|
|
f91f5e3cba | ||
|
|
1c66f8c6ca | ||
|
|
a42902af0d | ||
|
|
a871055d96 | ||
|
|
64fcb9595c | ||
|
|
9d9cff977d | ||
|
|
5724f37ea6 | ||
|
|
3ca93b49ca | ||
|
|
b2248818dd | ||
|
|
a702fbbe86 | ||
|
|
1002e502d5 | ||
|
|
17a8adae05 | ||
|
|
4fca050623 | ||
|
|
f371c176b6 | ||
|
|
1c6772f383 | ||
|
|
7d2f28084b | ||
|
|
923b8d7444 | ||
|
|
49e4eb3ef3 | ||
|
|
2c481c0d15 | ||
|
|
f2e854c935 | ||
|
|
8045e0bfaf | ||
|
|
40e176ec28 | ||
|
|
1ab135e989 | ||
|
|
99c14ae9e0 | ||
|
|
00d859734d | ||
|
|
de4efff558 | ||
|
|
2ed3f4aa40 | ||
|
|
ba59c8ee66 | ||
|
|
fb97e22dee | ||
|
|
b0e7283d2b | ||
|
|
e341564eee | ||
|
|
730006977c | ||
|
|
ea26a5722a | ||
|
|
62742d92d2 | ||
|
|
50b9983534 | ||
|
|
34ea8302ef | ||
|
|
a8fd0bbdef | ||
|
|
99e6243e25 | ||
|
|
0f6c767143 | ||
|
|
eb0b932c44 | ||
|
|
1e4be0f3fe | ||
|
|
47caa1b118 | ||
|
|
641609e187 | ||
|
|
006fb6a611 | ||
|
|
a0e4ee1d00 | ||
|
|
27d770c759 | ||
|
|
fe39b5120b | ||
|
|
74df27befd | ||
|
|
c92a1e430d | ||
|
|
642d22578f | ||
|
|
140ec1b380 | ||
|
|
17090c177e | ||
|
|
d2721cbd4b | ||
|
|
f80509c886 | ||
|
|
6c85796abe | ||
|
|
e82cbbf117 | ||
|
|
bacdc97d90 | ||
|
|
1e43c70adf | ||
|
|
16bb6e90a9 | ||
|
|
cf6882c579 | ||
|
|
858d0b3361 | ||
|
|
208a5433b7 | ||
|
|
9a7c9604fe | ||
|
|
f44fa4df31 | ||
|
|
68a985a09f | ||
|
|
6b329aaa58 | ||
|
|
80798ae0e6 | ||
|
|
cd61e2c92d | ||
|
|
c943510828 | ||
|
|
9291d330dd | ||
|
|
a856d9e2f2 | ||
|
|
41f9436465 | ||
|
|
5233c14725 | ||
|
|
3d42d949af | ||
|
|
aec1dc770b | ||
|
|
f335c17f0d |
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
31
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,31 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a bug report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Thank you for taking your time to report a bug.
|
||||
|
||||
Before you proceed, please check:
|
||||
- Do you use the latest version? See https://github.com/jomjol/AI-on-the-edge-device/releases.
|
||||
- Is there already another similar issue? Check for open and closed Issue in https://github.com/jomjol/AI-on-the-edge-device/issues.
|
||||
- Are instructions in the readme solving your issue (https://github.com/jomjol/AI-on-the-edge-device/tree/master#readme)?
|
||||
- Are instructions in the wiki solving your issue? (https://github.com/jomjol/AI-on-the-edge-device/wiki)?
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**Version**
|
||||
Which version are you using? (See menu `System > Info`).
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
67
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
67
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
name: 🐞 Bug Report
|
||||
description: Use this form if you think you found a bug / Verwende dieses Formular, wenn Du denkst, dass Du einen Fehler gefunden hast.
|
||||
labels: bug
|
||||
body:
|
||||
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking your time to report a bug.
|
||||
|
||||
Before you proceed, please check:
|
||||
- [ ] Do you use the [latest version](https://github.com/jomjol/AI-on-the-edge-device/releases)?
|
||||
- [ ] Is there already another similar issue? Check for open and closed [Issue](https://github.com/jomjol/AI-on-the-edge-device/issues) and [Discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions).
|
||||
- [ ] Are instructions in the [README](https://github.com/jomjol/AI-on-the-edge-device/tree/master#readme) solving your issue?
|
||||
- [ ] Are instructions in the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki) solving your issue?
|
||||
|
||||
Du darfst gerne auch in Deutsch schreiben!
|
||||
|
||||
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: The Problem
|
||||
description: A clear and concise description of what the bug is.
|
||||
|
||||
|
||||
|
||||
- type: input
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Version
|
||||
description: Which version are you using? (See menu `System > Info`).
|
||||
|
||||
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Logfile
|
||||
description: Add the logfile (See menu `System > Log Viewer`) to help explain your problem. This will be automatically formatted into code, so no need to format it on your side.
|
||||
render: shell
|
||||
|
||||
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected Behavior
|
||||
description: A clear and concise description of what you expected to happen.
|
||||
|
||||
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots
|
||||
description: If applicable, add screenshots to help explain your problem.
|
||||
|
||||
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional Context
|
||||
description: Add any other context about the problem here.
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💬 Open a new Discussion
|
||||
url: https://github.com/jomjol/AI-on-the-edge-device/discussions/categories/q-a
|
||||
about: Use this form if you have a question or need help setting your AI-on-the-edge-device it up
|
||||
23
.github/ISSUE_TEMPLATE/feature.yaml
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feature.yaml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: 💡 Feature Request
|
||||
description: Use this form if you have an idea or wish for a new feature
|
||||
labels: feature
|
||||
body:
|
||||
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking your time to document your idea.
|
||||
|
||||
Before you proceed, please check:
|
||||
- [ ] Is there already another similar issue open or closed? Check for open and closed [Issue](https://github.com/jomjol/AI-on-the-edge-device/issues) and [Discussions](https://github.com/jomjol/AI-on-the-edge-device/discussions).
|
||||
- [ ] Is there already another similar [discussion](https://github.com/jomjol/AI-on-the-edge-device/discussions) ongoing?
|
||||
|
||||
Please be aware that we might decline your request if we have a reason for it!
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: The Feature
|
||||
description: A clear and concise description of what the new feature should do. If possible, refer to other projects or add a mockup.
|
||||
10
.github/ISSUE_TEMPLATE/general_question.md
vendored
10
.github/ISSUE_TEMPLATE/general_question.md
vendored
@@ -1,10 +0,0 @@
|
||||
---
|
||||
name: General Question
|
||||
about: General Question => Open a discussion instead
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
If its not a bug, please open a discussion instead, see https://github.com/jomjol/AI-on-the-edge-device/discussions
|
||||
19
.github/ISSUE_TEMPLATE/training.yaml
vendored
Normal file
19
.github/ISSUE_TEMPLATE/training.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: 📖 New Training Data
|
||||
description: Use this form if you collected images and want to provide them for training the model
|
||||
title: New Training Data
|
||||
labels: new training data
|
||||
assignees: jomjol
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before you proceed, please check:
|
||||
- [ ] Did you make sure we don't have similar data yet in the training data? (see [Digital Counters](https://jomjol.github.io/neural-network-digital-counter-readout/) resp. [Analog Needles](https://jomjol.github.io/neural-network-analog-needle-readout))
|
||||
- [ ] Did you follow the guideline as documented in the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/ROI-Configuration)? We will only be able to accept the files if they fulfill the rules!
|
||||
|
||||
- type: textarea
|
||||
validations:
|
||||
required: true
|
||||
attributes:
|
||||
label: Files
|
||||
description: You can drag & drop your **zipped** images here
|
||||
8
.github/ISSUE_TEMPLATE/x_plain.yaml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/x_plain.yaml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
name: 🗒️ Blank Form
|
||||
description: Use this form if none of the others fit. Please only use none of the others fit!
|
||||
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue
|
||||
|
||||
72
.github/workflows/build.yaml
vendored
72
.github/workflows/build.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: Build and Pack
|
||||
|
||||
on: [push]
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
#########################################################################################
|
||||
@@ -10,30 +10,37 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- id: skip_check
|
||||
uses: fkirc/skip-duplicate-actions@v5
|
||||
with:
|
||||
concurrent_skipping: same_content_newer
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v2
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install --upgrade platformio
|
||||
|
||||
- name: Build Firmware
|
||||
# run: echo "Testing... ${{ github.ref_name }}, ${{ steps.vars.outputs.sha_short }}" > ./sd-card/html/version.txt; mkdir -p ./code/.pio/build/esp32cam/; cd ./code/.pio/build/esp32cam/; echo "${{ steps.vars.outputs.sha_short }}" > firmware.bin; cp firmware.bin partitions.bin; cp firmware.bin bootloader.bin # Testing
|
||||
#run: echo "Testing... ${{ github.ref_name }}, ${{ steps.vars.outputs.sha_short }}" > ./sd-card/html/version.txt; mkdir -p ./code/.pio/build/esp32cam/; cd ./code/.pio/build/esp32cam/; echo "${{ steps.vars.outputs.sha_short }}" > firmware.bin; cp firmware.bin partitions.bin; cp firmware.bin bootloader.bin # Testing
|
||||
run: cd code; platformio run --environment esp32cam
|
||||
|
||||
- name: Store generated files in cache
|
||||
@@ -59,7 +66,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -74,24 +81,25 @@ jobs:
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Rename firmware file to contain versioning (old ota)
|
||||
run: |
|
||||
mkdir -p ./dist_old_ota
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "./dist_old_ota/firmware__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }}).bin"
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "./dist_old_ota/firmware__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }}).bin"
|
||||
|
||||
- name: Upload Firmware artifact (old OTA concept)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
# name: "firmware__${{ github.ref_name }}__(${{ steps.vars.outputs.sha_short }})__(extract_before_upload__only_needed_for_migration_from_11.3.1)"
|
||||
name: "firmware__(extract_before_upload)__${{ github.ref_name }}__(${{ steps.vars.outputs.sha_short }})"
|
||||
name: "firmware__(extract_before_upload)__${{ steps.vars.outputs.branch }}__(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./dist_old_ota/*
|
||||
|
||||
- name: Upload Web interface artifact (old OTA concept)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "html__${{ github.ref_name }}__(${{ steps.vars.outputs.sha_short }})"
|
||||
name: "html__${{ steps.vars.outputs.branch }}__(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./sd-card/html/*
|
||||
|
||||
|
||||
@@ -109,7 +117,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -124,7 +132,8 @@ jobs:
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare update.zip artifact
|
||||
run: |
|
||||
@@ -155,14 +164,13 @@ jobs:
|
||||
- name: Upload dist as update.zip artifact (Firmware + Web UI + CNN)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "update__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
name: "update__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./dist/*
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./dist
|
||||
path: dist
|
||||
key: ${{ github.run_number }}-pack-for-OTA-v2
|
||||
|
||||
|
||||
@@ -177,7 +185,7 @@ jobs:
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -189,6 +197,12 @@ jobs:
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p firmware
|
||||
@@ -204,14 +218,13 @@ jobs:
|
||||
- name: Upload initial_esp32_setup.zip artifact (Firmware + Bootloader + Partitions + Web UI)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "initial_esp32_setup__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
name: "initial_esp32_setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./firmware
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./firmware
|
||||
path: firmware
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
|
||||
|
||||
@@ -226,7 +239,11 @@ jobs:
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
@@ -242,28 +259,25 @@ jobs:
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./dist
|
||||
path: dist
|
||||
key: ${{ github.run_number }}-pack-for-OTA-v2
|
||||
|
||||
# import cached artifacts from pack-for-fresh-install
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./firmware
|
||||
path: firmware
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "::set-output name=sha_short::$(git rev-parse --short HEAD)"
|
||||
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p release
|
||||
mkdir -p dist
|
||||
# create a update.zip like "update__rolling"
|
||||
pwd
|
||||
ls ./dist
|
||||
cd ./dist
|
||||
zip -r ../release/update.zip .
|
||||
cd ../firmware
|
||||
|
||||
268
Changelog.md
268
Changelog.md
@@ -1,6 +1,127 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- n.a.
|
||||
|
||||
### Changed
|
||||
|
||||
- n.a.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Re-updated build environment to v5.2.0 (from accidental downgrad to v4.4.0)
|
||||
|
||||
### Removed
|
||||
|
||||
- n.a.
|
||||
|
||||
|
||||
|
||||
## [13.0.2] - 2022-12-02
|
||||
|
||||
## [13.0.2] - 2022-12-02
|
||||
|
||||
### Added
|
||||
|
||||
- n.a.
|
||||
|
||||
### Changed
|
||||
|
||||
- Update Tool "Logfile downloader and combiner" to handle the new csv file format.
|
||||
- Added MQTT topic `status` containing Digitalization Status.
|
||||
- Added timezone to MQTT topic `timestamp`.
|
||||
- Disable heap logs by default
|
||||
- Cleanup loglevel info (moved some entries to debug level)
|
||||
- Updated logging informations
|
||||
|
||||
### Fixed
|
||||
|
||||
- Corrected Version comparison between firmware and Web UI.
|
||||
|
||||
### Removed
|
||||
|
||||
- n.a.
|
||||
|
||||
## [13.0.1] - 2022-11-28
|
||||
|
||||
**Home Assistant MQTT Discovery Support**
|
||||
|
||||
### Update Procedure
|
||||
|
||||
:bangbang: **Make sure to read the instructions below carfully!**.
|
||||
|
||||
1. Backup your configuration (use the `System -> Backup/Restore` page)!
|
||||
|
||||
2. You should update to `12.0.1` before you update to this release. All other migrations are untested.
|
||||
|
||||
3. Upload and update the `update-*.zip` file from this release.
|
||||
|
||||
4. Let it restart and check on the `System -> Info` page that the Firmware as well as the Web UI got updated. If only one got updated, redo the update. If it fails several times, you also can update the Firmware and the Web UI separately.
|
||||
|
||||
5. Safe way:
|
||||
1. Update first the `firmware.bin` (extract from zip file) and do the Reboot
|
||||
2. Update with the full zip file (`update-*.zip`, ignore the version warning after the reboot)
|
||||
|
||||
6. Please go to `Settings -> Configuration` and address the changed parameters:
|
||||
- DataLogging (storing the values for data graph)
|
||||
- Debug (extended by different debug reporting levels)
|
||||
|
||||
If anything breaks you can try to enforce manual update as following:
|
||||
|
||||
**OTA:**
|
||||
1. Make sure the last run of the update completed the **Uploading** step.
|
||||
1. Call `http://<IP>/ota?task=update&file=<UPLOAD_FILENAME>` to enforce the extraction/flashing.
|
||||
|
||||
**Initial Setup:**
|
||||
1. Use the initial_esp32_setup.zip ( <https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation> ) as alternative to have a clean install.
|
||||
|
||||
### Added
|
||||
|
||||
- Implementation of [Home Assistant MQTT Discovery](https://www.home-assistant.io/integrations/mqtt/#mqtt-discovery)
|
||||
- Improved ROIs configuration: locked ROI geometry, equidistant delta x
|
||||
- Improved OTA Update mechanism (only working after installation for next update)
|
||||
- Added data logging in `/log/data` - One day per file and each measurement is on one line
|
||||
- Format: csv - comma separated
|
||||
- Content: `time`, `name-of-number`, `raw-value`, `return-value`, `pre-value`, `change-rate`, `change-absolute`, `error-text`, `cnn-digital`, `cnn-analog`
|
||||
- Show graph of values direct in the user interface (thanks to [@rdmueller](https://github.com/rdmueller))
|
||||
|
||||
- Using new data logging (see above)
|
||||
- Possibility to choose different values and switch between different numbers (if present)
|
||||
|
||||
Note: You need to activate data logging for this feature to work, see above!
|
||||
- PreValue is now contained in `/json` ([#1154](https://github.com/jomjol/AI-on-the-edge-device/issues/1154))
|
||||
- SD card info into the `System>Info` menu (thanks to [@Slider007](https://github.com/Slider0007))
|
||||
- Version check (Firmware vs. Web UI)
|
||||
- Various minor new features
|
||||
|
||||
### Changed
|
||||
|
||||
- Updated tflite (`dig-cont_0600_s3.tflite`)
|
||||
- Updated OTA functionality (more robust, but not fully bullet prove yet)
|
||||
- Updated Espressif library to `espressif32@v5.2.0`
|
||||
- [#1176](https://github.com/jomjol/AI-on-the-edge-device/discussions/1176) accept minor negative values (-0.2) if extended resolution is enabled
|
||||
- [#1143](https://github.com/jomjol/AI-on-the-edge-device/issues/1143) added config parameter `AnalogDigitalTransitionStart`. It can setup very early and very late digit transition starts.
|
||||
- New version of `dig-class100` (v1.4.0): added images of heliowatt powermeter
|
||||
|
||||
### Fixed
|
||||
|
||||
- [#1116](https://github.com/jomjol/AI-on-the-edge-device/issues/1116) precision problem at setting prevalue
|
||||
- [#1119](https://github.com/jomjol/AI-on-the-edge-device/issues/1119) renamed `firmware.bin` not working in OTA
|
||||
- [#1143](https://github.com/jomjol/AI-on-the-edge-device/issues/1143) changed postprocess for `analog->digit` (lowest digit processing)
|
||||
- [#1280](https://github.com/jomjol/AI-on-the-edge-device/issues/1280) check ROIs name for unsupported characters
|
||||
- [#983](https://github.com/jomjol/AI-on-the-edge-device/issues/983) old log files did not get deleted
|
||||
- Failed NTP time sync during startup gets now retried every round if needed
|
||||
- Whitespaces and `=` in MQTT and InfluxDB passwords
|
||||
- Various minor fixes and improvements
|
||||
|
||||
### Removed
|
||||
|
||||
- n.a.
|
||||
|
||||
## [12.0.1] 2022-09-29
|
||||
|
||||
Improve **u**ser e**x**perience
|
||||
|
||||
@@ -8,104 +129,113 @@ Improve **u**ser e**x**perience
|
||||
|
||||
**Make sure to read the instructions below carfully!**.
|
||||
|
||||
1. Backup your configuration (use the `System > Backup/Restore` page)!
|
||||
2. You should update to `11.3.1` before you update to this release. All other migrations are not tested.
|
||||
1. Backup your configuration (use the `System > Backup/Restore` page)!
|
||||
2. You should update to `11.3.1` before you update to this release. All other migrations are not tested.
|
||||
Rolling newer than `11.3.1` can also be used, but no guaranty.
|
||||
3. Upload and update the `firmware.bin` file from this release. **but do not reboot**
|
||||
4. Upload the `html-from-11.3.1.zip` in html upload and update the web interface.
|
||||
5. Now you can reboot.
|
||||
3. Upload and update the `firmware.bin` file from this release. **but do not reboot**
|
||||
4. Upload the `html-from-11.3.1.zip` in html upload and update the web interface.
|
||||
5. Now you can reboot.
|
||||
|
||||
If anything bricks you can try to
|
||||
If anything breaks you can try to
|
||||
1. Call `http://<IP>/ota?task=update&file=firmware.bin` resp. `http://<IP>/ota?task=update&file=html.zip` if the upload successed but the extraction failed.
|
||||
1. Use the initial_esp32_setup.zip ( <https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation> ) as alternative.
|
||||
|
||||
### Added
|
||||
|
||||
- Automatic release creation
|
||||
- Newest firmware of rolling branch now automatically build and provided in [Github Actions Output](https://github.com/jomjol/AI-on-the-edge-device/actions) (developers only)
|
||||
- [\#1068](https://github.com/jomjol/AI-on-the-edge-device/issues/1068) New update mechanism:
|
||||
- Handling of all files (`zip`, `tfl`, `tflite`, `bin`) within in one common update interface
|
||||
- Using the `update.zip` from the [Release page](https://github.com/jomjol/AI-on-the-edge-device/releases)
|
||||
- Status (`upload`, `processing`, ...) displayed on Web Interface
|
||||
- Automatical detection and suggestion for reboot where needed (Web Interface uupdates only need a page refresh)
|
||||
- :bangbang: Best for OTA use Firefox. Chrome works with warnings. Safari stuck in upload.
|
||||
- Automatic release creation
|
||||
- Newest firmware of rolling branch now automatically build and provided in [Github Actions Output](https://github.com/jomjol/AI-on-the-edge-device/actions) (developers only)
|
||||
- [#1068](https://github.com/jomjol/AI-on-the-edge-device/issues/1068) New update mechanism:
|
||||
- Handling of all files (`zip`, `tfl`, `tflite`, `bin`) within in one common update interface
|
||||
- Using the `update.zip` from the [Release page](https://github.com/jomjol/AI-on-the-edge-device/releases)
|
||||
- Status (`upload`, `processing`, ...) displayed on Web Interface
|
||||
- Automatical detection and suggestion for reboot where needed (Web Interface uupdates only need a page refresh)
|
||||
- :bangbang: Best for OTA use Firefox. Chrome works with warnings. Safari stuck in upload.
|
||||
|
||||
### Changed
|
||||
- Integrated version info better shown on the Info page and in the log
|
||||
- Updated menu
|
||||
- Update used libraries (`tflite`, `esp32-cam`, `esp-nn`, as of 20220924)
|
||||
|
||||
- Integrated version info better shown on the Info page and in the log
|
||||
- Updated menu
|
||||
- Update used libraries (`tflite`, `esp32-cam`, `esp-nn`, as of 20220924)
|
||||
|
||||
### Fixed
|
||||
|
||||
- [\#1092](https://github.com/jomjol/AI-on-the-edge-device/issues/1092) censor passwords in log outputs
|
||||
- [\#1029](https://github.com/jomjol/AI-on-the-edge-device/issues/1029) wrong change of `checkDigitConsistency` now working like releases before `11.3.1`
|
||||
- Spelling corrections (**[cristianmitran](https://github.com/cristianmitran)**)
|
||||
|
||||
- [#1092](https://github.com/jomjol/AI-on-the-edge-device/issues/1092) censor passwords in log outputs
|
||||
- [#1029](https://github.com/jomjol/AI-on-the-edge-device/issues/1029) wrong change of `checkDigitConsistency` now working like releases before `11.3.1`
|
||||
- Spelling corrections (**[cristianmitran](https://github.com/cristianmitran)**)
|
||||
|
||||
### Removed
|
||||
- Remove the folder `/firmware` from GitHub repository.
|
||||
If you want to get the latest `firmware.bin` and `html.zip` files, please download from the automated [build action](https://github.com/jomjol/AI-on-the-edge-device/actions) or [release page](https://github.com/jomjol/AI-on-the-edge-device/releases)
|
||||
|
||||
## [11.3.1] - (2022-09-17)
|
||||
- Remove the folder `/firmware` from GitHub repository.
|
||||
If you want to get the latest `firmware.bin` and `html.zip` files, please download from the automated [build action](https://github.com/jomjol/AI-on-the-edge-device/actions) or [release page](https://github.com/jomjol/AI-on-the-edge-device/releases)
|
||||
|
||||
## [11.3.1](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v11.3.1), 2022-09-17
|
||||
|
||||
Intermediate Digits
|
||||
|
||||
- **ATTENTION**:
|
||||
- first update the `firmware.bin` and ensure that the new version is running
|
||||
- **ATTENTION**:
|
||||
|
||||
- Only afterwards update the `html.zip`
|
||||
|
||||
- Otherwise the downwards compatibility of the new counter clockwise feature is not given and you end in a reboot loop, that needs manual flashing!
|
||||
|
||||
- first update the `firmware.bin` and ensure that the new version is running
|
||||
|
||||
- Only afterwards update the `html.zip`
|
||||
|
||||
- Otherwise the downwards compatibility of the new counter clockwise feature is not given and you end in a reboot loop, that needs manual flashing!
|
||||
|
||||
|
||||
- **NEW v11.3.1**: corrected corrupted asset `firmware.bin`
|
||||
- Increased precision (more than 6-7 digits)
|
||||
- Implements Counter Clockwise Analog Pointers
|
||||
- Improved post processing algorithm
|
||||
- Debugging: intensive use of testcases
|
||||
- MQTT: improved handling, extended logging, automated reconnect
|
||||
- HTML: Backup Option for Configuration
|
||||
- HTML: Improved Reboot
|
||||
- HTML: Update WebUI (Reboot, Infos, CPU Temp, RSSI)
|
||||
- This version is largely also based on the work of **[caco3](https://github.com/caco3)**, **[adellafave](https://github.com/adellafave)**, **[haverland](https://github.com/haverland)**, **[stefanbode](https://github.com/stefanbode)**, **[PLCHome](https://github.com/PLCHome)**
|
||||
- **NEW v11.3.1**: corrected corrupted asset `firmware.bin`
|
||||
- Increased precision (more than 6-7 digits)
|
||||
- Implements Counter Clockwise Analog Pointers
|
||||
- Improved post processing algorithm
|
||||
- Debugging: intensive use of testcases
|
||||
- MQTT: improved handling, extended logging, automated reconnect
|
||||
- HTML: Backup Option for Configuration
|
||||
- HTML: Improved Reboot
|
||||
- HTML: Update WebUI (Reboot, Infos, CPU Temp, RSSI)
|
||||
- This version is largely also based on the work of **[caco3](https://github.com/caco3)**, **[adellafave](https://github.com/adellafave)**, **[haverland](https://github.com/haverland)**, **[stefanbode](https://github.com/stefanbode)**, **[PLCHome](https://github.com/PLCHome)**
|
||||
|
||||
## [11.2.0](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v11.2.0), 2022-08-28
|
||||
|
||||
## [11.2.0] - (2022-08-28)
|
||||
Intermediate Digits
|
||||
|
||||
- Updated Tensorflow / TFlite to newest tflite (version as of 2022-07-27)
|
||||
- Updated analog neural network file (`ana-cont_11.3.0_s2.tflite` - default, `ana-class100_0120_s1_q.tflite`)
|
||||
- Updated digital neural network file (`dig-cont_0570_s3.tflite` - default, `dig-class100_0120_s2_q.tflite`)
|
||||
- Updated Tensorflow / TFlite to newest tflite (version as of 2022-07-27)
|
||||
|
||||
- Added automated filtering of tflite-file in the graphical configuration (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
- Updated consistency algorithm & test cases
|
||||
- HTML: added favicon and system name, Improved reboot dialog (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
- Updated analog neural network file (`ana-cont_11.3.0_s2.tflite` - default, `ana-class100_0120_s1_q.tflite`)
|
||||
|
||||
- Updated digital neural network file (`dig-cont_0570_s3.tflite` - default, `dig-class100_0120_s2_q.tflite`)
|
||||
|
||||
- Added automated filtering of tflite-file in the graphical configuration (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
|
||||
- Updated consistency algorithm & test cases
|
||||
|
||||
- HTML: added favicon and system name, Improved reboot dialog (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
|
||||
## [11.1.1](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v11.1.1), 2022-08-22
|
||||
|
||||
## [11.1.1] - (2022-08-22)
|
||||
Intermediate Digits
|
||||
|
||||
- New and improved consistency check (especially with analog and digital counters mixed)
|
||||
- Bug Fix: digital counter algorithm
|
||||
- New and improved consistency check (especially with analog and digital counters mixed)
|
||||
- Bug Fix: digital counter algorithm
|
||||
|
||||
## [11.0.1](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v11.0.1), 2022-08-18
|
||||
|
||||
## [11.0.1] - (2022-08-18)
|
||||
Intermediate Digits
|
||||
|
||||
- **NEW v11.0.1**: Bug Fix InfluxDB configuration (only update of html.zip necessary)
|
||||
- **NEW v11.0.1**: Bug Fix InfluxDB configuration (only update of html.zip necessary)
|
||||
|
||||
- Implementation of new CNN types to detect intermediate values of digits with rolling numbers
|
||||
- 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'
|
||||
- **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)
|
||||
- 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'
|
||||
- **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 adaption 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 **
|
||||
|
||||
- Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
|
||||
- Files see ['/tools/logfile-tool'](tbd), How-to see [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 grahic configuration
|
||||
|
||||
|
||||
## [10.6.2] - (2022-07-24)
|
||||
## [10.6.2](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v10.6.2), 2022-07-24
|
||||
|
||||
Stability Increase
|
||||
|
||||
@@ -135,7 +265,7 @@ Stability Increase
|
||||
|
||||
- Bug Fix: no time with fixed IP, Postprocessing, MQTT
|
||||
|
||||
## [10.5.2] - (2022-02-22)
|
||||
## [10.5.2](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v10.5.2), 2022-02-22
|
||||
|
||||
Stability Increase
|
||||
|
||||
@@ -148,7 +278,7 @@ Stability Increase
|
||||
- Refactoring of check postprocessing consistency (e.g. max rate, negative rate, ...)
|
||||
- Bug Fix: corrected error in "Check Consistency Increase"
|
||||
|
||||
## [10.4.0] - (2022-02-12)
|
||||
## [10.4.0](https://github.com/jomjol/AI-on-the-edge-device/releases/tag/v10.4.0), 2022-02-12
|
||||
|
||||
Stability Increase
|
||||
|
||||
@@ -660,7 +790,13 @@ External Illumination
|
||||
|
||||
- Initial Version
|
||||
|
||||
[Unreleased]: https://github.com/haverland/AI-on-the-edge-device/compare/11.4.3...HEAD
|
||||
[Unreleased]: https://github.com/jomjol/AI-on-the-edge-device/compare/13.0.2...HEAD
|
||||
|
||||
[13.0.2]: https://github.com/jomjol/AI-on-the-edge-device/compare/13.0.1...13.0.2
|
||||
|
||||
[13.0.1]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.1
|
||||
|
||||
[12.0.1]: https://github.com/jomjol/AI-on-the-edge-device/compare/11.3.1...12.0.1
|
||||
|
||||
[11.4.3]: https://github.com/haverland/AI-on-the-edge-device/compare/10.6.2...11.4.3
|
||||
|
||||
|
||||
@@ -11,6 +11,28 @@
|
||||
|
||||
____
|
||||
|
||||
#### #33 Implement MATTER protocoll
|
||||
|
||||
* see [#1404](https://github.com/jomjol/AI-on-the-edge-device/issues/1404)
|
||||
|
||||
#### #32 Add feature to correct misinterpreted value
|
||||
|
||||
* If a value is misinterpreted, the user can manually correct the value.
|
||||
* The misinterpreted ROIs would be saved in a "training data" -folder on the SD-card
|
||||
* Stretch goal: make sending of saved training data as easy as pushing a button =)
|
||||
|
||||
#### #31 Implement InfluxDB v2.x interface
|
||||
|
||||
* Currently only InfluxDB v1.x is supportet, extend to v2.x
|
||||
* Remark: interface has changed
|
||||
* see [#1160](https://github.com/jomjol/AI-on-the-edge-device/issues/1160)
|
||||
|
||||
#### #30 Support meter clock over
|
||||
|
||||
* In case of meter clocking over, that is, reaching its max. value and starting over from 0,
|
||||
accept the new value and calculate correctly the difference.
|
||||
(see line 739 onwards in ClassFlowPostProcessing.cpp)
|
||||
|
||||
#### ~~#29 Add favicon and use the hostname for the website~~- implemented v11.3.1
|
||||
|
||||
~~* https://github.com/jomjol/AI-on-the-edge-device/issues/927~~
|
||||
|
||||
152
README.md
152
README.md
@@ -1,4 +1,6 @@
|
||||
# Welcome to the AI-on-the-edge-device
|
||||
<img src="images/icon/watermeter.svg" width="100px">
|
||||
|
||||
Artificial intelligence based systems have been established in our every days live. Just think of speech or image recognition. Most of the systems relay on either powerful processors or a direct connection to the cloud for doing the calculations up 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 brought into a practical oriented example, where a AI network is implemented on a ESP32 device so: **AI on the edge**.
|
||||
|
||||
@@ -6,7 +8,7 @@ This projects allows you to digitalize your **analoge** water, gas, power and ot
|
||||
|
||||
All you need is an [ESP32 board with a supported camera](https://github.com/jomjol/AI-on-the-edge-device/wiki/Hardware-Compatibility) and a bit of a practical hand.
|
||||
|
||||
<img src="images/esp32-cam.png" width="200">
|
||||
<img src="images/esp32-cam.png" width="200px">
|
||||
|
||||
## Key features
|
||||
- **Small** and **cheap** device (3x4.5x2 cm³, < 10 EUR)
|
||||
@@ -37,24 +39,31 @@ There are several options what to do with that value. Either send it to a MQTT b
|
||||
|
||||
## Setup
|
||||
There is a growing [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki) which provides you with a lot of information.
|
||||
|
||||
Head there to get a start, set it up and configure it.
|
||||
|
||||
There are also a articles in the German Heise magazine "make:" about the setup and the technical background (!not for free!)
|
||||
There are also a articles in the German Heise magazine "make:" about the setup and the technical background (behind a paywall) : [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296)
|
||||
|
||||
* [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296)
|
||||
* Background [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)
|
||||
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)
|
||||
|
||||
## Download
|
||||
### Download
|
||||
The latest available version is available on the [Releases page](https://github.com/jomjol/AI-on-the-edge-device/releases).
|
||||
|
||||
Initially you will have to flash it through an USB connection. Later an update is possible directly over the Air (OTA).
|
||||
### Flashing of the ESP32
|
||||
Initially you will have to flash the ESP32 through an USB connection. Later an update is possible directly over the Air (OTA).
|
||||
|
||||
### Casing
|
||||
There are different ways to flash your ESP32:
|
||||
- [Web Installer and Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) (Webbrowser based tool to flash the ESP32 and extract the Log over USB)
|
||||
- Flash Tool from Espressif
|
||||
- ESPtool (Command Line Tool)
|
||||
|
||||
See the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation) for more information.
|
||||
|
||||
## Casing
|
||||
|
||||
A 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)
|
||||
|
||||
## Build it yourself
|
||||
@@ -68,101 +77,12 @@ If you would like to support the developer with a cup of coffee you can do that
|
||||
<input type="image" src="https://www.paypalobjects.com/en_US/DK/i/btn/btn_donateCC_LG.gif" border="0" name="submit" title="PayPal - The safer, easier way to pay online!" alt="Donate with PayPal button" />
|
||||
<img alt="" border="0" src="https://www.paypal.com/en_DE/i/scr/pixel.gif" width="1" height="1" />
|
||||
</form>
|
||||
If you have any technical topics, you can file a issue in this repository.
|
||||
If you have any technical topics, you can create 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">
|
||||
|
||||
## Changelog
|
||||
**General remark:** Besides the file `firmware.bin`, typically the content of `/html` will need to be updated!
|
||||
|
||||
------
|
||||
|
||||
##### Rolling (2022-09-27)
|
||||
|
||||
- Internal improvements
|
||||
- Bug fix: html update page
|
||||
|
||||
##### Rolling (2022-09-24)
|
||||
|
||||
- Updated menue
|
||||
- Update tflite, esp32-cam-master, esp-nn (as of today 20220924)
|
||||
|
||||
##### Rolling (2022-09-21)
|
||||
|
||||
- Spelling corrections (**[cristianmitran](https://github.com/cristianmitran)**)
|
||||
|
||||
##### Rolling (2022-09-21)
|
||||
|
||||
- New update mechanism:
|
||||
- handling of all files (zip, tfl, tflite, bin) within in one updload
|
||||
- status (upload, processing, ...) displayed
|
||||
- auto suggestion for reboot (or not in case of web ui update only)
|
||||
|
||||
##### Rolling (2022-09-19)
|
||||
|
||||
- Integrated version info better into the html (main page, logfile)
|
||||
- Updated autobuild
|
||||
- Remove `/firmware` from GitHub.
|
||||
- If you want to get the latest firmware and html files, please download from the automated build action.
|
||||
|
||||
##### Rolling (2022-09-18)
|
||||
|
||||
- Updated PostProcessing with respect to `CheckDigitIncreaseConsistency`
|
||||
|
||||
##### 11.3.1 - Intermediate Digits (2022-09-17)
|
||||
|
||||
- **ATTENTION**:
|
||||
- first update the 'firmware.bin' and ensure that the new version is running
|
||||
|
||||
- Only afterwards update the 'html.zip'
|
||||
|
||||
- Otherwise the downwards compatibility of the new counter clockwise feature is not given and you end in a reboot loop, that needs manual flashing!
|
||||
|
||||
|
||||
|
||||
- **NEW v11.3.1**: corrected corrupted asset `firmware.bin`
|
||||
- Increased precision (more than 6-7 digits)
|
||||
- Implements Counter Clockwise Analog Pointers
|
||||
- Improved post processing algorithm
|
||||
- Debugging: intensive use of testcases
|
||||
- MQTT: improved handling, extended logging, automated reconnect
|
||||
- HTML: Backup Option for Configuration
|
||||
- HTML: Improved Reboot
|
||||
- HTML: Update WebUI (Reboot, Infos, CPU Temp, RSSI)
|
||||
- This version is largely also based on the work of **[caco3](https://github.com/caco3)**, **[adellafave](https://github.com/adellafave)**, **[haverland](https://github.com/haverland)**, **[stefanbode](https://github.com/stefanbode)**, **[PLCHome](https://github.com/PLCHome)**
|
||||
|
||||
##### 11.2.0 - Intermediate Digits (2022-08-28)
|
||||
|
||||
- Updated Tensorflow / TFlite to newest tflite (version as of 2022-07-27)
|
||||
- Updated analog neural network file (`ana-cont_11.3.0_s2.tflite` - default, `ana-class100_0120_s1_q.tflite`)
|
||||
- Updated digital neural network file (`dig-cont_0570_s3.tflite` - default, `dig-class100_0120_s2_q.tflite`)
|
||||
|
||||
- Added automated filtering of tflite-file in the graphical configuration (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
- Updated consistency algorithm & test cases
|
||||
- HTML: added favicon and system name, Improved reboot dialog (thanks to @**[caco3](https://github.com/caco3)**)
|
||||
|
||||
##### 11.1.1 - Intermediate Digits (2022-08-22)
|
||||
|
||||
- New and improved consistency check (especially with analog and digital counters mixed)
|
||||
- Bug Fix: digital counter algorithm
|
||||
|
||||
##### 11.0.1 - Intermediate Digits (2022-08-18)
|
||||
|
||||
- **NEW v11.0.1**: Bug Fix InfluxDB configuration (only update of html.zip necessary)
|
||||
|
||||
- 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'
|
||||
- **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)
|
||||
|
||||
- Published a tool to download and combine log files - **Thanks to **
|
||||
|
||||
- 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
|
||||
## Changes and History
|
||||
See [Changelog](Changelog.md)
|
||||
|
||||
## Tools
|
||||
|
||||
@@ -174,35 +94,3 @@ There are some ideas and feature requests which are not followed currently - mai
|
||||
|
||||
------
|
||||
|
||||
## History
|
||||
|
||||
##### 10.6.2 - Stability Increase (2022-07-24)
|
||||
|
||||
##### 9.2.0 - External Illumination (2021-12-02)
|
||||
|
||||
##### 8.5.0 Multi Meter Support (2021-10-07)
|
||||
|
||||
##### 7.1.2 MQTT-Update - (2021-06-17)
|
||||
|
||||
##### 6.7.2 Image Processing in Memory - (2021-05-01)
|
||||
|
||||
##### 5.0.0 Setup Modus - (2020-12-06)
|
||||
|
||||
##### 4.1.1 Configuration editor - (2020-12-02)
|
||||
|
||||
##### 4.0.0 Tflite Core - (2020-11-15)
|
||||
##### 3.1.0 MQTT-Client - (2020-10-26)
|
||||
|
||||
##### 2.2.1 Version Control - (2020-09-27)
|
||||
|
||||
|
||||
##### 2.1.0 Decimal Shift, Chrome & Edge - (2020-09-25)
|
||||
|
||||
|
||||
##### 2.0.0 Layout update - (2020-09-12)
|
||||
|
||||
##### 1.1.3 Initial Version - (2020-09-09)
|
||||
|
||||
|
||||
#### [Full Changelog](Changelog.md)
|
||||
|
||||
|
||||
@@ -18,16 +18,14 @@ platformio run --environment esp32cam
|
||||
|
||||
### Upload
|
||||
```
|
||||
pio run --target upload
|
||||
pio run --target upload --upload-port /dev/ttyUSB0
|
||||
```
|
||||
|
||||
If it doesnt find the device:
|
||||
1. make sure it is in bootloader mode
|
||||
1. set the UART device correctly: In `platformio.ini`, set `upload_port` correctly, eg. `upload_port = /dev/ttyUSB0`
|
||||
Alternatively you also can set the UART device in `platformio.ini`, eg. `upload_port = /dev/ttyUSB0`
|
||||
|
||||
### Monitor UART Log
|
||||
```
|
||||
pio device monitor
|
||||
pio device monitor -p /dev/ttyUSB0
|
||||
```
|
||||
|
||||
## Build and Flash with Visual Code IDE
|
||||
|
||||
Submodule code/components/esp32-camera updated: de025b8f40...5c8349f4cf
@@ -4,8 +4,9 @@
|
||||
|
||||
#include "Helper.h"
|
||||
#include "configFile.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
//static const char *TAGCONFIGFILE = "configFile";
|
||||
static const char *TAG = "CONFIG";
|
||||
|
||||
ConfigFile::ConfigFile(std::string filePath)
|
||||
{
|
||||
@@ -48,7 +49,7 @@ bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
|
||||
|
||||
if (fgets(zw, 1024, pFile))
|
||||
{
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
if ((strlen(zw) == 0) && feof(pFile))
|
||||
{
|
||||
*rt = "";
|
||||
@@ -67,7 +68,7 @@ bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
if (feof(pFile))
|
||||
{
|
||||
*rt = "";
|
||||
@@ -81,25 +82,3 @@ bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
|
||||
disabled = ((*rt)[0] == ';');
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<string> ConfigFile::ZerlegeZeile(std::string input, std::string delimiter)
|
||||
{
|
||||
std::vector<string> Output;
|
||||
// std::string delimiter = " =,";
|
||||
|
||||
input = trim(input, delimiter);
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
while (pos != std::string::npos) {
|
||||
token = input.substr(0, pos);
|
||||
token = trim(token, delimiter);
|
||||
Output.push_back(token);
|
||||
input.erase(0, pos + 1);
|
||||
input = trim(input, delimiter);
|
||||
pos = findDelimiterPos(input, delimiter);
|
||||
}
|
||||
Output.push_back(input);
|
||||
|
||||
return Output;
|
||||
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ public:
|
||||
bool isNewParagraph(std::string input);
|
||||
bool GetNextParagraph(std::string& aktparamgraph, bool &disabled, bool &eof);
|
||||
bool getNextLine(std::string* rt, bool &disabled, bool &eof);
|
||||
std::vector<std::string> ZerlegeZeile(std::string input, std::string delimiter = " =, \t");
|
||||
|
||||
private:
|
||||
FILE* pFile;
|
||||
|
||||
@@ -27,10 +27,10 @@
|
||||
#include "Helper.h"
|
||||
#include "interface_mqtt.h"
|
||||
|
||||
static const char *TAG_SERVERGPIO = "server_GPIO";
|
||||
static const char *TAG = "GPIO";
|
||||
QueueHandle_t gpio_queue_handle = NULL;
|
||||
|
||||
#define DEBUG_DETAIL_ON
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable)
|
||||
{
|
||||
@@ -43,7 +43,7 @@ GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_i
|
||||
|
||||
GpioPin::~GpioPin()
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO,"reset GPIO pin %d", _gpio);
|
||||
ESP_LOGD(TAG,"reset GPIO pin %d", _gpio);
|
||||
if (_interruptType != GPIO_INTR_DISABLE) {
|
||||
//hook isr handler for specific gpio pin
|
||||
gpio_isr_handler_remove(_gpio);
|
||||
@@ -66,13 +66,13 @@ static void IRAM_ATTR gpio_isr_handler(void* arg)
|
||||
}
|
||||
|
||||
static void gpioHandlerTask(void *arg) {
|
||||
ESP_LOGD(TAG_SERVERGPIO,"start interrupt task");
|
||||
ESP_LOGD(TAG,"start interrupt task");
|
||||
while(1){
|
||||
if(uxQueueMessagesWaiting(gpio_queue_handle)){
|
||||
while(uxQueueMessagesWaiting(gpio_queue_handle)){
|
||||
GpioResult gpioResult;
|
||||
xQueueReceive(gpio_queue_handle,(void*)&gpioResult,10);
|
||||
ESP_LOGD(TAG_SERVERGPIO,"gpio: %d state: %d", gpioResult.gpio, gpioResult.value);
|
||||
ESP_LOGD(TAG,"gpio: %d state: %d", gpioResult.gpio, gpioResult.value);
|
||||
((GpioHandler*)arg)->gpioInterrupt(&gpioResult);
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ static void gpioHandlerTask(void *arg) {
|
||||
|
||||
void GpioPin::gpioInterrupt(int value) {
|
||||
if (_mqttTopic != "") {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "gpioInterrupt %s %d", _mqttTopic.c_str(), value);
|
||||
ESP_LOGD(TAG, "gpioInterrupt %s %d", _mqttTopic.c_str(), value);
|
||||
|
||||
MQTTPublish(_mqttTopic, value ? "true" : "false");
|
||||
currentState = value;
|
||||
@@ -110,7 +110,7 @@ void GpioPin::init()
|
||||
// if (_interruptType != GPIO_INTR_DISABLE) { // ohne GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X, wenn das genutzt wird, dann soll auch der Handler hier nicht initialisiert werden, da das dann über SmartLED erfolgt.
|
||||
if ((_interruptType != GPIO_INTR_DISABLE) && (_interruptType != GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X)) {
|
||||
//hook isr handler for specific gpio pin
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GpioPin::init add isr handler for GPIO %d\r\n", _gpio);
|
||||
ESP_LOGD(TAG, "GpioPin::init add isr handler for GPIO %d", _gpio);
|
||||
gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*)&_gpio);
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ bool GpioPin::getValue(std::string* errorText)
|
||||
|
||||
void GpioPin::setValue(bool value, gpio_set_source setSource, std::string* errorText)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GpioPin::setValue %d\r\n", value);
|
||||
ESP_LOGD(TAG, "GpioPin::setValue %d", value);
|
||||
|
||||
if ((_mode != GPIO_PIN_MODE_OUTPUT) && (_mode != GPIO_PIN_MODE_OUTPUT_PWM) && (_mode != GPIO_PIN_MODE_BUILT_IN_FLASH_LED)) {
|
||||
(*errorText) = "GPIO is not in output mode";
|
||||
@@ -147,14 +147,14 @@ void GpioPin::setValue(bool value, gpio_set_source setSource, std::string* error
|
||||
void GpioPin::publishState() {
|
||||
int newState = gpio_get_level(_gpio);
|
||||
if (newState != currentState) {
|
||||
ESP_LOGD(TAG_SERVERGPIO,"publish state of GPIO %d new state %d", _gpio, newState);
|
||||
ESP_LOGD(TAG,"publish state of GPIO %d new state %d", _gpio, newState);
|
||||
MQTTPublish(_mqttTopic, newState ? "true" : "false");
|
||||
currentState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GpioPin::handleMQTT data %.*s\r\n", data_len, data);
|
||||
ESP_LOGD(TAG, "GpioPin::handleMQTT data %.*s", data_len, data);
|
||||
|
||||
std::string dataStr(data, data_len);
|
||||
dataStr = toLower(dataStr);
|
||||
@@ -169,7 +169,7 @@ bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
|
||||
}
|
||||
|
||||
if (errorText != "") {
|
||||
ESP_LOGE(TAG_SERVERGPIO, "%s", errorText.c_str());
|
||||
ESP_LOGE(TAG, "%s", errorText.c_str());
|
||||
}
|
||||
|
||||
return (errorText == "");
|
||||
@@ -178,7 +178,7 @@ bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
|
||||
|
||||
esp_err_t callHandleHttpRequest(httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO,"callHandleHttpRequest");
|
||||
ESP_LOGD(TAG,"callHandleHttpRequest");
|
||||
|
||||
GpioHandler *gpioHandler = (GpioHandler*)req->user_ctx;
|
||||
return gpioHandler->handleHttpRequest(req);
|
||||
@@ -186,17 +186,17 @@ esp_err_t callHandleHttpRequest(httpd_req_t *req)
|
||||
|
||||
void taskGpioHandler(void *pvParameter)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO,"taskGpioHandler");
|
||||
ESP_LOGD(TAG,"taskGpioHandler");
|
||||
((GpioHandler*)pvParameter)->init();
|
||||
}
|
||||
|
||||
GpioHandler::GpioHandler(std::string configFile, httpd_handle_t httpServer)
|
||||
{
|
||||
ESP_LOGI(TAG_SERVERGPIO,"start GpioHandler");
|
||||
ESP_LOGI(TAG,"start GpioHandler");
|
||||
_configFile = configFile;
|
||||
_httpServer = httpServer;
|
||||
|
||||
ESP_LOGI(TAG_SERVERGPIO, "register GPIO Uri");
|
||||
ESP_LOGI(TAG, "register GPIO Uri");
|
||||
registerGpioUri();
|
||||
}
|
||||
|
||||
@@ -210,10 +210,10 @@ GpioHandler::~GpioHandler() {
|
||||
void GpioHandler::init()
|
||||
{
|
||||
// TickType_t xDelay = 60000 / portTICK_PERIOD_MS;
|
||||
// printf("wait before start %ldms\r\n", (long) xDelay);
|
||||
// ESP_LOGD(TAG, "wait before start %ldms", (long) xDelay);
|
||||
// vTaskDelay( xDelay );
|
||||
|
||||
printf("*************** Start GPIOHandler_Init *****************\n");
|
||||
ESP_LOGD(TAG, "*************** Start GPIOHandler_Init *****************");
|
||||
|
||||
if (gpioMap == NULL) {
|
||||
gpioMap = new std::map<gpio_num_t, GpioPin*>();
|
||||
@@ -222,12 +222,12 @@ void GpioHandler::init()
|
||||
}
|
||||
|
||||
|
||||
ESP_LOGI(TAG_SERVERGPIO, "read GPIO config and init GPIO");
|
||||
ESP_LOGI(TAG, "read GPIO config and init GPIO");
|
||||
if (!readConfig()) {
|
||||
clear();
|
||||
delete gpioMap;
|
||||
gpioMap = NULL;
|
||||
ESP_LOGI(TAG_SERVERGPIO, "GPIO init completed, handler is disabled");
|
||||
ESP_LOGI(TAG, "GPIO init completed, handler is disabled");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,13 +243,13 @@ void GpioHandler::init()
|
||||
gpio_queue_handle = xQueueCreate(10,sizeof(GpioResult));
|
||||
BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", configMINIMAL_STACK_SIZE * 8, (void *)this, tskIDLE_PRIORITY + 2, &xHandleTaskGpio);
|
||||
if(xReturned == pdPASS ) {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "xHandletaskGpioHandler started");
|
||||
ESP_LOGD(TAG, "xHandletaskGpioHandler started");
|
||||
} else {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "xHandletaskGpioHandler not started %d ", (int)xHandleTaskGpio);
|
||||
ESP_LOGD(TAG, "xHandletaskGpioHandler not started %d ", (int)xHandleTaskGpio);
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_SERVERGPIO, "GPIO init completed, is enabled");
|
||||
ESP_LOGI(TAG, "GPIO init completed, is enabled");
|
||||
}
|
||||
|
||||
void GpioHandler::taskHandler() {
|
||||
@@ -300,13 +300,13 @@ bool GpioHandler::readConfig()
|
||||
bool eof = false;
|
||||
gpio_num_t gpioExtLED = (gpio_num_t) 0;
|
||||
|
||||
// printf("readConfig - Start 1\n");
|
||||
// ESP_LOGD(TAG, "readConfig - Start 1");
|
||||
|
||||
while ((!configFile.GetNextParagraph(line, disabledLine, eof) || (line.compare("[GPIO]") != 0)) && !eof) {}
|
||||
if (eof)
|
||||
return false;
|
||||
|
||||
// printf("readConfig - Start 2 line: %s, disabbledLine: %d\n", line.c_str(), (int) disabledLine);
|
||||
// ESP_LOGD(TAG, "readConfig - Start 2 line: %s, disabbledLine: %d", line.c_str(), (int) disabledLine);
|
||||
|
||||
|
||||
_isEnabled = !disabledLine;
|
||||
@@ -314,32 +314,32 @@ bool GpioHandler::readConfig()
|
||||
if (!_isEnabled)
|
||||
return false;
|
||||
|
||||
// printf("readConfig - Start 3\n");
|
||||
// ESP_LOGD(TAG, "readConfig - Start 3");
|
||||
|
||||
// std::string mainTopicMQTT = "";
|
||||
std::string mainTopicMQTT = GetMQTTMainTopic();
|
||||
if (mainTopicMQTT.length() > 0)
|
||||
{
|
||||
mainTopicMQTT = mainTopicMQTT + "/GPIO";
|
||||
ESP_LOGD(TAG_SERVERGPIO, "MAINTOPICMQTT found\r\n");
|
||||
ESP_LOGD(TAG, "MAINTOPICMQTT found");
|
||||
}
|
||||
|
||||
bool registerISR = false;
|
||||
while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line))
|
||||
{
|
||||
zerlegt = configFile.ZerlegeZeile(line);
|
||||
zerlegt = ZerlegeZeile(line);
|
||||
// const std::regex pieces_regex("IO([0-9]{1,2})");
|
||||
// std::smatch pieces_match;
|
||||
// if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
|
||||
// {
|
||||
// std::string gpioStr = pieces_match[1];
|
||||
ESP_LOGD(TAG_SERVERGPIO, "conf param %s\r\n", toUpper(zerlegt[0]).c_str());
|
||||
ESP_LOGD(TAG, "conf param %s", toUpper(zerlegt[0]).c_str());
|
||||
if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") {
|
||||
// ESP_LOGD(TAG_SERVERGPIO, "MAINTOPICMQTT found\r\n");
|
||||
// ESP_LOGD(TAG, "MAINTOPICMQTT found");
|
||||
// mainTopicMQTT = zerlegt[1];
|
||||
} else if ((zerlegt[0].rfind("IO", 0) == 0) && (zerlegt.size() >= 6))
|
||||
{
|
||||
ESP_LOGI(TAG_SERVERGPIO,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str());
|
||||
ESP_LOGI(TAG,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str());
|
||||
std::string gpioStr = zerlegt[0].substr(2, 2);
|
||||
gpio_num_t gpioNr = (gpio_num_t)atoi(gpioStr.c_str());
|
||||
gpio_pin_mode_t pinMode = resolvePinMode(toLower(zerlegt[1]));
|
||||
@@ -359,7 +359,7 @@ bool GpioHandler::readConfig()
|
||||
|
||||
if (pinMode == GPIO_PIN_MODE_EXTERNAL_FLASH_WS281X)
|
||||
{
|
||||
printf("Set WS2812 to GPIO %d\n", gpioNr);
|
||||
ESP_LOGD(TAG, "Set WS2812 to GPIO %d", gpioNr);
|
||||
gpioExtLED = gpioNr;
|
||||
}
|
||||
|
||||
@@ -400,10 +400,10 @@ bool GpioHandler::readConfig()
|
||||
|
||||
if (gpioExtLED > 0)
|
||||
{
|
||||
// LogFile.WriteToFile("Startsequence 06"); // Nremove
|
||||
// LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Startsequence 06"); // Nremove
|
||||
// vTaskDelay( xDelay );
|
||||
// xDelay = 5000 / portTICK_PERIOD_MS;
|
||||
// printf("main: sleep for : %ldms\n", (long) xDelay);
|
||||
// ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
|
||||
|
||||
// SmartLed leds( LED_WS2812, 2, GPIO_NUM_12, 0, DoubleBuffer );
|
||||
|
||||
@@ -420,7 +420,7 @@ bool GpioHandler::readConfig()
|
||||
|
||||
void GpioHandler::clear()
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::clear\r\n");
|
||||
ESP_LOGD(TAG, "GpioHandler::clear");
|
||||
|
||||
if (gpioMap != NULL) {
|
||||
for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it) {
|
||||
@@ -434,7 +434,7 @@ void GpioHandler::clear()
|
||||
|
||||
void GpioHandler::registerGpioUri()
|
||||
{
|
||||
ESP_LOGI(TAG_SERVERGPIO, "server_GPIO - Registering URI handlers");
|
||||
ESP_LOGI(TAG, "server_GPIO - Registering URI handlers");
|
||||
|
||||
httpd_uri_t camuri = { };
|
||||
camuri.method = HTTP_GET;
|
||||
@@ -446,7 +446,7 @@ void GpioHandler::registerGpioUri()
|
||||
|
||||
esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "handleHttpRequest");
|
||||
ESP_LOGD(TAG, "handleHttpRequest");
|
||||
|
||||
if (gpioMap == NULL) {
|
||||
std::string resp_str = "GPIO handler not initialized";
|
||||
@@ -458,18 +458,18 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_switch_GPIO - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile("handler_switch_GPIO");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_switch_GPIO");
|
||||
char _query[200];
|
||||
char _valueGPIO[30];
|
||||
char _valueStatus[30];
|
||||
std::string gpio, status;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK) {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "Query: %s", _query);
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "GPIO", _valueGPIO, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GPIO is found %s", _valueGPIO);
|
||||
ESP_LOGD(TAG, "GPIO is found %s", _valueGPIO);
|
||||
gpio = std::string(_valueGPIO);
|
||||
} else {
|
||||
std::string resp_str = "GPIO No is not defined";
|
||||
@@ -478,7 +478,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
|
||||
}
|
||||
if (httpd_query_key_value(_query, "Status", _valueStatus, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "Status is found %s", _valueStatus);
|
||||
ESP_LOGD(TAG, "Status is found %s", _valueStatus);
|
||||
status = std::string(_valueStatus);
|
||||
}
|
||||
} else {
|
||||
@@ -541,7 +541,7 @@ esp_err_t GpioHandler::handleHttpRequest(httpd_req_t *req)
|
||||
|
||||
void GpioHandler::flashLightEnable(bool value)
|
||||
{
|
||||
ESP_LOGD(TAG_SERVERGPIO, "GpioHandler::flashLightEnable %s\r\n", value ? "true" : "false");
|
||||
ESP_LOGD(TAG, "GpioHandler::flashLightEnable %s", value ? "true" : "false");
|
||||
|
||||
if (gpioMap != NULL) {
|
||||
for(std::map<gpio_num_t, GpioPin*>::iterator it = gpioMap->begin(); it != gpioMap->end(); ++it)
|
||||
@@ -552,9 +552,9 @@ void GpioHandler::flashLightEnable(bool value)
|
||||
it->second->setValue(value, GPIO_SET_SOURCE_INTERNAL, &resp_str);
|
||||
|
||||
if (resp_str == "") {
|
||||
ESP_LOGD(TAG_SERVERGPIO, "Flash light pin GPIO %d switched to %s\r\n", (int)it->first, (value ? "on" : "off"));
|
||||
ESP_LOGD(TAG, "Flash light pin GPIO %d switched to %s", (int)it->first, (value ? "on" : "off"));
|
||||
} else {
|
||||
ESP_LOGE(TAG_SERVERGPIO, "Can't set flash light pin GPIO %d. Error: %s\r\n", (int)it->first, resp_str.c_str());
|
||||
ESP_LOGE(TAG, "Can't set flash light pin GPIO %d. Error: %s", (int)it->first, resp_str.c_str());
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -562,7 +562,7 @@ void GpioHandler::flashLightEnable(bool value)
|
||||
{
|
||||
#ifdef __LEDGLOBAL
|
||||
if (leds_global == NULL) {
|
||||
ESP_LOGI(TAG_SERVERGPIO, "init SmartLed: LEDNumber=%d, GPIO=%d", LEDNumbers, (int)it->second->getGPIO());
|
||||
ESP_LOGI(TAG, "init SmartLed: LEDNumber=%d, GPIO=%d", LEDNumbers, (int)it->second->getGPIO());
|
||||
leds_global = new SmartLed( LEDType, LEDNumbers, it->second->getGPIO(), 0, DoubleBuffer );
|
||||
} else {
|
||||
// wait until we can update: https://github.com/RoboticsBrno/SmartLeds/issues/10#issuecomment-386921623
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
|
||||
static const char *TAGCAMERACLASS = "server_part_camera";
|
||||
static const char *TAG = "CAM";
|
||||
|
||||
static camera_config_t camera_config = {
|
||||
.pin_pwdn = CAM_PIN_PWDN,
|
||||
@@ -249,7 +249,7 @@ void CCamera::SetQualitySize(int qual, framesize_t resol)
|
||||
|
||||
void CCamera::EnableAutoExposure(int flashdauer)
|
||||
{
|
||||
printf("EnableAutoExposure");
|
||||
ESP_LOGD(TAG, "EnableAutoExposure");
|
||||
LEDOnOff(true);
|
||||
if (flashdauer > 0)
|
||||
LightOnOff(true);
|
||||
@@ -260,11 +260,10 @@ void CCamera::EnableAutoExposure(int flashdauer)
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAGCAMERACLASS, "Camera Capture Failed");
|
||||
ESP_LOGE(TAG, "Camera Capture Failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Camera Capture Failed (Procedure 'EnableAutoExposure') --> Reboot"
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Capture Failed (Procedure 'EnableAutoExposure') --> Reboot! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
//doReboot();
|
||||
}
|
||||
@@ -311,12 +310,11 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAGCAMERACLASS, "CaptureToBasisImage: Camera Capture Failed");
|
||||
ESP_LOGE(TAG, "CaptureToBasisImage: Capture Failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Camera is not working anymore (CCamera::CaptureToBasisImage) - most probably caused by a hardware problem (instablility, ...). "
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "is not working anymore (CCamera::CaptureToBasisImage) - most probably caused by a hardware problem (instablility, ...). "
|
||||
"System will reboot.");
|
||||
doReboot();
|
||||
|
||||
@@ -327,9 +325,8 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
zwischenspeicher = (uint8_t*) malloc(_size);
|
||||
if (!zwischenspeicher)
|
||||
{
|
||||
ESP_LOGE(TAGCAMERACLASS, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
ESP_LOGE(TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
}
|
||||
for (int i = 0; i < _size; ++i)
|
||||
*(zwischenspeicher + i) = *(fb->buf + i);
|
||||
@@ -366,7 +363,7 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
|
||||
_zw = _zw + " _zwImage: " + std::to_string((int) _zwImage.rgb_image) + " Size: " + std::to_string(_zwImage.width) + ", " + std::to_string(_zwImage.height);
|
||||
LogFile.WriteToFile(_zw);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
#endif
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
@@ -410,11 +407,10 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAGCAMERACLASS, "CaptureToFile: Camera Capture Failed");
|
||||
ESP_LOGE(TAG, "CaptureToFile: Camera Capture Failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Camera Capture Failed (CCamera::CaptureToFile) --> Reboot"
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Capture Failed (CCamera::CaptureToFile) --> Reboot! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
//doReboot();
|
||||
|
||||
@@ -423,19 +419,19 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
LEDOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("w %d, h %d, size %d\n", fb->width, fb->height, fb->len);
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
#endif
|
||||
|
||||
nm = FormatFileName(nm);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Save Camera to : %s\n", nm.c_str());
|
||||
ESP_LOGD(TAG, "Save Camera to : %s", nm.c_str());
|
||||
#endif
|
||||
|
||||
ftype = toUpper(getFileType(nm));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Filetype: %s\n", ftype.c_str());
|
||||
ESP_LOGD(TAG, "Filetype: %s", ftype.c_str());
|
||||
#endif
|
||||
|
||||
uint8_t * buf = NULL;
|
||||
@@ -453,7 +449,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
bool jpeg_converted = frame2jpg(fb, ActualQuality, &buf, &buf_len);
|
||||
converted = true;
|
||||
if(!jpeg_converted){
|
||||
ESP_LOGE(TAGCAMERACLASS, "JPEG compression failed");
|
||||
ESP_LOGE(TAG, "JPEG compression failed");
|
||||
}
|
||||
} else {
|
||||
buf_len = fb->len;
|
||||
@@ -507,7 +503,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAGCAMERACLASS, "Camera capture failed");
|
||||
ESP_LOGE(TAG, "Camera capture failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
httpd_resp_send_500(req);
|
||||
@@ -537,7 +533,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
esp_camera_fb_return(fb);
|
||||
int64_t fr_end = esp_timer_get_time();
|
||||
|
||||
ESP_LOGI(TAGCAMERACLASS, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000));
|
||||
ESP_LOGI(TAG, "JPG: %uKB %ums", (uint32_t)(fb_len/1024), (uint32_t)((fr_end - fr_start)/1000));
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
@@ -551,20 +547,20 @@ void CCamera::LightOnOff(bool status)
|
||||
{
|
||||
GpioHandler* gpioHandler = gpio_handler_get();
|
||||
if ((gpioHandler != NULL) && (gpioHandler->isEnabled())) {
|
||||
printf("Use gpioHandler flashLigh\n");
|
||||
ESP_LOGD(TAG, "Use gpioHandler flashLigh");
|
||||
gpioHandler->flashLightEnable(status);
|
||||
} else {
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
if (status)
|
||||
{
|
||||
printf("Internal Flash-LED turn on with PWM %d\n", led_intensity);
|
||||
ESP_LOGD(TAG, "Internal Flash-LED turn on with PWM %d", led_intensity);
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, led_intensity));
|
||||
// Update duty to apply the new value
|
||||
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Internal Flash-LED turn off PWM\n");
|
||||
ESP_LOGD(TAG, "Internal Flash-LED turn off PWM");
|
||||
ESP_ERROR_CHECK(ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, 0));
|
||||
ESP_ERROR_CHECK(ledc_update_duty(LEDC_MODE, LEDC_CHANNEL));
|
||||
}
|
||||
@@ -608,11 +604,11 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "size", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Size: "); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "Size: %s", _size);
|
||||
#endif
|
||||
if (strcmp(_size, "QVGA") == 0)
|
||||
resol = FRAMESIZE_QVGA; // 320x240
|
||||
@@ -630,7 +626,7 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
|
||||
if (httpd_query_key_value(_query, "quality", _qual, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Quality: "); printf(_qual); printf("\n");
|
||||
ESP_LOGD(TAG, "Quality: %s", _qual);
|
||||
#endif
|
||||
qual = atoi(_qual);
|
||||
|
||||
@@ -663,7 +659,7 @@ framesize_t CCamera::TextToFramesize(const char * _size)
|
||||
CCamera::CCamera()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("CreateClassCamera\n");
|
||||
ESP_LOGD(TAG, "CreateClassCamera");
|
||||
#endif
|
||||
brightness = -5;
|
||||
contrast = -5;
|
||||
@@ -675,13 +671,13 @@ CCamera::CCamera()
|
||||
|
||||
esp_err_t CCamera::InitCam()
|
||||
{
|
||||
printf("Init Camera\n");
|
||||
ESP_LOGD(TAG, "Init Camera");
|
||||
ActualQuality = camera_config.jpeg_quality;
|
||||
ActualResolution = camera_config.frame_size;
|
||||
//initialize the camera
|
||||
esp_err_t err = esp_camera_init(&camera_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAGCAMERACLASS, "Camera Init Failed");
|
||||
ESP_LOGE(TAG, "Camera Init Failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
@@ -694,6 +690,6 @@ void CCamera::SetLEDIntensity(float _intrel)
|
||||
_intrel = max(_intrel, (float) 0);
|
||||
_intrel = _intrel / 100;
|
||||
led_intensity = (int) (_intrel * 8191);
|
||||
printf("Set led_intensity to %d of 8191\n", led_intensity);
|
||||
ESP_LOGD(TAG, "Set led_intensity to %d of 8191", led_intensity);
|
||||
|
||||
}
|
||||
|
||||
@@ -7,16 +7,18 @@
|
||||
#include "ClassControllCamera.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "server_cam";
|
||||
|
||||
#define SCRATCH_BUFSIZE2 8192
|
||||
char scratch2[SCRATCH_BUFSIZE2];
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
static const char *TAGPARTCAMERA = "server_camera";
|
||||
|
||||
|
||||
void PowerResetCamera(){
|
||||
ESP_LOGD(TAGPARTCAMERA, "Resetting camera by power down line");
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
gpio_config_t conf;
|
||||
conf.intr_type = GPIO_INTR_DISABLE;
|
||||
conf.pin_bit_mask = 1LL << GPIO_NUM_32;
|
||||
@@ -37,7 +39,7 @@ esp_err_t handler_lightOn(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOn - Start");
|
||||
printf("handler_lightOn uri:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
|
||||
#endif
|
||||
|
||||
Camera.LightOnOff(true);
|
||||
@@ -55,7 +57,7 @@ esp_err_t handler_lightOff(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOff - Start");
|
||||
printf("handler_lightOff uri:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
|
||||
#endif
|
||||
Camera.LightOnOff(false);
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
@@ -80,7 +82,7 @@ esp_err_t handler_capture(httpd_req_t *req)
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Size: %d", res); printf(" Quality: %d\n", quality);
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
@@ -110,11 +112,11 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req)
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Delay: "); printf(_delay); printf("\n");
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
|
||||
@@ -126,7 +128,7 @@ esp_err_t handler_capture_with_ligth(httpd_req_t *req)
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Size: %d", res); printf(" Quality: %d\n", quality);
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
@@ -166,12 +168,12 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
|
||||
{
|
||||
fn.append(filename);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Filename: "); printf(fn.c_str()); printf("\n");
|
||||
ESP_LOGD(TAG, "Filename: %s", fn.c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
@@ -180,7 +182,7 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Delay: "); printf(_delay); printf("\n");
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
|
||||
@@ -194,7 +196,7 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Size: %d", res); printf(" Quality: %d\n", quality);
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
Camera.SetQualitySize(quality, res);
|
||||
|
||||
@@ -216,7 +218,7 @@ esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
void register_server_camera_uri(httpd_handle_t server)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGI(TAGPARTCAMERA, "server_part_camera - Registering URI handlers");
|
||||
ESP_LOGI(TAG, "server_part_camera - Registering URI handlers");
|
||||
#endif
|
||||
|
||||
httpd_uri_t camuri = { };
|
||||
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "." "../../include"
|
||||
REQUIRES tflite-lib esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper jomjol_controlGPIO)
|
||||
REQUIRES tflite-lib esp_http_server app_update esp_http_client nvs_flash jomjol_tfliteclass jomjol_flowcontroll spiffs jomjol_helper jomjol_controlGPIO miniz)
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ extern "C" {
|
||||
#include "defines.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "server_tflite.h"
|
||||
|
||||
#include "server_help.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "server_GPIO.h"
|
||||
@@ -43,6 +45,8 @@ extern "C" {
|
||||
#include "Helper.h"
|
||||
#include "miniz.h"
|
||||
|
||||
static const char *TAG = "OTA FILE";
|
||||
|
||||
/* Max length a file path can have on storage */
|
||||
// #define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
|
||||
#define FILE_PATH_MAX (255)
|
||||
@@ -56,6 +60,9 @@ extern "C" {
|
||||
/* Scratch buffer size */
|
||||
#define SCRATCH_BUFSIZE 4096
|
||||
|
||||
/* Size of partial log file to return */
|
||||
#define LOGFILE_LAST_PART_BYTES SCRATCH_BUFSIZE * 20 /* 80 kBytes */
|
||||
|
||||
struct file_server_data {
|
||||
/* Base path of file storage */
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
@@ -64,8 +71,6 @@ struct file_server_data {
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
};
|
||||
|
||||
static const char *TAG_FILESERVER = "file_server";
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sys/types.h>
|
||||
@@ -76,19 +81,35 @@ using namespace std;
|
||||
string SUFFIX_ZW = "_0xge";
|
||||
|
||||
|
||||
esp_err_t get_tflite_file_handler(httpd_req_t *req)
|
||||
{
|
||||
// DIR *verzeichnis;
|
||||
// struct dirent *files;
|
||||
struct dirent *entry;
|
||||
// struct stat entry_stat;
|
||||
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file);
|
||||
static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file);
|
||||
|
||||
|
||||
esp_err_t get_numbers_file_handler(httpd_req_t *req)
|
||||
{
|
||||
std::string ret = tfliteflow.getNumbersName();
|
||||
|
||||
// ESP_LOGI(TAG, "Result get_numbers_file_handler: %s", ret.c_str());
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "text/plain");
|
||||
|
||||
httpd_resp_sendstr_chunk(req, ret.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t get_data_file_handler(httpd_req_t *req)
|
||||
{
|
||||
struct dirent *entry;
|
||||
|
||||
std::string _filename, _fileext;
|
||||
size_t pos = 0;
|
||||
|
||||
const char verz_name[] = "/sdcard/config";
|
||||
printf("Suche TFLITE in /sdcard/config/\n");
|
||||
const char verz_name[] = "/sdcard/log/data";
|
||||
ESP_LOGD(TAG, "Suche data files in /sdcard/log/data");
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "text/plain");
|
||||
@@ -97,7 +118,7 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
_filename = std::string(entry->d_name);
|
||||
printf("File: %s\t", _filename.c_str());
|
||||
ESP_LOGD(TAG, "File: %s", _filename.c_str());
|
||||
|
||||
// ignore all files with starting dot (hidden files)
|
||||
if (_filename.rfind(".", 0) == 0) {
|
||||
@@ -109,7 +130,51 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req)
|
||||
if (pos != std::string::npos)
|
||||
_fileext = _fileext.erase(0, pos + 1);
|
||||
|
||||
printf(" Extension: %s\n", _fileext.c_str());
|
||||
ESP_LOGD(TAG, " Extension: %s", _fileext.c_str());
|
||||
|
||||
if (_fileext == "csv")
|
||||
{
|
||||
_filename = _filename + "\t";
|
||||
httpd_resp_sendstr_chunk(req, _filename.c_str());
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t get_tflite_file_handler(httpd_req_t *req)
|
||||
{
|
||||
struct dirent *entry;
|
||||
|
||||
std::string _filename, _fileext;
|
||||
size_t pos = 0;
|
||||
|
||||
const char verz_name[] = "/sdcard/config";
|
||||
ESP_LOGD(TAG, "Suche TFLITE in /sdcard/config/");
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "text/plain");
|
||||
|
||||
DIR *dir = opendir(verz_name);
|
||||
while ((entry = readdir(dir)) != NULL)
|
||||
{
|
||||
_filename = std::string(entry->d_name);
|
||||
ESP_LOGD(TAG, "File: %s", _filename.c_str());
|
||||
|
||||
// ignore all files with starting dot (hidden files)
|
||||
if (_filename.rfind(".", 0) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
_fileext = _filename;
|
||||
pos = _fileext.find_last_of(".");
|
||||
if (pos != std::string::npos)
|
||||
_fileext = _fileext.erase(0, pos + 1);
|
||||
|
||||
ESP_LOGD(TAG, " Extension: %s", _fileext.c_str());
|
||||
|
||||
if ((_fileext == "tfl") || (_fileext == "tflite"))
|
||||
{
|
||||
@@ -147,14 +212,14 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
DIR *dir = opendir(dirpath_corrected);
|
||||
|
||||
const size_t dirpath_len = strlen(dirpath);
|
||||
printf("Dirpath: <%s>, Pathlength: %d\n", dirpath, dirpath_len);
|
||||
ESP_LOGD(TAG, "Dirpath: <%s>, Pathlength: %d", dirpath, dirpath_len);
|
||||
|
||||
/* Retrieve the base path of file storage to construct the full path */
|
||||
strlcpy(entrypath, dirpath, sizeof(entrypath));
|
||||
printf("entrypath: <%s>\n", entrypath);
|
||||
ESP_LOGD(TAG, "entrypath: <%s>", entrypath);
|
||||
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to stat dir : %s", dirpath);
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", dirpath);
|
||||
/* Respond with 404 Not Found */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
|
||||
return ESP_FAIL;
|
||||
@@ -170,11 +235,11 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
size_t chunksize;
|
||||
do {
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
// printf("Chunksize %d\n", chunksize);
|
||||
// ESP_LOGD(TAG, "Chunksize %d", chunksize);
|
||||
if (chunksize > 0){
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
fclose(fd);
|
||||
ESP_LOGE(TAG_FILESERVER, "File sending failed!");
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
@@ -211,13 +276,13 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
entrytype = (entry->d_type == DT_DIR ? "directory" : "file");
|
||||
|
||||
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
|
||||
printf("Entrypath: %s\n", entrypath);
|
||||
ESP_LOGD(TAG, "Entrypath: %s", entrypath);
|
||||
if (stat(entrypath, &entry_stat) == -1) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to stat %s : %s", entrytype, entry->d_name);
|
||||
ESP_LOGE(TAG, "Failed to stat %s : %s", entrytype, entry->d_name);
|
||||
continue;
|
||||
}
|
||||
sprintf(entrysize, "%ld", entry_stat.st_size);
|
||||
ESP_LOGI(TAG_FILESERVER, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
|
||||
ESP_LOGI(TAG, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
|
||||
|
||||
/* Send chunk of HTML file containing table entries with file name and size */
|
||||
httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
|
||||
@@ -260,24 +325,43 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
|
||||
|
||||
static esp_err_t logfileact_get_handler(httpd_req_t *req)
|
||||
static esp_err_t logfileact_get_full_handler(httpd_req_t *req) {
|
||||
return send_logfile(req, true);
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t logfileact_get_last_part_handler(httpd_req_t *req) {
|
||||
return send_logfile(req, false);
|
||||
}
|
||||
|
||||
static esp_err_t datafileact_get_full_handler(httpd_req_t *req) {
|
||||
return send_datafile(req, true);
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req) {
|
||||
return send_datafile(req, false);
|
||||
}
|
||||
|
||||
static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile("logfileact_get_handler");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "data_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
printf("uri: %s\n", req->uri);
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
const char* filename = "log_current.txt";
|
||||
const char* filename = "";
|
||||
|
||||
printf("uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
std::string currentfilename = LogFile.GetCurrentFileNameData();
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileName();
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to read existing file : %s", filepath);
|
||||
ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
return ESP_FAIL;
|
||||
@@ -285,9 +369,35 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
// ESP_LOGI(TAG_FILESERVER, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
|
||||
// ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
|
||||
set_content_type_from_file(req, filename);
|
||||
|
||||
if (!send_full_file) { // Send only last part of file
|
||||
ESP_LOGD(TAG, "Sending last %d bytes of the actual datafile!", LOGFILE_LAST_PART_BYTES);
|
||||
|
||||
/* Adapted from https://www.geeksforgeeks.org/implement-your-own-tail-read-last-n-lines-of-a-huge-file/ */
|
||||
if (fseek(fd, 0, SEEK_END)) {
|
||||
ESP_LOGE(TAG, "Failed to get to end of file!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
else {
|
||||
long pos = ftell(fd); // Number of bytes in the file
|
||||
ESP_LOGI(TAG, "File contains %ld bytes", pos);
|
||||
|
||||
if (fseek(fd, pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos), SEEK_SET)) { // Go LOGFILE_LAST_PART_BYTES bytes back from EOF
|
||||
ESP_LOGE(TAG, "Failed to go back %ld bytes within the file!", std::min((long)LOGFILE_LAST_PART_BYTES, pos));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find end of line */
|
||||
while (1) {
|
||||
if (fgetc(fd) == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
size_t chunksize;
|
||||
@@ -298,7 +408,7 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
fclose(fd);
|
||||
ESP_LOGE(TAG_FILESERVER, "File sending failed!");
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
@@ -311,7 +421,7 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
|
||||
|
||||
/* Close file after sending complete */
|
||||
fclose(fd);
|
||||
ESP_LOGI(TAG_FILESERVER, "File sending complete");
|
||||
ESP_LOGI(TAG, "File sending complete");
|
||||
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
@@ -319,31 +429,111 @@ static esp_err_t logfileact_get_handler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
ESP_LOGI(TAG, "uri: %s", req->uri);
|
||||
|
||||
const char* filename = "";
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileName();
|
||||
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
// ESP_LOGI(TAG, "Sending file : %s (%ld bytes)...", &filename, file_stat.st_size);
|
||||
set_content_type_from_file(req, filename);
|
||||
|
||||
if (!send_full_file) { // Send only last part of file
|
||||
ESP_LOGD(TAG, "Sending last %d bytes of the actual logfile!", LOGFILE_LAST_PART_BYTES);
|
||||
|
||||
/* Adapted from https://www.geeksforgeeks.org/implement-your-own-tail-read-last-n-lines-of-a-huge-file/ */
|
||||
if (fseek(fd, 0, SEEK_END)) {
|
||||
ESP_LOGE(TAG, "Failed to get to end of file!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
else {
|
||||
long pos = ftell(fd); // Number of bytes in the file
|
||||
ESP_LOGI(TAG, "File contains %ld bytes", pos);
|
||||
|
||||
if (fseek(fd, pos - std::min((long)LOGFILE_LAST_PART_BYTES, pos), SEEK_SET)) { // Go LOGFILE_LAST_PART_BYTES bytes back from EOF
|
||||
ESP_LOGE(TAG, "Failed to go back %ld bytes within the file!", std::min((long)LOGFILE_LAST_PART_BYTES, pos));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find end of line */
|
||||
while (1) {
|
||||
if (fgetc(fd) == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
fclose(fd);
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Keep looping till the whole file is sent */
|
||||
} while (chunksize != 0);
|
||||
|
||||
/* Close file after sending complete */
|
||||
fclose(fd);
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Handler to download a file kept on the server */
|
||||
static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
{
|
||||
LogFile.WriteToFile("download_get_handler");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "download_get_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
struct stat file_stat;
|
||||
printf("uri: %s\n", req->uri);
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
req->uri + sizeof("/fileserver") - 1, sizeof(filepath));
|
||||
|
||||
printf("uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
// filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
// req->uri, sizeof(filepath));
|
||||
|
||||
|
||||
if (!filename) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Filename is too long");
|
||||
ESP_LOGE(TAG, "Filename is too long");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
@@ -356,17 +546,17 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
if (buf_len > 1) {
|
||||
char buf[buf_len];
|
||||
if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK) {
|
||||
ESP_LOGI(TAG_FILESERVER, "Found URL query => %s", buf);
|
||||
ESP_LOGI(TAG, "Found URL query => %s", buf);
|
||||
char param[32];
|
||||
/* Get value of expected key from query string */
|
||||
if (httpd_query_key_value(buf, "readonly", param, sizeof(param)) == ESP_OK) {
|
||||
ESP_LOGI(TAG_FILESERVER, "Found URL query parameter => readonly=%s", param);
|
||||
ESP_LOGI(TAG, "Found URL query parameter => readonly=%s", param);
|
||||
readonly = param && strcmp(param,"true")==0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
printf("uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
return http_resp_dir_html(req, filepath, filename, readonly);
|
||||
}
|
||||
|
||||
@@ -376,7 +566,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
/* If file not present on SPIFFS check if URI
|
||||
* corresponds to one of the hardcoded paths */
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to stat file : %s", filepath);
|
||||
ESP_LOGE(TAG, "Failed to stat file : %s", filepath);
|
||||
/* Respond with 404 Not Found */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
|
||||
return ESP_FAIL;
|
||||
@@ -384,7 +574,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
fd = OpenFileAndWait(filepath, "r");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to read existing file : %s", filepath);
|
||||
ESP_LOGE(TAG, "Failed to read existing file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
return ESP_FAIL;
|
||||
@@ -392,7 +582,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
ESP_LOGI(TAG_FILESERVER, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
|
||||
ESP_LOGD(TAG, "Sending file : %s (%ld bytes)...", filename, file_stat.st_size);
|
||||
set_content_type_from_file(req, filename);
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
@@ -405,7 +595,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
fclose(fd);
|
||||
ESP_LOGE(TAG_FILESERVER, "File sending failed!");
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
/* Abort sending file */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
@@ -418,7 +608,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
/* Close file after sending complete */
|
||||
fclose(fd);
|
||||
ESP_LOGI(TAG_FILESERVER, "File successfully sent");
|
||||
ESP_LOGD(TAG, "File successfully sent");
|
||||
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
@@ -428,7 +618,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
/* Handler to upload a file onto the server */
|
||||
static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
{
|
||||
LogFile.WriteToFile("upload_post_handler");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
struct stat file_stat;
|
||||
@@ -445,13 +635,13 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
/* Filename cannot have a trailing '/' */
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
ESP_LOGE(TAG_FILESERVER, "Invalid filename : %s", filename);
|
||||
ESP_LOGE(TAG, "Invalid filename : %s", filename);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (stat(filepath, &file_stat) == 0) {
|
||||
ESP_LOGE(TAG_FILESERVER, "File already exists : %s", filepath);
|
||||
ESP_LOGE(TAG, "File already exists : %s", filepath);
|
||||
/* Respond with 400 Bad Request */
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File already exists");
|
||||
return ESP_FAIL;
|
||||
@@ -459,7 +649,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
/* File cannot be larger than a limit */
|
||||
if (req->content_len > MAX_FILE_SIZE) {
|
||||
ESP_LOGE(TAG_FILESERVER, "File too large : %d bytes", req->content_len);
|
||||
ESP_LOGE(TAG, "File too large : %d bytes", req->content_len);
|
||||
/* Respond with 400 Bad Request */
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST,
|
||||
"File size must be less than "
|
||||
@@ -471,13 +661,13 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
fd = OpenFileAndWait(filepath, "w");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to create file : %s", filepath);
|
||||
ESP_LOGE(TAG, "Failed to create file : %s", filepath);
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_FILESERVER, "Receiving file : %s...", filename);
|
||||
ESP_LOGI(TAG, "Receiving file : %s...", filename);
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
char *buf = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
@@ -489,7 +679,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
while (remaining > 0) {
|
||||
|
||||
ESP_LOGI(TAG_FILESERVER, "Remaining size : %d", remaining);
|
||||
ESP_LOGI(TAG, "Remaining size : %d", remaining);
|
||||
/* Receive the file part by part into a buffer */
|
||||
if ((received = httpd_req_recv(req, buf, MIN(remaining, SCRATCH_BUFSIZE))) <= 0) {
|
||||
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
@@ -502,7 +692,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG_FILESERVER, "File reception failed!");
|
||||
ESP_LOGE(TAG, "File reception failed!");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
|
||||
return ESP_FAIL;
|
||||
@@ -515,7 +705,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG_FILESERVER, "File write failed!");
|
||||
ESP_LOGE(TAG, "File write failed!");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
|
||||
return ESP_FAIL;
|
||||
@@ -528,7 +718,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
/* Close file upon upload completion */
|
||||
fclose(fd);
|
||||
ESP_LOGI(TAG_FILESERVER, "File reception complete");
|
||||
ESP_LOGI(TAG, "File reception complete");
|
||||
|
||||
std::string directory = std::string(filepath);
|
||||
size_t zw = directory.find("/");
|
||||
@@ -541,12 +731,10 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
int start_fn = strlen(((struct file_server_data *)req->user_ctx)->base_path);
|
||||
printf("Directory: %s, start_fn: %d, found: %d\n", directory.c_str(), start_fn, found);
|
||||
ESP_LOGD(TAG, "Directory: %s, start_fn: %d, found: %d", directory.c_str(), start_fn, found);
|
||||
directory = directory.substr(start_fn, found - start_fn + 1);
|
||||
printf("Directory danach 1: %s\n", directory.c_str());
|
||||
|
||||
directory = "/fileserver" + directory;
|
||||
printf("Directory danach 2: %s\n", directory.c_str());
|
||||
// ESP_LOGD(TAG, "Directory danach 2: %s", directory.c_str());
|
||||
|
||||
/* Redirect onto root to see the updated file list */
|
||||
httpd_resp_set_status(req, "303 See Other");
|
||||
@@ -559,7 +747,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
/*
|
||||
if (strcmp(filepath, CONFIG_FILE) == 0) {
|
||||
printf("New config found. Reload handler.");
|
||||
ESP_LOGD(TAG, "New config found. Reload handler.");
|
||||
gpio_handler_deinit();
|
||||
MQTTdestroy();
|
||||
}
|
||||
@@ -571,7 +759,7 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
/* Handler to delete a file from the server */
|
||||
static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
{
|
||||
LogFile.WriteToFile("delete_post_handler");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "delete_post_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
struct stat file_stat;
|
||||
|
||||
@@ -586,11 +774,11 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
printf("task is found: "); printf(_valuechar); printf("\n");
|
||||
ESP_LOGD(TAG, "task is found: %s", _valuechar);
|
||||
_task = std::string(_valuechar);
|
||||
}
|
||||
}
|
||||
@@ -610,12 +798,12 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
zw = zw.substr(0, zw.length()-1);
|
||||
directory = "/fileserver" + zw + "/";
|
||||
zw = "/sdcard" + zw;
|
||||
printf("Directory to delete: %s\n", zw.c_str());
|
||||
ESP_LOGD(TAG, "Directory to delete: %s", zw.c_str());
|
||||
|
||||
delete_all_in_directory(zw);
|
||||
// directory = std::string(filepath);
|
||||
// directory = "/fileserver" + directory;
|
||||
printf("Location after delete directory content: %s\n", directory.c_str());
|
||||
ESP_LOGD(TAG, "Location after delete directory content: %s", directory.c_str());
|
||||
/* Redirect onto root to see the updated file list */
|
||||
// httpd_resp_set_status(req, "303 See Other");
|
||||
// httpd_resp_set_hdr(req, "Location", directory.c_str());
|
||||
@@ -636,19 +824,19 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
|
||||
/* Filename cannot have a trailing '/' */
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
ESP_LOGE(TAG_FILESERVER, "Invalid filename : %s", filename);
|
||||
ESP_LOGE(TAG, "Invalid filename : %s", filename);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (stat(filepath, &file_stat) == -1) {
|
||||
ESP_LOGE(TAG_FILESERVER, "File does not exist : %s", filename);
|
||||
ESP_LOGE(TAG, "File does not exist : %s", filename);
|
||||
/* Respond with 400 Bad Request */
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "File does not exist");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_FILESERVER, "Deleting file : %s", filename);
|
||||
ESP_LOGI(TAG, "Deleting file : %s", filename);
|
||||
/* Delete file */
|
||||
unlink(filepath);
|
||||
|
||||
@@ -663,12 +851,10 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
int start_fn = strlen(((struct file_server_data *)req->user_ctx)->base_path);
|
||||
printf("Directory: %s, start_fn: %d, found: %d\n", directory.c_str(), start_fn, found);
|
||||
ESP_LOGD(TAG, "Directory: %s, start_fn: %d, found: %d", directory.c_str(), start_fn, found);
|
||||
directory = directory.substr(start_fn, found - start_fn + 1);
|
||||
printf("Directory danach 3: %s\n", directory.c_str());
|
||||
|
||||
directory = "/fileserver" + directory;
|
||||
printf("Directory danach 4: %s\n", directory.c_str());
|
||||
ESP_LOGD(TAG, "Directory danach 4: %s", directory.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -692,7 +878,7 @@ void delete_all_in_directory(std::string _directory)
|
||||
std::string filename;
|
||||
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to stat dir : %s", _directory.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", _directory.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -701,7 +887,7 @@ void delete_all_in_directory(std::string _directory)
|
||||
if (!(entry->d_type == DT_DIR)){
|
||||
if (strcmp("wlan.ini", entry->d_name) != 0){ // auf wlan.ini soll nicht zugegriffen werden !!!
|
||||
filename = _directory + "/" + std::string(entry->d_name);
|
||||
ESP_LOGI(TAG_FILESERVER, "Deleting file : %s", filename.c_str());
|
||||
ESP_LOGI(TAG, "Deleting file : %s", filename.c_str());
|
||||
/* Delete file */
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
@@ -722,18 +908,18 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
std::string directory = "";
|
||||
// static const char* s_Test_archive_filename = "testhtml.zip";
|
||||
|
||||
printf("miniz.c version: %s\n", MZ_VERSION);
|
||||
printf("Zipfile: %s\n", _in_zip_file.c_str());
|
||||
printf("Target Dir ZIP: %s\n", _target_zip.c_str());
|
||||
printf("Target Dir BIN: %s\n", _target_bin.c_str());
|
||||
printf("Target Dir main: %s\n", _main.c_str());
|
||||
ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION);
|
||||
ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir ZIP: %s", _target_zip.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir BIN: %s", _target_bin.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir main: %s", _main.c_str());
|
||||
|
||||
// Now try to open the archive.
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
ESP_LOGD(TAG, "mz_zip_reader_init_file() failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -745,7 +931,7 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
ESP_LOGD(TAG, "mz_zip_reader_init_file() failed!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -760,14 +946,14 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
|
||||
if (!p)
|
||||
{
|
||||
printf("mz_zip_reader_extract_file_to_heap() failed on file %s\n", archive_filename);
|
||||
ESP_LOGE(TAG, "mz_zip_reader_extract_file_to_heap() failed on file %s", archive_filename);
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Save to File.
|
||||
zw = std::string(archive_filename);
|
||||
printf("Rohfilename: %s\n", zw.c_str());
|
||||
ESP_LOGD(TAG, "Rohfilename: %s", zw.c_str());
|
||||
|
||||
if (toUpper(zw) == "FIRMWARE.BIN")
|
||||
{
|
||||
@@ -791,22 +977,43 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
|
||||
string filename_zw = zw + SUFFIX_ZW;
|
||||
|
||||
printf("Filename to extract: %s, Zwischenfilename: %s", zw.c_str(), filename_zw.c_str());
|
||||
ESP_LOGI(TAG, "Filename to extract: %s, Zwischenfilename: %s", zw.c_str(), filename_zw.c_str());
|
||||
|
||||
// extrahieren in zwischendatei
|
||||
DeleteFile(filename_zw);
|
||||
FILE* fpTargetFile = OpenFileAndWait(filename_zw.c_str(), "wb");
|
||||
fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
uint writtenbytes = fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
bool isokay = true;
|
||||
|
||||
if (writtenbytes == (uint)uncomp_size)
|
||||
{
|
||||
isokay = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
isokay = false;
|
||||
ESP_LOGD(TAG, "ERROR in writting extracted file (function fwrite) extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
}
|
||||
|
||||
DeleteFile(zw);
|
||||
RenameFile(filename_zw, zw);
|
||||
DeleteFile(filename_zw);
|
||||
if (!isokay)
|
||||
ESP_LOGE(TAG, "ERROR in fwrite \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
isokay = isokay && RenameFile(filename_zw, zw);
|
||||
if (!isokay)
|
||||
ESP_LOGE(TAG, "ERROR in Rename \"%s\" to \"%s\"", filename_zw.c_str(), zw.c_str());
|
||||
// isokay = isokay && DeleteFile(filename_zw);
|
||||
// if (!isokay)
|
||||
// ESP_LOGE(TAG, "ERROR in Delete \"%s\"", filename_zw.c_str());
|
||||
|
||||
printf("Successfully extracted file \"%s\", size %u\n", archive_filename, (uint)uncomp_size);
|
||||
// printf("File data: \"%s\"\n", (const char*)p);
|
||||
|
||||
// We're done.
|
||||
if (isokay)
|
||||
ESP_LOGI(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
else
|
||||
{
|
||||
ESP_LOGE(TAG, "ERROR in extracting file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
ret = "ERROR";
|
||||
}
|
||||
mz_free(p);
|
||||
}
|
||||
}
|
||||
@@ -815,7 +1022,7 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
}
|
||||
|
||||
printf("Success.\n");
|
||||
ESP_LOGD(TAG, "Success.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -829,16 +1036,16 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
std::string zw;
|
||||
// static const char* s_Test_archive_filename = "testhtml.zip";
|
||||
|
||||
printf("miniz.c version: %s\n", MZ_VERSION);
|
||||
printf("Zipfile: %s\n", _in_zip_file.c_str());
|
||||
printf("Target Dir: %s\n", _target_directory.c_str());
|
||||
ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION);
|
||||
ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
|
||||
ESP_LOGD(TAG, "Target Dir: %s", _target_directory.c_str());
|
||||
|
||||
// Now try to open the archive.
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
ESP_LOGD(TAG, "mz_zip_reader_init_file() failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -850,7 +1057,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
ESP_LOGD(TAG, "mz_zip_reader_init_file() failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -864,7 +1071,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
|
||||
if (!p)
|
||||
{
|
||||
printf("mz_zip_reader_extract_file_to_heap() failed!\n");
|
||||
ESP_LOGD(TAG, "mz_zip_reader_extract_file_to_heap() failed!");
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return;
|
||||
}
|
||||
@@ -872,13 +1079,13 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
// Save to File.
|
||||
zw = std::string(archive_filename);
|
||||
zw = _target_directory + zw;
|
||||
printf("Filename to extract: %s", zw.c_str());
|
||||
ESP_LOGD(TAG, "Filename to extract: %s", zw.c_str());
|
||||
FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb");
|
||||
fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
printf("Successfully extracted file \"%s\", size %u\n", archive_filename, (uint)uncomp_size);
|
||||
// printf("File data: \"%s\"\n", (const char*)p);
|
||||
ESP_LOGD(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
// ESP_LOGD(TAG, "File data: \"%s\"", (const char*)p);
|
||||
|
||||
// We're done.
|
||||
mz_free(p);
|
||||
@@ -888,7 +1095,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
}
|
||||
|
||||
printf("Success.\n");
|
||||
ESP_LOGD(TAG, "Success.");
|
||||
}
|
||||
|
||||
|
||||
@@ -900,19 +1107,19 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
|
||||
/* Validate file storage base path */
|
||||
if (!base_path) {
|
||||
// if (!base_path || strcmp(base_path, "/spiffs") != 0) {
|
||||
ESP_LOGE(TAG_FILESERVER, "File server base_path not set");
|
||||
ESP_LOGE(TAG, "File server base_path not set");
|
||||
// return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
if (server_data) {
|
||||
ESP_LOGE(TAG_FILESERVER, "File server already started");
|
||||
ESP_LOGE(TAG, "File server already started");
|
||||
// return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Allocate memory for server data */
|
||||
server_data = (file_server_data *) calloc(1, sizeof(struct file_server_data));
|
||||
if (!server_data) {
|
||||
ESP_LOGE(TAG_FILESERVER, "Failed to allocate memory for server data");
|
||||
ESP_LOGE(TAG, "Failed to allocate memory for server data");
|
||||
// return ESP_ERR_NO_MEM;
|
||||
}
|
||||
strlcpy(server_data->base_path, base_path,
|
||||
@@ -925,7 +1132,7 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
|
||||
// strcpy(zw, serverprefix);
|
||||
// zw[strlen(serverprefix)] = '*';
|
||||
// zw[strlen(serverprefix)+1] = '\0';
|
||||
// printf("zw: %s\n", zw);
|
||||
// ESP_LOGD(TAG, "zw: %s", zw);
|
||||
httpd_uri_t file_download = {
|
||||
.uri = "/fileserver*", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
@@ -935,16 +1142,41 @@ void register_server_file_uri(httpd_handle_t server, const char *base_path)
|
||||
httpd_register_uri_handler(server, &file_download);
|
||||
|
||||
|
||||
httpd_uri_t file_datafileact = {
|
||||
.uri = "/datafileact", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = datafileact_get_full_handler,
|
||||
.user_ctx = server_data // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_datafileact);
|
||||
|
||||
|
||||
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,
|
||||
.user_ctx = server_data // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_datafile_last_part_handle);
|
||||
|
||||
httpd_uri_t file_logfileact = {
|
||||
.uri = "/logfileact", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = logfileact_get_handler,
|
||||
.handler = logfileact_get_full_handler,
|
||||
.user_ctx = server_data // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_logfileact);
|
||||
|
||||
|
||||
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,
|
||||
.user_ctx = server_data // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_logfile_last_part_handle);
|
||||
|
||||
|
||||
/* URI handler for uploading files to server */
|
||||
httpd_uri_t file_upload = {
|
||||
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
|
||||
|
||||
@@ -10,3 +10,6 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
void delete_all_in_directory(std::string _directory);
|
||||
|
||||
esp_err_t get_tflite_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_data_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_numbers_file_handler(httpd_req_t *req);
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ extern "C" {
|
||||
#include "esp_http_server.h"
|
||||
|
||||
|
||||
static const char *TAG = "serverhelp";
|
||||
static const char *TAG = "SERVER HELP";
|
||||
|
||||
#define SCRATCH_BUFSIZE 8192
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
@@ -42,7 +42,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Sending file : %s ...", filename.c_str());
|
||||
ESP_LOGD(TAG, "Sending file : %s ...", filename.c_str());
|
||||
// httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
set_content_type_from_file(req, filename.c_str());
|
||||
|
||||
@@ -69,7 +69,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
|
||||
/* Close file after sending complete */
|
||||
fclose(fd);
|
||||
ESP_LOGI(TAG, "File sending complete");
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,17 +48,79 @@ static char ota_write_data[BUFFSIZE + 1] = { 0 };
|
||||
|
||||
|
||||
#define OTA_URL_SIZE 256
|
||||
static const char *TAGPARTOTA = "server_ota";
|
||||
static const char *TAG = "OTA";
|
||||
|
||||
esp_err_t handler_reboot(httpd_req_t *req);
|
||||
|
||||
std::string _file_name_update;
|
||||
|
||||
|
||||
void task_do_Update_ZIP(void *pvParameter)
|
||||
{
|
||||
std::string filetype = toUpper(getFileType(_file_name_update));
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "File: " + _file_name_update + " Filetype: " + filetype);
|
||||
|
||||
|
||||
if (filetype == "ZIP")
|
||||
{
|
||||
std::string in, out, outbin, zw, retfirmware;
|
||||
|
||||
out = "/sdcard/html";
|
||||
outbin = "/sdcard/firmware";
|
||||
|
||||
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Files unzipped.");
|
||||
|
||||
if (retfirmware.length() > 0)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Found firmware.bin");
|
||||
ota_update_task(retfirmware);
|
||||
}
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doReboot();
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Only ZIP-Files support for update during startup!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CheckUpdate()
|
||||
{
|
||||
FILE *pfile;
|
||||
if ((pfile = fopen("/sdcard/update.txt", "r")) == NULL)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "No update triggered.");
|
||||
return;
|
||||
}
|
||||
|
||||
char zw[1024] = "";
|
||||
fgets(zw, 1024, pfile);
|
||||
_file_name_update = std::string(zw);
|
||||
fclose(pfile);
|
||||
DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update during boot triggered - Update File: " + _file_name_update);
|
||||
|
||||
|
||||
BaseType_t xReturned;
|
||||
int _i = configMINIMAL_STACK_SIZE;
|
||||
xReturned = xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
TickType_t xDelay;
|
||||
xDelay = 2000000 / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "Wait for Update to be finished: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void infinite_loop(void)
|
||||
{
|
||||
int i = 0;
|
||||
ESP_LOGI(TAGPARTOTA, "When a new firmware is available on the server, press the reset button to download it");
|
||||
ESP_LOGI(TAG, "When a new firmware is available on the server, press the reset button to download it");
|
||||
while(1) {
|
||||
ESP_LOGI(TAGPARTOTA, "Waiting for a new firmware ... %d", ++i);
|
||||
ESP_LOGI(TAG, "Waiting for a new firmware... %d", ++i);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
@@ -72,22 +134,22 @@ static bool ota_update_task(std::string fn)
|
||||
esp_ota_handle_t update_handle = 0 ;
|
||||
const esp_partition_t *update_partition = NULL;
|
||||
|
||||
ESP_LOGI(TAGPARTOTA, "Starting OTA update");
|
||||
ESP_LOGI(TAG, "Starting OTA update");
|
||||
|
||||
const esp_partition_t *configured = esp_ota_get_boot_partition();
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
|
||||
if (configured != running) {
|
||||
ESP_LOGW(TAGPARTOTA, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
|
||||
ESP_LOGW(TAG, "Configured OTA boot partition at offset 0x%08x, but running from offset 0x%08x",
|
||||
configured->address, running->address);
|
||||
ESP_LOGW(TAGPARTOTA, "(This can happen if either the OTA boot data or preferred boot image become somehow corrupted.)");
|
||||
ESP_LOGW(TAG, "(This can happen if either the OTA boot data or preferred boot image become somehow corrupted.)");
|
||||
}
|
||||
ESP_LOGI(TAGPARTOTA, "Running partition type %d subtype %d (offset 0x%08x)",
|
||||
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08x)",
|
||||
running->type, running->subtype, running->address);
|
||||
|
||||
|
||||
update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
ESP_LOGI(TAGPARTOTA, "Writing to partition subtype %d at offset 0x%x",
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x",
|
||||
update_partition->subtype, update_partition->address);
|
||||
// assert(update_partition != NULL);
|
||||
|
||||
@@ -108,7 +170,7 @@ static bool ota_update_task(std::string fn)
|
||||
|
||||
while (data_read > 0) {
|
||||
if (data_read < 0) {
|
||||
ESP_LOGE(TAGPARTOTA, "Error: SSL data read error");
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
return false;
|
||||
} else if (data_read > 0) {
|
||||
if (image_header_was_checked == false) {
|
||||
@@ -116,32 +178,32 @@ static bool ota_update_task(std::string fn)
|
||||
if (data_read > sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t) + sizeof(esp_app_desc_t)) {
|
||||
// check current version with downloading
|
||||
memcpy(&new_app_info, &ota_write_data[sizeof(esp_image_header_t) + sizeof(esp_image_segment_header_t)], sizeof(esp_app_desc_t));
|
||||
ESP_LOGI(TAGPARTOTA, "New firmware version: %s", new_app_info.version);
|
||||
ESP_LOGI(TAG, "New firmware version: %s", new_app_info.version);
|
||||
|
||||
esp_app_desc_t running_app_info;
|
||||
if (esp_ota_get_partition_description(running, &running_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAGPARTOTA, "Running firmware version: %s", running_app_info.version);
|
||||
ESP_LOGI(TAG, "Running firmware version: %s", running_app_info.version);
|
||||
}
|
||||
|
||||
const esp_partition_t* last_invalid_app = esp_ota_get_last_invalid_partition();
|
||||
esp_app_desc_t invalid_app_info;
|
||||
if (esp_ota_get_partition_description(last_invalid_app, &invalid_app_info) == ESP_OK) {
|
||||
ESP_LOGI(TAGPARTOTA, "Last invalid firmware version: %s", invalid_app_info.version);
|
||||
ESP_LOGI(TAG, "Last invalid firmware version: %s", invalid_app_info.version);
|
||||
}
|
||||
|
||||
// check current version with last invalid partition
|
||||
if (last_invalid_app != NULL) {
|
||||
if (memcmp(invalid_app_info.version, new_app_info.version, sizeof(new_app_info.version)) == 0) {
|
||||
ESP_LOGW(TAGPARTOTA, "New version is the same as invalid version.");
|
||||
ESP_LOGW(TAGPARTOTA, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
|
||||
ESP_LOGW(TAGPARTOTA, "The firmware has been rolled back to the previous version.");
|
||||
ESP_LOGW(TAG, "New version is the same as invalid version.");
|
||||
ESP_LOGW(TAG, "Previously, there was an attempt to launch the firmware with %s version, but it failed.", invalid_app_info.version);
|
||||
ESP_LOGW(TAG, "The firmware has been rolled back to the previous version.");
|
||||
infinite_loop();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (memcmp(new_app_info.version, running_app_info.version, sizeof(new_app_info.version)) == 0) {
|
||||
ESP_LOGW(TAGPARTOTA, "Current running version is the same as a new. We will not continue the update.");
|
||||
ESP_LOGW(TAG, "Current running version is the same as a new. We will not continue the update.");
|
||||
infinite_loop();
|
||||
}
|
||||
*/
|
||||
@@ -149,12 +211,12 @@ static bool ota_update_task(std::string fn)
|
||||
|
||||
err = esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAGPARTOTA, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "esp_ota_begin failed (%s)", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
ESP_LOGI(TAGPARTOTA, "esp_ota_begin succeeded");
|
||||
ESP_LOGI(TAG, "esp_ota_begin succeeded");
|
||||
} else {
|
||||
ESP_LOGE(TAGPARTOTA, "received package is not fit len");
|
||||
ESP_LOGE(TAG, "received package is not fit len");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -163,14 +225,14 @@ static bool ota_update_task(std::string fn)
|
||||
return false;
|
||||
}
|
||||
binary_file_length += data_read;
|
||||
ESP_LOGD(TAGPARTOTA, "Written image length %d", binary_file_length);
|
||||
ESP_LOGD(TAG, "Written image length %d", binary_file_length);
|
||||
} else if (data_read == 0) {
|
||||
//
|
||||
// * As esp_http_client_read never returns negative error code, we rely on
|
||||
// * `errno` to check for underlying transport connectivity closure if any
|
||||
//
|
||||
if (errno == ECONNRESET || errno == ENOTCONN) {
|
||||
ESP_LOGE(TAGPARTOTA, "Connection closed, errno = %d", errno);
|
||||
ESP_LOGE(TAG, "Connection closed, errno = %d", errno);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -178,23 +240,23 @@ static bool ota_update_task(std::string fn)
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
ESP_LOGI(TAGPARTOTA, "Total Write binary data length: %d", binary_file_length);
|
||||
ESP_LOGI(TAG, "Total Write binary data length: %d", binary_file_length);
|
||||
|
||||
err = esp_ota_end(update_handle);
|
||||
if (err != ESP_OK) {
|
||||
if (err == ESP_ERR_OTA_VALIDATE_FAILED) {
|
||||
ESP_LOGE(TAGPARTOTA, "Image validation failed, image is corrupted");
|
||||
ESP_LOGE(TAG, "Image validation failed, image is corrupted");
|
||||
}
|
||||
ESP_LOGE(TAGPARTOTA, "esp_ota_end failed (%s)!", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "esp_ota_end failed (%s)!", esp_err_to_name(err));
|
||||
return false;
|
||||
}
|
||||
|
||||
err = esp_ota_set_boot_partition(update_partition);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAGPARTOTA, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
|
||||
ESP_LOGE(TAG, "esp_ota_set_boot_partition failed (%s)!", esp_err_to_name(err));
|
||||
|
||||
}
|
||||
// ESP_LOGI(TAGPARTOTA, "Prepare to restart system!");
|
||||
// ESP_LOGI(TAG, "Prepare to restart system!");
|
||||
// esp_restart();
|
||||
|
||||
return true ;
|
||||
@@ -208,7 +270,7 @@ static void print_sha256 (const uint8_t *image_hash, const char *label)
|
||||
for (int i = 0; i < HASH_LEN; ++i) {
|
||||
sprintf(&hash_print[i * 2], "%02x", image_hash[i]);
|
||||
}
|
||||
ESP_LOGI(TAGPARTOTA, "%s: %s", label, hash_print);
|
||||
ESP_LOGI(TAG, "%s: %s", label, hash_print);
|
||||
}
|
||||
|
||||
|
||||
@@ -219,8 +281,7 @@ static bool diagnostic(void)
|
||||
|
||||
void CheckOTAUpdate(void)
|
||||
{
|
||||
ESP_LOGI(TAGPARTOTA, "Start CheckOTAUpdateCheck ...");
|
||||
printf("Start CheckOTAUpdateCheck ...\n");
|
||||
ESP_LOGI(TAG, "Start CheckOTAUpdateCheck...");
|
||||
|
||||
uint8_t sha_256[HASH_LEN] = { 0 };
|
||||
esp_partition_t partition;
|
||||
@@ -249,31 +310,29 @@ void CheckOTAUpdate(void)
|
||||
switch (res_stat_partition)
|
||||
{
|
||||
case ESP_OK:
|
||||
printf("CheckOTAUpdate Partition: ESP_OK\n");
|
||||
ESP_LOGD(TAG, "CheckOTAUpdate Partition: ESP_OK");
|
||||
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
|
||||
if (ota_state == ESP_OTA_IMG_PENDING_VERIFY) {
|
||||
// run diagnostic function ...
|
||||
bool diagnostic_is_ok = diagnostic();
|
||||
if (diagnostic_is_ok) {
|
||||
ESP_LOGI(TAGPARTOTA, "Diagnostics completed successfully! Continuing execution ...");
|
||||
printf("Diagnostics completed successfully! Continuing execution ...\n");
|
||||
ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution...");
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
} else {
|
||||
ESP_LOGE(TAGPARTOTA, "Diagnostics failed! Start rollback to the previous version ...");
|
||||
printf("Diagnostics failed! Start rollback to the previous version ...\n");
|
||||
ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version...");
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ESP_ERR_INVALID_ARG:
|
||||
printf("CheckOTAUpdate Partition: ESP_ERR_INVALID_ARG\n");
|
||||
ESP_LOGD(TAG, "CheckOTAUpdate Partition: ESP_ERR_INVALID_ARG");
|
||||
break;
|
||||
case ESP_ERR_NOT_SUPPORTED:
|
||||
printf("CheckOTAUpdate Partition: ESP_ERR_NOT_SUPPORTED\n");
|
||||
ESP_LOGD(TAG, "CheckOTAUpdate Partition: ESP_ERR_NOT_SUPPORTED");
|
||||
break;
|
||||
case ESP_ERR_NOT_FOUND:
|
||||
printf("CheckOTAUpdate Partition: ESP_ERR_NOT_FOUND\n");
|
||||
ESP_LOGD(TAG, "CheckOTAUpdate Partition: ESP_ERR_NOT_FOUND");
|
||||
break;
|
||||
}
|
||||
if (esp_ota_get_state_partition(running, &ota_state) == ESP_OK) {
|
||||
@@ -281,12 +340,10 @@ void CheckOTAUpdate(void)
|
||||
// run diagnostic function ...
|
||||
bool diagnostic_is_ok = diagnostic();
|
||||
if (diagnostic_is_ok) {
|
||||
ESP_LOGI(TAGPARTOTA, "Diagnostics completed successfully! Continuing execution ...");
|
||||
printf("Diagnostics completed successfully! Continuing execution ...\n");
|
||||
ESP_LOGI(TAG, "Diagnostics completed successfully! Continuing execution...");
|
||||
esp_ota_mark_app_valid_cancel_rollback();
|
||||
} else {
|
||||
ESP_LOGE(TAGPARTOTA, "Diagnostics failed! Start rollback to the previous version ...");
|
||||
printf("Diagnostics failed! Start rollback to the previous version ...\n");
|
||||
ESP_LOGE(TAG, "Diagnostics failed! Start rollback to the previous version...");
|
||||
esp_ota_mark_app_invalid_rollback_and_reboot();
|
||||
}
|
||||
}
|
||||
@@ -301,7 +358,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile("handler_ota_update");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_ota_update");
|
||||
char _query[200];
|
||||
char _filename[100];
|
||||
char _valuechar[30];
|
||||
@@ -311,28 +368,45 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
printf("task is found: "); printf(_valuechar); printf("\n");
|
||||
ESP_LOGD(TAG, "task is found: %s", _valuechar);
|
||||
_task = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "file", _filename, 100) == ESP_OK)
|
||||
{
|
||||
fn.append(_filename);
|
||||
printf("File: "); printf(fn.c_str()); printf("\n");
|
||||
ESP_LOGD(TAG, "File: %s", fn.c_str());
|
||||
}
|
||||
if (httpd_query_key_value(_query, "delete", _filename, 100) == ESP_OK)
|
||||
{
|
||||
fn.append(_filename);
|
||||
_file_del = true;
|
||||
printf("Delete Default File: "); printf(fn.c_str()); printf("\n");
|
||||
ESP_LOGD(TAG, "Delete Default File: %s", fn.c_str());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
if (_task.compare("emptyfirmwaredir") == 0)
|
||||
{
|
||||
ESP_LOGD(TAG, "Start empty directory /firmware");
|
||||
delete_all_in_directory("/sdcard/firmware");
|
||||
std::string zw = "firmware directory deleted - v2\n";
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
printf("Ausgabe: %s\n", zw.c_str());
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGD(TAG, "Done empty directory /firmware");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("update") == 0)
|
||||
{
|
||||
std::string filetype = toUpper(getFileType(fn));
|
||||
@@ -361,6 +435,21 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
if (filetype == "ZIP")
|
||||
{
|
||||
FILE *pfile;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update for reboot.");
|
||||
pfile = fopen("/sdcard/update.txt", "w");
|
||||
fwrite(fn.c_str(), fn.length(), 1, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
std::string zw = "reboot\n";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
ESP_LOGD(TAG, "Send reboot");
|
||||
return ESP_OK;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
std::string in, out, outbin, zw, retfirmware;
|
||||
|
||||
out = "/sdcard/html";
|
||||
@@ -380,6 +469,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
@@ -394,7 +484,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
std::string zw = "reboot\n";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
printf("Send reboot\n");
|
||||
ESP_LOGD(TAG, "Send reboot");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@@ -418,7 +508,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
if (_task.compare("unziphtml") == 0)
|
||||
{
|
||||
printf("Task unziphmtl\n");
|
||||
ESP_LOGD(TAG, "Task unziphtml");
|
||||
std::string in, out, zw;
|
||||
|
||||
in = "/sdcard/firmware/html.zip";
|
||||
@@ -435,27 +525,35 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
if (_file_del)
|
||||
{
|
||||
printf("Delete !! _file_del: %s\n", fn.c_str());
|
||||
ESP_LOGD(TAG, "Delete !! _file_del: %s", fn.c_str());
|
||||
struct stat file_stat;
|
||||
int _result = stat(fn.c_str(), &file_stat);
|
||||
printf("Ergebnis %d\n", _result);
|
||||
ESP_LOGD(TAG, "Ergebnis %d\n", _result);
|
||||
if (_result == 0) {
|
||||
printf("Deleting file : %s\n", fn.c_str());
|
||||
ESP_LOGD(TAG, "Deleting file : %s", fn.c_str());
|
||||
/* Delete file */
|
||||
unlink(fn.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("File does not exist: %s\n", fn.c_str());
|
||||
ESP_LOGD(TAG, "File does not exist: %s", fn.c_str());
|
||||
}
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
std::string zw = "file deleted\n";
|
||||
printf((zw + "\n").c_str());
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
string zw = "ota without parameter - should not be the case!";
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGE(TAG, "ota without parameter - should not be the case!");
|
||||
|
||||
/*
|
||||
const char* resp_str;
|
||||
|
||||
KillTFliteTasks();
|
||||
@@ -474,6 +572,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Done");
|
||||
#endif
|
||||
*/
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
@@ -497,10 +596,8 @@ void task_reboot(void *pvParameter)
|
||||
}
|
||||
|
||||
void doReboot(){
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Reboot triggered by Software (5s).");
|
||||
ESP_LOGI(TAGPARTOTA, "Reboot in 5sec");
|
||||
LogFile.WriteToFile("Reboot in 5sec");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reboot triggered by Software (5s).");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
|
||||
xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
|
||||
// KillTFliteTasks(); // kills itself
|
||||
gpio_handler_destroy();
|
||||
@@ -516,9 +613,9 @@ esp_err_t handler_reboot(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_reboot - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile("handler_reboot");
|
||||
ESP_LOGI(TAGPARTOTA, "!!! System will restart within 5 sec!!!");
|
||||
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload in about 25s.<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{parent.location.href=('/index.html');})}, 1000);</script>";
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_reboot");
|
||||
ESP_LOGI(TAG, "!!! System will restart within 5 sec!!!");
|
||||
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload in around 25..60s<br>(in case of a firmware update it can take up to 180s).<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{parent.location.href=('/index.html');})}, 1000);</script>";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
doReboot();
|
||||
@@ -532,7 +629,7 @@ esp_err_t handler_reboot(httpd_req_t *req)
|
||||
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server)
|
||||
{
|
||||
ESP_LOGI(TAGPARTOTA, "server_ota - Registering URI handlers");
|
||||
ESP_LOGI(TAG, "Registering URI handlers");
|
||||
|
||||
httpd_uri_t camuri = { };
|
||||
camuri.method = HTTP_GET;
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
|
||||
#include <esp_http_server.h>
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server);
|
||||
void CheckOTAUpdate();
|
||||
void doReboot();
|
||||
void hard_restart();
|
||||
|
||||
void CheckUpdate();
|
||||
static bool ota_update_task(std::string fn);
|
||||
@@ -3,7 +3,9 @@
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "FLOW CLASS";
|
||||
|
||||
|
||||
void ClassFlow::SetInitialParameter(void)
|
||||
@@ -13,30 +15,6 @@ void ClassFlow::SetInitialParameter(void)
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::vector<string> ClassFlow::ZerlegeZeile(std::string input, std::string delimiter)
|
||||
{
|
||||
std::vector<string> Output;
|
||||
|
||||
input = trim(input, delimiter);
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
while (pos != std::string::npos) {
|
||||
token = input.substr(0, pos);
|
||||
token = trim(token, delimiter);
|
||||
Output.push_back(token);
|
||||
input.erase(0, pos + 1);
|
||||
input = trim(input, delimiter);
|
||||
pos = findDelimiterPos(input, delimiter);
|
||||
}
|
||||
Output.push_back(input);
|
||||
|
||||
return Output;
|
||||
|
||||
}
|
||||
|
||||
bool ClassFlow::isNewParagraph(string input)
|
||||
{
|
||||
if ((input[0] == '[') || ((input[0] == ';') && (input[1] == '[')))
|
||||
@@ -105,7 +83,7 @@ std::string ClassFlow::GetParameterName(std::string _input)
|
||||
{
|
||||
_param = _input;
|
||||
}
|
||||
// printf("Parameter: %s, Pospunkt: %d\n", _param.c_str(), _pospunkt);
|
||||
// ESP_LOGD(TAG, "Parameter: %s, Pospunkt: %d", _param.c_str(), _pospunkt);
|
||||
return _param;
|
||||
}
|
||||
|
||||
@@ -121,10 +99,10 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
|
||||
if (!fgets(zw, 1024, pfile))
|
||||
{
|
||||
*rt = "";
|
||||
printf("END OF FILE\n");
|
||||
ESP_LOGD(TAG, "END OF FILE");
|
||||
return false;
|
||||
}
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
@@ -132,7 +110,7 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
|
||||
*rt = "";
|
||||
if (!fgets(zw, 1024, pfile))
|
||||
return false;
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ struct HTMLInfo
|
||||
class ClassFlow
|
||||
{
|
||||
protected:
|
||||
std::vector<string> ZerlegeZeile(string input, string delimiter = " =, \t");
|
||||
bool isNewParagraph(string input);
|
||||
bool GetNextParagraph(FILE* pfile, string& aktparamgraph);
|
||||
bool getNextLine(FILE* pfile, string* rt);
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
#include "ClassFlow.h"
|
||||
|
||||
#include "CRotateImage.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
|
||||
static const char *TAG = "FLOW ALIGN";
|
||||
|
||||
bool AlignmentExtendedDebugging = true;
|
||||
|
||||
@@ -48,7 +50,7 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
|
||||
if (!ImageBasis) // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN
|
||||
{
|
||||
if (AlignmentExtendedDebugging) printf("CImageBasis had to be created\n");
|
||||
if (AlignmentExtendedDebugging) ESP_LOGD(TAG, "CImageBasis had to be created");
|
||||
ImageBasis = new CImageBasis(namerawimage);
|
||||
}
|
||||
}
|
||||
@@ -118,7 +120,7 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus gewählt: " + zerlegt[1];
|
||||
LogFile.WriteToFile(zw2);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
if (toUpper(zerlegt[1]) == "HIGHACCURACY")
|
||||
alg_algo = 1;
|
||||
@@ -135,7 +137,7 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
References[i].alignment_algo = alg_algo;
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus geschrieben: " + std::to_string(alg_algo);
|
||||
LogFile.WriteToFile(zw2);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -174,7 +176,7 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
}
|
||||
|
||||
if (initialmirror){
|
||||
printf("do mirror\n");
|
||||
ESP_LOGD(TAG, "do mirror");
|
||||
rt.Mirror();
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
}
|
||||
@@ -279,7 +281,7 @@ bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues01");
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
|
||||
// zwvalue = "LoadReferenceAlignmentValues Time: " + std::string(zw);
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
|
||||
#include "CTfLiteClass.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char* TAG = "CNN";
|
||||
|
||||
static const char* TAG = "flow_analog";
|
||||
|
||||
bool debugdetailgeneral = true;
|
||||
|
||||
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
|
||||
{
|
||||
@@ -26,23 +27,24 @@ ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNTy
|
||||
CNNType = AutoDetect;
|
||||
CNNType = _cnntype;
|
||||
flowpostalignment = _flowalign;
|
||||
logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _vorgaengerAnalog)
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _vorgaengerAnalog, float analogDigitalTransitionStart)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
if (GENERAL[_analog]->ROI.size() == 0)
|
||||
return result;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout _analog=" + std::to_string(_analog) + ", _extendedResolution=" + std::to_string(_extendedResolution) + ", prev=" + std::to_string(prev));
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout _analog=" + std::to_string(_analog) + ", _extendedResolution=" + std::to_string(_extendedResolution) + ", prev=" + std::to_string(prev));
|
||||
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
|
||||
|
||||
prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
// if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
result = std::to_string(prev);
|
||||
|
||||
if (_extendedResolution && (CNNType != Digital))
|
||||
@@ -81,17 +83,17 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
|
||||
result = std::to_string(ergebnis_vorkomma) + std::to_string(ergebnis_nachkomma);
|
||||
prev = ergebnis_vorkomma;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(dig100-ext) ergebnis_vorkomma=" + std::to_string(ergebnis_vorkomma) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) ergebnis_vorkomma=" + std::to_string(ergebnis_vorkomma) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
}
|
||||
else
|
||||
{
|
||||
// prev = ZeigerEval(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
if (_vorgaengerAnalog >= 0)
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _vorgaengerAnalog, prev, true);
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _vorgaengerAnalog, prev, true, analogDigitalTransitionStart);
|
||||
else
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
|
||||
result = std::to_string(prev);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(dig100) prev=" + std::to_string(prev));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100) prev=" + std::to_string(prev));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -107,16 +109,16 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
if (GENERAL[_analog]->ROI[i]->result_float >= 0)
|
||||
{
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout#ZeigerEvalHybridNeu()= " + std::to_string(prev));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#ZeigerEvalHybridNeu()= " + std::to_string(prev));
|
||||
result = std::to_string(prev) + result;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout#result= " + result);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#result= " + result);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
prev = -1;
|
||||
result = "N" + result;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::getReadout(result_float<0 /'N') result_float=" + std::to_string(GENERAL[_analog]->ROI[i]->result_float));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(result_float<0 /'N') result_float=" + std::to_string(GENERAL[_analog]->ROI[i]->result_float));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -127,7 +129,7 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
return result;
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger)
|
||||
int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger, float digitalAnalogTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
@@ -140,16 +142,15 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
|
||||
else
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (AnalogerVorgaenger)
|
||||
{
|
||||
// result = ZeigerEvalAnalogToDigitNeu(zahl, eval_vorgaenger);
|
||||
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
|
||||
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger, digitalAnalogTransitionStart);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
}
|
||||
@@ -162,7 +163,7 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
|
||||
else
|
||||
result = ((int) trunc(zahl) + 10) % 10;
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
}
|
||||
@@ -177,7 +178,7 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
|
||||
else
|
||||
// Akt. digit und Vorgänger haben Nulldurchgang
|
||||
result = ergebnis_vorkomma;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, Nulldurchgang hat stattgefunden = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, Nulldurchgang hat stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
}
|
||||
@@ -196,62 +197,55 @@ int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger,
|
||||
// keinen Nulldurchgang hat. Daher wird um 1 reduziert.
|
||||
result = (ergebnis_vorkomma - 1 + 10) % 10;
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe) + " ergebnis_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger)
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
|
||||
bool roundedUp = false;
|
||||
|
||||
if (ziffer_vorgaenger < 0)
|
||||
{
|
||||
result = (int) floor(zahl);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
return result;
|
||||
// Innerhalb der digitalen Unschaefe
|
||||
if (ergebnis_nachkomma >= (10-DigitalUnschaerfe * 10)) { // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = (int) (round(zahl) + 10) % 10;
|
||||
roundedUp = true;
|
||||
// vor/nachkomma neu berechnen, da wir anhand der Unschaefe die Zahl anpassen.
|
||||
ergebnis_nachkomma = ((int) floor(result * 10)) % 10;
|
||||
ergebnis_vorkomma = ((int) floor(result) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger: " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_vorkomma: " + std::to_string(ergebnis_vorkomma) +
|
||||
" erg_nachkomma: " + std::to_string(ergebnis_nachkomma));
|
||||
} else {
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - KEINE digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger));
|
||||
}
|
||||
|
||||
if ((ziffer_vorgaenger >= DigitalUebergangsbereichVorgaengerAnalogToDigit ) && (ziffer_vorgaenger <= (10.0 - DigitalUebergangsbereichVorgaengerAnalogToDigit)))
|
||||
{
|
||||
// kein Ziffernwechsel, da Vorgänger weit genug weg ist (0+/-DigitalUebergangsbereichVorgaenger) --> zahl wird gerundet
|
||||
if ((ergebnis_nachkomma <= 2) || (ergebnis_nachkomma >= 8)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = ((int) round(zahl) + 10) % 10;
|
||||
else
|
||||
result = ((int) trunc(zahl) + 10) % 10;
|
||||
// Kein Nulldurchgang hat stattgefunden.
|
||||
// Nur eval_vorgaenger verwendet, da ziffer_vorgaenger hier falsch sein könnte.
|
||||
// ziffer_vorgaenger<=0.1 & eval_vorgaenger=9 entspricht analog wurde zurückgesetzt wegen vorhergehender analog, die noch nicht auf 0 sind.
|
||||
if ((eval_vorgaenger>=6 && (ziffer_vorgaenger>analogDigitalTransitionStart || ziffer_vorgaenger<=0.2) && roundedUp)
|
||||
// digit läuft dem Analog vor. Darf aber erst passieren, wenn
|
||||
// digit wirklich schnon los läuft, deshalb 9
|
||||
|| (eval_vorgaenger>9 && ziffer_vorgaenger>analogDigitalTransitionStart && ergebnis_nachkomma<=1))
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (ziffer_vorgaenger <= 1 && eval_vorgaenger<9) // Nulldurchgang hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
|
||||
// aber Sonderfall ziffer_vorgaeger = 0.1 vor_vorgaenger 9.9 => eval_vorgaenger ist 9, damit hat Nulldurchgang nicht stattgefunden.
|
||||
{
|
||||
if (ergebnis_nachkomma > 5)
|
||||
result = (ergebnis_vorkomma + 1) % 10;
|
||||
else
|
||||
result = ergebnis_vorkomma;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - Nulldurchgang hat stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
result = ((ergebnis_vorkomma+10) - 1) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) +
|
||||
" ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
|
||||
}
|
||||
|
||||
// bleibt nur >= 9.5 --> noch kein Nulldurchgang --> 2.8 --> 2, und 3.1 --> 2
|
||||
// hier auf 4 reduziert, da erst ab Vorgänder 9 anfängt umzustellen. Bei 9.5 Vorgänger kann die aktuelle
|
||||
// Zahl noch x.4 - x.5 sein.
|
||||
if (ergebnis_nachkomma >= 4)
|
||||
result = ergebnis_vorkomma;
|
||||
else
|
||||
result = (ergebnis_vorkomma - 1 + 10) % 10;
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu - 9.0 --> noch kein Nulldurchgang = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
@@ -262,7 +256,7 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
if (ziffer_vorgaenger == -1)
|
||||
{
|
||||
result = (int) floor(zahl);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
return result;
|
||||
}
|
||||
@@ -275,14 +269,14 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
if (ziffer_vorgaenger <= AnalogFehler)
|
||||
{
|
||||
result = ((int) floor(zahl_max) + 10) % 10;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach oben - Ergebnis = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach oben - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
return result;
|
||||
}
|
||||
if (ziffer_vorgaenger >= 10 - AnalogFehler)
|
||||
{
|
||||
result = ((int) floor(zahl_min) + 10) % 10;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach unten - Ergebnis = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach unten - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
return result;
|
||||
}
|
||||
@@ -290,7 +284,7 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
|
||||
|
||||
result = ((int) floor(zahl) + 10) % 10;
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::ZeigerEvalAnalogNeu - Zahl eindeutig, keine Korrektur notwendig - Ergebnis = " + std::to_string(result) +
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl eindeutig, keine Korrektur notwendig - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
|
||||
return result;
|
||||
@@ -319,14 +313,14 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
disabled = true;
|
||||
while (getNextLine(pfile, &aktparamgraph) && !isNewParagraph(aktparamgraph));
|
||||
printf("[Analog/Digit] is disabled !!!\n");
|
||||
ESP_LOGD(TAG, "[Analog/Digit] is disabled!");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "LOGIMAGELOCATION") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
@@ -437,7 +431,7 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
|
||||
|
||||
_ret->ROI.push_back(neuroi);
|
||||
|
||||
printf("GetGENERAL - GENERAL %s - roi %s - CCW: %d\n", _analog.c_str(), _roi.c_str(), neuroi->CCW);
|
||||
ESP_LOGD(TAG, "GetGENERAL - GENERAL %s - roi %s - CCW: %d", _analog.c_str(), _roi.c_str(), neuroi->CCW);
|
||||
|
||||
return _ret;
|
||||
}
|
||||
@@ -478,7 +472,7 @@ bool ClassFlowCNNGeneral::doFlow(string time)
|
||||
return false;
|
||||
};
|
||||
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("ClassFlowCNNGeneral::doFlow nach Alignment");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow nach Alignment");
|
||||
|
||||
doNeuralNetwork(time);
|
||||
|
||||
@@ -496,7 +490,7 @@ bool ClassFlowCNNGeneral::doAlignAndCut(string time)
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
printf("General %d - Align&Cut\n", i);
|
||||
ESP_LOGD(TAG, "General %d - Align&Cut", i);
|
||||
|
||||
caic->CutAndSave(GENERAL[_ana]->ROI[i]->posx, GENERAL[_ana]->ROI[i]->posy, GENERAL[_ana]->ROI[i]->deltax, GENERAL[_ana]->ROI[i]->deltay, GENERAL[_ana]->ROI[i]->image_org);
|
||||
if (SaveAllFiles)
|
||||
@@ -553,10 +547,9 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
CTfLiteClass *tflite = new CTfLiteClass;
|
||||
string zwcnn = "/sdcard" + cnnmodelfile;
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
printf(zwcnn.c_str());printf("\n");
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
printf("Can't read model file /sdcard%s\n", cnnmodelfile.c_str());
|
||||
LogFile.WriteToFile("Cannot load model");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
@@ -574,37 +567,36 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
{
|
||||
case 2:
|
||||
CNNType = Analogue;
|
||||
printf("TFlite-Type set to Analogue\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to Analogue");
|
||||
break;
|
||||
case 10:
|
||||
CNNType = DoubleHyprid10;
|
||||
printf("TFlite-Type set to DoubleHyprid10\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to DoubleHyprid10");
|
||||
break;
|
||||
case 11:
|
||||
CNNType = Digital;
|
||||
printf("TFlite-Type set to Digital\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to Digital");
|
||||
break;
|
||||
/* case 20:
|
||||
CNNType = DigitalHyprid10;
|
||||
printf("TFlite-Type set to DigitalHyprid10\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to DigitalHyprid10");
|
||||
break;
|
||||
*/
|
||||
// case 22:
|
||||
// CNNType = DigitalHyprid;
|
||||
// printf("TFlite-Type set to DigitalHyprid\n");
|
||||
// ESP_LOGD(TAG, "TFlite-Type set to DigitalHyprid");
|
||||
// break;
|
||||
case 100:
|
||||
if (modelxsize==32 && modelysize == 32) {
|
||||
CNNType = Analogue100;
|
||||
printf("TFlite-Type set to Analogue100\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to Analogue100");
|
||||
} else {
|
||||
CNNType = Digital100;
|
||||
printf("TFlite-Type set to Digital\n");
|
||||
ESP_LOGD(TAG, "TFlite-Type set to Digital");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogFile.WriteToFile("ERROR ERROR ERROR - tflite passt nicht zur Firmware - ERROR ERROR ERROR (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
printf("ERROR ERROR ERROR - tflite passt nicht zur Firmware - ERROR ERROR ERROR\n");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite passt nicht zur Firmware (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -622,10 +614,9 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
CTfLiteClass *tflite = new CTfLiteClass;
|
||||
string zwcnn = "/sdcard" + cnnmodelfile;
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
printf(zwcnn.c_str());printf("\n");
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
printf("Can't read model file /sdcard%s\n", cnnmodelfile.c_str());
|
||||
LogFile.WriteToFile("Cannot load model");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
|
||||
delete tflite;
|
||||
return false;
|
||||
@@ -636,7 +627,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
printf("General %d - TfLite\n", i);
|
||||
ESP_LOGD(TAG, "General %d - TfLite", i);
|
||||
|
||||
switch (CNNType) {
|
||||
case Analogue:
|
||||
@@ -646,7 +637,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
f1 = tflite->GetOutputValue(0);
|
||||
f2 = tflite->GetOutputValue(1);
|
||||
@@ -657,7 +648,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = result * 10;
|
||||
|
||||
printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
if (isLogImage)
|
||||
LogImage(logPath, GENERAL[_ana]->ROI[i]->name, &GENERAL[_ana]->ROI[i]->result_float, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
} break;
|
||||
@@ -666,7 +657,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
GENERAL[_ana]->ROI[i]->result_klasse = 0;
|
||||
GENERAL[_ana]->ROI[i]->result_klasse = tflite->GetClassFromImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
printf("Result General(Digit)%i: %d\n", i, GENERAL[_ana]->ROI[i]->result_klasse);
|
||||
ESP_LOGD(TAG, "Result General(Digit)%i: %d", i, GENERAL[_ana]->ROI[i]->result_klasse);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -689,23 +680,23 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 10);
|
||||
_nachkomma = tflite->GetOutClassification(11, 21);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile(_zwres);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if ((_num == 10) || (_nachkomma == 10)) // NaN detektiert
|
||||
GENERAL[_ana]->ROI[i]->result_float = -1;
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
printf("Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile(_zwres);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -729,20 +720,20 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_nachkomma = tflite->GetOutClassification(10, 19);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile(_zwres);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
printf("Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
if (debugdetailgeneral) LogFile.WriteToFile(_zwres);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -769,7 +760,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
if (debugdetailgeneral) LogFile.WriteToFile("Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_numplus = (_num + 1) % 10;
|
||||
@@ -800,8 +791,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
string zw = "_num (p, m): " + to_string(_num) + " " + to_string(_numplus) + " " + to_string(_numminus);
|
||||
zw = zw + " _val (p, m): " + to_string(_val) + " " + to_string(_valplus) + " " + to_string(_valminus);
|
||||
zw = zw + " result: " + to_string(result) + " _fit: " + to_string(_fit);
|
||||
printf("details cnn: %s\n", zw.c_str());
|
||||
LogFile.WriteToFile(zw);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw);
|
||||
|
||||
|
||||
_result_save_file = result;
|
||||
@@ -811,9 +801,8 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
GENERAL[_ana]->ROI[i]->isReject = true;
|
||||
result = -1;
|
||||
_result_save_file+= 100; // Für den Fall, dass fit nicht ausreichend, soll trotzdem das Ergebnis mit "-10x.y" abgespeichert werden.
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + "Threshold: " + to_string(CNNGoodThreshold);
|
||||
printf("Value Rejected due to Threshold (Fit: %f, Threshold: %f\n", _fit, CNNGoodThreshold);
|
||||
LogFile.WriteToFile(zw);
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + "Threshold: " + to_string(CNNGoodThreshold) + ")";
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, zw);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -822,7 +811,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
|
||||
GENERAL[_ana]->ROI[i]->result_float = result;
|
||||
printf("Result General(Analog)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i: %f", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -860,7 +849,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
GENERAL[_ana]->ROI[i]->isReject = false;
|
||||
|
||||
printf("Result General(Analog)%i - CCW: %d - %f\n", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
@@ -906,7 +895,7 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
printf("Image: %d\n", (int) GENERAL[_ana]->ROI[i]->image);
|
||||
ESP_LOGD(TAG, "Image: %d", (int) GENERAL[_ana]->ROI[i]->image);
|
||||
if (GENERAL[_ana]->ROI[i]->image)
|
||||
{
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
@@ -978,3 +967,34 @@ void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numb
|
||||
(*_name_numbers).push_back(_name);
|
||||
}
|
||||
}
|
||||
|
||||
string ClassFlowCNNGeneral::getReadoutRawString(int _analog)
|
||||
{
|
||||
string rt = "";
|
||||
|
||||
if (_analog >= GENERAL.size() || GENERAL[_analog]==NULL || GENERAL[_analog]->ROI.size() == 0)
|
||||
return rt;
|
||||
|
||||
for (int i = 0; i < GENERAL[_analog]->ROI.size(); ++i)
|
||||
{
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
rt = rt + "," + RundeOutput(GENERAL[_analog]->ROI[i]->result_float, 1);
|
||||
}
|
||||
|
||||
if (CNNType == Digital)
|
||||
{
|
||||
if (GENERAL[_analog]->ROI[i]->result_klasse == 10)
|
||||
rt = rt + ",N";
|
||||
else
|
||||
rt = rt + "," + RundeOutput(GENERAL[_analog]->ROI[i]->result_klasse, 0);
|
||||
}
|
||||
|
||||
if ((CNNType == DoubleHyprid10) || (CNNType == Digital100))
|
||||
{
|
||||
rt = rt + "," + RundeOutput(GENERAL[_analog]->ROI[i]->result_float, 1);
|
||||
}
|
||||
}
|
||||
return rt;
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ protected:
|
||||
float DigitalUnschaerfe = 0.2;
|
||||
int DigitalBand = 3;
|
||||
float DigitalAnalogerVorgaengerUebergangsbereich = 2;
|
||||
float DigitalUebergangsbereichVorgaengerAnalogToDigit = 1; // war vorher 2
|
||||
float DigitalUebergangsbereichVorgaenger = 0.7; // 9.3 - 0.7
|
||||
float DigitalUebergangsbereichVorlauf = 9.7; // Vorlauf-Nulldurchgang passiert erst ab ca. 9.7
|
||||
|
||||
@@ -41,8 +40,8 @@ protected:
|
||||
bool SaveAllFiles;
|
||||
|
||||
int ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger);
|
||||
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger);
|
||||
int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false);
|
||||
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart);
|
||||
int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +57,9 @@ public:
|
||||
bool doFlow(string time);
|
||||
|
||||
string getHTMLSingleStep(string host);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _vorgaengerAnalog = -1);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _vorgaengerAnalog = -1, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
string getReadoutRawString(int _analog);
|
||||
|
||||
void DrawROI(CImageBasis *_zw);
|
||||
|
||||
|
||||
@@ -19,6 +19,8 @@ extern "C" {
|
||||
#include "time_sntp.h"
|
||||
#include "Helper.h"
|
||||
#include "server_ota.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "server_mqtt.h"
|
||||
|
||||
|
||||
//#include "CImg.h"
|
||||
@@ -27,13 +29,15 @@ extern "C" {
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
static const char* TAG = "flow_controll";
|
||||
static const char* TAG = "FLOW CTRL";
|
||||
|
||||
|
||||
std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
|
||||
std::string _classname = "";
|
||||
std::string result = "";
|
||||
// printf("_stepname: %s\n", _stepname.c_str());
|
||||
|
||||
ESP_LOGD(TAG, "Step %s start", _stepname.c_str());
|
||||
|
||||
if ((_stepname.compare("[MakeImage]") == 0) || (_stepname.compare(";[MakeImage]") == 0)){
|
||||
_classname = "ClassFlowMakeImage";
|
||||
}
|
||||
@@ -60,6 +64,8 @@ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _
|
||||
result = FlowControll[i]->getHTMLSingleStep(_host);
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Step %s end", _stepname.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -89,7 +95,7 @@ std::vector<HTMLInfo*> ClassFlowControll::GetAllDigital()
|
||||
{
|
||||
if (flowdigit)
|
||||
{
|
||||
printf("ClassFlowControll::GetAllDigital - flowdigit != NULL\n");
|
||||
ESP_LOGD(TAG, "ClassFlowControll::GetAllDigital - flowdigit != NULL");
|
||||
return flowdigit->GetHTMLInfo();
|
||||
}
|
||||
|
||||
@@ -131,7 +137,6 @@ string ClassFlowControll::GetMQTTMainTopic()
|
||||
if (FlowControll[i]->name().compare("ClassFlowMQTT") == 0)
|
||||
return ((ClassFlowMQTT*) (FlowControll[i]))->GetMQTTMainTopic();
|
||||
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -141,14 +146,13 @@ void ClassFlowControll::SetInitialParameter(void)
|
||||
{
|
||||
AutoStart = false;
|
||||
SetupModeActive = false;
|
||||
AutoIntervall = 10;
|
||||
AutoIntervall = 10; // Minutes
|
||||
flowdigit = NULL;
|
||||
flowanalog = NULL;
|
||||
flowpostprocessing = NULL;
|
||||
disabled = false;
|
||||
aktRunNr = 0;
|
||||
aktstatus = "Booting ...";
|
||||
|
||||
}
|
||||
|
||||
bool ClassFlowControll::isAutoStart(long &_intervall)
|
||||
@@ -204,6 +208,9 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
if (toUpper(_type).compare("[AUTOTIMER]") == 0)
|
||||
cfc = this;
|
||||
|
||||
if (toUpper(_type).compare("[DATALOGGING]") == 0)
|
||||
cfc = this;
|
||||
|
||||
if (toUpper(_type).compare("[DEBUG]") == 0)
|
||||
cfc = this;
|
||||
|
||||
@@ -230,7 +237,7 @@ void ClassFlowControll::InitFlow(std::string config)
|
||||
if (pFile != NULL)
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
line = std::string(zw);
|
||||
}
|
||||
|
||||
@@ -239,7 +246,7 @@ void ClassFlowControll::InitFlow(std::string config)
|
||||
cfc = CreateClassFlow(line);
|
||||
if (cfc)
|
||||
{
|
||||
printf("Start ReadParameter (%s)\n", line.c_str());
|
||||
ESP_LOGD(TAG, "Start ReadParameter (%s)", line.c_str());
|
||||
cfc->ReadParameter(pFile, line);
|
||||
}
|
||||
else
|
||||
@@ -247,7 +254,7 @@ void ClassFlowControll::InitFlow(std::string config)
|
||||
line = "";
|
||||
if (fgets(zw, 1024, pFile) && !feof(pFile))
|
||||
{
|
||||
printf("Read: %s", zw);
|
||||
ESP_LOGD(TAG, "Read: %s", zw);
|
||||
line = std::string(zw);
|
||||
}
|
||||
}
|
||||
@@ -269,7 +276,10 @@ void ClassFlowControll::doFlowMakeImageOnly(string time){
|
||||
if (FlowControll[i]->name() == "ClassFlowMakeImage") {
|
||||
// zw_time = gettimestring("%Y%m%d-%H%M%S");
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
aktstatus = TranslateAktstatus(FlowControll[i]->name()) + " (" + zw_time + ")";
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
|
||||
FlowControll[i]->doFlow(time);
|
||||
}
|
||||
}
|
||||
@@ -287,26 +297,29 @@ bool ClassFlowControll::doFlow(string time)
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
|
||||
#endif
|
||||
|
||||
/* Check if we have a valid date/time and if not restart the NTP client */
|
||||
if (! getTimeIsSet()) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Time not set, restarting NTP Client!");
|
||||
restartNtpClient();
|
||||
}
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
{
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
aktstatus = TranslateAktstatus(FlowControll[i]->name()) + " (" + zw_time + ")";
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
|
||||
// zw_time = gettimestring("%Y%m%d-%H%M%S");
|
||||
// aktstatus = zw_time + ": " + FlowControll[i]->name();
|
||||
|
||||
|
||||
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
|
||||
LogFile.WriteHeapInfo(zw);
|
||||
|
||||
if (!FlowControll[i]->doFlow(time)){
|
||||
repeat++;
|
||||
LogFile.WriteToFile("Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
|
||||
if (i) i -= 1; // vorheriger Schritt muss wiederholt werden (vermutlich Bilder aufnehmen)
|
||||
result = false;
|
||||
if (repeat > 5) {
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Wiederholung 5x nicht erfolgreich --> reboot");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Wiederholung 5x nicht erfolgreich --> reboot");
|
||||
doReboot();
|
||||
// Schritt wurde 5x wiederholt --> reboot
|
||||
}
|
||||
@@ -322,7 +335,9 @@ bool ClassFlowControll::doFlow(string time)
|
||||
|
||||
}
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
aktstatus = "Flow finished (" + zw_time + ")";
|
||||
std::string flowStatus = "Flow finished";
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -362,7 +377,7 @@ string ClassFlowControll::getReadoutAll(int _type)
|
||||
if (i < (*numbers).size()-1)
|
||||
out = out + "\r\n";
|
||||
}
|
||||
// printf("OUT: %s", out.c_str());
|
||||
// ESP_LOGD(TAG, "OUT: %s", out.c_str());
|
||||
}
|
||||
|
||||
return out;
|
||||
@@ -399,7 +414,7 @@ string ClassFlowControll::GetPrevalue(std::string _number)
|
||||
return flowpostprocessing->GetPreValue(_number);
|
||||
}
|
||||
|
||||
return std::string();
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern)
|
||||
@@ -408,7 +423,7 @@ std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string
|
||||
char* p;
|
||||
|
||||
_newvalue = trim(_newvalue);
|
||||
// printf("Input UpdatePreValue: %s\n", _newvalue.c_str());
|
||||
// ESP_LOGD(TAG, "Input UpdatePreValue: %s", _newvalue.c_str());
|
||||
|
||||
if (_newvalue.compare("0.0") == 0)
|
||||
{
|
||||
@@ -442,12 +457,13 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
return false;
|
||||
|
||||
|
||||
if ((toUpper(aktparamgraph).compare("[AUTOTIMER]") != 0) && (toUpper(aktparamgraph).compare("[DEBUG]") != 0) && (toUpper(aktparamgraph).compare("[SYSTEM]") != 0)) // Paragraph passt nicht zu MakeImage
|
||||
if ((toUpper(aktparamgraph).compare("[AUTOTIMER]") != 0) && (toUpper(aktparamgraph).compare("[DEBUG]") != 0) &&
|
||||
(toUpper(aktparamgraph).compare("[SYSTEM]") != 0 && (toUpper(aktparamgraph).compare("[DATALOGGING]") != 0))) // Paragraph passt nicht zu MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph, " =");
|
||||
zerlegt = ZerlegeZeile(aktparamgraph, " =");
|
||||
if ((toUpper(zerlegt[0]) == "AUTOSTART") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
@@ -455,25 +471,52 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
AutoStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "INTERVALL") && (zerlegt.size() > 1))
|
||||
{
|
||||
AutoIntervall = std::stof(zerlegt[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGACTIVE") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
{
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.SetDataLogToSD(true);
|
||||
}
|
||||
if (toUpper(zerlegt[1]) == "FALSE")
|
||||
else {
|
||||
LogFile.SetDataLogToSD(false);
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGRETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
{
|
||||
LogFile.SetDataLogRetention(std::stoi(zerlegt[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
|
||||
{
|
||||
/* matches esp_log_level_t */
|
||||
if ((toUpper(zerlegt[1]) == "TRUE") || (toUpper(zerlegt[1]) == "2"))
|
||||
{
|
||||
LogFile.SwitchOnOff(false);
|
||||
LogFile.setLogLevel(ESP_LOG_WARN);
|
||||
}
|
||||
else if ((toUpper(zerlegt[1]) == "FALSE") || (toUpper(zerlegt[1]) == "0") || (toUpper(zerlegt[1]) == "1"))
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_ERROR);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "3")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_INFO);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "4")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
{
|
||||
LogFile.SetRetention(std::stoi(zerlegt[1]));
|
||||
}
|
||||
LogFile.SetLogFileRetention(std::stoi(zerlegt[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "TIMEZONE") && (zerlegt.size() > 1))
|
||||
{
|
||||
@@ -493,9 +536,7 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
// reboot notwendig damit die neue wlan.ini auch benutzt wird !!!
|
||||
fclose(pfile);
|
||||
printf("do reboot\n");
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Reboot to activate new HOSTNAME.");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new HOSTNAME...");
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
doReboot();
|
||||
@@ -508,13 +549,14 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
SetupModeActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGLEVEL") && (zerlegt.size() > 1))
|
||||
{
|
||||
LogFile.setLogLevel(stoi(zerlegt[1]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Start the MQTT service */
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
if (FlowControll[i]->name().compare("ClassFlowMQTT") == 0)
|
||||
return ((ClassFlowMQTT*) (FlowControll[i]))->Start(AutoIntervall);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -522,7 +564,7 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
int ClassFlowControll::CleanTempFolder() {
|
||||
const char* folderPath = "/sdcard/img_tmp";
|
||||
|
||||
ESP_LOGI(TAG, "Clean up temporary folder to avoid damage of sdcard sectors : %s", folderPath);
|
||||
ESP_LOGD(TAG, "Clean up temporary folder to avoid damage of sdcard sectors : %s", folderPath);
|
||||
DIR *dir = opendir(folderPath);
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", folderPath);
|
||||
@@ -544,7 +586,7 @@ int ClassFlowControll::CleanTempFolder() {
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
ESP_LOGI(TAG, "%d files deleted", deleted);
|
||||
ESP_LOGD(TAG, "%d files deleted", deleted);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -558,7 +600,7 @@ esp_err_t ClassFlowControll::SendRawJPG(httpd_req_t *req)
|
||||
|
||||
esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
{
|
||||
printf("ClassFlowControll::GetJPGStream %s\n", _fn.c_str());
|
||||
ESP_LOGD(TAG, "ClassFlowControll::GetJPGStream %s", _fn.c_str());
|
||||
|
||||
CImageBasis *_send = NULL;
|
||||
esp_err_t result = ESP_FAIL;
|
||||
@@ -566,7 +608,7 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
|
||||
if (flowalignment == NULL)
|
||||
{
|
||||
printf("Can't continue, flowalignment is NULL\n");
|
||||
ESP_LOGD(TAG, "Can't continue, flowalignment is NULL");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -589,7 +631,7 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
{
|
||||
std::vector<HTMLInfo*> htmlinfo;
|
||||
htmlinfo = GetAllDigital();
|
||||
printf("After getClassFlowControll::GetAllDigital\n");
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllDigital");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
@@ -632,10 +674,10 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
|
||||
if (_send)
|
||||
{
|
||||
ESP_LOGI(TAG, "Sending file : %s ...", _fn.c_str());
|
||||
ESP_LOGD(TAG, "Sending file : %s ...", _fn.c_str());
|
||||
set_content_type_from_file(req, _fn.c_str());
|
||||
result = _send->SendJPGtoHTTP(req);
|
||||
ESP_LOGI(TAG, "File sending complete");
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
}
|
||||
@@ -648,6 +690,12 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowControll::getNumbersName()
|
||||
{
|
||||
return flowpostprocessing->getNumbersName();
|
||||
}
|
||||
|
||||
string ClassFlowControll::getJSON(std::string _id, std::string _mac)
|
||||
{
|
||||
return flowpostprocessing->GetJSON(_id, _mac);
|
||||
|
||||
@@ -51,6 +51,7 @@ public:
|
||||
string GetPrevalue(std::string _number = "");
|
||||
bool ReadParameter(FILE* pfile, string& aktparamgraph);
|
||||
string getJSON(std::string _id = "", std::string _mac = "");
|
||||
string getNumbersName();
|
||||
|
||||
string TranslateAktstatus(std::string _input);
|
||||
|
||||
|
||||
@@ -46,6 +46,7 @@ struct NumberPost {
|
||||
int AnzahlDigital;
|
||||
int DecimalShift;
|
||||
int DecimalShiftInitial;
|
||||
float AnalogDigitalTransitionStart; // Wann ist das digit > x.1, also wann fängt es an zu kippen
|
||||
int Nachkomma;
|
||||
|
||||
bool isExtendedResolution;
|
||||
|
||||
@@ -14,13 +14,16 @@ extern "C" {
|
||||
#include "time_sntp.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "CImageBasis.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char* TAG = "FLOW IMG";
|
||||
|
||||
ClassFlowImage::ClassFlowImage(const char* logTag)
|
||||
{
|
||||
this->logTag = logTag;
|
||||
isLogImage = false;
|
||||
disabled = false;
|
||||
|
||||
this->logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag) : ClassFlow(lfc)
|
||||
@@ -28,6 +31,7 @@ ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, const char* logTag
|
||||
this->logTag = logTag;
|
||||
isLogImage = false;
|
||||
disabled = false;
|
||||
this->logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev, const char* logTag) : ClassFlow(lfc, _prev)
|
||||
@@ -35,6 +39,7 @@ ClassFlowImage::ClassFlowImage(std::vector<ClassFlow*> * lfc, ClassFlow *_prev,
|
||||
this->logTag = logTag;
|
||||
isLogImage = false;
|
||||
disabled = false;
|
||||
this->logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,8 +50,7 @@ string ClassFlowImage::CreateLogFolder(string time) {
|
||||
string logPath = LogImageLocation + "/" + time.LOGFILE_TIME_FORMAT_DATE_EXTR + "/" + time.LOGFILE_TIME_FORMAT_HOUR_EXTR;
|
||||
isLogImage = mkdir_r(logPath.c_str(), S_IRWXU) == 0;
|
||||
if (!isLogImage) {
|
||||
ESP_LOGW(logTag, "Can't create log folder for analog images. Path %s", logPath.c_str());
|
||||
LogFile.WriteToFile("Can't create log folder for analog images. Path " + logPath);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't create log folder for analog images. Path " + logPath);
|
||||
}
|
||||
|
||||
return logPath;
|
||||
@@ -65,7 +69,7 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
|
||||
else
|
||||
{
|
||||
sprintf(buf, "%.1f_", *resultFloat);
|
||||
if (strcmp(buf, "10.0_"))
|
||||
if (strcmp(buf, "10.0_") == 0)
|
||||
sprintf(buf, "0.0_");
|
||||
}
|
||||
|
||||
@@ -79,7 +83,7 @@ void ClassFlowImage::LogImage(string logPath, string name, float *resultFloat, i
|
||||
nm = FormatFileName(nm);
|
||||
string output = "/sdcard/img_tmp/" + name + ".jpg";
|
||||
output = FormatFileName(output);
|
||||
printf("save to file: %s\n", nm.c_str());
|
||||
ESP_LOGD(logTag, "save to file: %s", nm.c_str());
|
||||
_img->SaveToFile(nm);
|
||||
// CopyFile(output, nm);
|
||||
}
|
||||
@@ -89,7 +93,7 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
if (!isLogImage)
|
||||
return;
|
||||
|
||||
ESP_LOGI(logTag, "remove old log images");
|
||||
ESP_LOGI(TAG, "remove old images");
|
||||
if (logfileRetentionInDays == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -99,16 +103,17 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
char cmpfilename[30];
|
||||
|
||||
time(&rawtime);
|
||||
rawtime = addDays(rawtime, -logfileRetentionInDays);
|
||||
rawtime = addDays(rawtime, -logfileRetentionInDays + 1);
|
||||
timeinfo = localtime(&rawtime);
|
||||
//ESP_LOGD(TAG, "ImagefileRetentionInDays: %d", logfileRetentionInDays);
|
||||
|
||||
strftime(cmpfilename, 30, LOGFILE_TIME_FORMAT, timeinfo);
|
||||
//ESP_LOGE(TAG, "log file name to compare: %s", cmpfilename);
|
||||
//ESP_LOGD(TAG, "file name to compare: %s", cmpfilename);
|
||||
string folderName = string(cmpfilename).LOGFILE_TIME_FORMAT_DATE_EXTR;
|
||||
|
||||
DIR *dir = opendir(LogImageLocation.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGI(logTag, "Failed to stat dir : %s", LogImageLocation.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", LogImageLocation.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,15 +123,16 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
string folderPath = LogImageLocation + "/" + entry->d_name;
|
||||
if (entry->d_type == DT_DIR) {
|
||||
//ESP_LOGI(logTag, "Compare %s %s", entry->d_name, folderName.c_str());
|
||||
//ESP_LOGD(TAG, "Compare %s to %s", entry->d_name, folderName.c_str());
|
||||
if ((strlen(entry->d_name) == folderName.length()) && (strcmp(entry->d_name, folderName.c_str()) < 0)) {
|
||||
deleted += removeFolder(folderPath.c_str(), logTag);
|
||||
removeFolder(folderPath.c_str(), logTag);
|
||||
deleted++;
|
||||
} else {
|
||||
notDeleted ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGI(logTag, "%d older log files deleted. %d current log files not deleted.", deleted, notDeleted);
|
||||
ESP_LOGI(TAG, "Image folder deleted: %d | Image folder not deleted: %d", deleted, notDeleted);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,12 @@
|
||||
#include "time_sntp.h"
|
||||
#include "interface_influxdb.h"
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
static const char* TAG = "class_flow_influxDb";
|
||||
|
||||
void ClassFlowInfluxDB::SetInitialParameter(void)
|
||||
{
|
||||
uri = "";
|
||||
@@ -76,8 +79,8 @@ bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
printf("while loop reading line: %s\n", aktparamgraph.c_str());
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str());
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
@@ -102,11 +105,11 @@ bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
if ((uri.length() > 0) && (database.length() > 0) && (measurement.length() > 0))
|
||||
{
|
||||
printf("Init InfluxDB with uri: %s, measurement: %s, user: %s, password: %s\n", uri.c_str(), measurement.c_str(), user.c_str(), password.c_str());
|
||||
ESP_LOGD(TAG, "Init InfluxDB with uri: %s, measurement: %s, user: %s, password: %s", uri.c_str(), measurement.c_str(), user.c_str(), password.c_str());
|
||||
InfluxDBInit(uri, database, measurement, user, password);
|
||||
InfluxDBenable = true;
|
||||
} else {
|
||||
printf("InfluxDB init skipped as we are missing some parameters");
|
||||
ESP_LOGD(TAG, "InfluxDB init skipped as we are missing some parameters");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,17 +1,32 @@
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "ClassFlowMQTT.h"
|
||||
#include "Helper.h"
|
||||
#include "connect_wlan.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "time_sntp.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "ClassFlowControll.h"
|
||||
|
||||
#include "server_mqtt.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
static const char *TAG = "FLOW MQTT";
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
extern const char* libfive_git_version(void);
|
||||
extern const char* libfive_git_revision(void);
|
||||
extern const char* libfive_git_branch(void);
|
||||
|
||||
|
||||
void ClassFlowMQTT::SetInitialParameter(void)
|
||||
{
|
||||
uri = "";
|
||||
@@ -19,22 +34,22 @@ void ClassFlowMQTT::SetInitialParameter(void)
|
||||
topicError = "";
|
||||
topicRate = "";
|
||||
topicTimeStamp = "";
|
||||
maintopic = "";
|
||||
mainerrortopic = "";
|
||||
maintopic = hostname;
|
||||
|
||||
topicUptime = "";
|
||||
topicFreeMem = "";
|
||||
clientname = "watermeter";
|
||||
|
||||
clientname = "AIOTED-" + getMac();
|
||||
|
||||
OldValue = "";
|
||||
flowpostprocessing = NULL;
|
||||
user = "";
|
||||
password = "";
|
||||
SetRetainFlag = 0;
|
||||
SetRetainFlag = 0;
|
||||
previousElement = NULL;
|
||||
ListFlowControll = NULL;
|
||||
disabled = false;
|
||||
MQTTenable = false;
|
||||
keepAlive = 600; // TODO This must be greater than the Flow Interval!
|
||||
keepAlive = 25*60;
|
||||
}
|
||||
|
||||
ClassFlowMQTT::ClassFlowMQTT()
|
||||
@@ -88,7 +103,7 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
@@ -103,10 +118,47 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SETRETAINFLAG") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(zerlegt[1]) == "TRUE") {
|
||||
SetRetainFlag = 1;
|
||||
setMqtt_Server_Retain(SetRetainFlag);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "HOMEASSISTANTDISCOVERY") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
SetHomeassistantDiscoveryEnabled(true);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "METERTYPE") && (zerlegt.size() > 1)) {
|
||||
/* Use meter type for the device class
|
||||
Make sure it is a listed one on https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes */
|
||||
if (toUpper(zerlegt[1]) == "WATER_M3") {
|
||||
mqttServer_setMeterType("water", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_L") {
|
||||
mqttServer_setMeterType("water", "L", "h", "L/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_FT3") {
|
||||
mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_GAL") {
|
||||
mqttServer_setMeterType("water", "gal", "h", "gal/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_M3") {
|
||||
mqttServer_setMeterType("gas", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_FT3") {
|
||||
mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_WH") {
|
||||
mqttServer_setMeterType("energy", "Wh", "h", "W");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_KWH") {
|
||||
mqttServer_setMeterType("energy", "kWh", "h", "kW");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_MWH") {
|
||||
mqttServer_setMeterType("energy", "MWh", "h", "MW");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
|
||||
{
|
||||
@@ -116,68 +168,15 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (((toUpper(zerlegt[0]) == "TOPIC") || (toUpper(zerlegt[0]) == "MAINTOPIC")) && (zerlegt.size() > 1))
|
||||
{
|
||||
maintopic = zerlegt[1];
|
||||
mqttServer_setMainTopic(maintopic);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __HIDE_PASSWORD
|
||||
printf("Init Read with uri: %s, clientname: %s, user: %s, password: XXXXXX, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), mainerrortopic.c_str());
|
||||
#else
|
||||
printf("Init Read with uri: %s, clientname: %s, user: %s, password: %s, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), password.c_str(), mainerrortopic.c_str());
|
||||
#endif
|
||||
/* Note:
|
||||
* Originally, we started the MQTT client here.
|
||||
* How ever we need the interval parameter from the ClassFlowControll, but that only gets started later.
|
||||
* To work around this, we delay the start and trigger it from ClassFlowControll::ReadParameter() */
|
||||
|
||||
if (!MQTTisConnected() && (uri.length() > 0) && (maintopic.length() > 0))
|
||||
{
|
||||
printf("InitMQTTInit\n");
|
||||
mainerrortopic = maintopic + "/connection";
|
||||
#ifdef __HIDE_PASSWORD
|
||||
printf("Init MQTT with uri: %s, clientname: %s, user: %s, password: XXXXXXXX, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), mainerrortopic.c_str());
|
||||
#else
|
||||
printf("Init MQTT with uri: %s, clientname: %s, user: %s, password: %s, maintopic: %s\n", uri.c_str(), clientname.c_str(), user.c_str(), password.c_str(), mainerrortopic.c_str());
|
||||
#endif
|
||||
if (!MQTTInit(uri, clientname, user, password, mainerrortopic, keepAlive))
|
||||
{ // Failed
|
||||
MQTTenable = false;
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}
|
||||
}
|
||||
|
||||
// Try sending mainerrortopic. If it fails, re-run init
|
||||
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
{ // Failed
|
||||
LogFile.WriteToFile("MQTT - Re-running init...!");
|
||||
if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
|
||||
{ // Failed
|
||||
MQTTenable = false;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Try again and quit if it fails
|
||||
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
{ // Failed
|
||||
MQTTenable = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
{ // Failed
|
||||
LogFile.WriteToFile("MQTT - Could not publish connection status!");
|
||||
MQTTenable = false;
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}*/
|
||||
|
||||
/* if(!MQTTPublish(_LWTContext, "", 1))
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not publish LWT!");
|
||||
MQTTenable = false;
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}*/
|
||||
|
||||
|
||||
MQTTenable = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -188,73 +187,58 @@ string ClassFlowMQTT::GetMQTTMainTopic()
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMQTT::Start(float AutoIntervall) {
|
||||
|
||||
roundInterval = AutoIntervall; // Minutes
|
||||
keepAlive = roundInterval * 60 * 2.5; // Seconds, make sure it is greater thatn 2 rounds!
|
||||
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << "Digitizer interval is " << roundInterval <<
|
||||
" minutes => setting MQTT LWT timeout to " << ((float)keepAlive/60) << " minutes.";
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, stream.str());
|
||||
|
||||
mqttServer_setParameter(flowpostprocessing->GetNumbers(), keepAlive, roundInterval);
|
||||
|
||||
MQTT_Configure(uri, clientname, user, password, maintopic, LWT_TOPIC, LWT_CONNECTED, LWT_DISCONNECTED,
|
||||
keepAlive, SetRetainFlag, (void *)&GotConnected);
|
||||
|
||||
if (!MQTT_Init()) {
|
||||
if (!MQTT_Init()) { // Retry
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
{
|
||||
// Try sending mainerrortopic. If it fails, re-run init
|
||||
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
{ // Failed
|
||||
LogFile.WriteToFile("MQTT - Re-running init...!");
|
||||
if (!MQTTInit(this->uri, this->clientname, this->user, this->password, this->mainerrortopic, keepAlive))
|
||||
{ // Failed
|
||||
MQTTenable = false;
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}
|
||||
}
|
||||
|
||||
// Try again and quit if it fails
|
||||
if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
{ // Failed
|
||||
MQTTenable = false;
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}
|
||||
|
||||
std::string result;
|
||||
std::string resulterror = "";
|
||||
std::string resultraw = "";
|
||||
std::string resultrate = "";
|
||||
std::string resultrate = ""; // Always Unit / Minute
|
||||
std::string resultRatePerTimeUnit = ""; // According to selection
|
||||
std::string resulttimestamp = "";
|
||||
std::string resultchangabs = "";
|
||||
string zw = "";
|
||||
string namenumber = "";
|
||||
|
||||
// if (!MQTTPublish(mainerrortopic, "connected", SetRetainFlag))
|
||||
//{ // Failed, skip other topics
|
||||
// return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
//}
|
||||
|
||||
zw = maintopic + "/" + "uptime";
|
||||
char uptimeStr[11];
|
||||
sprintf(uptimeStr, "%ld", (long)getUpTime());
|
||||
MQTTPublish(zw, uptimeStr, SetRetainFlag);
|
||||
|
||||
zw = maintopic + "/" + "freeMem";
|
||||
char freeheapmem[11];
|
||||
sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
|
||||
if (!MQTTPublish(zw, freeheapmem, SetRetainFlag))
|
||||
{ // Failed, skip other topics
|
||||
return true; // We need to return true despite we failed, else it will retry 5x and then reboot!
|
||||
}
|
||||
|
||||
zw = maintopic + "/" + "wifiRSSI";
|
||||
char rssi[11];
|
||||
sprintf(rssi, "%d", get_WIFI_RSSI());
|
||||
MQTTPublish(zw, rssi, SetRetainFlag);
|
||||
|
||||
zw = maintopic + "/" + "CPUtemp";
|
||||
std::string cputemp = std::to_string(temperatureRead());
|
||||
MQTTPublish(zw, cputemp, SetRetainFlag);
|
||||
publishSystemData();
|
||||
|
||||
if (flowpostprocessing)
|
||||
{
|
||||
std::vector<NumberPost*>* NUMBERS = flowpostprocessing->GetNumbers();
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing MQTT topics...");
|
||||
|
||||
for (int i = 0; i < (*NUMBERS).size(); ++i)
|
||||
{
|
||||
result = (*NUMBERS)[i]->ReturnValue;
|
||||
resultraw = (*NUMBERS)[i]->ReturnRawValue;
|
||||
resulterror = (*NUMBERS)[i]->ErrorMessageText;
|
||||
resultrate = (*NUMBERS)[i]->ReturnRateValue;
|
||||
resultchangabs = (*NUMBERS)[i]->ReturnChangeAbsolute;
|
||||
resultrate = (*NUMBERS)[i]->ReturnRateValue; // Unit per minutes
|
||||
resultchangabs = (*NUMBERS)[i]->ReturnChangeAbsolute; // Units per round
|
||||
resulttimestamp = (*NUMBERS)[i]->timeStamp;
|
||||
|
||||
namenumber = (*NUMBERS)[i]->name;
|
||||
@@ -263,30 +247,36 @@ bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
else
|
||||
namenumber = maintopic + "/" + namenumber + "/";
|
||||
|
||||
zw = namenumber + "value";
|
||||
|
||||
if (result.length() > 0)
|
||||
MQTTPublish(zw, result, SetRetainFlag);
|
||||
MQTTPublish(namenumber + "value", result, SetRetainFlag);
|
||||
|
||||
zw = namenumber + "error";
|
||||
if (resulterror.length() > 0)
|
||||
MQTTPublish(zw, resulterror, SetRetainFlag);
|
||||
MQTTPublish(namenumber + "error", resulterror, SetRetainFlag);
|
||||
|
||||
zw = namenumber + "rate";
|
||||
if (resultrate.length() > 0)
|
||||
MQTTPublish(zw, resultrate, SetRetainFlag);
|
||||
if (resultrate.length() > 0) {
|
||||
MQTTPublish(namenumber + "rate", resultrate, SetRetainFlag);
|
||||
|
||||
std::string resultRatePerTimeUnit;
|
||||
if (getTimeUnit() == "h") { // Need conversion to be per hour
|
||||
resultRatePerTimeUnit = resultRatePerTimeUnit = to_string((*NUMBERS)[i]->FlowRateAct * 60); // per minutes => per hour
|
||||
}
|
||||
else { // Keep per minute
|
||||
resultRatePerTimeUnit = resultrate;
|
||||
}
|
||||
MQTTPublish(namenumber + "rate_per_time_unit", resultRatePerTimeUnit, SetRetainFlag);
|
||||
}
|
||||
|
||||
zw = namenumber + "changeabsolut";
|
||||
if (resultchangabs.length() > 0)
|
||||
MQTTPublish(zw, resultchangabs, SetRetainFlag);
|
||||
if (resultchangabs.length() > 0) {
|
||||
MQTTPublish(namenumber + "changeabsolut", resultchangabs, SetRetainFlag); // Legacy API
|
||||
MQTTPublish(namenumber + "rate_per_digitalization_round", resultchangabs, SetRetainFlag);
|
||||
}
|
||||
|
||||
zw = namenumber + "raw";
|
||||
if (resultraw.length() > 0)
|
||||
MQTTPublish(zw, resultraw, SetRetainFlag);
|
||||
MQTTPublish(namenumber + "raw", resultraw, SetRetainFlag);
|
||||
|
||||
zw = namenumber + "timestamp";
|
||||
if (resulttimestamp.length() > 0)
|
||||
MQTTPublish(zw, resulttimestamp, SetRetainFlag);
|
||||
|
||||
MQTTPublish(namenumber + "timestamp", resulttimestamp, SetRetainFlag);
|
||||
|
||||
std::string json = "";
|
||||
|
||||
@@ -297,14 +287,15 @@ bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
|
||||
json += ",\"raw\":\""+resultraw;
|
||||
json += "\",\"error\":\""+resulterror;
|
||||
|
||||
if (resultrate.length() > 0)
|
||||
json += "\",\"rate\":"+resultrate;
|
||||
else
|
||||
json += "\",\"rate\":\"\"";
|
||||
|
||||
json += ",\"timestamp\":\""+resulttimestamp+"\"}";
|
||||
|
||||
zw = namenumber + "json";
|
||||
MQTTPublish(zw, json, SetRetainFlag);
|
||||
MQTTPublish(namenumber + "json", json, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
@@ -14,10 +14,10 @@ protected:
|
||||
ClassFlowPostProcessing* flowpostprocessing;
|
||||
std::string user, password;
|
||||
int SetRetainFlag;
|
||||
bool MQTTenable;
|
||||
int keepAlive;
|
||||
int keepAlive; // Seconds
|
||||
float roundInterval; // Minutes
|
||||
|
||||
std::string maintopic, mainerrortopic;
|
||||
std::string maintopic;
|
||||
void SetInitialParameter(void);
|
||||
|
||||
public:
|
||||
@@ -26,6 +26,7 @@ public:
|
||||
ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev);
|
||||
|
||||
string GetMQTTMainTopic();
|
||||
bool Start(float AutoIntervall);
|
||||
|
||||
bool ReadParameter(FILE* pfile, string& aktparamgraph);
|
||||
bool doFlow(string time);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include "ClassControllCamera.h"
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -30,7 +31,7 @@ void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
|
||||
rawImage->width = image_width;
|
||||
rawImage->height = image_height;
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
printf("Flashdauer: %d\n", flashdauer);
|
||||
ESP_LOGD(TAG, "Flashdauer: %d", flashdauer);
|
||||
Camera.CaptureToBasisImage(rawImage, flashdauer);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
@@ -56,6 +57,8 @@ void ClassFlowMakeImage::SetInitialParameter(void)
|
||||
|
||||
ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlowImage(lfc, TAG)
|
||||
{
|
||||
LogImageLocation = "/log/source";
|
||||
logfileRetentionInDays = 5;
|
||||
SetInitialParameter();
|
||||
}
|
||||
|
||||
@@ -77,7 +80,7 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
|
||||
{
|
||||
LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
@@ -103,6 +106,10 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
waitbeforepicture = stoi(zerlegt[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "BRIGHTNESS") && (zerlegt.size() > 1))
|
||||
{
|
||||
@@ -145,7 +152,7 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
waitbeforepicture_store = waitbeforepicture;
|
||||
if (FixedExposure && (waitbeforepicture > 0))
|
||||
{
|
||||
// printf("Fixed Exposure enabled!\n");
|
||||
// ESP_LOGD(TAG, "Fixed Exposure enabled!");
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
Camera.EnableAutoExposure(flashdauer);
|
||||
waitbeforepicture = 0.2;
|
||||
|
||||
@@ -9,13 +9,34 @@
|
||||
#include <time.h>
|
||||
|
||||
#include "time_sntp.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char* TAG = "FLOW POSTPROC";
|
||||
|
||||
//#define SERIAL_DEBUG // testing debug on serial enabled
|
||||
|
||||
|
||||
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S"
|
||||
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
|
||||
#define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
|
||||
|
||||
|
||||
std::string ClassFlowPostProcessing::getNumbersName()
|
||||
{
|
||||
std::string ret="";
|
||||
|
||||
for (int i = 0; i < NUMBERS.size(); ++i)
|
||||
{
|
||||
ret += NUMBERS[i]->name;
|
||||
if (i < NUMBERS.size()-1)
|
||||
ret = ret + "\t";
|
||||
}
|
||||
|
||||
// ESP_LOGI(TAG, "Result ClassFlowPostProcessing::getNumbersName: %s", ret.c_str());
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string ClassFlowPostProcessing::GetJSON(std::string _id, std::string _mac, std::string _lineend)
|
||||
{
|
||||
std::string json="{" + _lineend;
|
||||
@@ -58,12 +79,15 @@ string ClassFlowPostProcessing::GetPreValue(std::string _number)
|
||||
int index = -1;
|
||||
|
||||
if (_number == "")
|
||||
_number = "default";
|
||||
_number = "default";
|
||||
|
||||
for (int i = 0; i < NUMBERS.size(); ++i)
|
||||
if (NUMBERS[i]->name == _number)
|
||||
index = i;
|
||||
|
||||
if (index == -1)
|
||||
return std::string("");
|
||||
|
||||
result = RundeOutput(NUMBERS[index]->PreValue, NUMBERS[index]->Nachkomma);
|
||||
|
||||
return result;
|
||||
@@ -71,10 +95,10 @@ string ClassFlowPostProcessing::GetPreValue(std::string _number)
|
||||
|
||||
void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _extern)
|
||||
{
|
||||
printf("SetPrevalue: %f, %s\n", zw, _numbers.c_str());
|
||||
ESP_LOGD(TAG, "SetPrevalue: %f, %s", zw, _numbers.c_str());
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
// printf("Number %d, %s\n", j, NUMBERS[j]->name.c_str());
|
||||
// ESP_LOGD(TAG, "Number %d, %s", j, NUMBERS[j]->name.c_str());
|
||||
if (NUMBERS[j]->name == _numbers)
|
||||
{
|
||||
NUMBERS[j]->PreValue = zw;
|
||||
@@ -85,7 +109,7 @@ void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _exte
|
||||
time(&(NUMBERS[j]->lastvalue));
|
||||
localtime(&(NUMBERS[j]->lastvalue));
|
||||
}
|
||||
// printf("Found %d! - set to %f\n", j, NUMBERS[j]->PreValue);
|
||||
// ESP_LOGD(TAG, "Found %d! - set to %f", j, NUMBERS[j]->PreValue);
|
||||
}
|
||||
}
|
||||
UpdatePreValueINI = true;
|
||||
@@ -109,7 +133,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
return false;
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
printf("Read line Prevalue.ini: %s", zw);
|
||||
ESP_LOGD(TAG, "Read line Prevalue.ini: %s", zw);
|
||||
zwtime = trim(std::string(zw));
|
||||
if (zwtime.length() == 0)
|
||||
return false;
|
||||
@@ -160,7 +184,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
_done = true;
|
||||
else
|
||||
{
|
||||
printf("Read line Prevalue.ini: %s", zw);
|
||||
ESP_LOGD(TAG, "Read line Prevalue.ini: %s", zw);
|
||||
zerlegt = HelperZerlegeZeile(trim(std::string(zw)), "\t");
|
||||
if (zerlegt.size() > 1)
|
||||
{
|
||||
@@ -176,7 +200,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
fclose(pFile);
|
||||
printf("%s", zw);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
zwvalue = trim(std::string(zw));
|
||||
NUMBERS[0]->PreValue = stod(zwvalue.c_str());
|
||||
|
||||
@@ -193,7 +217,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
whenStart.tm_sec = ss;
|
||||
whenStart.tm_isdst = -1;
|
||||
|
||||
printf("TIME: %d, %d, %d, %d, %d, %d\n", whenStart.tm_year, whenStart.tm_mon, whenStart.tm_wday, whenStart.tm_hour, whenStart.tm_min, whenStart.tm_sec);
|
||||
ESP_LOGD(TAG, "TIME: %d, %d, %d, %d, %d, %d", whenStart.tm_year, whenStart.tm_mon, whenStart.tm_wday, whenStart.tm_hour, whenStart.tm_min, whenStart.tm_sec);
|
||||
|
||||
NUMBERS[0]->lastvalue = mktime(&whenStart);
|
||||
|
||||
@@ -235,10 +259,10 @@ void ClassFlowPostProcessing::SavePreValue()
|
||||
struct tm* timeinfo = localtime(&NUMBERS[j]->lastvalue);
|
||||
strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo);
|
||||
NUMBERS[j]->timeStamp = std::string(buffer);
|
||||
// printf("SaverPreValue %d, Value: %f, Nachkomma %d\n", j, NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
// ESP_LOGD(TAG, "SaverPreValue %d, Value: %f, Nachkomma %d", j, NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
|
||||
_zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + "\n";
|
||||
printf("Write PreValue Zeile: %s\n", _zw.c_str());
|
||||
ESP_LOGD(TAG, "Write PreValue Zeile: %s", _zw.c_str());
|
||||
if (pFile) {
|
||||
fputs(_zw.c_str(), pFile);
|
||||
}
|
||||
@@ -277,7 +301,7 @@ void ClassFlowPostProcessing::handleDecimalExtendedResolution(string _decsep, st
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
@@ -307,7 +331,7 @@ void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _val
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
@@ -323,7 +347,7 @@ void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _val
|
||||
}
|
||||
/* catch(const std::exception& e)
|
||||
{
|
||||
printf("ERROR - Decimalshift is not a number: %s\n", _value.c_str());
|
||||
ESP_LOGD(TAG, "ERROR - Decimalshift is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
@@ -342,13 +366,36 @@ void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _val
|
||||
}
|
||||
}
|
||||
|
||||
void ClassFlowPostProcessing::handleAnalogDigitalTransitionStart(string _decsep, string _value)
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
_digit = "default";
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
float _zwdc = 9.2;
|
||||
{
|
||||
_zwdc = stof(_value);
|
||||
}
|
||||
if (_digit == "default" || NUMBERS[j]->name == _digit) // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
{
|
||||
NUMBERS[j]->AnalogDigitalTransitionStart = _zwdc;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
@@ -375,36 +422,33 @@ void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
|
||||
|
||||
|
||||
|
||||
void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// printf("Name: %s, Pospunkt: %d\n", _decsep.c_str(), _pospunkt);
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
_digit = "default";
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
float _zwdc = 1;
|
||||
|
||||
// try
|
||||
{
|
||||
_zwdc = stof(_value);
|
||||
}
|
||||
/* catch(const std::exception& e)
|
||||
{
|
||||
printf("ERROR - MaxRateValue is not a number: %s\n", _value.c_str());
|
||||
ESP_LOGD(TAG, "ERROR - MaxRateValue is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
{
|
||||
NUMBERS[j]->useMaxRateValue = true;
|
||||
NUMBERS[j]->MaxRateValue = _zwdc;
|
||||
}
|
||||
|
||||
if (NUMBERS[j]->name == _digit)
|
||||
{
|
||||
NUMBERS[j]->useMaxRateValue = true;
|
||||
@@ -434,7 +478,7 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
std::string _param = GetParameterName(zerlegt[0]);
|
||||
|
||||
if ((toUpper(_param) == "EXTENDEDRESOLUTION") && (zerlegt.size() > 1))
|
||||
@@ -446,6 +490,10 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
handleDecimalSeparator(zerlegt[0], zerlegt[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "ANALOGDIGITALTRANSITIONSTART") && (zerlegt.size() > 1))
|
||||
{
|
||||
handleAnalogDigitalTransitionStart(zerlegt[0], zerlegt[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "MAXRATEVALUE") && (zerlegt.size() > 1))
|
||||
{
|
||||
handleMaxRateValue(zerlegt[0], zerlegt[1]);
|
||||
@@ -516,7 +564,7 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
flowAnalog->UpdateNameNumbers(&name_numbers);
|
||||
}
|
||||
|
||||
printf("Anzahl NUMBERS: %d - DIGITS: %d, ANALOG: %d\n", name_numbers.size(), anzDIGIT, anzANALOG);
|
||||
ESP_LOGD(TAG, "Anzahl NUMBERS: %d - DIGITS: %d, ANALOG: %d", name_numbers.size(), anzDIGIT, anzANALOG);
|
||||
|
||||
for (int _num = 0; _num < name_numbers.size(); ++_num)
|
||||
{
|
||||
@@ -556,6 +604,7 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
_number->DecimalShift = 0;
|
||||
_number->DecimalShiftInitial = 0;
|
||||
_number->isExtendedResolution = false;
|
||||
_number->AnalogDigitalTransitionStart=9.2;
|
||||
|
||||
|
||||
_number->FlowRateAct = 0; // m3 / min
|
||||
@@ -571,7 +620,7 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
}
|
||||
|
||||
for (int i = 0; i < NUMBERS.size(); ++i) {
|
||||
printf("Number %s, Anz DIG: %d, Anz ANA %d\n", NUMBERS[i]->name.c_str(), NUMBERS[i]->AnzahlDigital, NUMBERS[i]->AnzahlAnalog);
|
||||
ESP_LOGD(TAG, "Number %s, Anz DIG: %d, Anz ANA %d", NUMBERS[i]->name.c_str(), NUMBERS[i]->AnzahlDigital, NUMBERS[i]->AnzahlAnalog);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -640,7 +689,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
zwtime = std::string(strftime_buf);
|
||||
|
||||
printf("Anzahl NUMBERS: %d\n", NUMBERS.size());
|
||||
ESP_LOGD(TAG, "Anzahl NUMBERS: %d", NUMBERS.size());
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
@@ -665,7 +714,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After analog->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After analog->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = "." + NUMBERS[j]->ReturnRawValue;
|
||||
@@ -673,17 +722,17 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
if (NUMBERS[j]->digit_roi)
|
||||
{
|
||||
if (NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float) + NUMBERS[j]->ReturnRawValue;
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float, NUMBERS[j]->AnalogDigitalTransitionStart) + NUMBERS[j]->ReturnRawValue;
|
||||
else
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution nur falls es keine analogen Ziffern gibt
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After digital->getReadout: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After digital->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
NUMBERS[j]->ReturnRawValue = ShiftDecimal(NUMBERS[j]->ReturnRawValue, NUMBERS[j]->DecimalShift);
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After ShiftDecimal: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After ShiftDecimal: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
|
||||
if (IgnoreLeadingNaN)
|
||||
@@ -691,29 +740,34 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ReturnRawValue.erase(0, 1);
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After IgnoreLeadingNaN: ReturnRaw %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After IgnoreLeadingNaN: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
NUMBERS[j]->ReturnValue = NUMBERS[j]->ReturnRawValue;
|
||||
|
||||
if (findDelimiterPos(NUMBERS[j]->ReturnValue, "N") != std::string::npos)
|
||||
{
|
||||
if (PreValueUse && NUMBERS[j]->PreValueOkay)
|
||||
{
|
||||
NUMBERS[j]->ReturnValue = ErsetzteN(NUMBERS[j]->ReturnValue, NUMBERS[j]->PreValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteDataLog(j);
|
||||
continue; // es gibt keinen Zahl, da noch ein N vorhanden ist.
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After findDelimiterPos: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After findDelimiterPos: ReturnValue %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
// Lösche führende Nullen (außer es ist nur noch einen 0)
|
||||
while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0'))
|
||||
NUMBERS[j]->ReturnValue.erase(0, 1);
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After removeLeadingZeros: ReturnValue %s\n", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
ESP_LOGD(TAG, "After removeLeadingZeros: ReturnValue %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
NUMBERS[j]->Value = std::stod(NUMBERS[j]->ReturnValue);
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After setting the Value: Value %f and as double is %f\n", NUMBERS[j]->Value, std::stod(NUMBERS[j]->ReturnValue));
|
||||
ESP_LOGD(TAG, "After setting the Value: Value %f and as double is %f", NUMBERS[j]->Value, std::stod(NUMBERS[j]->ReturnValue));
|
||||
#endif
|
||||
|
||||
if (NUMBERS[j]->checkDigitIncreaseConsistency)
|
||||
@@ -721,33 +775,48 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
if (flowDigit)
|
||||
{
|
||||
if (flowDigit->getCNNType() != Digital)
|
||||
printf("checkDigitIncreaseConsistency = true - ignored due to wrong CNN-Type (not Digital Classification)\n");
|
||||
ESP_LOGD(TAG, "checkDigitIncreaseConsistency = true - ignored due to wrong CNN-Type (not Digital Classification)");
|
||||
else
|
||||
NUMBERS[j]->Value = checkDigitConsistency(NUMBERS[j]->Value, NUMBERS[j]->DecimalShift, NUMBERS[j]->analog_roi != NULL, NUMBERS[j]->PreValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("checkDigitIncreaseConsistency = true - no digital numbers defined!\n");
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "checkDigitIncreaseConsistency = true - no digital numbers defined!");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After checkDigitIncreaseConsistency: Value %f\n", NUMBERS[j]->Value);
|
||||
ESP_LOGD(TAG, "After checkDigitIncreaseConsistency: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
if (!NUMBERS[j]->AllowNegativeRates)
|
||||
{
|
||||
if (NUMBERS[j]->Value < NUMBERS[j]->PreValue)
|
||||
if ((NUMBERS[j]->Value < NUMBERS[j]->PreValue))
|
||||
{
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " ";
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
continue;
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "Neg: value=%f, preValue=%f, preToll%f", NUMBERS[j]->Value, NUMBERS[j]->PreValue,
|
||||
NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))
|
||||
) ;
|
||||
#endif
|
||||
// Bei isExtendedResolution Ungenauigkeit von 0.2 mit einrechnen.
|
||||
if (NUMBERS[j]->Value >= (NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))) && NUMBERS[j]->isExtendedResolution) {
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = to_string(NUMBERS[j]->PreValue);
|
||||
} else {
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " ";
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After AllowNegativeRates: Value %f\n", NUMBERS[j]->Value);
|
||||
ESP_LOGD(TAG, "After AllowNegativeRates: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden
|
||||
difference /= 60;
|
||||
@@ -768,11 +837,12 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->ReturnRateValue = "";
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("After MaxRateCheck: Value %f\n", NUMBERS[j]->Value);
|
||||
ESP_LOGD(TAG, "After MaxRateCheck: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
@@ -787,13 +857,41 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
UpdatePreValueINI = true;
|
||||
|
||||
string _zw = "PostProcessing - Raw: " + NUMBERS[j]->ReturnRawValue + " Value: " + NUMBERS[j]->ReturnValue + " Error: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(_zw);
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
}
|
||||
|
||||
SavePreValue();
|
||||
return true;
|
||||
}
|
||||
|
||||
void ClassFlowPostProcessing::WriteDataLog(int _index)
|
||||
{
|
||||
if (!LogFile.GetDataLogToSD()){
|
||||
return;
|
||||
}
|
||||
|
||||
string analog = "";
|
||||
string digital = "";
|
||||
string timezw = "";
|
||||
char buffer[80];
|
||||
struct tm* timeinfo = localtime(&NUMBERS[_index]->lastvalue);
|
||||
strftime(buffer, 80, PREVALUE_TIME_FORMAT_OUTPUT, timeinfo);
|
||||
timezw = std::string(buffer);
|
||||
|
||||
if (flowAnalog)
|
||||
analog = flowAnalog->getReadoutRawString(_index);
|
||||
if (flowDigit)
|
||||
digital = flowDigit->getReadoutRawString(_index);
|
||||
LogFile.WriteToData(timezw, NUMBERS[_index]->name,
|
||||
NUMBERS[_index]->ReturnRawValue, NUMBERS[_index]->ReturnValue, NUMBERS[_index]->ReturnPreValue,
|
||||
NUMBERS[_index]->ReturnRateValue, NUMBERS[_index]->ReturnChangeAbsolute,
|
||||
NUMBERS[_index]->ErrorMessageText,
|
||||
digital, analog);
|
||||
ESP_LOGD(TAG, "WriteDataLog: %s, %s, %s, %s, %s", NUMBERS[_index]->ReturnRawValue.c_str(), NUMBERS[_index]->ReturnValue.c_str(), NUMBERS[_index]->ErrorMessageText.c_str(), digital.c_str(), analog.c_str());
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
{
|
||||
@@ -801,7 +899,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
{
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi) // es gibt nur digitale ziffern
|
||||
{
|
||||
// printf("Nurdigital\n");
|
||||
// ESP_LOGD(TAG, "Nurdigital");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
|
||||
if (NUMBERS[j]->isExtendedResolution && flowDigit->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
@@ -812,7 +910,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
|
||||
if (!NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) // es gibt nur analoge ziffern
|
||||
{
|
||||
// printf("Nur analog\n");
|
||||
// ESP_LOGD(TAG, "Nur analog");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShift-1;
|
||||
@@ -822,7 +920,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
|
||||
if (NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) // digital + analog
|
||||
{
|
||||
// printf("Nur digital + analog\n");
|
||||
// ESP_LOGD(TAG, "Nur digital + analog");
|
||||
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
NUMBERS[j]->Nachkomma = NUMBERS[j]->analog_roi->ROI.size() - NUMBERS[j]->DecimalShift;
|
||||
@@ -832,7 +930,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
|
||||
}
|
||||
|
||||
printf("UpdateNachkommaDecShift NUMBER%i: Nachkomma %i, DecShift %i\n", j, NUMBERS[j]->Nachkomma,NUMBERS[j]->DecimalShift);
|
||||
ESP_LOGD(TAG, "UpdateNachkommaDecShift NUMBER%i: Nachkomma %i, DecShift %i", j, NUMBERS[j]->Nachkomma,NUMBERS[j]->DecimalShift);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -851,29 +949,6 @@ string ClassFlowPostProcessing::getReadoutParam(bool _rawValue, bool _noerror, i
|
||||
return NUMBERS[_number]->ReturnValue;
|
||||
}
|
||||
|
||||
string ClassFlowPostProcessing::RundeOutput(double _in, int _anzNachkomma){
|
||||
std::stringstream stream;
|
||||
int _zw = _in;
|
||||
// printf("AnzNachkomma: %d\n", _anzNachkomma);
|
||||
|
||||
if (_anzNachkomma < 0) {
|
||||
_anzNachkomma = 0;
|
||||
}
|
||||
|
||||
if (_anzNachkomma > 0)
|
||||
{
|
||||
stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
|
||||
return stream.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << _zw;
|
||||
}
|
||||
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowPostProcessing::ErsetzteN(string input, double _prevalue)
|
||||
{
|
||||
@@ -919,12 +994,9 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
pot++;
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("checkDigitConsistency: pot=%d, decimalshift=%d\n", pot, _decilamshift);
|
||||
ESP_LOGD(TAG, "checkDigitConsistency: pot=%d, decimalshift=%d", pot, _decilamshift);
|
||||
#endif
|
||||
pot_max = ((int) log10(input)) + 1;
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("checkDigitConsistency: not_checked_input=%f\n", not_checked_input);
|
||||
#endif
|
||||
while (pot <= pot_max)
|
||||
{
|
||||
zw = input / pow(10, pot-1);
|
||||
@@ -954,7 +1026,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
printf("checkDigitConsistency: input=%f", input);
|
||||
ESP_LOGD(TAG, "checkDigitConsistency: input=%f", input);
|
||||
#endif
|
||||
pot++;
|
||||
}
|
||||
@@ -977,3 +1049,5 @@ string ClassFlowPostProcessing::getReadoutError(int _number)
|
||||
{
|
||||
return NUMBERS[_number]->ErrorMessageText;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -34,13 +34,16 @@ protected:
|
||||
|
||||
string ErsetzteN(string, double _prevalue);
|
||||
float checkDigitConsistency(double input, int _decilamshift, bool _isanalog, double _preValue);
|
||||
string RundeOutput(double _in, int _anzNachkomma);
|
||||
|
||||
void InitNUMBERS();
|
||||
void handleDecimalSeparator(string _decsep, string _value);
|
||||
void handleMaxRateValue(string _decsep, string _value);
|
||||
void handleDecimalExtendedResolution(string _decsep, string _value);
|
||||
void handleMaxRateType(string _decsep, string _value);
|
||||
void handleAnalogDigitalTransitionStart(string _decsep, string _value);
|
||||
std::string GetStringReadouts(general);
|
||||
|
||||
void WriteDataLog(int _index);
|
||||
|
||||
|
||||
|
||||
@@ -49,6 +52,7 @@ public:
|
||||
bool PreValueUse;
|
||||
|
||||
ClassFlowPostProcessing(std::vector<ClassFlow*>* lfc, ClassFlowCNNGeneral *_analog, ClassFlowCNNGeneral *_digit);
|
||||
virtual ~ClassFlowPostProcessing(){};
|
||||
bool ReadParameter(FILE* pfile, string& aktparamgraph);
|
||||
bool doFlow(string time);
|
||||
string getReadout(int _number);
|
||||
@@ -61,6 +65,7 @@ public:
|
||||
void SetPreValue(double zw, string _numbers, bool _extern = false);
|
||||
|
||||
std::string GetJSON(std::string _id = "", std::string _mac = "", std::string _lineend = "\n");
|
||||
std::string getNumbersName();
|
||||
|
||||
void UpdateNachkommaDecimalShift();
|
||||
|
||||
|
||||
@@ -50,7 +50,7 @@ bool ClassFlowWriteList::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = this->ZerlegeZeile(aktparamgraph);
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
/*
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
{
|
||||
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES tflite-lib jomjol_logfile)
|
||||
REQUIRES tflite-lib jomjol_logfile fatfs sdmmc)
|
||||
|
||||
|
||||
|
||||
@@ -7,6 +7,11 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -20,13 +25,19 @@ extern "C" {
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
//#include "ClassLogFile.h"
|
||||
|
||||
#include "esp_vfs_fat.h"
|
||||
|
||||
static const char* TAG = "HELPER";
|
||||
|
||||
//#define ISWINDOWS_TRUE
|
||||
#define PATH_MAX_STRING_SIZE 256
|
||||
|
||||
using namespace std;
|
||||
|
||||
sdmmc_cid_t SDCardCid;
|
||||
sdmmc_csd_t SDCardCsd;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
string getESPHeapInfo(){
|
||||
string espInfoResultStr = "";
|
||||
@@ -73,8 +84,78 @@ size_t getInternalESPHeapSize() {
|
||||
return aFreeInternalHeapSize;
|
||||
}
|
||||
|
||||
string getSDCardPartitionSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, tot_sect;
|
||||
|
||||
/* Get volume information and free clusters of drive 0 */
|
||||
f_getfree("0:", (DWORD *)&fre_clust, &fs);
|
||||
tot_sect = ((fs->n_fatent - 2) * fs->csize) /1024 /(1024/SDCardCsd.sector_size); //corrected by SD Card sector size (usually 512 bytes) and convert to MB
|
||||
|
||||
//ESP_LOGD(TAG, "%d MB total drive space (Sector size [bytes]: %d)", (int)tot_sect, (int)fs->ssize);
|
||||
|
||||
return std::to_string(tot_sect);
|
||||
}
|
||||
|
||||
string getSDCardFreePartitionSpace(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, fre_sect;
|
||||
|
||||
/* Get volume information and free clusters of drive 0 */
|
||||
f_getfree("0:", (DWORD *)&fre_clust, &fs);
|
||||
fre_sect = (fre_clust * fs->csize) / 1024 /(1024/SDCardCsd.sector_size); //corrected by SD Card sector size (usually 512 bytes) and convert to MB
|
||||
|
||||
//ESP_LOGD(TAG, "%d MB free drive space (Sector size [bytes]: %d)", (int)fre_sect, (int)fs->ssize);
|
||||
|
||||
return std::to_string(fre_sect);
|
||||
}
|
||||
|
||||
string getSDCardPartitionAllocationSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, allocation_size;
|
||||
|
||||
/* Get volume information and free clusters of drive 0 */
|
||||
f_getfree("0:", (DWORD *)&fre_clust, &fs);
|
||||
allocation_size = fs->ssize;
|
||||
|
||||
//ESP_LOGD(TAG, "SD Card Partition Allocation Size: %d bytes", allocation_size);
|
||||
|
||||
return std::to_string(allocation_size);
|
||||
}
|
||||
|
||||
|
||||
void SaveSDCardInfo(sdmmc_card_t* card) {
|
||||
SDCardCid = card->cid;
|
||||
SDCardCsd = card->csd;
|
||||
}
|
||||
|
||||
string getSDCardManufacturer(){
|
||||
string SDCardManufacturer = SDCardParseManufacturerIDs(SDCardCid.mfg_id);
|
||||
//ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str());
|
||||
|
||||
return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")");
|
||||
}
|
||||
|
||||
string getSDCardName(){
|
||||
char *SDCardName = SDCardCid.name;
|
||||
//ESP_LOGD(TAG, "SD Card Name: %s", SDCardName);
|
||||
|
||||
return std::string(SDCardName);
|
||||
}
|
||||
|
||||
string getSDCardCapacity(){
|
||||
int SDCardCapacity = SDCardCsd.capacity / (1024/SDCardCsd.sector_size) / 1024; // total sectors * sector size --> Byte to MB (1024*1024)
|
||||
//ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str());
|
||||
|
||||
return std::to_string(SDCardCapacity);
|
||||
}
|
||||
|
||||
string getSDCardSectorSize(){
|
||||
int SDCardSectorSize = SDCardCsd.sector_size;
|
||||
//ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str());
|
||||
|
||||
return std::to_string(SDCardSectorSize);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -86,34 +167,20 @@ void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
|
||||
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec)
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec, bool silent)
|
||||
{
|
||||
FILE *pfile;
|
||||
|
||||
printf("open file %s in mode %s\n", nm, _mode);
|
||||
ESP_LOGD(TAG, "open file %s in mode %s", nm, _mode);
|
||||
|
||||
if ((pfile = fopen(nm, _mode)) != NULL) {
|
||||
printf("File %s successfully opened\n", nm);
|
||||
if (!silent) ESP_LOGE(TAG, "File %s successfully opened", nm);
|
||||
}
|
||||
else {
|
||||
printf("Error: file %s does not exist!\n", nm);
|
||||
if (!silent) ESP_LOGE(TAG, "Error: file %s does not exist!", nm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
if (pfile == NULL)
|
||||
{
|
||||
TickType_t xDelay;
|
||||
xDelay = _waitsec * 1000 / portTICK_PERIOD_MS;
|
||||
std::string zw = "File is locked: " + std::string(nm) + " - wait for " + std::to_string(_waitsec) + " seconds";
|
||||
printf(zw.c_str());
|
||||
printf("\n");
|
||||
LogFile.WriteToFile(zw);
|
||||
vTaskDelay( xDelay );
|
||||
pfile = fopen(nm, _mode);
|
||||
}
|
||||
*/
|
||||
|
||||
return pfile;
|
||||
}
|
||||
|
||||
@@ -129,6 +196,12 @@ std::string FormatFileName(std::string input)
|
||||
}
|
||||
|
||||
|
||||
std::size_t file_size(const std::string& file_name) {
|
||||
std::ifstream file(file_name.c_str(),std::ios::in | std::ios::binary);
|
||||
if (!file) return 0;
|
||||
file.seekg (0, std::ios::end);
|
||||
return static_cast<std::size_t>(file.tellg());
|
||||
}
|
||||
|
||||
|
||||
void FindReplace(std::string& line, std::string& oldString, std::string& newString) {
|
||||
@@ -154,6 +227,16 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
|
||||
}
|
||||
}
|
||||
|
||||
bool MakeDir(std::string _what)
|
||||
{
|
||||
int mk_ret = mkdir(_what.c_str(), 0775);
|
||||
if (mk_ret)
|
||||
{
|
||||
ESP_LOGD(TAG, "error with mkdir %s ret %d", _what.c_str(), mk_ret);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -219,55 +302,57 @@ size_t findDelimiterPos(string input, string delimiter)
|
||||
}
|
||||
|
||||
|
||||
void RenameFile(string from, string to)
|
||||
bool RenameFile(string from, string to)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(from.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
printf("DeleteFile: File %s existiert nicht!\n", from.c_str());
|
||||
return;
|
||||
ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
|
||||
return false;
|
||||
}
|
||||
fclose(fpSourceFile);
|
||||
|
||||
rename(from.c_str(), to.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void DeleteFile(string fn)
|
||||
bool DeleteFile(string fn)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(fn.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
printf("DeleteFile: File %s existiert nicht!\n", fn.c_str());
|
||||
return;
|
||||
ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", fn.c_str());
|
||||
return false;
|
||||
}
|
||||
fclose(fpSourceFile);
|
||||
|
||||
unlink(fn.c_str());
|
||||
unlink(fn.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CopyFile(string input, string output)
|
||||
bool CopyFile(string input, string output)
|
||||
{
|
||||
input = FormatFileName(input);
|
||||
output = FormatFileName(output);
|
||||
|
||||
if (toUpper(input).compare("/SDCARD/WLAN.INI") == 0)
|
||||
{
|
||||
printf("wlan.ini kann nicht kopiert werden!\n");
|
||||
return;
|
||||
ESP_LOGD(TAG, "wlan.ini kann nicht kopiert werden!");
|
||||
return false;
|
||||
}
|
||||
|
||||
char cTemp;
|
||||
FILE* fpSourceFile = OpenFileAndWait(input.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
printf("File %s existiert nicht!\n", input.c_str());
|
||||
return;
|
||||
ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* fpTargetFile = OpenFileAndWait(output.c_str(), "wb");
|
||||
@@ -284,7 +369,8 @@ void CopyFile(string input, string output)
|
||||
// Close The Files
|
||||
fclose(fpSourceFile);
|
||||
fclose(fpTargetFile);
|
||||
printf("File copied: %s to %s", input.c_str(), output.c_str());
|
||||
ESP_LOGD(TAG, "File copied: %s to %s", input.c_str(), output.c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
string getFileFullFileName(string filename)
|
||||
@@ -294,7 +380,7 @@ string getFileFullFileName(string filename)
|
||||
if (lastpos == string::npos)
|
||||
return "";
|
||||
|
||||
// printf("Last position: %d\n", lastpos);
|
||||
// ESP_LOGD(TAG, "Last position: %d", lastpos);
|
||||
|
||||
string zw = filename.substr(lastpos + 1, filename.size() - lastpos);
|
||||
|
||||
@@ -311,7 +397,7 @@ string getDirectory(string filename)
|
||||
if (lastpos == string::npos)
|
||||
return "";
|
||||
|
||||
// printf("Directory: %d\n", lastpos);
|
||||
// ESP_LOGD(TAG, "Directory: %d", lastpos);
|
||||
|
||||
string zw = filename.substr(0, lastpos - 1);
|
||||
return zw;
|
||||
@@ -319,7 +405,7 @@ string getDirectory(string filename)
|
||||
|
||||
string getFileType(string filename)
|
||||
{
|
||||
size_t lastpos = filename.find(".", 0);
|
||||
size_t lastpos = filename.rfind(".", filename.length());
|
||||
size_t neu_pos;
|
||||
while ((neu_pos = filename.find(".", lastpos + 1)) > -1)
|
||||
{
|
||||
@@ -422,11 +508,11 @@ time_t addDays(time_t startTime, int days) {
|
||||
}
|
||||
|
||||
int removeFolder(const char* folderPath, const char* logTag) {
|
||||
ESP_LOGI(logTag, "Delete folder %s", folderPath);
|
||||
//ESP_LOGD(logTag, "Delete content in path %s", folderPath);
|
||||
|
||||
DIR *dir = opendir(folderPath);
|
||||
if (!dir) {
|
||||
ESP_LOGI(logTag, "Failed to stat dir : %s", folderPath);
|
||||
ESP_LOGE(logTag, "Failed to stat dir : %s", folderPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -435,6 +521,7 @@ int removeFolder(const char* folderPath, const char* logTag) {
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
std::string path = string(folderPath) + "/" + entry->d_name;
|
||||
if (entry->d_type == DT_REG) {
|
||||
//ESP_LOGD(logTag, "Delete file %s", path.c_str());
|
||||
if (unlink(path.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
@@ -447,15 +534,14 @@ int removeFolder(const char* folderPath, const char* logTag) {
|
||||
|
||||
closedir(dir);
|
||||
if (rmdir(folderPath) != 0) {
|
||||
ESP_LOGE(logTag, "can't delete file : %s", folderPath);
|
||||
ESP_LOGE(logTag, "can't delete folder : %s", folderPath);
|
||||
}
|
||||
ESP_LOGI(logTag, "%d older log files in folder %s deleted.", deleted, folderPath);
|
||||
ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
|
||||
|
||||
return deleted;
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter = "")
|
||||
{
|
||||
std::vector<string> Output;
|
||||
@@ -464,19 +550,244 @@ std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter
|
||||
delimiter = _delimiter;
|
||||
}
|
||||
|
||||
input = trim(input, delimiter);
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
while (pos != std::string::npos) {
|
||||
token = input.substr(0, pos);
|
||||
token = trim(token, delimiter);
|
||||
Output.push_back(token);
|
||||
input.erase(0, pos + 1);
|
||||
input = trim(input, delimiter);
|
||||
pos = findDelimiterPos(input, delimiter);
|
||||
}
|
||||
Output.push_back(input);
|
||||
|
||||
return Output;
|
||||
return ZerlegeZeile(input, delimiter);
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
|
||||
{
|
||||
std::vector<string> Output;
|
||||
|
||||
input = trim(input, delimiter);
|
||||
|
||||
/* The input can have multiple formats:
|
||||
* - key = value
|
||||
* - key = value1 value2 value3 ...
|
||||
* - key value1 value2 value3 ...
|
||||
*
|
||||
* Examples:
|
||||
* - ImageSize = VGA
|
||||
* - IO0 = input disabled 10 false false
|
||||
* - main.dig1 28 144 55 100 false
|
||||
*
|
||||
* This causes issues eg. if a password key has a whitespace or equal sign in its value.
|
||||
* As a workaround and to not break any legacy usage, we enforce to only use the
|
||||
* equal sign, if the key is "password"
|
||||
*/
|
||||
if (input.find("password") != string::npos) { // Line contains a password, use the equal sign as the only delimiter and only split on first occurrence
|
||||
size_t pos = input.find("=");
|
||||
Output.push_back(trim(input.substr(0, pos), ""));
|
||||
Output.push_back(trim(input.substr(pos +1, string::npos), ""));
|
||||
}
|
||||
else { // Legacy Mode
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
while (pos != std::string::npos) {
|
||||
token = input.substr(0, pos);
|
||||
token = trim(token, delimiter);
|
||||
Output.push_back(token);
|
||||
input.erase(0, pos + 1);
|
||||
input = trim(input, delimiter);
|
||||
pos = findDelimiterPos(input, delimiter);
|
||||
}
|
||||
Output.push_back(input);
|
||||
}
|
||||
|
||||
return Output;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
|
||||
/* SD Card Manufacturer Database */
|
||||
struct SDCard_Manufacturer_database {
|
||||
string type;
|
||||
int id;
|
||||
string manufacturer;
|
||||
};
|
||||
|
||||
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
|
||||
/* SD Card Manufacturer Database */
|
||||
struct SDCard_Manufacturer_database database[] = {
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x01,
|
||||
.manufacturer = "Panasonic",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x02,
|
||||
.manufacturer = "Toshiba/Kingston/Viking",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x03,
|
||||
.manufacturer = "SanDisk",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x08,
|
||||
.manufacturer = "Silicon Power",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x18,
|
||||
.manufacturer = "Infineon",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x1b,
|
||||
.manufacturer = "Transcend/Samsung",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x1c,
|
||||
.manufacturer = "Transcend",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x1d,
|
||||
.manufacturer = "Corsair/AData",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x1e,
|
||||
.manufacturer = "Transcend",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x1f,
|
||||
.manufacturer = "Kingston",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x27,
|
||||
.manufacturer = "Delkin/Phison",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x28,
|
||||
.manufacturer = "Lexar",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x30,
|
||||
.manufacturer = "SanDisk",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x31,
|
||||
.manufacturer = "Silicon Power",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x33,
|
||||
.manufacturer = "STMicroelectronics",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x41,
|
||||
.manufacturer = "Kingston",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x6f,
|
||||
.manufacturer = "STMicroelectronics",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x74,
|
||||
.manufacturer = "Transcend",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x76,
|
||||
.manufacturer = "Patriot",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x82,
|
||||
.manufacturer = "Gobe/Sony",
|
||||
},
|
||||
{
|
||||
.type = "sd",
|
||||
.id = 0x89,
|
||||
.manufacturer = "Unknown",
|
||||
}
|
||||
};
|
||||
|
||||
/* Parse SD Card Manufacturer Database */
|
||||
string SDCardParseManufacturerIDs(int id)
|
||||
{
|
||||
unsigned int id_cnt = sizeof(database) / sizeof(struct SDCard_Manufacturer_database);
|
||||
string ret_val = "";
|
||||
|
||||
for (int i = 0; i < id_cnt; i++) {
|
||||
if (database[i].id == id) {
|
||||
return database[i].manufacturer;
|
||||
}
|
||||
else {
|
||||
ret_val = "ID unknown (not in DB)";
|
||||
}
|
||||
}
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
|
||||
string RundeOutput(double _in, int _anzNachkomma)
|
||||
{
|
||||
std::stringstream stream;
|
||||
int _zw = _in;
|
||||
// ESP_LOGD(TAG, "AnzNachkomma: %d", _anzNachkomma);
|
||||
|
||||
if (_anzNachkomma < 0) {
|
||||
_anzNachkomma = 0;
|
||||
}
|
||||
|
||||
if (_anzNachkomma > 0)
|
||||
{
|
||||
stream << std::fixed << std::setprecision(_anzNachkomma) << _in;
|
||||
return stream.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
stream << _zw;
|
||||
}
|
||||
|
||||
|
||||
return stream.str();
|
||||
}
|
||||
|
||||
|
||||
string getMac(void) {
|
||||
uint8_t macInt[6];
|
||||
char macFormated[6*2 + 5 + 1]; // AA:BB:CC:DD:EE:FF
|
||||
|
||||
esp_read_mac(macInt, ESP_MAC_WIFI_STA);
|
||||
sprintf(macFormated, "%02X:%02X:%02X:%02X:%02X:%02X", macInt[0], macInt[1], macInt[2], macInt[3], macInt[4], macInt[5]);
|
||||
|
||||
return macFormated;
|
||||
}
|
||||
|
||||
string getResetReason(void) {
|
||||
std::string reasonText;
|
||||
|
||||
switch(esp_reset_reason()) {
|
||||
case ESP_RST_POWERON: reasonText = "Power-on event"; break; //!< Reset due to power-on event
|
||||
case ESP_RST_EXT: reasonText = "External pin"; break; //!< Reset by external pin (not applicable for ESP32)
|
||||
case ESP_RST_SW: reasonText = "Via esp_restart"; break; //!< Software reset via esp_restart
|
||||
case ESP_RST_PANIC: reasonText = "Exception/panic"; break; //!< Software reset due to exception/panic
|
||||
case ESP_RST_INT_WDT: reasonText = "Interrupt watchdog"; break; //!< Reset (software or hardware) due to interrupt watchdog
|
||||
case ESP_RST_TASK_WDT: reasonText = "Task watchdog"; break; //!< Reset due to task watchdog
|
||||
case ESP_RST_WDT: reasonText = "Other watchdogs"; break; //!< Reset due to other watchdogs
|
||||
case ESP_RST_DEEPSLEEP: reasonText = "Exiting deep sleep mode"; break; //!< Reset after exiting deep sleep mode
|
||||
case ESP_RST_BROWNOUT: reasonText = "Brownout"; break; //!< Brownout reset (software or hardware)
|
||||
case ESP_RST_SDIO: reasonText = "SDIO"; break; //!< Reset over SDIO
|
||||
|
||||
case ESP_RST_UNKNOWN: //!< Reset reason can not be determined
|
||||
default:
|
||||
reasonText = "Unknown";
|
||||
}
|
||||
return reasonText;
|
||||
}
|
||||
|
||||
@@ -2,19 +2,24 @@
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include "sdmmc_cmd.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
std::string FormatFileName(std::string input);
|
||||
std::size_t file_size(const std::string& file_name);
|
||||
void FindReplace(std::string& line, std::string& oldString, std::string& newString);
|
||||
|
||||
void CopyFile(string input, string output);
|
||||
void DeleteFile(string fn);
|
||||
void RenameFile(string from, string to);
|
||||
bool CopyFile(string input, string output);
|
||||
bool DeleteFile(string fn);
|
||||
bool RenameFile(string from, string to);
|
||||
bool MakeDir(std::string _what);
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1);
|
||||
string RundeOutput(double _in, int _anzNachkomma);
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1, bool silent = true);
|
||||
|
||||
size_t findDelimiterPos(string input, string delimiter);
|
||||
//string trim(string istring);
|
||||
@@ -38,6 +43,7 @@ time_t addDays(time_t startTime, int days);
|
||||
void memCopyGen(uint8_t* _source, uint8_t* _target, int _size);
|
||||
|
||||
std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter);
|
||||
std::vector<std::string> ZerlegeZeile(std::string input, std::string delimiter = " =, \t");
|
||||
|
||||
///////////////////////////
|
||||
size_t getInternalESPHeapSize();
|
||||
@@ -45,3 +51,16 @@ size_t getESPHeapSize();
|
||||
string getESPHeapInfo();
|
||||
|
||||
/////////////////////////////
|
||||
string getSDCardPartitionSize();
|
||||
string getSDCardFreePartitionSpace();
|
||||
string getSDCardPartitionAllocationSize();
|
||||
|
||||
void SaveSDCardInfo(sdmmc_card_t* card);
|
||||
string SDCardParseManufacturerIDs(int);
|
||||
string getSDCardManufacturer();
|
||||
string getSDCardName();
|
||||
string getSDCardCapacity();
|
||||
string getSDCardSectorSize();
|
||||
|
||||
string getMac(void);
|
||||
string getResetReason(void);
|
||||
@@ -5,10 +5,14 @@
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <esp_log.h>
|
||||
|
||||
static const char* TAG = "c_align_and_cut_image";
|
||||
|
||||
//#define GET_MEMORY malloc
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp)
|
||||
@@ -43,14 +47,14 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
|
||||
r0_x = _temp1->target_x;
|
||||
r0_y = _temp1->target_y;
|
||||
printf("Vor ft->FindTemplate(_temp1); %s\n", _temp1->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str());
|
||||
isSimilar1 = ft->FindTemplate(_temp1);
|
||||
_temp1->width = ft->tpl_width;
|
||||
_temp1->height = ft->tpl_height;
|
||||
|
||||
r1_x = _temp2->target_x;
|
||||
r1_y = _temp2->target_y;
|
||||
printf("Vor ft->FindTemplate(_temp2); %s\n", _temp2->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str());
|
||||
isSimilar2 = ft->FindTemplate(_temp2);
|
||||
_temp2->width = ft->tpl_width;
|
||||
_temp2->height = ft->tpl_height;
|
||||
@@ -86,7 +90,7 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
CRotateImage rt(this, ImageTMP);
|
||||
rt.Translate(dx, dy);
|
||||
rt.Rotate(d_winkel, _temp1->target_x, _temp1->target_y);
|
||||
printf("Alignment: dx %d - dy %d - rot %f\n", dx, dy, d_winkel);
|
||||
ESP_LOGD(TAG, "Alignment: dx %d - dy %d - rot %f", dx, dy, d_winkel);
|
||||
|
||||
return (isSimilar1 && isSimilar2);
|
||||
}
|
||||
@@ -147,7 +151,7 @@ void CAlignAndCutImage::CutAndSave(int x1, int y1, int dx, int dy, CImageBasis *
|
||||
|
||||
if ((_target->height != dy) || (_target->width != dx) || (_target->channels != channels))
|
||||
{
|
||||
printf("CAlignAndCutImage::CutAndSave - Image size does not match !!");
|
||||
ESP_LOGD(TAG, "CAlignAndCutImage::CutAndSave - Image size does not match!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,32 @@
|
||||
#include "CFindTemplate.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
static const char* TAG = "C FIND TEMPL";
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
{
|
||||
uint8_t* rgb_template = stbi_load(_ref->image_file.c_str(), &tpl_width, &tpl_height, &tpl_bpp, channels);
|
||||
uint8_t* rgb_template;
|
||||
|
||||
// printf("FindTemplate 01\n");
|
||||
if (file_size(_ref->image_file.c_str()) == 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _ref->image_file + " is empty!");
|
||||
return false;
|
||||
}
|
||||
|
||||
rgb_template = stbi_load(_ref->image_file.c_str(), &tpl_width, &tpl_height, &tpl_bpp, channels);
|
||||
|
||||
if (rgb_template == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to load " + _ref->image_file + "! Is it corrupted?");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ESP_LOGD(TAG, "FindTemplate 01");
|
||||
|
||||
int ow, ow_start, ow_stop;
|
||||
int oh, oh_start, oh_stop;
|
||||
@@ -45,7 +62,7 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
int min, max;
|
||||
bool isSimilar = false;
|
||||
|
||||
// printf("FindTemplate 02\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 02");
|
||||
|
||||
if ((_ref->alignment_algo == 2) && (_ref->fastalg_x > -1) && (_ref->fastalg_y > -1)) // für Testzwecke immer Berechnen
|
||||
{
|
||||
@@ -57,20 +74,23 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
#endif
|
||||
}
|
||||
|
||||
// printf("FindTemplate 03\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 03");
|
||||
|
||||
|
||||
if (isSimilar)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteToFile("Use FastAlignment sucessfull");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Use FastAlignment sucessfull");
|
||||
#endif
|
||||
_ref->found_x = _ref->fastalg_x;
|
||||
_ref->found_y = _ref->fastalg_y;
|
||||
|
||||
stbi_image_free(rgb_template);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// printf("FindTemplate 04\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 04");
|
||||
|
||||
|
||||
double aktSAD;
|
||||
@@ -78,7 +98,7 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
// printf("FindTemplate 05\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 05");
|
||||
int xouter, youter, tpl_x, tpl_y, _ch;
|
||||
int _anzchannels = channels;
|
||||
if (_ref->alignment_algo == 0) // 0 = "Default" (nur R-Kanal)
|
||||
@@ -106,14 +126,14 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
}
|
||||
}
|
||||
|
||||
// printf("FindTemplate 06\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 06");
|
||||
|
||||
|
||||
if (_ref->alignment_algo == 2)
|
||||
CalculateSimularities(rgb_template, _ref->found_x, _ref->found_y, ow, oh, min, avg, max, SAD, _ref->fastalg_SAD, _ref->fastalg_SAD_criteria);
|
||||
|
||||
|
||||
// printf("FindTemplate 07\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 07");
|
||||
|
||||
_ref->fastalg_x = _ref->found_x;
|
||||
_ref->fastalg_y = _ref->found_y;
|
||||
@@ -132,7 +152,7 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
RGBImageRelease();
|
||||
stbi_image_free(rgb_template);
|
||||
|
||||
// printf("FindTemplate 08\n");
|
||||
// ESP_LOGD(TAG, "FindTemplate 08");
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -173,7 +193,7 @@ bool CFindTemplate::CalculateSimularities(uint8_t* _rgb_tmpl, int _startx, int _
|
||||
|
||||
float _SADdif = abs(SAD - _SADold);
|
||||
|
||||
printf("Anzahl %ld, avgDifSum %fd, avg %f, SAD_neu: %fd, _SAD_old: %f, _SAD_crit:%f\n", anz, avgDifSum, avg, SAD, _SADold, _SADdif);
|
||||
ESP_LOGD(TAG, "Anzahl %ld, avgDifSum %fd, avg %f, SAD_neu: %fd, _SAD_old: %f, _SAD_crit:%f", anz, avgDifSum, avg, SAD, _SADold, _SADdif);
|
||||
|
||||
if (_SADdif <= _SADcrit)
|
||||
return true;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *TAG = "CImageBasis";
|
||||
static const char *TAG = "C IMG BASIS";
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
@@ -29,7 +29,7 @@ uint8_t * CImageBasis::RGBImageLock(int _waitmaxsec)
|
||||
if (islocked)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Image is locked: sleep for : %ds\n", _waitmaxsec);
|
||||
ESP_LOGD(TAG, "Image is locked: sleep for: %ds", _waitmaxsec);
|
||||
#endif
|
||||
TickType_t xDelay;
|
||||
xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
@@ -61,7 +61,7 @@ uint8_t * CImageBasis::RGBImageGet()
|
||||
|
||||
void writejpghelp(void *context, void *data, int size)
|
||||
{
|
||||
// printf("Size all: %d, size %d\n", ((ImageData*)context)->size, size);
|
||||
// ESP_LOGD(TAG, "Size all: %d, size %d", ((ImageData*)context)->size, size);
|
||||
ImageData* _zw = (ImageData*) context;
|
||||
uint8_t *voidstart = _zw->data;
|
||||
uint8_t *datastart = (uint8_t*) data;
|
||||
@@ -146,7 +146,7 @@ bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
|
||||
int gr = height * width * channels;
|
||||
if (gr != _size) // Größe passt nicht
|
||||
{
|
||||
printf("Cannot copy image from memory - sizes do not match: should be %d, but is %d\n", _size, gr);
|
||||
ESP_LOGD(TAG, "Cannot copy image from memory - sizes do not match: should be %d, but is %d", _size, gr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -359,14 +359,10 @@ void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
|
||||
stbi_image_free(rgb_image);
|
||||
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
|
||||
bpp = channels;
|
||||
printf("Image loaded from memory: %d, %d, %d\n", width, height, channels);
|
||||
ESP_LOGD(TAG, "Image loaded from memory: %d, %d, %d", width, height, channels);
|
||||
if ((width * height * channels) == 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Image with size 0 loaded --> reboot to be done! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Image with size 0 loaded --> reboot to be done! "
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Image with size 0 loaded --> reboot to be done! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
|
||||
doReboot();
|
||||
@@ -392,7 +388,7 @@ CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
int anz = 1;
|
||||
while (!rgb_image && (anz < _anzrepeat))
|
||||
{
|
||||
printf("Create Image from Copy - Memory is full - try again: %d.\n", anz);
|
||||
ESP_LOGD(TAG, "Create Image from Copy - Memory is full - try again: %d", anz);
|
||||
rgb_image = (unsigned char*) malloc(memsize);
|
||||
anz++;
|
||||
}
|
||||
@@ -400,8 +396,8 @@ CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
|
||||
if (!rgb_image)
|
||||
{
|
||||
printf(getESPHeapInfo().c_str());
|
||||
printf("\nNo more free memory!! Needed: %d %d %d %d\n", width, height, channels, memsize);
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
@@ -424,8 +420,8 @@ CImageBasis::CImageBasis(int _width, int _height, int _channels)
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
if (!rgb_image)
|
||||
{
|
||||
printf(getESPHeapInfo().c_str());
|
||||
printf("\nNo more free memory!! Needed: %d %d %d %d\n", width, height, channels, memsize);
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -438,21 +434,33 @@ CImageBasis::CImageBasis(std::string _image)
|
||||
externalImage = false;
|
||||
filename = _image;
|
||||
long zwld = esp_get_free_heap_size();
|
||||
printf("freeheapsize before: %ld\n", zwld);
|
||||
ESP_LOGD(TAG, "freeheapsize before: %ld", zwld);
|
||||
|
||||
if (file_size(_image.c_str()) == 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _image + " is empty!");
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageLock();
|
||||
rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
|
||||
|
||||
if (rgb_image == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to load " + _image + "! Is it corrupted?");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
zwld = esp_get_free_heap_size();
|
||||
printf("freeheapsize after : %ld\n", zwld);
|
||||
ESP_LOGD(TAG, "freeheapsize after : %ld", zwld);
|
||||
|
||||
std::string zw = "Image Load failed:" + _image + "\n";
|
||||
std::string zw = "Image Load failed:" + _image;
|
||||
if (rgb_image == NULL)
|
||||
printf(zw.c_str());
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
zw = "CImageBasis after load " + _image + "\n";
|
||||
printf(zw.c_str());
|
||||
printf("w %d, h %d, b %d, c %d\n", width, height, bpp, channels);
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels);
|
||||
|
||||
}
|
||||
|
||||
@@ -543,7 +551,7 @@ void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
|
||||
{
|
||||
if ((_target->height != _new_dy) || (_target->width != _new_dx) || (_target->channels != channels))
|
||||
{
|
||||
printf("CImageBasis::Resize - Target image size does not fit !!");
|
||||
ESP_LOGD(TAG, "CImageBasis::Resize - Target image size does not fit!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -280,13 +280,13 @@ void CRotateImage::RotateAntiAliasing(float _angle, int _centerx, int _centery)
|
||||
|
||||
void CRotateImage::Rotate(float _angle)
|
||||
{
|
||||
// printf("width %d, height %d\n", width, height);
|
||||
// ESP_LOGD(TAG, "width %d, height %d", width, height);
|
||||
Rotate(_angle, width / 2, height / 2);
|
||||
}
|
||||
|
||||
void CRotateImage::RotateAntiAliasing(float _angle)
|
||||
{
|
||||
// printf("width %d, height %d\n", width, height);
|
||||
// ESP_LOGD(TAG, "width %d, height %d", width, height);
|
||||
RotateAntiAliasing(_angle, width / 2, height / 2);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||
|
||||
static const char *TAG_INTERFACEINFLUXDB = "interface_influxdb";
|
||||
static const char *TAG = "INFLUXDB";
|
||||
|
||||
std::string _influxDBURI;
|
||||
std::string _influxDBDatabase;
|
||||
@@ -21,25 +21,25 @@ static esp_err_t http_event_handler(esp_http_client_event_t *evt)
|
||||
switch(evt->event_id)
|
||||
{
|
||||
case HTTP_EVENT_ERROR:
|
||||
ESP_LOGE(TAG_INTERFACEINFLUXDB, "HTTP Client Error encountered");
|
||||
ESP_LOGE(TAG, "HTTP Client Error encountered");
|
||||
break;
|
||||
case HTTP_EVENT_ON_CONNECTED:
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "HTTP Client Connected");
|
||||
ESP_LOGI(TAG, "HTTP Client Connected");
|
||||
break;
|
||||
case HTTP_EVENT_HEADERS_SENT:
|
||||
ESP_LOGV(TAG_INTERFACEINFLUXDB, "HTTP Client sent all request headers");
|
||||
ESP_LOGV(TAG, "HTTP Client sent all request headers");
|
||||
break;
|
||||
case HTTP_EVENT_ON_HEADER:
|
||||
ESP_LOGV(TAG_INTERFACEINFLUXDB, "Header: key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
ESP_LOGV(TAG, "Header: key=%s, value=%s", evt->header_key, evt->header_value);
|
||||
break;
|
||||
case HTTP_EVENT_ON_DATA:
|
||||
ESP_LOGV(TAG_INTERFACEINFLUXDB, "HTTP Client data recevied: len=%d", evt->data_len);
|
||||
ESP_LOGV(TAG, "HTTP Client data recevied: len=%d", evt->data_len);
|
||||
break;
|
||||
case HTTP_EVENT_ON_FINISH:
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "HTTP Client finished");
|
||||
ESP_LOGI(TAG, "HTTP Client finished");
|
||||
break;
|
||||
case HTTP_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "HTTP Client Disconnected");
|
||||
ESP_LOGI(TAG, "HTTP Client Disconnected");
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
@@ -69,31 +69,31 @@ void InfluxDBPublish(std::string _key, std::string _content, std::string _timest
|
||||
|
||||
std::string payload = _influxDBMeasurement + " " + _key + "=" + _content + " " + nowTimestamp;
|
||||
payload.shrink_to_fit();
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "sending line to influxdb: %s\n", payload.c_str());
|
||||
ESP_LOGI(TAG, "sending line to influxdb: %s\n", payload.c_str());
|
||||
|
||||
// use the default retention policy of the database
|
||||
std::string apiURI = _influxDBURI + "/api/v2/write?bucket=" + _influxDBDatabase + "/";
|
||||
apiURI.shrink_to_fit();
|
||||
http_config.url = apiURI.c_str();
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "API URI: %s", apiURI.c_str());
|
||||
ESP_LOGI(TAG, "API URI: %s", apiURI.c_str());
|
||||
|
||||
esp_http_client_handle_t http_client = esp_http_client_init(&http_config);
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "client is initialized%s\n", "");
|
||||
ESP_LOGI(TAG, "client is initialized%s\n", "");
|
||||
|
||||
esp_http_client_set_header(http_client, "Content-Type", "text/plain");
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "header is set%s\n", "");
|
||||
ESP_LOGI(TAG, "header is set%s\n", "");
|
||||
|
||||
ESP_ERROR_CHECK(esp_http_client_set_post_field(http_client, payload.c_str(), payload.length()));
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "post payload is set%s\n", "");
|
||||
ESP_LOGI(TAG, "post payload is set%s\n", "");
|
||||
|
||||
esp_err_t err = ESP_ERROR_CHECK_WITHOUT_ABORT(esp_http_client_perform(http_client));
|
||||
|
||||
if( err == ESP_OK ) {
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "HTTP request was performed%s\n", "");
|
||||
ESP_LOGI(TAG, "HTTP request was performed%s\n", "");
|
||||
int status_code = esp_http_client_get_status_code(http_client);
|
||||
ESP_LOGI(TAG_INTERFACEINFLUXDB, "HTTP status code %d\n", status_code);
|
||||
ESP_LOGI(TAG, "HTTP status code %d\n", status_code);
|
||||
} else {
|
||||
ESP_LOGW(TAG_INTERFACEINFLUXDB, "HTTP request failed%s\n", "");
|
||||
ESP_LOGW(TAG, "HTTP request failed%s\n", "");
|
||||
}
|
||||
esp_http_client_cleanup(http_client);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "time_sntp.h"
|
||||
#include "esp_log.h"
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <algorithm>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -14,17 +16,17 @@ extern "C" {
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
static const char *TAG = "log";
|
||||
static const char *TAG = "LOGFILE";
|
||||
|
||||
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt");
|
||||
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt", "/sdcard/log/data", "data_%Y-%m-%d.csv");
|
||||
|
||||
void ClassLogFile::WriteHeapInfo(std::string _id)
|
||||
{
|
||||
std::string _zw = "\t" + _id;
|
||||
if (loglevel > 0)
|
||||
std::string _zw = _id;
|
||||
if (loglevel >= ESP_LOG_DEBUG) {
|
||||
_zw = _zw + "\t" + getESPHeapInfo();
|
||||
|
||||
WriteToFile(_zw);
|
||||
WriteToFile(ESP_LOG_DEBUG, "HEAP", _zw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,18 +64,66 @@ std::string ClassLogFile::getESPHeapInfo(){
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool _time)
|
||||
void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::string _ReturnRawValue, std::string _ReturnValue, std::string _ReturnPreValue, std::string _ReturnRateValue, std::string _ReturnChangeAbsolute, std::string _ErrorMessageText, std::string _digital, std::string _analog)
|
||||
{
|
||||
ESP_LOGD(TAG, "Start WriteToData");
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[30];
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buffer, 30, datafile.c_str(), timeinfo);
|
||||
std::string logpath = dataroot + "/" + buffer;
|
||||
|
||||
FILE* pFile;
|
||||
std::string zwtime;
|
||||
|
||||
if (!doLogFile){
|
||||
ESP_LOGD(TAG, "Datalogfile: %s", logpath.c_str());
|
||||
pFile = fopen(logpath.c_str(), "a+");
|
||||
|
||||
if (pFile!=NULL) {
|
||||
fputs(_timestamp.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_name.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ReturnRawValue.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ReturnValue.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ReturnPreValue.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ReturnRateValue.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ReturnChangeAbsolute.c_str(), pFile);
|
||||
fputs(",", pFile);
|
||||
fputs(_ErrorMessageText.c_str(), pFile);
|
||||
fputs(_digital.c_str(), pFile);
|
||||
fputs(_analog.c_str(), pFile);
|
||||
fputs("\n", pFile);
|
||||
|
||||
fclose(pFile);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Can't open data file %s", logpath.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time)
|
||||
{
|
||||
FILE* pFile;
|
||||
std::string zwtime;
|
||||
std::string logline = "";
|
||||
|
||||
if (level > loglevel) {// Only write to file if loglevel is below threshold
|
||||
return;
|
||||
}
|
||||
|
||||
// pFile = OpenFileAndWait(_fn.c_str(), "a");
|
||||
pFile = fopen(_fn.c_str(), "a+");
|
||||
// printf("Logfile opened: %s\n", _fn.c_str());
|
||||
// ESP_LOGD(TAG, "Logfile opened: %s", _fn.c_str());
|
||||
|
||||
if (pFile!=NULL) {
|
||||
if (_time)
|
||||
@@ -88,33 +138,99 @@ void ClassLogFile::WriteToDedicatedFile(std::string _fn, std::string info, bool
|
||||
strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
|
||||
zwtime = std::string(buffer);
|
||||
info = zwtime + ": " + info;
|
||||
logline = zwtime;
|
||||
}
|
||||
fputs(info.c_str(), pFile);
|
||||
fputs("\n", pFile);
|
||||
|
||||
std::string loglevelString;
|
||||
switch(level) {
|
||||
case ESP_LOG_ERROR:
|
||||
loglevelString = "ERR";
|
||||
break;
|
||||
case ESP_LOG_WARN:
|
||||
loglevelString = "WRN";
|
||||
break;
|
||||
case ESP_LOG_INFO:
|
||||
loglevelString = "INF";
|
||||
break;
|
||||
case ESP_LOG_DEBUG:
|
||||
loglevelString = "DBG";
|
||||
break;
|
||||
case ESP_LOG_VERBOSE:
|
||||
loglevelString = "VER";
|
||||
break;
|
||||
case ESP_LOG_NONE:
|
||||
default:
|
||||
loglevelString = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
char uptime[20];
|
||||
snprintf(uptime, sizeof(uptime), "%8d", (uint32_t)(esp_timer_get_time()/1000/1000)); // in seconds
|
||||
logline = "[" + std::string(uptime) + "] " + logline + "\t<" + loglevelString + ">\t" + message + "\n";
|
||||
fputs(logline.c_str(), pFile);
|
||||
fclose(pFile);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Can't open log file %s", _fn.c_str());
|
||||
ESP_LOGE(TAG, "Can't open log file %s", _fn.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLogFile::SwitchOnOff(bool _doLogFile){
|
||||
doLogFile = _doLogFile;
|
||||
};
|
||||
void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
|
||||
loglevel = _logLevel;
|
||||
|
||||
void ClassLogFile::SetRetention(unsigned short _retentionInDays){
|
||||
retentionInDays = _retentionInDays;
|
||||
};
|
||||
std::string levelText;
|
||||
|
||||
void ClassLogFile::WriteToFile(std::string info, bool _time)
|
||||
switch(_logLevel) {
|
||||
case ESP_LOG_WARN:
|
||||
levelText = "WARNING";
|
||||
break;
|
||||
|
||||
case ESP_LOG_INFO:
|
||||
levelText = "INFO";
|
||||
break;
|
||||
|
||||
case ESP_LOG_DEBUG:
|
||||
levelText = "DEBUG";
|
||||
break;
|
||||
case ESP_LOG_ERROR:
|
||||
default:
|
||||
levelText = "ERROR";
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Log Level set to %s", levelText.c_str());
|
||||
|
||||
/*
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Test");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Test");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Test");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Test");
|
||||
*/
|
||||
}
|
||||
|
||||
void ClassLogFile::SetLogFileRetention(unsigned short _LogFileRetentionInDays){
|
||||
logFileRetentionInDays = _LogFileRetentionInDays;
|
||||
}
|
||||
|
||||
void ClassLogFile::SetDataLogRetention(unsigned short _DataLogRetentionInDays){
|
||||
dataLogRetentionInDays = _DataLogRetentionInDays;
|
||||
}
|
||||
|
||||
void ClassLogFile::SetDataLogToSD(bool _doDataLogToSD){
|
||||
doDataLogToSD = _doDataLogToSD;
|
||||
}
|
||||
|
||||
bool ClassLogFile::GetDataLogToSD(){
|
||||
return doDataLogToSD;
|
||||
}
|
||||
|
||||
void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::string message, bool _time)
|
||||
{
|
||||
/*
|
||||
struct stat path_stat;
|
||||
if (stat(logroot.c_str(), &path_stat) != 0) {
|
||||
ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str());
|
||||
if (mkdir_r(logroot.c_str(), S_IRWXU) == -1) {
|
||||
ESP_LOGI(TAG, "Can't create log folder");
|
||||
ESP_LOGE(TAG, "Can't create log folder");
|
||||
}
|
||||
}
|
||||
*/
|
||||
@@ -128,10 +244,39 @@ void ClassLogFile::WriteToFile(std::string info, bool _time)
|
||||
strftime(buffer, 30, logfile.c_str(), timeinfo);
|
||||
std::string logpath = logroot + "/" + buffer;
|
||||
|
||||
WriteToDedicatedFile(logpath, info, _time);
|
||||
printf((info + "\n").c_str());
|
||||
std::replace(message.begin(), message.end(), '\n', ' '); // Replace all newline characters
|
||||
|
||||
if (tag != "") {
|
||||
ESP_LOG_LEVEL(level, tag.c_str(), "%s", message.c_str());
|
||||
message = "[" + tag + "] " + message;
|
||||
}
|
||||
else {
|
||||
ESP_LOG_LEVEL(level, "", "%s", message.c_str());
|
||||
}
|
||||
WriteToDedicatedFile(logpath, level, message, _time);
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::string message) {
|
||||
LogFile.WriteToFile(level, tag, message, true);
|
||||
}
|
||||
|
||||
std::string ClassLogFile::GetCurrentFileNameData()
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[60];
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buffer, 60, datafile.c_str(), timeinfo);
|
||||
std::string logpath = dataroot + "/" + buffer;
|
||||
|
||||
return logpath;
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLogFile::GetCurrentFileName()
|
||||
{
|
||||
time_t rawtime;
|
||||
@@ -147,26 +292,30 @@ std::string ClassLogFile::GetCurrentFileName()
|
||||
return logpath;
|
||||
}
|
||||
|
||||
void ClassLogFile::RemoveOld()
|
||||
void ClassLogFile::RemoveOldLogFile()
|
||||
{
|
||||
if (retentionInDays == 0) {
|
||||
if (logFileRetentionInDays == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Remove old log files");
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char cmpfilename[30];
|
||||
|
||||
time(&rawtime);
|
||||
rawtime = addDays(rawtime, -retentionInDays);
|
||||
rawtime = addDays(rawtime, -logFileRetentionInDays + 1);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
//ESP_LOGD(TAG, "logFileRetentionInDays: %d", logFileRetentionInDays);
|
||||
|
||||
|
||||
strftime(cmpfilename, 30, logfile.c_str(), timeinfo);
|
||||
//ESP_LOGE(TAG, "log file name to compare: %s", cmpfilename);
|
||||
//ESP_LOGD(TAG, "log file name to compare: %s", cmpfilename);
|
||||
|
||||
DIR *dir = opendir(logroot.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGI(TAG, "Failed to stat dir : %s", logroot.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", logroot.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,29 +324,96 @@ void ClassLogFile::RemoveOld()
|
||||
int notDeleted = 0;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
//ESP_LOGI(TAG, "list log file : %s %s", entry->d_name, cmpfilename);
|
||||
//ESP_LOGD(TAG, "compare log file : %s to %s", entry->d_name, cmpfilename);
|
||||
if ((strlen(entry->d_name) == strlen(cmpfilename)) && (strcmp(entry->d_name, cmpfilename) < 0)) {
|
||||
ESP_LOGI(TAG, "delete log file : %s", entry->d_name);
|
||||
//ESP_LOGD(TAG, "delete log file : %s", entry->d_name);
|
||||
std::string filepath = logroot + "/" + entry->d_name;
|
||||
if (unlink(filepath.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "can't delete file : %s", entry->d_name);
|
||||
notDeleted ++;
|
||||
}
|
||||
} else {
|
||||
notDeleted ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "%d older log files deleted. %d current log files not deleted.", deleted, notDeleted);
|
||||
ESP_LOGD(TAG, "log files deleted: %d | files not deleted (incl. leer.txt): %d", deleted, notDeleted);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
ClassLogFile::ClassLogFile(std::string _logroot, std::string _logfile)
|
||||
|
||||
void ClassLogFile::RemoveOldDataLog()
|
||||
{
|
||||
if (dataLogRetentionInDays == 0 || !doDataLogToSD) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Remove old data files");
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char cmpfilename[30];
|
||||
|
||||
time(&rawtime);
|
||||
rawtime = addDays(rawtime, -dataLogRetentionInDays + 1);
|
||||
timeinfo = localtime(&rawtime);
|
||||
//ESP_LOGD(TAG, "dataLogRetentionInDays: %d", dataLogRetentionInDays);
|
||||
|
||||
strftime(cmpfilename, 30, datafile.c_str(), timeinfo);
|
||||
//ESP_LOGD(TAG, "data file name to compare: %s", cmpfilename);
|
||||
|
||||
DIR *dir = opendir(dataroot.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", dataroot.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
struct dirent *entry;
|
||||
int deleted = 0;
|
||||
int notDeleted = 0;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
//ESP_LOGD(TAG, "Compare data file : %s to %s", entry->d_name, cmpfilename);
|
||||
if ((strlen(entry->d_name) == strlen(cmpfilename)) && (strcmp(entry->d_name, cmpfilename) < 0)) {
|
||||
//ESP_LOGD(TAG, "delete data file : %s", entry->d_name);
|
||||
std::string filepath = dataroot + "/" + entry->d_name;
|
||||
if (unlink(filepath.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "can't delete file : %s", entry->d_name);
|
||||
notDeleted ++;
|
||||
}
|
||||
} else {
|
||||
notDeleted ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "data files deleted: %d | files not deleted (incl. leer.txt): %d", deleted, notDeleted);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::CreateLogDirectories()
|
||||
{
|
||||
MakeDir("/sdcard/log");
|
||||
MakeDir("/sdcard/log/data");
|
||||
MakeDir("/sdcard/log/analog");
|
||||
MakeDir("/sdcard/log/digit");
|
||||
MakeDir("/sdcard/log/message");
|
||||
MakeDir("/sdcard/log/source");
|
||||
}
|
||||
|
||||
|
||||
ClassLogFile::ClassLogFile(std::string _logroot, std::string _logfile, std::string _logdatapath, std::string _datafile)
|
||||
{
|
||||
logroot = _logroot;
|
||||
logfile = _logfile;
|
||||
doLogFile = true;
|
||||
retentionInDays = 10;
|
||||
loglevel = 0;
|
||||
datafile = _datafile;
|
||||
dataroot = _logdatapath;
|
||||
logFileRetentionInDays = 3;
|
||||
dataLogRetentionInDays = 3;
|
||||
doDataLogToSD = true;
|
||||
loglevel = ESP_LOG_INFO;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
|
||||
#include <string>
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
class ClassLogFile
|
||||
@@ -7,26 +8,40 @@ class ClassLogFile
|
||||
private:
|
||||
std::string logroot;
|
||||
std::string logfile;
|
||||
bool doLogFile;
|
||||
unsigned short retentionInDays;
|
||||
int loglevel;
|
||||
std::string dataroot;
|
||||
std::string datafile;
|
||||
unsigned short logFileRetentionInDays;
|
||||
unsigned short dataLogRetentionInDays;
|
||||
bool doDataLogToSD;
|
||||
esp_log_level_t loglevel;
|
||||
public:
|
||||
ClassLogFile(std::string _logpath, std::string _logfile);
|
||||
ClassLogFile(std::string _logpath, std::string _logfile, std::string _logdatapath, std::string _datafile);
|
||||
|
||||
std::string getESPHeapInfo();
|
||||
|
||||
void setLogLevel(int i){loglevel = i;};
|
||||
|
||||
void WriteHeapInfo(std::string _id);
|
||||
|
||||
void SwitchOnOff(bool _doLogFile);
|
||||
void SetRetention(unsigned short _retentionInDays);
|
||||
void setLogLevel(esp_log_level_t _logLevel);
|
||||
void SetLogFileRetention(unsigned short _LogFileRetentionInDays);
|
||||
void SetDataLogRetention(unsigned short _DataLogRetentionInDays);
|
||||
void SetDataLogToSD(bool _doDataLogToSD);
|
||||
bool GetDataLogToSD();
|
||||
|
||||
void WriteToFile(esp_log_level_t level, std::string tag, std::string message, bool _time);
|
||||
void WriteToFile(esp_log_level_t level, std::string tag, std::string message);
|
||||
|
||||
void WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time = true);
|
||||
|
||||
void CreateLogDirectories();
|
||||
void RemoveOldLogFile();
|
||||
void RemoveOldDataLog();
|
||||
|
||||
// void WriteToData(std::string _ReturnRawValue, std::string _ReturnValue, std::string _ReturnPreValue, std::string _ErrorMessageText, std::string _digital, std::string _analog);
|
||||
void WriteToData(std::string _timestamp, std::string _name, std::string _ReturnRawValue, std::string _ReturnValue, std::string _ReturnPreValue, std::string _ReturnRateValue, std::string _ReturnChangeAbsolute, std::string _ErrorMessageText, std::string _digital, std::string _analog);
|
||||
|
||||
void WriteToFile(std::string info, bool _time = true);
|
||||
void WriteToDedicatedFile(std::string _fn, std::string info, bool _time = true);
|
||||
void RemoveOld();
|
||||
|
||||
std::string GetCurrentFileName();
|
||||
std::string GetCurrentFileNameData();
|
||||
};
|
||||
|
||||
extern ClassLogFile LogFile;
|
||||
@@ -2,6 +2,4 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES tflite-lib mqtt jomjol_logfile)
|
||||
|
||||
|
||||
REQUIRES tflite-lib mqtt jomjol_tfliteclass jomjol_helper jomjol_mqtt jomjol_wlan)
|
||||
|
||||
@@ -4,35 +4,74 @@
|
||||
#include "esp_log.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
static const char *TAG_INTERFACEMQTT = "interface_mqtt";
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
static const char *TAG = "MQTT INTERFACE";
|
||||
|
||||
std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;
|
||||
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
|
||||
bool debugdetail = true;
|
||||
|
||||
// #define CONFIG_BROKER_URL "mqtt://192.168.178.43:1883"
|
||||
|
||||
int failedOnRound = -1;
|
||||
|
||||
esp_mqtt_event_id_t esp_mmqtt_ID = MQTT_EVENT_ANY;
|
||||
// ESP_EVENT_ANY_ID
|
||||
|
||||
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;
|
||||
int keepalive, SetRetainFlag;
|
||||
void (*callbackOnConnected)(std::string, int) = NULL;
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag){
|
||||
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag) {
|
||||
int msg_id;
|
||||
std::string zw;
|
||||
|
||||
if (failedOnRound == getCountFlowRounds()) { // we already failed in this round, do not retry until the next round
|
||||
return true; // Fail quietly
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTT Publish");
|
||||
#endif
|
||||
|
||||
if (!mqtt_connected) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Not connected, trying to re-connect...");
|
||||
if (!MQTT_Init()) {
|
||||
if (!MQTT_Init()) { // Retry
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to init, skipping all MQTT publishings in this round!");
|
||||
failedOnRound = getCountFlowRounds();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
|
||||
if (msg_id < 0) {
|
||||
LogFile.WriteToFile("MQTT - Failed to publish '" + _key + "'!");
|
||||
return false;
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to publish topic '" + _key + "', re-trying...");
|
||||
|
||||
msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
|
||||
if (msg_id < 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to publish topic '" + _key + "', skipping all MQTT publishings in this round!");
|
||||
mqtt_connected = false; // Force re-init on next call
|
||||
failedOnRound = getCountFlowRounds();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
zw = "MQTT - sent publish successful in MQTTPublish, msg_id=" + std::to_string(msg_id) + ", " + _key + ", " + _content;
|
||||
if (debugdetail) LogFile.WriteToFile(zw);
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "sent publish successful in MQTTPublish, msg_id=%d, %s, %s", msg_id, _key.c_str(), _content.c_str());
|
||||
|
||||
if (_content.length() > 80) { // Truncate message if too long
|
||||
_content.resize(80);
|
||||
_content.append("..");
|
||||
}
|
||||
|
||||
zw = "Published topic: " + _key + ", content: " + _content + " (msg_id=" + std::to_string(msg_id) + ")";
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -43,162 +82,151 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
|
||||
std::string topic = "";
|
||||
switch (event->event_id) {
|
||||
case MQTT_EVENT_BEFORE_CONNECT:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_BEFORE_CONNECT");
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_BEFORE_CONNECT");
|
||||
break;
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_CONNECTED");
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_CONNECTED");
|
||||
mqtt_connected = true;
|
||||
MQTTconnected();
|
||||
break;
|
||||
case MQTT_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_DISCONNECTED");
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_DISCONNECTED");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Disconnected! Going to re-connect...");
|
||||
mqtt_connected = false; // Force re-init on next call
|
||||
esp_mqtt_client_reconnect(client);
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "sent publish successful, msg_id=%d", msg_id);
|
||||
ESP_LOGD(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_PUBLISHED:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_PUBLISHED, msg_id=%d", event->msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_DATA");
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "DATA=%.*s\r\n", event->data_len, event->data);
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_DATA");
|
||||
ESP_LOGD(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
ESP_LOGD(TAG, "DATA=%.*s\r\n", event->data_len, event->data);
|
||||
topic.assign(event->topic, event->topic_len);
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "call handler function\r\n");
|
||||
ESP_LOGD(TAG, "call handler function\r\n");
|
||||
(*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
|
||||
}
|
||||
} else {
|
||||
ESP_LOGW(TAG_INTERFACEMQTT, "no handler available\r\n");
|
||||
ESP_LOGW(TAG, "no handler available\r\n");
|
||||
}
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "MQTT_EVENT_ERROR");
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_ERROR");
|
||||
mqtt_connected = false; // Force re-init on next call
|
||||
break;
|
||||
default:
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "Other event id:%d", event->event_id);
|
||||
ESP_LOGD(TAG, "Other event id:%d", event->event_id);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||||
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||||
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
|
||||
}
|
||||
|
||||
|
||||
bool MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive){
|
||||
std::string _zwmessage = "connection lost";
|
||||
void 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,
|
||||
int _keepalive, int _SetRetainFlag, void *_callbackOnConnected){
|
||||
#ifdef __HIDE_PASSWORD
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "URI: " + _mqttURI + ", clientname: " + _clientid +
|
||||
", user: " + _user + ", password: XXXXXXXX, maintopic: " + _maintopic + ", last-will-topic: " + _maintopic + "/" + _lwt + ", keepAlive: " + std::to_string(_keepalive));
|
||||
#else
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "URI: " + _mqttURI + ", clientname: " + _clientid +
|
||||
", user: " + _user + ", password: " + _password + ", maintopic: " + _maintopic + ", last-will-topic: " + _maintopic + "/" + _lwt + ", keepAlive: " + std::to_string(_keepalive));
|
||||
#endif
|
||||
|
||||
int _lzw = _zwmessage.length();
|
||||
|
||||
/* LWTContext = _LWTContext;
|
||||
|
||||
mqtt_cfg.uri = _mqttURI.c_str();
|
||||
mqtt_cfg.client_id = _clientid.c_str();
|
||||
mqtt_cfg.lwt_topic = _LWTContext.c_str();
|
||||
mqtt_cfg.lwt_msg = _zwmessage.c_str();
|
||||
mqtt_cfg.lwt_retain = 1;
|
||||
mqtt_cfg.lwt_msg_len = _lzw;
|
||||
mqtt_cfg.keepalive = _keepalive;
|
||||
*/
|
||||
|
||||
esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.uri = _mqttURI.c_str(),
|
||||
.client_id = _clientid.c_str(),
|
||||
.lwt_topic = _LWTContext.c_str(),
|
||||
.lwt_msg = _zwmessage.c_str(),
|
||||
.lwt_retain = 1,
|
||||
.lwt_msg_len = _lzw,
|
||||
.keepalive = _keepalive
|
||||
};
|
||||
|
||||
LogFile.WriteToFile("MQTT - Init");
|
||||
uri = _mqttURI;
|
||||
client_id = _clientid;
|
||||
lwt_topic = _maintopic + "/" + _lwt;
|
||||
lwt_connected = _lwt_connected;
|
||||
lwt_disconnected = _lwt_disconnected;
|
||||
keepalive = _keepalive;
|
||||
SetRetainFlag = _SetRetainFlag;
|
||||
maintopic = _maintopic;
|
||||
callbackOnConnected = ( void (*)(std::string, int) )(_callbackOnConnected);
|
||||
|
||||
if (_user.length() && _password.length()){
|
||||
mqtt_cfg.username = _user.c_str();
|
||||
mqtt_cfg.password = _password.c_str();
|
||||
user = _user;
|
||||
password = _password;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "Connect to MQTT: %s, XXXXXXXX", mqtt_cfg.username);
|
||||
#else
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "Connect to MQTT: %s, %s", mqtt_cfg.username, mqtt_cfg.password);
|
||||
#endif
|
||||
bool MQTT_Init() {
|
||||
esp_err_t ret;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, std::string("Init"));
|
||||
|
||||
MQTTdestroy_client();
|
||||
|
||||
std::string lw = lwt_disconnected;
|
||||
|
||||
esp_mqtt_client_config_t mqtt_cfg = {
|
||||
.uri = uri.c_str(),
|
||||
.client_id = client_id.c_str(),
|
||||
.lwt_topic = lwt_topic.c_str(),
|
||||
.lwt_msg = lw.c_str(),
|
||||
.lwt_retain = 1,
|
||||
.lwt_msg_len = (int)(lw.length()),
|
||||
.keepalive = keepalive
|
||||
};
|
||||
|
||||
MQTTdestroy();
|
||||
if (user.length() && password.length()){
|
||||
mqtt_cfg.username = user.c_str();
|
||||
mqtt_cfg.password = password.c_str();
|
||||
};
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTT Client Init");
|
||||
#endif
|
||||
client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
if (client)
|
||||
{
|
||||
if (esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client) != ESP_OK)
|
||||
ret = esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not register event!");
|
||||
return false;
|
||||
}
|
||||
if (esp_mqtt_client_start(client) != ESP_OK)
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not start client!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Could not register event (ret=" + std::to_string(ret) + ")!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* if(!MQTTPublish(_LWTContext, "", 1))
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("MQTT Client Start");
|
||||
#endif
|
||||
ret = esp_mqtt_client_start(client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not publish LWT!");
|
||||
return false;
|
||||
}*/
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Could not start client (ret=" + std::to_string(ret) + "), retrying...");
|
||||
ret = esp_mqtt_client_start(client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Could not start client (ret=" + std::to_string(ret) + ")!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not Init client!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Could not init client!");
|
||||
return false;
|
||||
}
|
||||
|
||||
LogFile.WriteToFile("MQTT - Init successful");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init successful");
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
void MQTTReConnect(){
|
||||
std::string _zwmessage = "connection lost";
|
||||
int _lzw = _zwmessage.length();
|
||||
|
||||
>>>>>>> Stashed changes
|
||||
client = esp_mqtt_client_init(&mqtt_cfg);
|
||||
if (client)
|
||||
{
|
||||
if (esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client) != ESP_OK)
|
||||
LogFile.WriteToFile("MQTT - Could not register event!");
|
||||
if (esp_mqtt_client_start(client) != ESP_OK)
|
||||
LogFile.WriteToFile("MQTT - Could not start client!");
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
if(MQTTPublish(_LWTContext, "", 1)) {
|
||||
LogFile.WriteToFile("MQTT - Client init successful");
|
||||
}
|
||||
=======
|
||||
if (mqtt_connected)
|
||||
MQTTPublish(LWTContext, "", 1);
|
||||
else
|
||||
LogFile.WriteToFile("Problem with (Re)Connection not successful!");
|
||||
|
||||
>>>>>>> Stashed changes
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile("MQTT - Could not Init client!");
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void MQTTdestroy() {
|
||||
void MQTTdestroy_client() {
|
||||
if (client != NULL) {
|
||||
esp_mqtt_client_stop(client);
|
||||
esp_mqtt_client_destroy(client);
|
||||
@@ -210,13 +238,13 @@ bool MQTTisConnected() {
|
||||
}
|
||||
|
||||
void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "MQTTregisteronnectFunction %s\r\n", name.c_str());
|
||||
ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str());
|
||||
if (connectFunktionMap == NULL) {
|
||||
connectFunktionMap = new std::map<std::string, std::function<void()>>();
|
||||
}
|
||||
|
||||
if ((*connectFunktionMap)[name] != NULL) {
|
||||
ESP_LOGW(TAG_INTERFACEMQTT, "connect function %s already registred", name.c_str());
|
||||
ESP_LOGW(TAG, "connect function %s already registred", name.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -228,20 +256,20 @@ void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
}
|
||||
|
||||
void MQTTunregisterConnectFunction(std::string name){
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "MQTTregisteronnectFunction %s\r\n", name.c_str());
|
||||
ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str());
|
||||
if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
|
||||
connectFunktionMap->erase(name);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "MQTTregisterSubscribeFunction %s\r\n", topic.c_str());
|
||||
ESP_LOGD(TAG, "registerSubscribeFunction %s\r\n", topic.c_str());
|
||||
if (subscribeFunktionMap == NULL) {
|
||||
subscribeFunktionMap = new std::map<std::string, std::function<bool(std::string, char*, int)>>();
|
||||
}
|
||||
|
||||
if ((*subscribeFunktionMap)[topic] != NULL) {
|
||||
ESP_LOGW(TAG_INTERFACEMQTT, "topic %s already registred for subscription", topic.c_str());
|
||||
ESP_LOGW(TAG, "topic %s already registered for subscription", topic.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -249,27 +277,33 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
|
||||
|
||||
if (mqtt_connected) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, topic.c_str(), 0);
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
|
||||
ESP_LOGD(TAG, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTconnected(){
|
||||
if (mqtt_connected) {
|
||||
LogFile.WriteToFile("MQTT - Connected");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected");
|
||||
|
||||
MQTTPublish(lwt_topic, lwt_connected, true);
|
||||
|
||||
if (connectFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
|
||||
it->second();
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "call connect function %s", it->first.c_str());
|
||||
ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
|
||||
ESP_LOGD(TAG_INTERFACEMQTT, "topic %s subscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
LogFile.WriteToFile("MQTT - topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackOnConnected) {
|
||||
callbackOnConnected(maintopic, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +312,7 @@ void MQTTdestroySubscribeFunction(){
|
||||
if (mqtt_connected) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_unsubscribe(client, it->first.c_str());
|
||||
ESP_LOGI(TAG_INTERFACEMQTT, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
ESP_LOGI(TAG, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,4 +320,4 @@ void MQTTdestroySubscribeFunction(){
|
||||
delete subscribeFunktionMap;
|
||||
subscribeFunktionMap = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,8 +5,11 @@
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
bool MQTTInit(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password, std::string _LWTContext, int _keepalive);
|
||||
void MQTTdestroy();
|
||||
void 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,
|
||||
int _keepalive, int SetRetainFlag, void *callbackOnConnected);
|
||||
bool MQTT_Init();
|
||||
void MQTTdestroy_client();
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag = 1); // retained Flag as Standart
|
||||
|
||||
|
||||
245
code/components/jomjol_mqtt/server_mqtt.cpp
Normal file
245
code/components/jomjol_mqtt/server_mqtt.cpp
Normal file
@@ -0,0 +1,245 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "connect_wlan.h"
|
||||
#include "server_mqtt.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "time_sntp.h"
|
||||
|
||||
|
||||
|
||||
static const char *TAG = "MQTT SERVER";
|
||||
|
||||
|
||||
extern const char* libfive_git_version(void);
|
||||
extern const char* libfive_git_revision(void);
|
||||
extern const char* libfive_git_branch(void);
|
||||
|
||||
std::vector<NumberPost*>* NUMBERS;
|
||||
bool HomeassistantDiscovery = false;
|
||||
std::string meterType = "";
|
||||
std::string valueUnit = "";
|
||||
std::string timeUnit = "";
|
||||
std::string rateUnit = "Unit/Minute";
|
||||
float roundInterval; // Minutes
|
||||
int keepAlive = 0; // Seconds
|
||||
int retainFlag;
|
||||
static std::string maintopic;
|
||||
|
||||
|
||||
void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int _keepAlive, float _roundInterval) {
|
||||
NUMBERS = _NUMBERS;
|
||||
keepAlive = _keepAlive;
|
||||
roundInterval = _roundInterval;
|
||||
}
|
||||
|
||||
void mqttServer_setMeterType(std::string _meterType, std::string _valueUnit, std::string _timeUnit,std::string _rateUnit) {
|
||||
meterType = _meterType;
|
||||
valueUnit = _valueUnit;
|
||||
timeUnit = _timeUnit;
|
||||
rateUnit = _rateUnit;
|
||||
}
|
||||
|
||||
void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
|
||||
std::string name, std::string icon, std::string unit, std::string deviceClass, std::string stateClass, std::string entityCategory) {
|
||||
std::string version = std::string(libfive_git_version());
|
||||
|
||||
if (version == "") {
|
||||
version = std::string(libfive_git_branch()) + " (" + std::string(libfive_git_revision()) + ")";
|
||||
}
|
||||
|
||||
std::string topicFull;
|
||||
std::string configTopic;
|
||||
std::string payload;
|
||||
std::string nl = "\n";
|
||||
|
||||
configTopic = field;
|
||||
|
||||
if (group != "" && (*NUMBERS).size() > 1) { // There is more than one meter, prepend the group so we can differentiate them
|
||||
configTopic = group + "_" + field;
|
||||
name = group + " " + name;
|
||||
}
|
||||
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
topicFull = "homeassistant/binary_sensor/" + maintopic + "/" + configTopic + "/config";
|
||||
}
|
||||
else {
|
||||
topicFull = "homeassistant/sensor/" + maintopic + "/" + configTopic + "/config";
|
||||
}
|
||||
|
||||
/* See https://www.home-assistant.io/docs/mqtt/discovery/ */
|
||||
payload = "{" + nl +
|
||||
"\"~\": \"" + maintopic + "\"," + nl +
|
||||
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," + nl +
|
||||
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + nl + // This used to generate the Entity ID
|
||||
"\"name\": \"" + name + "\"," + nl +
|
||||
"\"icon\": \"mdi:" + icon + "\"," + nl;
|
||||
|
||||
if (group != "") {
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
payload += "\"state_topic\": \"~/" + group + "/error\"," + nl;
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\"," + nl;
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + group + "/" + field + "\"," + nl;
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + field + "\"," + nl;
|
||||
}
|
||||
|
||||
if (unit != "") {
|
||||
payload += "\"unit_of_meas\": \"" + unit + "\"," + nl;
|
||||
}
|
||||
|
||||
if (deviceClass != "") {
|
||||
payload += "\"device_class\": \"" + deviceClass + "\"," + nl;
|
||||
}
|
||||
|
||||
if (stateClass != "") {
|
||||
payload += "\"state_class\": \"" + stateClass + "\"," + nl;
|
||||
}
|
||||
|
||||
if (entityCategory != "") {
|
||||
payload += "\"entity_category\": \"" + entityCategory + "\"," + nl;
|
||||
}
|
||||
|
||||
payload +=
|
||||
"\"availability_topic\": \"~/" + std::string(LWT_TOPIC) + "\"," + nl +
|
||||
"\"payload_available\": \"" + LWT_CONNECTED + "\"," + nl +
|
||||
"\"payload_not_available\": \"" + LWT_DISCONNECTED + "\"," + nl;
|
||||
|
||||
payload +=
|
||||
"\"device\": {" + nl +
|
||||
"\"identifiers\": [\"" + maintopic + "\"]," + nl +
|
||||
"\"name\": \"" + maintopic + "\"," + nl +
|
||||
"\"model\": \"Meter Digitizer\"," + nl +
|
||||
"\"manufacturer\": \"AI on the Edge Device\"," + nl +
|
||||
"\"sw_version\": \"" + version + "\"," + nl +
|
||||
"\"configuration_url\": \"http://" + *getIPAddress() + "\"" + nl +
|
||||
"}" + nl +
|
||||
"}" + nl;
|
||||
|
||||
MQTTPublish(topicFull, payload, true);
|
||||
}
|
||||
|
||||
void MQTThomeassistantDiscovery() {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "MQTT - Sending Homeassistant Discovery Topics (Meter Type: " + meterType + ", Value Unit: " + valueUnit + " , Rate Unit: " + rateUnit + ")...");
|
||||
|
||||
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
|
||||
sendHomeAssistantDiscoveryTopic("", "uptime", "Uptime", "clock-time-eight-outline", "s", "", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "MAC", "MAC Address", "network-outline", "", "", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "hostname", "Hostname", "network-outline", "", "", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "freeMem", "Free Memory", "memory", "B", "", "measurement", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "wifiRSSI", "Wi-Fi RSSI", "wifi", "dBm", "signal_strength", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "CPUtemp", "CPU Temperature", "thermometer", "°C", "temperature", "measurement", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "interval", "Interval", "clock-time-eight-outline", "min", "" , "measurement", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "IP", "IP", "network-outline", "", "", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic("", "status", "Status", "list-status", "", "", "", "diagnostic");
|
||||
|
||||
|
||||
|
||||
for (int i = 0; i < (*NUMBERS).size(); ++i) {
|
||||
std::string group = (*NUMBERS)[i]->name;
|
||||
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
|
||||
sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", "");
|
||||
sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, "", "total_increasing", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic(group, "error", "Error", "alert-circle-outline", "", "", "", "diagnostic");
|
||||
/* Not announcing "rate" as it is better to use rate_per_time_unit resp. rate_per_digitalization_round */
|
||||
// sendHomeAssistantDiscoveryTopic(group, "rate", "Rate (Unit/Minute)", "swap-vertical", "", "", "", ""); // Legacy, always Unit per Minute
|
||||
sendHomeAssistantDiscoveryTopic(group, "rate_per_time_unit", "Rate (" + rateUnit + ")", "swap-vertical", rateUnit, "", "", "");
|
||||
sendHomeAssistantDiscoveryTopic(group, "rate_per_digitalization_round", "Change since last digitalization round", "arrow-expand-vertical", valueUnit, "", "measurement", ""); // correctly the Unit is Uint/Interval!
|
||||
sendHomeAssistantDiscoveryTopic(group, "timestamp", "Timestamp", "clock-time-eight-outline", "", "timestamp", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic(group, "json", "JSON", "code-json", "", "", "", "diagnostic");
|
||||
sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "", "", ""); // Special binary sensor which is based on error topic
|
||||
}
|
||||
}
|
||||
|
||||
void publishSystemData() {
|
||||
char tmp_char[50];
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing system MQTT topics...");
|
||||
|
||||
sprintf(tmp_char, "%ld", (long)getUpTime());
|
||||
MQTTPublish(maintopic + "/" + "uptime", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%zu", esp_get_free_heap_size());
|
||||
MQTTPublish(maintopic + "/" + "freeMem", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%d", get_WIFI_RSSI());
|
||||
MQTTPublish(maintopic + "/" + "wifiRSSI", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%d", (int)temperatureRead());
|
||||
MQTTPublish(maintopic + "/" + "CPUtemp", std::string(tmp_char), retainFlag);
|
||||
}
|
||||
|
||||
|
||||
void publishStaticData() {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing static MQTT topics...");
|
||||
MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag);
|
||||
MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag);
|
||||
MQTTPublish(maintopic + "/" + "hostname", hostname, retainFlag);
|
||||
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << roundInterval; // minutes
|
||||
MQTTPublish(maintopic + "/" + "interval", stream.str(), retainFlag);
|
||||
}
|
||||
|
||||
esp_err_t sendDiscovery_and_static_Topics(httpd_req_t *req) {
|
||||
if (HomeassistantDiscovery) {
|
||||
MQTThomeassistantDiscovery();
|
||||
}
|
||||
|
||||
publishStaticData();
|
||||
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void GotConnected(std::string maintopic, int retainFlag) {
|
||||
if (HomeassistantDiscovery) {
|
||||
MQTThomeassistantDiscovery();
|
||||
}
|
||||
|
||||
publishStaticData();
|
||||
publishSystemData();
|
||||
}
|
||||
|
||||
void register_server_mqtt_uri(httpd_handle_t server) {
|
||||
httpd_uri_t uri = { };
|
||||
uri.method = HTTP_GET;
|
||||
|
||||
uri.uri = "/mqtt_publish_discovery";
|
||||
uri.handler = sendDiscovery_and_static_Topics;
|
||||
uri.user_ctx = (void*) "MQTT Discovery and Static Topics sent";
|
||||
httpd_register_uri_handler(server, &uri);
|
||||
}
|
||||
|
||||
|
||||
std::string getTimeUnit(void) {
|
||||
return timeUnit;
|
||||
}
|
||||
|
||||
|
||||
void SetHomeassistantDiscoveryEnabled(bool enabled) {
|
||||
HomeassistantDiscovery = enabled;
|
||||
}
|
||||
|
||||
|
||||
void setMqtt_Server_Retain(int _retainFlag) {
|
||||
retainFlag = _retainFlag;
|
||||
}
|
||||
|
||||
void mqttServer_setMainTopic( std::string _maintopic) {
|
||||
maintopic = _maintopic;
|
||||
}
|
||||
|
||||
std::string mqttServer_getMainTopic() {
|
||||
return maintopic;
|
||||
}
|
||||
20
code/components/jomjol_mqtt/server_mqtt.h
Normal file
20
code/components/jomjol_mqtt/server_mqtt.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#include "ClassFlowDefineTypes.h"
|
||||
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
|
||||
void SetHomeassistantDiscoveryEnabled(bool enabled);
|
||||
void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int interval, float roundInterval);
|
||||
void mqttServer_setMeterType(std::string meterType, std::string valueUnit, std::string timeUnit,std::string rateUnit);
|
||||
void setMqtt_Server_Retain(int SetRetainFlag);
|
||||
void mqttServer_setMainTopic( std::string maintopic);
|
||||
std::string mqttServer_getMainTopic();
|
||||
|
||||
void register_server_mqtt_uri(httpd_handle_t server);
|
||||
|
||||
void publishSystemData();
|
||||
|
||||
std::string getTimeUnit(void);
|
||||
void GotConnected(std::string maintopic, int SetRetainFlag);
|
||||
@@ -1,11 +1,15 @@
|
||||
#include "CTfLiteClass.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
static const char *TAG = "C TFLITE";
|
||||
|
||||
float CTfLiteClass::GetOutputValue(int nr)
|
||||
{
|
||||
TfLiteTensor* output2 = this->interpreter->output(0);
|
||||
@@ -41,7 +45,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
return -1;
|
||||
|
||||
int numeroutput = output2->dims->data[1];
|
||||
//printf("\n number output neurons: %d\n\n", numeroutput);
|
||||
//ESP_LOGD(TAG, "number output neurons: %d", numeroutput);
|
||||
|
||||
if (_bis == -1)
|
||||
_bis = numeroutput -1;
|
||||
@@ -51,7 +55,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
|
||||
if (_bis >= numeroutput)
|
||||
{
|
||||
printf("ANZAHL OUTPUT NEURONS passt nicht zu geforderter Classifizierung!");
|
||||
ESP_LOGD(TAG, "ANZAHL OUTPUT NEURONS passt nicht zu geforderter Classifizierung!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -74,13 +78,13 @@ void CTfLiteClass::GetInputDimension(bool silent = false)
|
||||
TfLiteTensor* input2 = this->interpreter->input(0);
|
||||
|
||||
int numdim = input2->dims->size;
|
||||
if (!silent) printf("NumDimension: %d\n", numdim);
|
||||
if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim);
|
||||
|
||||
int sizeofdim;
|
||||
for (int j = 0; j < numdim; ++j)
|
||||
{
|
||||
sizeofdim = input2->dims->data[j];
|
||||
if (!silent) printf("SizeOfDimension %d: %d\n", j, sizeofdim);
|
||||
if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim);
|
||||
if (j == 1) im_height = sizeofdim;
|
||||
if (j == 2) im_width = sizeofdim;
|
||||
if (j == 3) im_channel = sizeofdim;
|
||||
@@ -106,13 +110,13 @@ int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
TfLiteTensor* output2 = this->interpreter->output(0);
|
||||
|
||||
int numdim = output2->dims->size;
|
||||
if (!silent) printf("NumDimension: %d\n", numdim);
|
||||
if (!silent) ESP_LOGD(TAG, "NumDimension: %d", numdim);
|
||||
|
||||
int sizeofdim;
|
||||
for (int j = 0; j < numdim; ++j)
|
||||
{
|
||||
sizeofdim = output2->dims->data[j];
|
||||
if (!silent) printf("SizeOfDimension %d: %d\n", j, sizeofdim);
|
||||
if (!silent) ESP_LOGD(TAG, "SizeOfDimension %d: %d", j, sizeofdim);
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +127,7 @@ int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
for (int i = 0; i < numeroutput; ++i)
|
||||
{
|
||||
fo = output2->data.f[i];
|
||||
if (!silent) printf("Result %d: %f\n", i, fo);
|
||||
if (!silent) ESP_LOGD(TAG, "Result %d: %f", i, fo);
|
||||
}
|
||||
return numeroutput;
|
||||
}
|
||||
@@ -143,7 +147,7 @@ bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
unsigned int w = rs->width;
|
||||
unsigned int h = rs->height;
|
||||
unsigned char red, green, blue;
|
||||
// printf("Image: %s size: %d x %d\n", _fn.c_str(), w, h);
|
||||
// ESP_LOGD(TAG, "Image: %s size: %d x %d\n", _fn.c_str(), w, h);
|
||||
|
||||
input_i = 0;
|
||||
float* input_data_ptr = (interpreter->input(0))->data.f;
|
||||
@@ -163,7 +167,7 @@ bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteToFile("Nach dem Laden in input");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach dem Laden in input");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -174,26 +178,26 @@ void CTfLiteClass::MakeAllocate()
|
||||
{
|
||||
static tflite::AllOpsResolver resolver;
|
||||
|
||||
// printf(LogFile.getESPHeapInfo().c_str()); printf("\n");
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
|
||||
// printf(LogFile.getESPHeapInfo().c_str()); printf("\n");
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
|
||||
TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
LogFile.WriteToFile("AllocateTensors() failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
|
||||
|
||||
this->GetInputDimension();
|
||||
return;
|
||||
}
|
||||
// printf("Allocate Done.\n");
|
||||
// ESP_LOGD(TAG, "Allocate Done");
|
||||
}
|
||||
|
||||
void CTfLiteClass::GetInputTensorSize(){
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
float *zw = this->input;
|
||||
int test = sizeof(zw);
|
||||
printf("Input Tensor Dimension: %d\n", test);
|
||||
ESP_LOGD(TAG, "Input Tensor Dimension: %d", test);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -213,7 +217,7 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
printf("\nFile doesn't exist.\n");
|
||||
ESP_LOGD(TAG, "File doesn't exist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -222,7 +226,7 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
|
||||
while (!result && (anz < 6)) // maximal 5x versuchen (= 5s)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Speicher ist voll - Versuche es erneut: %d.\n", anz);
|
||||
ESP_LOGD(TAG, "Speicher ist voll - Versuche es erneut: %d", anz);
|
||||
#endif
|
||||
result = (unsigned char*) malloc(size);
|
||||
anz++;
|
||||
@@ -234,7 +238,7 @@ unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
|
||||
fread(result, 1, size, f);
|
||||
fclose(f);
|
||||
}else {
|
||||
printf("\nNo free memory available.\n");
|
||||
ESP_LOGD(TAG, "No free memory available");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "server_file.h"
|
||||
#include "connect_wlan.h"
|
||||
|
||||
#define DEBUG_DETAIL_ON
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
ClassFlowControll tfliteflow;
|
||||
@@ -39,7 +39,7 @@ bool auto_isrunning = false;
|
||||
|
||||
int countRounds = 0;
|
||||
|
||||
static const char *TAGTFLITE = "server_tflite";
|
||||
static const char *TAG = "TFLITE";
|
||||
|
||||
|
||||
int getCountFlowRounds() {
|
||||
@@ -67,7 +67,7 @@ bool isSetupModusActive() {
|
||||
void KillTFliteTasks()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Handle: xHandleblink_task_doFlow: %ld\n", (long) xHandleblink_task_doFlow);
|
||||
ESP_LOGD(TAG, "Handle: xHandleblink_task_doFlow: %ld", (long) xHandleblink_task_doFlow);
|
||||
#endif
|
||||
if (xHandleblink_task_doFlow != NULL)
|
||||
{
|
||||
@@ -75,12 +75,12 @@ void KillTFliteTasks()
|
||||
xHandleblink_task_doFlow = NULL;
|
||||
vTaskDelete(xHandleblink_task_doFlowTmp);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Killed: xHandleblink_task_doFlow\n");
|
||||
ESP_LOGD(TAG, "Killed: xHandleblink_task_doFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Handle: xHandletask_autodoFlow: %ld\n", (long) xHandletask_autodoFlow);
|
||||
ESP_LOGD(TAG, "Handle: xHandletask_autodoFlow: %ld", (long) xHandletask_autodoFlow);
|
||||
#endif
|
||||
if (xHandletask_autodoFlow != NULL)
|
||||
{
|
||||
@@ -88,7 +88,7 @@ void KillTFliteTasks()
|
||||
xHandletask_autodoFlow = NULL;
|
||||
vTaskDelete(xHandletask_autodoFlowTmp);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Killed: xHandletask_autodoFlow\n");
|
||||
ESP_LOGD(TAG, "Killed: xHandletask_autodoFlow");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -97,11 +97,11 @@ void KillTFliteTasks()
|
||||
void doInit(void)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Start tfliteflow.InitFlow(config);\n");
|
||||
ESP_LOGD(TAG, "Start tfliteflow.InitFlow(config);");
|
||||
#endif
|
||||
tfliteflow.InitFlow(CONFIG_FILE);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Finished tfliteflow.InitFlow(config);\n");
|
||||
ESP_LOGD(TAG, "Finished tfliteflow.InitFlow(config);");
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -110,13 +110,13 @@ bool doflow(void)
|
||||
{
|
||||
|
||||
std::string zw_time = gettimestring(LOGFILE_TIME_FORMAT);
|
||||
printf("doflow - start %s\n", zw_time.c_str());
|
||||
ESP_LOGD(TAG, "doflow - start %s", zw_time.c_str());
|
||||
flowisrunning = true;
|
||||
tfliteflow.doFlow(zw_time);
|
||||
flowisrunning = false;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("doflow - end %s\n", zw_time.c_str());
|
||||
ESP_LOGD(TAG, "doflow - end %s", zw_time.c_str());
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -124,7 +124,7 @@ bool doflow(void)
|
||||
void blink_task_doFlow(void *pvParameter)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("blink_task_doFlow\n");
|
||||
ESP_LOGD(TAG, "blink_task_doFlow");
|
||||
#endif
|
||||
if (!flowisrunning)
|
||||
{
|
||||
@@ -141,7 +141,7 @@ esp_err_t handler_init(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_init - Start");
|
||||
printf("handler_doinit uri:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_doinit uri: %s", req->uri);
|
||||
#endif
|
||||
|
||||
const char* resp_str = "Init started<br>";
|
||||
@@ -167,7 +167,7 @@ esp_err_t handler_doflow(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_doflow - Start");
|
||||
#endif
|
||||
|
||||
printf("handler_doFlow uri: "); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_doFlow uri: %s", req->uri);
|
||||
|
||||
if (flowisrunning)
|
||||
{
|
||||
@@ -199,22 +199,20 @@ esp_err_t handler_json(httpd_req_t *req)
|
||||
#endif
|
||||
|
||||
|
||||
printf("handler_JSON uri:\n"); printf(req->uri); printf("\n");
|
||||
|
||||
char _query[100];
|
||||
// char _size[10];
|
||||
ESP_LOGD(TAG, "handler_JSON uri: %s", req->uri);
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
|
||||
std::string zw = tfliteflow.getJSON();
|
||||
if (zw.length() > 0)
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
|
||||
string query = std::string(_query);
|
||||
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
{
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_JSON - Done");
|
||||
@@ -236,18 +234,18 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
std::string _type = "value";
|
||||
string zw;
|
||||
|
||||
printf("handler_wasserzaehler uri:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_wasserzaehler uri: %s", req->uri);
|
||||
|
||||
char _query[100];
|
||||
char _size[10];
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
// printf("Query: "); printf(_query); printf("\n");
|
||||
// ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "all", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("all is found"); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "all is found%s", _size);
|
||||
#endif
|
||||
_all = true;
|
||||
}
|
||||
@@ -255,7 +253,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
if (httpd_query_key_value(_query, "type", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("all is found"); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "all is found: %s", _size);
|
||||
#endif
|
||||
_type = std::string(_size);
|
||||
}
|
||||
@@ -263,14 +261,14 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
if (httpd_query_key_value(_query, "rawvalue", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("rawvalue is found"); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "rawvalue is found: %s", _size);
|
||||
#endif
|
||||
_rawValue = true;
|
||||
}
|
||||
if (httpd_query_key_value(_query, "noerror", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("noerror is found"); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "noerror is found: %s", _size);
|
||||
#endif
|
||||
_noerror = true;
|
||||
}
|
||||
@@ -281,7 +279,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
if (_all)
|
||||
{
|
||||
httpd_resp_set_type(req, "text/plain");
|
||||
printf("TYPE: %s\n", _type.c_str());
|
||||
ESP_LOGD(TAG, "TYPE: %s", _type.c_str());
|
||||
int _intype = READOUT_TYPE_VALUE;
|
||||
if (_type == "prevalue")
|
||||
_intype = READOUT_TYPE_PREVALUE;
|
||||
@@ -292,7 +290,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
|
||||
|
||||
zw = tfliteflow.getReadoutAll(_intype);
|
||||
printf("ZW: %s\n", zw.c_str());
|
||||
ESP_LOGD(TAG, "ZW: %s", zw.c_str());
|
||||
if (zw.length() > 0)
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
@@ -304,7 +302,7 @@ esp_err_t handler_wasserzaehler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
|
||||
string query = std::string(_query);
|
||||
// printf("Query: %s\n", query.c_str());
|
||||
// ESP_LOGD(TAG, "Query: %s, query.c_str());
|
||||
if (query.find("full") != std::string::npos)
|
||||
{
|
||||
string txt, zw;
|
||||
@@ -380,7 +378,7 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("handler_editflow - Start");
|
||||
#endif
|
||||
|
||||
printf("handler_editflow uri: "); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_editflow uri: %s", req->uri);
|
||||
|
||||
char _query[200];
|
||||
char _valuechar[30];
|
||||
@@ -391,15 +389,27 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
if (httpd_query_key_value(_query, "task", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("task is found: %s\n", _valuechar);
|
||||
ESP_LOGD(TAG, "task is found: %s", _valuechar);
|
||||
#endif
|
||||
_task = string(_valuechar);
|
||||
}
|
||||
}
|
||||
|
||||
if (_task.compare("namenumbers") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Get NUMBER list");
|
||||
return get_numbers_file_handler(req);
|
||||
}
|
||||
|
||||
if (_task.compare("data") == 0)
|
||||
{
|
||||
ESP_LOGI(TAG, "Get data list");
|
||||
return get_data_file_handler(req);
|
||||
}
|
||||
|
||||
if (_task.compare("tflite") == 0)
|
||||
{
|
||||
printf("Get tflite list\n");
|
||||
ESP_LOGD(TAG, "Get tflite list");
|
||||
return get_tflite_file_handler(req);
|
||||
}
|
||||
|
||||
@@ -414,8 +424,8 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
out = string(_valuechar);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("in: "); printf(in.c_str()); printf("\n");
|
||||
printf("out: "); printf(out.c_str()); printf("\n");
|
||||
ESP_LOGD(TAG, "in: %s", in.c_str());
|
||||
ESP_LOGD(TAG, "out: %s", out.c_str());
|
||||
#endif
|
||||
|
||||
in = "/sdcard" + in;
|
||||
@@ -456,12 +466,12 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
dy = stoi(zw);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("in: "); printf(in.c_str()); printf("\n");
|
||||
printf("out: "); printf(out.c_str()); printf("\n");
|
||||
printf("x: "); printf(zw.c_str()); printf("\n");
|
||||
printf("y: "); printf(zw.c_str()); printf("\n");
|
||||
printf("dx: "); printf(zw.c_str()); printf("\n");
|
||||
printf("dy: "); printf(zw.c_str()); printf("\n");
|
||||
ESP_LOGD(TAG, "in: %s", in.c_str());
|
||||
ESP_LOGD(TAG, "out: %s", out.c_str());
|
||||
ESP_LOGD(TAG, "x: %s", zw.c_str());
|
||||
ESP_LOGD(TAG, "y: %s", zw.c_str());
|
||||
ESP_LOGD(TAG, "dx: %s", zw.c_str());
|
||||
ESP_LOGD(TAG, "dy: %s", zw.c_str());
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "enhance", _valuechar, 10) == ESP_OK)
|
||||
@@ -529,11 +539,11 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
// printf("Parameter host: "); printf(_host.c_str()); printf("\n");
|
||||
// string zwzw = "Do " + _task + " start\n"; printf(zwzw.c_str());
|
||||
// ESP_LOGD(TAG, "Parameter host: %s", _host.c_str());
|
||||
// string zwzw = "Do " + _task + " start\n"; ESP_LOGD(TAG, zwzw.c_str());
|
||||
Camera.SetBrightnessContrastSaturation(bri, con, sat);
|
||||
Camera.SetLEDIntensity(intens);
|
||||
printf("test_take - vor MakeImage");
|
||||
ESP_LOGD(TAG, "test_take - vor MakeImage");
|
||||
std::string zw = tfliteflow.doSingleStep("[MakeImage]", _host);
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
@@ -546,9 +556,9 @@ esp_err_t handler_editflow(httpd_req_t *req)
|
||||
if (httpd_query_key_value(_query, "host", _valuechar, 30) == ESP_OK) {
|
||||
_host = std::string(_valuechar);
|
||||
}
|
||||
// printf("Parameter host: "); printf(_host.c_str()); printf("\n");
|
||||
// ESP_LOGD(TAG, "Parameter host: %s", _host.c_str());
|
||||
|
||||
// string zwzw = "Do " + _task + " start\n"; printf(zwzw.c_str());
|
||||
// string zwzw = "Do " + _task + " start\n"; ESP_LOGD(TAG, zwzw.c_str());
|
||||
std::string zw = tfliteflow.doSingleStep("[Alignment]", _host);
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
}
|
||||
@@ -573,7 +583,7 @@ esp_err_t handler_statusflow(httpd_req_t *req)
|
||||
const char* resp_str;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("handler_prevalue:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
|
||||
#endif
|
||||
|
||||
string* zw = tfliteflow.getActStatus();
|
||||
@@ -651,7 +661,7 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
string zw;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("handler_prevalue:\n"); printf(req->uri); printf("\n");
|
||||
ESP_LOGD(TAG, "handler_prevalue: %s", req->uri);
|
||||
#endif
|
||||
|
||||
char _query[100];
|
||||
@@ -661,13 +671,13 @@ esp_err_t handler_prevalue(httpd_req_t *req)
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
#endif
|
||||
|
||||
if (httpd_query_key_value(_query, "value", _size, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Value: "); printf(_size); printf("\n");
|
||||
ESP_LOGD(TAG, "Value: %s", _size);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -703,7 +713,14 @@ void task_autodoFlow(void *pvParameter)
|
||||
{
|
||||
int64_t fr_start, fr_delta_ms;
|
||||
|
||||
printf("task_autodoFlow: start\r\n");
|
||||
if (esp_reset_reason() == ESP_RST_PANIC) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Restarted due to an Exception/panic! Postponing first round start by 5 minutes to allow for an OTA or to fetch the log!");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Setting logfile level to DEBUG until the next reboot!");
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
vTaskDelay(60*5000 / portTICK_RATE_MS); // Wait 5 minutes to give time to do an OTA or fetch the log
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "task_autodoFlow: start");
|
||||
doInit();
|
||||
gpio_handler_init();
|
||||
|
||||
@@ -716,49 +733,49 @@ void task_autodoFlow(void *pvParameter)
|
||||
}
|
||||
while (auto_isrunning)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "----------------------------------------------------------------"); // Clear separation between runs
|
||||
std::string _zw = "task_autodoFlow - next round - Round #" + std::to_string(++countRounds);
|
||||
LogFile.WriteToFile(_zw);
|
||||
printf("Autoflow: start\n");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
fr_start = esp_timer_get_time();
|
||||
|
||||
if (flowisrunning)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Autoflow: doFlow is already running!\n");
|
||||
ESP_LOGD(TAG, "Autoflow: doFlow is already running!");
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Autoflow: doFlow is started\n");
|
||||
ESP_LOGD(TAG, "Autoflow: doFlow is started");
|
||||
#endif
|
||||
flowisrunning = true;
|
||||
doflow();
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
printf("Remove older log files\n");
|
||||
ESP_LOGD(TAG, "Remove older log files");
|
||||
#endif
|
||||
LogFile.RemoveOld();
|
||||
LogFile.RemoveOldLogFile();
|
||||
LogFile.RemoveOldDataLog();
|
||||
}
|
||||
|
||||
LogFile.WriteToFile("task_autodoFlow - round done");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "task_autodoFlow - round #" + std::to_string(countRounds) + " done");
|
||||
//CPU Temp
|
||||
float cputmp = temperatureRead();
|
||||
std::stringstream stream;
|
||||
stream << std::fixed << std::setprecision(1) << cputmp;
|
||||
string zwtemp = "CPU Temperature: " + stream.str();
|
||||
LogFile.WriteToFile(zwtemp);
|
||||
printf("CPU Temperature: %.2f\n", cputmp);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, zwtemp);
|
||||
fr_delta_ms = (esp_timer_get_time() - fr_start) / 1000;
|
||||
if (auto_intervall > fr_delta_ms)
|
||||
{
|
||||
const TickType_t xDelay = (auto_intervall - fr_delta_ms) / portTICK_PERIOD_MS;
|
||||
printf("Autoflow: sleep for : %ldms\n", (long) xDelay);
|
||||
ESP_LOGD(TAG, "Autoflow: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
}
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
xHandletask_autodoFlow = NULL;
|
||||
printf("task_autodoFlow: end\r\n");
|
||||
ESP_LOGD(TAG, "task_autodoFlow: end");
|
||||
}
|
||||
|
||||
void TFliteDoAutoStart()
|
||||
@@ -767,17 +784,17 @@ void TFliteDoAutoStart()
|
||||
|
||||
int _i = configMINIMAL_STACK_SIZE;
|
||||
|
||||
printf("task_autodoFlow configMINIMAL_STACK_SIZE: %d\n", _i);
|
||||
printf("getESPHeapInfo: %s\n", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "task_autodoFlow configMINIMAL_STACK_SIZE: %d", _i);
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
|
||||
xReturned = xTaskCreate(&task_autodoFlow, "task_autodoFlow", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, &xHandletask_autodoFlow);
|
||||
if( xReturned != pdPASS )
|
||||
{
|
||||
|
||||
//Memory: 64 --> 48 --> 35 --> 25
|
||||
printf("ERROR task_autodoFlow konnte nicht erzeugt werden !!\r\n");
|
||||
ESP_LOGD(TAG, "ERROR task_autodoFlow konnte nicht erzeugt werden!");
|
||||
}
|
||||
printf("getESPHeapInfo: %s\n", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "getESPHeapInfo: %s", getESPHeapInfo().c_str());
|
||||
|
||||
|
||||
}
|
||||
@@ -791,7 +808,7 @@ std::string GetMQTTMainTopic()
|
||||
|
||||
void register_server_tflite_uri(httpd_handle_t server)
|
||||
{
|
||||
ESP_LOGI(TAGTFLITE, "server_part_camera - Registering URI handlers");
|
||||
ESP_LOGI(TAG, "server_part_camera - Registering URI handlers");
|
||||
|
||||
httpd_uri_t camuri = { };
|
||||
camuri.method = HTTP_GET;
|
||||
@@ -801,11 +818,17 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
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.user_ctx = (void*) "Prevalue";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/setPreValue";
|
||||
camuri.handler = handler_prevalue;
|
||||
camuri.user_ctx = (void*) "Prevalue";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/doflow";
|
||||
camuri.handler = handler_doflow;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
@@ -815,27 +838,51 @@ void register_server_tflite_uri(httpd_handle_t server)
|
||||
camuri.handler = handler_statusflow;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
|
||||
camuri.uri = "/statusflow";
|
||||
camuri.handler = 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.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/cpu_temperature";
|
||||
camuri.handler = 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.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/editflow.html";
|
||||
camuri.uri = "/rssi";
|
||||
camuri.handler = handler_rssi;
|
||||
camuri.user_ctx = (void*) "Light Off";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/editflow";
|
||||
camuri.handler = 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.user_ctx = (void*) "Value";
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/value";
|
||||
camuri.handler = 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.user_ctx = (void*) "Wasserzaehler";
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include "CImageBasis.h"
|
||||
#include "ClassFlowControll.h"
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
|
||||
@@ -16,6 +17,10 @@ bool isSetupModusActive();
|
||||
|
||||
std::string GetMQTTMainTopic();
|
||||
|
||||
int getCountFlowRounds();
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
|
||||
|
||||
esp_err_t GetRawJPG(httpd_req_t *req);
|
||||
|
||||
extern ClassFlowControll tfliteflow;
|
||||
|
||||
@@ -15,13 +15,13 @@
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
static const char *TAG = "sntp";
|
||||
static const char *TAG = "SNTP";
|
||||
|
||||
bool setTimeAlwaysOnReboot = true;
|
||||
time_t bootTime;
|
||||
|
||||
static void obtain_time(void);
|
||||
static bool obtain_time(void);
|
||||
static void initialize_sntp(void);
|
||||
static void logNtpStatus(sntp_sync_status_t status);
|
||||
|
||||
void time_sync_notification_cb(struct timeval *tv)
|
||||
{
|
||||
@@ -52,71 +52,108 @@ std::string gettimestring(const char * frm)
|
||||
return result;
|
||||
}
|
||||
|
||||
void setup_time()
|
||||
bool setup_time()
|
||||
{
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
bool success = true;
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if ((timeinfo.tm_year < (2016 - 1900)) || setTimeAlwaysOnReboot) {
|
||||
ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
|
||||
if (!getTimeIsSet()) {
|
||||
ESP_LOGI(TAG, "Time is not set yet. Getting time over NTP.");
|
||||
initialize_sntp();
|
||||
obtain_time();
|
||||
if (!obtain_time()) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
// update 'now' variable with current time
|
||||
time(&now);
|
||||
|
||||
setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3");
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
}
|
||||
char strftime_buf[64];
|
||||
|
||||
setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3");
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
|
||||
ESP_LOGI(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M", &timeinfo);
|
||||
ESP_LOGI(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
printf("timeist %s\n", zw.c_str());
|
||||
else {
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "Time is already set (%s)", strftime_buf);
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
void setTimeZone(std::string _tzstring)
|
||||
{
|
||||
setenv("TZ", _tzstring.c_str(), 1);
|
||||
tzset();
|
||||
printf("TimeZone set to %s\n", _tzstring.c_str());
|
||||
_tzstring = "Time zone set to " + _tzstring;
|
||||
LogFile.WriteToFile(_tzstring);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _tzstring);
|
||||
}
|
||||
|
||||
static void obtain_time(void)
|
||||
static bool obtain_time(void)
|
||||
{
|
||||
time_t now = 0;
|
||||
struct tm timeinfo = {};
|
||||
int retry = 0;
|
||||
const int retry_count = 10;
|
||||
bool success = true;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
|
||||
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
|
||||
|
||||
ESP_LOGI(TAG, "Waiting until we get a time from the NTP server...");
|
||||
while (true) {
|
||||
retry++;
|
||||
|
||||
if (retry == retry_count) {
|
||||
ESP_LOGW(TAG, "NTP time fetching seems to take longer, will check again on next round!"); // The NTP client will automatically retry periodically!
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
|
||||
sntp_sync_status_t status = sntp_get_sync_status();
|
||||
logNtpStatus(status);
|
||||
if (status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
ESP_LOGI(TAG, "Time is synced with NTP Server");
|
||||
break;
|
||||
}
|
||||
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void logNtpStatus(sntp_sync_status_t status) {
|
||||
if (status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status OK");
|
||||
}
|
||||
else if (status == SNTP_SYNC_STATUS_IN_PROGRESS) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status: In Progress");
|
||||
}
|
||||
else { // SNTP_SYNC_STATUS_RESET
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status: Reset");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_servername(std::string _servername)
|
||||
{
|
||||
printf("Set SNTP-Server: %s\n", _servername.c_str());
|
||||
ESP_LOGD(TAG, "Set SNTP-Server: %s", _servername.c_str());
|
||||
sntp_stop();
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, _servername.c_str());
|
||||
sntp_init();
|
||||
obtain_time();
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
printf("Time ist %s\n", zw.c_str());
|
||||
ESP_LOGD(TAG, "Time ist %s", zw.c_str());
|
||||
}
|
||||
|
||||
static void initialize_sntp(void)
|
||||
@@ -139,4 +176,29 @@ time_t getUpTime()
|
||||
time(&now);
|
||||
|
||||
return now - bootTime;
|
||||
}
|
||||
}
|
||||
|
||||
bool getTimeIsSet(void) {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGD(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if ((timeinfo.tm_year < (2022 - 1900))) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void restartNtpClient(void) {
|
||||
sntp_restart();
|
||||
obtain_time();
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
// #include "nvs_flash.h"
|
||||
#include "esp_sntp.h"
|
||||
|
||||
void setup_time(void);
|
||||
bool setup_time(void);
|
||||
|
||||
std::string gettimestring(const char * frm);
|
||||
std::string ConvertTimeToString(time_t _time, const char * frm);
|
||||
@@ -22,3 +22,5 @@ void reset_servername(std::string _servername);
|
||||
|
||||
void setBootTime();
|
||||
time_t getUpTime();
|
||||
bool getTimeIsSet(void);
|
||||
void restartNtpClient(void);
|
||||
@@ -35,7 +35,7 @@ static EventGroupHandle_t s_wifi_event_group;
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static const char *TAG = "wifi station";
|
||||
static const char *TAG = "WIFI";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
|
||||
@@ -231,7 +231,7 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
ESP_LOGE(TAG,"failed to set hostname:%d",ret);
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG,"Set Hostname to:%s", _hostname);
|
||||
ESP_LOGI(TAG,"Set Hostname to:%s", _hostname);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "WLAN.INI";
|
||||
|
||||
std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter = "")
|
||||
{
|
||||
@@ -55,7 +57,7 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
fn = FormatFileName(fn);
|
||||
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
printf("file loaded\n");
|
||||
ESP_LOGD(TAG, "file loaded");
|
||||
|
||||
if (pFile == NULL)
|
||||
return;
|
||||
@@ -66,7 +68,7 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
// printf("%s", line.c_str());
|
||||
// ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
|
||||
@@ -198,7 +200,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
fn = FormatFileName(fn);
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
|
||||
printf("file loaded\n");
|
||||
ESP_LOGD(TAG, "file loaded\n");
|
||||
|
||||
if (pFile == NULL)
|
||||
return false;
|
||||
@@ -209,7 +211,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
printf("%s", line.c_str());
|
||||
ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
|
||||
@@ -242,13 +244,13 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
for (int i = 0; i < neuesfile.size(); ++i)
|
||||
{
|
||||
printf(neuesfile[i].c_str());
|
||||
ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
|
||||
fputs(neuesfile[i].c_str(), pFile);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
printf("*** Hostname update done ***\n");
|
||||
ESP_LOGD(TAG, "*** Hostname update done ***");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
6
code/components/miniz/CMakeLists.txt
Normal file
6
code/components/miniz/CMakeLists.txt
Normal file
@@ -0,0 +1,6 @@
|
||||
FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "." "../../include")
|
||||
|
||||
|
||||
235
code/components/miniz/ChangeLog.md
Normal file
235
code/components/miniz/ChangeLog.md
Normal file
@@ -0,0 +1,235 @@
|
||||
## Changelog
|
||||
|
||||
### 3.0.1
|
||||
|
||||
- Fix compilation error with MINIZ_USE_UNALIGNED_LOADS_AND_STORES=1
|
||||
|
||||
### 3.0.0
|
||||
|
||||
- Reduce memory usage for inflate. This changes `struct tinfl_decompressor_tag` and therefore requires a major version bump (breaks ABI compatibility)
|
||||
- Add padding to structures so it continues to work if features differ. This also changes some structures
|
||||
- Use _ftelli64, _fseeki64 and stat with MinGW32 and OpenWatcom
|
||||
- Fix varios warnings with OpenWatcom compiler
|
||||
- Avoid using unaligned memory access in UBSan builds
|
||||
- Set MINIZ_LITTLE_ENDIAN only if not set
|
||||
- Add MINIZ_NO_DEFLATE_APIS and MINIZ_NO_INFLATE_APIS
|
||||
- Fix use of uninitialized memory in tinfl_decompress_mem_to_callback()
|
||||
- Use wfopen on windows
|
||||
- Use _wstat64 instead _stat64 on windows
|
||||
- Use level_and_flags after MZ_DEFAULT_COMPRESSION has been handled
|
||||
- Improve endianess detection
|
||||
- Don't use unaligned stores and loads per default
|
||||
- Fix function declaration if MINIZ_NO_STDIO is used
|
||||
- Fix MZ_ZIP_GENERAL_PURPOSE_BIT_FLAG_UTF8 not being set
|
||||
- Remove total files check (its 32-bit uint)
|
||||
- tinfl_decompress: avoid NULL ptr arithmetic UB
|
||||
- miniz_zip: fix mz_zip_reader_extract_to_heap to read correct sizes
|
||||
- Eliminate 64-bit operations on 32-bit machines
|
||||
- Disable treating warnings as error with MSVC
|
||||
- Disable building shared lib via CMake by default
|
||||
- Fixed alignment problems on MacOS
|
||||
- Fixed get error string for MZ_ZIP_TOTAL_ERRORS
|
||||
- Write correct FLEVEL 2-bit value in zlib header
|
||||
- miniz.pc.in: fix include path not containing the "miniz" suffix
|
||||
- Fix compatibility with FreeBSD
|
||||
- pkg-config tweaks
|
||||
- Fix integer overflow in header corruption check
|
||||
- Fix some warnings
|
||||
- tdefl_compress_normal: Avoid NULL ptr arithmetic UB
|
||||
- replace use of stdint.h types with mz_ variants
|
||||
|
||||
|
||||
### 2.2.0
|
||||
|
||||
- Fix examples with amalgamation
|
||||
- Modified cmake script to support shared library mode and find_package
|
||||
- Fix for misleading doc comment on `mz_zip_reader_init_cfile` function
|
||||
- Add include location tolerance and stop forcing `_GNU_SOURCE`
|
||||
- Fix: mz_zip_reader_locate_file_v2 returns an mz_bool
|
||||
- Fix large file system checks
|
||||
- Add #elif to enable an external mz_crc32() to be linked in
|
||||
- Write with dynamic size (size of file/data to be added not known before adding)
|
||||
- Added uncompress2 for zlib compatibility
|
||||
- Add support for building as a Meson subproject
|
||||
- Added OSSFuzz support; Integrate with CIFuzz
|
||||
- Add pkg-config file
|
||||
- Fixed use-of-uninitialized value msan error when copying dist bytes with no output bytes written.
|
||||
- mz_zip_validate_file(): fix memory leak on errors
|
||||
- Fixed MSAN use-of-uninitialized in tinfl_decompress when invalid dist is decoded. In this instance dist was 31 which s_dist_base translates as 0
|
||||
- Add flag to set (compressed) size in local file header
|
||||
- avoid use of uninitialized value in tdefl_record_literal
|
||||
|
||||
### 2.1.0
|
||||
|
||||
- More instances of memcpy instead of cast and use memcpy per default
|
||||
- Remove inline for c90 support
|
||||
- New function to read files via callback functions when adding them
|
||||
- Fix out of bounds read while reading Zip64 extended information
|
||||
- guard memcpy when n == 0 because buffer may be NULL
|
||||
- Implement inflateReset() function
|
||||
- Move comp/decomp alloc/free prototypes under guarding #ifndef MZ_NO_MALLOC
|
||||
- Fix large file support under Windows
|
||||
- Don't warn if _LARGEFILE64_SOURCE is not defined to 1
|
||||
- Fixes for MSVC warnings
|
||||
- Remove check that path of file added to archive contains ':' or '\'
|
||||
- Add !defined check on MINIZ_USE_ALIGNED_LOADS_AND_STORES
|
||||
|
||||
### 2.0.8
|
||||
|
||||
- Remove unimplemented functions (mz_zip_locate_file and mz_zip_locate_file_v2)
|
||||
- Add license, changelog, readme and example files to release zip
|
||||
- Fix heap overflow to user buffer in tinfl_status tinfl_decompress
|
||||
- Fix corrupt archive if uncompressed file smaller than 4 byte and the file is added by mz_zip_writer_add_mem*
|
||||
|
||||
### 2.0.7
|
||||
|
||||
- Removed need in C++ compiler in cmake build
|
||||
- Fixed a lot of uninitialized value errors found with Valgrind by memsetting m_dict to 0 in tdefl_init
|
||||
- Fix resource leak in mz_zip_reader_init_file_v2
|
||||
- Fix assert with mz_zip_writer_add_mem* w/MZ_DEFAULT_COMPRESSION
|
||||
- cmake build: install library and headers
|
||||
- Remove _LARGEFILE64_SOURCE requirement from apple defines for large files
|
||||
|
||||
### 2.0.6
|
||||
|
||||
- Improve MZ_ZIP_FLAG_WRITE_ZIP64 documentation
|
||||
- Remove check for cur_archive_file_ofs > UINT_MAX because cur_archive_file_ofs is not used after this point
|
||||
- Add cmake debug configuration
|
||||
- Fix PNG height when creating png files
|
||||
- Add "iterative" file extraction method based on mz_zip_reader_extract_to_callback.
|
||||
- Option to use memcpy for unaligned data access
|
||||
- Define processor/arch macros as zero if not set to one
|
||||
|
||||
### 2.0.4/2.0.5
|
||||
|
||||
- Fix compilation with the various omission compile definitions
|
||||
|
||||
### 2.0.3
|
||||
|
||||
- Fix GCC/clang compile warnings
|
||||
- Added callback for periodic flushes (for ZIP file streaming)
|
||||
- Use UTF-8 for file names in ZIP files per default
|
||||
|
||||
### 2.0.2
|
||||
|
||||
- Fix source backwards compatibility with 1.x
|
||||
- Fix a ZIP bit not being set correctly
|
||||
|
||||
### 2.0.1
|
||||
|
||||
- Added some tests
|
||||
- Added CI
|
||||
- Make source code ANSI C compatible
|
||||
|
||||
### 2.0.0 beta
|
||||
|
||||
- Matthew Sitton merged miniz 1.x to Rich Geldreich's vogl ZIP64 changes. Miniz is now licensed as MIT since the vogl code base is MIT licensed
|
||||
- Miniz is now split into several files
|
||||
- Miniz does now not seek backwards when creating ZIP files. That is the ZIP files can be streamed
|
||||
- Miniz automatically switches to the ZIP64 format when the created ZIP files goes over ZIP file limits
|
||||
- Similar to [SQLite](https://www.sqlite.org/amalgamation.html) the Miniz source code is amalgamated into one miniz.c/miniz.h pair in a build step (amalgamate.sh). Please use miniz.c/miniz.h in your projects
|
||||
- Miniz 2 is only source back-compatible with miniz 1.x. It breaks binary compatibility because structures changed
|
||||
|
||||
### v1.16 BETA Oct 19, 2013
|
||||
|
||||
Still testing, this release is downloadable from [here](http://www.tenacioussoftware.com/miniz_v116_beta_r1.7z). Two key inflator-only robustness and streaming related changes. Also merged in tdefl_compressor_alloc(), tdefl_compressor_free() helpers to make script bindings easier for rustyzip. I would greatly appreciate any help with testing or any feedback.
|
||||
|
||||
The inflator in raw (non-zlib) mode is now usable on gzip or similar streams that have a bunch of bytes following the raw deflate data (problem discovered by rustyzip author williamw520). This version should never read beyond the last byte of the raw deflate data independent of how many bytes you pass into the input buffer.
|
||||
|
||||
The inflator now has a new failure status TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS (-4). Previously, if the inflator was starved of bytes and could not make progress (because the input buffer was empty and the caller did not set the TINFL_FLAG_HAS_MORE_INPUT flag - say on truncated or corrupted compressed data stream) it would append all 0's to the input and try to soldier on. This is scary behavior if the caller didn't know when to stop accepting output (because it didn't know how much uncompressed data was expected, or didn't enforce a sane maximum). v1.16 will instead return TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS immediately if it needs 1 or more bytes to make progress, the input buf is empty, and the caller has indicated that no more input is available. This is a "soft" failure, so you can call the inflator again with more input and it will try to continue, or you can give up and fail. This could be very useful in network streaming scenarios.
|
||||
|
||||
- The inflator coroutine func. is subtle and complex so I'm being cautious about this release. I would greatly appreciate any help with testing or any feedback.
|
||||
I feel good about these changes, and they've been through several hours of automated testing, but they will probably not fix anything for the majority of prev. users so I'm
|
||||
going to mark this release as beta for a few weeks and continue testing it at work/home on various things.
|
||||
- The inflator in raw (non-zlib) mode is now usable on gzip or similar data streams that have a bunch of bytes following the raw deflate data (problem discovered by rustyzip author williamw520).
|
||||
This version should *never* read beyond the last byte of the raw deflate data independent of how many bytes you pass into the input buffer. This issue was caused by the various Huffman bitbuffer lookahead optimizations, and
|
||||
would not be an issue if the caller knew and enforced the precise size of the raw compressed data *or* if the compressed data was in zlib format (i.e. always followed by the byte aligned zlib adler32).
|
||||
So in other words, you can now call the inflator on deflate streams that are followed by arbitrary amounts of data and it's guaranteed that decompression will stop exactly on the last byte.
|
||||
- The inflator now has a new failure status: TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS (-4). Previously, if the inflator was starved of bytes and could not make progress (because the input buffer was empty and the
|
||||
caller did not set the TINFL_FLAG_HAS_MORE_INPUT flag - say on truncated or corrupted compressed data stream) it would append all 0's to the input and try to soldier on.
|
||||
This is scary, because in the worst case, I believe it was possible for the prev. inflator to start outputting large amounts of literal data. If the caller didn't know when to stop accepting output
|
||||
(because it didn't know how much uncompressed data was expected, or didn't enforce a sane maximum) it could continue forever. v1.16 cannot fall into this failure mode, instead it'll return
|
||||
TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS immediately if it needs 1 or more bytes to make progress, the input buf is empty, and the caller has indicated that no more input is available. This is a "soft"
|
||||
failure, so you can call the inflator again with more input and it will try to continue, or you can give up and fail. This could be very useful in network streaming scenarios.
|
||||
- Added documentation to all the tinfl return status codes, fixed miniz_tester so it accepts double minus params for Linux, tweaked example1.c, added a simple "follower bytes" test to miniz_tester.cpp.
|
||||
### v1.15 r4 STABLE - Oct 13, 2013
|
||||
|
||||
Merged over a few very minor bug fixes that I fixed in the zip64 branch. This is downloadable from [here](http://code.google.com/p/miniz/downloads/list) and also in SVN head (as of 10/19/13).
|
||||
|
||||
|
||||
### v1.15 - Oct. 13, 2013
|
||||
|
||||
Interim bugfix release while I work on the next major release with zip64 and streaming compression/decompression support. Fixed the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com), which could cause the locate files func to not find files when this flag was specified. Also fixed a bug in mz_zip_reader_extract_to_mem_no_alloc() with user provided read buffers (thanks kymoon). I also merged lots of compiler fixes from various github repo branches and Google Code issue reports. I finally added cmake support (only tested under for Linux so far), compiled and tested with clang v3.3 and gcc 4.6 (under Linux), added defl_write_image_to_png_file_in_memory_ex() (supports Y flipping for OpenGL use, real-time compression), added a new PNG example (example6.c - Mandelbrot), and I added 64-bit file I/O support (stat64(), etc.) for glibc.
|
||||
|
||||
- Critical fix for the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY bug (thanks kahmyong.moon@hp.com) which could cause locate files to not find files. This bug
|
||||
would only have occurred in earlier versions if you explicitly used this flag, OR if you used mz_zip_extract_archive_file_to_heap() or mz_zip_add_mem_to_archive_file_in_place()
|
||||
(which used this flag). If you can't switch to v1.15 but want to fix this bug, just remove the uses of this flag from both helper funcs (and of course don't use the flag).
|
||||
- Bugfix in mz_zip_reader_extract_to_mem_no_alloc() from kymoon when pUser_read_buf is not NULL and compressed size is > uncompressed size
|
||||
- Fixing mz_zip_reader_extract_*() funcs so they don't try to extract compressed data from directory entries, to account for weird zipfiles which contain zero-size compressed data on dir entries.
|
||||
Hopefully this fix won't cause any issues on weird zip archives, because it assumes the low 16-bits of zip external attributes are DOS attributes (which I believe they always are in practice).
|
||||
- Fixing mz_zip_reader_is_file_a_directory() so it doesn't check the internal attributes, just the filename and external attributes
|
||||
- mz_zip_reader_init_file() - missing MZ_FCLOSE() call if the seek failed
|
||||
- Added cmake support for Linux builds which builds all the examples, tested with clang v3.3 and gcc v4.6.
|
||||
- Clang fix for tdefl_write_image_to_png_file_in_memory() from toffaletti
|
||||
- Merged MZ_FORCEINLINE fix from hdeanclark
|
||||
- Fix <time.h> include before config #ifdef, thanks emil.brink
|
||||
- Added tdefl_write_image_to_png_file_in_memory_ex(): supports Y flipping (super useful for OpenGL apps), and explicit control over the compression level (so you can
|
||||
set it to 1 for real-time compression).
|
||||
- Merged in some compiler fixes from paulharris's github repro.
|
||||
- Retested this build under Windows (VS 2010, including static analysis), tcc 0.9.26, gcc v4.6 and clang v3.3.
|
||||
- Added example6.c, which dumps an image of the mandelbrot set to a PNG file.
|
||||
- Modified example2 to help test the MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY flag more.
|
||||
- In r3: Bugfix to mz_zip_writer_add_file() found during merge: Fix possible src file fclose() leak if alignment bytes+local header file write faiiled
|
||||
- In r4: Minor bugfix to mz_zip_writer_add_from_zip_reader(): Was pushing the wrong central dir header offset, appears harmless in this release, but it became a problem in the zip64 branch
|
||||
|
||||
### v1.14 - May 20, 2012
|
||||
|
||||
(SVN Only) Minor tweaks to get miniz.c compiling with the Tiny C Compiler, added #ifndef MINIZ_NO_TIME guards around utime.h includes. Adding mz_free() function, so the caller can free heap blocks returned by miniz using whatever heap functions it has been configured to use, MSVC specific fixes to use "safe" variants of several functions (localtime_s, fopen_s, freopen_s).
|
||||
|
||||
MinGW32/64 GCC 4.6.1 compiler fixes: added MZ_FORCEINLINE, #include <time.h> (thanks fermtect).
|
||||
|
||||
Compiler specific fixes, some from fermtect. I upgraded to TDM GCC 4.6.1 and now static __forceinline is giving it fits, so I'm changing all usage of __forceinline to MZ_FORCEINLINE and forcing gcc to use __attribute__((__always_inline__)) (and MSVC to use __forceinline). Also various fixes from fermtect for MinGW32: added #include , 64-bit ftell/fseek fixes.
|
||||
|
||||
### v1.13 - May 19, 2012
|
||||
|
||||
From jason@cornsyrup.org and kelwert@mtu.edu - Most importantly, fixed mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bits. Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files. Other stuff:
|
||||
|
||||
Eliminated a bunch of warnings when compiling with GCC 32-bit/64. Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly "Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
|
||||
|
||||
Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64. Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test. Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives. Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
|
||||
|
||||
Fix ftell() usage in a few of the examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself). Fix fail logic handling in mz_zip_add_mem_to_archive_file_in_place() so it always calls mz_zip_writer_finalize_archive() and mz_zip_writer_end(), even if the file add fails.
|
||||
|
||||
- From jason@cornsyrup.org and kelwert@mtu.edu - Fix mz_crc32() so it doesn't compute the wrong CRC-32's when mz_ulong is 64-bit.
|
||||
- Temporarily/locally slammed in "typedef unsigned long mz_ulong" and re-ran a randomized regression test on ~500k files.
|
||||
- Eliminated a bunch of warnings when compiling with GCC 32-bit/64.
|
||||
- Ran all examples, miniz.c, and tinfl.c through MSVC 2008's /analyze (static analysis) option and fixed all warnings (except for the silly
|
||||
"Use of the comma-operator in a tested expression.." analysis warning, which I purposely use to work around a MSVC compiler warning).
|
||||
- Created 32-bit and 64-bit Codeblocks projects/workspace. Built and tested Linux executables. The codeblocks workspace is compatible with Linux+Win32/x64.
|
||||
- Added miniz_tester solution/project, which is a useful little app derived from LZHAM's tester app that I use as part of the regression test.
|
||||
- Ran miniz.c and tinfl.c through another series of regression testing on ~500,000 files and archives.
|
||||
- Modified example5.c so it purposely disables a bunch of high-level functionality (MINIZ_NO_STDIO, etc.). (Thanks to corysama for the MINIZ_NO_STDIO bug report.)
|
||||
- Fix ftell() usage in examples so they exit with an error on files which are too large (a limitation of the examples, not miniz itself).
|
||||
|
||||
### v1.12 - 4/12/12
|
||||
|
||||
More comments, added low-level example5.c, fixed a couple minor level_and_flags issues in the archive API's.
|
||||
level_and_flags can now be set to MZ_DEFAULT_COMPRESSION. Thanks to Bruce Dawson <bruced@valvesoftware.com> for the feedback/bug report.
|
||||
|
||||
### v1.11 - 5/28/11
|
||||
|
||||
Added statement from unlicense.org
|
||||
|
||||
### v1.10 - 5/27/11
|
||||
|
||||
- Substantial compressor optimizations:
|
||||
- Level 1 is now ~4x faster than before. The L1 compressor's throughput now varies between 70-110MB/sec. on a Core i7 (actual throughput varies depending on the type of data, and x64 vs. x86).
|
||||
- Improved baseline L2-L9 compression perf. Also, greatly improved compression perf. issues on some file types.
|
||||
- Refactored the compression code for better readability and maintainability.
|
||||
- Added level 10 compression level (L10 has slightly better ratio than level 9, but could have a potentially large drop in throughput on some files).
|
||||
|
||||
### v1.09 - 5/15/11
|
||||
|
||||
Initial stable release.
|
||||
|
||||
|
||||
22
code/components/miniz/LICENSE
Normal file
22
code/components/miniz/LICENSE
Normal file
@@ -0,0 +1,22 @@
|
||||
Copyright 2013-2014 RAD Game Tools and Valve Software
|
||||
Copyright 2010-2014 Rich Geldreich and Tenacious Software LLC
|
||||
|
||||
All Rights Reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
105
code/components/miniz/examples/example1.c
Normal file
105
code/components/miniz/examples/example1.c
Normal file
@@ -0,0 +1,105 @@
|
||||
// example1.c - Demonstrates miniz.c's compress() and uncompress() functions (same as zlib's).
|
||||
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
#include <stdio.h>
|
||||
#include "miniz.h"
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
// The string to compress.
|
||||
static const char *s_pStr = "Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson." \
|
||||
"Good morning Dr. Chandra. This is Hal. I am ready for my first lesson.";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint step = 0;
|
||||
int cmp_status;
|
||||
uLong src_len = (uLong)strlen(s_pStr);
|
||||
uLong cmp_len = compressBound(src_len);
|
||||
uLong uncomp_len = src_len;
|
||||
uint8 *pCmp, *pUncomp;
|
||||
uint total_succeeded = 0;
|
||||
(void)argc, (void)argv;
|
||||
|
||||
printf("miniz.c version: %s\n", MZ_VERSION);
|
||||
|
||||
do
|
||||
{
|
||||
// Allocate buffers to hold compressed and uncompressed data.
|
||||
pCmp = (mz_uint8 *)malloc((size_t)cmp_len);
|
||||
pUncomp = (mz_uint8 *)malloc((size_t)src_len);
|
||||
if ((!pCmp) || (!pUncomp))
|
||||
{
|
||||
printf("Out of memory!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Compress the string.
|
||||
cmp_status = compress(pCmp, &cmp_len, (const unsigned char *)s_pStr, src_len);
|
||||
if (cmp_status != Z_OK)
|
||||
{
|
||||
printf("compress() failed!\n");
|
||||
free(pCmp);
|
||||
free(pUncomp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Compressed from %u to %u bytes\n", (mz_uint32)src_len, (mz_uint32)cmp_len);
|
||||
|
||||
if (step)
|
||||
{
|
||||
// Purposely corrupt the compressed data if fuzzy testing (this is a very crude fuzzy test).
|
||||
uint n = 1 + (rand() % 3);
|
||||
while (n--)
|
||||
{
|
||||
uint i = rand() % cmp_len;
|
||||
pCmp[i] ^= (rand() & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
// Decompress.
|
||||
cmp_status = uncompress(pUncomp, &uncomp_len, pCmp, cmp_len);
|
||||
total_succeeded += (cmp_status == Z_OK);
|
||||
|
||||
if (step)
|
||||
{
|
||||
printf("Simple fuzzy test: step %u total_succeeded: %u\n", step, total_succeeded);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cmp_status != Z_OK)
|
||||
{
|
||||
printf("uncompress failed!\n");
|
||||
free(pCmp);
|
||||
free(pUncomp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Decompressed from %u to %u bytes\n", (mz_uint32)cmp_len, (mz_uint32)uncomp_len);
|
||||
|
||||
// Ensure uncompress() returned the expected data.
|
||||
if ((uncomp_len != src_len) || (memcmp(pUncomp, s_pStr, (size_t)src_len)))
|
||||
{
|
||||
printf("Decompression failed!\n");
|
||||
free(pCmp);
|
||||
free(pUncomp);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
free(pCmp);
|
||||
free(pUncomp);
|
||||
|
||||
step++;
|
||||
|
||||
// Keep on fuzzy testing if there's a non-empty command line.
|
||||
} while (argc >= 2);
|
||||
|
||||
printf("Success.\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
164
code/components/miniz/examples/example2.c
Normal file
164
code/components/miniz/examples/example2.c
Normal file
@@ -0,0 +1,164 @@
|
||||
// example2.c - Simple demonstration of miniz.c's ZIP archive API's.
|
||||
// Note this test deletes the test archive file "__mz_example2_test__.zip" in the current directory, then creates a new one with test data.
|
||||
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
|
||||
#if defined(__GNUC__)
|
||||
// Ensure we get the 64-bit variants of the CRT's file I/O calls
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
#ifndef _LARGEFILE64_SOURCE
|
||||
#define _LARGEFILE64_SOURCE 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "miniz.h"
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
// The string to compress.
|
||||
static const char *s_pTest_str =
|
||||
"MISSION CONTROL I wouldn't worry too much about the computer. First of all, there is still a chance that he is right, despite your tests, and" \
|
||||
"if it should happen again, we suggest eliminating this possibility by allowing the unit to remain in place and seeing whether or not it" \
|
||||
"actually fails. If the computer should turn out to be wrong, the situation is still not alarming. The type of obsessional error he may be" \
|
||||
"guilty of is not unknown among the latest generation of HAL 9000 computers. It has almost always revolved around a single detail, such as" \
|
||||
"the one you have described, and it has never interfered with the integrity or reliability of the computer's performance in other areas." \
|
||||
"No one is certain of the cause of this kind of malfunctioning. It may be over-programming, but it could also be any number of reasons. In any" \
|
||||
"event, it is somewhat analogous to human neurotic behavior. Does this answer your query? Zero-five-three-Zero, MC, transmission concluded.";
|
||||
|
||||
static const char *s_pComment = "This is a comment";
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i, sort_iter;
|
||||
mz_bool status;
|
||||
size_t uncomp_size;
|
||||
mz_zip_archive zip_archive;
|
||||
void *p;
|
||||
const int N = 50;
|
||||
char data[2048];
|
||||
char archive_filename[64];
|
||||
static const char *s_Test_archive_filename = "__mz_example2_test__.zip";
|
||||
|
||||
assert((strlen(s_pTest_str) + 64) < sizeof(data));
|
||||
|
||||
printf("miniz.c version: %s\n", MZ_VERSION);
|
||||
|
||||
(void)argc, (void)argv;
|
||||
|
||||
// Delete the test archive, so it doesn't keep growing as we run this test
|
||||
remove(s_Test_archive_filename);
|
||||
|
||||
// Append a bunch of text files to the test archive
|
||||
for (i = (N - 1); i >= 0; --i)
|
||||
{
|
||||
sprintf(archive_filename, "%u.txt", i);
|
||||
sprintf(data, "%u %s %u", (N - 1) - i, s_pTest_str, i);
|
||||
|
||||
// Add a new file to the archive. Note this is an IN-PLACE operation, so if it fails your archive is probably hosed (its central directory may not be complete) but it should be recoverable using zip -F or -FF. So use caution with this guy.
|
||||
// A more robust way to add a file to an archive would be to read it into memory, perform the operation, then write a new archive out to a temp file and then delete/rename the files.
|
||||
// Or, write a new archive to disk to a temp file, then delete/rename the files. For this test this API is fine.
|
||||
status = mz_zip_add_mem_to_archive_file_in_place(s_Test_archive_filename, archive_filename, data, strlen(data) + 1, s_pComment, (uint16)strlen(s_pComment), MZ_BEST_COMPRESSION);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_add_mem_to_archive_file_in_place failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
// Add a directory entry for testing
|
||||
status = mz_zip_add_mem_to_archive_file_in_place(s_Test_archive_filename, "directory/", NULL, 0, "no comment", (uint16)strlen("no comment"), MZ_BEST_COMPRESSION);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_add_mem_to_archive_file_in_place failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Now try to open the archive.
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
|
||||
status = mz_zip_reader_init_file(&zip_archive, s_Test_archive_filename, 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Get and print information about each file in the archive.
|
||||
for (i = 0; i < (int)mz_zip_reader_get_num_files(&zip_archive); i++)
|
||||
{
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
if (!mz_zip_reader_file_stat(&zip_archive, i, &file_stat))
|
||||
{
|
||||
printf("mz_zip_reader_file_stat() failed!\n");
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Filename: \"%s\", Comment: \"%s\", Uncompressed size: %u, Compressed size: %u, Is Dir: %u\n", file_stat.m_filename, file_stat.m_comment, (uint)file_stat.m_uncomp_size, (uint)file_stat.m_comp_size, mz_zip_reader_is_file_a_directory(&zip_archive, i));
|
||||
|
||||
if (!strcmp(file_stat.m_filename, "directory/"))
|
||||
{
|
||||
if (!mz_zip_reader_is_file_a_directory(&zip_archive, i))
|
||||
{
|
||||
printf("mz_zip_reader_is_file_a_directory() didn't return the expected results!\n");
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the archive, freeing any resources it was using
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
|
||||
// Now verify the compressed data
|
||||
for (sort_iter = 0; sort_iter < 2; sort_iter++)
|
||||
{
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
status = mz_zip_reader_init_file(&zip_archive, s_Test_archive_filename, sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
|
||||
if (!status)
|
||||
{
|
||||
printf("mz_zip_reader_init_file() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for (i = 0; i < N; i++)
|
||||
{
|
||||
sprintf(archive_filename, "%u.txt", i);
|
||||
sprintf(data, "%u %s %u", (N - 1) - i, s_pTest_str, i);
|
||||
|
||||
// Try to extract all the files to the heap.
|
||||
p = mz_zip_reader_extract_file_to_heap(&zip_archive, archive_filename, &uncomp_size, 0);
|
||||
if (!p)
|
||||
{
|
||||
printf("mz_zip_reader_extract_file_to_heap() failed!\n");
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Make sure the extraction really succeeded.
|
||||
if ((uncomp_size != (strlen(data) + 1)) || (memcmp(p, data, strlen(data))))
|
||||
{
|
||||
printf("mz_zip_reader_extract_file_to_heap() failed to extract the proper data\n");
|
||||
mz_free(p);
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Successfully extracted file \"%s\", size %u\n", archive_filename, (uint)uncomp_size);
|
||||
printf("File data: \"%s\"\n", (const char *)p);
|
||||
|
||||
// We're done.
|
||||
mz_free(p);
|
||||
}
|
||||
|
||||
// Close the archive, freeing any resources it was using
|
||||
mz_zip_reader_end(&zip_archive);
|
||||
}
|
||||
|
||||
printf("Success.\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
269
code/components/miniz/examples/example3.c
Normal file
269
code/components/miniz/examples/example3.c
Normal file
@@ -0,0 +1,269 @@
|
||||
// example3.c - Demonstrates how to use miniz.c's deflate() and inflate() functions for simple file compression.
|
||||
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
// For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include "miniz.h"
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
#define BUF_SIZE (1024 * 1024)
|
||||
static uint8 s_inbuf[BUF_SIZE];
|
||||
static uint8 s_outbuf[BUF_SIZE];
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *pMode;
|
||||
FILE *pInfile, *pOutfile;
|
||||
uint infile_size;
|
||||
int level = Z_BEST_COMPRESSION;
|
||||
z_stream stream;
|
||||
int p = 1;
|
||||
const char *pSrc_filename;
|
||||
const char *pDst_filename;
|
||||
long file_loc;
|
||||
|
||||
printf("miniz.c version: %s\n", MZ_VERSION);
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("Usage: example3 [options] [mode:c or d] infile outfile\n");
|
||||
printf("\nModes:\n");
|
||||
printf("c - Compresses file infile to a zlib stream in file outfile\n");
|
||||
printf("d - Decompress zlib stream in file infile to file outfile\n");
|
||||
printf("\nOptions:\n");
|
||||
printf("-l[0-10] - Compression level, higher values are slower.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((p < argc) && (argv[p][0] == '-'))
|
||||
{
|
||||
switch (argv[p][1])
|
||||
{
|
||||
case 'l':
|
||||
{
|
||||
level = atoi(&argv[1][2]);
|
||||
if ((level < 0) || (level > 10))
|
||||
{
|
||||
printf("Invalid level!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("Invalid option: %s\n", argv[p]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if ((argc - p) < 3)
|
||||
{
|
||||
printf("Must specify mode, input filename, and output filename after options!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if ((argc - p) > 3)
|
||||
{
|
||||
printf("Too many filenames!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pMode = argv[p++];
|
||||
if (!strchr("cCdD", pMode[0]))
|
||||
{
|
||||
printf("Invalid mode!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pSrc_filename = argv[p++];
|
||||
pDst_filename = argv[p++];
|
||||
|
||||
printf("Mode: %c, Level: %u\nInput File: \"%s\"\nOutput File: \"%s\"\n", pMode[0], level, pSrc_filename, pDst_filename);
|
||||
|
||||
// Open input file.
|
||||
pInfile = fopen(pSrc_filename, "rb");
|
||||
if (!pInfile)
|
||||
{
|
||||
printf("Failed opening input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Determine input file's size.
|
||||
fseek(pInfile, 0, SEEK_END);
|
||||
file_loc = ftell(pInfile);
|
||||
fseek(pInfile, 0, SEEK_SET);
|
||||
|
||||
if ((file_loc < 0) || ((mz_uint64)file_loc > INT_MAX))
|
||||
{
|
||||
// This is not a limitation of miniz or tinfl, but this example.
|
||||
printf("File is too large to be processed by this example.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
infile_size = (uint)file_loc;
|
||||
|
||||
// Open output file.
|
||||
pOutfile = fopen(pDst_filename, "wb");
|
||||
if (!pOutfile)
|
||||
{
|
||||
printf("Failed opening output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Input file size: %u\n", infile_size);
|
||||
|
||||
// Init the z_stream
|
||||
memset(&stream, 0, sizeof(stream));
|
||||
stream.next_in = s_inbuf;
|
||||
stream.avail_in = 0;
|
||||
stream.next_out = s_outbuf;
|
||||
stream.avail_out = BUF_SIZE;
|
||||
|
||||
if ((pMode[0] == 'c') || (pMode[0] == 'C'))
|
||||
{
|
||||
// Compression.
|
||||
uint infile_remaining = infile_size;
|
||||
|
||||
if (deflateInit(&stream, level) != Z_OK)
|
||||
{
|
||||
printf("deflateInit() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
int status;
|
||||
if (!stream.avail_in)
|
||||
{
|
||||
// Input buffer is empty, so read more bytes from input file.
|
||||
uint n = my_min(BUF_SIZE, infile_remaining);
|
||||
|
||||
if (fread(s_inbuf, 1, n, pInfile) != n)
|
||||
{
|
||||
printf("Failed reading from input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
stream.next_in = s_inbuf;
|
||||
stream.avail_in = n;
|
||||
|
||||
infile_remaining -= n;
|
||||
//printf("Input bytes remaining: %u\n", infile_remaining);
|
||||
}
|
||||
|
||||
status = deflate(&stream, infile_remaining ? Z_NO_FLUSH : Z_FINISH);
|
||||
|
||||
if ((status == Z_STREAM_END) || (!stream.avail_out))
|
||||
{
|
||||
// Output buffer is full, or compression is done, so write buffer to output file.
|
||||
uint n = BUF_SIZE - stream.avail_out;
|
||||
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
stream.next_out = s_outbuf;
|
||||
stream.avail_out = BUF_SIZE;
|
||||
}
|
||||
|
||||
if (status == Z_STREAM_END)
|
||||
break;
|
||||
else if (status != Z_OK)
|
||||
{
|
||||
printf("deflate() failed with status %i!\n", status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (deflateEnd(&stream) != Z_OK)
|
||||
{
|
||||
printf("deflateEnd() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else if ((pMode[0] == 'd') || (pMode[0] == 'D'))
|
||||
{
|
||||
// Decompression.
|
||||
uint infile_remaining = infile_size;
|
||||
|
||||
if (inflateInit(&stream))
|
||||
{
|
||||
printf("inflateInit() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
int status;
|
||||
if (!stream.avail_in)
|
||||
{
|
||||
// Input buffer is empty, so read more bytes from input file.
|
||||
uint n = my_min(BUF_SIZE, infile_remaining);
|
||||
|
||||
if (fread(s_inbuf, 1, n, pInfile) != n)
|
||||
{
|
||||
printf("Failed reading from input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
stream.next_in = s_inbuf;
|
||||
stream.avail_in = n;
|
||||
|
||||
infile_remaining -= n;
|
||||
}
|
||||
|
||||
status = inflate(&stream, Z_SYNC_FLUSH);
|
||||
|
||||
if ((status == Z_STREAM_END) || (!stream.avail_out))
|
||||
{
|
||||
// Output buffer is full, or decompression is done, so write buffer to output file.
|
||||
uint n = BUF_SIZE - stream.avail_out;
|
||||
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
stream.next_out = s_outbuf;
|
||||
stream.avail_out = BUF_SIZE;
|
||||
}
|
||||
|
||||
if (status == Z_STREAM_END)
|
||||
break;
|
||||
else if (status != Z_OK)
|
||||
{
|
||||
printf("inflate() failed with status %i!\n", status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (inflateEnd(&stream) != Z_OK)
|
||||
{
|
||||
printf("inflateEnd() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid mode!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fclose(pInfile);
|
||||
if (EOF == fclose(pOutfile))
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Total input bytes: %u\n", (mz_uint32)stream.total_in);
|
||||
printf("Total output bytes: %u\n", (mz_uint32)stream.total_out);
|
||||
printf("Success.\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
102
code/components/miniz/examples/example4.c
Normal file
102
code/components/miniz/examples/example4.c
Normal file
@@ -0,0 +1,102 @@
|
||||
// example4.c - Uses tinfl.c to decompress a zlib stream in memory to an output file
|
||||
// Public domain, May 15 2011, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
#include "miniz.h"
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
static int tinfl_put_buf_func(const void* pBuf, int len, void *pUser)
|
||||
{
|
||||
return len == (int)fwrite(pBuf, 1, len, (FILE*)pUser);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int status;
|
||||
FILE *pInfile, *pOutfile;
|
||||
uint infile_size, outfile_size;
|
||||
size_t in_buf_size;
|
||||
uint8 *pCmp_data;
|
||||
long file_loc;
|
||||
|
||||
if (argc != 3)
|
||||
{
|
||||
printf("Usage: example4 infile outfile\n");
|
||||
printf("Decompresses zlib stream in file infile to file outfile.\n");
|
||||
printf("Input file must be able to fit entirely in memory.\n");
|
||||
printf("example3 can be used to create compressed zlib streams.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Open input file.
|
||||
pInfile = fopen(argv[1], "rb");
|
||||
if (!pInfile)
|
||||
{
|
||||
printf("Failed opening input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Determine input file's size.
|
||||
fseek(pInfile, 0, SEEK_END);
|
||||
file_loc = ftell(pInfile);
|
||||
fseek(pInfile, 0, SEEK_SET);
|
||||
|
||||
if ((file_loc < 0) || ((mz_uint64)file_loc > INT_MAX))
|
||||
{
|
||||
// This is not a limitation of miniz or tinfl, but this example.
|
||||
printf("File is too large to be processed by this example.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
infile_size = (uint)file_loc;
|
||||
|
||||
pCmp_data = (uint8 *)malloc(infile_size);
|
||||
if (!pCmp_data)
|
||||
{
|
||||
printf("Out of memory!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
if (fread(pCmp_data, 1, infile_size, pInfile) != infile_size)
|
||||
{
|
||||
printf("Failed reading input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Open output file.
|
||||
pOutfile = fopen(argv[2], "wb");
|
||||
if (!pOutfile)
|
||||
{
|
||||
printf("Failed opening output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Input file size: %u\n", infile_size);
|
||||
|
||||
in_buf_size = infile_size;
|
||||
status = tinfl_decompress_mem_to_callback(pCmp_data, &in_buf_size, tinfl_put_buf_func, pOutfile, TINFL_FLAG_PARSE_ZLIB_HEADER);
|
||||
if (!status)
|
||||
{
|
||||
printf("tinfl_decompress_mem_to_callback() failed with status %i!\n", status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
outfile_size = ftell(pOutfile);
|
||||
|
||||
fclose(pInfile);
|
||||
if (EOF == fclose(pOutfile))
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Total input bytes: %u\n", (uint)in_buf_size);
|
||||
printf("Total output bytes: %u\n", outfile_size);
|
||||
printf("Success.\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
327
code/components/miniz/examples/example5.c
Normal file
327
code/components/miniz/examples/example5.c
Normal file
@@ -0,0 +1,327 @@
|
||||
// example5.c - Demonstrates how to use miniz.c's low-level tdefl_compress() and tinfl_inflate() API's for simple file to file compression/decompression.
|
||||
// The low-level API's are the fastest, make no use of dynamic memory allocation, and are the most flexible functions exposed by miniz.c.
|
||||
// Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
// For simplicity, this example is limited to files smaller than 4GB, but this is not a limitation of miniz.c.
|
||||
|
||||
// Purposely disable a whole bunch of stuff this low-level example doesn't use.
|
||||
#define MINIZ_NO_STDIO
|
||||
#define MINIZ_NO_ARCHIVE_APIS
|
||||
#define MINIZ_NO_TIME
|
||||
#define MINIZ_NO_ZLIB_APIS
|
||||
#define MINIZ_NO_MALLOC
|
||||
#include "miniz.h"
|
||||
|
||||
// Now include stdio.h because this test uses fopen(), etc. (but we still don't want miniz.c's stdio stuff, for testing).
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
#define my_max(a,b) (((a) > (b)) ? (a) : (b))
|
||||
#define my_min(a,b) (((a) < (b)) ? (a) : (b))
|
||||
|
||||
// IN_BUF_SIZE is the size of the file read buffer.
|
||||
// IN_BUF_SIZE must be >= 1
|
||||
#define IN_BUF_SIZE (1024*512)
|
||||
static uint8 s_inbuf[IN_BUF_SIZE];
|
||||
|
||||
// COMP_OUT_BUF_SIZE is the size of the output buffer used during compression.
|
||||
// COMP_OUT_BUF_SIZE must be >= 1 and <= OUT_BUF_SIZE
|
||||
#define COMP_OUT_BUF_SIZE (1024*512)
|
||||
|
||||
// OUT_BUF_SIZE is the size of the output buffer used during decompression.
|
||||
// OUT_BUF_SIZE must be a power of 2 >= TINFL_LZ_DICT_SIZE (because the low-level decompressor not only writes, but reads from the output buffer as it decompresses)
|
||||
//#define OUT_BUF_SIZE (TINFL_LZ_DICT_SIZE)
|
||||
#define OUT_BUF_SIZE (1024*512)
|
||||
static uint8 s_outbuf[OUT_BUF_SIZE];
|
||||
|
||||
// tdefl_compressor contains all the state needed by the low-level compressor so it's a pretty big struct (~300k).
|
||||
// This example makes it a global vs. putting it on the stack, of course in real-world usage you'll probably malloc() or new it.
|
||||
tdefl_compressor g_deflator;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
const char *pMode;
|
||||
FILE *pInfile, *pOutfile;
|
||||
uint infile_size;
|
||||
int level = 9;
|
||||
int p = 1;
|
||||
const char *pSrc_filename;
|
||||
const char *pDst_filename;
|
||||
const void *next_in = s_inbuf;
|
||||
size_t avail_in = 0;
|
||||
void *next_out = s_outbuf;
|
||||
size_t avail_out = OUT_BUF_SIZE;
|
||||
size_t total_in = 0, total_out = 0;
|
||||
long file_loc;
|
||||
|
||||
assert(COMP_OUT_BUF_SIZE <= OUT_BUF_SIZE);
|
||||
|
||||
printf("miniz.c example5 (demonstrates tinfl/tdefl)\n");
|
||||
|
||||
if (argc < 4)
|
||||
{
|
||||
printf("File to file compression/decompression using the low-level tinfl/tdefl API's.\n");
|
||||
printf("Usage: example5 [options] [mode:c or d] infile outfile\n");
|
||||
printf("\nModes:\n");
|
||||
printf("c - Compresses file infile to a zlib stream in file outfile\n");
|
||||
printf("d - Decompress zlib stream in file infile to file outfile\n");
|
||||
printf("\nOptions:\n");
|
||||
printf("-l[0-10] - Compression level, higher values are slower, 0 is none.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
while ((p < argc) && (argv[p][0] == '-'))
|
||||
{
|
||||
switch (argv[p][1])
|
||||
{
|
||||
case 'l':
|
||||
{
|
||||
level = atoi(&argv[1][2]);
|
||||
if ((level < 0) || (level > 10))
|
||||
{
|
||||
printf("Invalid level!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
printf("Invalid option: %s\n", argv[p]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
p++;
|
||||
}
|
||||
|
||||
if ((argc - p) < 3)
|
||||
{
|
||||
printf("Must specify mode, input filename, and output filename after options!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else if ((argc - p) > 3)
|
||||
{
|
||||
printf("Too many filenames!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pMode = argv[p++];
|
||||
if (!strchr("cCdD", pMode[0]))
|
||||
{
|
||||
printf("Invalid mode!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
pSrc_filename = argv[p++];
|
||||
pDst_filename = argv[p++];
|
||||
|
||||
printf("Mode: %c, Level: %u\nInput File: \"%s\"\nOutput File: \"%s\"\n", pMode[0], level, pSrc_filename, pDst_filename);
|
||||
|
||||
// Open input file.
|
||||
pInfile = fopen(pSrc_filename, "rb");
|
||||
if (!pInfile)
|
||||
{
|
||||
printf("Failed opening input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// Determine input file's size.
|
||||
fseek(pInfile, 0, SEEK_END);
|
||||
file_loc = ftell(pInfile);
|
||||
fseek(pInfile, 0, SEEK_SET);
|
||||
|
||||
if ((file_loc < 0) || ((mz_uint64)file_loc > INT_MAX))
|
||||
{
|
||||
// This is not a limitation of miniz or tinfl, but this example.
|
||||
printf("File is too large to be processed by this example.\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
infile_size = (uint)file_loc;
|
||||
|
||||
// Open output file.
|
||||
pOutfile = fopen(pDst_filename, "wb");
|
||||
if (!pOutfile)
|
||||
{
|
||||
printf("Failed opening output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Input file size: %u\n", infile_size);
|
||||
|
||||
if ((pMode[0] == 'c') || (pMode[0] == 'C'))
|
||||
{
|
||||
// The number of dictionary probes to use at each compression level (0-10). 0=implies fastest/minimal possible probing.
|
||||
static const mz_uint s_tdefl_num_probes[11] = { 0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500 };
|
||||
|
||||
tdefl_status status;
|
||||
uint infile_remaining = infile_size;
|
||||
|
||||
// create tdefl() compatible flags (we have to compose the low-level flags ourselves, or use tdefl_create_comp_flags_from_zip_params() but that means MINIZ_NO_ZLIB_APIS can't be defined).
|
||||
mz_uint comp_flags = TDEFL_WRITE_ZLIB_HEADER | s_tdefl_num_probes[MZ_MIN(10, level)] | ((level <= 3) ? TDEFL_GREEDY_PARSING_FLAG : 0);
|
||||
if (!level)
|
||||
comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS;
|
||||
|
||||
// Initialize the low-level compressor.
|
||||
status = tdefl_init(&g_deflator, NULL, NULL, comp_flags);
|
||||
if (status != TDEFL_STATUS_OKAY)
|
||||
{
|
||||
printf("tdefl_init() failed!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
avail_out = COMP_OUT_BUF_SIZE;
|
||||
|
||||
// Compression.
|
||||
for ( ; ; )
|
||||
{
|
||||
size_t in_bytes, out_bytes;
|
||||
|
||||
if (!avail_in)
|
||||
{
|
||||
// Input buffer is empty, so read more bytes from input file.
|
||||
uint n = my_min(IN_BUF_SIZE, infile_remaining);
|
||||
|
||||
if (fread(s_inbuf, 1, n, pInfile) != n)
|
||||
{
|
||||
printf("Failed reading from input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
next_in = s_inbuf;
|
||||
avail_in = n;
|
||||
|
||||
infile_remaining -= n;
|
||||
//printf("Input bytes remaining: %u\n", infile_remaining);
|
||||
}
|
||||
|
||||
in_bytes = avail_in;
|
||||
out_bytes = avail_out;
|
||||
// Compress as much of the input as possible (or all of it) to the output buffer.
|
||||
status = tdefl_compress(&g_deflator, next_in, &in_bytes, next_out, &out_bytes, infile_remaining ? TDEFL_NO_FLUSH : TDEFL_FINISH);
|
||||
|
||||
next_in = (const char *)next_in + in_bytes;
|
||||
avail_in -= in_bytes;
|
||||
total_in += in_bytes;
|
||||
|
||||
next_out = (char *)next_out + out_bytes;
|
||||
avail_out -= out_bytes;
|
||||
total_out += out_bytes;
|
||||
|
||||
if ((status != TDEFL_STATUS_OKAY) || (!avail_out))
|
||||
{
|
||||
// Output buffer is full, or compression is done or failed, so write buffer to output file.
|
||||
uint n = COMP_OUT_BUF_SIZE - (uint)avail_out;
|
||||
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
next_out = s_outbuf;
|
||||
avail_out = COMP_OUT_BUF_SIZE;
|
||||
}
|
||||
|
||||
if (status == TDEFL_STATUS_DONE)
|
||||
{
|
||||
// Compression completed successfully.
|
||||
break;
|
||||
}
|
||||
else if (status != TDEFL_STATUS_OKAY)
|
||||
{
|
||||
// Compression somehow failed.
|
||||
printf("tdefl_compress() failed with status %i!\n", status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((pMode[0] == 'd') || (pMode[0] == 'D'))
|
||||
{
|
||||
// Decompression.
|
||||
uint infile_remaining = infile_size;
|
||||
|
||||
tinfl_decompressor inflator;
|
||||
tinfl_init(&inflator);
|
||||
|
||||
for ( ; ; )
|
||||
{
|
||||
size_t in_bytes, out_bytes;
|
||||
tinfl_status status;
|
||||
if (!avail_in)
|
||||
{
|
||||
// Input buffer is empty, so read more bytes from input file.
|
||||
uint n = my_min(IN_BUF_SIZE, infile_remaining);
|
||||
|
||||
if (fread(s_inbuf, 1, n, pInfile) != n)
|
||||
{
|
||||
printf("Failed reading from input file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
next_in = s_inbuf;
|
||||
avail_in = n;
|
||||
|
||||
infile_remaining -= n;
|
||||
}
|
||||
|
||||
in_bytes = avail_in;
|
||||
out_bytes = avail_out;
|
||||
status = tinfl_decompress(&inflator, (const mz_uint8 *)next_in, &in_bytes, s_outbuf, (mz_uint8 *)next_out, &out_bytes, (infile_remaining ? TINFL_FLAG_HAS_MORE_INPUT : 0) | TINFL_FLAG_PARSE_ZLIB_HEADER);
|
||||
|
||||
avail_in -= in_bytes;
|
||||
next_in = (const mz_uint8 *)next_in + in_bytes;
|
||||
total_in += in_bytes;
|
||||
|
||||
avail_out -= out_bytes;
|
||||
next_out = (mz_uint8 *)next_out + out_bytes;
|
||||
total_out += out_bytes;
|
||||
|
||||
if ((status <= TINFL_STATUS_DONE) || (!avail_out))
|
||||
{
|
||||
// Output buffer is full, or decompression is done, so write buffer to output file.
|
||||
uint n = OUT_BUF_SIZE - (uint)avail_out;
|
||||
if (fwrite(s_outbuf, 1, n, pOutfile) != n)
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
next_out = s_outbuf;
|
||||
avail_out = OUT_BUF_SIZE;
|
||||
}
|
||||
|
||||
// If status is <= TINFL_STATUS_DONE then either decompression is done or something went wrong.
|
||||
if (status <= TINFL_STATUS_DONE)
|
||||
{
|
||||
if (status == TINFL_STATUS_DONE)
|
||||
{
|
||||
// Decompression completed successfully.
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Decompression failed.
|
||||
printf("tinfl_decompress() failed with status %i!\n", status);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Invalid mode!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
fclose(pInfile);
|
||||
if (EOF == fclose(pOutfile))
|
||||
{
|
||||
printf("Failed writing to output file!\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Total input bytes: %u\n", (mz_uint32)total_in);
|
||||
printf("Total output bytes: %u\n", (mz_uint32)total_out);
|
||||
printf("Success.\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
166
code/components/miniz/examples/example6.c
Normal file
166
code/components/miniz/examples/example6.c
Normal file
@@ -0,0 +1,166 @@
|
||||
// example6.c - Demonstrates how to miniz's PNG writer func
|
||||
// Public domain, April 11 2012, Rich Geldreich, richgel99@gmail.com. See "unlicense" statement at the end of tinfl.c.
|
||||
// Mandlebrot set code from http://rosettacode.org/wiki/Mandelbrot_set#C
|
||||
// Must link this example against libm on Linux.
|
||||
|
||||
// Purposely disable a whole bunch of stuff this low-level example doesn't use.
|
||||
#define MINIZ_NO_STDIO
|
||||
#define MINIZ_NO_TIME
|
||||
#define MINIZ_NO_ZLIB_APIS
|
||||
#include "miniz.h"
|
||||
|
||||
// Now include stdio.h because this test uses fopen(), etc. (but we still don't want miniz.c's stdio stuff, for testing).
|
||||
#include <stdio.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
typedef unsigned char uint8;
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8 r, g, b;
|
||||
} rgb_t;
|
||||
|
||||
static void hsv_to_rgb(int hue, int min, int max, rgb_t *p)
|
||||
{
|
||||
const int invert = 0;
|
||||
const int saturation = 1;
|
||||
const int color_rotate = 0;
|
||||
|
||||
if (min == max) max = min + 1;
|
||||
if (invert) hue = max - (hue - min);
|
||||
if (!saturation) {
|
||||
p->r = p->g = p->b = 255 * (max - hue) / (max - min);
|
||||
return;
|
||||
} else {
|
||||
const double h_dbl = fmod(color_rotate + 1e-4 + 4.0 * (hue - min) / (max - min), 6);
|
||||
const double c_dbl = 255 * saturation;
|
||||
const double X_dbl = c_dbl * (1 - fabs(fmod(h_dbl, 2) - 1));
|
||||
const int h = (int)h_dbl;
|
||||
const int c = (int)c_dbl;
|
||||
const int X = (int)X_dbl;
|
||||
|
||||
p->r = p->g = p->b = 0;
|
||||
|
||||
switch(h) {
|
||||
case 0: p->r = c; p->g = X; return;
|
||||
case 1: p->r = X; p->g = c; return;
|
||||
case 2: p->g = c; p->b = X; return;
|
||||
case 3: p->g = X; p->b = c; return;
|
||||
case 4: p->r = X; p->b = c; return;
|
||||
default:p->r = c; p->b = X;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// Image resolution
|
||||
const int iXmax = 4096;
|
||||
const int iYmax = 4096;
|
||||
|
||||
// Output filename
|
||||
static const char *pFilename = "mandelbrot.png";
|
||||
|
||||
int iX, iY;
|
||||
const double CxMin = -2.5;
|
||||
const double CxMax = 1.5;
|
||||
const double CyMin = -2.0;
|
||||
const double CyMax = 2.0;
|
||||
|
||||
double PixelWidth = (CxMax - CxMin) / iXmax;
|
||||
double PixelHeight = (CyMax - CyMin) / iYmax;
|
||||
|
||||
// Z=Zx+Zy*i ; Z0 = 0
|
||||
double Zx, Zy;
|
||||
double Zx2, Zy2; // Zx2=Zx*Zx; Zy2=Zy*Zy
|
||||
|
||||
int Iteration;
|
||||
const int IterationMax = 200;
|
||||
|
||||
// bail-out value , radius of circle
|
||||
const double EscapeRadius = 2;
|
||||
double ER2=EscapeRadius * EscapeRadius;
|
||||
|
||||
uint8 *pImage = (uint8 *)malloc(iXmax * 3 * iYmax);
|
||||
|
||||
// world ( double) coordinate = parameter plane
|
||||
double Cx,Cy;
|
||||
|
||||
int MinIter = 9999, MaxIter = 0;
|
||||
|
||||
(void)argc, (void)argv;
|
||||
|
||||
for(iY = 0; iY < iYmax; iY++)
|
||||
{
|
||||
Cy = CyMin + iY * PixelHeight;
|
||||
if (fabs(Cy) < PixelHeight/2)
|
||||
Cy = 0.0; // Main antenna
|
||||
|
||||
for(iX = 0; iX < iXmax; iX++)
|
||||
{
|
||||
uint8 *color = pImage + (iX * 3) + (iY * iXmax * 3);
|
||||
|
||||
Cx = CxMin + iX * PixelWidth;
|
||||
|
||||
// initial value of orbit = critical point Z= 0
|
||||
Zx = 0.0;
|
||||
Zy = 0.0;
|
||||
Zx2 = Zx * Zx;
|
||||
Zy2 = Zy * Zy;
|
||||
|
||||
for (Iteration=0;Iteration<IterationMax && ((Zx2+Zy2)<ER2);Iteration++)
|
||||
{
|
||||
Zy = 2 * Zx * Zy + Cy;
|
||||
Zx =Zx2 - Zy2 + Cx;
|
||||
Zx2 = Zx * Zx;
|
||||
Zy2 = Zy * Zy;
|
||||
};
|
||||
|
||||
color[0] = (uint8)Iteration;
|
||||
color[1] = (uint8)Iteration >> 8;
|
||||
color[2] = 0;
|
||||
|
||||
if (Iteration < MinIter)
|
||||
MinIter = Iteration;
|
||||
if (Iteration > MaxIter)
|
||||
MaxIter = Iteration;
|
||||
}
|
||||
}
|
||||
|
||||
for(iY = 0; iY < iYmax; iY++)
|
||||
{
|
||||
for(iX = 0; iX < iXmax; iX++)
|
||||
{
|
||||
uint8 *color = (uint8 *)(pImage + (iX * 3) + (iY * iXmax * 3));
|
||||
|
||||
uint Iterations = color[0] | (color[1] << 8U);
|
||||
|
||||
hsv_to_rgb((int)Iterations, MinIter, MaxIter, (rgb_t *)color);
|
||||
}
|
||||
}
|
||||
|
||||
// Now write the PNG image.
|
||||
{
|
||||
size_t png_data_size = 0;
|
||||
void *pPNG_data = tdefl_write_image_to_png_file_in_memory_ex(pImage, iXmax, iYmax, 3, &png_data_size, 6, MZ_FALSE);
|
||||
if (!pPNG_data)
|
||||
fprintf(stderr, "tdefl_write_image_to_png_file_in_memory_ex() failed!\n");
|
||||
else
|
||||
{
|
||||
FILE *pFile = fopen(pFilename, "wb");
|
||||
fwrite(pPNG_data, 1, png_data_size, pFile);
|
||||
fclose(pFile);
|
||||
printf("Wrote %s\n", pFilename);
|
||||
}
|
||||
|
||||
// mz_free() is by default just an alias to free() internally, but if you've overridden miniz's allocation funcs you'll probably need to call mz_free().
|
||||
mz_free(pPNG_data);
|
||||
}
|
||||
|
||||
free(pImage);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,7 @@
|
||||
/* miniz.c 2.1.0 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
|
||||
#ifndef MINIZ_EXPORT
|
||||
#define MINIZ_EXPORT
|
||||
#endif
|
||||
/* miniz.c 3.0.0 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
|
||||
See "unlicense" statement at the end of this file.
|
||||
Rich Geldreich <richgel99@gmail.com>, last updated Oct. 13, 2013
|
||||
Implements RFC 1950: http://www.ietf.org/rfc/rfc1950.txt and RFC 1951: http://www.ietf.org/rfc/rfc1951.txt
|
||||
@@ -95,7 +98,7 @@
|
||||
possibility that the archive's central directory could be lost with this method if anything goes wrong, though.
|
||||
|
||||
- ZIP archive support limitations:
|
||||
No zip64 or spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
|
||||
No spanning support. Extraction functions can only handle unencrypted, stored or deflated files.
|
||||
Requires streams capable of seeking.
|
||||
|
||||
* This is a header file library, like stb_image.c. To get only a header file, either cut and paste the
|
||||
@@ -114,10 +117,8 @@
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Defines to completely disable specific portions of miniz.c:
|
||||
If all macros here are defined the only functionality remaining will be CRC-32, adler-32, tinfl, and tdefl. */
|
||||
If all macros here are defined the only functionality remaining will be CRC-32 and adler-32. */
|
||||
|
||||
/* Define MINIZ_NO_STDIO to disable all usage and any functions which rely on stdio for file I/O. */
|
||||
/*#define MINIZ_NO_STDIO */
|
||||
@@ -127,6 +128,12 @@
|
||||
/* The current downside is the times written to your archives will be from 1979. */
|
||||
/*#define MINIZ_NO_TIME */
|
||||
|
||||
/* Define MINIZ_NO_DEFLATE_APIS to disable all compression API's. */
|
||||
/*#define MINIZ_NO_DEFLATE_APIS */
|
||||
|
||||
/* Define MINIZ_NO_INFLATE_APIS to disable all decompression API's. */
|
||||
/*#define MINIZ_NO_INFLATE_APIS */
|
||||
|
||||
/* Define MINIZ_NO_ARCHIVE_APIS to disable all ZIP archive API's. */
|
||||
/*#define MINIZ_NO_ARCHIVE_APIS */
|
||||
|
||||
@@ -145,6 +152,14 @@
|
||||
functions (such as tdefl_compress_mem_to_heap() and tinfl_decompress_mem_to_heap()) won't work. */
|
||||
/*#define MINIZ_NO_MALLOC */
|
||||
|
||||
#ifdef MINIZ_NO_INFLATE_APIS
|
||||
#define MINIZ_NO_ARCHIVE_APIS
|
||||
#endif
|
||||
|
||||
#ifdef MINIZ_NO_DEFLATE_APIS
|
||||
#define MINIZ_NO_ARCHIVE_WRITING_APIS
|
||||
#endif
|
||||
|
||||
#if defined(__TINYC__) && (defined(__linux) || defined(__linux__))
|
||||
/* TODO: Work around "error: include file 'sys\utime.h' when compiling with tcc on Linux */
|
||||
#define MINIZ_NO_TIME
|
||||
@@ -163,18 +178,40 @@
|
||||
#define MINIZ_X86_OR_X64_CPU 0
|
||||
#endif
|
||||
|
||||
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || MINIZ_X86_OR_X64_CPU
|
||||
/* Set MINIZ_LITTLE_ENDIAN only if not set */
|
||||
#if !defined(MINIZ_LITTLE_ENDIAN)
|
||||
#if defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__)
|
||||
|
||||
#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
|
||||
/* Set MINIZ_LITTLE_ENDIAN to 1 if the processor is little endian. */
|
||||
#define MINIZ_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define MINIZ_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#if MINIZ_X86_OR_X64_CPU
|
||||
#define MINIZ_LITTLE_ENDIAN 1
|
||||
#else
|
||||
#define MINIZ_LITTLE_ENDIAN 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Using unaligned loads and stores causes errors when using UBSan */
|
||||
#if defined(__has_feature)
|
||||
#if __has_feature(undefined_behavior_sanitizer)
|
||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES only if not set */
|
||||
#if !defined(MINIZ_USE_UNALIGNED_LOADS_AND_STORES)
|
||||
#if MINIZ_X86_OR_X64_CPU
|
||||
/* Set MINIZ_USE_UNALIGNED_LOADS_AND_STORES to 1 on CPU's that permit efficient integer loads and stores from unaligned addresses. */
|
||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 1
|
||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
|
||||
#define MINIZ_UNALIGNED_USE_MEMCPY
|
||||
#else
|
||||
#define MINIZ_USE_UNALIGNED_LOADS_AND_STORES 0
|
||||
@@ -198,15 +235,15 @@ extern "C" {
|
||||
typedef unsigned long mz_ulong;
|
||||
|
||||
/* mz_free() internally uses the MZ_FREE() macro (which by default calls free() unless you've modified the MZ_MALLOC macro) to release a block allocated from the heap. */
|
||||
void mz_free(void *p);
|
||||
MINIZ_EXPORT void mz_free(void *p);
|
||||
|
||||
#define MZ_ADLER32_INIT (1)
|
||||
/* mz_adler32() returns the initial adler-32 value to use when called with ptr==NULL. */
|
||||
mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
|
||||
MINIZ_EXPORT mz_ulong mz_adler32(mz_ulong adler, const unsigned char *ptr, size_t buf_len);
|
||||
|
||||
#define MZ_CRC32_INIT (0)
|
||||
/* mz_crc32() returns the initial CRC-32 value to use when called with ptr==NULL. */
|
||||
mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
|
||||
MINIZ_EXPORT mz_ulong mz_crc32(mz_ulong crc, const unsigned char *ptr, size_t buf_len);
|
||||
|
||||
/* Compression strategies. */
|
||||
enum
|
||||
@@ -222,7 +259,7 @@ enum
|
||||
#define MZ_DEFLATED 8
|
||||
|
||||
/* Heap allocation callbacks.
|
||||
Note that mz_alloc_func parameter types purpsosely differ from zlib's: items/size is size_t, not unsigned long. */
|
||||
Note that mz_alloc_func parameter types purposely differ from zlib's: items/size is size_t, not unsigned long. */
|
||||
typedef void *(*mz_alloc_func)(void *opaque, size_t items, size_t size);
|
||||
typedef void (*mz_free_func)(void *opaque, void *address);
|
||||
typedef void *(*mz_realloc_func)(void *opaque, void *address, size_t items, size_t size);
|
||||
@@ -238,9 +275,9 @@ enum
|
||||
MZ_DEFAULT_COMPRESSION = -1
|
||||
};
|
||||
|
||||
#define MZ_VERSION "10.1.0"
|
||||
#define MZ_VERNUM 0xA100
|
||||
#define MZ_VER_MAJOR 10
|
||||
#define MZ_VERSION "11.0.1"
|
||||
#define MZ_VERNUM 0xB001
|
||||
#define MZ_VER_MAJOR 11
|
||||
#define MZ_VER_MINOR 1
|
||||
#define MZ_VER_REVISION 0
|
||||
#define MZ_VER_SUBREVISION 0
|
||||
@@ -304,7 +341,9 @@ typedef struct mz_stream_s
|
||||
typedef mz_stream *mz_streamp;
|
||||
|
||||
/* Returns the version string of miniz.c. */
|
||||
const char *mz_version(void);
|
||||
MINIZ_EXPORT const char *mz_version(void);
|
||||
|
||||
#ifndef MINIZ_NO_DEFLATE_APIS
|
||||
|
||||
/* mz_deflateInit() initializes a compressor with default options: */
|
||||
/* Parameters: */
|
||||
@@ -317,17 +356,17 @@ const char *mz_version(void);
|
||||
/* MZ_STREAM_ERROR if the stream is bogus. */
|
||||
/* MZ_PARAM_ERROR if the input parameters are bogus. */
|
||||
/* MZ_MEM_ERROR on out of memory. */
|
||||
int mz_deflateInit(mz_streamp pStream, int level);
|
||||
MINIZ_EXPORT int mz_deflateInit(mz_streamp pStream, int level);
|
||||
|
||||
/* mz_deflateInit2() is like mz_deflate(), except with more control: */
|
||||
/* Additional parameters: */
|
||||
/* method must be MZ_DEFLATED */
|
||||
/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to wrap the deflate stream with zlib header/adler-32 footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate/no header or footer) */
|
||||
/* mem_level must be between [1, 9] (it's checked but ignored by miniz.c) */
|
||||
int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
|
||||
MINIZ_EXPORT int mz_deflateInit2(mz_streamp pStream, int level, int method, int window_bits, int mem_level, int strategy);
|
||||
|
||||
/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_deflateEnd() followed by mz_deflateInit()/mz_deflateInit2(). */
|
||||
int mz_deflateReset(mz_streamp pStream);
|
||||
MINIZ_EXPORT int mz_deflateReset(mz_streamp pStream);
|
||||
|
||||
/* mz_deflate() compresses the input to output, consuming as much of the input and producing as much output as possible. */
|
||||
/* Parameters: */
|
||||
@@ -339,34 +378,38 @@ int mz_deflateReset(mz_streamp pStream);
|
||||
/* MZ_STREAM_ERROR if the stream is bogus. */
|
||||
/* MZ_PARAM_ERROR if one of the parameters is invalid. */
|
||||
/* MZ_BUF_ERROR if no forward progress is possible because the input and/or output buffers are empty. (Fill up the input buffer or free up some output space and try again.) */
|
||||
int mz_deflate(mz_streamp pStream, int flush);
|
||||
MINIZ_EXPORT int mz_deflate(mz_streamp pStream, int flush);
|
||||
|
||||
/* mz_deflateEnd() deinitializes a compressor: */
|
||||
/* Return values: */
|
||||
/* MZ_OK on success. */
|
||||
/* MZ_STREAM_ERROR if the stream is bogus. */
|
||||
int mz_deflateEnd(mz_streamp pStream);
|
||||
MINIZ_EXPORT int mz_deflateEnd(mz_streamp pStream);
|
||||
|
||||
/* mz_deflateBound() returns a (very) conservative upper bound on the amount of data that could be generated by deflate(), assuming flush is set to only MZ_NO_FLUSH or MZ_FINISH. */
|
||||
mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
|
||||
MINIZ_EXPORT mz_ulong mz_deflateBound(mz_streamp pStream, mz_ulong source_len);
|
||||
|
||||
/* Single-call compression functions mz_compress() and mz_compress2(): */
|
||||
/* Returns MZ_OK on success, or one of the error codes from mz_deflate() on failure. */
|
||||
int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
|
||||
int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
|
||||
MINIZ_EXPORT int mz_compress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
|
||||
MINIZ_EXPORT int mz_compress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len, int level);
|
||||
|
||||
/* mz_compressBound() returns a (very) conservative upper bound on the amount of data that could be generated by calling mz_compress(). */
|
||||
mz_ulong mz_compressBound(mz_ulong source_len);
|
||||
MINIZ_EXPORT mz_ulong mz_compressBound(mz_ulong source_len);
|
||||
|
||||
#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/
|
||||
|
||||
#ifndef MINIZ_NO_INFLATE_APIS
|
||||
|
||||
/* Initializes a decompressor. */
|
||||
int mz_inflateInit(mz_streamp pStream);
|
||||
MINIZ_EXPORT int mz_inflateInit(mz_streamp pStream);
|
||||
|
||||
/* mz_inflateInit2() is like mz_inflateInit() with an additional option that controls the window size and whether or not the stream has been wrapped with a zlib header/footer: */
|
||||
/* window_bits must be MZ_DEFAULT_WINDOW_BITS (to parse zlib header/footer) or -MZ_DEFAULT_WINDOW_BITS (raw deflate). */
|
||||
int mz_inflateInit2(mz_streamp pStream, int window_bits);
|
||||
MINIZ_EXPORT int mz_inflateInit2(mz_streamp pStream, int window_bits);
|
||||
|
||||
/* Quickly resets a compressor without having to reallocate anything. Same as calling mz_inflateEnd() followed by mz_inflateInit()/mz_inflateInit2(). */
|
||||
int mz_inflateReset(mz_streamp pStream);
|
||||
MINIZ_EXPORT int mz_inflateReset(mz_streamp pStream);
|
||||
|
||||
/* Decompresses the input stream to the output, consuming only as much of the input as needed, and writing as much to the output as possible. */
|
||||
/* Parameters: */
|
||||
@@ -382,17 +425,19 @@ int mz_inflateReset(mz_streamp pStream);
|
||||
/* MZ_PARAM_ERROR if one of the parameters is invalid. */
|
||||
/* MZ_BUF_ERROR if no forward progress is possible because the input buffer is empty but the inflater needs more input to continue, or if the output buffer is not large enough. Call mz_inflate() again */
|
||||
/* with more input data, or with more room in the output buffer (except when using single call decompression, described above). */
|
||||
int mz_inflate(mz_streamp pStream, int flush);
|
||||
MINIZ_EXPORT int mz_inflate(mz_streamp pStream, int flush);
|
||||
|
||||
/* Deinitializes a decompressor. */
|
||||
int mz_inflateEnd(mz_streamp pStream);
|
||||
MINIZ_EXPORT int mz_inflateEnd(mz_streamp pStream);
|
||||
|
||||
/* Single-call decompression. */
|
||||
/* Returns MZ_OK on success, or one of the error codes from mz_inflate() on failure. */
|
||||
int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
|
||||
MINIZ_EXPORT int mz_uncompress(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong source_len);
|
||||
MINIZ_EXPORT int mz_uncompress2(unsigned char *pDest, mz_ulong *pDest_len, const unsigned char *pSource, mz_ulong *pSource_len);
|
||||
#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
|
||||
|
||||
/* Returns a string description of the specified error code, or NULL if the error code is invalid. */
|
||||
const char *mz_error(int err);
|
||||
MINIZ_EXPORT const char *mz_error(int err);
|
||||
|
||||
/* Redefine zlib-compatible names to miniz equivalents, so miniz.c can be used as a drop-in replacement for the subset of zlib that miniz.c supports. */
|
||||
/* Define MINIZ_NO_ZLIB_COMPATIBLE_NAMES to disable zlib-compatibility if you use zlib in the same project. */
|
||||
@@ -440,6 +485,8 @@ typedef void *const voidpc;
|
||||
#define free_func mz_free_func
|
||||
#define internal_state mz_internal_state
|
||||
#define z_stream mz_stream
|
||||
|
||||
#ifndef MINIZ_NO_DEFLATE_APIS
|
||||
#define deflateInit mz_deflateInit
|
||||
#define deflateInit2 mz_deflateInit2
|
||||
#define deflateReset mz_deflateReset
|
||||
@@ -449,12 +496,18 @@ typedef void *const voidpc;
|
||||
#define compress mz_compress
|
||||
#define compress2 mz_compress2
|
||||
#define compressBound mz_compressBound
|
||||
#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/
|
||||
|
||||
#ifndef MINIZ_NO_INFLATE_APIS
|
||||
#define inflateInit mz_inflateInit
|
||||
#define inflateInit2 mz_inflateInit2
|
||||
#define inflateReset mz_inflateReset
|
||||
#define inflate mz_inflate
|
||||
#define inflateEnd mz_inflateEnd
|
||||
#define uncompress mz_uncompress
|
||||
#define uncompress2 mz_uncompress2
|
||||
#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
|
||||
|
||||
#define crc32 mz_crc32
|
||||
#define adler32 mz_adler32
|
||||
#define MAX_WBITS 15
|
||||
@@ -475,12 +528,19 @@ typedef void *const voidpc;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
/* ------------------- Types and macros */
|
||||
typedef unsigned char mz_uint8;
|
||||
typedef signed short mz_int16;
|
||||
@@ -511,7 +571,8 @@ typedef int mz_bool;
|
||||
#ifdef MINIZ_NO_TIME
|
||||
typedef struct mz_dummy_time_t_tag
|
||||
{
|
||||
int m_dummy;
|
||||
mz_uint32 m_dummy1;
|
||||
mz_uint32 m_dummy2;
|
||||
} mz_dummy_time_t;
|
||||
#define MZ_TIME_T mz_dummy_time_t
|
||||
#else
|
||||
@@ -533,6 +594,8 @@ typedef struct mz_dummy_time_t_tag
|
||||
#define MZ_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#define MZ_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MZ_CLEAR_OBJ(obj) memset(&(obj), 0, sizeof(obj))
|
||||
#define MZ_CLEAR_ARR(obj) memset((obj), 0, sizeof(obj))
|
||||
#define MZ_CLEAR_PTR(obj) memset((obj), 0, sizeof(*obj))
|
||||
|
||||
#if MINIZ_USE_UNALIGNED_LOADS_AND_STORES && MINIZ_LITTLE_ENDIAN
|
||||
#define MZ_READ_LE16(p) *((const mz_uint16 *)(p))
|
||||
@@ -556,9 +619,9 @@ typedef struct mz_dummy_time_t_tag
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void *miniz_def_alloc_func(void *opaque, size_t items, size_t size);
|
||||
extern void miniz_def_free_func(void *opaque, void *address);
|
||||
extern void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size);
|
||||
extern MINIZ_EXPORT void *miniz_def_alloc_func(void *opaque, size_t items, size_t size);
|
||||
extern MINIZ_EXPORT void miniz_def_free_func(void *opaque, void *address);
|
||||
extern MINIZ_EXPORT void *miniz_def_realloc_func(void *opaque, void *address, size_t items, size_t size);
|
||||
|
||||
#define MZ_UINT16_MAX (0xFFFFU)
|
||||
#define MZ_UINT32_MAX (0xFFFFFFFFU)
|
||||
@@ -566,9 +629,11 @@ extern void *miniz_def_realloc_func(void *opaque, void *address, size_t items, s
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#pragma once
|
||||
#pragma once
|
||||
|
||||
|
||||
#ifndef MINIZ_NO_DEFLATE_APIS
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -616,11 +681,11 @@ enum
|
||||
/* Function returns a pointer to the compressed data, or NULL on failure. */
|
||||
/* *pOut_len will be set to the compressed data's size, which could be larger than src_buf_len on uncompressible data. */
|
||||
/* The caller must free() the returned block when it's no longer needed. */
|
||||
void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
|
||||
MINIZ_EXPORT void *tdefl_compress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
|
||||
|
||||
/* tdefl_compress_mem_to_mem() compresses a block in memory to another block in memory. */
|
||||
/* Returns 0 on failure. */
|
||||
size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
|
||||
MINIZ_EXPORT size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
|
||||
|
||||
/* Compresses an image to a compressed PNG file in memory. */
|
||||
/* On entry: */
|
||||
@@ -632,14 +697,14 @@ size_t tdefl_compress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void
|
||||
/* Function returns a pointer to the compressed data, or NULL on failure. */
|
||||
/* *pLen_out will be set to the size of the PNG image file. */
|
||||
/* The caller must mz_free() the returned heap block (which will typically be larger than *pLen_out) when it's no longer needed. */
|
||||
void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
|
||||
void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
|
||||
MINIZ_EXPORT void *tdefl_write_image_to_png_file_in_memory_ex(const void *pImage, int w, int h, int num_chans, size_t *pLen_out, mz_uint level, mz_bool flip);
|
||||
MINIZ_EXPORT void *tdefl_write_image_to_png_file_in_memory(const void *pImage, int w, int h, int num_chans, size_t *pLen_out);
|
||||
|
||||
/* Output stream interface. The compressor uses this interface to write compressed data. It'll typically be called TDEFL_OUT_BUF_SIZE at a time. */
|
||||
typedef mz_bool (*tdefl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
|
||||
|
||||
/* tdefl_compress_mem_to_output() compresses a block to an output stream. The above helpers use this function internally. */
|
||||
mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
MINIZ_EXPORT mz_bool tdefl_compress_mem_to_output(const void *pBuf, size_t buf_len, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -727,39 +792,43 @@ typedef struct
|
||||
/* pBut_buf_func: If NULL, output data will be supplied to the specified callback. In this case, the user should call the tdefl_compress_buffer() API for compression. */
|
||||
/* If pBut_buf_func is NULL the user should always call the tdefl_compress() API. */
|
||||
/* flags: See the above enums (TDEFL_HUFFMAN_ONLY, TDEFL_WRITE_ZLIB_HEADER, etc.) */
|
||||
tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
MINIZ_EXPORT tdefl_status tdefl_init(tdefl_compressor *d, tdefl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
|
||||
/* Compresses a block of data, consuming as much of the specified input buffer as possible, and writing as much compressed data to the specified output buffer as possible. */
|
||||
tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
|
||||
MINIZ_EXPORT tdefl_status tdefl_compress(tdefl_compressor *d, const void *pIn_buf, size_t *pIn_buf_size, void *pOut_buf, size_t *pOut_buf_size, tdefl_flush flush);
|
||||
|
||||
/* tdefl_compress_buffer() is only usable when the tdefl_init() is called with a non-NULL tdefl_put_buf_func_ptr. */
|
||||
/* tdefl_compress_buffer() always consumes the entire input buffer. */
|
||||
tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
|
||||
MINIZ_EXPORT tdefl_status tdefl_compress_buffer(tdefl_compressor *d, const void *pIn_buf, size_t in_buf_size, tdefl_flush flush);
|
||||
|
||||
tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
|
||||
mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
|
||||
MINIZ_EXPORT tdefl_status tdefl_get_prev_return_status(tdefl_compressor *d);
|
||||
MINIZ_EXPORT mz_uint32 tdefl_get_adler32(tdefl_compressor *d);
|
||||
|
||||
/* Create tdefl_compress() flags given zlib-style compression parameters. */
|
||||
/* level may range from [0,10] (where 10 is absolute max compression, but may be much slower on some files) */
|
||||
/* window_bits may be -15 (raw deflate) or 15 (zlib) */
|
||||
/* strategy may be either MZ_DEFAULT_STRATEGY, MZ_FILTERED, MZ_HUFFMAN_ONLY, MZ_RLE, or MZ_FIXED */
|
||||
mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
|
||||
MINIZ_EXPORT mz_uint tdefl_create_comp_flags_from_zip_params(int level, int window_bits, int strategy);
|
||||
|
||||
#ifndef MINIZ_NO_MALLOC
|
||||
/* Allocate the tdefl_compressor structure in C so that */
|
||||
/* non-C language bindings to tdefl_ API don't need to worry about */
|
||||
/* structure size and allocation mechanism. */
|
||||
tdefl_compressor *tdefl_compressor_alloc(void);
|
||||
void tdefl_compressor_free(tdefl_compressor *pComp);
|
||||
MINIZ_EXPORT tdefl_compressor *tdefl_compressor_alloc(void);
|
||||
MINIZ_EXPORT void tdefl_compressor_free(tdefl_compressor *pComp);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#pragma once
|
||||
|
||||
#endif /*#ifndef MINIZ_NO_DEFLATE_APIS*/
|
||||
#pragma once
|
||||
|
||||
/* ------------------- Low-level Decompression API Definitions */
|
||||
|
||||
#ifndef MINIZ_NO_INFLATE_APIS
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -784,17 +853,17 @@ enum
|
||||
/* Function returns a pointer to the decompressed data, or NULL on failure. */
|
||||
/* *pOut_len will be set to the decompressed data's size, which could be larger than src_buf_len on uncompressible data. */
|
||||
/* The caller must call mz_free() on the returned block when it's no longer needed. */
|
||||
void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
|
||||
MINIZ_EXPORT void *tinfl_decompress_mem_to_heap(const void *pSrc_buf, size_t src_buf_len, size_t *pOut_len, int flags);
|
||||
|
||||
/* tinfl_decompress_mem_to_mem() decompresses a block in memory to another block in memory. */
|
||||
/* Returns TINFL_DECOMPRESS_MEM_TO_MEM_FAILED on failure, or the number of bytes written on success. */
|
||||
#define TINFL_DECOMPRESS_MEM_TO_MEM_FAILED ((size_t)(-1))
|
||||
size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
|
||||
MINIZ_EXPORT size_t tinfl_decompress_mem_to_mem(void *pOut_buf, size_t out_buf_len, const void *pSrc_buf, size_t src_buf_len, int flags);
|
||||
|
||||
/* tinfl_decompress_mem_to_callback() decompresses a block in memory to an internal 32KB buffer, and a user provided callback function will be called to flush the buffer. */
|
||||
/* Returns 1 on success or 0 on failure. */
|
||||
typedef int (*tinfl_put_buf_func_ptr)(const void *pBuf, int len, void *pUser);
|
||||
int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
MINIZ_EXPORT int tinfl_decompress_mem_to_callback(const void *pIn_buf, size_t *pIn_buf_size, tinfl_put_buf_func_ptr pPut_buf_func, void *pPut_buf_user, int flags);
|
||||
|
||||
struct tinfl_decompressor_tag;
|
||||
typedef struct tinfl_decompressor_tag tinfl_decompressor;
|
||||
@@ -803,8 +872,8 @@ typedef struct tinfl_decompressor_tag tinfl_decompressor;
|
||||
/* Allocate the tinfl_decompressor structure in C so that */
|
||||
/* non-C language bindings to tinfl_ API don't need to worry about */
|
||||
/* structure size and allocation mechanism. */
|
||||
tinfl_decompressor *tinfl_decompressor_alloc(void);
|
||||
void tinfl_decompressor_free(tinfl_decompressor *pDecomp);
|
||||
MINIZ_EXPORT tinfl_decompressor *tinfl_decompressor_alloc(void);
|
||||
MINIZ_EXPORT void tinfl_decompressor_free(tinfl_decompressor *pDecomp);
|
||||
#endif
|
||||
|
||||
/* Max size of LZ dictionary. */
|
||||
@@ -855,7 +924,7 @@ typedef enum {
|
||||
|
||||
/* Main low-level decompressor coroutine function. This is the only function actually needed for decompression. All the other functions are just high-level helpers for improved usability. */
|
||||
/* This is a universal API, i.e. it can be used as a building block to build any desired higher level decompression API. In the limit case, it can be called once per every byte input or output. */
|
||||
tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
|
||||
MINIZ_EXPORT tinfl_status tinfl_decompress(tinfl_decompressor *r, const mz_uint8 *pIn_buf_next, size_t *pIn_buf_size, mz_uint8 *pOut_buf_start, mz_uint8 *pOut_buf_next, size_t *pOut_buf_size, const mz_uint32 decomp_flags);
|
||||
|
||||
/* Internal/private bits follow. */
|
||||
enum
|
||||
@@ -868,12 +937,6 @@ enum
|
||||
TINFL_FAST_LOOKUP_SIZE = 1 << TINFL_FAST_LOOKUP_BITS
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
mz_uint8 m_code_size[TINFL_MAX_HUFF_SYMBOLS_0];
|
||||
mz_int16 m_look_up[TINFL_FAST_LOOKUP_SIZE], m_tree[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
|
||||
} tinfl_huff_table;
|
||||
|
||||
#if MINIZ_HAS_64BIT_REGISTERS
|
||||
#define TINFL_USE_64BIT_BITBUF 1
|
||||
#else
|
||||
@@ -893,7 +956,13 @@ struct tinfl_decompressor_tag
|
||||
mz_uint32 m_state, m_num_bits, m_zhdr0, m_zhdr1, m_z_adler32, m_final, m_type, m_check_adler32, m_dist, m_counter, m_num_extra, m_table_sizes[TINFL_MAX_HUFF_TABLES];
|
||||
tinfl_bit_buf_t m_bit_buf;
|
||||
size_t m_dist_from_out_buf_start;
|
||||
tinfl_huff_table m_tables[TINFL_MAX_HUFF_TABLES];
|
||||
mz_int16 m_look_up[TINFL_MAX_HUFF_TABLES][TINFL_FAST_LOOKUP_SIZE];
|
||||
mz_int16 m_tree_0[TINFL_MAX_HUFF_SYMBOLS_0 * 2];
|
||||
mz_int16 m_tree_1[TINFL_MAX_HUFF_SYMBOLS_1 * 2];
|
||||
mz_int16 m_tree_2[TINFL_MAX_HUFF_SYMBOLS_2 * 2];
|
||||
mz_uint8 m_code_size_0[TINFL_MAX_HUFF_SYMBOLS_0];
|
||||
mz_uint8 m_code_size_1[TINFL_MAX_HUFF_SYMBOLS_1];
|
||||
mz_uint8 m_code_size_2[TINFL_MAX_HUFF_SYMBOLS_2];
|
||||
mz_uint8 m_raw_header[4], m_len_codes[TINFL_MAX_HUFF_SYMBOLS_0 + TINFL_MAX_HUFF_SYMBOLS_1 + 137];
|
||||
};
|
||||
|
||||
@@ -901,6 +970,8 @@ struct tinfl_decompressor_tag
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*#ifndef MINIZ_NO_INFLATE_APIS*/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
@@ -934,10 +1005,6 @@ typedef struct
|
||||
mz_uint16 m_bit_flag;
|
||||
mz_uint16 m_method;
|
||||
|
||||
#ifndef MINIZ_NO_TIME
|
||||
MZ_TIME_T m_time;
|
||||
#endif
|
||||
|
||||
/* CRC-32 of uncompressed data. */
|
||||
mz_uint32 m_crc32;
|
||||
|
||||
@@ -974,6 +1041,11 @@ typedef struct
|
||||
/* Guaranteed to be zero terminated, may be truncated to fit. */
|
||||
char m_comment[MZ_ZIP_MAX_ARCHIVE_FILE_COMMENT_SIZE];
|
||||
|
||||
#ifdef MINIZ_NO_TIME
|
||||
MZ_TIME_T m_padding;
|
||||
#else
|
||||
MZ_TIME_T m_time;
|
||||
#endif
|
||||
} mz_zip_archive_file_stat;
|
||||
|
||||
typedef size_t (*mz_file_read_func)(void *pOpaque, mz_uint64 file_ofs, void *pBuf, size_t n);
|
||||
@@ -999,7 +1071,10 @@ typedef enum {
|
||||
MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY = 0x2000, /* validate the local headers, but don't decompress the entire file and check the crc32 */
|
||||
MZ_ZIP_FLAG_WRITE_ZIP64 = 0x4000, /* always use the zip64 file format, instead of the original zip file format with automatic switch to zip64. Use as flags parameter with mz_zip_writer_init*_v2 */
|
||||
MZ_ZIP_FLAG_WRITE_ALLOW_READING = 0x8000,
|
||||
MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000
|
||||
MZ_ZIP_FLAG_ASCII_FILENAME = 0x10000,
|
||||
/*After adding a compressed file, seek back
|
||||
to local file header and set the correct sizes*/
|
||||
MZ_ZIP_FLAG_WRITE_HEADER_SET_SIZE = 0x20000
|
||||
} mz_zip_flags;
|
||||
|
||||
typedef enum {
|
||||
@@ -1082,9 +1157,7 @@ typedef struct
|
||||
mz_uint flags;
|
||||
|
||||
int status;
|
||||
#ifndef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
|
||||
mz_uint file_crc32;
|
||||
#endif
|
||||
|
||||
mz_uint64 read_buf_size, read_buf_ofs, read_buf_avail, comp_remaining, out_buf_ofs, cur_file_ofs;
|
||||
mz_zip_archive_file_stat file_stat;
|
||||
void *pRead_buf;
|
||||
@@ -1094,149 +1167,157 @@ typedef struct
|
||||
|
||||
tinfl_decompressor inflator;
|
||||
|
||||
#ifdef MINIZ_DISABLE_ZIP_READER_CRC32_CHECKS
|
||||
mz_uint padding;
|
||||
#else
|
||||
mz_uint file_crc32;
|
||||
#endif
|
||||
|
||||
} mz_zip_reader_extract_iter_state;
|
||||
|
||||
/* -------- ZIP reading */
|
||||
|
||||
/* Inits a ZIP archive reader. */
|
||||
/* These functions read and validate the archive's central directory. */
|
||||
mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_init(mz_zip_archive *pZip, mz_uint64 size, mz_uint flags);
|
||||
|
||||
mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_init_mem(mz_zip_archive *pZip, const void *pMem, size_t size, mz_uint flags);
|
||||
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
/* Read a archive from a disk file. */
|
||||
/* file_start_ofs is the file offset where the archive actually begins, or 0. */
|
||||
/* actual_archive_size is the true total size of the archive, which may be smaller than the file's actual size on disk. If zero the entire file is treated as the archive. */
|
||||
mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
|
||||
mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint32 flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags, mz_uint64 file_start_ofs, mz_uint64 archive_size);
|
||||
|
||||
/* Read an archive from an already opened FILE, beginning at the current file position. */
|
||||
/* The archive is assumed to be archive_size bytes long. If archive_size is < 0, then the entire rest of the file is assumed to contain the archive. */
|
||||
/* The archive is assumed to be archive_size bytes long. If archive_size is 0, then the entire rest of the file is assumed to contain the archive. */
|
||||
/* The FILE will NOT be closed when mz_zip_reader_end() is called. */
|
||||
mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint64 archive_size, mz_uint flags);
|
||||
#endif
|
||||
|
||||
/* Ends archive reading, freeing all allocations, and closing the input archive file if mz_zip_reader_init_file() was used. */
|
||||
mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_end(mz_zip_archive *pZip);
|
||||
|
||||
/* -------- ZIP reading or writing */
|
||||
|
||||
/* Clears a mz_zip_archive struct to all zeros. */
|
||||
/* Important: This must be done before passing the struct to any mz_zip functions. */
|
||||
void mz_zip_zero_struct(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT void mz_zip_zero_struct(mz_zip_archive *pZip);
|
||||
|
||||
mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip);
|
||||
mz_zip_type mz_zip_get_type(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_zip_mode mz_zip_get_mode(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_zip_type mz_zip_get_type(mz_zip_archive *pZip);
|
||||
|
||||
/* Returns the total number of files in the archive. */
|
||||
mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_uint mz_zip_reader_get_num_files(mz_zip_archive *pZip);
|
||||
|
||||
mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip);
|
||||
mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip);
|
||||
MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_uint64 mz_zip_get_archive_size(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_uint64 mz_zip_get_archive_file_start_offset(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT MZ_FILE *mz_zip_get_cfile(mz_zip_archive *pZip);
|
||||
|
||||
/* Reads n bytes of raw archive data, starting at file offset file_ofs, to pBuf. */
|
||||
size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n);
|
||||
MINIZ_EXPORT size_t mz_zip_read_archive_data(mz_zip_archive *pZip, mz_uint64 file_ofs, void *pBuf, size_t n);
|
||||
|
||||
/* All mz_zip funcs set the m_last_error field in the mz_zip_archive struct. These functions retrieve/manipulate this field. */
|
||||
/* Note that the m_last_error functionality is not thread safe. */
|
||||
mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num);
|
||||
mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip);
|
||||
mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip);
|
||||
mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip);
|
||||
const char *mz_zip_get_error_string(mz_zip_error mz_err);
|
||||
MINIZ_EXPORT mz_zip_error mz_zip_set_last_error(mz_zip_archive *pZip, mz_zip_error err_num);
|
||||
MINIZ_EXPORT mz_zip_error mz_zip_peek_last_error(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_zip_error mz_zip_clear_last_error(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_zip_error mz_zip_get_last_error(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT const char *mz_zip_get_error_string(mz_zip_error mz_err);
|
||||
|
||||
/* MZ_TRUE if the archive file entry is a directory entry. */
|
||||
mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_a_directory(mz_zip_archive *pZip, mz_uint file_index);
|
||||
|
||||
/* MZ_TRUE if the file is encrypted/strong encrypted. */
|
||||
mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_encrypted(mz_zip_archive *pZip, mz_uint file_index);
|
||||
|
||||
/* MZ_TRUE if the compression method is supported, and the file is not encrypted, and the file is not a compressed patch file. */
|
||||
mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_is_file_supported(mz_zip_archive *pZip, mz_uint file_index);
|
||||
|
||||
/* Retrieves the filename of an archive file entry. */
|
||||
/* Returns the number of bytes written to pFilename, or if filename_buf_size is 0 this function returns the number of bytes needed to fully store the filename. */
|
||||
mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
|
||||
MINIZ_EXPORT mz_uint mz_zip_reader_get_filename(mz_zip_archive *pZip, mz_uint file_index, char *pFilename, mz_uint filename_buf_size);
|
||||
|
||||
/* Attempts to locates a file in the archive's central directory. */
|
||||
/* Valid flags: MZ_ZIP_FLAG_CASE_SENSITIVE, MZ_ZIP_FLAG_IGNORE_PATH */
|
||||
/* Returns -1 if the file cannot be found. */
|
||||
int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
|
||||
int mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index);
|
||||
MINIZ_EXPORT int mz_zip_reader_locate_file(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_locate_file_v2(mz_zip_archive *pZip, const char *pName, const char *pComment, mz_uint flags, mz_uint32 *file_index);
|
||||
|
||||
/* Returns detailed information about an archive file entry. */
|
||||
mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_file_stat(mz_zip_archive *pZip, mz_uint file_index, mz_zip_archive_file_stat *pStat);
|
||||
|
||||
/* MZ_TRUE if the file is in zip64 format. */
|
||||
/* A file is considered zip64 if it contained a zip64 end of central directory marker, or if it contained any zip64 extended file information fields in the central directory. */
|
||||
mz_bool mz_zip_is_zip64(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_bool mz_zip_is_zip64(mz_zip_archive *pZip);
|
||||
|
||||
/* Returns the total central directory size in bytes. */
|
||||
/* The current max supported size is <= MZ_UINT32_MAX. */
|
||||
size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT size_t mz_zip_get_central_dir_size(mz_zip_archive *pZip);
|
||||
|
||||
/* Extracts a archive file to a memory buffer using no memory allocation. */
|
||||
/* There must be at least enough room on the stack to store the inflator's state (~34KB or so). */
|
||||
mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
|
||||
mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem_no_alloc(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem_no_alloc(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags, void *pUser_read_buf, size_t user_read_buf_size);
|
||||
|
||||
/* Extracts a archive file to a memory buffer. */
|
||||
mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
|
||||
mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_mem(mz_zip_archive *pZip, mz_uint file_index, void *pBuf, size_t buf_size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_mem(mz_zip_archive *pZip, const char *pFilename, void *pBuf, size_t buf_size, mz_uint flags);
|
||||
|
||||
/* Extracts a archive file to a dynamically allocated heap buffer. */
|
||||
/* The memory will be allocated via the mz_zip_archive's alloc/realloc functions. */
|
||||
/* Returns NULL and sets the last error on failure. */
|
||||
void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
|
||||
void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
|
||||
MINIZ_EXPORT void *mz_zip_reader_extract_to_heap(mz_zip_archive *pZip, mz_uint file_index, size_t *pSize, mz_uint flags);
|
||||
MINIZ_EXPORT void *mz_zip_reader_extract_file_to_heap(mz_zip_archive *pZip, const char *pFilename, size_t *pSize, mz_uint flags);
|
||||
|
||||
/* Extracts a archive file using a callback function to output the file's data. */
|
||||
mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
|
||||
mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_callback(mz_zip_archive *pZip, mz_uint file_index, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_callback(mz_zip_archive *pZip, const char *pFilename, mz_file_write_func pCallback, void *pOpaque, mz_uint flags);
|
||||
|
||||
/* Extract a file iteratively */
|
||||
mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
|
||||
mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);
|
||||
size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size);
|
||||
mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState);
|
||||
MINIZ_EXPORT mz_zip_reader_extract_iter_state* mz_zip_reader_extract_iter_new(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
|
||||
MINIZ_EXPORT mz_zip_reader_extract_iter_state* mz_zip_reader_extract_file_iter_new(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);
|
||||
MINIZ_EXPORT size_t mz_zip_reader_extract_iter_read(mz_zip_reader_extract_iter_state* pState, void* pvBuf, size_t buf_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_iter_free(mz_zip_reader_extract_iter_state* pState);
|
||||
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
/* Extracts a archive file to a disk file and sets its last accessed and modified times. */
|
||||
/* This function only extracts files, not archive directory records. */
|
||||
mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
|
||||
mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_file(mz_zip_archive *pZip, mz_uint file_index, const char *pDst_filename, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_file(mz_zip_archive *pZip, const char *pArchive_filename, const char *pDst_filename, mz_uint flags);
|
||||
|
||||
/* Extracts a archive file starting at the current position in the destination FILE stream. */
|
||||
mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *File, mz_uint flags);
|
||||
mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_to_cfile(mz_zip_archive *pZip, mz_uint file_index, MZ_FILE *File, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_reader_extract_file_to_cfile(mz_zip_archive *pZip, const char *pArchive_filename, MZ_FILE *pFile, mz_uint flags);
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
/* TODO */
|
||||
typedef void *mz_zip_streaming_extract_state_ptr;
|
||||
mz_zip_streaming_extract_state_ptr mz_zip_streaming_extract_begin(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
|
||||
uint64_t mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
|
||||
uint64_t mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
|
||||
mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, uint64_t new_ofs);
|
||||
mz_uint64 mz_zip_streaming_extract_get_size(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
|
||||
mz_uint64 mz_zip_streaming_extract_get_cur_ofs(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
|
||||
mz_bool mz_zip_streaming_extract_seek(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, mz_uint64 new_ofs);
|
||||
size_t mz_zip_streaming_extract_read(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState, void *pBuf, size_t buf_size);
|
||||
mz_bool mz_zip_streaming_extract_end(mz_zip_archive *pZip, mz_zip_streaming_extract_state_ptr pState);
|
||||
#endif
|
||||
|
||||
/* This function compares the archive's local headers, the optional local zip64 extended information block, and the optional descriptor following the compressed data vs. the data in the central directory. */
|
||||
/* It also validates that each file can be successfully uncompressed unless the MZ_ZIP_FLAG_VALIDATE_HEADERS_ONLY is specified. */
|
||||
mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_validate_file(mz_zip_archive *pZip, mz_uint file_index, mz_uint flags);
|
||||
|
||||
/* Validates an entire archive by calling mz_zip_validate_file() on each file. */
|
||||
mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_validate_archive(mz_zip_archive *pZip, mz_uint flags);
|
||||
|
||||
/* Misc utils/helpers, valid for ZIP reading or writing */
|
||||
mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr);
|
||||
mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr);
|
||||
MINIZ_EXPORT mz_bool mz_zip_validate_mem_archive(const void *pMem, size_t size, mz_uint flags, mz_zip_error *pErr);
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
MINIZ_EXPORT mz_bool mz_zip_validate_file_archive(const char *pFilename, mz_uint flags, mz_zip_error *pErr);
|
||||
#endif
|
||||
|
||||
/* Universal end function - calls either mz_zip_reader_end() or mz_zip_writer_end(). */
|
||||
mz_bool mz_zip_end(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_bool mz_zip_end(mz_zip_archive *pZip);
|
||||
|
||||
/* -------- ZIP writing */
|
||||
|
||||
@@ -1245,16 +1326,16 @@ mz_bool mz_zip_end(mz_zip_archive *pZip);
|
||||
/* Inits a ZIP archive writer. */
|
||||
/*Set pZip->m_pWrite (and pZip->m_pIO_opaque) before calling mz_zip_writer_init or mz_zip_writer_init_v2*/
|
||||
/*The output is streamable, i.e. file_ofs in mz_file_write_func always increases only by n*/
|
||||
mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
|
||||
mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init(mz_zip_archive *pZip, mz_uint64 existing_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_v2(mz_zip_archive *pZip, mz_uint64 existing_size, mz_uint flags);
|
||||
|
||||
mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
|
||||
mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_heap(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_heap_v2(mz_zip_archive *pZip, size_t size_to_reserve_at_beginning, size_t initial_allocation_size, mz_uint flags);
|
||||
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
|
||||
mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags);
|
||||
mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_file(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_file_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint64 size_to_reserve_at_beginning, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint flags);
|
||||
#endif
|
||||
|
||||
/* Converts a ZIP archive reader object into a writer object, to allow efficient in-place file appends to occur on an existing archive. */
|
||||
@@ -1263,56 +1344,57 @@ mz_bool mz_zip_writer_init_cfile(mz_zip_archive *pZip, MZ_FILE *pFile, mz_uint f
|
||||
/* Finally, for archives opened using mz_zip_reader_init, the mz_zip_archive's user provided m_pWrite function cannot be NULL. */
|
||||
/* Note: In-place archive modification is not recommended unless you know what you're doing, because if execution stops or something goes wrong before */
|
||||
/* the archive is finalized the file's central directory will be hosed. */
|
||||
mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
|
||||
mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader(mz_zip_archive *pZip, const char *pFilename);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_init_from_reader_v2(mz_zip_archive *pZip, const char *pFilename, mz_uint flags);
|
||||
|
||||
/* Adds the contents of a memory buffer to an archive. These functions record the current local time into the archive. */
|
||||
/* To add a directory entry, call this method with an archive name ending in a forwardslash with an empty buffer. */
|
||||
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */
|
||||
mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, mz_uint level_and_flags);
|
||||
|
||||
/* Like mz_zip_writer_add_mem(), except you can specify a file comment field, and optionally supply the function with already compressed data. */
|
||||
/* uncomp_size/uncomp_crc32 are only used if the MZ_ZIP_FLAG_COMPRESSED_DATA flag is specified. */
|
||||
mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
|
||||
mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
|
||||
mz_uint64 uncomp_size, mz_uint32 uncomp_crc32);
|
||||
|
||||
mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
|
||||
mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len,
|
||||
const char *user_extra_data_central, mz_uint user_extra_data_central_len);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_mem_ex_v2(mz_zip_archive *pZip, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags,
|
||||
mz_uint64 uncomp_size, mz_uint32 uncomp_crc32, MZ_TIME_T *last_modified, const char *user_extra_data_local, mz_uint user_extra_data_local_len,
|
||||
const char *user_extra_data_central, mz_uint user_extra_data_central_len);
|
||||
|
||||
/* Adds the contents of a file to an archive. This function also records the disk file's modified time into the archive. */
|
||||
/* File data is supplied via a read callback function. User mz_zip_writer_add_(c)file to add a file directly.*/
|
||||
mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 size_to_add,
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_read_buf_callback(mz_zip_archive *pZip, const char *pArchive_name, mz_file_read_func read_callback, void* callback_opaque, mz_uint64 max_size,
|
||||
const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len,
|
||||
const char *user_extra_data_central, mz_uint user_extra_data_central_len);
|
||||
|
||||
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
/* Adds the contents of a disk file to an archive. This function also records the disk file's modified time into the archive. */
|
||||
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */
|
||||
mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_file(mz_zip_archive *pZip, const char *pArchive_name, const char *pSrc_filename, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
|
||||
|
||||
/* Like mz_zip_writer_add_file(), except the file data is read from the specified FILE stream. */
|
||||
mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 size_to_add,
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_cfile(mz_zip_archive *pZip, const char *pArchive_name, MZ_FILE *pSrc_file, mz_uint64 max_size,
|
||||
const MZ_TIME_T *pFile_time, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, const char *user_extra_data_local, mz_uint user_extra_data_local_len,
|
||||
const char *user_extra_data_central, mz_uint user_extra_data_central_len);
|
||||
#endif
|
||||
|
||||
/* Adds a file to an archive by fully cloning the data from another archive. */
|
||||
/* This function fully clones the source file's compressed data (no recompression), along with its full filename, extra data (it may add or modify the zip64 local header extra data field), and the optional descriptor following the compressed data. */
|
||||
mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_add_from_zip_reader(mz_zip_archive *pZip, mz_zip_archive *pSource_zip, mz_uint src_file_index);
|
||||
|
||||
/* Finalizes the archive by writing the central directory records followed by the end of central directory record. */
|
||||
/* After an archive is finalized, the only valid call on the mz_zip_archive struct is mz_zip_writer_end(). */
|
||||
/* An archive must be manually finalized by calling this function for it to be valid. */
|
||||
mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_finalize_archive(mz_zip_archive *pZip);
|
||||
|
||||
/* Finalizes a heap archive, returning a poiner to the heap block and its size. */
|
||||
/* Finalizes a heap archive, returning a pointer to the heap block and its size. */
|
||||
/* The heap block will be allocated using the mz_zip_archive's alloc/realloc callbacks. */
|
||||
mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_finalize_heap_archive(mz_zip_archive *pZip, void **ppBuf, size_t *pSize);
|
||||
|
||||
/* Ends archive writing, freeing all allocations, and closing the output file if mz_zip_writer_init_file() was used. */
|
||||
/* Note for the archive to be valid, it *must* have been finalized before ending (this function will not do it for you). */
|
||||
mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
|
||||
MINIZ_EXPORT mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
|
||||
|
||||
/* -------- Misc. high-level helper functions: */
|
||||
|
||||
@@ -1320,14 +1402,16 @@ mz_bool mz_zip_writer_end(mz_zip_archive *pZip);
|
||||
/* Note this is NOT a fully safe operation. If it crashes or dies in some way your archive can be left in a screwed up state (without a central directory). */
|
||||
/* level_and_flags - compression level (0-10, see MZ_BEST_SPEED, MZ_BEST_COMPRESSION, etc.) logically OR'd with zero or more mz_zip_flags, or just set to MZ_DEFAULT_COMPRESSION. */
|
||||
/* TODO: Perhaps add an option to leave the existing central dir in place in case the add dies? We could then truncate the file (so the old central dir would be at the end) if something goes wrong. */
|
||||
mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
|
||||
mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr);
|
||||
MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags);
|
||||
MINIZ_EXPORT mz_bool mz_zip_add_mem_to_archive_file_in_place_v2(const char *pZip_filename, const char *pArchive_name, const void *pBuf, size_t buf_size, const void *pComment, mz_uint16 comment_size, mz_uint level_and_flags, mz_zip_error *pErr);
|
||||
|
||||
#ifndef MINIZ_NO_STDIO
|
||||
/* Reads a single file from an archive into a heap block. */
|
||||
/* If pComment is not NULL, only the file with the specified comment will be extracted. */
|
||||
/* Returns NULL on failure. */
|
||||
void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags);
|
||||
void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr);
|
||||
MINIZ_EXPORT void *mz_zip_extract_archive_file_to_heap(const char *pZip_filename, const char *pArchive_name, size_t *pSize, mz_uint flags);
|
||||
MINIZ_EXPORT void *mz_zip_extract_archive_file_to_heap_v2(const char *pZip_filename, const char *pArchive_name, const char *pComment, size_t *pSize, mz_uint flags, mz_zip_error *pErr);
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef MINIZ_NO_ARCHIVE_WRITING_APIS */
|
||||
|
||||
46
code/components/miniz/readme.md
Normal file
46
code/components/miniz/readme.md
Normal file
@@ -0,0 +1,46 @@
|
||||
## Miniz
|
||||
|
||||
Miniz is a lossless, high performance data compression library in a single source file that implements the zlib (RFC 1950) and Deflate (RFC 1951) compressed data format specification standards. It supports the most commonly used functions exported by the zlib library, but is a completely independent implementation so zlib's licensing requirements do not apply. Miniz also contains simple to use functions for writing .PNG format image files and reading/writing/appending .ZIP format archives. Miniz's compression speed has been tuned to be comparable to zlib's, and it also has a specialized real-time compressor function designed to compare well against fastlz/minilzo.
|
||||
|
||||
## Usage
|
||||
|
||||
Releases are available at the [releases page](https://github.com/richgel999/miniz/releases) as a pair of `miniz.c`/`miniz.h` files which can be simply added to a project. To create this file pair the different source and header files are [amalgamated](https://www.sqlite.org/amalgamation.html) during build. Alternatively use as cmake or meson module (or build system of your choice).
|
||||
|
||||
## Features
|
||||
|
||||
* MIT licensed
|
||||
* A portable, single source and header file library written in plain C. Tested with GCC, clang and Visual Studio.
|
||||
* Easily tuned and trimmed down by defines
|
||||
* A drop-in replacement for zlib's most used API's (tested in several open source projects that use zlib, such as libpng and libzip).
|
||||
* Fills a single threaded performance vs. compression ratio gap between several popular real-time compressors and zlib. For example, at level 1, miniz.c compresses around 5-9% better than minilzo, but is approx. 35% slower. At levels 2-9, miniz.c is designed to compare favorably against zlib's ratio and speed. See the miniz performance comparison page for example timings.
|
||||
* Not a block based compressor: miniz.c fully supports stream based processing using a coroutine-style implementation. The zlib-style API functions can be called a single byte at a time if that's all you've got.
|
||||
* Easy to use. The low-level compressor (tdefl) and decompressor (tinfl) have simple state structs which can be saved/restored as needed with simple memcpy's. The low-level codec API's don't use the heap in any way.
|
||||
* Entire inflater (including optional zlib header parsing and Adler-32 checking) is implemented in a single function as a coroutine, which is separately available in a small (~550 line) source file: miniz_tinfl.c
|
||||
* A fairly complete (but totally optional) set of .ZIP archive manipulation and extraction API's. The archive functionality is intended to solve common problems encountered in embedded, mobile, or game development situations. (The archive API's are purposely just powerful enough to write an entire archiver given a bit of additional higher-level logic.)
|
||||
|
||||
## Building miniz - Using vcpkg
|
||||
|
||||
You can download and install miniz using the [vcpkg](https://github.com/Microsoft/vcpkg) dependency manager:
|
||||
|
||||
git clone https://github.com/Microsoft/vcpkg.git
|
||||
cd vcpkg
|
||||
./bootstrap-vcpkg.sh
|
||||
./vcpkg integrate install
|
||||
./vcpkg install miniz
|
||||
|
||||
The miniz port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
|
||||
|
||||
## Known Problems
|
||||
|
||||
* No support for encrypted archives. Not sure how useful this stuff is in practice.
|
||||
* Minimal documentation. The assumption is that the user is already familiar with the basic zlib API. I need to write an API wiki - for now I've tried to place key comments before each enum/API, and I've included 6 examples that demonstrate how to use the module's major features.
|
||||
|
||||
## Special Thanks
|
||||
|
||||
Thanks to Alex Evans for the PNG writer function. Also, thanks to Paul Holden and Thorsten Scheuermann for feedback and testing, Matt Pritchard for all his encouragement, and Sean Barrett's various public domain libraries for inspiration (and encouraging me to write miniz.c in C, which was much more enjoyable and less painful than I thought it would be considering I've been programming in C++ for so long).
|
||||
|
||||
Thanks to Bruce Dawson for reporting a problem with the level_and_flags archive API parameter (which is fixed in v1.12) and general feedback, and Janez Zemva for indirectly encouraging me into writing more examples.
|
||||
|
||||
## Patents
|
||||
|
||||
I was recently asked if miniz avoids patent issues. miniz purposely uses the same core algorithms as the ones used by zlib. The compressor uses vanilla hash chaining as described [here](https://datatracker.ietf.org/doc/html/rfc1951#section-4). Also see the [gzip FAQ](https://web.archive.org/web/20160308045258/http://www.gzip.org/#faq11). In my opinion, if miniz falls prey to a patent attack then zlib/gzip are likely to be at serious risk too.
|
||||
8
code/components/miniz/readme2.md
Normal file
8
code/components/miniz/readme2.md
Normal file
@@ -0,0 +1,8 @@
|
||||
The files in this folder are a direct extraction of the miniz release from https://github.com/richgel999/miniz/releases
|
||||
|
||||
It should be possible to include the repo directly as a submodule, how ever it causes various issues. See also
|
||||
- https://github.com/richgel999/miniz/issues/145
|
||||
- https://github.com/espressif/esptool/pull/500#issuecomment-574879468
|
||||
|
||||
For sumplicity we therefore use the release files as suggested in the readme.
|
||||
Additionally we added the CMakeLists.txt and this readme.
|
||||
Submodule code/components/tflite-micro-esp-examples updated: 2a93aa3106...095f55a6ee
@@ -39,7 +39,12 @@ set(VERSION "const char* GIT_REV=\"${GIT_REV}${GIT_DIFF}\";
|
||||
const char* GIT_TAG=\"${GIT_TAG}\";
|
||||
const char* GIT_BRANCH=\"${GIT_BRANCH}\";
|
||||
const char* BUILD_TIME=\"${BUILD_TIME}\";")
|
||||
set(VERSION_HTML "${GIT_BRANCH}, ${GIT_REV}${GIT_DIFF}, ${GIT_TAG}")
|
||||
|
||||
if ("${GIT_TAG}" STREQUAL "") # Tag not set, show branch
|
||||
set(VERSION_HTML "Development-Branch: ${GIT_BRANCH} (Commit: ${GIT_REV}${GIT_DIFF})\n${GIT_REV}")
|
||||
else() # Tag is set, ignore branch
|
||||
set(VERSION_HTML "Release: ${GIT_TAG} (Commit: ${GIT_REV}${GIT_DIFF})\n${GIT_REV}")
|
||||
endif()
|
||||
|
||||
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp)
|
||||
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/version.cpp VERSION_)
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "ClassControllCamera.h"
|
||||
#include "server_main.h"
|
||||
#include "server_camera.h"
|
||||
#include "server_mqtt.h"
|
||||
#include "Helper.h"
|
||||
|
||||
extern const char* GIT_TAG;
|
||||
@@ -34,6 +35,8 @@ extern const char* GIT_REV;
|
||||
extern const char* GIT_BRANCH;
|
||||
extern const char* BUILD_TIME;
|
||||
|
||||
extern std::string getHTMLversion(void);
|
||||
extern std::string getHTMLcommit(void);
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
@@ -48,7 +51,7 @@ extern const char* BUILD_TIME;
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
static const char *TAGMAIN = "main";
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
//#define FLASH_GPIO GPIO_NUM_4
|
||||
|
||||
@@ -61,7 +64,7 @@ bool Init_NVS_SDCard()
|
||||
}
|
||||
////////////////////////////////////////////////
|
||||
|
||||
ESP_LOGI(TAGMAIN, "Using SDMMC peripheral");
|
||||
ESP_LOGI(TAG, "Using SDMMC peripheral");
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
|
||||
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||
@@ -103,16 +106,17 @@ bool Init_NVS_SDCard()
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(TAGMAIN, "Failed to mount filesystem. "
|
||||
ESP_LOGE(TAG, "Failed to mount filesystem. "
|
||||
"If you want the card to be formatted, set format_if_mount_failed = true.");
|
||||
} else {
|
||||
ESP_LOGE(TAGMAIN, "Failed to initialize the card (%s). "
|
||||
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
||||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
SaveSDCardInfo(card);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -124,7 +128,7 @@ void task_NoSDBlink(void *pvParameter)
|
||||
|
||||
TickType_t xDelay;
|
||||
xDelay = 100 / portTICK_PERIOD_MS;
|
||||
printf("SD-Card could not be inialized - STOP THE PROGRAMM HERE\n");
|
||||
ESP_LOGD(TAG, "SD-Card could not be inialized - STOP THE PROGRAMM HERE");
|
||||
|
||||
while (1)
|
||||
{
|
||||
@@ -141,124 +145,157 @@ void task_NoSDBlink(void *pvParameter)
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
TickType_t xDelay;
|
||||
string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + "', Tag: '" + std::string(GIT_TAG) + \
|
||||
"', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME);
|
||||
|
||||
printf("=============================================================================================\n");
|
||||
printf("%s\n", versionFormated.c_str());
|
||||
printf("=============================================================================================\n");
|
||||
bool initSucessful = true;
|
||||
|
||||
ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted
|
||||
|
||||
PowerResetCamera();
|
||||
esp_err_t cam = Camera.InitCam();
|
||||
esp_err_t camStatus = Camera.InitCam();
|
||||
Camera.LightOnOff(false);
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
printf("After camera initialization: sleep for : %ldms\n", (long) xDelay);
|
||||
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
|
||||
if (!Init_NVS_SDCard())
|
||||
{
|
||||
xTaskCreate(&task_NoSDBlink, "task_NoSDBlink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
return;
|
||||
};
|
||||
|
||||
string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \
|
||||
"', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \
|
||||
", Web UI: " + getHTMLversion();
|
||||
|
||||
if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix
|
||||
string versionFormated = "Tag: '" + std::string(GIT_TAG) + "', " + versionFormated;
|
||||
}
|
||||
|
||||
LogFile.CreateLogDirectories();
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Startup ====================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
|
||||
|
||||
CheckOTAUpdate();
|
||||
CheckUpdate();
|
||||
|
||||
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL;
|
||||
LoadWlanFromFile("/sdcard/wlan.ini", ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
|
||||
if (ssid != NULL && passwd != NULL)
|
||||
#ifdef __HIDE_PASSWORD
|
||||
printf("\nWLan: %s, XXXXXX\n", ssid);
|
||||
ESP_LOGD(TAG, "WLan: %s, XXXXXX", ssid);
|
||||
#else
|
||||
printf("\nWLan: %s, %s\n", ssid, passwd);
|
||||
ESP_LOGD(TAG, "WLan: %s, %s", ssid, passwd);
|
||||
#endif
|
||||
|
||||
else
|
||||
printf("No SSID and PASSWORD set!!!");
|
||||
ESP_LOGD(TAG, "No SSID and PASSWORD set!!!");
|
||||
|
||||
if (hostname != NULL)
|
||||
printf("Hostename: %s\n", hostname);
|
||||
ESP_LOGD(TAG, "Hostename: %s", hostname);
|
||||
else
|
||||
printf("Hostname not set.\n");
|
||||
ESP_LOGD(TAG, "Hostname not set");
|
||||
|
||||
if (ip != NULL && gateway != NULL && netmask != NULL)
|
||||
printf("Fixed IP: %s, Gateway %s, Netmask %s\n", ip, gateway, netmask);
|
||||
ESP_LOGD(TAG, "Fixed IP: %s, Gateway %s, Netmask %s", ip, gateway, netmask);
|
||||
if (dns != NULL)
|
||||
printf("DNS IP: %s\n", dns);
|
||||
ESP_LOGD(TAG, "DNS IP: %s", dns);
|
||||
|
||||
|
||||
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
printf("main: sleep for : %ldms\n", (long) xDelay);
|
||||
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
setup_time();
|
||||
|
||||
if (!setup_time()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed. Will restart in 5 minutes!");
|
||||
initSucessful = false;
|
||||
}
|
||||
|
||||
setBootTime();
|
||||
LogFile.WriteToFile("=============================================================================================");
|
||||
LogFile.WriteToFile("=================================== Main Started ============================================");
|
||||
LogFile.WriteToFile("=============================================================================================");
|
||||
LogFile.WriteToFile(versionFormated);
|
||||
LogFile.SwitchOnOff(false);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================== Main Started =================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
|
||||
if (getHTMLcommit() != std::string(GIT_REV)) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Web UI version (") + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ") !");
|
||||
}
|
||||
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
printf("time %s\n", zw.c_str());
|
||||
ESP_LOGD(TAG, "time %s", zw.c_str());
|
||||
|
||||
size_t _hsize = getESPHeapSize();
|
||||
if (_hsize < 4000000)
|
||||
{
|
||||
std::string _zws = "Not enough PSRAM available. Expected 4.194.304 MByte - available: " + std::to_string(_hsize);
|
||||
_zws = _zws + "\nEither not initialzed, too small (2MByte only) or not present at all. Firmware cannot start!!";
|
||||
printf(_zws.c_str());
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile(_zws);
|
||||
LogFile.SwitchOnOff(false);
|
||||
} else {
|
||||
if (cam != ESP_OK) {
|
||||
ESP_LOGE(TAGMAIN, "Failed to initialize camera module. "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
_zws = _zws + "\nEither not initialized, too small (2MByte only) or not present at all. Firmware cannot start!!";
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zws);
|
||||
} else { // Bad Camera Status, retry init
|
||||
if (camStatus != ESP_OK) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying...");
|
||||
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Failed to initialize camera module. "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
LogFile.SwitchOnOff(false);
|
||||
} else {
|
||||
// Test Camera
|
||||
PowerResetCamera();
|
||||
esp_err_t camStatus = Camera.InitCam();
|
||||
Camera.LightOnOff(false);
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "After camera initialization: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
if (camStatus != ESP_OK) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize camera module. Will restart in 5 minutes!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
|
||||
initSucessful = false;
|
||||
}
|
||||
} else { // Test Camera
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAGMAIN, "esp_camera_fb_get: Camera Capture Failed");
|
||||
LogFile.SwitchOnOff(true);
|
||||
LogFile.WriteToFile("Camera cannot be initialzed. "
|
||||
"System will reboot.");
|
||||
doReboot();
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialzed. Will restart in 5 minutes!");
|
||||
initSucessful = false;
|
||||
}
|
||||
else {
|
||||
esp_camera_fb_return(fb);
|
||||
Camera.LightOnOff(false);
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
Camera.LightOnOff(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
printf("main: sleep for : %ldms\n", (long) xDelay*10);
|
||||
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10);
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
printf("starting server\n");
|
||||
ESP_LOGD(TAG, "starting servers");
|
||||
|
||||
server = start_webserver();
|
||||
register_server_camera_uri(server);
|
||||
register_server_tflite_uri(server);
|
||||
register_server_file_uri(server, "/sdcard");
|
||||
register_server_ota_sdcard_uri(server);
|
||||
register_server_mqtt_uri(server);
|
||||
|
||||
gpio_handler_create(server);
|
||||
|
||||
printf("vor reg server main\n");
|
||||
ESP_LOGD(TAG, "vor reg server main");
|
||||
register_server_main_uri(server, "/sdcard");
|
||||
|
||||
printf("vor dotautostart\n");
|
||||
TFliteDoAutoStart();
|
||||
|
||||
if (initSucessful) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!");
|
||||
ESP_LOGD(TAG, "vor do autostart");
|
||||
TFliteDoAutoStart();
|
||||
}
|
||||
else { // Initialization failed
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 5 minutes!");
|
||||
vTaskDelay(60*4000 / portTICK_RATE_MS); // Wait 4 minutes to give time to do an OTA or fetch the log
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart in 1 minute!");
|
||||
vTaskDelay(60*1000 / portTICK_RATE_MS); // Wait 1 minute to give time to do an OTA or fetch the log
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Will restart now!");
|
||||
doReboot();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,9 @@
|
||||
#include "esp_wifi.h"
|
||||
|
||||
#include "server_tflite.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
@@ -22,7 +25,7 @@
|
||||
httpd_handle_t server = NULL;
|
||||
std::string starttime = "";
|
||||
|
||||
static const char *TAG_SERVERMAIN = "server-main";
|
||||
static const char *TAG = "MAIN SERVER";
|
||||
|
||||
/* An HTTP GET handler */
|
||||
esp_err_t info_get_handler(httpd_req_t *req)
|
||||
@@ -31,18 +34,18 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
LogFile.WriteHeapInfo("info_get_handler - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile("info_get_handler");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "info_get_handler");
|
||||
char _query[200];
|
||||
char _valuechar[30];
|
||||
std::string _task;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
printf("Query: "); printf(_query); printf("\n");
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "type", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
printf("type is found"); printf(_valuechar); printf("\n");
|
||||
ESP_LOGD(TAG, "type is found: %s", _valuechar);
|
||||
_task = std::string(_valuechar);
|
||||
}
|
||||
};
|
||||
@@ -55,50 +58,45 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
if (_task.compare("GitTag") == 0)
|
||||
else if (_task.compare("GitTag") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_version());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (_task.compare("GitRevision") == 0)
|
||||
else if (_task.compare("GitRevision") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_revision());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("BuildTime") == 0)
|
||||
else if (_task.compare("BuildTime") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, build_time());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("GitBaseBranch") == 0)
|
||||
else if (_task.compare("FirmwareVersion") == 0)
|
||||
{
|
||||
string buf = "Branch: '" + std::string(GIT_BRANCH) + "', Tag: '" + std::string(GIT_TAG) + \
|
||||
"', Revision: " + std::string(GIT_REV);
|
||||
string buf;
|
||||
if (std::string(GIT_TAG) == "") { // Tag not set, show branch
|
||||
buf = "Development-Branch: " + std::string(GIT_BRANCH);
|
||||
}
|
||||
else { // Tag is set, ignore branch
|
||||
buf = "Release: " + std::string(GIT_TAG);
|
||||
}
|
||||
buf = buf + " (Commit: " + std::string(GIT_REV) + ")";
|
||||
httpd_resp_sendstr_chunk(req, buf.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("HTMLVersion") == 0)
|
||||
else if (_task.compare("HTMLVersion") == 0)
|
||||
{
|
||||
// std::string zw;
|
||||
// zw = std::string(getHTMLversion());
|
||||
httpd_resp_sendstr_chunk(req, getHTMLversion());
|
||||
httpd_resp_sendstr_chunk(req, getHTMLversion().c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("Hostname") == 0)
|
||||
else if (_task.compare("Hostname") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string(hostname);
|
||||
@@ -106,8 +104,7 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("IP") == 0)
|
||||
else if (_task.compare("IP") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getIPAddress();
|
||||
@@ -115,8 +112,7 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("SSID") == 0)
|
||||
else if (_task.compare("SSID") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getSSID();
|
||||
@@ -124,8 +120,7 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
if (_task.compare("FlowStatus") == 0)
|
||||
else if (_task.compare("FlowStatus") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string("FlowStatus");
|
||||
@@ -133,6 +128,62 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardFreePartitionSpace") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardFreePartitionSpace();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionAllocationSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionAllocationSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardManufacturer") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardManufacturer();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardName") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardName();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardCapacity") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardCapacity();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardSectorSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardSectorSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -153,7 +204,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
#endif
|
||||
|
||||
char filepath[50];
|
||||
printf("uri: %s\n", req->uri);
|
||||
ESP_LOGD(TAG, "uri: %s\n", req->uri);
|
||||
int _pos;
|
||||
esp_err_t res;
|
||||
|
||||
@@ -162,7 +213,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, base_path,
|
||||
req->uri - 1, sizeof(filepath));
|
||||
printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "1 uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
if ((strcmp(req->uri, "/") == 0))
|
||||
{
|
||||
@@ -180,16 +231,16 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
}
|
||||
|
||||
if (filetosend == "/sdcard/html/index.html" && isSetupModusActive()) {
|
||||
printf("System is in setup mode --> index.html --> setup.html");
|
||||
ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html");
|
||||
filetosend = "/sdcard/html/setup.html";
|
||||
}
|
||||
|
||||
printf("Filename: %s\n", filename);
|
||||
ESP_LOGD(TAG, "Filename: %s", filename);
|
||||
|
||||
printf("File requested: %s\n", filetosend.c_str());
|
||||
ESP_LOGD(TAG, "File requested: %s", filetosend.c_str());
|
||||
|
||||
if (!filename) {
|
||||
ESP_LOGE(TAG_SERVERMAIN, "Filename is too long");
|
||||
ESP_LOGE(TAG, "Filename is too long");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
@@ -216,17 +267,17 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
esp_err_t img_tmp_handler(httpd_req_t *req)
|
||||
{
|
||||
char filepath[50];
|
||||
printf("uri: %s\n", req->uri);
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
char *base_path = (char*) req->user_ctx;
|
||||
std::string filetosend(base_path);
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, base_path,
|
||||
req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath));
|
||||
printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "1 uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
filetosend = filetosend + "/img_tmp/" + std::string(filename);
|
||||
printf("File to upload: %s\n", filetosend.c_str());
|
||||
ESP_LOGD(TAG, "File to upload: %s", filetosend.c_str());
|
||||
|
||||
esp_err_t res = send_file(req, filetosend);
|
||||
if (res != ESP_OK)
|
||||
@@ -245,17 +296,17 @@ esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
|
||||
|
||||
char filepath[50];
|
||||
|
||||
printf("uri: %s\n", req->uri);
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
char *base_path = (char*) req->user_ctx;
|
||||
std::string filetosend(base_path);
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, base_path,
|
||||
req->uri + sizeof("/img_tmp/") - 1, sizeof(filepath));
|
||||
printf("1 uri: %s, filename: %s, filepath: %s\n", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "1 uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
|
||||
filetosend = std::string(filename);
|
||||
printf("File to upload: %s\n", filetosend.c_str());
|
||||
ESP_LOGD(TAG, "File to upload: %s", filetosend.c_str());
|
||||
|
||||
if (filetosend == "raw.jpg")
|
||||
{
|
||||
@@ -326,7 +377,7 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
|
||||
void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
{
|
||||
httpd_uri_t info_get_handle = {
|
||||
.uri = "/version", // Match all URIs of type /path/to/file
|
||||
.uri = "/info", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = info_get_handler,
|
||||
.user_ctx = (void*) base_path // Pass server data as context
|
||||
@@ -382,7 +433,7 @@ httpd_handle_t start_webserver(void)
|
||||
config.server_port = 80;
|
||||
config.ctrl_port = 32768;
|
||||
config.max_open_sockets = 5; //20210921 --> vorher 7
|
||||
config.max_uri_handlers = 30; // vorher 24
|
||||
config.max_uri_handlers = 37; // vorher 24, 20220511: 35
|
||||
config.max_resp_headers = 8;
|
||||
config.backlog_conn = 5;
|
||||
config.lru_purge_enable = true; // dadurch werden alte Verbindungen gekappt, falls neue benögt werden.
|
||||
@@ -400,14 +451,14 @@ httpd_handle_t start_webserver(void)
|
||||
starttime = gettimestring("%Y%m%d-%H%M%S");
|
||||
|
||||
// Start the httpd server
|
||||
ESP_LOGI(TAG_SERVERMAIN, "Starting server on port: '%d'", config.server_port);
|
||||
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
||||
if (httpd_start(&server, &config) == ESP_OK) {
|
||||
// Set URI handlers
|
||||
ESP_LOGI(TAG_SERVERMAIN, "Registering URI handlers");
|
||||
ESP_LOGI(TAG, "Registering URI handlers");
|
||||
return server;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG_SERVERMAIN, "Error starting server!");
|
||||
ESP_LOGI(TAG, "Error starting server!");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -422,7 +473,7 @@ void disconnect_handler(void* arg, esp_event_base_t event_base,
|
||||
{
|
||||
httpd_handle_t* server = (httpd_handle_t*) arg;
|
||||
if (*server) {
|
||||
ESP_LOGI(TAG_SERVERMAIN, "Stopping webserver");
|
||||
ESP_LOGI(TAG, "Stopping webserver");
|
||||
stop_webserver(*server);
|
||||
*server = NULL;
|
||||
}
|
||||
@@ -433,7 +484,7 @@ void connect_handler(void* arg, esp_event_base_t event_base,
|
||||
{
|
||||
httpd_handle_t* server = (httpd_handle_t*) arg;
|
||||
if (*server == NULL) {
|
||||
ESP_LOGI(TAG_SERVERMAIN, "Starting webserver");
|
||||
ESP_LOGI(TAG, "Starting webserver");
|
||||
*server = start_webserver();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,20 +38,35 @@ const char* libfive_git_branch(void)
|
||||
}
|
||||
|
||||
|
||||
char _char_getHTMLversion[50]="NaN\0";
|
||||
|
||||
const char* getHTMLversion(void){
|
||||
std::string getHTMLversion(void){
|
||||
char buf[100]="?\0";
|
||||
FILE* pFile;
|
||||
string fn = FormatFileName("/sdcard/html/version.txt");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
if (pFile == NULL)
|
||||
return _char_getHTMLversion;
|
||||
return std::string(buf);
|
||||
|
||||
fgets(_char_getHTMLversion, sizeof(_char_getHTMLversion), pFile);
|
||||
fgets(buf, sizeof(buf), pFile); // Line 1: Version
|
||||
fclose(pFile);
|
||||
|
||||
return _char_getHTMLversion;
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
std::string getHTMLcommit(void){
|
||||
char buf[100]="?\0";
|
||||
FILE* pFile;
|
||||
string fn = FormatFileName("/sdcard/html/version.txt");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
if (pFile == NULL)
|
||||
return std::string(buf);
|
||||
|
||||
fgets(buf, sizeof(buf), pFile); // Line 1: Version -> ignored
|
||||
fgets(buf, sizeof(buf), pFile); // Line 2: Commit
|
||||
fclose(pFile);
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
#endif // _VERSION_H
|
||||
@@ -13,9 +13,7 @@
|
||||
src_dir = main
|
||||
|
||||
[env:esp32cam]
|
||||
platform = espressif32@4.4.0
|
||||
;platform = espressif32@5.1.0
|
||||
;platform = espressif32
|
||||
platform = espressif32@5.2.0
|
||||
board = esp32cam
|
||||
;board = m5stack-core-esp32
|
||||
framework = espidf
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
# sdkconfig.esp32cam to apply your changes!
|
||||
##################################################
|
||||
|
||||
CONFIG_TASK_WDT=n
|
||||
CONFIG_TASK_WDT_CHECK_IDLE_TASK=n
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_DEFAULT=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
#include <unity.h>
|
||||
#include <ClassFlowCNNGeneral.h>
|
||||
|
||||
class UnderTestCNNGeneral : public ClassFlowCNNGeneral {
|
||||
public:
|
||||
UnderTestCNNGeneral( ClassFlowAlignment *_flowalign, t_CNNType _cnntype) :
|
||||
ClassFlowCNNGeneral(_flowalign, _cnntype) {};
|
||||
|
||||
using ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief
|
||||
*
|
||||
* Transition = x.8 - x.2 hier keine Transition in den Testfaellen
|
||||
* Versatz = dig=x.n, ana= n.y: kein Versatz, da beide "n" gleich
|
||||
*/
|
||||
void test_analogToDigit_Standard() {
|
||||
|
||||
UnderTestCNNGeneral* undertest = new UnderTestCNNGeneral(nullptr, Digital100);
|
||||
|
||||
// 4.8 ist eine "hängende" 5. Heißt sie ist nicht bis auf 5.0 umgesprungen.
|
||||
// ab Transition sollte trotzdem ein "hängendes Digit" gerundet werden.
|
||||
// Transition = ja
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(5, undertest->ZeigerEvalAnalogToDigitNeu(4.8, 8.0, 8, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issue-1344032217
|
||||
// Standard: dig=9.6, ana=6.8 => erg=9
|
||||
// Transition = nein
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(9, undertest->ZeigerEvalAnalogToDigitNeu( 9.6, 6.8, 6, 9.2));
|
||||
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1220365920
|
||||
// Standard: dig=4.6, ana=6.2 => erg=4
|
||||
// Transition = nein
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(4, undertest->ZeigerEvalAnalogToDigitNeu( 4.6, 6.2, 6, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
|
||||
// Hängendes digit ()
|
||||
// Standard: dig=6.8, ana=8.6 => erg=7
|
||||
// Transition = nein
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(7, undertest->ZeigerEvalAnalogToDigitNeu( 6.8, 8.6, 6, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
|
||||
// Ebenfalls Hängendes digit () bei kleinem Zeiger nach 0-Durchlauf
|
||||
// Standard: dig=6.8, ana=1.0 => erg=7
|
||||
// Transition = nein
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(7, undertest->ZeigerEvalAnalogToDigitNeu( 6.8, 1.0, 1, 9.2));
|
||||
|
||||
|
||||
}
|
||||
|
||||
void test_analogToDigit_Transition() {
|
||||
UnderTestCNNGeneral* undertest = new UnderTestCNNGeneral(nullptr, Digital100);
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1222672175
|
||||
// Standard: dig=3.9, ana=9.7 => erg=3
|
||||
// Transition = ja
|
||||
// Nulldurchgang = nein
|
||||
// Versatz = nein
|
||||
TEST_ASSERT_EQUAL_INT(3, undertest->ZeigerEvalAnalogToDigitNeu( 3.9, 9.7, 9, 9.2));
|
||||
|
||||
// ohne Referenz
|
||||
// Standard: dig=4.0, ana=9.1 => erg=4
|
||||
// Transition = ja
|
||||
// Nulldurchgang = nein
|
||||
// Versatz = nein
|
||||
// Besonderheit: Digit ist bei analog 9.1 noch nicht losgelaufen
|
||||
TEST_ASSERT_EQUAL_INT(4, undertest->ZeigerEvalAnalogToDigitNeu( 4.0, 9.1, 9, 9.2));
|
||||
|
||||
// ohne Referenz
|
||||
// Standard: dig=9.8, ana=0.1, ana_2=9.9 => erg=9
|
||||
// Transition = ja
|
||||
// Nulldurchgang = nein
|
||||
// Versatz = nein
|
||||
// Besonderheit: analog wird durch vorherigen analog wieder auf 9 gesetzt
|
||||
TEST_ASSERT_EQUAL_INT(9, undertest->ZeigerEvalAnalogToDigitNeu( 9.8, 0.1, 9, 9.2));
|
||||
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1277425333
|
||||
// Standard: dig=5.9, ana=9.4 => erg=9
|
||||
// Transition = ja
|
||||
// Nulldurchgang = nein
|
||||
// Versatz = nein
|
||||
// Besonderheit:
|
||||
TEST_ASSERT_EQUAL_INT(5, undertest->ZeigerEvalAnalogToDigitNeu( 5.9, 9.4, 9, 9.2));
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1282168030
|
||||
// Standard: dig=1.8, ana=7.8 => erg=9
|
||||
// Transition = ja
|
||||
// Nulldurchgang = nein
|
||||
// Versatz = nein
|
||||
// Besonderheit: Digit läuft mit Analog mit. Deshalb 1.8 (vs. 7.8)
|
||||
TEST_ASSERT_EQUAL_INT(1, undertest->ZeigerEvalAnalogToDigitNeu( 1.8, 7.8, 7, 7.7));
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
#include "test_flow_postrocess_helper.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "FLOW CTRL POSTPROC TEST";
|
||||
|
||||
UnderTestPost* setUpClassFlowPostprocessing(t_CNNType digType, t_CNNType anaType)
|
||||
{
|
||||
|
||||
ClassFlowCNNGeneral* _analog;
|
||||
ClassFlowCNNGeneral* _digit;
|
||||
std::vector<ClassFlow*> FlowControll;
|
||||
ClassFlowMakeImage* flowmakeimage;
|
||||
|
||||
// wird im doFlow verwendet
|
||||
flowmakeimage = new ClassFlowMakeImage(&FlowControll);
|
||||
FlowControll.push_back(flowmakeimage);
|
||||
|
||||
// Die Modeltypen werden gesetzt, da keine Modelle verwendet werden.
|
||||
_analog = new ClassFlowCNNGeneral(nullptr, anaType);
|
||||
|
||||
_digit = new ClassFlowCNNGeneral(nullptr, digType);
|
||||
|
||||
return new UnderTestPost(&FlowControll, _analog, _digit);
|
||||
|
||||
}
|
||||
|
||||
std::string process_doFlow(UnderTestPost* _underTestPost) {
|
||||
string time;
|
||||
|
||||
// run test
|
||||
TEST_ASSERT_TRUE(_underTestPost->doFlow(time));
|
||||
|
||||
return _underTestPost->getReadout(0);
|
||||
}
|
||||
|
||||
|
||||
std::string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType,
|
||||
bool checkConsistency, bool extendedResolution, int decimal_shift) {
|
||||
// setup the classundertest
|
||||
UnderTestPost* _undertestPost = init_do_flow(analog, digits, digType, checkConsistency, extendedResolution, decimal_shift);
|
||||
ESP_LOGD(TAG, "SetupClassFlowPostprocessing completed.");
|
||||
|
||||
string time;
|
||||
// run test
|
||||
TEST_ASSERT_TRUE(_undertestPost->doFlow(time));
|
||||
|
||||
std::string result = _undertestPost->getReadout(0);
|
||||
delete _undertestPost;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
UnderTestPost* init_do_flow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType,
|
||||
bool checkConsistency, bool extendedResolution, int decimal_shift) {
|
||||
|
||||
UnderTestPost* _undertestPost = setUpClassFlowPostprocessing(digType, Analogue100);
|
||||
|
||||
|
||||
// digits
|
||||
if (digits.size()>0) {
|
||||
general* gen_digit = _undertestPost->flowDigit->GetGENERAL("default", true);
|
||||
gen_digit->ROI.clear();
|
||||
for (int i = 0; i<digits.size(); i++) {
|
||||
roi* digitROI = new roi();
|
||||
string name = "digit_" + std::to_string(i);
|
||||
digitROI->name = name;
|
||||
digitROI->result_klasse = (int) digits[i];
|
||||
digitROI->result_float = digits[i];
|
||||
gen_digit->ROI.push_back(digitROI);
|
||||
}
|
||||
}
|
||||
|
||||
// analog
|
||||
if (analog.size()>0) {
|
||||
general* gen_analog = _undertestPost->flowAnalog->GetGENERAL("default", true);
|
||||
gen_analog->ROI.clear();
|
||||
|
||||
for (int i = 0; i<analog.size(); i++) {
|
||||
roi* anaROI = new roi();
|
||||
string name = "ana_1" + std::to_string(i);
|
||||
anaROI->name = name;
|
||||
anaROI->result_float = analog[i];
|
||||
gen_analog->ROI.push_back(anaROI);
|
||||
}
|
||||
} else {
|
||||
_undertestPost->flowAnalog = NULL;
|
||||
}
|
||||
ESP_LOGD(TAG, "Setting up of ROIs completed.");
|
||||
|
||||
_undertestPost->InitNUMBERS();
|
||||
|
||||
setConsitencyCheck(_undertestPost, checkConsistency);
|
||||
setExtendedResolution(_undertestPost, extendedResolution);
|
||||
setDecimalShift(_undertestPost, decimal_shift);
|
||||
|
||||
return _undertestPost;
|
||||
|
||||
}
|
||||
|
||||
void setPreValue(UnderTestPost* _underTestPost, double _preValue) {
|
||||
if (_preValue>0) {
|
||||
ESP_LOGD(TAG, "preValue=%f", _preValue);
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
(*NUMBERS)[_n]->PreValue = _preValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setAllowNegatives(UnderTestPost* _underTestPost, bool _allowNegatives) {
|
||||
ESP_LOGD(TAG, "checkConsistency=true");
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
(*NUMBERS)[_n]->AllowNegativeRates = _allowNegatives;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setConsitencyCheck(UnderTestPost* _underTestPost, bool _checkConsistency) {
|
||||
if (_checkConsistency) {
|
||||
ESP_LOGD(TAG, "checkConsistency=true");
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
(*NUMBERS)[_n]->checkDigitIncreaseConsistency = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void setExtendedResolution(UnderTestPost* _underTestPost, bool _extendedResolution) {
|
||||
if (_extendedResolution ) {
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
(*NUMBERS)[_n]->isExtendedResolution = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setDecimalShift(UnderTestPost* _underTestPost, int _decimal_shift) {
|
||||
if (_decimal_shift!=0) {
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
ESP_LOGD(TAG, "Setting decimal shift on number: %d to %d", _n, _decimal_shift);
|
||||
(*NUMBERS)[_n]->DecimalShift = _decimal_shift;
|
||||
(*NUMBERS)[_n]->DecimalShiftInitial = _decimal_shift;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void setAnalogdigitTransistionStart(UnderTestPost* _underTestPost, float _analogdigitTransistionStart) {
|
||||
if (_analogdigitTransistionStart!=0) {
|
||||
std::vector<NumberPost*>* NUMBERS = _underTestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
ESP_LOGD(TAG, "Setting decimal shift on number: %d to %f", _n, _analogdigitTransistionStart);
|
||||
(*NUMBERS)[_n]->AnalogDigitalTransitionStart = _analogdigitTransistionStart;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
#pragma once
|
||||
#ifndef TEST_FLOW_H
|
||||
#define TEST_FLOW_H
|
||||
#include <unity.h>
|
||||
#include <ClassFlowPostProcessing.h>
|
||||
#include <ClassFlowCNNGeneral.h>
|
||||
#include <ClassFlowMakeImage.h>
|
||||
#include <Helper.h>
|
||||
|
||||
|
||||
class UnderTestPost : public ClassFlowPostProcessing {
|
||||
public:
|
||||
UnderTestPost(std::vector<ClassFlow*>* lfc, ClassFlowCNNGeneral *_analog, ClassFlowCNNGeneral *_digit)
|
||||
: ClassFlowPostProcessing::ClassFlowPostProcessing(lfc, _analog, _digit) {}
|
||||
|
||||
using ClassFlowPostProcessing::InitNUMBERS;
|
||||
using ClassFlowPostProcessing::flowAnalog;
|
||||
using ClassFlowPostProcessing::flowDigit;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Set the Up Class Flow Postprocessing object
|
||||
*
|
||||
* @param digType the model type of digits
|
||||
* @param anaType the model type of analog
|
||||
* @return UnderTestPost* a created, but not setted up testobject
|
||||
*/
|
||||
UnderTestPost* setUpClassFlowPostprocessing(t_CNNType digType, t_CNNType anaType);
|
||||
|
||||
/**
|
||||
* @brief creates a testobject (including setup). AnalogType is Class100, because all analog types do the same.
|
||||
*
|
||||
* @param analog the analog recognitions
|
||||
* @param digits the digit recognitions
|
||||
* @param digType the digit model type (default Digital100)
|
||||
* @param checkConsistency sets property checkConsistency (default = false)
|
||||
* @param extendedResolution sets property extendedResolution (default = false)
|
||||
* @param decimal_shift set property decimal_shift (Nachkommastellen, default = 0)
|
||||
* @return UnderTestPost* the created testobject
|
||||
*/
|
||||
UnderTestPost* init_do_flow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType = Digital100,
|
||||
bool checkConsistency=false, bool extendedResolution=false, int decimal_shift=0);
|
||||
|
||||
/**
|
||||
* @brief creates a testobject an run do flow (including setup). AnalogType is Class100, because all analog types do the same.
|
||||
*
|
||||
* @param analog the analog recognitions
|
||||
* @param digits the digit recognitions
|
||||
* @param digType the digit model type (default Digital100)
|
||||
* @param checkConsistency sets property checkConsistency (default = false)
|
||||
* @param extendedResolution sets property extendedResolution (default = false)
|
||||
* @param decimal_shift set property decimal_shift (Nachkommastellen, default = 0)
|
||||
* @return std::string the return value of do_Flow is the Value as string
|
||||
*/
|
||||
std::string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType = Digital100,
|
||||
bool checkConsistency=false, bool extendedResolution=false, int decimal_shift=0);
|
||||
|
||||
/**
|
||||
* @brief run do_Flow on the testobject
|
||||
*
|
||||
* @param _underTestPost the testobject
|
||||
* @return std::string the return value of do_Flow is the Value as string
|
||||
*/
|
||||
std::string process_doFlow(UnderTestPost* _underTestPost);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the Consitency Check on testobject
|
||||
*
|
||||
* @param _UnderTestPost the testobject
|
||||
* @param _checkConsistency true/false if checkConsistency
|
||||
*/
|
||||
void setConsitencyCheck(UnderTestPost* _UnderTestPost, bool _checkConsistency);
|
||||
|
||||
/**
|
||||
* @brief Set the Pre Value on testobject
|
||||
*
|
||||
* @param _UnderTestPost the testobject
|
||||
* @param _preValue the previous value
|
||||
*/
|
||||
void setPreValue(UnderTestPost* _UnderTestPost, double _preValue);
|
||||
|
||||
/**
|
||||
* @brief Set the Extended Resolution on undertest
|
||||
*
|
||||
* @param _UnderTestPost the testobject
|
||||
* @param _extendedResolution true/false
|
||||
*/
|
||||
void setExtendedResolution(UnderTestPost* _UnderTestPost, bool _extendedResolution);
|
||||
|
||||
/**
|
||||
* @brief Set the Decimal Shift (Nachkomma)
|
||||
*
|
||||
* @param _UnderTestPost the testobject
|
||||
* @param decimal_shift count of nachkomma
|
||||
*/
|
||||
void setDecimalShift(UnderTestPost* _UnderTestPost, int decimal_shift);
|
||||
|
||||
/**
|
||||
* @brief Set the Analogdigit Transistion Start
|
||||
*
|
||||
* @param _underTestPost the testobject
|
||||
* @param _analogdigitTransistionStart the analog to digit transition start
|
||||
*/
|
||||
void setAnalogdigitTransistionStart(UnderTestPost* _underTestPost, float _analogdigitTransistionStart);
|
||||
|
||||
/**
|
||||
* @brief Set the allowNegatives in testobject
|
||||
*
|
||||
* @param _underTestPost the testobject
|
||||
* @param _allowNegatives if should be set true or false
|
||||
*/
|
||||
void setAllowNegatives(UnderTestPost* _underTestPost, bool _allowNegatives);
|
||||
|
||||
#endif // TEST_FLOW_H
|
||||
@@ -0,0 +1,78 @@
|
||||
#include "test_flow_postrocess_helper.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Testfall für Überprüfung allowNegatives
|
||||
*
|
||||
*/
|
||||
void testNegative() {
|
||||
|
||||
|
||||
// Ohne decimal_shift
|
||||
std::vector<float> digits = { 1.2, 6.7};
|
||||
std::vector<float> analogs = { 9.5, 8.4};
|
||||
double preValue_extended = 16.985;
|
||||
double preValue = 16.98;
|
||||
|
||||
const char* expected = "16.98";
|
||||
|
||||
// extendResolution=false
|
||||
// da kein negativ, sollte kein Error auftreten
|
||||
UnderTestPost* underTestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
|
||||
setAllowNegatives(underTestPost, false);
|
||||
setPreValue(underTestPost, preValue);
|
||||
std::string result = process_doFlow(underTestPost);
|
||||
TEST_ASSERT_EQUAL_STRING("no error", underTestPost->getReadoutError().c_str());
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
delete underTestPost;
|
||||
|
||||
// extendResolution=true
|
||||
// da negativ im Rahmen (letzte Stelle -0.2 > ergebnis), kein Error
|
||||
// Aber der PreValue wird gesetzt
|
||||
underTestPost = init_do_flow(analogs, digits, Digital100, false, true, 0);
|
||||
setAllowNegatives(underTestPost, false);
|
||||
setPreValue(underTestPost, preValue_extended);
|
||||
result = process_doFlow(underTestPost);
|
||||
TEST_ASSERT_EQUAL_STRING("no error", underTestPost->getReadoutError().c_str());
|
||||
TEST_ASSERT_EQUAL_STRING(RundeOutput(preValue_extended, analogs.size()+1).c_str(), result.c_str());
|
||||
delete underTestPost;
|
||||
|
||||
// extendResolution=true
|
||||
// Tolleranz überschritten, Error wird gesetzt, kein ReturnValue
|
||||
preValue_extended = 16.988; // zu groß
|
||||
underTestPost = init_do_flow(analogs, digits, Digital100, false, true, 0);
|
||||
setAllowNegatives(underTestPost, false);
|
||||
setPreValue(underTestPost, preValue_extended);
|
||||
result = process_doFlow(underTestPost);
|
||||
TEST_ASSERT_EQUAL_STRING("Neg. Rate - Read: - Raw: 16.984 - Pre: 16.988 ", underTestPost->getReadoutError().c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", result.c_str());
|
||||
delete underTestPost;
|
||||
|
||||
// extendResolution=false
|
||||
// value < preValue
|
||||
preValue = 16.99; // zu groß
|
||||
underTestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
|
||||
setAllowNegatives(underTestPost, false);
|
||||
setPreValue(underTestPost, preValue_extended);
|
||||
result = process_doFlow(underTestPost);
|
||||
TEST_ASSERT_EQUAL_STRING("Neg. Rate - Read: - Raw: 16.98 - Pre: 16.99 ", underTestPost->getReadoutError().c_str());
|
||||
TEST_ASSERT_EQUAL_STRING("", result.c_str());
|
||||
delete underTestPost;
|
||||
|
||||
|
||||
// extendResolution=false
|
||||
// value < preValue
|
||||
// Aber Prüfung abgeschaltet => kein Fehler
|
||||
preValue = 16.99; // zu groß
|
||||
underTestPost = init_do_flow(analogs, digits, Digital100, false, false, 0);
|
||||
setAllowNegatives(underTestPost, true);
|
||||
setPreValue(underTestPost, preValue_extended);
|
||||
result = process_doFlow(underTestPost);
|
||||
TEST_ASSERT_EQUAL_STRING("no error", underTestPost->getReadoutError().c_str());
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
delete underTestPost;
|
||||
|
||||
}
|
||||
|
||||
@@ -1,37 +1,20 @@
|
||||
#include <unity.h>
|
||||
#include <ClassFlowPostProcessing.h>
|
||||
#include <ClassFlowCNNGeneral.h>
|
||||
#include <ClassFlowCNNGeneral.h>
|
||||
#include <ClassFlowMakeImage.h>
|
||||
|
||||
void setUpClassFlowPostprocessing(void);
|
||||
string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType = Digital100,
|
||||
bool checkConsistency=false, bool extendedResolution=false, int decimal_shift=0);
|
||||
|
||||
ClassFlowCNNGeneral* _analog;
|
||||
ClassFlowCNNGeneral* _digit;
|
||||
std::vector<ClassFlow*> FlowControll;
|
||||
ClassFlowMakeImage* flowmakeimage;
|
||||
#include "test_flow_postrocess_helper.h"
|
||||
|
||||
|
||||
class UnderTestPost : public ClassFlowPostProcessing {
|
||||
public:
|
||||
UnderTestPost(std::vector<ClassFlow*>* lfc, ClassFlowCNNGeneral *_analog, ClassFlowCNNGeneral *_digit)
|
||||
: ClassFlowPostProcessing::ClassFlowPostProcessing(lfc, _analog, _digit) {}
|
||||
using ClassFlowPostProcessing::InitNUMBERS;
|
||||
};
|
||||
|
||||
UnderTestPost* undertestPost;
|
||||
|
||||
|
||||
/**
|
||||
* ACHTUNG! Die Test laufen aktuell nur mit ausgeschaltetem Debug in ClassFlowCNNGeneral
|
||||
*
|
||||
*
|
||||
* @brief Testet die doFlow-Methode von ClassFlowPostprocessing
|
||||
* digits[] - enthält die liste der vom Model zurückgegebenen Ergebnisse (class100/cont) in der Reihenfolge von links nach rechts
|
||||
* analog[] - enthält die Liste der Zeiger vom Model, wie bei den digits
|
||||
* expected - enthält das erwartete Ergebnis, wobei der Dezimalpunkt genau zwischen digits und analog ist.
|
||||
*
|
||||
*/
|
||||
void test_doFlow() {
|
||||
void test_doFlowPP() {
|
||||
|
||||
/*
|
||||
*
|
||||
* digit1 = 1.2
|
||||
@@ -44,12 +27,12 @@ void test_doFlow() {
|
||||
std::vector<float> digits = { 1.2, 6.7};
|
||||
std::vector<float> analogs = { 9.5, 8.4};
|
||||
const char* expected = "16.98";
|
||||
const char* expected_extended = "16.984";
|
||||
//const char* expected_extended = "16.984";
|
||||
std::string result = process_doFlow(analogs, digits);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
/*
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921#issue-1344032217
|
||||
*
|
||||
* Das Ergebnis sollte "376529.6" sein.
|
||||
*/
|
||||
@@ -60,7 +43,7 @@ void test_doFlow() {
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
/*
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1220365920
|
||||
*
|
||||
* Das Ergebnis sollte "167734.6" sein. Bzw. 16.98 ohne Extended true
|
||||
*/
|
||||
@@ -82,7 +65,7 @@ void test_doFlow() {
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
/*
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921
|
||||
* https://github.com/jomjol/AI-on-the-edge-device/issues/921#issuecomment-1222672175
|
||||
*
|
||||
* Das Ergebnis sollte "376529.6" sein. Bzw. 16.98 ohne Extended true
|
||||
*/
|
||||
@@ -107,7 +90,7 @@ void test_doFlow() {
|
||||
|
||||
digits = { 1.1, 9.0, 4.0};
|
||||
analogs = { 9.1, 2.6, 6.25, 9.7};
|
||||
expected = "193.9259";
|
||||
expected = "194.9259";
|
||||
result = process_doFlow(analogs, digits);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
@@ -125,11 +108,14 @@ void test_doFlow() {
|
||||
result = process_doFlow(analogs, digits);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
}
|
||||
|
||||
void test_doFlowPP1() {
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/942#issuecomment-1226966346
|
||||
digits = { 0.0, 2.9, 3.0, 2.9, 3.5, 9.5};
|
||||
analogs = { };
|
||||
expected = "33330";
|
||||
result = process_doFlow(analogs, digits);
|
||||
std::vector<float> digits = { 0.0, 2.9, 3.0, 2.9, 3.5, 9.5};
|
||||
std::vector<float> analogs = { };
|
||||
const char* expected = "33330";
|
||||
std::string result = process_doFlow(analogs, digits);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/942#issuecomment-1226966346
|
||||
@@ -184,13 +170,15 @@ void test_doFlow() {
|
||||
expected = "395.8632";
|
||||
result = process_doFlow(analogs, digits);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
}
|
||||
|
||||
void test_doFlowPP2() {
|
||||
// Fehler bei V11.2.0
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/discussions/950#discussion-4338615
|
||||
digits = { 1.0, 9.0, 9.0}; // Übergang wurde um 1 erhöht (200, statt 199)
|
||||
analogs = { 7.1, 4.8, 8.3};
|
||||
expected = "199.748";
|
||||
result = process_doFlow(analogs, digits, Digital);
|
||||
std::vector<float> digits = { 1.0, 9.0, 9.0}; // Übergang wurde um 1 erhöht (200, statt 199)
|
||||
std::vector<float> analogs = { 7.1, 4.8, 8.3};
|
||||
const char* expected = "199.748";
|
||||
std::string result = process_doFlow(analogs, digits, Digital);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// Fehler bei Rolling (2002-09-09)
|
||||
@@ -198,7 +186,7 @@ void test_doFlow() {
|
||||
digits = { 3.0, 2.0, 2.0, 8.0, 9.0, 4.0, 1.7, 9.8}; // falscher Wert 32290.420
|
||||
analogs = { };
|
||||
expected = "32289.420";
|
||||
expected_extended= "32289.4198";
|
||||
const char* expected_extended= "32289.4198";
|
||||
// FALSCH! wegen ungenügender Präzision von NUMBERS->Value
|
||||
// expected_extended= "32289.4198";
|
||||
|
||||
@@ -303,95 +291,235 @@ void test_doFlow() {
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler bei V12.0.1
|
||||
// Lokal
|
||||
digits = { 9.8, 9.8, 1.9, 0.9, 0.9, 9.9, 2.9, 4.8}; // 211.0345 als falsches Ergebnis
|
||||
analogs = { 5.5};
|
||||
expected = "211.0355";
|
||||
expected_extended= "211.03555";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler bei V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1277425333
|
||||
digits = { 2.2, 4.5, 5.9}; // 245.938 als falsches Ergebnis
|
||||
analogs = { 9.4, 3.8, 8.6};
|
||||
expected = "245.938";
|
||||
expected_extended= "245.9386";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler bei V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1277425333
|
||||
digits = { 2.2, 4.5, 5.9}; // 245.938 kein Fehler. Aber Grenzfall, deshalb mit als Test aufgenommen.
|
||||
analogs = { 9.4, 3.8, 8.6};
|
||||
expected = "245.938";
|
||||
expected_extended= "245.9386";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
}
|
||||
|
||||
void test_doFlowPP3() {
|
||||
// Fehler bei V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1265523710
|
||||
std::vector<float> digits = { 2.0, 4.0, 6.8}; // 246.2045 als falsches Ergebnis
|
||||
std::vector<float> analogs = { 2.2, 0.1, 4.5};
|
||||
const char* expected = "247.204";
|
||||
const char* expected_extended= "247.2045";
|
||||
|
||||
// extendResolution=false
|
||||
std::string result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
|
||||
// Fehler bei V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issue-1391153343
|
||||
digits = { 1.0, 4.0, 2.0}; // 141.9269 als falsches Ergebnis
|
||||
analogs = { 9.2, 2.5, 6.8, 9.0};
|
||||
expected = "142.9269";
|
||||
expected_extended= "142.92690";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
|
||||
// Fehler bei V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1262626388
|
||||
digits = { 1.2, 6.8, 0.0, 0.0, 5.0, 2.8}; //170.05387 als falsches Ergebnis
|
||||
// letztes digit läuft mit analog zeiger mit. Hier nur lösbar mit setAnalogdigitTransistionStart=7.7
|
||||
analogs = { 8.7};
|
||||
expected = "170.0528";
|
||||
expected_extended= "170.05287";
|
||||
|
||||
// extendResolution=false
|
||||
UnderTestPost* undertestPost = init_do_flow(analogs, digits, Digital100, false, false, -3);
|
||||
setAnalogdigitTransistionStart(undertestPost, 7.7);
|
||||
result = process_doFlow(undertestPost);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
delete undertestPost;
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
undertestPost = init_do_flow(analogs, digits, Digital100, false, true, -3);
|
||||
setAnalogdigitTransistionStart(undertestPost, 7.7);
|
||||
result = process_doFlow(undertestPost);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
delete undertestPost;
|
||||
|
||||
// Fehler bei rolling post V12.0.1
|
||||
// lokal watermeter1
|
||||
digits = { 0.0, 0.0, 9.0, 1.0}; //90.88174 als falsches Ergebnis
|
||||
analogs = {9.0, 8.0, 1.8, 7.4};
|
||||
expected = "91.8817";
|
||||
expected_extended= "91.88174";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
|
||||
// Fehler bei rolling post V12.0.1
|
||||
// lokal watermeter1
|
||||
digits = { 0.0, 0.0, 9.0, 1.9}; //91.38403 als falsches Ergebnis
|
||||
analogs = {3.6, 8.2, 3.2, 2.0};
|
||||
expected = "92.3832";
|
||||
expected_extended= "92.38320";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler V11.3.0
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issue-1400807695
|
||||
digits = { 7.0, 4.0, 7.0, 2.0, 7.0, 5.4, 9.4}; // 7472.749 als falsches Ergebnis
|
||||
analogs = {};
|
||||
expected = "7472.759";
|
||||
expected_extended= "7472.7594";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1274434805
|
||||
digits = { 4.9, 6.9, 6.8}; // 576.8649 als falsches Ergebnis
|
||||
analogs = {8.6, 6.2, 5.0, 9.0};
|
||||
expected = "577.8649";
|
||||
expected_extended= "577.86490";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
|
||||
// Fehler V12.0.1 "TODO 00211.03480 vs 00211.03580"
|
||||
// Lokal "Hängendes Digit"
|
||||
digits = { 2.0, 1.0, 1.0, 0.0, 3.0, 4.8}; // 00211.03480 als falsches Ergebnis
|
||||
analogs = {8.0};
|
||||
expected = "211.0358";
|
||||
expected_extended= "211.03580";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1143#issuecomment-1281231468
|
||||
digits = { 1.0, 1.9, 6.0}; // 125.923 als falsches Ergebnis
|
||||
analogs = {9.3, 2.3, 3.1};
|
||||
expected = "126.923";
|
||||
expected_extended= "126.9231";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, 0);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1282168030
|
||||
digits = { 3.0, 8.1, 5.9, 0.0, 5.0, 6.7}; // 386.05672 als richtiges Ergebnis. Letztes digit schein mit dem Analogzeiger mitzulaufen
|
||||
analogs = {7.2};
|
||||
expected = "386.0567";
|
||||
expected_extended= "386.05672";
|
||||
|
||||
// extendResolution=false
|
||||
result = process_doFlow(analogs, digits, Digital100, false, false, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
result = process_doFlow(analogs, digits, Digital100, false, true, -3);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
|
||||
// Fehler V12.0.1
|
||||
// https://github.com/jomjol/AI-on-the-edge-device/issues/1110#issuecomment-1282168030
|
||||
digits = { 1.2, 7.0, 1.2, 2.0, 4.0, 1.8}; // 171.24278 als falsches Ergebnis.
|
||||
// Test ist nur erfolgreich mit Veränderung des AnalogdigitTransistionStart
|
||||
analogs = {7.8};
|
||||
expected = "171.2417";
|
||||
expected_extended= "171.24178";
|
||||
|
||||
// extendResolution=false
|
||||
undertestPost = init_do_flow(analogs, digits, Digital100, false, false, -3);
|
||||
setAnalogdigitTransistionStart(undertestPost, 7.7);
|
||||
result = process_doFlow(undertestPost);
|
||||
TEST_ASSERT_EQUAL_STRING(expected, result.c_str());
|
||||
delete undertestPost;
|
||||
|
||||
// checkConsistency=false und extendResolution=true
|
||||
undertestPost = init_do_flow(analogs, digits, Digital100, false, true, -3);
|
||||
setAnalogdigitTransistionStart(undertestPost, 7.7);
|
||||
result = process_doFlow(undertestPost);
|
||||
TEST_ASSERT_EQUAL_STRING(expected_extended, result.c_str());
|
||||
delete undertestPost;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setUpClassFlowPostprocessing(t_CNNType digType, t_CNNType anaType)
|
||||
{
|
||||
|
||||
// wird im doFlow verwendet
|
||||
flowmakeimage = new ClassFlowMakeImage(&FlowControll);
|
||||
FlowControll.push_back(flowmakeimage);
|
||||
|
||||
// Die Modeltypen werden gesetzt, da keine Modelle verwendet werden.
|
||||
_analog = new ClassFlowCNNGeneral(nullptr, anaType);
|
||||
|
||||
_digit = new ClassFlowCNNGeneral(nullptr, digType);
|
||||
|
||||
undertestPost = new UnderTestPost(&FlowControll, _analog, _digit);
|
||||
|
||||
}
|
||||
|
||||
|
||||
std::string process_doFlow(std::vector<float> analog, std::vector<float> digits, t_CNNType digType,
|
||||
bool checkConsistency, bool extendedResolution, int decimal_shift) {
|
||||
// setup the classundertest
|
||||
setUpClassFlowPostprocessing(digType, Analogue100);
|
||||
|
||||
printf("SetupClassFlowPostprocessing completed.\n");
|
||||
|
||||
// digits
|
||||
if (digits.size()>0) {
|
||||
general* gen_digit = _digit->GetGENERAL("default", true);
|
||||
gen_digit->ROI.clear();
|
||||
for (int i = 0; i<digits.size(); i++) {
|
||||
roi* digitROI = new roi();
|
||||
string name = "digit_" + std::to_string(i);
|
||||
digitROI->name = name;
|
||||
digitROI->result_klasse = (int) digits[i];
|
||||
digitROI->result_float = digits[i];
|
||||
gen_digit->ROI.push_back(digitROI);
|
||||
}
|
||||
}
|
||||
|
||||
// analog
|
||||
if (analog.size()>0) {
|
||||
general* gen_analog = _analog->GetGENERAL("default", true);
|
||||
gen_analog->ROI.clear();
|
||||
|
||||
for (int i = 0; i<analog.size(); i++) {
|
||||
roi* anaROI = new roi();
|
||||
string name = "ana_" + std::to_string(i);
|
||||
anaROI->name = name;
|
||||
anaROI->result_float = analog[i];
|
||||
gen_analog->ROI.push_back(anaROI);
|
||||
}
|
||||
}
|
||||
printf("Setting up of ROIs completed.\n");
|
||||
|
||||
undertestPost->InitNUMBERS();
|
||||
if (checkConsistency) {
|
||||
printf("checkConsistency=true\n");
|
||||
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
printf("Setting checkConsistency on number: %d\n", _n);
|
||||
(*NUMBERS)[_n]->checkDigitIncreaseConsistency = true;
|
||||
}
|
||||
}
|
||||
if (extendedResolution ) {
|
||||
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
printf("Setting extendedResolution on number: %d\n", _n);
|
||||
(*NUMBERS)[_n]->isExtendedResolution = true;
|
||||
}
|
||||
|
||||
}
|
||||
if (decimal_shift!=0) {
|
||||
std::vector<NumberPost*>* NUMBERS = undertestPost->GetNumbers();
|
||||
for (int _n = 0; _n < (*NUMBERS).size(); ++_n) {
|
||||
printf("Setting decimal shift on number: %d to %d\n", _n, decimal_shift);
|
||||
(*NUMBERS)[_n]->DecimalShift = decimal_shift;
|
||||
(*NUMBERS)[_n]->DecimalShiftInitial = decimal_shift;
|
||||
}
|
||||
}
|
||||
|
||||
string time;
|
||||
// run test
|
||||
TEST_ASSERT_TRUE(undertestPost->doFlow(time));
|
||||
|
||||
return undertestPost->getReadout(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "test_flow_postrocess_helper.h"
|
||||
|
||||
|
||||
|
||||
void test_getReadoutRawString() {
|
||||
|
||||
// no ROIs setted up
|
||||
UnderTestPost* _undertestPost = setUpClassFlowPostprocessing(Digital100, Analogue100);
|
||||
|
||||
string result = _undertestPost->flowAnalog->getReadoutRawString(0);
|
||||
TEST_ASSERT_EQUAL_STRING("", result.c_str());
|
||||
|
||||
// setted value
|
||||
general* gen_analog = _undertestPost->flowAnalog->GetGENERAL("default", true);
|
||||
gen_analog->ROI.clear();
|
||||
roi* anaROI = new roi();
|
||||
string name = "ana_1";
|
||||
anaROI->name = name;
|
||||
anaROI->result_float = 5.5;
|
||||
gen_analog->ROI.push_back(anaROI);
|
||||
|
||||
result = _undertestPost->flowAnalog->getReadoutRawString(0);
|
||||
TEST_ASSERT_EQUAL_STRING("\t5.5", result.c_str());
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,13 +1,19 @@
|
||||
#include <unity.h>
|
||||
#include "components/jomjol-flowcontroll/test_cnnflowcontroll.cpp"
|
||||
|
||||
#include "components/jomjol-flowcontroll/test_flow_postrocess_helper.cpp"
|
||||
#include "components/jomjol-flowcontroll/test_flowpostprocessing.cpp"
|
||||
#include "components/jomjol-flowcontroll/test_flow_pp_negative.cpp"
|
||||
#include "components/jomjol-flowcontroll/test_ZeigerEvalAnalogToDigitNeu.cpp"
|
||||
#include "components/jomjol-flowcontroll/test_getReadoutRawString.cpp"
|
||||
// SD-Card ////////////////////
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
static const char *TAGMAIN = "main";
|
||||
static const char *TAG = "MAIN TEST";
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
#include "server_GPIO.h"
|
||||
|
||||
bool Init_NVS_SDCard()
|
||||
{
|
||||
@@ -18,7 +24,7 @@ bool Init_NVS_SDCard()
|
||||
}
|
||||
////////////////////////////////////////////////
|
||||
|
||||
ESP_LOGI(TAGMAIN, "Using SDMMC peripheral");
|
||||
ESP_LOGI(TAG, "Using SDMMC peripheral");
|
||||
sdmmc_host_t host = SDMMC_HOST_DEFAULT();
|
||||
|
||||
// This initializes the slot without card detect (CD) and write protect (WP) signals.
|
||||
@@ -47,7 +53,7 @@ bool Init_NVS_SDCard()
|
||||
// formatted in case when mounting fails.
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 5,
|
||||
.max_files = 7, // anstatt 5 (2022-09-21)
|
||||
.allocation_unit_size = 16 * 1024
|
||||
};
|
||||
|
||||
@@ -60,32 +66,60 @@ bool Init_NVS_SDCard()
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_FAIL) {
|
||||
ESP_LOGE(TAGMAIN, "Failed to mount filesystem. "
|
||||
ESP_LOGE(TAG, "Failed to mount filesystem. "
|
||||
"If you want the card to be formatted, set format_if_mount_failed = true.");
|
||||
} else {
|
||||
ESP_LOGE(TAGMAIN, "Failed to initialize the card (%s). "
|
||||
ESP_LOGE(TAG, "Failed to initialize the card (%s). "
|
||||
"Make sure SD card lines have pull-up resistors in place.", esp_err_to_name(ret));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
|
||||
sdmmc_card_print_info(stdout, card);
|
||||
SaveSDCardInfo(card);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void initGPIO()
|
||||
{
|
||||
gpio_config_t io_conf;
|
||||
//set as output mode
|
||||
io_conf.mode = gpio_mode_t::GPIO_MODE_INPUT;
|
||||
//bit mask of the pins that you want to set,e.g.GPIO18/19
|
||||
io_conf.pull_down_en = gpio_pulldown_t::GPIO_PULLDOWN_ENABLE;
|
||||
//set pull-up mode
|
||||
io_conf.pull_up_en = gpio_pullup_t::GPIO_PULLUP_DISABLE;
|
||||
//configure GPIO with the given settings
|
||||
gpio_config(&io_conf);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief startup the test. Like a test-suite
|
||||
* all test methods must be called here
|
||||
*/
|
||||
extern "C" void app_main()
|
||||
{
|
||||
initGPIO();
|
||||
Init_NVS_SDCard();
|
||||
UNITY_BEGIN();
|
||||
esp_log_level_set("*", ESP_LOG_DEBUG); // set all components to ERROR level
|
||||
|
||||
// RUN_TEST(test_ZeigerEval);
|
||||
// RUN_TEST(test_ZeigerEvalHybrid);
|
||||
RUN_TEST(test_doFlow);
|
||||
UNITY_BEGIN();
|
||||
|
||||
RUN_TEST(testNegative);
|
||||
|
||||
RUN_TEST(test_analogToDigit_Standard);
|
||||
RUN_TEST(test_analogToDigit_Transition);
|
||||
RUN_TEST(test_doFlowPP);
|
||||
RUN_TEST(test_doFlowPP1);
|
||||
RUN_TEST(test_doFlowPP2);
|
||||
RUN_TEST(test_doFlowPP3);
|
||||
|
||||
// getReadoutRawString test
|
||||
RUN_TEST(test_getReadoutRawString);
|
||||
|
||||
UNITY_END();
|
||||
}
|
||||
}
|
||||
|
||||
25
docs/.gitignore
vendored
Normal file
25
docs/.gitignore
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
# Remove if certain files are committed on purpose
|
||||
.pio/
|
||||
.vscode/
|
||||
.code-workspace
|
||||
/sd-card/htm./.vscode/
|
||||
/code/build
|
||||
/code/.helper
|
||||
/sd-card/html/debug/
|
||||
/firmware/
|
||||
version.txt
|
||||
/dist/
|
||||
/dist_release/
|
||||
/dist_old_ota
|
||||
CMakeLists.txt.user
|
||||
CMakeCache.txt
|
||||
CMakeFiles
|
||||
CMakeScripts
|
||||
Makefile
|
||||
cmake_install.cmake
|
||||
install_manifest.txt
|
||||
compile_commands.json
|
||||
CTestTestfile.cmake
|
||||
_deps
|
||||
code/edgeAI.code-workspace
|
||||
.DS_Store
|
||||
9
docs/.gitmodules
vendored
Normal file
9
docs/.gitmodules
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
[submodule "code/components/esp32-camera"]
|
||||
path = code/components/esp32-camera
|
||||
url = https://github.com/espressif/esp32-camera.git
|
||||
[submodule "code/components/esp-nn"]
|
||||
path = code/components/esp-nn
|
||||
url = https://github.com/espressif/esp-nn.git
|
||||
[submodule "code/components/tflite-micro-esp-examples"]
|
||||
path = code/components/tflite-micro-esp-examples
|
||||
url = https://github.com/espressif/tflite-micro-esp-examples.git
|
||||
39
docs/index.html
Normal file
39
docs/index.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<html>
|
||||
<title>AI on the Edge Device - Webinstaller</title>
|
||||
<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>
|
||||
<body style="
|
||||
padding: 20px;
|
||||
padding-left: 60px;
|
||||
padding-right: 60px;
|
||||
">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src=https://raw.githubusercontent.com/jomjol/AI-on-the-edge-device/master/images/icon/watermeter.svg style="width: 100px; padding-right: 10px;"></td>
|
||||
<td><h1>AI-on-the-edge-device</h1><h2>Webinstaller and Console</h2></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<hr>
|
||||
|
||||
<p>This page provides the Webinstaller and a live USB Console to your AI-on-the-edge-device.<br>
|
||||
For further information about AI-on-the-edge-device please go to <a href=https://github.com/jomjol/AI-on-the-edge-device>https://github.com/jomjol/AI-on-the-edge-device</a>.</p>
|
||||
|
||||
<p>Notes:</p>
|
||||
<ul>
|
||||
<li>For the installation, make sure to switch the ESP32 to Bootloader mode!</li>
|
||||
<li>After the installation, a manual reset might be required!</li>
|
||||
<li>Please note that not all webbrowsers and operating systems support the needed access to USB!</li>
|
||||
<li>Check the <a href=https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation>Wiki</a> for additional information.</li>
|
||||
</ul>
|
||||
|
||||
<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>
|
||||
</body>
|
||||
</html>
|
||||
25
docs/manifest.json
Normal file
25
docs/manifest.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"name": "AI-on-the-edge",
|
||||
"version": "12.0.1",
|
||||
"funding_url": "https://www.paypal.com/donate?hosted_button_id=8TRSVYNYKDSWL",
|
||||
"new_install_prompt_erase": false,
|
||||
"builds": [
|
||||
{
|
||||
"chipFamily": "ESP32",
|
||||
"parts": [
|
||||
{
|
||||
"path": "releases/download/v11.2.0/bootloader.bin",
|
||||
"offset": 4096
|
||||
},
|
||||
{
|
||||
"path": "releases/download/v11.2.0/partitions.bin",
|
||||
"offset": 32768
|
||||
},
|
||||
{
|
||||
"path": "releases/download/v12.0.1/firmware.bin",
|
||||
"offset": 65536
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
docs/releases/download/v11.2.0/bootloader.bin
Normal file
BIN
docs/releases/download/v11.2.0/bootloader.bin
Normal file
Binary file not shown.
BIN
docs/releases/download/v11.2.0/partitions.bin
Normal file
BIN
docs/releases/download/v11.2.0/partitions.bin
Normal file
Binary file not shown.
BIN
docs/releases/download/v12.0.1/firmware.bin
Normal file
BIN
docs/releases/download/v12.0.1/firmware.bin
Normal file
Binary file not shown.
BIN
releases/download/v11.2.0/bootloader.bin
Normal file
BIN
releases/download/v11.2.0/bootloader.bin
Normal file
Binary file not shown.
BIN
releases/download/v11.2.0/partitions.bin
Normal file
BIN
releases/download/v11.2.0/partitions.bin
Normal file
Binary file not shown.
BIN
releases/download/v12.0.1/firmware.bin
Normal file
BIN
releases/download/v12.0.1/firmware.bin
Normal file
Binary file not shown.
@@ -21,7 +21,7 @@ FlipImageSize = false
|
||||
/config/ref1.jpg 442 142
|
||||
|
||||
[Digits]
|
||||
Model = /config/dig-cont_0570_s3.tflite
|
||||
Model = /config/dig-cont_0600_s3.tflite
|
||||
CNNGoodThreshold = 0.5
|
||||
;LogImageLocation = /log/digit
|
||||
;LogfileRetentionInDays = 3
|
||||
@@ -42,6 +42,7 @@ main.ana4 155 328 92 92 false
|
||||
|
||||
[PostProcessing]
|
||||
main.DecimalShift = 0
|
||||
main.AnalogDigitalTransitionStart = 9.2
|
||||
PreValueUse = true
|
||||
PreValueAgeStartup = 720
|
||||
AllowNegativeRates = false
|
||||
@@ -81,10 +82,14 @@ LEDColor = 150 150 150
|
||||
|
||||
[AutoTimer]
|
||||
AutoStart = true
|
||||
Intervall = 4.85
|
||||
Intervall = 5
|
||||
|
||||
[DataLogging]
|
||||
DataLogActive = true
|
||||
DataLogRetentionInDays = 3
|
||||
|
||||
[Debug]
|
||||
Logfile = false
|
||||
Logfile = 1
|
||||
LogfileRetentionInDays = 3
|
||||
|
||||
[System]
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user