mirror of
https://github.com/jomjol/AI-on-the-edge-device.git
synced 2025-12-10 05:26:52 +03:00
Compare commits
27 Commits
v13.0.3
...
v14.0.0-RC
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
245302c6ca | ||
|
|
0e2ab869cb | ||
|
|
04f2f23931 | ||
|
|
c6cfe73e23 | ||
|
|
914cfceedf | ||
|
|
f1a836a407 | ||
|
|
55f78dce6d | ||
|
|
304b9e0c32 | ||
|
|
f4d086508d | ||
|
|
e23c89ae57 | ||
|
|
53a764abc8 | ||
|
|
4f07c88769 | ||
|
|
fa406d8989 | ||
|
|
1ca54f39f8 | ||
|
|
5867e90f69 | ||
|
|
e87b91f6eb | ||
|
|
4b52e61755 | ||
|
|
eb48212630 | ||
|
|
961662f483 | ||
|
|
306b1a75a5 | ||
|
|
7350864150 | ||
|
|
16d0758ea3 | ||
|
|
877a1b14e5 | ||
|
|
a122b37c81 | ||
|
|
ad137b329b | ||
|
|
85905a7045 | ||
|
|
9847f95c93 |
2
.github/ISSUE_TEMPLATE/feature.yaml
vendored
2
.github/ISSUE_TEMPLATE/feature.yaml
vendored
@@ -1,6 +1,6 @@
|
||||
name: 💡 Feature Request
|
||||
description: Use this form if you have an idea or wish for a new feature
|
||||
labels: feature
|
||||
labels: enhancement
|
||||
body:
|
||||
|
||||
|
||||
|
||||
98
.github/label-commenter-config.yml
vendored
Normal file
98
.github/label-commenter-config.yml
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
# Reply Bot Configuration
|
||||
# See https://github.com/peaceiris/actions-label-commenter
|
||||
# Make sure to also add the response to .github/workflows/reply-bot.yml!
|
||||
# Due to the way it works, you have to add each response twice, once for the issue, once for the discussions!
|
||||
|
||||
labels:
|
||||
#######################################################################
|
||||
# Bot Response: Logfile
|
||||
#######################################################################
|
||||
- name: bot-reply Logfile
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
Please provide a logfile!
|
||||
Make sure to first enable the `DEBUG` level in `Settings->Configuration->Debug->Logfile Log Level`!
|
||||
Then wait until the issue arises again.
|
||||
When you copy the log into here, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
discussion:
|
||||
body: |
|
||||
Please provide a logfile!
|
||||
Make sure to first enable the `DEBUG` level in `Settings->Configuration->Debug->Logfile Log Level`!
|
||||
Then wait until the issue arises again.
|
||||
When you copy the log into here, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Web Console
|
||||
#######################################################################
|
||||
- name: bot-reply Web Console
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
You can use the [Web Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) to get USB log from the device.
|
||||
The USB log contains more information about the startup and operation of the device than the normal Web UI log
|
||||
When you copy the log into herm, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
discussion:
|
||||
body: |
|
||||
You can use the [Web Console](https://jomjol.github.io/AI-on-the-edge-device/index.html) to get USB log from the device.
|
||||
The USB log contains more information about the startup and operation of the device than the normal Web UI log
|
||||
When you copy the log into herm, please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Properly Format Code
|
||||
#######################################################################
|
||||
- name: bot-reply Properly Format Code
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
Please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
This makes your code or log much easier to read!
|
||||
discussion:
|
||||
body: |
|
||||
Please make sure to use **Fenced code blocks** by wrapping it into separate lines with ` ``` `, see https://docs.github.com/en/get-started/writing-on-github/working-with-advanced-formatting/creating-and-highlighting-code-blocks#fenced-code-blocks
|
||||
This makes your code or log much easier to read!
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Web Installer
|
||||
#######################################################################
|
||||
- name: bot-reply Web Installer
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
You can use the [Web Installer](https://jomjol.github.io/AI-on-the-edge-device/index.html) install the firmware onto the ESP32.
|
||||
discussion:
|
||||
body: |
|
||||
You can use the [Web Installer](https://jomjol.github.io/AI-on-the-edge-device/index.html) install the firmware onto the ESP32.
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Rolling Build
|
||||
#######################################################################
|
||||
- name: bot-reply Rolling Build
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
You can try the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling+event%3Apush) of the the `rolling` or any other branch. It might already contain a fix for your issue.
|
||||
See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/rolling-installation) for additional information.
|
||||
discussion:
|
||||
body: |
|
||||
You can try the latest [Automatic Build](https://github.com/jomjol/AI-on-the-edge-device/actions/workflows/build.yaml?query=branch%3Arolling+event%3Apush) of the the `rolling` or any other branch. It might already contain a fix for your issue.
|
||||
See the [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/rolling-installation) for additional information.
|
||||
|
||||
|
||||
#######################################################################
|
||||
# Bot Response: Show Trained Digits/Pointers
|
||||
#######################################################################
|
||||
- name: bot-reply Show Trained Digits/Pointers
|
||||
labeled:
|
||||
issue:
|
||||
body: |
|
||||
See [Digital Digits](https://jomjol.github.io/neural-network-digital-counter-readout) resp. [Analogue Pointers](https://jomjol.github.io/neural-network-analog-needle-readout) for an overview of all trained data.
|
||||
If your type is not contained it can be added to our training material, see [here](https://jomjol.github.io/AI-on-the-edge-device-docs/Learn-models-with-your-own-images/).
|
||||
discussion:
|
||||
body: |
|
||||
See [Digital Digits](https://jomjol.github.io/neural-network-digital-counter-readout) resp. [Analogue Pointers](https://jomjol.github.io/neural-network-analog-needle-readout) for an overview of all trained data.
|
||||
If your type is not contained it can be added to our training material, see [here](https://jomjol.github.io/AI-on-the-edge-device-docs/Learn-models-with-your-own-images/).
|
||||
449
.github/workflows/build.yaml
vendored
449
.github/workflows/build.yaml
vendored
@@ -24,16 +24,43 @@ jobs:
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Cache PlatformIO
|
||||
uses: actions/cache@v3
|
||||
- name: Update PIP cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: pip-${{ github.run_id }}
|
||||
restore-keys: pip # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update PlatformIO cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ~/.platformio
|
||||
key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
|
||||
key: platformio-${{ github.run_id }}
|
||||
restore-keys: platformio # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update Build cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: ./code/.pio/
|
||||
key: build-${{ github.run_id }}
|
||||
restore-keys: build # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.10'
|
||||
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
@@ -43,71 +70,18 @@ jobs:
|
||||
#run: echo "Testing... ${{ github.ref_name }}, ${{ steps.vars.outputs.sha_short }}" > ./sd-card/html/version.txt; mkdir -p ./code/.pio/build/esp32cam/; cd ./code/.pio/build/esp32cam/; echo "${{ steps.vars.outputs.sha_short }}" > firmware.bin; cp firmware.bin partitions.bin; cp firmware.bin bootloader.bin # Testing
|
||||
run: cd code; platformio run --environment esp32cam
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for old OTA (v1)
|
||||
#########################################################################################
|
||||
pack-for-OTA-v1:
|
||||
# Old OTA concept
|
||||
# firmware__*.zip needs to be unpacked before attaching to the release!
|
||||
# The bin filename can contain versioning.
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
- name: Prepare Web UI (copy data from repo and update hashes in all files)
|
||||
run: |
|
||||
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__${{ 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)__${{ 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__${{ steps.vars.outputs.branch }}__(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./sd-card/html/*
|
||||
|
||||
rm -rf ./html; mkdir html
|
||||
cp ./sd-card/html/* ./html/
|
||||
cd html; find . -type f -exec sed -i 's/$COMMIT_HASH/${{ steps.vars.outputs.sha_short }}/g' {} \;
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for new OTA (v2)
|
||||
## Pack for Update
|
||||
#########################################################################################
|
||||
pack-for-OTA-v2:
|
||||
pack-for-update:
|
||||
# New OTA concept
|
||||
# update__version.zip file with following content:
|
||||
# - /firmware.bin
|
||||
@@ -119,15 +93,84 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare update__*.zip artifact
|
||||
run: |
|
||||
mkdir -p ./update
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "update/firmware.bin"
|
||||
|
||||
- name: Add Web UI to update
|
||||
run: cp -r ./html ./update/
|
||||
|
||||
- name: Add CNN to update
|
||||
run: |
|
||||
mkdir -p ./update/config/
|
||||
cp ./sd-card/config/*.tfl ./update/config/ 2>/dev/null || true
|
||||
cp ./sd-card/config/*.tflite ./update/config/ 2>/dev/null || true
|
||||
|
||||
- name: Upload update as update.zip artifact (Firmware + Web UI + CNN)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "AI-on-the-edge-device__update__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./update/*
|
||||
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for Remote Setup
|
||||
#########################################################################################
|
||||
pack-for-remote_setup:
|
||||
# New Remote Setup concept
|
||||
# remote_setup__version.zip file with following content:
|
||||
# - /firmware.bin
|
||||
# - /html/*
|
||||
# - /config/*
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update remote_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: remote_setup
|
||||
key: remote_setup-${{ github.run_id }}
|
||||
restore-keys: remote_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
@@ -135,51 +178,30 @@ jobs:
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare update.zip artifact
|
||||
- name: Prepare remote_setup__*.zip artifact
|
||||
run: |
|
||||
mkdir -p ./dist
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "dist/firmware.bin"
|
||||
mkdir -p ./remote_setup
|
||||
cp "./code/.pio/build/esp32cam/firmware.bin" "remote_setup/firmware.bin"
|
||||
|
||||
# - name: Upload update.zip Artifact (Firmware only)
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: "update_firmware_only__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
# path: ./dist/*
|
||||
|
||||
- name: Add Web UI to dist
|
||||
run: cp -r ./sd-card/html ./dist/
|
||||
- name: Add Web UI to remote_setup
|
||||
run: cp -r ./html ./remote_setup/
|
||||
|
||||
# - name: Upload update.zip artifact (Firmware + Web UI)
|
||||
# uses: actions/upload-artifact@v3
|
||||
# with:
|
||||
# name: "update_firmware+webinterface__${{ github.ref_name }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
# path: ./dist/*
|
||||
|
||||
- name: Add CNN to dist
|
||||
- name: Add whole config folder to remote_setup
|
||||
run: |
|
||||
mkdir ./dist/config/
|
||||
cp ./sd-card/config/*.tfl ./dist/config/ 2>/dev/null || true
|
||||
cp ./sd-card/config/*.tflite ./dist/config/ 2>/dev/null || true
|
||||
mkdir -p ./remote_setup/config/
|
||||
cp ./sd-card/config/* ./remote_setup/config/ 2>/dev/null || true
|
||||
|
||||
- name: Upload dist as update.zip artifact (Firmware + Web UI + CNN)
|
||||
- name: Upload remote_setup as remote_setup.zip artifact (Firmware + Web UI + Config)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "update__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./dist/*
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: dist
|
||||
key: ${{ github.run_number }}-pack-for-OTA-v2
|
||||
|
||||
|
||||
name: "AI-on-the-edge-device__remote-setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./remote_setup/*
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Pack for a fresh install (USB flashing) (initial_esp32_setup)
|
||||
## Pack for a fresh install (USB flashing) (manual_setup)
|
||||
#########################################################################################
|
||||
pack-for-fresh-install:
|
||||
pack-for-manual_setup:
|
||||
# creates old style binaries for fresh installation (backward compatible to wiki)
|
||||
runs-on: ubuntu-latest
|
||||
needs: build
|
||||
@@ -187,15 +209,86 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
- name: Update generated-files cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
./html/*
|
||||
key: generated-files-${{ github.run_id }}
|
||||
restore-keys: generated-files # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update manual_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: manual_setup
|
||||
key: manual_setup-${{ github.run_id }}
|
||||
restore-keys: manual_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Prepare manual_setup__*.zip artifact
|
||||
run: |
|
||||
mkdir -p manual_setup
|
||||
rm -rf manual_setup/*.zip
|
||||
mkdir -p release
|
||||
# copy builds to manual_setup folder
|
||||
cp -f "./code/.pio/build/esp32cam/firmware.bin" "manual_setup/firmware.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/bootloader.bin" "manual_setup/bootloader.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/partitions.bin" "manual_setup/partitions.bin"
|
||||
cd sd-card; zip -r ../manual_setup/sd-card.zip *; cd ..
|
||||
cd ./manual_setup
|
||||
|
||||
- name: Upload manual_setup.zip artifact (Firmware + Bootloader + Partitions + Web UI)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "AI-on-the-edge-device__manual-setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./manual_setup
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Prepare and create release
|
||||
#########################################################################################
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pack-for-update, pack-for-manual_setup, pack-for-remote_setup]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow updating the branches
|
||||
permissions:
|
||||
contents: write
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update remote_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: remote_setup
|
||||
key: remote_setup-${{ github.run_id }}
|
||||
restore-keys: remote_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Update manual_setup cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: manual_setup
|
||||
key: manual_setup-${{ github.run_id }}
|
||||
restore-keys: manual_setup # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
@@ -205,87 +298,20 @@ jobs:
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p firmware
|
||||
rm -rf firmware/*.zip
|
||||
mkdir -p release
|
||||
# copy builds to firmware folder
|
||||
cp -f "./code/.pio/build/esp32cam/firmware.bin" "firmware/firmware.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/bootloader.bin" "firmware/bootloader.bin"
|
||||
cp -f "./code/.pio/build/esp32cam/partitions.bin" "firmware/partitions.bin"
|
||||
zip -r ./firmware/sd-card.zip sd-card
|
||||
cd ./firmware
|
||||
|
||||
- name: Upload initial_esp32_setup.zip artifact (Firmware + Bootloader + Partitions + Web UI)
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: "initial_esp32_setup__${{ steps.vars.outputs.branch }}_(${{ steps.vars.outputs.sha_short }})"
|
||||
path: ./firmware
|
||||
|
||||
- name: Store generated files in cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: firmware
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
# create AI-on-the-edge-device__update__*.zip like "AI-on-the-edge-device__update__v13.0.5.zip"
|
||||
cd ./update
|
||||
zip -r ../release/AI-on-the-edge-device__update__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
# create AI-on-the-edge-device__manual-setup__*.zip like "AI-on-the-edge-device__manual-setup__v13.0.5.zip"
|
||||
cd ../manual_setup
|
||||
zip -r ../release/AI-on-the-edge-device__manual-setup__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
# create AI-on-the-edge-device__remote-setup__*.zip like "AI-on-the-edge-device__remote-setup__v13.0.5.zip"
|
||||
cd ../manual_setup
|
||||
zip -r ../release/AI-on-the-edge-device__remote-setup__${{ steps.vars.outputs.branch }}.zip .
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Prepare and create release
|
||||
#########################################################################################
|
||||
release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [pack-for-OTA-v2, pack-for-fresh-install]
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: |
|
||||
./code/.pio/build/esp32cam/firmware.bin
|
||||
./code/.pio/build/esp32cam/partitions.bin
|
||||
./code/.pio/build/esp32cam/bootloader.bin
|
||||
./sd-card/html/version.txt
|
||||
key: ${{ github.run_number }}
|
||||
|
||||
# import the changes from
|
||||
- name: Get generated files from cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
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
|
||||
key: ${{ github.run_number }}-pack-for-fresh-install
|
||||
|
||||
|
||||
|
||||
- name: Prepare artifacts for release
|
||||
run: |
|
||||
mkdir -p release
|
||||
mkdir -p dist
|
||||
# create a update.zip like "update__rolling"
|
||||
pwd
|
||||
ls ./dist
|
||||
cd ./dist
|
||||
zip -r ../release/update.zip .
|
||||
cd ../firmware
|
||||
zip -r ../release/initial_esp32_setup.zip .
|
||||
cd ../sd-card/html
|
||||
zip -r ../../firmware/html-from-11.3.1.zip .
|
||||
|
||||
|
||||
# extract the version used in next step
|
||||
- id: get_version
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
@@ -312,15 +338,16 @@ jobs:
|
||||
# all artifacts in firmware folder pushed to the release
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
# Note:
|
||||
# If you get the error "Resource not accessible by integration",
|
||||
# The access rights are not sufficient, see
|
||||
# https://github.com/softprops/action-gh-release/issues/232#issuecomment-1131379440
|
||||
if: startsWith(github.ref, 'refs/tags/')
|
||||
with:
|
||||
name: ${{ steps.get_version.outputs.version-without-v }}
|
||||
body: ${{ steps.extract-release-notes.outputs.release_notes }}
|
||||
files: |
|
||||
release/*
|
||||
firmware/firmware.bin
|
||||
firmware/html-from-11.3.1.zip
|
||||
|
||||
|
||||
# Commit&Push Changelog to master branch. Must be manually merged back to rolling
|
||||
- name: Commit changes and push changes
|
||||
@@ -331,3 +358,57 @@ jobs:
|
||||
git add Changelog.md
|
||||
git commit Changelog.md -m "Update Changelog.md for ${{github.event.inputs.versionIncrement}} release"
|
||||
git push origin HEAD:master
|
||||
|
||||
|
||||
#########################################################################################
|
||||
## Update the Web Installer on a release
|
||||
#########################################################################################
|
||||
update-web-installer:
|
||||
needs: [release]
|
||||
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Update update cache on every commit
|
||||
uses: actions/cache@v3.2.3
|
||||
with:
|
||||
path: update
|
||||
key: update-${{ github.run_id }}
|
||||
restore-keys: update # This matches above key as it is only used as a prefix. it the restores the nearest cache, see https://github.com/restore-keys:/blob/main/tips-and-workarounds.md#update-a-cache
|
||||
|
||||
- name: Set Variables
|
||||
id: vars
|
||||
run: |
|
||||
echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT
|
||||
echo "branch=$(echo ${{ github.ref_name }} | tr / __)" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Add binary to Web Installer and update manifest
|
||||
run: |
|
||||
rm -f docs/binary/firmware.bin
|
||||
cp -f update/firmware.bin docs/binary/firmware.bin
|
||||
cp -f docs/manifest_template.json docs/manifest.json
|
||||
sed -i 's/VERSION/${{ steps.vars.outputs.branch }}/g' docs/manifest.json
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v2
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: 'docs'
|
||||
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
|
||||
30
.github/workflows/clear_cache.yml
vendored
Normal file
30
.github/workflows/clear_cache.yml
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
name: Clear cache
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
clear-cache:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Clear cache
|
||||
uses: actions/github-script@v6
|
||||
with:
|
||||
script: |
|
||||
console.log("About to clear")
|
||||
const caches = await github.rest.actions.getActionsCacheList({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
for (const cache of caches.data.actions_caches) {
|
||||
console.log(cache)
|
||||
github.rest.actions.deleteActionsCacheById({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
cache_id: cache.id,
|
||||
})
|
||||
}
|
||||
console.log("Clear completed")
|
||||
79
.github/workflows/reply-bot.yml
vendored
Normal file
79
.github/workflows/reply-bot.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# Reply Bot
|
||||
# It uses the configuration in .github/label-commenter-config.yml
|
||||
# See https://github.com/peaceiris/actions-label-commenter
|
||||
|
||||
name: Reply-Bot
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
discussion:
|
||||
types: [labeled]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
discussions: write
|
||||
|
||||
jobs:
|
||||
comment:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
|
||||
####################################################################
|
||||
## Remove labels again (issues only)
|
||||
## Make sure to also add the reply message to .github/label-commenter-config.yml!
|
||||
## This currently seems no longer to work due to changes on the actions-cool/issues-helper!
|
||||
####################################################################
|
||||
# - name: Remove 'Logfile' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Logfile'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Logfile'
|
||||
#
|
||||
# - name: Remove 'Web Console' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Web Console'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Web Console'
|
||||
#
|
||||
# - name: Remove 'Properly Format Code' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Properly Format Code'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Properly Format Code'
|
||||
#
|
||||
# - name: Remove 'Web Installer' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Web Installer'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Web Installer'
|
||||
#
|
||||
# - name: Remove 'Rolling Build' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Rolling Build'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Rolling Build'
|
||||
#
|
||||
# - name: Remove 'Show Trained Digits/Pointers' label again (issues only)
|
||||
# if: github.event.label.name == 'bot-reply Show Trained Digits/Pointers'
|
||||
# uses: actions-cool/issues-helper@v3
|
||||
# with:
|
||||
# actions: 'remove-labels'
|
||||
# labels: 'bot-reply Show Trained Digits/Pointers'
|
||||
|
||||
####################################################################
|
||||
## Write the response
|
||||
####################################################################
|
||||
- name: Write Response
|
||||
uses: peaceiris/actions-label-commenter@c2d00660c86f2b9ed0fb35b372c451558eba85b3
|
||||
with:
|
||||
repo-token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
159
Changelog.md
159
Changelog.md
@@ -1,82 +1,58 @@
|
||||
# Changelog
|
||||
|
||||
## [Unreleased]
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
**Stabilization and Improved User Experience**
|
||||
|
||||
Thanks to over 80 Pull Requests from 6 contributors, we can anounce another great release with many many improvements and new features:
|
||||
|
||||
### Update Procedure
|
||||
Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update)
|
||||
|
||||
### Changes
|
||||
For a full list of changes see [Full list of changes](https://github.com/jomjol/AI-on-the-edge-device/compare/v13.0.8...v14.0.0)
|
||||
|
||||
#### Added
|
||||
- [1877](https://github.com/jomjol/AI-on-the-edge-device/pull/1877) Show WIFI signal text labels / Log RSSI value to logfile
|
||||
- Web UI caching of static files
|
||||
- Added various debug tools
|
||||
- [1798](https://github.com/jomjol/AI-on-the-edge-device/pull/1798) Add error handling for memory intensive tasks
|
||||
- [1784](https://github.com/jomjol/AI-on-the-edge-device/pull/1784) Add option to disable brownout detector
|
||||
- Added full web browser based installation mode (including initial setup of SD-card) - see [WebInstaller](https://jomjol.github.io/AI-on-the-edge-device/index.html)
|
||||
- Added [Demo Mode](https://jomjol.github.io/AI-on-the-edge-device-docs/Demo-Mode)
|
||||
- [1648](https://github.com/jomjol/AI-on-the-edge-device/pull/1648) Added trigger to start a flow by [REST](https://jomjol.github.io/AI-on-the-edge-device-docs/REST-API) API or [MQTT](https://jomjol.github.io/AI-on-the-edge-device-docs/MQTT-API/)
|
||||
- Show special images during steps `Initializing` and `Take Image` as the current camera image might be incomplete or outdated
|
||||
|
||||
#### Changed
|
||||
- Migrated documentation (Wiki) to [https://jomjol.github.io/AI-on-the-edge-device-docs](https://jomjol.github.io/AI-on-the-edge-device-docs). Please help us to make it even better.
|
||||
- New OTA Update page with progress indication
|
||||
- Various memory optimizations
|
||||
- Cleanup code/Web UI
|
||||
- Updated models
|
||||
- [1809](https://github.com/jomjol/AI-on-the-edge-device/pull/1809) Store preprocessed image with ROI to RAM
|
||||
- Better log messages on some errors/issues
|
||||
- [1742](https://github.com/jomjol/AI-on-the-edge-device/pull/1742) Replace alert boxes with overlay info boxes
|
||||
- Improve log message when web UI is installed incomplete
|
||||
- [1676](https://github.com/jomjol/AI-on-the-edge-device/pull/1676) Improve NTP handling
|
||||
- HTML: improved user informations (info boxes, error hints, ...)
|
||||
- [1904](https://github.com/jomjol/AI-on-the-edge-device/pull/1904) Removed newlines in JSON and replaced all whitespaces where there was more than one
|
||||
|
||||
#### Fixed
|
||||
- Fixed many many things
|
||||
- [1509](https://github.com/jomjol/AI-on-the-edge-device/pull/1509) Protect `wifi.ini` from beeing deleted.
|
||||
- [1530](https://github.com/jomjol/AI-on-the-edge-device/pull/1530) Homeassistant `Problem Sensor`
|
||||
- [1518](https://github.com/jomjol/AI-on-the-edge-device/pull/1518) JSON Strings
|
||||
- [1817](https://github.com/jomjol/AI-on-the-edge-device/pull/1817) DataGraph: datafiles sorted -> newest on top
|
||||
|
||||
#### Removed
|
||||
- n.a.
|
||||
|
||||
### 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
|
||||
## [13.0.8] - 2022-12-19
|
||||
|
||||
**Home Assistant MQTT Discovery Support**
|
||||
|
||||
### Update Procedure
|
||||
|
||||
:bangbang: **Make sure to read the instructions below carfully!**.
|
||||
|
||||
1. Backup your configuration (use the `System -> Backup/Restore` page)!
|
||||
|
||||
2. You should update to `12.0.1` before you update to this release. All other migrations are untested.
|
||||
|
||||
3. Upload and update the `update-*.zip` file from this release.
|
||||
|
||||
4. Let it restart and check on the `System -> Info` page that the Firmware as well as the Web UI got updated. If only one got updated, redo the update. If it fails several times, you also can update the Firmware and the Web UI separately.
|
||||
|
||||
5. Safe way:
|
||||
1. Update first the `firmware.bin` (extract 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.
|
||||
### Update Procedure see [online documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/#update)
|
||||
|
||||
### Added
|
||||
|
||||
@@ -105,6 +81,20 @@ If anything breaks you can try to enforce manual update as following:
|
||||
- [#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
|
||||
- NEW v13.0.2: Update Tool "Logfile downloader and combiner" to handle the new csv file format.
|
||||
- NEW v13.0.2: MQTT: Added MQTT topic `status` (Digitalization Status), Timezone to MQTT topic `timestamp`.#
|
||||
- NEW v13.0.2: Logging: Disable heap logs by default, cleanup
|
||||
- NEW v13.0.7:
|
||||
- log NTP server name
|
||||
- Improved log messages
|
||||
- Various preparations for next release
|
||||
- **NEW v13.0.8**:
|
||||
- Continue booting on PSRAM issues, Web UI will show an error
|
||||
- Updated models
|
||||
- Various UI enhancements
|
||||
- Various internal improvements
|
||||
- Show uptime in log
|
||||
- Show uptime and round on overview page
|
||||
|
||||
### Fixed
|
||||
|
||||
@@ -116,6 +106,23 @@ If anything breaks you can try to enforce manual update as following:
|
||||
- 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
|
||||
- NEW v13.0.2: Corrected Version comparison between firmware and Web UI.
|
||||
- NEW v13.0.3: Re-updated build environment to v5.2.0 (from accidental downgrad to v4.4.0)
|
||||
- NEW v13.0.4: Fix for reboot in case of MQTT not used
|
||||
- NEW v13.0.5: No reboot in case of missing NTP-connection
|
||||
- NEW v13.0.7:
|
||||
- Prevent autoreboot on cam framebuffer init error
|
||||
- Properly protect `wlan.ini` against deletion
|
||||
- Fixed various MQTT topic content issues
|
||||
- Fix Digit detected as 10 (<https://github.com/jomjol/AI-on-the-edge-device/pull/1525>)
|
||||
- Fix frozen time in datafile on error
|
||||
- Various minor fixes
|
||||
- **NEW v13.0.8**:
|
||||
- Fix Rate Problem ([#1578](https://github.com/jomjol/AI-on-the-edge-device/issues/1578), [#1572](https://github.com/jomjol/AI-on-the-edge-device/issues/1572))
|
||||
- Stabilized MQTT
|
||||
- Fixed redundant calls in OTA
|
||||
- Block REST API calls till resource is ready
|
||||
- Fixed number renaming ([#1635](https://github.com/jomjol/AI-on-the-edge-device/issues/1635))
|
||||
|
||||
### Removed
|
||||
|
||||
@@ -137,8 +144,8 @@ Improve **u**ser e**x**perience
|
||||
5. Now you can reboot.
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -790,9 +797,15 @@ External Illumination
|
||||
|
||||
- Initial Version
|
||||
|
||||
[Unreleased]: https://github.com/jomjol/AI-on-the-edge-device/compare/13.0.2...HEAD
|
||||
[Unreleased]: https://github.com/jomjol/AI-on-the-edge-device/compare/13.0.8...HEAD
|
||||
|
||||
[13.0.2]: https://github.com/jomjol/AI-on-the-edge-device/compare/13.0.1...13.0.2
|
||||
[13.0.8]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.8
|
||||
|
||||
[13.0.7]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.7
|
||||
|
||||
[13.0.5]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.5
|
||||
|
||||
[13.0.4]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.4
|
||||
|
||||
[13.0.1]: https://github.com/jomjol/AI-on-the-edge-device/compare/12.0.1...13.0.1
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@
|
||||
|
||||
|
||||
____
|
||||
#### #34 implement state and Roi for water leak detection
|
||||
for example see Roi on the next picture..
|
||||

|
||||
in case of position change between the measurments set this state to true, if there is no change set it back to false.
|
||||
In a defined time window this movement can lead into an alarm state / water leak..
|
||||
haveing this state in the mqtt broker can trigger functions like closing the ater pipe walve and so on...
|
||||
|
||||
|
||||
|
||||
#### #33 Implement MATTER protocoll
|
||||
|
||||
|
||||
22
README.md
22
README.md
@@ -6,18 +6,21 @@ Here this edge computing is brought into a practical oriented example, where a A
|
||||
|
||||
This projects allows you to digitalize your **analoge** water, gas, power and other meters using cheap and easily available hardware.
|
||||
|
||||
All you need is an [ESP32 board with a supported camera](https://github.com/jomjol/AI-on-the-edge-device/wiki/Hardware-Compatibility) and a bit of a practical hand.
|
||||
All you need is an [ESP32 board with a supported camera](https://jomjol.github.io/AI-on-the-edge-device-docs/Hardware-Compatibility/) and a bit of a practical hand.
|
||||
|
||||
<img src="images/esp32-cam.png" width="200px">
|
||||
|
||||
## Key features
|
||||
- Tensorflow Lite (TFlite) integration - including easy to use wrapper
|
||||
- Inline Image processing (feature detection, alignment, ROI extraction)
|
||||
- **Small** and **cheap** device (3x4.5x2 cm³, < 10 EUR)
|
||||
- camera and illumination integrated
|
||||
- Web surface for administration and control
|
||||
- Web surface to administrate and control
|
||||
- OTA-Interface to update directly through the web interface
|
||||
- API for easy integration
|
||||
- Inline Image processing (feature detection, alignment, ROI extraction)
|
||||
- Tensorflow Lite (TFlite) integration - including easy to use wrapper
|
||||
- Full integration into Homeassistant
|
||||
- Support for Influx DB 1
|
||||
- MQTT
|
||||
- REST API
|
||||
|
||||
## Workflow
|
||||
The device takes a photo of your meter at a defined interval. It then extracts the Regions of Interest (ROI's) out of it and runs them through an artificial inteligence. As a result, you get the digitalized value of your meter.
|
||||
@@ -38,7 +41,7 @@ There are several options what to do with that value. Either send it to a MQTT b
|
||||
|
||||
|
||||
## Setup
|
||||
There is a growing [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki) which provides you with a lot of information.
|
||||
There is a growing [documentation](https://jomjol.github.io/AI-on-the-edge-device-docs/) which provides you with a lot of information.
|
||||
Head there to get a start, set it up and configure it.
|
||||
|
||||
There are also a articles in the German Heise magazine "make:" about the setup and the technical background (behind a paywall) : [DIY - Setup](https://www.heise.de/select/make/2021/2/2103513300897420296)
|
||||
@@ -56,7 +59,10 @@ There are different ways to flash your ESP32:
|
||||
- Flash Tool from Espressif
|
||||
- ESPtool (Command Line Tool)
|
||||
|
||||
See the [Wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Installation) for more information.
|
||||
See the [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/) for more information.
|
||||
|
||||
### Flashing the SD-Card
|
||||
The SD-Card must be flashed separately, see the [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/Installation/) for details.
|
||||
|
||||
## Casing
|
||||
|
||||
@@ -87,7 +93,7 @@ See [Changelog](Changelog.md)
|
||||
## Tools
|
||||
|
||||
* Logfile downloader and combiner (Thx to [reserve85](https://github.com/reserve85))
|
||||
* Files see ['/tools/logfile-tool'](tbd), How-to see [wiki](https://github.com/jomjol/AI-on-the-edge-device/wiki/Gasmeter-Log-Downloader)
|
||||
* Files see ['/tools/logfile-tool'](tbd), How-to see [Docu](https://jomjol.github.io/AI-on-the-edge-device-docs/outdated--Gasmeter-Log-Downloader/)
|
||||
|
||||
## Additional Ideas
|
||||
There are some ideas and feature requests which are not followed currently - mainly due to capacity reasons on side of the developer. They are collected here: [FeatureRequest.md](FeatureRequest.md)
|
||||
|
||||
8
code/.gitignore
vendored
8
code/.gitignore
vendored
@@ -5,3 +5,11 @@
|
||||
.vscode/ipch
|
||||
version.cpp
|
||||
sdkconfig.esp32cam
|
||||
sdkconfig.esp32cam-dev
|
||||
sdkconfig.esp32cam-debug
|
||||
sdkconfig.esp32cam-board-rev3
|
||||
sdkconfig.esp32cam-cpu-freq-240
|
||||
sdkconfig.esp32cam-board-rev3-cpu-freq-240
|
||||
sdkconfig.esp32cam-dev-himem
|
||||
sdkconfig.esp32cam-dev-task-analysis
|
||||
sdkconfig.esp32cam-no-softap
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 3.13.4)
|
||||
cmake_minimum_required(VERSION 3.16.0)
|
||||
|
||||
list(APPEND EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common components/tflite-micro-esp-examples/components/tflite-lib)
|
||||
|
||||
@@ -8,6 +8,15 @@ ADD_CUSTOM_COMMAND(
|
||||
COMMAND ${CMAKE_COMMAND} -P
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/version.cmake)
|
||||
|
||||
if(EXISTS "${SDKCONFIG}.defaults")
|
||||
if(EXISTS "sdkconfig.defaults")
|
||||
set(SDKCONFIG_DEFAULTS "${SDKCONFIG}.defaults;sdkconfig.defaults")
|
||||
message(STATUS "-- Using defaults: ${SDKCONFIG_DEFAULTS} + sdkconfig.defaults")
|
||||
else()
|
||||
set(SDKCONFIG_DEFAULTS "${SDKCONFIG}.defaults")
|
||||
endif()
|
||||
message(STATUS "-- Using defaults: ${SDKCONFIG_DEFAULTS}")
|
||||
endif()
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(esp32cam-server-only)
|
||||
project(AI-on-the-edge)
|
||||
|
||||
@@ -6,12 +6,14 @@
|
||||
#include "configFile.h"
|
||||
#include <esp_log.h>
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "CONFIG";
|
||||
|
||||
ConfigFile::ConfigFile(std::string filePath)
|
||||
{
|
||||
std::string config = FormatFileName(filePath);
|
||||
pFile = OpenFileAndWait(config.c_str(), "r");
|
||||
pFile = fopen(config.c_str(), "r");
|
||||
}
|
||||
|
||||
ConfigFile::~ConfigFile()
|
||||
@@ -65,7 +67,7 @@ bool ConfigFile::getNextLine(std::string *rt, bool &disabled, bool &eof)
|
||||
}
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CONFIGFILE_H
|
||||
#define CONFIGFILE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@@ -9,7 +14,10 @@ public:
|
||||
bool isNewParagraph(std::string input);
|
||||
bool GetNextParagraph(std::string& aktparamgraph, bool &disabled, bool &eof);
|
||||
bool getNextLine(std::string* rt, bool &disabled, bool &eof);
|
||||
bool ConfigFileExists(){return pFile;};
|
||||
|
||||
private:
|
||||
FILE* pFile;
|
||||
};
|
||||
};
|
||||
|
||||
#endif //CONFIGFILE_H
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#include <cstdint>
|
||||
#include "esp_attr.h"
|
||||
union Hsv;
|
||||
@@ -67,3 +70,5 @@ union Hsv {
|
||||
bool operator==( Hsv in ) const { return in.value == value; }
|
||||
void swap( Hsv& o ) { value = o.value; }
|
||||
};
|
||||
|
||||
#endif //COLOR_H
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SMARTLEDS_H
|
||||
#define SMARTLEDS_H
|
||||
|
||||
/*
|
||||
* A C++ driver for the WS2812 LEDs using the RMT peripheral on the ESP32.
|
||||
*
|
||||
@@ -528,3 +531,5 @@ private:
|
||||
int _latchFrames;
|
||||
uint8_t _latchBuffer[ LATCH_FRAME_SIZE_BYTES ];
|
||||
};
|
||||
|
||||
#endif //SMARTLEDS_H
|
||||
|
||||
@@ -10,28 +10,26 @@
|
||||
|
||||
#include "server_tflite.h"
|
||||
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
//#include "errno.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <vector>
|
||||
//#include <regex>
|
||||
|
||||
#include "defines.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "server_GPIO.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "configFile.h"
|
||||
#include "Helper.h"
|
||||
#include "interface_mqtt.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
static const char *TAG = "GPIO";
|
||||
QueueHandle_t gpio_queue_handle = NULL;
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
GpioPin::GpioPin(gpio_num_t gpio, const char* name, gpio_pin_mode_t mode, gpio_int_type_t interruptType, uint8_t dutyResolution, std::string mqttTopic, bool httpEnable)
|
||||
{
|
||||
_gpio = gpio;
|
||||
@@ -83,12 +81,14 @@ static void gpioHandlerTask(void *arg) {
|
||||
}
|
||||
|
||||
void GpioPin::gpioInterrupt(int value) {
|
||||
#ifdef ENABLE_MQTT
|
||||
if (_mqttTopic != "") {
|
||||
ESP_LOGD(TAG, "gpioInterrupt %s %d", _mqttTopic.c_str(), value);
|
||||
|
||||
MQTTPublish(_mqttTopic, value ? "true" : "false");
|
||||
currentState = value;
|
||||
MQTTPublish(_mqttTopic, value ? "true" : "false");
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
currentState = value;
|
||||
}
|
||||
|
||||
void GpioPin::init()
|
||||
@@ -114,10 +114,12 @@ void GpioPin::init()
|
||||
gpio_isr_handler_add(_gpio, gpio_isr_handler, (void*)&_gpio);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
if ((_mqttTopic != "") && ((_mode == GPIO_PIN_MODE_OUTPUT) || (_mode == GPIO_PIN_MODE_OUTPUT_PWM) || (_mode == GPIO_PIN_MODE_BUILT_IN_FLASH_LED))) {
|
||||
std::function<bool(std::string, char*, int)> f = std::bind(&GpioPin::handleMQTT, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
|
||||
MQTTregisterSubscribeFunction(_mqttTopic, f);
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
}
|
||||
|
||||
bool GpioPin::getValue(std::string* errorText)
|
||||
@@ -138,9 +140,11 @@ void GpioPin::setValue(bool value, gpio_set_source setSource, std::string* error
|
||||
} else {
|
||||
gpio_set_level(_gpio, value);
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
if ((_mqttTopic != "") && (setSource != GPIO_SET_SOURCE_MQTT)) {
|
||||
MQTTPublish(_mqttTopic, value ? "true" : "false");
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,11 +152,14 @@ void GpioPin::publishState() {
|
||||
int newState = gpio_get_level(_gpio);
|
||||
if (newState != currentState) {
|
||||
ESP_LOGD(TAG,"publish state of GPIO %d new state %d", _gpio, newState);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(_mqttTopic, newState ? "true" : "false");
|
||||
#endif //ENABLE_MQTT
|
||||
currentState = newState;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
|
||||
ESP_LOGD(TAG, "GpioPin::handleMQTT data %.*s", data_len, data);
|
||||
|
||||
@@ -174,7 +181,7 @@ bool GpioPin::handleMQTT(std::string, char* data, int data_len) {
|
||||
|
||||
return (errorText == "");
|
||||
}
|
||||
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
esp_err_t callHandleHttpRequest(httpd_req_t *req)
|
||||
{
|
||||
@@ -236,12 +243,14 @@ void GpioHandler::init()
|
||||
it->second->init();
|
||||
}
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
std::function<void()> f = std::bind(&GpioHandler::handleMQTTconnect, this);
|
||||
MQTTregisterConnectFunction("gpio-handler", f);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
if (xHandleTaskGpio == NULL) {
|
||||
gpio_queue_handle = xQueueCreate(10,sizeof(GpioResult));
|
||||
BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", configMINIMAL_STACK_SIZE * 8, (void *)this, tskIDLE_PRIORITY + 2, &xHandleTaskGpio);
|
||||
BaseType_t xReturned = xTaskCreate(&gpioHandlerTask, "gpio_int", 3 * 1024, (void *)this, tskIDLE_PRIORITY + 4, &xHandleTaskGpio);
|
||||
if(xReturned == pdPASS ) {
|
||||
ESP_LOGD(TAG, "xHandletaskGpioHandler started");
|
||||
} else {
|
||||
@@ -261,7 +270,7 @@ void GpioHandler::taskHandler() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
void GpioHandler::handleMQTTconnect()
|
||||
{
|
||||
if (gpioMap != NULL) {
|
||||
@@ -271,9 +280,12 @@ void GpioHandler::handleMQTTconnect()
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
void GpioHandler::deinit() {
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTunregisterConnectFunction("gpio-handler");
|
||||
#endif //ENABLE_MQTT
|
||||
clear();
|
||||
if (xHandleTaskGpio != NULL) {
|
||||
vTaskDelete(xHandleTaskGpio);
|
||||
@@ -294,7 +306,7 @@ bool GpioHandler::readConfig()
|
||||
|
||||
ConfigFile configFile = ConfigFile(_configFile);
|
||||
|
||||
std::vector<std::string> zerlegt;
|
||||
std::vector<std::string> splitted;
|
||||
std::string line = "";
|
||||
bool disabledLine = false;
|
||||
bool eof = false;
|
||||
@@ -316,6 +328,7 @@ bool GpioHandler::readConfig()
|
||||
|
||||
// ESP_LOGD(TAG, "readConfig - Start 3");
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
// std::string mainTopicMQTT = "";
|
||||
std::string mainTopicMQTT = GetMQTTMainTopic();
|
||||
if (mainTopicMQTT.length() > 0)
|
||||
@@ -323,37 +336,43 @@ bool GpioHandler::readConfig()
|
||||
mainTopicMQTT = mainTopicMQTT + "/GPIO";
|
||||
ESP_LOGD(TAG, "MAINTOPICMQTT found");
|
||||
}
|
||||
|
||||
#endif // ENABLE_MQTT
|
||||
bool registerISR = false;
|
||||
while (configFile.getNextLine(&line, disabledLine, eof) && !configFile.isNewParagraph(line))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(line);
|
||||
splitted = ZerlegeZeile(line);
|
||||
// const std::regex pieces_regex("IO([0-9]{1,2})");
|
||||
// std::smatch pieces_match;
|
||||
// if (std::regex_match(zerlegt[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
|
||||
// if (std::regex_match(splitted[0], pieces_match, pieces_regex) && (pieces_match.size() == 2))
|
||||
// {
|
||||
// std::string gpioStr = pieces_match[1];
|
||||
ESP_LOGD(TAG, "conf param %s", toUpper(zerlegt[0]).c_str());
|
||||
if (toUpper(zerlegt[0]) == "MAINTOPICMQTT") {
|
||||
ESP_LOGD(TAG, "conf param %s", toUpper(splitted[0]).c_str());
|
||||
if (toUpper(splitted[0]) == "MAINTOPICMQTT") {
|
||||
// ESP_LOGD(TAG, "MAINTOPICMQTT found");
|
||||
// mainTopicMQTT = zerlegt[1];
|
||||
} else if ((zerlegt[0].rfind("IO", 0) == 0) && (zerlegt.size() >= 6))
|
||||
// mainTopicMQTT = splitted[1];
|
||||
} else if ((splitted[0].rfind("IO", 0) == 0) && (splitted.size() >= 6))
|
||||
{
|
||||
ESP_LOGI(TAG,"Enable GP%s in %s mode", zerlegt[0].c_str(), zerlegt[1].c_str());
|
||||
std::string gpioStr = zerlegt[0].substr(2, 2);
|
||||
ESP_LOGI(TAG,"Enable GP%s in %s mode", splitted[0].c_str(), splitted[1].c_str());
|
||||
std::string gpioStr = splitted[0].substr(2, 2);
|
||||
gpio_num_t gpioNr = (gpio_num_t)atoi(gpioStr.c_str());
|
||||
gpio_pin_mode_t pinMode = resolvePinMode(toLower(zerlegt[1]));
|
||||
gpio_int_type_t intType = resolveIntType(toLower(zerlegt[2]));
|
||||
uint16_t dutyResolution = (uint8_t)atoi(zerlegt[3].c_str());
|
||||
bool mqttEnabled = toLower(zerlegt[4]) == "true";
|
||||
bool httpEnabled = toLower(zerlegt[5]) == "true";
|
||||
gpio_pin_mode_t pinMode = resolvePinMode(toLower(splitted[1]));
|
||||
gpio_int_type_t intType = resolveIntType(toLower(splitted[2]));
|
||||
uint16_t dutyResolution = (uint8_t)atoi(splitted[3].c_str());
|
||||
#ifdef ENABLE_MQTT
|
||||
bool mqttEnabled = toLower(splitted[4]) == "true";
|
||||
#endif // ENABLE_MQTT
|
||||
bool httpEnabled = toLower(splitted[5]) == "true";
|
||||
char gpioName[100];
|
||||
if (zerlegt.size() >= 7) {
|
||||
strcpy(gpioName, trim(zerlegt[6]).c_str());
|
||||
if (splitted.size() >= 7) {
|
||||
strcpy(gpioName, trim(splitted[6]).c_str());
|
||||
} else {
|
||||
sprintf(gpioName, "GPIO%d", gpioNr);
|
||||
}
|
||||
#ifdef ENABLE_MQTT
|
||||
std::string mqttTopic = mqttEnabled ? (mainTopicMQTT + "/" + gpioName) : "";
|
||||
#else // ENABLE_MQTT
|
||||
std::string mqttTopic = "";
|
||||
#endif // ENABLE_MQTT
|
||||
GpioPin* gpioPin = new GpioPin(gpioNr, gpioName, pinMode, intType,dutyResolution, mqttTopic, httpEnabled);
|
||||
(*gpioMap)[gpioNr] = gpioPin;
|
||||
|
||||
@@ -367,28 +386,28 @@ bool GpioHandler::readConfig()
|
||||
registerISR = true;
|
||||
}
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDNUMBERS")
|
||||
if (toUpper(splitted[0]) == "LEDNUMBERS")
|
||||
{
|
||||
LEDNumbers = stoi(zerlegt[1]);
|
||||
LEDNumbers = stoi(splitted[1]);
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDCOLOR")
|
||||
if (toUpper(splitted[0]) == "LEDCOLOR")
|
||||
{
|
||||
uint8_t _r, _g, _b;
|
||||
_r = stoi(zerlegt[1]);
|
||||
_g = stoi(zerlegt[2]);
|
||||
_b = stoi(zerlegt[3]);
|
||||
_r = stoi(splitted[1]);
|
||||
_g = stoi(splitted[2]);
|
||||
_b = stoi(splitted[3]);
|
||||
|
||||
LEDColor = Rgb{_r, _g, _b};
|
||||
}
|
||||
if (toUpper(zerlegt[0]) == "LEDTYPE")
|
||||
if (toUpper(splitted[0]) == "LEDTYPE")
|
||||
{
|
||||
if (zerlegt[1] == "WS2812")
|
||||
if (splitted[1] == "WS2812")
|
||||
LEDType = LED_WS2812;
|
||||
if (zerlegt[1] == "WS2812B")
|
||||
if (splitted[1] == "WS2812B")
|
||||
LEDType = LED_WS2812B;
|
||||
if (zerlegt[1] == "SK6812")
|
||||
if (splitted[1] == "SK6812")
|
||||
LEDType = LED_SK6812;
|
||||
if (zerlegt[1] == "WS2813")
|
||||
if (splitted[1] == "WS2813")
|
||||
LEDType = LED_WS2813;
|
||||
}
|
||||
}
|
||||
@@ -673,6 +692,7 @@ void gpio_handler_deinit() {
|
||||
void gpio_handler_destroy()
|
||||
{
|
||||
if (gpioHandler != NULL) {
|
||||
gpio_handler_deinit();
|
||||
delete gpioHandler;
|
||||
gpioHandler = NULL;
|
||||
}
|
||||
@@ -682,3 +702,4 @@ GpioHandler* gpio_handler_get()
|
||||
{
|
||||
return gpioHandler;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVER_GPIO_H
|
||||
#define SERVER_GPIO_H
|
||||
|
||||
@@ -9,11 +11,6 @@
|
||||
|
||||
#include "SmartLeds.h"
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
|
||||
// wenn __LEDGLOBAL definiert ist, wird eine globale Variable für die LED-Ansteuerung verwendet, ansonsten lokal und jedesmal neu
|
||||
#define __LEDGLOBAL
|
||||
|
||||
typedef enum {
|
||||
GPIO_PIN_MODE_DISABLED = 0x0,
|
||||
GPIO_PIN_MODE_INPUT = 0x1,
|
||||
@@ -45,7 +42,9 @@ public:
|
||||
void init();
|
||||
bool getValue(std::string* errorText);
|
||||
void setValue(bool value, gpio_set_source setSource, std::string* errorText);
|
||||
#ifdef ENABLE_MQTT
|
||||
bool handleMQTT(std::string, char* data, int data_len);
|
||||
#endif //ENABLE_MQTT
|
||||
void publishState();
|
||||
void gpioInterrupt(int value);
|
||||
gpio_int_type_t getInterruptType() { return _interruptType; }
|
||||
@@ -77,7 +76,9 @@ public:
|
||||
void gpioInterrupt(GpioResult* gpioResult);
|
||||
void flashLightEnable(bool value);
|
||||
bool isEnabled() { return _isEnabled; }
|
||||
#ifdef ENABLE_MQTT
|
||||
void handleMQTTconnect();
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
private:
|
||||
std::string _configFile;
|
||||
@@ -109,4 +110,5 @@ GpioHandler* gpio_handler_get();
|
||||
|
||||
|
||||
|
||||
#endif //SERVER_GPIO_H
|
||||
#endif //SERVER_GPIO_H
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@
|
||||
#include "server_ota.h"
|
||||
#include "server_GPIO.h"
|
||||
|
||||
|
||||
#define BOARD_ESP32CAM_AITHINKER
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <esp_event.h>
|
||||
#include <esp_log.h>
|
||||
@@ -28,45 +26,8 @@
|
||||
|
||||
#include "esp_camera.h"
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
#define USE_PWM_LEDFLASH
|
||||
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
|
||||
//// PWM für Flash-LED
|
||||
#define LEDC_TIMER LEDC_TIMER_1 // LEDC_TIMER_0
|
||||
#define LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_OUTPUT_IO (4) // Define the output GPIO
|
||||
#define LEDC_CHANNEL LEDC_CHANNEL_1
|
||||
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
|
||||
//#define LEDC_DUTY (195) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095
|
||||
#define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
// ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN 32
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 0
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 21
|
||||
#define CAM_PIN_D2 19
|
||||
#define CAM_PIN_D1 18
|
||||
#define CAM_PIN_D0 5
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#include "driver/ledc.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
static const char *TAG = "CAM";
|
||||
|
||||
@@ -90,8 +51,8 @@ static camera_config_t camera_config = {
|
||||
.pin_pclk = CAM_PIN_PCLK,
|
||||
|
||||
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
|
||||
.xclk_freq_hz = 20000000, // Orginalwert
|
||||
// .xclk_freq_hz = 5000000, // Test, um die Bildfehler los zu werden !!!! Hängt in Version 9.2 !!!!
|
||||
.xclk_freq_hz = 20000000, // Orginal value
|
||||
// .xclk_freq_hz = 5000000, // Test to get rid of the image errors !!!! Hangs in version 9.2 !!!!
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
@@ -101,18 +62,16 @@ static camera_config_t camera_config = {
|
||||
.jpeg_quality = 12, //0-63 lower number means higher quality
|
||||
.fb_count = 1, //if more than one, i2s runs in continuous mode. Use only with JPEG
|
||||
.fb_location = CAMERA_FB_IN_PSRAM, /*!< The location where the frame buffer will be allocated */
|
||||
// .grab_mode = CAMERA_GRAB_WHEN_EMPTY,
|
||||
.grab_mode = CAMERA_GRAB_LATEST, // erst ab neuer esp32cam-version
|
||||
.grab_mode = CAMERA_GRAB_LATEST, // only from new esp32cam version
|
||||
|
||||
};
|
||||
|
||||
|
||||
#include "driver/ledc.h"
|
||||
|
||||
CCamera Camera;
|
||||
|
||||
#define FLASH_GPIO GPIO_NUM_4
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
uint8_t *demoImage = NULL; // Buffer holding the demo image in bytes
|
||||
|
||||
#define DEMO_IMAGE_SIZE 30000 // Max size of demo image in bytes
|
||||
|
||||
typedef struct {
|
||||
httpd_req_t *req;
|
||||
@@ -120,6 +79,21 @@ typedef struct {
|
||||
} jpg_chunking_t;
|
||||
|
||||
|
||||
bool CCamera::testCamera(void) {
|
||||
bool success;
|
||||
camera_fb_t *fb = esp_camera_fb_get();
|
||||
if (fb) {
|
||||
success = true;
|
||||
}
|
||||
else {
|
||||
success = false;
|
||||
}
|
||||
|
||||
esp_camera_fb_return(fb);
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void CCamera::ledc_init(void)
|
||||
{
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
@@ -164,6 +138,7 @@ static size_t jpg_encode_stream(void * arg, size_t index, const void* data, size
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
bool CCamera::SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation)
|
||||
{
|
||||
bool result = false;
|
||||
@@ -221,39 +196,17 @@ void CCamera::SetQualitySize(int qual, framesize_t resol)
|
||||
image_height = 480;
|
||||
image_width = 640;
|
||||
}
|
||||
// No higher Mode than VGA, damit der Kameraspeicher ausreicht.
|
||||
/*
|
||||
if (resol == FRAMESIZE_SVGA)
|
||||
{
|
||||
image_height = 600;
|
||||
image_width = 800;
|
||||
}
|
||||
if (resol == FRAMESIZE_XGA)
|
||||
{
|
||||
image_height = 768;
|
||||
image_width = 1024;
|
||||
}
|
||||
if (resol == FRAMESIZE_SXGA)
|
||||
{
|
||||
image_height = 1024;
|
||||
image_width = 1280;
|
||||
}
|
||||
if (resol == FRAMESIZE_UXGA)
|
||||
{
|
||||
image_height = 1200;
|
||||
image_width = 1600;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CCamera::EnableAutoExposure(int flashdauer)
|
||||
void CCamera::EnableAutoExposure(int flash_duration)
|
||||
{
|
||||
ESP_LOGD(TAG, "EnableAutoExposure");
|
||||
LEDOnOff(true);
|
||||
if (flashdauer > 0)
|
||||
if (flash_duration > 0)
|
||||
LightOnOff(true);
|
||||
const TickType_t xDelay = flashdauer / portTICK_PERIOD_MS;
|
||||
const TickType_t xDelay = flash_duration / portTICK_PERIOD_MS;
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
@@ -277,24 +230,20 @@ void CCamera::EnableAutoExposure(int flashdauer)
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
isFixedExposure = true;
|
||||
waitbeforepicture_org = flashdauer;
|
||||
waitbeforepicture_org = flash_duration;
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
{
|
||||
string ftype;
|
||||
|
||||
uint8_t *zwischenspeicher = NULL;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start");
|
||||
#endif
|
||||
|
||||
_Image->EmptyImage(); //Delete previous stored raw image -> black image
|
||||
|
||||
LEDOnOff(true);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Start");
|
||||
#endif
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
LightOnOff(true);
|
||||
@@ -302,18 +251,18 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
vTaskDelay( xDelay );
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LightOn");
|
||||
#endif
|
||||
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
esp_camera_fb_return(fb);
|
||||
fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
ESP_LOGE(TAG, "CaptureToBasisImage: Capture Failed");
|
||||
LEDOnOff(false);
|
||||
LightOnOff(false);
|
||||
|
||||
ESP_LOGE(TAG, "CaptureToBasisImage: Capture Failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "is not working anymore (CCamera::CaptureToBasisImage) - most probably caused by a hardware problem (instablility, ...). "
|
||||
"System will reboot.");
|
||||
doReboot();
|
||||
@@ -321,20 +270,18 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int _size = fb->len;
|
||||
zwischenspeicher = (uint8_t*) malloc(_size);
|
||||
if (!zwischenspeicher)
|
||||
{
|
||||
ESP_LOGE(TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Insufficient memory space for image in function CaptureToBasisImage()");
|
||||
if (demoMode) { // Use images stored on SD-Card instead of camera image
|
||||
/* Replace Framebuffer with image from SD-Card */
|
||||
loadNextDemoImage(fb);
|
||||
}
|
||||
for (int i = 0; i < _size; ++i)
|
||||
*(zwischenspeicher + i) = *(fb->buf + i);
|
||||
|
||||
CImageBasis* _zwImage = new CImageBasis();
|
||||
_zwImage->LoadFromMemory(fb->buf, fb->len);
|
||||
esp_camera_fb_return(fb);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After fb_get");
|
||||
#endif
|
||||
|
||||
LEDOnOff(false);
|
||||
|
||||
@@ -344,15 +291,9 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
// TickType_t xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
// vTaskDelay( xDelay ); // wait for power to recover
|
||||
|
||||
uint8_t * buf = NULL;
|
||||
|
||||
CImageBasis _zwImage;
|
||||
_zwImage.LoadFromMemory(zwischenspeicher, _size);
|
||||
free(zwischenspeicher);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LoadFromMemory");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After LoadFromMemory");
|
||||
#endif
|
||||
|
||||
stbi_uc* p_target;
|
||||
stbi_uc* p_source;
|
||||
@@ -360,31 +301,27 @@ esp_err_t CCamera::CaptureToBasisImage(CImageBasis *_Image, int delay)
|
||||
int width = image_width;
|
||||
int height = image_height;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
|
||||
_zw = _zw + " _zwImage: " + std::to_string((int) _zwImage.rgb_image) + " Size: " + std::to_string(_zwImage.width) + ", " + std::to_string(_zwImage.height);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "Targetimage: " + std::to_string((int) _Image->rgb_image) + " Size: " + std::to_string(_Image->width) + ", " + std::to_string(_Image->height);
|
||||
_zw = _zw + " _zwImage: " + std::to_string((int) _zwImage->rgb_image) + " Size: " + std::to_string(_zwImage->width) + ", " + std::to_string(_zwImage->height);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
#endif
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
p_target = _Image->rgb_image + (channels * (y * width + x));
|
||||
p_source = _zwImage.rgb_image + (channels * (y * width + x));
|
||||
p_source = _zwImage->rgb_image + (channels * (y * width + x));
|
||||
p_target[0] = p_source[0];
|
||||
p_target[1] = p_source[1];
|
||||
p_target[2] = p_source[2];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - After Copy To Target");
|
||||
#endif
|
||||
delete _zwImage;
|
||||
|
||||
free(buf);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CCamera::CaptureToBasisImage - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -394,7 +331,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
{
|
||||
string ftype;
|
||||
|
||||
LEDOnOff(true); // Abgeschaltet, um Strom zu sparen !!!!!!
|
||||
LEDOnOff(true); // Switched off to save power !
|
||||
|
||||
if (delay > 0)
|
||||
{
|
||||
@@ -418,21 +355,21 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
}
|
||||
LEDOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "w %d, h %d, size %d", fb->width, fb->height, fb->len);
|
||||
#endif
|
||||
|
||||
nm = FormatFileName(nm);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Save Camera to : %s", nm.c_str());
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Save Camera to: %s", nm.c_str());
|
||||
#endif
|
||||
|
||||
ftype = toUpper(getFileType(nm));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filetype: %s", ftype.c_str());
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filetype: %s", ftype.c_str());
|
||||
#endif
|
||||
|
||||
uint8_t * buf = NULL;
|
||||
size_t buf_len = 0;
|
||||
@@ -457,7 +394,7 @@ esp_err_t CCamera::CaptureToFile(std::string nm, int delay)
|
||||
}
|
||||
}
|
||||
|
||||
FILE * fp = OpenFileAndWait(nm.c_str(), "wb");
|
||||
FILE * fp = fopen(nm.c_str(), "wb");
|
||||
if (fp == NULL) /* If an error occurs during the file creation */
|
||||
{
|
||||
fprintf(stderr, "fopen() failed for '%s'\n", nm.c_str());
|
||||
@@ -520,14 +457,23 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
}
|
||||
|
||||
if(res == ESP_OK){
|
||||
if(fb->format == PIXFORMAT_JPEG){
|
||||
fb_len = fb->len;
|
||||
if (demoMode) { // Use images stored on SD-Card instead of camera image
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using Demo image!");
|
||||
/* Replace Framebuffer with image from SD-Card */
|
||||
loadNextDemoImage(fb);
|
||||
|
||||
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
|
||||
} else {
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
fb_len = jchunk.len;
|
||||
}
|
||||
else {
|
||||
if(fb->format == PIXFORMAT_JPEG){
|
||||
fb_len = fb->len;
|
||||
res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
|
||||
} else {
|
||||
jpg_chunking_t jchunk = {req, 0};
|
||||
res = frame2jpg_cb(fb, 80, jpg_encode_stream, &jchunk)?ESP_OK:ESP_FAIL;
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
fb_len = jchunk.len;
|
||||
}
|
||||
}
|
||||
}
|
||||
esp_camera_fb_return(fb);
|
||||
@@ -543,6 +489,7 @@ esp_err_t CCamera::CaptureToHTTP(httpd_req_t *req, int delay)
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void CCamera::LightOnOff(bool status)
|
||||
{
|
||||
GpioHandler* gpioHandler = gpio_handler_get();
|
||||
@@ -578,6 +525,7 @@ void CCamera::LightOnOff(bool status)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CCamera::LEDOnOff(bool status)
|
||||
{
|
||||
// Init the GPIO
|
||||
@@ -635,9 +583,10 @@ void CCamera::GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol
|
||||
if (qual < 0)
|
||||
qual = 0;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
framesize_t CCamera::TextToFramesize(const char * _size)
|
||||
{
|
||||
if (strcmp(_size, "QVGA") == 0)
|
||||
@@ -669,21 +618,25 @@ CCamera::CCamera()
|
||||
ledc_init();
|
||||
}
|
||||
|
||||
|
||||
esp_err_t CCamera::InitCam()
|
||||
{
|
||||
ESP_LOGD(TAG, "Init Camera");
|
||||
ActualQuality = camera_config.jpeg_quality;
|
||||
ActualResolution = camera_config.frame_size;
|
||||
//initialize the camera
|
||||
esp_camera_deinit(); // De-init in case it was already initialized
|
||||
esp_err_t err = esp_camera_init(&camera_config);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Camera Init Failed");
|
||||
return err;
|
||||
}
|
||||
|
||||
CameraInitSuccessful = true;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void CCamera::SetLEDIntensity(float _intrel)
|
||||
{
|
||||
_intrel = min(_intrel, (float) 100);
|
||||
@@ -693,3 +646,92 @@ void CCamera::SetLEDIntensity(float _intrel)
|
||||
ESP_LOGD(TAG, "Set led_intensity to %d of 8191", led_intensity);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CCamera::getCameraInitSuccessful()
|
||||
{
|
||||
return CameraInitSuccessful;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> demoFiles;
|
||||
|
||||
void CCamera::useDemoMode()
|
||||
{
|
||||
char line[50];
|
||||
|
||||
FILE *fd = fopen("/sdcard/demo/files.txt", "r");
|
||||
if (!fd) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can not start Demo mode, the folder '/sdcard/demo/' does not contain the needed files!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "See Details on https://jomjol.github.io/AI-on-the-edge-device-docs/Demo-Mode!");
|
||||
return;
|
||||
}
|
||||
|
||||
demoImage = (uint8_t*)malloc(DEMO_IMAGE_SIZE);
|
||||
if (demoImage == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Unable to acquire required memory for demo image!");
|
||||
return;
|
||||
}
|
||||
|
||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||
line[strlen(line) - 1] = '\0';
|
||||
demoFiles.push_back(line);
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Using Demo mode (" + std::to_string(demoFiles.size()) +
|
||||
" files) instead of real camera image!");
|
||||
|
||||
for (auto file : demoFiles) {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, file);
|
||||
}
|
||||
|
||||
demoMode = true;
|
||||
}
|
||||
|
||||
|
||||
bool CCamera::loadNextDemoImage(camera_fb_t *fb) {
|
||||
char filename[50];
|
||||
int readBytes;
|
||||
long fileSize;
|
||||
|
||||
snprintf(filename, sizeof(filename), "/sdcard/demo/%s", demoFiles[getCountFlowRounds() % demoFiles.size()].c_str());
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Using " + std::string(filename) + " as demo image");
|
||||
|
||||
/* Inject saved image */
|
||||
|
||||
FILE * fp = fopen(filename, "rb");
|
||||
if (!fp) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filename) +"!");
|
||||
return false;
|
||||
}
|
||||
|
||||
fileSize = GetFileSize(filename);
|
||||
if (fileSize > DEMO_IMAGE_SIZE) {
|
||||
char buf[100];
|
||||
snprintf(buf, sizeof(buf), "Demo Image (%d bytes) is larger than provided buffer (%d bytes)!",
|
||||
(int)fileSize, DEMO_IMAGE_SIZE);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, std::string(buf));
|
||||
return false;
|
||||
}
|
||||
|
||||
readBytes = fread(demoImage, 1, DEMO_IMAGE_SIZE, fp);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "read " + std::to_string(readBytes) + " bytes");
|
||||
fclose(fp);
|
||||
|
||||
fb->buf = demoImage; // Update pointer
|
||||
fb->len = readBytes;
|
||||
// ToDo do we also need to set height, width, format and timestamp?
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
long CCamera::GetFileSize(std::string filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
long rc = stat(filename.c_str(), &stat_buf);
|
||||
return rc == 0 ? stat_buf.st_size : -1;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSCONTROLLCAMERA_H
|
||||
#define CLASSCONTROLLCAMERA_H
|
||||
|
||||
@@ -11,10 +13,7 @@
|
||||
#include <string>
|
||||
#include <esp_http_server.h>
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
class CCamera {
|
||||
protected:
|
||||
@@ -26,6 +25,11 @@ class CCamera {
|
||||
int led_intensity = 4095;
|
||||
|
||||
void ledc_init(void);
|
||||
bool CameraInitSuccessful = false;
|
||||
bool demoMode = false;
|
||||
|
||||
bool loadNextDemoImage(camera_fb_t *fb);
|
||||
long GetFileSize(std::string filename);
|
||||
|
||||
public:
|
||||
int image_height, image_width;
|
||||
@@ -40,9 +44,11 @@ class CCamera {
|
||||
bool SetBrightnessContrastSaturation(int _brightness, int _contrast, int _saturation);
|
||||
void GetCameraParameter(httpd_req_t *req, int &qual, framesize_t &resol);
|
||||
void SetLEDIntensity(float _intrel);
|
||||
|
||||
void EnableAutoExposure(int flashdauer);
|
||||
|
||||
bool testCamera(void);
|
||||
void EnableAutoExposure(int flash_duration);
|
||||
bool getCameraInitSuccessful();
|
||||
void useDemoMode(void);
|
||||
|
||||
|
||||
framesize_t TextToFramesize(const char * text);
|
||||
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef _IMG_CONVERTERS_H_
|
||||
#define _IMG_CONVERTERS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_camera.h"
|
||||
|
||||
typedef size_t (* jpg_out_cb)(void * arg, size_t index, const void* data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg_cb(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param cp Callback to be called to write the bytes of the output JPEG
|
||||
* @param arg Pointer to be passed to the callback
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg_cb(camera_fb_t * fb, uint8_t quality, jpg_out_cb cb, void * arg);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to JPEG buffer
|
||||
*
|
||||
* @param src Source buffer in RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2jpg(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to JPEG buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param quality JPEG quality of the resulting image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2jpg(camera_fb_t * fb, uint8_t quality, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to BMP buffer
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param width Width in pixels of the source image
|
||||
* @param height Height in pixels of the source image
|
||||
* @param format Format of the source image
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2bmp(uint8_t *src, size_t src_len, uint16_t width, uint16_t height, pixformat_t format, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert camera frame buffer to BMP buffer
|
||||
*
|
||||
* @param fb Source camera frame buffer
|
||||
* @param out Pointer to be populated with the address of the resulting buffer
|
||||
* @param out_len Pointer to be populated with the length of the output buffer
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool frame2bmp(camera_fb_t * fb, uint8_t ** out, size_t * out_len);
|
||||
|
||||
/**
|
||||
* @brief Convert image buffer to RGB888 buffer (used for face detection)
|
||||
*
|
||||
* @param src Source buffer in JPEG, RGB565, RGB888, YUYV or GRAYSCALE format
|
||||
* @param src_len Length in bytes of the source buffer
|
||||
* @param format Format of the source image
|
||||
* @param rgb_buf Pointer to the output buffer (width * height * 3)
|
||||
*
|
||||
* @return true on success
|
||||
*/
|
||||
bool fmt2rgb888(const uint8_t *src_buf, size_t src_len, pixformat_t format, uint8_t * rgb_buf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _IMG_CONVERTERS_H_ */
|
||||
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* This file is part of the OpenMV project.
|
||||
* Copyright (c) 2013/2014 Ibrahim Abdelkader <i.abdalkader@gmail.com>
|
||||
* This work is licensed under the MIT license, see the file LICENSE for details.
|
||||
*
|
||||
* Sensor abstraction layer.
|
||||
*
|
||||
*/
|
||||
#ifndef __SENSOR_H__
|
||||
#define __SENSOR_H__
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
OV9650_PID = 0x96,
|
||||
OV7725_PID = 0x77,
|
||||
OV2640_PID = 0x26,
|
||||
OV3660_PID = 0x3660,
|
||||
OV5640_PID = 0x5640,
|
||||
OV7670_PID = 0x76,
|
||||
NT99141_PID = 0x1410,
|
||||
GC2145_PID = 0x2145,
|
||||
GC032A_PID = 0x232a,
|
||||
GC0308_PID = 0x9b,
|
||||
} camera_pid_t;
|
||||
|
||||
typedef enum {
|
||||
CAMERA_OV7725,
|
||||
CAMERA_OV2640,
|
||||
CAMERA_OV3660,
|
||||
CAMERA_OV5640,
|
||||
CAMERA_OV7670,
|
||||
CAMERA_NT99141,
|
||||
CAMERA_GC2145,
|
||||
CAMERA_GC032A,
|
||||
CAMERA_GC0308,
|
||||
CAMERA_MODEL_MAX,
|
||||
CAMERA_NONE,
|
||||
} camera_model_t;
|
||||
|
||||
typedef enum {
|
||||
OV2640_SCCB_ADDR = 0x30,// 0x60 >> 1
|
||||
OV5640_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
OV3660_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
OV7725_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
OV7670_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
NT99141_SCCB_ADDR = 0x2A,// 0x54 >> 1
|
||||
GC2145_SCCB_ADDR = 0x3C,// 0x78 >> 1
|
||||
GC032A_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
GC0308_SCCB_ADDR = 0x21,// 0x42 >> 1
|
||||
} camera_sccb_addr_t;
|
||||
|
||||
typedef enum {
|
||||
PIXFORMAT_RGB565, // 2BPP/RGB565
|
||||
PIXFORMAT_YUV422, // 2BPP/YUV422
|
||||
PIXFORMAT_GRAYSCALE, // 1BPP/GRAYSCALE
|
||||
PIXFORMAT_JPEG, // JPEG/COMPRESSED
|
||||
PIXFORMAT_RGB888, // 3BPP/RGB888
|
||||
PIXFORMAT_RAW, // RAW
|
||||
PIXFORMAT_RGB444, // 3BP2P/RGB444
|
||||
PIXFORMAT_RGB555, // 3BP2P/RGB555
|
||||
} pixformat_t;
|
||||
|
||||
typedef enum {
|
||||
FRAMESIZE_96X96, // 96x96
|
||||
FRAMESIZE_QQVGA, // 160x120
|
||||
FRAMESIZE_QCIF, // 176x144
|
||||
FRAMESIZE_HQVGA, // 240x176
|
||||
FRAMESIZE_240X240, // 240x240
|
||||
FRAMESIZE_QVGA, // 320x240
|
||||
FRAMESIZE_CIF, // 400x296
|
||||
FRAMESIZE_HVGA, // 480x320
|
||||
FRAMESIZE_VGA, // 640x480
|
||||
FRAMESIZE_SVGA, // 800x600
|
||||
FRAMESIZE_XGA, // 1024x768
|
||||
FRAMESIZE_HD, // 1280x720
|
||||
FRAMESIZE_SXGA, // 1280x1024
|
||||
FRAMESIZE_UXGA, // 1600x1200
|
||||
// 3MP Sensors
|
||||
FRAMESIZE_FHD, // 1920x1080
|
||||
FRAMESIZE_P_HD, // 720x1280
|
||||
FRAMESIZE_P_3MP, // 864x1536
|
||||
FRAMESIZE_QXGA, // 2048x1536
|
||||
// 5MP Sensors
|
||||
FRAMESIZE_QHD, // 2560x1440
|
||||
FRAMESIZE_WQXGA, // 2560x1600
|
||||
FRAMESIZE_P_FHD, // 1080x1920
|
||||
FRAMESIZE_QSXGA, // 2560x1920
|
||||
FRAMESIZE_INVALID
|
||||
} framesize_t;
|
||||
|
||||
typedef struct {
|
||||
const camera_model_t model;
|
||||
const char *name;
|
||||
const camera_sccb_addr_t sccb_addr;
|
||||
const camera_pid_t pid;
|
||||
const framesize_t max_size;
|
||||
const bool support_jpeg;
|
||||
} camera_sensor_info_t;
|
||||
|
||||
typedef enum {
|
||||
ASPECT_RATIO_4X3,
|
||||
ASPECT_RATIO_3X2,
|
||||
ASPECT_RATIO_16X10,
|
||||
ASPECT_RATIO_5X3,
|
||||
ASPECT_RATIO_16X9,
|
||||
ASPECT_RATIO_21X9,
|
||||
ASPECT_RATIO_5X4,
|
||||
ASPECT_RATIO_1X1,
|
||||
ASPECT_RATIO_9X16
|
||||
} aspect_ratio_t;
|
||||
|
||||
typedef enum {
|
||||
GAINCEILING_2X,
|
||||
GAINCEILING_4X,
|
||||
GAINCEILING_8X,
|
||||
GAINCEILING_16X,
|
||||
GAINCEILING_32X,
|
||||
GAINCEILING_64X,
|
||||
GAINCEILING_128X,
|
||||
} gainceiling_t;
|
||||
|
||||
typedef struct {
|
||||
uint16_t max_width;
|
||||
uint16_t max_height;
|
||||
uint16_t start_x;
|
||||
uint16_t start_y;
|
||||
uint16_t end_x;
|
||||
uint16_t end_y;
|
||||
uint16_t offset_x;
|
||||
uint16_t offset_y;
|
||||
uint16_t total_x;
|
||||
uint16_t total_y;
|
||||
} ratio_settings_t;
|
||||
|
||||
typedef struct {
|
||||
const uint16_t width;
|
||||
const uint16_t height;
|
||||
const aspect_ratio_t aspect_ratio;
|
||||
} resolution_info_t;
|
||||
|
||||
// Resolution table (in sensor.c)
|
||||
extern const resolution_info_t resolution[];
|
||||
// camera sensor table (in sensor.c)
|
||||
extern const camera_sensor_info_t camera_sensor[];
|
||||
|
||||
typedef struct {
|
||||
uint8_t MIDH;
|
||||
uint8_t MIDL;
|
||||
uint16_t PID;
|
||||
uint8_t VER;
|
||||
} sensor_id_t;
|
||||
|
||||
typedef struct {
|
||||
framesize_t framesize;//0 - 10
|
||||
bool scale;
|
||||
bool binning;
|
||||
uint8_t quality;//0 - 63
|
||||
int8_t brightness;//-2 - 2
|
||||
int8_t contrast;//-2 - 2
|
||||
int8_t saturation;//-2 - 2
|
||||
int8_t sharpness;//-2 - 2
|
||||
uint8_t denoise;
|
||||
uint8_t special_effect;//0 - 6
|
||||
uint8_t wb_mode;//0 - 4
|
||||
uint8_t awb;
|
||||
uint8_t awb_gain;
|
||||
uint8_t aec;
|
||||
uint8_t aec2;
|
||||
int8_t ae_level;//-2 - 2
|
||||
uint16_t aec_value;//0 - 1200
|
||||
uint8_t agc;
|
||||
uint8_t agc_gain;//0 - 30
|
||||
uint8_t gainceiling;//0 - 6
|
||||
uint8_t bpc;
|
||||
uint8_t wpc;
|
||||
uint8_t raw_gma;
|
||||
uint8_t lenc;
|
||||
uint8_t hmirror;
|
||||
uint8_t vflip;
|
||||
uint8_t dcw;
|
||||
uint8_t colorbar;
|
||||
} camera_status_t;
|
||||
|
||||
typedef struct _sensor sensor_t;
|
||||
typedef struct _sensor {
|
||||
sensor_id_t id; // Sensor ID.
|
||||
uint8_t slv_addr; // Sensor I2C slave address.
|
||||
pixformat_t pixformat;
|
||||
camera_status_t status;
|
||||
int xclk_freq_hz;
|
||||
|
||||
// Sensor function pointers
|
||||
int (*init_status) (sensor_t *sensor);
|
||||
int (*reset) (sensor_t *sensor);
|
||||
int (*set_pixformat) (sensor_t *sensor, pixformat_t pixformat);
|
||||
int (*set_framesize) (sensor_t *sensor, framesize_t framesize);
|
||||
int (*set_contrast) (sensor_t *sensor, int level);
|
||||
int (*set_brightness) (sensor_t *sensor, int level);
|
||||
int (*set_saturation) (sensor_t *sensor, int level);
|
||||
int (*set_sharpness) (sensor_t *sensor, int level);
|
||||
int (*set_denoise) (sensor_t *sensor, int level);
|
||||
int (*set_gainceiling) (sensor_t *sensor, gainceiling_t gainceiling);
|
||||
int (*set_quality) (sensor_t *sensor, int quality);
|
||||
int (*set_colorbar) (sensor_t *sensor, int enable);
|
||||
int (*set_whitebal) (sensor_t *sensor, int enable);
|
||||
int (*set_gain_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_exposure_ctrl) (sensor_t *sensor, int enable);
|
||||
int (*set_hmirror) (sensor_t *sensor, int enable);
|
||||
int (*set_vflip) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_aec2) (sensor_t *sensor, int enable);
|
||||
int (*set_awb_gain) (sensor_t *sensor, int enable);
|
||||
int (*set_agc_gain) (sensor_t *sensor, int gain);
|
||||
int (*set_aec_value) (sensor_t *sensor, int gain);
|
||||
|
||||
int (*set_special_effect) (sensor_t *sensor, int effect);
|
||||
int (*set_wb_mode) (sensor_t *sensor, int mode);
|
||||
int (*set_ae_level) (sensor_t *sensor, int level);
|
||||
|
||||
int (*set_dcw) (sensor_t *sensor, int enable);
|
||||
int (*set_bpc) (sensor_t *sensor, int enable);
|
||||
int (*set_wpc) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*set_raw_gma) (sensor_t *sensor, int enable);
|
||||
int (*set_lenc) (sensor_t *sensor, int enable);
|
||||
|
||||
int (*get_reg) (sensor_t *sensor, int reg, int mask);
|
||||
int (*set_reg) (sensor_t *sensor, int reg, int mask, int value);
|
||||
int (*set_res_raw) (sensor_t *sensor, int startX, int startY, int endX, int endY, int offsetX, int offsetY, int totalX, int totalY, int outputX, int outputY, bool scale, bool binning);
|
||||
int (*set_pll) (sensor_t *sensor, int bypass, int mul, int sys, int root, int pre, int seld5, int pclken, int pclk);
|
||||
int (*set_xclk) (sensor_t *sensor, int timer, int xclk);
|
||||
} sensor_t;
|
||||
|
||||
camera_sensor_info_t *esp_camera_sensor_get_info(sensor_id_t *id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __SENSOR_H__ */
|
||||
@@ -9,15 +9,13 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "server_cam";
|
||||
|
||||
#define SCRATCH_BUFSIZE2 8192
|
||||
char scratch2[SCRATCH_BUFSIZE2];
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
void PowerResetCamera(){
|
||||
|
||||
ESP_LOGD(TAG, "Resetting camera by power down line");
|
||||
gpio_config_t conf;
|
||||
conf.intr_type = GPIO_INTR_DISABLE;
|
||||
@@ -37,182 +35,223 @@ void PowerResetCamera(){
|
||||
|
||||
esp_err_t handler_lightOn(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOn - Start");
|
||||
ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOn - Start");
|
||||
ESP_LOGD(TAG, "handler_lightOn uri: %s", req->uri);
|
||||
#endif
|
||||
|
||||
Camera.LightOnOff(true);
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
{
|
||||
Camera.LightOnOff(true);
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lighton not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOn - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOn - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_lightOff(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOff - Start");
|
||||
ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
|
||||
#endif
|
||||
Camera.LightOnOff(false);
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOff - Start");
|
||||
ESP_LOGD(TAG, "handler_lightOff uri: %s", req->uri);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOff - Done");
|
||||
#endif
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
{
|
||||
Camera.LightOnOff(false);
|
||||
const char* resp_str = (const char*) req->user_ctx;
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /lightoff not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_lightOff - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_capture(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture - Start");
|
||||
#endif
|
||||
|
||||
int quality;
|
||||
framesize_t res;
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
|
||||
esp_err_t ressult;
|
||||
ressult = Camera.CaptureToHTTP(req);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture - Done");
|
||||
#endif
|
||||
|
||||
return ressult;
|
||||
};
|
||||
|
||||
|
||||
esp_err_t handler_capture_with_ligth(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_ligth - Start");
|
||||
#endif
|
||||
char _query[100];
|
||||
char _delay[10];
|
||||
|
||||
int quality;
|
||||
framesize_t res;
|
||||
int delay = 2500;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
int quality;
|
||||
framesize_t res;
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
|
||||
esp_err_t result;
|
||||
result = Camera.CaptureToHTTP(req);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture - Done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_capture_with_light(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_light - Start");
|
||||
#endif
|
||||
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
{
|
||||
char _query[100];
|
||||
char _delay[10];
|
||||
|
||||
int quality;
|
||||
framesize_t res;
|
||||
int delay = 2500;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
|
||||
Camera.SetQualitySize(quality, res);
|
||||
Camera.LightOnOff(true);
|
||||
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
|
||||
vTaskDelay( xDelay );
|
||||
Camera.SetQualitySize(quality, res);
|
||||
Camera.LightOnOff(true);
|
||||
const TickType_t xDelay = delay / portTICK_PERIOD_MS;
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
esp_err_t ressult;
|
||||
ressult = Camera.CaptureToHTTP(req);
|
||||
esp_err_t result;
|
||||
result = Camera.CaptureToHTTP(req);
|
||||
|
||||
Camera.LightOnOff(false);
|
||||
Camera.LightOnOff(false);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_ligth - Done");
|
||||
#endif
|
||||
|
||||
return ressult;
|
||||
};
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_with_light - Done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /capture_with_flashlight not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_capture_save_to_file(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_save_to_file - Start");
|
||||
#endif
|
||||
|
||||
char _query[100];
|
||||
char _delay[10];
|
||||
int delay = 0;
|
||||
char filename[100];
|
||||
std::string fn = "/sdcard/";
|
||||
|
||||
|
||||
int quality;
|
||||
framesize_t res;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
if (Camera.getCameraInitSuccessful())
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
|
||||
char _query[100];
|
||||
char _delay[10];
|
||||
int delay = 0;
|
||||
char filename[100];
|
||||
std::string fn = "/sdcard/";
|
||||
|
||||
|
||||
int quality;
|
||||
framesize_t res;
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 100) == ESP_OK)
|
||||
{
|
||||
fn.append(filename);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filename: %s", fn.c_str());
|
||||
#endif
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
if (httpd_query_key_value(_query, "filename", filename, 100) == ESP_OK)
|
||||
{
|
||||
fn.append(filename);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Filename: %s", fn.c_str());
|
||||
#endif
|
||||
}
|
||||
else
|
||||
fn.append("noname.jpg");
|
||||
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
fn.append("noname.jpg");
|
||||
|
||||
if (httpd_query_key_value(_query, "delay", _delay, 10) == ESP_OK)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Delay: %s", _delay);
|
||||
#endif
|
||||
delay = atoi(_delay);
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
Camera.SetQualitySize(quality, res);
|
||||
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
}
|
||||
esp_err_t result;
|
||||
result = Camera.CaptureToFile(fn, delay);
|
||||
|
||||
const char* resp_str = (const char*) fn.c_str();
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
else
|
||||
fn.append("noname.jpg");
|
||||
|
||||
Camera.GetCameraParameter(req, quality, res);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Size: %d, Quality: %d", res, quality);
|
||||
#endif
|
||||
Camera.SetQualitySize(quality, res);
|
||||
|
||||
esp_err_t ressult;
|
||||
ressult = Camera.CaptureToFile(fn, delay);
|
||||
|
||||
const char* resp_str = (const char*) fn.c_str();
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_capture_save_to_file - Done");
|
||||
#endif
|
||||
|
||||
return ressult;
|
||||
};
|
||||
|
||||
else
|
||||
{
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Camera not initialized: REST API /save not available!");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void register_server_camera_uri(httpd_handle_t server)
|
||||
@@ -240,7 +279,7 @@ void register_server_camera_uri(httpd_handle_t server)
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
camuri.uri = "/capture_with_flashlight";
|
||||
camuri.handler = handler_capture_with_ligth;
|
||||
camuri.handler = handler_capture_with_light;
|
||||
camuri.user_ctx = NULL;
|
||||
httpd_register_uri_handler(server, &camuri);
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef JOMJOL_CONTROLCAMERA_H
|
||||
#define JOMJOL_CONTROLCAMERA_H
|
||||
|
||||
|
||||
@@ -33,42 +33,29 @@ extern "C" {
|
||||
#include <esp_spiffs.h>
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#include "defines.h"
|
||||
#include "../../include/defines.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "server_tflite.h"
|
||||
|
||||
#include "server_help.h"
|
||||
#include "interface_mqtt.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
#include "server_GPIO.h"
|
||||
|
||||
#include "Helper.h"
|
||||
#include "miniz.h"
|
||||
|
||||
|
||||
static const char *TAG = "OTA FILE";
|
||||
|
||||
/* Max length a file path can have on storage */
|
||||
// #define FILE_PATH_MAX (ESP_VFS_PATH_MAX + CONFIG_SPIFFS_OBJ_NAME_LEN)
|
||||
#define FILE_PATH_MAX (255)
|
||||
|
||||
/* Max size of an individual file. Make sure this
|
||||
* value is same as that set in upload_script.html */
|
||||
#define MAX_FILE_SIZE (8000*1024) // 8 MB
|
||||
#define MAX_FILE_SIZE_STR "8MB"
|
||||
|
||||
|
||||
/* Scratch buffer size */
|
||||
#define SCRATCH_BUFSIZE 4096
|
||||
|
||||
/* Size of partial log file to return */
|
||||
#define LOGFILE_LAST_PART_BYTES SCRATCH_BUFSIZE * 20 /* 80 kBytes */
|
||||
|
||||
struct file_server_data {
|
||||
/* Base path of file storage */
|
||||
char base_path[ESP_VFS_PATH_MAX + 1];
|
||||
|
||||
/* Scratch buffer for temporary storage during file transfer */
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
char scratch[SERVER_FILER_SCRATCH_BUFSIZE];
|
||||
};
|
||||
|
||||
|
||||
@@ -219,22 +206,24 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
ESP_LOGD(TAG, "entrypath: <%s>", entrypath);
|
||||
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", dirpath);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat dir: " + std::string(dirpath) + "!");
|
||||
/* Respond with 404 Not Found */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "Directory does not exist");
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
/* Send HTML file header */
|
||||
httpd_resp_sendstr_chunk(req, "<!DOCTYPE html><html><body>");
|
||||
|
||||
/////////////////////////////////////////////////
|
||||
if (!readonly) {
|
||||
FILE *fd = OpenFileAndWait("/sdcard/html/upload_script.html", "r");
|
||||
FILE *fd = fopen("/sdcard/html/file_server.html", "r");
|
||||
char *chunk = ((struct file_server_data *)req->user_ctx)->scratch;
|
||||
size_t chunksize;
|
||||
do {
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
// ESP_LOGD(TAG, "Chunksize %d", chunksize);
|
||||
if (chunksize > 0){
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -256,11 +245,11 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
|
||||
/* Send file-list table definition and column labels */
|
||||
httpd_resp_sendstr_chunk(req,
|
||||
"<table class=\"fixed\" border=\"1\">"
|
||||
"<table id=\"files_table\">"
|
||||
"<col width=\"800px\" /><col width=\"300px\" /><col width=\"300px\" /><col width=\"100px\" />"
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size (Bytes)</th>");
|
||||
"<thead><tr><th>Name</th><th>Type</th><th>Size</th>");
|
||||
if (!readonly) {
|
||||
httpd_resp_sendstr_chunk(req, "<th>Delete<br>"
|
||||
httpd_resp_sendstr_chunk(req, "<th>"
|
||||
"<form method=\"post\" action=\"");
|
||||
httpd_resp_sendstr_chunk(req, _zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req,
|
||||
@@ -278,11 +267,23 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
strlcpy(entrypath + dirpath_len, entry->d_name, sizeof(entrypath) - dirpath_len);
|
||||
ESP_LOGD(TAG, "Entrypath: %s", entrypath);
|
||||
if (stat(entrypath, &entry_stat) == -1) {
|
||||
ESP_LOGE(TAG, "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, "Found %s : %s (%s bytes)", entrytype, entry->d_name, entrysize);
|
||||
|
||||
if (entry->d_type == DT_DIR) {
|
||||
strcpy(entrysize, "-\0");
|
||||
}
|
||||
else {
|
||||
if (entry_stat.st_size >= 1024) {
|
||||
sprintf(entrysize, "%ld KiB", entry_stat.st_size / 1024); // kBytes
|
||||
}
|
||||
else {
|
||||
sprintf(entrysize, "%ld B", entry_stat.st_size); // Bytes
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Found %s: %s (%s bytes)", entrytype, entry->d_name, entrysize);
|
||||
|
||||
/* Send chunk of HTML file containing table entries with file name and size */
|
||||
httpd_resp_sendstr_chunk(req, "<tr><td><a href=\"");
|
||||
@@ -320,10 +321,10 @@ static esp_err_t http_resp_dir_html(httpd_req_t *req, const char *dirpath, const
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
|
||||
*/
|
||||
|
||||
static esp_err_t logfileact_get_full_handler(httpd_req_t *req) {
|
||||
return send_logfile(req, true);
|
||||
@@ -346,31 +347,26 @@ static esp_err_t datafileact_get_last_part_handler(httpd_req_t *req) {
|
||||
static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "data_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
ESP_LOGD(TAG, "uri: %s", req->uri);
|
||||
|
||||
const char* filename = "";
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileNameData();
|
||||
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, currentfilename.c_str(), currentfilename.c_str());
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
fd = fopen(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
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");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(currentfilename) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
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);
|
||||
// ESP_LOGI(TAG, "Sending file: %s (%ld bytes)...", &filename, file_stat.st_size);
|
||||
set_content_type_from_file(req, currentfilename.c_str());
|
||||
|
||||
if (!send_full_file) { // Send only last part of file
|
||||
ESP_LOGD(TAG, "Sending last %d bytes of the actual datafile!", LOGFILE_LAST_PART_BYTES);
|
||||
@@ -403,7 +399,7 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -432,7 +428,6 @@ static esp_err_t send_datafile(httpd_req_t *req, bool send_full_file)
|
||||
static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "log_get_last_part_handler");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
//struct stat file_stat;
|
||||
ESP_LOGI(TAG, "uri: %s", req->uri);
|
||||
@@ -441,20 +436,22 @@ static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
|
||||
std::string currentfilename = LogFile.GetCurrentFileName();
|
||||
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, filepath);
|
||||
ESP_LOGD(TAG, "uri: %s, filename: %s, filepath: %s", req->uri, filename, currentfilename.c_str());
|
||||
|
||||
// Since the log file is still could open for writing, we need to close it first
|
||||
LogFile.CloseLogFileAppendHandle();
|
||||
|
||||
fd = OpenFileAndWait(currentfilename.c_str(), "r");
|
||||
fd = fopen(currentfilename.c_str(), "r");
|
||||
if (!fd) {
|
||||
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");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(currentfilename.c_str()) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
// ESP_LOGI(TAG, "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
|
||||
@@ -488,7 +485,7 @@ static esp_err_t send_logfile(httpd_req_t *req, bool send_full_file)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -534,8 +531,8 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
|
||||
if (!filename) {
|
||||
ESP_LOGE(TAG, "Filename is too long");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
/* Respond with 414 Error */
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -566,23 +563,23 @@ 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, "Failed to stat file : %s", filepath);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to stat file: " + std::string(filepath) + "!");
|
||||
/* Respond with 404 Not Found */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, "File does not exist");
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fd = OpenFileAndWait(filepath, "r");
|
||||
fd = fopen(filepath, "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");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to read file: " + std::string(filepath) +"!");
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
ESP_LOGD(TAG, "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 */
|
||||
@@ -590,7 +587,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_FILER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
@@ -599,7 +596,7 @@ static esp_err_t download_get_handler(httpd_req_t *req)
|
||||
/* 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");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to send file!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -623,25 +620,28 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
FILE *fd = NULL;
|
||||
struct stat file_stat;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
/* Skip leading "/upload" from URI to get filename */
|
||||
/* Note sizeof() counts NULL termination hence the -1 */
|
||||
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
req->uri + sizeof("/upload") - 1, sizeof(filepath));
|
||||
if (!filename) {
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
/* Respond with 413 Error */
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Filename cannot have a trailing '/' */
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
ESP_LOGE(TAG, "Invalid filename : %s", filename);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
|
||||
ESP_LOGE(TAG, "Invalid filename: %s", filename);
|
||||
/* Respond with 400 Bad Request */
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid filename");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (stat(filepath, &file_stat) == 0) {
|
||||
ESP_LOGE(TAG, "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;
|
||||
@@ -649,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, "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 "
|
||||
@@ -659,15 +659,15 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fd = OpenFileAndWait(filepath, "w");
|
||||
fd = fopen(filepath, "w");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to create file : %s", filepath);
|
||||
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, "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;
|
||||
@@ -679,9 +679,9 @@ static esp_err_t upload_post_handler(httpd_req_t *req)
|
||||
|
||||
while (remaining > 0) {
|
||||
|
||||
ESP_LOGI(TAG, "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_req_recv(req, buf, MIN(remaining, SERVER_FILER_SCRATCH_BUFSIZE))) <= 0) {
|
||||
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
/* Retry if timeout occurred */
|
||||
continue;
|
||||
@@ -772,6 +772,8 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
std::string directory;
|
||||
std::string zw;
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 200) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
@@ -790,8 +792,8 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
const char *filename = get_path_from_uri(filepath, ((struct file_server_data *)req->user_ctx)->base_path,
|
||||
req->uri + sizeof("/delete") - 1, sizeof(filepath));
|
||||
if (!filename) {
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
/* Respond with 414 Error */
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
zw = std::string(filename);
|
||||
@@ -824,19 +826,26 @@ static esp_err_t delete_post_handler(httpd_req_t *req)
|
||||
|
||||
/* Filename cannot have a trailing '/' */
|
||||
if (filename[strlen(filename) - 1] == '/') {
|
||||
ESP_LOGE(TAG, "Invalid filename : %s", filename);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Invalid filename");
|
||||
ESP_LOGE(TAG, "Invalid filename: %s", filename);
|
||||
/* Respond with 400 Bad Request */
|
||||
httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid filename");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (strcmp(filename, "wlan.ini") == 0) {
|
||||
ESP_LOGE(TAG, "Trying to delete protected file : %s", filename);
|
||||
httpd_resp_send_err(req, HTTPD_403_FORBIDDEN, "Not allowed to delete wlan.ini");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (stat(filepath, &file_stat) == -1) {
|
||||
ESP_LOGE(TAG, "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, "Deleting file : %s", filename);
|
||||
ESP_LOGI(TAG, "Deleting file: %s", filename);
|
||||
/* Delete file */
|
||||
unlink(filepath);
|
||||
|
||||
@@ -878,7 +887,7 @@ void delete_all_in_directory(std::string _directory)
|
||||
std::string filename;
|
||||
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", _directory.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir: %s", _directory.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -887,7 +896,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, "Deleting file : %s", filename.c_str());
|
||||
ESP_LOGI(TAG, "Deleting file: %s", filename.c_str());
|
||||
/* Delete file */
|
||||
unlink(filename.c_str());
|
||||
}
|
||||
@@ -896,7 +905,7 @@ void delete_all_in_directory(std::string _directory)
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main)
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main, bool _initial_setup)
|
||||
{
|
||||
int i, sort_iter;
|
||||
mz_bool status;
|
||||
@@ -906,13 +915,9 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
char archive_filename[64];
|
||||
std::string zw, ret = "";
|
||||
std::string directory = "";
|
||||
// static const char* s_Test_archive_filename = "testhtml.zip";
|
||||
|
||||
ESP_LOGD(TAG, "miniz.c version: %s", MZ_VERSION);
|
||||
ESP_LOGD(TAG, "Zipfile: %s", _in_zip_file.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir ZIP: %s", _target_zip.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir BIN: %s", _target_bin.c_str());
|
||||
// ESP_LOGD(TAG, "Target Dir main: %s", _main.c_str());
|
||||
|
||||
// Now try to open the archive.
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
@@ -925,7 +930,9 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
|
||||
// Get and print information about each file in the archive.
|
||||
int numberoffiles = (int)mz_zip_reader_get_num_files(&zip_archive);
|
||||
for (sort_iter = 0; sort_iter < 2; sort_iter++)
|
||||
ESP_LOGI(TAG, "Numbers of files to be extracted: %d", numberoffiles);
|
||||
|
||||
sort_iter = 0;
|
||||
{
|
||||
memset(&zip_archive, 0, sizeof(zip_archive));
|
||||
status = mz_zip_reader_init_file(&zip_archive, _in_zip_file.c_str(), sort_iter ? MZ_ZIP_FLAG_DO_NOT_SORT_CENTRAL_DIRECTORY : 0);
|
||||
@@ -963,6 +970,16 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
else
|
||||
{
|
||||
std::string _dir = getDirectory(zw);
|
||||
if ((_dir == "config-initial") && !_initial_setup)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
_dir = "config";
|
||||
std::string _s1 = "config-initial";
|
||||
FindReplace(zw, _s1, _dir);
|
||||
}
|
||||
|
||||
if (_dir.length() > 0)
|
||||
{
|
||||
@@ -981,7 +998,7 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
|
||||
// extrahieren in zwischendatei
|
||||
DeleteFile(filename_zw);
|
||||
FILE* fpTargetFile = OpenFileAndWait(filename_zw.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(filename_zw.c_str(), "wb");
|
||||
uint writtenbytes = fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
@@ -1003,9 +1020,6 @@ std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::st
|
||||
isokay = isokay && RenameFile(filename_zw, zw);
|
||||
if (!isokay)
|
||||
ESP_LOGE(TAG, "ERROR in Rename \"%s\" to \"%s\"", filename_zw.c_str(), zw.c_str());
|
||||
// isokay = isokay && DeleteFile(filename_zw);
|
||||
// if (!isokay)
|
||||
// ESP_LOGE(TAG, "ERROR in Delete \"%s\"", filename_zw.c_str());
|
||||
|
||||
if (isokay)
|
||||
ESP_LOGI(TAG, "Successfully extracted file \"%s\", size %u", archive_filename, (uint)uncomp_size);
|
||||
@@ -1080,7 +1094,7 @@ void unzip(std::string _in_zip_file, std::string _target_directory){
|
||||
zw = std::string(archive_filename);
|
||||
zw = _target_directory + zw;
|
||||
ESP_LOGD(TAG, "Filename to extract: %s", zw.c_str());
|
||||
FILE* fpTargetFile = OpenFileAndWait(zw.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(zw.c_str(), "wb");
|
||||
fwrite(p, 1, (uint)uncomp_size, fpTargetFile);
|
||||
fclose(fpTargetFile);
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERFILE_H
|
||||
#define SERVERFILE_H
|
||||
|
||||
#include <esp_http_server.h>
|
||||
#include <string>
|
||||
|
||||
void register_server_file_uri(httpd_handle_t server, const char *base_path);
|
||||
|
||||
void unzip(std::string _in_zip_file, std::string _target_directory);
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/");
|
||||
std::string unzip_new(std::string _in_zip_file, std::string _target_zip, std::string _target_bin, std::string _main = "/sdcard/", bool _initial_setup = false);
|
||||
|
||||
|
||||
void delete_all_in_directory(std::string _directory);
|
||||
@@ -13,3 +18,4 @@ esp_err_t get_tflite_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_data_file_handler(httpd_req_t *req);
|
||||
esp_err_t get_numbers_file_handler(httpd_req_t *req);
|
||||
|
||||
#endif //SERVERFILE_H
|
||||
@@ -21,29 +21,49 @@ extern "C" {
|
||||
|
||||
#include "esp_http_server.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
static const char *TAG = "SERVER HELP";
|
||||
|
||||
#define SCRATCH_BUFSIZE 8192
|
||||
char scratch[SCRATCH_BUFSIZE];
|
||||
char scratch[SERVER_HELPER_SCRATCH_BUFSIZE];
|
||||
|
||||
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
bool endsWith(std::string const &str, std::string const &suffix) {
|
||||
if (str.length() < suffix.length()) {
|
||||
return false;
|
||||
}
|
||||
return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
{
|
||||
FILE *fd = OpenFileAndWait(filename.c_str(), "r");
|
||||
FILE *fd = fopen(filename.c_str(), "r");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to read existing file : %s", filename.c_str());
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to read existing file");
|
||||
ESP_LOGE(TAG, "Failed to read file: %s", filename.c_str());
|
||||
/* Respond with 404 Error */
|
||||
httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, get404());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGD(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", "*");
|
||||
|
||||
/* For all files with the following file extention tell
|
||||
the webbrowser to cache them for 24h */
|
||||
if (endsWith(filename, ".html") ||
|
||||
endsWith(filename, ".htm") ||
|
||||
endsWith(filename, ".css") ||
|
||||
endsWith(filename, ".js") ||
|
||||
endsWith(filename, ".map") ||
|
||||
endsWith(filename, ".jpg") ||
|
||||
endsWith(filename, ".jpeg") ||
|
||||
endsWith(filename, ".ico") ||
|
||||
endsWith(filename, ".png")) {
|
||||
httpd_resp_set_hdr(req, "Cache-Control", "max-age=86400");
|
||||
}
|
||||
|
||||
set_content_type_from_file(req, filename.c_str());
|
||||
|
||||
/* Retrieve the pointer to scratch buffer for temporary storage */
|
||||
@@ -51,7 +71,7 @@ esp_err_t send_file(httpd_req_t *req, std::string filename)
|
||||
size_t chunksize;
|
||||
do {
|
||||
/* Read file in chunks into the scratch buffer */
|
||||
chunksize = fread(chunk, 1, SCRATCH_BUFSIZE, fd);
|
||||
chunksize = fread(chunk, 1, SERVER_HELPER_SCRATCH_BUFSIZE, fd);
|
||||
|
||||
/* Send the buffer contents as HTTP response chunk */
|
||||
if (httpd_resp_send_chunk(req, chunk, chunksize) != ESP_OK) {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERHELP_H
|
||||
#define SERVERHELP_H
|
||||
|
||||
#include <string>
|
||||
//#include <sys/param.h>
|
||||
#include "esp_http_server.h"
|
||||
@@ -7,4 +12,6 @@ const char* get_path_from_uri(char *dest, const char *base_path, const char *uri
|
||||
|
||||
esp_err_t send_file(httpd_req_t *req, std::string filename);
|
||||
|
||||
esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);
|
||||
esp_err_t set_content_type_from_file(httpd_req_t *req, const char *filename);
|
||||
|
||||
#endif //SERVERHELP_H
|
||||
@@ -29,30 +29,39 @@
|
||||
#include "server_tflite.h"
|
||||
#include "server_file.h"
|
||||
#include "server_GPIO.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
#include "ClassControllCamera.h"
|
||||
#include "connect_wlan.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
#define BUFFSIZE 1024
|
||||
#define HASH_LEN 32 /* SHA-256 digest length */
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
/*an ota data write buffer ready to write to the flash*/
|
||||
static char ota_write_data[BUFFSIZE + 1] = { 0 };
|
||||
static char ota_write_data[SERVER_OTA_SCRATCH_BUFSIZE + 1] = { 0 };
|
||||
|
||||
|
||||
#define OTA_URL_SIZE 256
|
||||
static const char *TAG = "OTA";
|
||||
|
||||
esp_err_t handler_reboot(httpd_req_t *req);
|
||||
static bool ota_update_task(std::string fn);
|
||||
|
||||
std::string _file_name_update;
|
||||
bool initial_setup = false;
|
||||
|
||||
|
||||
static void infinite_loop(void)
|
||||
{
|
||||
int i = 0;
|
||||
ESP_LOGI(TAG, "When a new firmware is available on the server, press the reset button to download it");
|
||||
while(1) {
|
||||
ESP_LOGI(TAG, "Waiting for a new firmware... %d", ++i);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void task_do_Update_ZIP(void *pvParameter)
|
||||
@@ -69,7 +78,7 @@ void task_do_Update_ZIP(void *pvParameter)
|
||||
out = "/sdcard/html";
|
||||
outbin = "/sdcard/firmware";
|
||||
|
||||
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/");
|
||||
retfirmware = unzip_new(_file_name_update, out+"/", outbin+"/", "/sdcard/", initial_setup);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Files unzipped.");
|
||||
|
||||
if (retfirmware.length() > 0)
|
||||
@@ -77,8 +86,15 @@ void task_do_Update_ZIP(void *pvParameter)
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Found firmware.bin");
|
||||
ota_update_task(retfirmware);
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doReboot();
|
||||
doRebootOTA();
|
||||
} else if (filetype == "BIN")
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Do firmware update - file: " + _file_name_update);
|
||||
ota_update_task(_file_name_update);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doRebootOTA();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -99,34 +115,27 @@ void CheckUpdate()
|
||||
char zw[1024] = "";
|
||||
fgets(zw, 1024, pfile);
|
||||
_file_name_update = std::string(zw);
|
||||
if (fgets(zw, 1024, pfile))
|
||||
{
|
||||
std::string _szw = std::string(zw);
|
||||
if (_szw == "init")
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Inital Setup triggered.");
|
||||
initial_setup = true; }
|
||||
}
|
||||
|
||||
fclose(pfile);
|
||||
DeleteFile("/sdcard/update.txt"); // Prevent Boot Loop!!!
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update during boot triggered - Update File: " + _file_name_update);
|
||||
|
||||
|
||||
BaseType_t xReturned;
|
||||
int _i = configMINIMAL_STACK_SIZE;
|
||||
xReturned = xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
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(TAG, "When a new firmware is available on the server, press the reset button to download it");
|
||||
while(1) {
|
||||
ESP_LOGI(TAG, "Waiting for a new firmware... %d", ++i);
|
||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
||||
xTaskCreate(&task_do_Update_ZIP, "task_do_Update_ZIP", configMINIMAL_STACK_SIZE * 35, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
while(1) { // wait until reboot within task_do_Update_ZIP
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static bool ota_update_task(std::string fn)
|
||||
{
|
||||
esp_err_t err;
|
||||
@@ -160,13 +169,13 @@ static bool ota_update_task(std::string fn)
|
||||
|
||||
int data_read;
|
||||
|
||||
FILE* f = OpenFileAndWait(fn.c_str(), "rb"); // vorher nur "r"
|
||||
FILE* f = fopen(fn.c_str(), "rb"); // previously only "r
|
||||
|
||||
if (f == NULL) { // File does not exist
|
||||
return false;
|
||||
}
|
||||
|
||||
data_read = fread(ota_write_data, 1, BUFFSIZE, f);
|
||||
data_read = fread(ota_write_data, 1, SERVER_OTA_SCRATCH_BUFSIZE, f);
|
||||
|
||||
while (data_read > 0) {
|
||||
if (data_read < 0) {
|
||||
@@ -236,7 +245,7 @@ static bool ota_update_task(std::string fn)
|
||||
break;
|
||||
}
|
||||
}
|
||||
data_read = fread(ota_write_data, 1, BUFFSIZE, f);
|
||||
data_read = fread(ota_write_data, 1, SERVER_OTA_SCRATCH_BUFSIZE, f);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
@@ -279,6 +288,7 @@ static bool diagnostic(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CheckOTAUpdate(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Start CheckOTAUpdateCheck...");
|
||||
@@ -351,7 +361,6 @@ void CheckOTAUpdate(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -388,7 +397,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "Delete Default File: %s", fn.c_str());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
if (_task.compare("emptyfirmwaredir") == 0)
|
||||
{
|
||||
@@ -433,7 +442,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
}
|
||||
|
||||
|
||||
if (filetype == "ZIP")
|
||||
if ((filetype == "ZIP") || (filetype == "BIN"))
|
||||
{
|
||||
FILE *pfile;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Update for reboot.");
|
||||
@@ -447,32 +456,9 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "Send reboot");
|
||||
return ESP_OK;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
std::string in, out, outbin, zw, retfirmware;
|
||||
|
||||
out = "/sdcard/html";
|
||||
outbin = "/sdcard/firmware";
|
||||
|
||||
retfirmware = unzip_new(fn, out+"/", outbin+"/");
|
||||
|
||||
if (retfirmware.length() > 0)
|
||||
{
|
||||
filetype = "BIN";
|
||||
fn = retfirmware;
|
||||
}
|
||||
else
|
||||
{
|
||||
zw = "Web Interface Update Successfull!\nNo reboot necessary.\n";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
if (filetype == "BIN")
|
||||
{
|
||||
const char* resp_str;
|
||||
@@ -497,7 +483,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
std::string zw = "Update failed - no valid file specified (zip, bin, tfl, tlite)!";
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
@@ -530,7 +516,7 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
int _result = stat(fn.c_str(), &file_stat);
|
||||
ESP_LOGD(TAG, "Ergebnis %d\n", _result);
|
||||
if (_result == 0) {
|
||||
ESP_LOGD(TAG, "Deleting file : %s", fn.c_str());
|
||||
ESP_LOGD(TAG, "Deleting file: %s", fn.c_str());
|
||||
/* Delete file */
|
||||
unlink(fn.c_str());
|
||||
}
|
||||
@@ -568,65 +554,118 @@ esp_err_t handler_ota_update(httpd_req_t *req)
|
||||
}
|
||||
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Done");
|
||||
#endif
|
||||
*/
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Done");
|
||||
#endif
|
||||
|
||||
void hard_restart() {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void hard_restart()
|
||||
{
|
||||
esp_task_wdt_init(1,true);
|
||||
esp_task_wdt_add(NULL);
|
||||
while(true);
|
||||
}
|
||||
|
||||
void task_reboot(void *pvParameter)
|
||||
|
||||
void task_reboot(void *KillAutoFlow)
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
// write a reboot, to identify a reboot by purpouse
|
||||
FILE* pfile = fopen("/sdcard/reboot.txt", "w");
|
||||
std::string _s_zw= "reboot";
|
||||
fwrite(_s_zw.c_str(), strlen(_s_zw.c_str()), 1, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
|
||||
if ((bool)KillAutoFlow) {
|
||||
KillTFliteTasks(); // Kill autoflow task if executed in extra task, if not don't kill parent task
|
||||
}
|
||||
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
/* Stop service tasks */
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTdestroy_client(true);
|
||||
#endif //ENABLE_MQTT
|
||||
gpio_handler_destroy();
|
||||
esp_camera_deinit();
|
||||
WIFIDestroy();
|
||||
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
hard_restart(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated)
|
||||
|
||||
ESP_LOGE(TAG, "Reboot failed!");
|
||||
vTaskDelete(NULL); //Delete this task if it comes to this point
|
||||
}
|
||||
|
||||
void doReboot(){
|
||||
|
||||
void doReboot()
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reboot triggered by Software (5s).");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
|
||||
xTaskCreate(&task_reboot, "reboot", configMINIMAL_STACK_SIZE * 64, NULL, 10, NULL);
|
||||
// KillTFliteTasks(); // kills itself
|
||||
gpio_handler_destroy();
|
||||
|
||||
BaseType_t xReturned = xTaskCreate(&task_reboot, "task_reboot", configMINIMAL_STACK_SIZE * 3, (void*) true, 10, NULL);
|
||||
if( xReturned != pdPASS )
|
||||
{
|
||||
ESP_LOGE(TAG, "task_reboot not created -> force reboot without killing flow");
|
||||
task_reboot((void*) false);
|
||||
}
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS); // Prevent serving web client fetch response until system is shuting down
|
||||
}
|
||||
|
||||
|
||||
void doRebootOTA()
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Reboot in 5sec");
|
||||
|
||||
esp_camera_deinit();
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
esp_restart(); // Reset type: CPU reset (Reset both CPUs)
|
||||
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
hard_restart(); // Reset type: System reset (Triggered by watchdog), if esp_restart stalls (WDT needs to be activated)
|
||||
}
|
||||
|
||||
|
||||
esp_err_t handler_reboot(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "handler_reboot");
|
||||
ESP_LOGI(TAG, "!!! System will restart within 5 sec!!!");
|
||||
const char* resp_str = "<body style='font-family: arial'> <h3 id=t></h3></body><script>var h='Rebooting!<br>The page will automatically reload in around 25..60s<br>(in case of a firmware update it can take up to 180s).<br>'; document.getElementById('t').innerHTML=h; setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h; fetch(window.location.hostname,{mode: 'no-cors'}).then(r=>{parent.location.href=('/index.html');})}, 1000);</script>";
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
|
||||
std::string response =
|
||||
"<html><head><script>"
|
||||
"function m(h) {"
|
||||
"document.getElementById('t').innerHTML=h;"
|
||||
"setInterval(function (){h +='.'; document.getElementById('t').innerHTML=h;"
|
||||
"fetch('reboot_page.html',{mode: 'no-cors'}).then(r=>{parent.location.href=('index.html');})}, 1000);"
|
||||
"}</script></head></html><body style='font-family: arial'><h3 id=t></h3>"
|
||||
"<script>m('Rebooting!<br>The page will automatically reload in around 25..60s.<br><br>');</script>"
|
||||
"</body></html>";
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, response.c_str(), strlen(response.c_str()));
|
||||
|
||||
doReboot();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_reboot - Done");
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server)
|
||||
{
|
||||
ESP_LOGI(TAG, "Registering URI handlers");
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVEROTA_H
|
||||
#define SERVEROTA_H
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
#include <esp_http_server.h>
|
||||
@@ -8,6 +13,8 @@
|
||||
void register_server_ota_sdcard_uri(httpd_handle_t server);
|
||||
void CheckOTAUpdate();
|
||||
void doReboot();
|
||||
void doRebootOTA();
|
||||
void hard_restart();
|
||||
void CheckUpdate();
|
||||
static bool ota_update_task(std::string fn);
|
||||
|
||||
#endif //SERVEROTA_H
|
||||
@@ -4,8 +4,9 @@
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "FLOW CLASS";
|
||||
static const char *TAG = "CLASS";
|
||||
|
||||
|
||||
void ClassFlow::SetInitialParameter(void)
|
||||
@@ -105,7 +106,7 @@ bool ClassFlow::getNextLine(FILE* pfile, string *rt)
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
*rt = zw;
|
||||
*rt = trim(*rt);
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '[')) // Kommentarzeilen (; oder #) und Leerzeilen überspringen, es sei denn es ist ein neuer auskommentierter Paragraph
|
||||
while ((zw[0] == ';' || zw[0] == '#' || (rt->size() == 0)) && !(zw[1] == '['))
|
||||
{
|
||||
*rt = "";
|
||||
if (!fgets(zw, 1024, pfile))
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOW_H
|
||||
#define CLASSFLOW_H
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -9,10 +12,6 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define LOGFILE_TIME_FORMAT "%Y%m%d-%H%M%S"
|
||||
#define LOGFILE_TIME_FORMAT_DATE_EXTR substr(0, 8)
|
||||
#define LOGFILE_TIME_FORMAT_HOUR_EXTR substr(9, 2)
|
||||
|
||||
struct HTMLInfo
|
||||
{
|
||||
float val;
|
||||
@@ -52,3 +51,4 @@ public:
|
||||
|
||||
};
|
||||
|
||||
#endif //CLASSFLOW_H
|
||||
@@ -1,17 +1,17 @@
|
||||
#include "ClassFlowAlignment.h"
|
||||
#include "ClassFlowMakeImage.h"
|
||||
#include "ClassFlow.h"
|
||||
#include "server_tflite.h"
|
||||
|
||||
#include "CRotateImage.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
static const char *TAG = "FLOW ALIGN";
|
||||
|
||||
bool AlignmentExtendedDebugging = true;
|
||||
static const char *TAG = "ALIGN";
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
@@ -30,11 +30,15 @@ void ClassFlowAlignment::SetInitialParameter(void)
|
||||
AlignAndCutImage = NULL;
|
||||
ImageBasis = NULL;
|
||||
ImageTMP = NULL;
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
AlgROI = (ImageData*)heap_caps_malloc(sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
#endif
|
||||
previousElement = NULL;
|
||||
disabled = false;
|
||||
SAD_criteria = 0.05;
|
||||
}
|
||||
|
||||
|
||||
ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
{
|
||||
SetInitialParameter();
|
||||
@@ -48,9 +52,9 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
}
|
||||
}
|
||||
|
||||
if (!ImageBasis) // die Funktion Bilder aufnehmen existiert nicht --> muss erst erzeugt werden NUR ZU TESTZWECKEN
|
||||
if (!ImageBasis) // the function take pictures does not exist --> must be created first ONLY FOR TEST PURPOSES
|
||||
{
|
||||
if (AlignmentExtendedDebugging) ESP_LOGD(TAG, "CImageBasis had to be created");
|
||||
ESP_LOGD(TAG, "CImageBasis had to be created");
|
||||
ImageBasis = new CImageBasis(namerawimage);
|
||||
}
|
||||
}
|
||||
@@ -58,7 +62,7 @@ ClassFlowAlignment::ClassFlowAlignment(std::vector<ClassFlow*>* lfc)
|
||||
|
||||
bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
int suchex = 40;
|
||||
int suchey = 40;
|
||||
int alg_algo = 0;
|
||||
@@ -70,61 +74,61 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (aktparamgraph.compare("[Alignment]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[Alignment]") != 0) //Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "FLIPIMAGESIZE") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "FLIPIMAGESIZE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
initialflip = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "INITIALMIRROR") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "INITIALMIRROR") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
initialmirror = true;
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "INITALROTATE") || (toUpper(zerlegt[0]) == "INITIALROTATE")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "INITALROTATE") || (toUpper(splitted[0]) == "INITIALROTATE")) && (splitted.size() > 1))
|
||||
{
|
||||
this->initalrotate = std::stod(zerlegt[1]);
|
||||
this->initalrotate = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SEARCHFIELDX") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SEARCHFIELDX") && (splitted.size() > 1))
|
||||
{
|
||||
suchex = std::stod(zerlegt[1]);
|
||||
suchex = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SEARCHFIELDY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SEARCHFIELDY") && (splitted.size() > 1))
|
||||
{
|
||||
suchey = std::stod(zerlegt[1]);
|
||||
suchey = std::stod(splitted[1]);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "ANTIALIASING") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "ANTIALIASING") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
use_antialiasing = true;
|
||||
}
|
||||
if ((zerlegt.size() == 3) && (anz_ref < 2))
|
||||
if ((splitted.size() == 3) && (anz_ref < 2))
|
||||
{
|
||||
References[anz_ref].image_file = FormatFileName("/sdcard" + zerlegt[0]);
|
||||
References[anz_ref].target_x = std::stod(zerlegt[1]);
|
||||
References[anz_ref].target_y = std::stod(zerlegt[2]);
|
||||
References[anz_ref].image_file = FormatFileName("/sdcard" + splitted[0]);
|
||||
References[anz_ref].target_x = std::stod(splitted[1]);
|
||||
References[anz_ref].target_y = std::stod(splitted[2]);
|
||||
anz_ref++;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "ALIGNMENTALGO") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "ALIGNMENTALGO") && (splitted.size() > 1))
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus gewählt: " + zerlegt[1];
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
if (toUpper(zerlegt[1]) == "HIGHACCURACY")
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignment mode selected: " + splitted[1];
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
if (toUpper(splitted[1]) == "HIGHACCURACY")
|
||||
alg_algo = 1;
|
||||
if (toUpper(zerlegt[1]) == "FAST")
|
||||
if (toUpper(splitted[1]) == "FAST")
|
||||
alg_algo = 2;
|
||||
}
|
||||
}
|
||||
@@ -135,10 +139,10 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
References[i].search_y = suchey;
|
||||
References[i].fastalg_SAD_criteria = SAD_criteria;
|
||||
References[i].alignment_algo = alg_algo;
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignmentmodus geschrieben: " + std::to_string(alg_algo);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw2 = "Alignment mode written: " + std::to_string(alg_algo);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw2);
|
||||
#endif
|
||||
}
|
||||
|
||||
LoadReferenceAlignmentValues();
|
||||
@@ -147,6 +151,7 @@ bool ClassFlowAlignment::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowAlignment::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result;
|
||||
@@ -160,12 +165,42 @@ string ClassFlowAlignment::getHTMLSingleStep(string host)
|
||||
|
||||
bool ClassFlowAlignment::doFlow(string time)
|
||||
{
|
||||
if (!ImageTMP)
|
||||
ImageTMP = new CImageBasis(ImageBasis, 5);
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
if (!AlgROI) // AlgROI needs to be allocated before ImageTMP to avoid heap fragmentation
|
||||
{
|
||||
AlgROI = (ImageData*)heap_caps_realloc(AlgROI, sizeof(ImageData), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
if (!AlgROI)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlgROI");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
}
|
||||
}
|
||||
|
||||
if (AlignAndCutImage)
|
||||
delete AlignAndCutImage;
|
||||
AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);
|
||||
if (AlgROI)
|
||||
{
|
||||
ImageBasis->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!ImageTMP)
|
||||
{
|
||||
ImageTMP = new CImageBasis(ImageBasis);
|
||||
if (!ImageTMP)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate ImageTMP -> Exec this round aborted!");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
delete AlignAndCutImage;
|
||||
AlignAndCutImage = new CAlignAndCutImage(ImageBasis, ImageTMP);
|
||||
if (!AlignAndCutImage)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate AlignAndCutImage -> Exec this round aborted!");
|
||||
LogFile.WriteHeapInfo("ClassFlowAlignment-doFlow");
|
||||
return false;
|
||||
}
|
||||
|
||||
CRotateImage rt(AlignAndCutImage, ImageTMP, initialflip);
|
||||
if (initialflip)
|
||||
@@ -175,10 +210,13 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
ImageBasis->width = _zw;
|
||||
}
|
||||
|
||||
if (initialmirror){
|
||||
if (initialmirror)
|
||||
{
|
||||
ESP_LOGD(TAG, "do mirror");
|
||||
rt.Mirror();
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
|
||||
if (SaveAllFiles)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/mirror.jpg"));
|
||||
}
|
||||
|
||||
if ((initalrotate != 0) || initialflip)
|
||||
@@ -187,7 +225,9 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
rt.RotateAntiAliasing(initalrotate);
|
||||
else
|
||||
rt.Rotate(initalrotate);
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
|
||||
|
||||
if (SaveAllFiles)
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/rot.jpg"));
|
||||
}
|
||||
|
||||
if (!AlignAndCutImage->Align(&References[0], &References[1]))
|
||||
@@ -195,8 +235,15 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
SaveReferenceAlignmentValues();
|
||||
}
|
||||
|
||||
if (SaveAllFiles) AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
if (AlgROI) {
|
||||
DrawRef(ImageTMP);
|
||||
tfliteflow.DigitalDrawROI(ImageTMP);
|
||||
tfliteflow.AnalogDrawROI(ImageTMP);
|
||||
ImageTMP->writeToMemoryAsJPG((ImageData*)AlgROI, 90);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SaveAllFiles)
|
||||
{
|
||||
if (initialflip)
|
||||
@@ -205,15 +252,14 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
ImageTMP->width = ImageTMP->height;
|
||||
ImageTMP->height = _zw;
|
||||
}
|
||||
DrawRef(ImageTMP);
|
||||
|
||||
AlignAndCutImage->SaveToFile(FormatFileName("/sdcard/img_tmp/alg.jpg"));
|
||||
ImageTMP->SaveToFile(FormatFileName("/sdcard/img_tmp/alg_roi.jpg"));
|
||||
}
|
||||
|
||||
if (ImageTMP) // nuss gelöscht werden, um Speicherplatz für das Laden von tflite zu haben
|
||||
{
|
||||
delete ImageTMP;
|
||||
ImageTMP = NULL;
|
||||
}
|
||||
// must be deleted to have memory space for loading tflite
|
||||
delete ImageTMP;
|
||||
ImageTMP = NULL;
|
||||
|
||||
LoadReferenceAlignmentValues();
|
||||
|
||||
@@ -221,7 +267,6 @@ bool ClassFlowAlignment::doFlow(string time)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowAlignment::SaveReferenceAlignmentValues()
|
||||
{
|
||||
FILE* pFile;
|
||||
@@ -261,92 +306,74 @@ void ClassFlowAlignment::SaveReferenceAlignmentValues()
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool ClassFlowAlignment::LoadReferenceAlignmentValues(void)
|
||||
{
|
||||
FILE* pFile;
|
||||
char zw[1024];
|
||||
string zwvalue;
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues01");
|
||||
|
||||
pFile = fopen(FileStoreRefAlignment.c_str(), "r");
|
||||
if (pFile == NULL)
|
||||
return false;
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues01");
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
ESP_LOGD(TAG, "%s", zw);
|
||||
|
||||
// zwvalue = "LoadReferenceAlignmentValues Time: " + std::string(zw);
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zwvalue);
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues02");
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
zerlegt = ZerlegeZeile(std::string(zw), " \t");
|
||||
if (zerlegt.size() < 6)
|
||||
splitted = ZerlegeZeile(std::string(zw), " \t");
|
||||
if (splitted.size() < 6)
|
||||
{
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "Exit 01");
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues03");
|
||||
|
||||
References[0].fastalg_x = stoi(zerlegt[0]);
|
||||
References[0].fastalg_y = stoi(zerlegt[1]);
|
||||
References[0].fastalg_SAD = stof(zerlegt[2]);
|
||||
References[0].fastalg_min = stoi(zerlegt[3]);
|
||||
References[0].fastalg_max = stoi(zerlegt[4]);
|
||||
References[0].fastalg_avg = stof(zerlegt[5]);
|
||||
References[0].fastalg_x = stoi(splitted[0]);
|
||||
References[0].fastalg_y = stoi(splitted[1]);
|
||||
References[0].fastalg_SAD = stof(splitted[2]);
|
||||
References[0].fastalg_min = stoi(splitted[3]);
|
||||
References[0].fastalg_max = stoi(splitted[4]);
|
||||
References[0].fastalg_avg = stof(splitted[5]);
|
||||
|
||||
fgets(zw, 1024, pFile);
|
||||
zerlegt = ZerlegeZeile(std::string(zw));
|
||||
if (zerlegt.size() < 6)
|
||||
splitted = ZerlegeZeile(std::string(zw));
|
||||
if (splitted.size() < 6)
|
||||
{
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "Exit 02");
|
||||
fclose(pFile);
|
||||
return false;
|
||||
}
|
||||
|
||||
// LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", "LoadReferenceAlignmentValues03");
|
||||
|
||||
References[1].fastalg_x = stoi(zerlegt[0]);
|
||||
References[1].fastalg_y = stoi(zerlegt[1]);
|
||||
References[1].fastalg_SAD = stof(zerlegt[2]);
|
||||
References[1].fastalg_min = stoi(zerlegt[3]);
|
||||
References[1].fastalg_max = stoi(zerlegt[4]);
|
||||
References[1].fastalg_avg = stof(zerlegt[5]);
|
||||
References[1].fastalg_x = stoi(splitted[0]);
|
||||
References[1].fastalg_y = stoi(splitted[1]);
|
||||
References[1].fastalg_SAD = stof(splitted[2]);
|
||||
References[1].fastalg_min = stoi(splitted[3]);
|
||||
References[1].fastalg_max = stoi(splitted[4]);
|
||||
References[1].fastalg_avg = stof(splitted[5]);
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
#endif
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string _zw = "\tLoadReferences[0]\tx,y:\t" + std::to_string(References[0].fastalg_x) + "\t" + std::to_string(References[0].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[0].fastalg_SAD) + "\t" + std::to_string(References[0].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[0].fastalg_max) + "\t" + std::to_string(References[0].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
_zw = "\tLoadReferences[1]\tx,y:\t" + std::to_string(References[1].fastalg_x) + "\t" + std::to_string(References[1].fastalg_x);
|
||||
_zw = _zw + "\tSAD, min, max, avg:\t" + std::to_string(References[1].fastalg_SAD) + "\t" + std::to_string(References[1].fastalg_min);
|
||||
_zw = _zw + "\t" + std::to_string(References[1].fastalg_max) + "\t" + std::to_string(References[1].fastalg_avg);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", _zw);
|
||||
#endif*/
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowAlignment::DrawRef(CImageBasis *_zw)
|
||||
{
|
||||
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
|
||||
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
|
||||
if (_zw->ImageOkay())
|
||||
{
|
||||
_zw->drawRect(References[0].target_x, References[0].target_y, References[0].width, References[0].height, 255, 0, 0, 2);
|
||||
_zw->drawRect(References[1].target_x, References[1].target_y, References[1].width, References[1].height, 255, 0, 0, 2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWALIGNMENT_H
|
||||
#define CLASSFLOWALIGNMENT_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "Helper.h"
|
||||
#include "CAlignAndCutImage.h"
|
||||
@@ -31,6 +34,9 @@ protected:
|
||||
|
||||
public:
|
||||
CImageBasis *ImageBasis, *ImageTMP;
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
ImageData *AlgROI;
|
||||
#endif
|
||||
|
||||
ClassFlowAlignment(std::vector<ClassFlow*>* lfc);
|
||||
|
||||
@@ -44,3 +50,5 @@ public:
|
||||
string name(){return "ClassFlowAlignment";};
|
||||
};
|
||||
|
||||
|
||||
#endif //CLASSFLOWALIGNMENT_H
|
||||
|
||||
@@ -8,9 +8,16 @@
|
||||
#include "CTfLiteClass.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "CNN";
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
#include <esp_heap_trace.h>
|
||||
#define NUM_RECORDS 300
|
||||
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
|
||||
#endif
|
||||
|
||||
|
||||
ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNType _cnntype) : ClassFlowImage(NULL, TAG)
|
||||
@@ -30,7 +37,8 @@ ClassFlowCNNGeneral::ClassFlowCNNGeneral(ClassFlowAlignment *_flowalign, t_CNNTy
|
||||
logfileRetentionInDays = 5;
|
||||
}
|
||||
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _vorgaengerAnalog, float analogDigitalTransitionStart)
|
||||
|
||||
string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution, int prev, float _before_narrow_Analog, float analogDigitalTransitionStart)
|
||||
{
|
||||
string result = "";
|
||||
|
||||
@@ -40,19 +48,19 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10) + 10) % 10;
|
||||
float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
int result_after_decimal_point = ((int) floor(number * 10) + 10) % 10;
|
||||
|
||||
prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(analog) zahl=" + std::to_string(zahl) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
prev = PointerEvalAnalogNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
// LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(analog) number=" + std::to_string(number) + ", result_after_decimal_point=" + std::to_string(result_after_decimal_point) + ", prev=" + std::to_string(prev));
|
||||
result = std::to_string(prev);
|
||||
|
||||
if (_extendedResolution && (CNNType != Digital))
|
||||
result = result + std::to_string(ergebnis_nachkomma);
|
||||
result = result + std::to_string(result_after_decimal_point);
|
||||
|
||||
for (int i = GENERAL[_analog]->ROI.size() - 2; i >= 0; --i)
|
||||
{
|
||||
prev = ZeigerEvalAnalogNeu(GENERAL[_analog]->ROI[i]->result_float, prev);
|
||||
prev = PointerEvalAnalogNew(GENERAL[_analog]->ROI[i]->result_float, prev);
|
||||
result = std::to_string(prev) + result;
|
||||
}
|
||||
return result;
|
||||
@@ -73,25 +81,24 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
if ((CNNType == DoubleHyprid10) || (CNNType == Digital100))
|
||||
{
|
||||
|
||||
float zahl = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
if (zahl >= 0) // NaN?
|
||||
float number = GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float;
|
||||
if (number >= 0) // NaN?
|
||||
{
|
||||
if (_extendedResolution) // ist nur gesetzt, falls es die erste Ziffer ist (kein Analog vorher!)
|
||||
if (_extendedResolution) // is only set if it is the first digit (no analogue before!)
|
||||
{
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl)) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number)) % 10;
|
||||
|
||||
result = std::to_string(ergebnis_vorkomma) + std::to_string(ergebnis_nachkomma);
|
||||
prev = ergebnis_vorkomma;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) ergebnis_vorkomma=" + std::to_string(ergebnis_vorkomma) + ", ergebnis_nachkomma=" + std::to_string(ergebnis_nachkomma) + ", prev=" + std::to_string(prev));
|
||||
result = std::to_string(result_before_decimal_point) + std::to_string(result_after_decimal_point);
|
||||
prev = result_before_decimal_point;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100-ext) result_before_decimal_point=" + std::to_string(result_before_decimal_point) + ", result_after_decimal_point=" + std::to_string(result_after_decimal_point) + ", prev=" + std::to_string(prev));
|
||||
}
|
||||
else
|
||||
{
|
||||
// prev = ZeigerEval(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev);
|
||||
if (_vorgaengerAnalog >= 0)
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _vorgaengerAnalog, prev, true, analogDigitalTransitionStart);
|
||||
if (_before_narrow_Analog >= 0)
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, _before_narrow_Analog, prev, true, analogDigitalTransitionStart);
|
||||
else
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[GENERAL[_analog]->ROI.size() - 1]->result_float, prev, prev);
|
||||
result = std::to_string(prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout(dig100) prev=" + std::to_string(prev));
|
||||
|
||||
@@ -108,8 +115,8 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
{
|
||||
if (GENERAL[_analog]->ROI[i]->result_float >= 0)
|
||||
{
|
||||
prev = ZeigerEvalHybridNeu(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#ZeigerEvalHybridNeu()= " + std::to_string(prev));
|
||||
prev = PointerEvalHybridNew(GENERAL[_analog]->ROI[i]->result_float, GENERAL[_analog]->ROI[i+1]->result_float, prev);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#PointerEvalHybridNew()= " + std::to_string(prev));
|
||||
result = std::to_string(prev) + result;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "getReadout#result= " + result);
|
||||
|
||||
@@ -124,123 +131,119 @@ string ClassFlowCNNGeneral::getReadout(int _analog = 0, bool _extendedResolution
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger, float digitalAnalogTransitionStart)
|
||||
|
||||
int ClassFlowCNNGeneral::PointerEvalHybridNew(float number, float number_of_predecessors, int eval_predecessors, bool Analog_Predecessors, float digitalAnalogTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number) + 10) % 10;
|
||||
|
||||
if (eval_vorgaenger < 0)
|
||||
if (eval_predecessors < 0)
|
||||
{
|
||||
if ((ergebnis_nachkomma <= DigitalUnschaerfe * 10) || (ergebnis_nachkomma >= DigitalUnschaerfe * 10)) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = (int) (round(zahl) + 10) % 10;
|
||||
if ((result_after_decimal_point <= Digital_Uncertainty * 10) || (result_after_decimal_point >= Digital_Uncertainty * 10)) // Band around the digit --> Rounding, as digit reaches inaccuracy in the frame
|
||||
result = (int) (round(number) + 10) % 10;
|
||||
else
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
result = (int) ((int) trunc(number) + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - No predecessor - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (AnalogerVorgaenger)
|
||||
if (Analog_Predecessors)
|
||||
{
|
||||
result = ZeigerEvalAnalogToDigitNeu(zahl, zahl_vorgaenger, eval_vorgaenger, digitalAnalogTransitionStart);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - Analoger Vorgänger, Bewertung über ZeigerEvalAnalogNeu = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
result = PointerEvalAnalogToDigitNew(number, number_of_predecessors, eval_predecessors, digitalAnalogTransitionStart);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - Analog predecessor, evaluation over PointerEvalAnalogNew = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if ((zahl_vorgaenger >= DigitalUebergangsbereichVorgaenger ) && (zahl_vorgaenger <= (10.0 - DigitalUebergangsbereichVorgaenger)))
|
||||
if ((number_of_predecessors >= Digital_Transition_Area_Predecessor ) && (number_of_predecessors <= (10.0 - Digital_Transition_Area_Predecessor)))
|
||||
{
|
||||
// kein Ziffernwechsel, da Vorgänger weit genug weg ist (0+/-DigitalUebergangsbereichVorgaenger) --> zahl wird gerundet
|
||||
if ((ergebnis_nachkomma <= DigitalBand) || (ergebnis_nachkomma >= (10-DigitalBand))) // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = ((int) round(zahl) + 10) % 10;
|
||||
// no digit change, because predecessor is far enough away (0+/-DigitalTransitionRangePredecessor) --> number is rounded
|
||||
if ((result_after_decimal_point <= DigitalBand) || (result_after_decimal_point >= (10-DigitalBand))) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|
||||
result = ((int) round(number) + 10) % 10;
|
||||
else
|
||||
result = ((int) trunc(zahl) + 10) % 10;
|
||||
result = ((int) trunc(number) + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, kein Ziffernwechsel, da Vorkomma weit genug weg = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - NO analogue predecessor, no change of digits, as pre-decimal point far enough away = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
if (eval_vorgaenger <= 1) // Nulldurchgang beim Vorgänger hat stattgefunden (!Bewertung über Prev_value und nicht Zahl!) --> hier aufrunden (2.8 --> 3, aber auch 3.1 --> 3)
|
||||
if (eval_predecessors <= 1) // Zero crossing at the predecessor has taken place (! evaluation via Prev_value and not number!) --> round up here (2.8 --> 3, but also 3.1 --> 3)
|
||||
{
|
||||
// Wir nehmen einfach an, dass das aktuelle Digit nach dem Nulldurchgang des Vorgängers
|
||||
// mindestens zur Hälfte (x.5) durchlaufen hat
|
||||
if (ergebnis_nachkomma > 5)
|
||||
// Das akt. digit hat noch keinen Nulldurchgang, aber der Vorgänger schon.
|
||||
result = (ergebnis_vorkomma + 1) % 10;
|
||||
// We simply assume that the current digit after the zero crossing of the predecessor
|
||||
// has passed through at least half (x.5)
|
||||
if (result_after_decimal_point > 5)
|
||||
// The current digit does not yet have a zero crossing, but the predecessor does..
|
||||
result = (result_before_decimal_point + 1) % 10;
|
||||
else
|
||||
// Akt. digit und Vorgänger haben Nulldurchgang
|
||||
result = ergebnis_vorkomma;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, Nulldurchgang hat stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe));
|
||||
// Act. digit and predecessor have zero crossing
|
||||
result = result_before_decimal_point % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - NO analogue predecessor, zero crossing has taken placen = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// bleibt nur >= 9.x --> noch kein Nulldurchgang --> 2.8 --> 2,
|
||||
// und ab 9.7(DigitalUebergangsbereichVorlauf) 3.1 --> 2
|
||||
// alles >=x.4 kann als aktuelle Zahl gelten im Übergang. Bei 9.x Vorgänger kann die aktuelle
|
||||
// Zahl noch x.6 - x.7 sein.
|
||||
// Vorlauf (else - Zweig) passiert nicht bereits ab 9.
|
||||
if (DigitalUebergangsbereichVorlauf>=zahl_vorgaenger || ergebnis_nachkomma >= 4)
|
||||
// aktuelles digit hat genauso wie das Vorgängerdigit noch keinen Nulldurchgang.
|
||||
result = ergebnis_vorkomma;
|
||||
// remains only >= 9.x --> no zero crossing yet --> 2.8 --> 2,
|
||||
// and from 9.7(DigitalTransitionRangeLead) 3.1 --> 2
|
||||
// everything >=x.4 can be considered as current number in transition. With 9.x predecessor the current
|
||||
// number can still be x.6 - x.7.
|
||||
// Preceding (else - branch) does not already happen from 9.
|
||||
if (Digital_Transition_Area_Forward>=number_of_predecessors || result_after_decimal_point >= 4)
|
||||
// The current digit, like the previous digit, does not yet have a zero crossing.
|
||||
result = result_before_decimal_point % 10;
|
||||
else
|
||||
// aktuelles digit läuft dem kleineren digit (9.x) vor. Also schon >=x.0 während das vorherige Digit noch
|
||||
// keinen Nulldurchgang hat. Daher wird um 1 reduziert.
|
||||
result = (ergebnis_vorkomma - 1 + 10) % 10;
|
||||
// current digit precedes the smaller digit (9.x). So already >=x.0 while the previous digit has not yet
|
||||
// has no zero crossing. Therefore, it is reduced by 1.
|
||||
result = (result_before_decimal_point - 1 + 10) % 10;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalHybridNeu - KEIN Analoger Vorgänger, >= 9.5 --> noch kein Nulldurchgang = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " zahl_vorgaenger = " + std::to_string(zahl_vorgaenger)+ " eval_vorgaenger = " + std::to_string(eval_vorgaenger) + " DigitalUnschaerfe = " + std::to_string(DigitalUnschaerfe) + " ergebnis_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalHybridNew - O analogue predecessor, >= 9.5 --> no zero crossing yet = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " number_of_predecessors = " + std::to_string(number_of_predecessors)+ " eval_predecessors = " + std::to_string(eval_predecessors) + " Digital_Uncertainty = " + std::to_string(Digital_Uncertainty) + " result_after_decimal_point = " + std::to_string(result_after_decimal_point));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart)
|
||||
int ClassFlowCNNGeneral::PointerEvalAnalogToDigitNew(float number, float numeral_preceder, int eval_predecessors, float analogDigitalTransitionStart)
|
||||
{
|
||||
int result;
|
||||
int ergebnis_nachkomma = ((int) floor(zahl * 10)) % 10;
|
||||
int ergebnis_vorkomma = ((int) floor(zahl) + 10) % 10;
|
||||
int result_after_decimal_point = ((int) floor(number * 10)) % 10;
|
||||
int result_before_decimal_point = ((int) floor(number) + 10) % 10;
|
||||
bool roundedUp = false;
|
||||
|
||||
// Innerhalb der digitalen Unschaefe
|
||||
if (ergebnis_nachkomma >= (10-DigitalUnschaerfe * 10)) { // Band um die Ziffer --> Runden, da Ziffer im Rahmen Ungenauigkeit erreicht
|
||||
result = (int) (round(zahl) + 10) % 10;
|
||||
// Within the digital inequalities
|
||||
if ((result_after_decimal_point >= (10-Digital_Uncertainty * 10)) // Band around the digit --> Round off, as digit reaches inaccuracy in the frame
|
||||
|| (eval_predecessors <= 4 && result_after_decimal_point>=6)) { // or digit runs after (analogue =0..4, digit >=6)
|
||||
result = (int) (round(number) + 10) % 10;
|
||||
roundedUp = true;
|
||||
// vor/nachkomma neu berechnen, da wir anhand der Unschaefe die Zahl anpassen.
|
||||
ergebnis_nachkomma = ((int) floor(result * 10)) % 10;
|
||||
ergebnis_vorkomma = ((int) floor(result) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger: " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_vorkomma: " + std::to_string(ergebnis_vorkomma) +
|
||||
" erg_nachkomma: " + std::to_string(ergebnis_nachkomma));
|
||||
// before/ after decimal point, because we adjust the number based on the uncertainty.
|
||||
result_after_decimal_point = ((int) floor(result * 10)) % 10;
|
||||
result_before_decimal_point = ((int) floor(result) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Digital Uncertainty - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder: " + std::to_string(numeral_preceder) +
|
||||
" erg before comma: " + std::to_string(result_before_decimal_point) +
|
||||
" erg after comma: " + std::to_string(result_after_decimal_point));
|
||||
} else {
|
||||
result = (int) ((int) trunc(zahl) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - KEINE digitaleUnschaerfe - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger));
|
||||
result = (int) ((int) trunc(number) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - NO digital Uncertainty - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder));
|
||||
}
|
||||
|
||||
// Kein Nulldurchgang hat stattgefunden.
|
||||
// Nur eval_vorgaenger verwendet, da ziffer_vorgaenger hier falsch sein könnte.
|
||||
// ziffer_vorgaenger<=0.1 & eval_vorgaenger=9 entspricht analog wurde zurückgesetzt wegen vorhergehender analog, die noch nicht auf 0 sind.
|
||||
if ((eval_vorgaenger>=6 && (ziffer_vorgaenger>analogDigitalTransitionStart || ziffer_vorgaenger<=0.2) && roundedUp)
|
||||
// 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))
|
||||
|
||||
// No zero crossing has taken place.
|
||||
// Only eval_predecessors used because numeral_preceder could be wrong here.
|
||||
// numeral_preceder<=0.1 & eval_predecessors=9 corresponds to analogue was reset because of previous analogue that are not yet at 0.
|
||||
if ((eval_predecessors>=6 && (numeral_preceder>analogDigitalTransitionStart || numeral_preceder<=0.2) && roundedUp))
|
||||
{
|
||||
result = ((ergebnis_vorkomma+10) - 1) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogToDigitNeu - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) +
|
||||
" ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) +
|
||||
" erg_nachkomma = " + std::to_string(ergebnis_nachkomma));
|
||||
result = ((result_before_decimal_point+10) - 1) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogToDigitNew - Nulldurchgang noch nicht stattgefunden = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) +
|
||||
" numeral_preceder = " + std::to_string(numeral_preceder) +
|
||||
" eerg after comma = " + std::to_string(result_after_decimal_point));
|
||||
|
||||
}
|
||||
|
||||
@@ -248,53 +251,53 @@ int ClassFlowCNNGeneral::ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vor
|
||||
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger)
|
||||
|
||||
int ClassFlowCNNGeneral::PointerEvalAnalogNew(float number, int numeral_preceder)
|
||||
{
|
||||
float zahl_min, zahl_max;
|
||||
float number_min, number_max;
|
||||
int result;
|
||||
|
||||
if (ziffer_vorgaenger == -1)
|
||||
if (numeral_preceder == -1)
|
||||
{
|
||||
result = (int) floor(zahl);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - kein Vorgänger - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = (int) floor(number);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - No predecessor - Result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
|
||||
zahl_min = zahl - AnalogFehler / 10.0;
|
||||
zahl_max = zahl + AnalogFehler / 10.0;
|
||||
number_min = number - Analog_error / 10.0;
|
||||
number_max = number + Analog_error / 10.0;
|
||||
|
||||
if ((int) floor(zahl_max) - (int) floor(zahl_min) != 0)
|
||||
if ((int) floor(number_max) - (int) floor(number_min) != 0)
|
||||
{
|
||||
if (ziffer_vorgaenger <= AnalogFehler)
|
||||
if (numeral_preceder <= Analog_error)
|
||||
{
|
||||
result = ((int) floor(zahl_max) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach oben - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number_max) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number ambiguous, correction upwards - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
if (ziffer_vorgaenger >= 10 - AnalogFehler)
|
||||
if (numeral_preceder >= 10 - Analog_error)
|
||||
{
|
||||
result = ((int) floor(zahl_min) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl uneindeutig, Korrektur nach unten - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number_min) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number ambiguous, downward correction - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
result = ((int) floor(zahl) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ZeigerEvalAnalogNeu - Zahl eindeutig, keine Korrektur notwendig - Ergebnis = " + std::to_string(result) +
|
||||
" zahl: " + std::to_string(zahl) + " ziffer_vorgaenger = " + std::to_string(ziffer_vorgaenger) + " AnalogFehler = " + std::to_string(AnalogFehler));
|
||||
result = ((int) floor(number) + 10) % 10;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "PointerEvalAnalogNew - number unambiguous, no correction necessary - result = " + std::to_string(result) +
|
||||
" number: " + std::to_string(number) + " numeral_preceder = " + std::to_string(numeral_preceder) + " Analog_error = " + std::to_string(Analog_error));
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -320,53 +323,53 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "LOGIMAGELOCATION") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "LOGIMAGELOCATION") && (splitted.size() > 1))
|
||||
{
|
||||
this->LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
this->LogImageLocation = "/sdcard" + splitted[1];
|
||||
this->isLogImage = true;
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGIMAGESELECT") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGIMAGESELECT") && (splitted.size() > 1))
|
||||
{
|
||||
LogImageSelect = zerlegt[1];
|
||||
LogImageSelect = splitted[1];
|
||||
isLogImageSelect = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
|
||||
this->logfileRetentionInDays = std::stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "MODEL") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "MODEL") && (splitted.size() > 1))
|
||||
{
|
||||
this->cnnmodelfile = zerlegt[1];
|
||||
this->cnnmodelfile = splitted[1];
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CNNGOODTHRESHOLD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CNNGOODTHRESHOLD") && (splitted.size() > 1))
|
||||
{
|
||||
CNNGoodThreshold = std::stof(zerlegt[1]);
|
||||
CNNGoodThreshold = std::stof(splitted[1]);
|
||||
}
|
||||
if (zerlegt.size() >= 5)
|
||||
if (splitted.size() >= 5)
|
||||
{
|
||||
general* _analog = GetGENERAL(zerlegt[0], true);
|
||||
general* _analog = GetGENERAL(splitted[0], true);
|
||||
roi* neuroi = _analog->ROI[_analog->ROI.size()-1];
|
||||
neuroi->posx = std::stoi(zerlegt[1]);
|
||||
neuroi->posy = std::stoi(zerlegt[2]);
|
||||
neuroi->deltax = std::stoi(zerlegt[3]);
|
||||
neuroi->deltay = std::stoi(zerlegt[4]);
|
||||
neuroi->posx = std::stoi(splitted[1]);
|
||||
neuroi->posy = std::stoi(splitted[2]);
|
||||
neuroi->deltax = std::stoi(splitted[3]);
|
||||
neuroi->deltay = std::stoi(splitted[4]);
|
||||
neuroi->CCW = false;
|
||||
if (zerlegt.size() >= 6)
|
||||
if (splitted.size() >= 6)
|
||||
{
|
||||
neuroi->CCW = toUpper(zerlegt[5]) == "TRUE";
|
||||
neuroi->CCW = toUpper(splitted[5]) == "TRUE";
|
||||
}
|
||||
neuroi->result_float = -1;
|
||||
neuroi->image = NULL;
|
||||
neuroi->image_org = NULL;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
}
|
||||
@@ -385,6 +388,7 @@ bool ClassFlowCNNGeneral::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
general* ClassFlowCNNGeneral::FindGENERAL(string _name_number)
|
||||
{
|
||||
for (int i = 0; i < GENERAL.size(); ++i)
|
||||
@@ -416,7 +420,7 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
|
||||
if (GENERAL[i]->name == _analog)
|
||||
_ret = GENERAL[i];
|
||||
|
||||
if (!_create) // nicht gefunden und soll auch nicht erzeugt werden
|
||||
if (!_create) // not found and should not be created
|
||||
return _ret;
|
||||
|
||||
if (_ret == NULL)
|
||||
@@ -437,7 +441,6 @@ general* ClassFlowCNNGeneral::GetGENERAL(string _name, bool _create = true)
|
||||
}
|
||||
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result, zw;
|
||||
@@ -462,9 +465,16 @@ string ClassFlowCNNGeneral::getHTMLSingleStep(string host)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doFlow(string time)
|
||||
{
|
||||
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
//register a buffer to record the memory trace
|
||||
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
|
||||
// start tracing
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
if (disabled)
|
||||
return true;
|
||||
|
||||
@@ -472,14 +482,21 @@ bool ClassFlowCNNGeneral::doFlow(string time)
|
||||
return false;
|
||||
};
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow nach Alignment");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "doFlow after alignment");
|
||||
|
||||
doNeuralNetwork(time);
|
||||
|
||||
RemoveOldLogs();
|
||||
|
||||
#ifdef HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doAlignAndCut(string time)
|
||||
{
|
||||
if (disabled)
|
||||
@@ -505,40 +522,45 @@ bool ClassFlowCNNGeneral::doAlignAndCut(string time)
|
||||
if (SaveAllFiles)
|
||||
{
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowCNNGeneral::DrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
int r = 0;
|
||||
int g = 255;
|
||||
int b = 0;
|
||||
if (_zw->ImageOkay())
|
||||
{
|
||||
if (CNNType == Analogue || CNNType == Analogue100)
|
||||
{
|
||||
int r = 0;
|
||||
int g = 255;
|
||||
int b = 0;
|
||||
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
_zw->drawRect(GENERAL[_ana]->ROI[i]->posx, GENERAL[_ana]->ROI[i]->posy, GENERAL[_ana]->ROI[i]->deltax, GENERAL[_ana]->ROI[i]->deltay, r, g, b, 1);
|
||||
_zw->drawEllipse( (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) (GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
_zw->drawLine((int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) GENERAL[_ana]->ROI[i]->posy, (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay), r, g, b, 2);
|
||||
_zw->drawLine((int) GENERAL[_ana]->ROI[i]->posx, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); ++_dig)
|
||||
for (int i = 0; i < GENERAL[_dig]->ROI.size(); ++i)
|
||||
_zw->drawRect(GENERAL[_dig]->ROI[i]->posx, GENERAL[_dig]->ROI[i]->posy, GENERAL[_dig]->ROI[i]->deltax, GENERAL[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2);
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
{
|
||||
_zw->drawRect(GENERAL[_ana]->ROI[i]->posx, GENERAL[_ana]->ROI[i]->posy, GENERAL[_ana]->ROI[i]->deltax, GENERAL[_ana]->ROI[i]->deltay, r, g, b, 1);
|
||||
_zw->drawEllipse( (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) (GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
_zw->drawLine((int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) GENERAL[_ana]->ROI[i]->posy, (int) (GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax/2), (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay), r, g, b, 2);
|
||||
_zw->drawLine((int) GENERAL[_ana]->ROI[i]->posx, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), (int) GENERAL[_ana]->ROI[i]->posx + GENERAL[_ana]->ROI[i]->deltax, (int) (GENERAL[_ana]->ROI[i]->posy + GENERAL[_ana]->ROI[i]->deltay/2), r, g, b, 2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); ++_dig)
|
||||
for (int i = 0; i < GENERAL[_dig]->ROI.size(); ++i)
|
||||
_zw->drawRect(GENERAL[_dig]->ROI[i]->posx, GENERAL[_dig]->ROI[i]->posy, GENERAL[_dig]->ROI[i]->deltax, GENERAL[_dig]->ROI[i]->deltay, 0, 0, (255 - _dig*100), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
{
|
||||
if (disabled)
|
||||
@@ -549,11 +571,18 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnnmodelfile + " -> Init aborted!");
|
||||
LogFile.WriteHeapInfo("getNetworkParameter-LoadModel");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
tflite->MakeAllocate();
|
||||
|
||||
if (!tflite->MakeAllocate()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tflite model -> Init aborted!");
|
||||
LogFile.WriteHeapInfo("getNetworkParameter-MakeAllocate");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (CNNType == AutoDetect)
|
||||
{
|
||||
@@ -596,7 +625,7 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite passt nicht zur Firmware (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "tflite does not fit the firmware (outout_dimension=" + std::to_string(_anzoutputdimensions) + ")");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -604,6 +633,7 @@ bool ClassFlowCNNGeneral::getNetworkParameter()
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
{
|
||||
if (disabled)
|
||||
@@ -615,152 +645,88 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
string zwcnn = "/sdcard" + cnnmodelfile;
|
||||
zwcnn = FormatFileName(zwcnn);
|
||||
ESP_LOGD(TAG, "%s", zwcnn.c_str());
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't read model file " + cnnmodelfile);
|
||||
|
||||
if (!tflite->LoadModel(zwcnn)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't load tflite model " + cnnmodelfile + " -> Exec aborted this round!");
|
||||
LogFile.WriteHeapInfo("doNeuralNetwork-LoadModel");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
tflite->MakeAllocate();
|
||||
}
|
||||
|
||||
for (int _ana = 0; _ana < GENERAL.size(); ++_ana)
|
||||
if (!tflite->MakeAllocate()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Can't allocate tfilte model -> Exec aborted this round!");
|
||||
LogFile.WriteHeapInfo("doNeuralNetwork-MakeAllocate");
|
||||
delete tflite;
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int n = 0; n < GENERAL.size(); ++n) // For each NUMBER
|
||||
{
|
||||
for (int i = 0; i < GENERAL[_ana]->ROI.size(); ++i)
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Processing Number '" + GENERAL[n]->name + "'");
|
||||
for (int roi = 0; roi < GENERAL[n]->ROI.size(); ++roi) // For each ROI
|
||||
{
|
||||
ESP_LOGD(TAG, "General %d - TfLite", i);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "ROI #" + std::to_string(roi) + " - TfLite");
|
||||
//ESP_LOGD(TAG, "General %d - TfLite", i);
|
||||
|
||||
switch (CNNType) {
|
||||
case Analogue:
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Analogue");
|
||||
{
|
||||
float f1, f2;
|
||||
f1 = 0; f2 = 0;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->LoadInputImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After Invoke");
|
||||
|
||||
f1 = tflite->GetOutputValue(0);
|
||||
f2 = tflite->GetOutputValue(1);
|
||||
float result = fmod(atan2(f1, f2) / (M_PI * 2) + 2, 1);
|
||||
|
||||
if(GENERAL[_ana]->ROI[i]->CCW)
|
||||
GENERAL[_ana]->ROI[i]->result_float = 10 - (result * 10);
|
||||
if(GENERAL[n]->ROI[roi]->CCW)
|
||||
GENERAL[n]->ROI[roi]->result_float = 10 - (result * 10);
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = result * 10;
|
||||
GENERAL[n]->ROI[roi]->result_float = result * 10;
|
||||
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "General result (Analog)%i - CCW: %d - %f", roi, GENERAL[n]->ROI[roi]->CCW, GENERAL[n]->ROI[roi]->result_float);
|
||||
if (isLogImage)
|
||||
LogImage(logPath, GENERAL[_ana]->ROI[i]->name, &GENERAL[_ana]->ROI[i]->result_float, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
LogImage(logPath, GENERAL[n]->ROI[roi]->name, &GENERAL[n]->ROI[roi]->result_float, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
} break;
|
||||
|
||||
case Digital:
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Digital");
|
||||
{
|
||||
GENERAL[_ana]->ROI[i]->result_klasse = 0;
|
||||
GENERAL[_ana]->ROI[i]->result_klasse = tflite->GetClassFromImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
ESP_LOGD(TAG, "Result General(Digit)%i: %d", i, GENERAL[_ana]->ROI[i]->result_klasse);
|
||||
GENERAL[n]->ROI[roi]->result_klasse = 0;
|
||||
GENERAL[n]->ROI[roi]->result_klasse = tflite->GetClassFromImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
ESP_LOGD(TAG, "General result (Digit)%i: %d", roi, GENERAL[n]->ROI[roi]->result_klasse);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
string _imagename = GENERAL[n]->name + "_" + GENERAL[n]->ROI[roi]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
if (LogImageSelect.find(GENERAL[n]->ROI[roi]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[n]->ROI[roi]->result_klasse, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[n]->ROI[roi]->result_klasse, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
/*
|
||||
case DigitalHyprid:
|
||||
{
|
||||
int _num, _nachkomma;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 10);
|
||||
_nachkomma = tflite->GetOutClassification(11, 21);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if ((_num == 10) || (_nachkomma == 10)) // NaN detektiert
|
||||
GENERAL[_ana]->ROI[i]->result_float = -1;
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
*/
|
||||
/*
|
||||
case DigitalHyprid10:
|
||||
{
|
||||
int _num, _nachkomma;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_nachkomma = tflite->GetOutClassification(10, 19);
|
||||
|
||||
|
||||
string _zwres = "Nach Invoke - Nummer: " + to_string(_num) + " Nachkomma: " + to_string(_nachkomma);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
GENERAL[_ana]->ROI[i]->result_float = fmod((double) _num + (((double)_nachkomma)-5)/10 + (double) 10, 10);
|
||||
|
||||
ESP_LOGD(TAG, "Result General(DigitalHyprid)%i: %f\n", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
_zwres = "Result General(DigitalHyprid)" + to_string(i) + ": " + to_string(GENERAL[_ana]->ROI[i]->result_float);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, _zwres);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, NULL, &GENERAL[_ana]->ROI[i]->result_klasse, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
*/
|
||||
|
||||
case DoubleHyprid10:
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: DoubleHyprid10");
|
||||
int _num, _numplus, _numminus;
|
||||
float _val, _valplus, _valminus;
|
||||
float _fit;
|
||||
float _result_save_file;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->LoadInputImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
tflite->Invoke();
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach Invoke");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "After Invoke");
|
||||
|
||||
_num = tflite->GetOutClassification(0, 9);
|
||||
_numplus = (_num + 1) % 10;
|
||||
@@ -798,32 +764,32 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
|
||||
if (_fit < CNNGoodThreshold)
|
||||
{
|
||||
GENERAL[_ana]->ROI[i]->isReject = true;
|
||||
GENERAL[n]->ROI[roi]->isReject = true;
|
||||
result = -1;
|
||||
_result_save_file+= 100; // Für den Fall, dass fit nicht ausreichend, soll trotzdem das Ergebnis mit "-10x.y" abgespeichert werden.
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + "Threshold: " + to_string(CNNGoodThreshold) + ")";
|
||||
_result_save_file+= 100; // In case fit is not sufficient, the result should still be saved with "-10x.y".
|
||||
string zw = "Value Rejected due to Threshold (Fit: " + to_string(_fit) + ", Threshold: " + to_string(CNNGoodThreshold) + ")";
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, zw);
|
||||
}
|
||||
else
|
||||
{
|
||||
GENERAL[_ana]->ROI[i]->isReject = false;
|
||||
GENERAL[n]->ROI[roi]->isReject = false;
|
||||
}
|
||||
|
||||
|
||||
GENERAL[_ana]->ROI[i]->result_float = result;
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i: %f", i, GENERAL[_ana]->ROI[i]->result_float);
|
||||
GENERAL[n]->ROI[roi]->result_float = result;
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i: %f", roi, GENERAL[n]->ROI[roi]->result_float);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
string _imagename = GENERAL[n]->name + "_" + GENERAL[n]->ROI[roi]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
if (LogImageSelect.find(GENERAL[n]->ROI[roi]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -831,37 +797,38 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
case Digital100:
|
||||
case Analogue100:
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CNN Type: Digital100 or Analogue100");
|
||||
int _num;
|
||||
float _result_save_file;
|
||||
|
||||
tflite->LoadInputImageBasis(GENERAL[_ana]->ROI[i]->image);
|
||||
tflite->LoadInputImageBasis(GENERAL[n]->ROI[roi]->image);
|
||||
tflite->Invoke();
|
||||
|
||||
_num = tflite->GetOutClassification();
|
||||
|
||||
if(GENERAL[_ana]->ROI[i]->CCW)
|
||||
GENERAL[_ana]->ROI[i]->result_float = 10 - ((float)_num / 10.0);
|
||||
if(GENERAL[n]->ROI[roi]->CCW)
|
||||
GENERAL[n]->ROI[roi]->result_float = 10 - ((float)_num / 10.0);
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->result_float = (float)_num / 10.0;
|
||||
GENERAL[n]->ROI[roi]->result_float = (float)_num / 10.0;
|
||||
|
||||
_result_save_file = GENERAL[_ana]->ROI[i]->result_float;
|
||||
_result_save_file = GENERAL[n]->ROI[roi]->result_float;
|
||||
|
||||
|
||||
GENERAL[_ana]->ROI[i]->isReject = false;
|
||||
GENERAL[n]->ROI[roi]->isReject = false;
|
||||
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", i, GENERAL[_ana]->ROI[i]->CCW, GENERAL[_ana]->ROI[i]->result_float);
|
||||
ESP_LOGD(TAG, "Result General(Analog)%i - CCW: %d - %f", roi, GENERAL[n]->ROI[roi]->CCW, GENERAL[n]->ROI[roi]->result_float);
|
||||
|
||||
if (isLogImage)
|
||||
{
|
||||
string _imagename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name;
|
||||
string _imagename = GENERAL[n]->name + "_" + GENERAL[n]->ROI[roi]->name;
|
||||
if (isLogImageSelect)
|
||||
{
|
||||
if (LogImageSelect.find(GENERAL[_ana]->ROI[i]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
if (LogImageSelect.find(GENERAL[n]->ROI[roi]->name) != std::string::npos)
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[_ana]->ROI[i]->image_org);
|
||||
LogImage(logPath, _imagename, &_result_save_file, NULL, time, GENERAL[n]->ROI[roi]->image_org);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -878,6 +845,7 @@ bool ClassFlowCNNGeneral::doNeuralNetwork(string time)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowCNNGeneral::isExtendedResolution(int _number)
|
||||
{
|
||||
if (!(CNNType == Digital))
|
||||
@@ -887,7 +855,6 @@ bool ClassFlowCNNGeneral::isExtendedResolution(int _number)
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
{
|
||||
std::vector<HTMLInfo*> result;
|
||||
@@ -899,20 +866,20 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
if (GENERAL[_ana]->ROI[i]->image)
|
||||
{
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
else
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp"));
|
||||
GENERAL[_ana]->ROI[i]->image->SaveToFile(FormatFileName("/sdcard/img_tmp/" + GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg"));
|
||||
}
|
||||
|
||||
HTMLInfo *zw = new HTMLInfo;
|
||||
if (GENERAL[_ana]->name == "default")
|
||||
{
|
||||
zw->filename = GENERAL[_ana]->ROI[i]->name + ".bmp";
|
||||
zw->filename = GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
zw->filename_org = GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
}
|
||||
else
|
||||
{
|
||||
zw->filename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".bmp";
|
||||
zw->filename = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
zw->filename_org = GENERAL[_ana]->name + "_" + GENERAL[_ana]->ROI[i]->name + ".jpg";
|
||||
}
|
||||
|
||||
@@ -929,11 +896,13 @@ std::vector<HTMLInfo*> ClassFlowCNNGeneral::GetHTMLInfo()
|
||||
return result;
|
||||
}
|
||||
|
||||
int ClassFlowCNNGeneral::getAnzahlGENERAL()
|
||||
|
||||
int ClassFlowCNNGeneral::getNumberGENERAL()
|
||||
{
|
||||
return GENERAL.size();
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getNameGENERAL(int _analog)
|
||||
{
|
||||
if (_analog < GENERAL.size())
|
||||
@@ -942,6 +911,7 @@ string ClassFlowCNNGeneral::getNameGENERAL(int _analog)
|
||||
return "GENERAL DOES NOT EXIST";
|
||||
}
|
||||
|
||||
|
||||
general* ClassFlowCNNGeneral::GetGENERAL(int _analog)
|
||||
{
|
||||
if (_analog < GENERAL.size())
|
||||
@@ -951,7 +921,6 @@ general* ClassFlowCNNGeneral::GetGENERAL(int _analog)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numbers)
|
||||
{
|
||||
for (int _dig = 0; _dig < GENERAL.size(); _dig++)
|
||||
@@ -968,6 +937,7 @@ void ClassFlowCNNGeneral::UpdateNameNumbers(std::vector<std::string> *_name_numb
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowCNNGeneral::getReadoutRawString(int _analog)
|
||||
{
|
||||
string rt = "";
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CLASSCNNGENERAL__
|
||||
#define __CLASSCNNGENERAL__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWCNNGENERAL_H
|
||||
#define CLASSFLOWCNNGENERAL_H
|
||||
|
||||
#include"ClassFlowDefineTypes.h"
|
||||
#include "ClassFlowAlignment.h"
|
||||
@@ -23,13 +25,15 @@ protected:
|
||||
t_CNNType CNNType;
|
||||
std::vector<general*> GENERAL;
|
||||
float CNNGoodThreshold;
|
||||
float AnalogFehler = 3.0;
|
||||
float AnalogToDigtalFehler = 0.8;
|
||||
float DigitalUnschaerfe = 0.2;
|
||||
int DigitalBand = 3;
|
||||
float DigitalAnalogerVorgaengerUebergangsbereich = 2;
|
||||
float DigitalUebergangsbereichVorgaenger = 0.7; // 9.3 - 0.7
|
||||
float DigitalUebergangsbereichVorlauf = 9.7; // Vorlauf-Nulldurchgang passiert erst ab ca. 9.7
|
||||
|
||||
//moved to define.h
|
||||
//float Analog_error = 3.0;
|
||||
//float AnalogToDigtalFehler = 0.8;
|
||||
//float Digital_Uncertainty = 0.2;
|
||||
//int DigitalBand = 3;
|
||||
//float Digital_Transition_Range_Predecessor = 2;
|
||||
//float Digital_Transition_Area_Predecessor = 0.7; // 9.3 - 0.7
|
||||
//float Digital_Transition_Area_Forward = 9.7; // Pre-run zero crossing only happens from approx. 9.7 onwards
|
||||
|
||||
string cnnmodelfile;
|
||||
int modelxsize, modelysize, modelchannel;
|
||||
@@ -39,9 +43,9 @@ protected:
|
||||
|
||||
bool SaveAllFiles;
|
||||
|
||||
int ZeigerEvalAnalogNeu(float zahl, int ziffer_vorgaenger);
|
||||
int ZeigerEvalAnalogToDigitNeu(float zahl, float ziffer_vorgaenger, int eval_vorgaenger, float analogDigitalTransitionStart);
|
||||
int ZeigerEvalHybridNeu(float zahl, float zahl_vorgaenger, int eval_vorgaenger, bool AnalogerVorgaenger = false, float analogDigitalTransitionStart=9.2);
|
||||
int PointerEvalAnalogNew(float zahl, int numeral_preceder);
|
||||
int PointerEvalAnalogToDigitNew(float zahl, float numeral_preceder, int eval_predecessors, float analogDigitalTransitionStart);
|
||||
int PointerEvalHybridNew(float zahl, float number_of_predecessors, int eval_predecessors, bool Analog_Predecessors = false, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +61,7 @@ public:
|
||||
bool doFlow(string time);
|
||||
|
||||
string getHTMLSingleStep(string host);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _vorgaengerAnalog = -1, float analogDigitalTransitionStart=9.2);
|
||||
string getReadout(int _analog, bool _extendedResolution = false, int prev = -1, float _before_narrow_Analog = -1, float analogDigitalTransitionStart=9.2);
|
||||
|
||||
string getReadoutRawString(int _analog);
|
||||
|
||||
@@ -65,7 +69,7 @@ public:
|
||||
|
||||
std::vector<HTMLInfo*> GetHTMLInfo();
|
||||
|
||||
int getAnzahlGENERAL();
|
||||
int getNumberGENERAL();
|
||||
general* GetGENERAL(int _analog);
|
||||
general* GetGENERAL(string _name, bool _create);
|
||||
general* FindGENERAL(string _name_number);
|
||||
|
||||
@@ -19,17 +19,17 @@ extern "C" {
|
||||
#include "time_sntp.h"
|
||||
#include "Helper.h"
|
||||
#include "server_ota.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "server_mqtt.h"
|
||||
|
||||
|
||||
//#include "CImg.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#include "server_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#include "server_help.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
static const char* TAG = "CTRL";
|
||||
|
||||
static const char* TAG = "FLOW CTRL";
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _host){
|
||||
@@ -50,16 +50,21 @@ std::string ClassFlowControll::doSingleStep(std::string _stepname, std::string _
|
||||
if ((_stepname.compare("[Analog]") == 0) || (_stepname.compare(";[Analog]") == 0)){
|
||||
_classname = "ClassFlowCNNGeneral";
|
||||
}
|
||||
#ifdef ENABLE_MQTT
|
||||
if ((_stepname.compare("[MQTT]") == 0) || (_stepname.compare(";[MQTT]") == 0)){
|
||||
_classname = "ClassFlowMQTT";
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if ((_stepname.compare("[InfluxDB]") == 0) || (_stepname.compare(";[InfluxDB]") == 0)){
|
||||
_classname = "ClassFlowInfluxDB";
|
||||
}
|
||||
#endif //ENABLE_INFLUXDB
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
if (FlowControll[i]->name().compare(_classname) == 0){
|
||||
if (!(FlowControll[i]->name().compare("ClassFlowMakeImage") == 0)) // falls es ein MakeImage ist, braucht das Bild nicht extra aufgenommen zu werden, dass passiert bei html-Abfrage automatisch
|
||||
if (!(FlowControll[i]->name().compare("ClassFlowMakeImage") == 0)) // if it is a MakeImage, the image does not need to be included, this happens automatically with the html query.
|
||||
FlowControll[i]->doFlow("");
|
||||
result = FlowControll[i]->getHTMLSingleStep(_host);
|
||||
}
|
||||
@@ -78,14 +83,18 @@ std::string ClassFlowControll::TranslateAktstatus(std::string _input)
|
||||
return ("Aligning");
|
||||
if (_input.compare("ClassFlowCNNGeneral") == 0)
|
||||
return ("Digitalization of ROIs");
|
||||
if (_input.compare("ClassFlowMQTT") == 0)
|
||||
return ("Sending MQTT");
|
||||
if (_input.compare("ClassFlowInfluxDB") == 0)
|
||||
return ("Sending InfluxDB");
|
||||
#ifdef ENABLE_MQTT
|
||||
if (_input.compare("ClassFlowMQTT") == 0)
|
||||
return ("Sending MQTT");
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if (_input.compare("ClassFlowInfluxDB") == 0)
|
||||
return ("Sending InfluxDB");
|
||||
#endif //ENABLE_INFLUXDB
|
||||
if (_input.compare("ClassFlowPostProcessing") == 0)
|
||||
return ("Processing");
|
||||
return ("Post-Processing");
|
||||
if (_input.compare("ClassFlowWriteList") == 0)
|
||||
return ("Processing");
|
||||
return ("Writing List");
|
||||
|
||||
return "Unkown Status";
|
||||
}
|
||||
@@ -103,6 +112,7 @@ std::vector<HTMLInfo*> ClassFlowControll::GetAllDigital()
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
std::vector<HTMLInfo*> ClassFlowControll::GetAllAnalog()
|
||||
{
|
||||
if (flowanalog)
|
||||
@@ -112,6 +122,7 @@ std::vector<HTMLInfo*> ClassFlowControll::GetAllAnalog()
|
||||
return empty;
|
||||
}
|
||||
|
||||
|
||||
t_CNNType ClassFlowControll::GetTypeDigital()
|
||||
{
|
||||
if (flowdigit)
|
||||
@@ -120,6 +131,7 @@ t_CNNType ClassFlowControll::GetTypeDigital()
|
||||
return t_CNNType::None;
|
||||
}
|
||||
|
||||
|
||||
t_CNNType ClassFlowControll::GetTypeAnalog()
|
||||
{
|
||||
if (flowanalog)
|
||||
@@ -129,8 +141,23 @@ t_CNNType ClassFlowControll::GetTypeAnalog()
|
||||
}
|
||||
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
void ClassFlowControll::DigitalDrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (flowdigit)
|
||||
flowdigit->DrawROI(_zw);
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::AnalogDrawROI(CImageBasis *_zw)
|
||||
{
|
||||
if (flowanalog)
|
||||
flowanalog->DrawROI(_zw);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
string ClassFlowControll::GetMQTTMainTopic()
|
||||
{
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
@@ -140,6 +167,16 @@ string ClassFlowControll::GetMQTTMainTopic()
|
||||
return "";
|
||||
}
|
||||
|
||||
bool ClassFlowControll::StartMQTTService() {
|
||||
/* 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 false;
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
|
||||
void ClassFlowControll::SetInitialParameter(void)
|
||||
@@ -152,15 +189,17 @@ void ClassFlowControll::SetInitialParameter(void)
|
||||
flowpostprocessing = NULL;
|
||||
disabled = false;
|
||||
aktRunNr = 0;
|
||||
aktstatus = "Booting ...";
|
||||
aktstatus = "Flow task not yet created";
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::isAutoStart(long &_intervall)
|
||||
{
|
||||
_intervall = AutoIntervall * 60 * 1000; // AutoIntervall: Minuten -> ms
|
||||
_intervall = AutoIntervall * 60 * 1000; // AutoInterval: minutes -> ms
|
||||
return AutoStart;
|
||||
}
|
||||
|
||||
|
||||
ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
{
|
||||
ClassFlow* cfc = NULL;
|
||||
@@ -187,12 +226,14 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
cfc = new ClassFlowCNNGeneral(flowalignment);
|
||||
flowdigit = (ClassFlowCNNGeneral*) cfc;
|
||||
}
|
||||
#ifdef ENABLE_MQTT
|
||||
if (toUpper(_type).compare("[MQTT]") == 0)
|
||||
cfc = new ClassFlowMQTT(&FlowControll);
|
||||
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
if (toUpper(_type).compare("[INFLUXDB]") == 0)
|
||||
cfc = new ClassFlowInfluxDB(&FlowControll);
|
||||
|
||||
#endif //ENABLE_INFLUXDB
|
||||
if (toUpper(_type).compare("[WRITELIST]") == 0)
|
||||
cfc = new ClassFlowWriteList(&FlowControll);
|
||||
|
||||
@@ -202,7 +243,7 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
flowpostprocessing = (ClassFlowPostProcessing*) cfc;
|
||||
}
|
||||
|
||||
if (cfc) // Wird nur angehangen, falls es nicht [AutoTimer] ist, denn dieses ist für FlowControll
|
||||
if (cfc) // Attached only if it is not [AutoTimer], because this is for FlowControll
|
||||
FlowControll.push_back(cfc);
|
||||
|
||||
if (toUpper(_type).compare("[AUTOTIMER]") == 0)
|
||||
@@ -220,16 +261,21 @@ ClassFlow* ClassFlowControll::CreateClassFlow(std::string _type)
|
||||
return cfc;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::InitFlow(std::string config)
|
||||
{
|
||||
aktstatus = "Initialization";
|
||||
//#ifdef ENABLE_MQTT
|
||||
//MQTTPublish(mqttServer_getMainTopic() + "/" + "status", "Initialization", false); // Right now, not possible -> MQTT Service is going to be started later
|
||||
//#endif //ENABLE_MQTT
|
||||
|
||||
string line;
|
||||
|
||||
flowpostprocessing = NULL;
|
||||
|
||||
ClassFlow* cfc;
|
||||
FILE* pFile;
|
||||
config = FormatFileName(config);
|
||||
pFile = OpenFileAndWait(config.c_str(), "r");
|
||||
pFile = fopen(config.c_str(), "r");
|
||||
|
||||
line = "";
|
||||
|
||||
@@ -261,67 +307,83 @@ void ClassFlowControll::InitFlow(std::string config)
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
}
|
||||
|
||||
std::string* ClassFlowControll::getActStatus(){
|
||||
|
||||
std::string* ClassFlowControll::getActStatus()
|
||||
{
|
||||
return &aktstatus;
|
||||
}
|
||||
|
||||
void ClassFlowControll::doFlowMakeImageOnly(string time){
|
||||
|
||||
void ClassFlowControll::setActStatus(std::string _aktstatus)
|
||||
{
|
||||
aktstatus = _aktstatus;
|
||||
}
|
||||
|
||||
|
||||
void ClassFlowControll::doFlowMakeImageOnly(string time)
|
||||
{
|
||||
std::string zw_time;
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
{
|
||||
if (FlowControll[i]->name() == "ClassFlowMakeImage") {
|
||||
// zw_time = gettimestring("%Y%m%d-%H%M%S");
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
FlowControll[i]->doFlow(time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::doFlow(string time)
|
||||
{
|
||||
// CleanTempFolder(); // dazu muss man noch eine Rolling einführen
|
||||
|
||||
bool result = true;
|
||||
std::string zw_time;
|
||||
int repeat = 0;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow - Start");
|
||||
#endif
|
||||
|
||||
/* Check if we have a valid date/time and if not restart the NTP client */
|
||||
if (! getTimeIsSet()) {
|
||||
/* if (! getTimeIsSet()) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Time not set, restarting NTP Client!");
|
||||
restartNtpClient();
|
||||
}
|
||||
}*/
|
||||
|
||||
//checkNtpStatus(0);
|
||||
|
||||
for (int i = 0; i < FlowControll.size(); ++i)
|
||||
{
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = TranslateAktstatus(FlowControll[i]->name());
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
//LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatus);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
|
||||
LogFile.WriteHeapInfo(zw);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
string zw = "FlowControll.doFlow - " + FlowControll[i]->name();
|
||||
LogFile.WriteHeapInfo(zw);
|
||||
#endif
|
||||
|
||||
if (!FlowControll[i]->doFlow(time)){
|
||||
repeat++;
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Fehler im vorheriger Schritt - wird zum " + to_string(repeat) + ". Mal wiederholt");
|
||||
if (i) i -= 1; // vorheriger Schritt muss wiederholt werden (vermutlich Bilder aufnehmen)
|
||||
if (i) i -= 1; // vPrevious step must be repeated (probably take pictures)
|
||||
result = false;
|
||||
if (repeat > 5) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Wiederholung 5x nicht erfolgreich --> reboot");
|
||||
doReboot();
|
||||
// Schritt wurde 5x wiederholt --> reboot
|
||||
//Step was repeated 5x --> reboot
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -329,15 +391,19 @@ bool ClassFlowControll::doFlow(string time)
|
||||
result = true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::doFlow");
|
||||
#endif
|
||||
}
|
||||
zw_time = gettimestring("%H:%M:%S");
|
||||
|
||||
zw_time = getCurrentTimeString("%H:%M:%S");
|
||||
std::string flowStatus = "Flow finished";
|
||||
aktstatus = flowStatus + " (" + zw_time + ")";
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
//LogFile.WriteToFile(ESP_LOG_INFO, TAG, aktstatus);
|
||||
#ifdef ENABLE_MQTT
|
||||
MQTTPublish(mqttServer_getMainTopic() + "/" + "status", flowStatus, false);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -407,6 +473,7 @@ string ClassFlowControll::getReadout(bool _rawvalue = false, bool _noerror = fal
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowControll::GetPrevalue(std::string _number)
|
||||
{
|
||||
if (flowpostprocessing)
|
||||
@@ -417,6 +484,7 @@ string ClassFlowControll::GetPrevalue(std::string _number)
|
||||
return std::string("");
|
||||
}
|
||||
|
||||
|
||||
std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern)
|
||||
{
|
||||
float zw;
|
||||
@@ -446,9 +514,10 @@ std::string ClassFlowControll::UpdatePrevalue(std::string _newvalue, std::string
|
||||
return std::string();
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -463,23 +532,23 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph, " =");
|
||||
if ((toUpper(zerlegt[0]) == "AUTOSTART") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph, " =");
|
||||
if ((toUpper(splitted[0]) == "AUTOSTART") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
AutoStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "INTERVALL") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "INTERVALL") && (splitted.size() > 1))
|
||||
{
|
||||
AutoIntervall = std::stof(zerlegt[1]);
|
||||
AutoIntervall = std::stof(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGACTIVE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "DATALOGACTIVE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
LogFile.SetDataLogToSD(true);
|
||||
}
|
||||
@@ -488,53 +557,56 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "DATALOGRETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "DATALOGRETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
LogFile.SetDataLogRetention(std::stoi(zerlegt[1]));
|
||||
LogFile.SetDataLogRetention(std::stoi(splitted[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILE") && (splitted.size() > 1))
|
||||
{
|
||||
/* matches esp_log_level_t */
|
||||
if ((toUpper(zerlegt[1]) == "TRUE") || (toUpper(zerlegt[1]) == "2"))
|
||||
if ((toUpper(splitted[1]) == "TRUE") || (toUpper(splitted[1]) == "2"))
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_WARN);
|
||||
}
|
||||
else if ((toUpper(zerlegt[1]) == "FALSE") || (toUpper(zerlegt[1]) == "0") || (toUpper(zerlegt[1]) == "1"))
|
||||
else if ((toUpper(splitted[1]) == "FALSE") || (toUpper(splitted[1]) == "0") || (toUpper(splitted[1]) == "1"))
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_ERROR);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "3")
|
||||
else if (toUpper(splitted[1]) == "3")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_INFO);
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "4")
|
||||
else if (toUpper(splitted[1]) == "4")
|
||||
{
|
||||
LogFile.setLogLevel(ESP_LOG_DEBUG);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
LogFile.SetLogFileRetention(std::stoi(zerlegt[1]));
|
||||
LogFile.SetLogFileRetention(std::stoi(splitted[1]));
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "TIMEZONE") && (zerlegt.size() > 1))
|
||||
{
|
||||
string zw = "Set TimeZone: " + zerlegt[1];
|
||||
setTimeZone(zerlegt[1]);
|
||||
}
|
||||
/* TimeServer and TimeZone got already read from the config, see setupTime () */
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "TIMESERVER") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "RSSITHREASHOLD") && (splitted.size() > 1))
|
||||
{
|
||||
string zw = "Set TimeZone: " + zerlegt[1];
|
||||
reset_servername(zerlegt[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "HOSTNAME") && (zerlegt.size() > 1))
|
||||
{
|
||||
if (ChangeHostName("/sdcard/wlan.ini", zerlegt[1]))
|
||||
if (ChangeRSSIThreashold(WLAN_CONFIG_FILE, atoi(splitted[1].c_str())))
|
||||
{
|
||||
// reboot notwendig damit die neue wlan.ini auch benutzt wird !!!
|
||||
// reboot necessary so that the new wlan.ini is also used !!!
|
||||
fclose(pfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new RSSITHREASHOLD ...");
|
||||
esp_restart();
|
||||
hard_restart();
|
||||
doReboot();
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(splitted[0]) == "HOSTNAME") && (splitted.size() > 1))
|
||||
{
|
||||
if (ChangeHostName(WLAN_CONFIG_FILE, splitted[1]))
|
||||
{
|
||||
// reboot necessary so that the new wlan.ini is also used !!!
|
||||
fclose(pfile);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Rebooting to activate new HOSTNAME...");
|
||||
esp_restart();
|
||||
@@ -543,20 +615,14 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SETUPMODE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SETUPMODE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
SetupModeActive = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@@ -564,10 +630,10 @@ bool ClassFlowControll::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
int ClassFlowControll::CleanTempFolder() {
|
||||
const char* folderPath = "/sdcard/img_tmp";
|
||||
|
||||
ESP_LOGD(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);
|
||||
ESP_LOGE(TAG, "Failed to stat dir: %s", folderPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -579,7 +645,7 @@ int ClassFlowControll::CleanTempFolder() {
|
||||
if (unlink(path.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "can't delete file : %s", path.c_str());
|
||||
ESP_LOGE(TAG, "can't delete file: %s", path.c_str());
|
||||
}
|
||||
} else if (entry->d_type == DT_DIR) {
|
||||
deleted += removeFolder(path.c_str(), TAG);
|
||||
@@ -602,90 +668,228 @@ esp_err_t ClassFlowControll::GetJPGStream(std::string _fn, httpd_req_t *req)
|
||||
{
|
||||
ESP_LOGD(TAG, "ClassFlowControll::GetJPGStream %s", _fn.c_str());
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - Start");
|
||||
#endif
|
||||
|
||||
CImageBasis *_send = NULL;
|
||||
esp_err_t result = ESP_FAIL;
|
||||
bool Dodelete = false;
|
||||
bool _sendDelete = false;
|
||||
|
||||
if (flowalignment == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "Can't continue, flowalignment is NULL");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (_fn == "alg.jpg")
|
||||
{
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_fn == "alg_roi.jpg")
|
||||
{
|
||||
CImageBasis* _imgzw = new CImageBasis(flowalignment->ImageBasis);
|
||||
flowalignment->DrawRef(_imgzw);
|
||||
if (flowdigit) flowdigit->DrawROI(_imgzw);
|
||||
if (flowanalog) flowanalog->DrawROI(_imgzw);
|
||||
_send = _imgzw;
|
||||
Dodelete = true;
|
||||
if (_fn == "alg.jpg") {
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<HTMLInfo*> htmlinfo;
|
||||
htmlinfo = GetAllDigital();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllDigital");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
if (!_send)
|
||||
{
|
||||
htmlinfo = GetAllAnalog();
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg.jpg cannot be served");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
else if (_fn == "alg_roi.jpg") {
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG // no CImageBasis needed to create alg_roi.jpg (ca. 790kB less RAM)
|
||||
if (aktstatus.find("Initialization (delayed)") != -1) {
|
||||
FILE* file = fopen("/sdcard/html/Flowstate_initialization_delayed.jpg", "rb");
|
||||
|
||||
if (!file) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/Flowstate_initialization_delayed.jpg not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long fileSize = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
unsigned char* fileBuffer = (unsigned char*) malloc(fileSize);
|
||||
|
||||
if (!fileBuffer) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(fileBuffer, fileSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)fileBuffer, fileSize);
|
||||
delete fileBuffer;
|
||||
}
|
||||
else if (aktstatus.find("Initialization") != -1) {
|
||||
FILE* file = fopen("/sdcard/html/Flowstate_initialization.jpg", "rb");
|
||||
|
||||
if (!file) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/Flowstate_initialization.jpg not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
long fileSize = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
unsigned char* fileBuffer = (unsigned char*) malloc(fileSize);
|
||||
|
||||
if (!fileBuffer) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create fileBuffer: " + std::to_string(fileSize));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(fileBuffer, fileSize, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)fileBuffer, fileSize);
|
||||
delete fileBuffer;
|
||||
}
|
||||
else if (aktstatus.find("Take Image") != -1) {
|
||||
if (flowalignment && flowalignment->AlgROI) {
|
||||
FILE* file = fopen("/sdcard/html/Flowstate_take_image.jpg", "rb");
|
||||
|
||||
if (!file) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/Flowstate_take_image.jpg not found");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fseek(file, 0, SEEK_END);
|
||||
flowalignment->AlgROI->size = ftell(file); /* how long is the file ? */
|
||||
fseek(file, 0, SEEK_SET); /* reset */
|
||||
|
||||
if (flowalignment->AlgROI->size > MAX_JPG_SIZE) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "File /sdcard/html/Flowstate_take_image.jpg too large: " + std::to_string(flowalignment->AlgROI->size));
|
||||
fclose(file);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
fread(flowalignment->AlgROI->data, flowalignment->AlgROI->size, 1, file);
|
||||
fclose(file);
|
||||
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served!");
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (flowalignment && flowalignment->AlgROI) {
|
||||
httpd_resp_set_type(req, "image/jpeg");
|
||||
result = httpd_resp_send(req, (const char *)flowalignment->AlgROI->data, flowalignment->AlgROI->size);
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "ClassFlowControll::GetJPGStream: alg_roi.jpg cannot be served -> alg.jpg is going to be served!");
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (!flowalignment) {
|
||||
ESP_LOGD(TAG, "ClassFloDControll::GetJPGStream: FlowAlignment is not (yet) initialized. Interrupt serving!");
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
_send = new CImageBasis(flowalignment->ImageBasis);
|
||||
|
||||
if (_send->ImageOkay()) {
|
||||
if (flowalignment) flowalignment->DrawRef(_send);
|
||||
if (flowdigit) flowdigit->DrawROI(_send);
|
||||
if (flowanalog) flowanalog->DrawROI(_send);
|
||||
_sendDelete = true; // delete temporary _send element after sending
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "ClassFlowControll::GetJPGStream: Not enough memory to create alg_roi.jpg -> alg.jpg is going to be served!");
|
||||
|
||||
if (flowalignment && flowalignment->ImageBasis->ImageOkay()) {
|
||||
_send = flowalignment->ImageBasis;
|
||||
}
|
||||
else {
|
||||
httpd_resp_send(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
std::vector<HTMLInfo*> htmlinfo;
|
||||
|
||||
htmlinfo = GetAllDigital();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllDigital");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
|
||||
if (!_send)
|
||||
{
|
||||
htmlinfo = GetAllAnalog();
|
||||
ESP_LOGD(TAG, "After getClassFlowControll::GetAllAnalog");
|
||||
|
||||
for (int i = 0; i < htmlinfo.size(); ++i)
|
||||
{
|
||||
if (_fn == htmlinfo[i]->filename)
|
||||
{
|
||||
if (htmlinfo[i]->image)
|
||||
_send = htmlinfo[i]->image;
|
||||
}
|
||||
|
||||
if (_fn == htmlinfo[i]->filename_org)
|
||||
{
|
||||
if (htmlinfo[i]->image_org)
|
||||
_send = htmlinfo[i]->image_org;
|
||||
}
|
||||
delete htmlinfo[i];
|
||||
}
|
||||
htmlinfo.clear();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - before send");
|
||||
#endif
|
||||
|
||||
if (_send)
|
||||
{
|
||||
ESP_LOGD(TAG, "Sending file : %s ...", _fn.c_str());
|
||||
ESP_LOGD(TAG, "Sending file: %s ...", _fn.c_str());
|
||||
set_content_type_from_file(req, _fn.c_str());
|
||||
result = _send->SendJPGtoHTTP(req);
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
ESP_LOGD(TAG, "File sending complete");
|
||||
|
||||
if (_sendDelete)
|
||||
delete _send;
|
||||
|
||||
_send = NULL;
|
||||
}
|
||||
|
||||
if (Dodelete)
|
||||
{
|
||||
delete _send;
|
||||
}
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowControll::GetJPGStream - done");
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -696,7 +900,8 @@ string ClassFlowControll::getNumbersName()
|
||||
return flowpostprocessing->getNumbersName();
|
||||
}
|
||||
|
||||
string ClassFlowControll::getJSON(std::string _id, std::string _mac)
|
||||
|
||||
string ClassFlowControll::getJSON()
|
||||
{
|
||||
return flowpostprocessing->GetJSON(_id, _mac);
|
||||
return flowpostprocessing->GetJSON();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __FLOWCONTROLL__
|
||||
#define __FLOWCONTROLL__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWCONTROLL_H
|
||||
#define CLASSFLOWCONTROLL_H
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -8,18 +10,15 @@
|
||||
#include "ClassFlowAlignment.h"
|
||||
#include "ClassFlowCNNGeneral.h"
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
#include "ClassFlowMQTT.h"
|
||||
#include "ClassFlowInfluxDB.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "ClassFlowMQTT.h"
|
||||
#endif //ENABLE_MQTT
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#include "ClassFlowInfluxDB.h"
|
||||
#endif //ENABLE_INFLUXDB
|
||||
#include "ClassFlowCNNGeneral.h"
|
||||
#include "ClassFlowWriteList.h"
|
||||
|
||||
|
||||
#define READOUT_TYPE_VALUE 0
|
||||
#define READOUT_TYPE_PREVALUE 1
|
||||
#define READOUT_TYPE_RAWVALUE 2
|
||||
#define READOUT_TYPE_ERROR 3
|
||||
|
||||
|
||||
class ClassFlowControll :
|
||||
public ClassFlow
|
||||
{
|
||||
@@ -50,12 +49,19 @@ public:
|
||||
string UpdatePrevalue(std::string _newvalue, std::string _numbers, bool _extern);
|
||||
string GetPrevalue(std::string _number = "");
|
||||
bool ReadParameter(FILE* pfile, string& aktparamgraph);
|
||||
string getJSON(std::string _id = "", std::string _mac = "");
|
||||
string getJSON();
|
||||
string getNumbersName();
|
||||
|
||||
string TranslateAktstatus(std::string _input);
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
string GetMQTTMainTopic();
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#ifdef ALGROI_LOAD_FROM_MEM_AS_JPG
|
||||
void DigitalDrawROI(CImageBasis *_zw);
|
||||
void AnalogDrawROI(CImageBasis *_zw);
|
||||
#endif
|
||||
|
||||
esp_err_t GetJPGStream(std::string _fn, httpd_req_t *req);
|
||||
esp_err_t SendRawJPG(httpd_req_t *req);
|
||||
@@ -65,12 +71,17 @@ public:
|
||||
bool isAutoStart(long &_intervall);
|
||||
|
||||
std::string* getActStatus();
|
||||
void setActStatus(std::string _aktstatus);
|
||||
|
||||
std::vector<HTMLInfo*> GetAllDigital();
|
||||
std::vector<HTMLInfo*> GetAllAnalog();
|
||||
|
||||
t_CNNType GetTypeDigital();
|
||||
t_CNNType GetTypeAnalog();
|
||||
|
||||
#ifdef ENABLE_MQTT
|
||||
bool StartMQTTService();
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
int CleanTempFolder();
|
||||
|
||||
@@ -80,3 +91,4 @@ public:
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CLASSFLOWIMAGE_CLASS__
|
||||
#define __CLASSFLOWIMAGE_CLASS__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWDEFINETYPES_H
|
||||
#define CLASSFLOWDEFINETYPES_H
|
||||
|
||||
#include "ClassFlowImage.h"
|
||||
|
||||
@@ -33,20 +35,20 @@ struct NumberPost {
|
||||
bool checkDigitIncreaseConsistency;
|
||||
time_t lastvalue;
|
||||
string timeStamp;
|
||||
double FlowRateAct; // m3 / min
|
||||
double PreValue; // letzter Wert, der gut ausgelesen wurde
|
||||
double Value; // letzer ausgelesener Wert, inkl. Korrekturen
|
||||
string ReturnRateValue; // RückgabewertRate
|
||||
string ReturnChangeAbsolute; // RückgabewertRate
|
||||
string ReturnRawValue; // Rohwert (mit N & führenden 0)
|
||||
string ReturnValue; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
string ReturnPreValue; // korrigierter Rückgabewert ohne Fehlermeldung
|
||||
string ErrorMessageText; // Fehlermeldung bei Consistency Check
|
||||
double FlowRateAct; // m3 / min
|
||||
double PreValue; // last value that was read out well
|
||||
double Value; // last value read out, incl. corrections
|
||||
string ReturnRateValue; // return value rate
|
||||
string ReturnChangeAbsolute; // return value rate
|
||||
string ReturnRawValue; // Raw value (with N & leading 0)
|
||||
string ReturnValue; // corrected return value, if necessary with error message
|
||||
string ReturnPreValue; // corrected return value without error message
|
||||
string ErrorMessageText; // Error message for consistency check
|
||||
int AnzahlAnalog;
|
||||
int AnzahlDigital;
|
||||
int DecimalShift;
|
||||
int DecimalShiftInitial;
|
||||
float AnalogDigitalTransitionStart; // Wann ist das digit > x.1, also wann fängt es an zu kippen
|
||||
float AnalogDigitalTransitionStart; // When is the digit > x.1, i.e. when does it start to tilt?
|
||||
int Nachkomma;
|
||||
|
||||
bool isExtendedResolution;
|
||||
|
||||
@@ -15,8 +15,9 @@ extern "C" {
|
||||
#include "ClassLogFile.h"
|
||||
#include "CImageBasis.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "FLOW IMG";
|
||||
static const char* TAG = "IMG";
|
||||
|
||||
ClassFlowImage::ClassFlowImage(const char* logTag)
|
||||
{
|
||||
@@ -93,7 +94,7 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
if (!isLogImage)
|
||||
return;
|
||||
|
||||
ESP_LOGI(TAG, "remove old images");
|
||||
ESP_LOGD(TAG, "remove old images");
|
||||
if (logfileRetentionInDays == 0) {
|
||||
return;
|
||||
}
|
||||
@@ -113,7 +114,7 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
|
||||
DIR *dir = opendir(LogImageLocation.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", LogImageLocation.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir: %s", LogImageLocation.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -132,7 +133,7 @@ void ClassFlowImage::RemoveOldLogs()
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "Image folder deleted: %d | Image folder not deleted: %d", deleted, notDeleted);
|
||||
ESP_LOGD(TAG, "Image folder deleted: %d | Image folder not deleted: %d", deleted, notDeleted);
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFLOWIMAGE_H
|
||||
#define CLASSFLOWIMAGE_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
using namespace std;
|
||||
@@ -22,3 +26,5 @@ public:
|
||||
|
||||
void RemoveOldLogs();
|
||||
};
|
||||
|
||||
#endif //CLASSFLOWIMAGE_H
|
||||
@@ -1,3 +1,4 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#include <sstream>
|
||||
#include "ClassFlowInfluxDB.h"
|
||||
#include "Helper.h"
|
||||
@@ -5,8 +6,10 @@
|
||||
|
||||
#include "time_sntp.h"
|
||||
#include "interface_influxdb.h"
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -66,7 +69,7 @@ ClassFlowInfluxDB::ClassFlowInfluxDB(std::vector<ClassFlow*>* lfc, ClassFlow *_p
|
||||
|
||||
bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -80,26 +83,26 @@ bool ClassFlowInfluxDB::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
ESP_LOGD(TAG, "while loop reading line: %s", aktparamgraph.c_str());
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
this->user = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "PASSWORD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
|
||||
{
|
||||
this->password = zerlegt[1];
|
||||
this->password = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "URI") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
|
||||
{
|
||||
this->uri = zerlegt[1];
|
||||
this->uri = splitted[1];
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "MEASUREMENT")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "MEASUREMENT")) && (splitted.size() > 1))
|
||||
{
|
||||
this->measurement = zerlegt[1];
|
||||
this->measurement = splitted[1];
|
||||
}
|
||||
if (((toUpper(zerlegt[0]) == "DATABASE")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "DATABASE")) && (splitted.size() > 1))
|
||||
{
|
||||
this->database = zerlegt[1];
|
||||
this->database = splitted[1];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,3 +165,5 @@ bool ClassFlowInfluxDB::doFlow(string zwtime)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif //ENABLE_INFLUXDB
|
||||
@@ -1,4 +1,10 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFINFLUXDB_H
|
||||
#define CLASSFINFLUXDB_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
@@ -29,3 +35,5 @@ public:
|
||||
string name(){return "ClassFlowInfluxDB";};
|
||||
};
|
||||
|
||||
#endif //CLASSFINFLUXDB_H
|
||||
#endif //ENABLE_INFLUXDB
|
||||
@@ -1,3 +1,5 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include "ClassFlowMQTT.h"
|
||||
@@ -13,14 +15,9 @@
|
||||
#include "server_mqtt.h"
|
||||
|
||||
#include <time.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
static const char *TAG = "FLOW MQTT";
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
static const char *TAG = "MQTT";
|
||||
|
||||
extern const char* libfive_git_version(void);
|
||||
extern const char* libfive_git_revision(void);
|
||||
@@ -90,7 +87,7 @@ ClassFlowMQTT::ClassFlowMQTT(std::vector<ClassFlow*>* lfc, ClassFlow *_prev)
|
||||
|
||||
bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -98,76 +95,76 @@ bool ClassFlowMQTT::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((toUpper(splitted[0]) == "USER") && (splitted.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
this->user = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "PASSWORD") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "PASSWORD") && (splitted.size() > 1))
|
||||
{
|
||||
this->password = zerlegt[1];
|
||||
this->password = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "URI") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "URI") && (splitted.size() > 1))
|
||||
{
|
||||
this->uri = zerlegt[1];
|
||||
this->uri = splitted[1];
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "SETRETAINFLAG") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SETRETAINFLAG") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE") {
|
||||
if (toUpper(splitted[1]) == "TRUE") {
|
||||
SetRetainFlag = 1;
|
||||
setMqtt_Server_Retain(SetRetainFlag);
|
||||
}
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "HOMEASSISTANTDISCOVERY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "HOMEASSISTANTDISCOVERY") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SetHomeassistantDiscoveryEnabled(true);
|
||||
}
|
||||
if ((toUpper(zerlegt[0]) == "METERTYPE") && (zerlegt.size() > 1)) {
|
||||
if ((toUpper(splitted[0]) == "METERTYPE") && (splitted.size() > 1)) {
|
||||
/* Use meter type for the device class
|
||||
Make sure it is a listed one on https://developers.home-assistant.io/docs/core/entity/sensor/#available-device-classes */
|
||||
if (toUpper(zerlegt[1]) == "WATER_M3") {
|
||||
if (toUpper(splitted[1]) == "WATER_M3") {
|
||||
mqttServer_setMeterType("water", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_L") {
|
||||
else if (toUpper(splitted[1]) == "WATER_L") {
|
||||
mqttServer_setMeterType("water", "L", "h", "L/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_FT3") {
|
||||
else if (toUpper(splitted[1]) == "WATER_FT3") {
|
||||
mqttServer_setMeterType("water", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "WATER_GAL") {
|
||||
else if (toUpper(splitted[1]) == "WATER_GAL") {
|
||||
mqttServer_setMeterType("water", "gal", "h", "gal/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_M3") {
|
||||
else if (toUpper(splitted[1]) == "GAS_M3") {
|
||||
mqttServer_setMeterType("gas", "m³", "h", "m³/h");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "GAS_FT3") {
|
||||
else if (toUpper(splitted[1]) == "GAS_FT3") {
|
||||
mqttServer_setMeterType("gas", "ft³", "m", "ft³/m"); // Minutes
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_WH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_WH") {
|
||||
mqttServer_setMeterType("energy", "Wh", "h", "W");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_KWH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_KWH") {
|
||||
mqttServer_setMeterType("energy", "kWh", "h", "kW");
|
||||
}
|
||||
else if (toUpper(zerlegt[1]) == "ENERGY_MWH") {
|
||||
else if (toUpper(splitted[1]) == "ENERGY_MWH") {
|
||||
mqttServer_setMeterType("energy", "MWh", "h", "MW");
|
||||
}
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CLIENTID") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CLIENTID") && (splitted.size() > 1))
|
||||
{
|
||||
this->clientname = zerlegt[1];
|
||||
this->clientname = splitted[1];
|
||||
}
|
||||
|
||||
if (((toUpper(zerlegt[0]) == "TOPIC") || (toUpper(zerlegt[0]) == "MAINTOPIC")) && (zerlegt.size() > 1))
|
||||
if (((toUpper(splitted[0]) == "TOPIC") || (toUpper(splitted[0]) == "MAINTOPIC")) && (splitted.size() > 1))
|
||||
{
|
||||
maintopic = zerlegt[1];
|
||||
maintopic = splitted[1];
|
||||
mqttServer_setMainTopic(maintopic);
|
||||
}
|
||||
}
|
||||
@@ -187,28 +184,26 @@ string ClassFlowMQTT::GetMQTTMainTopic()
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMQTT::Start(float AutoIntervall) {
|
||||
|
||||
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());
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, 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);
|
||||
bool MQTTConfigCheck = 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;
|
||||
}
|
||||
if (!MQTTConfigCheck) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return (MQTT_Init() == 1);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,6 +212,7 @@ bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
std::string result;
|
||||
std::string resulterror = "";
|
||||
std::string resultraw = "";
|
||||
std::string resultpre = "";
|
||||
std::string resultrate = ""; // Always Unit / Minute
|
||||
std::string resultRatePerTimeUnit = ""; // According to selection
|
||||
std::string resulttimestamp = "";
|
||||
@@ -226,16 +222,17 @@ bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
|
||||
publishSystemData();
|
||||
|
||||
if (flowpostprocessing)
|
||||
if (flowpostprocessing && getMQTTisConnected())
|
||||
{
|
||||
std::vector<NumberPost*>* NUMBERS = flowpostprocessing->GetNumbers();
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing MQTT topics...");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing MQTT topics...");
|
||||
|
||||
for (int i = 0; i < (*NUMBERS).size(); ++i)
|
||||
{
|
||||
result = (*NUMBERS)[i]->ReturnValue;
|
||||
resultraw = (*NUMBERS)[i]->ReturnRawValue;
|
||||
resultpre = (*NUMBERS)[i]->ReturnPreValue;
|
||||
resulterror = (*NUMBERS)[i]->ErrorMessageText;
|
||||
resultrate = (*NUMBERS)[i]->ReturnRateValue; // Unit per minutes
|
||||
resultchangabs = (*NUMBERS)[i]->ReturnChangeAbsolute; // Units per round
|
||||
@@ -278,43 +275,32 @@ bool ClassFlowMQTT::doFlow(string zwtime)
|
||||
if (resulttimestamp.length() > 0)
|
||||
MQTTPublish(namenumber + "timestamp", resulttimestamp, SetRetainFlag);
|
||||
|
||||
std::string json = "";
|
||||
|
||||
if (result.length() > 0)
|
||||
json += "{\"value\":"+result;
|
||||
else
|
||||
json += "{\"value\":\"\"";
|
||||
|
||||
json += ",\"raw\":\""+resultraw;
|
||||
json += "\",\"error\":\""+resulterror;
|
||||
|
||||
if (resultrate.length() > 0)
|
||||
json += "\",\"rate\":"+resultrate;
|
||||
else
|
||||
json += "\",\"rate\":\"\"";
|
||||
|
||||
json += ",\"timestamp\":\""+resulttimestamp+"\"}";
|
||||
|
||||
std::string json = flowpostprocessing->getJsonFromNumber(i, "\n");
|
||||
MQTTPublish(namenumber + "json", json, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < ListFlowControll->size(); ++i)
|
||||
{
|
||||
zw = (*ListFlowControll)[i]->getReadout();
|
||||
if (zw.length() > 0)
|
||||
{
|
||||
if (result.length() == 0)
|
||||
result = zw;
|
||||
else
|
||||
result = result + "\t" + zw;
|
||||
}
|
||||
}
|
||||
MQTTPublish(topic, result, SetRetainFlag);
|
||||
}
|
||||
|
||||
/* Disabled because this is no longer a use case */
|
||||
// else
|
||||
// {
|
||||
// for (int i = 0; i < ListFlowControll->size(); ++i)
|
||||
// {
|
||||
// zw = (*ListFlowControll)[i]->getReadout();
|
||||
// if (zw.length() > 0)
|
||||
// {
|
||||
// if (result.length() == 0)
|
||||
// result = zw;
|
||||
// else
|
||||
// result = result + "\t" + zw;
|
||||
// }
|
||||
// }
|
||||
// MQTTPublish(topic, result, SetRetainFlag);
|
||||
// }
|
||||
|
||||
OldValue = result;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -1,4 +1,10 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWMQTT_H
|
||||
#define CLASSFFLOWMQTT_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
@@ -32,4 +38,5 @@ public:
|
||||
bool doFlow(string time);
|
||||
string name(){return "ClassFlowMQTT";};
|
||||
};
|
||||
|
||||
#endif //CLASSFFLOWMQTT_H
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -25,14 +26,14 @@ esp_err_t ClassFlowMakeImage::camera_capture(){
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void ClassFlowMakeImage::takePictureWithFlash(int flashdauer)
|
||||
void ClassFlowMakeImage::takePictureWithFlash(int flash_duration)
|
||||
{
|
||||
// für den Fall, dass das Bild geflippt wird, muss es hier zurück gesetzt werden ////
|
||||
// in case the image is flipped, it must be reset here //
|
||||
rawImage->width = image_width;
|
||||
rawImage->height = image_height;
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
ESP_LOGD(TAG, "Flashdauer: %d", flashdauer);
|
||||
Camera.CaptureToBasisImage(rawImage, flashdauer);
|
||||
ESP_LOGD(TAG, "flash_duration: %d", flash_duration);
|
||||
Camera.CaptureToBasisImage(rawImage, flash_duration);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
@@ -51,7 +52,7 @@ void ClassFlowMakeImage::SetInitialParameter(void)
|
||||
SaveAllFiles = false;
|
||||
disabled = false;
|
||||
FixedExposure = false;
|
||||
namerawimage = "/sdcard/img_tmp/raw.jpg";
|
||||
namerawimage = "/sdcard/img_tmp/raw.jpg";
|
||||
}
|
||||
|
||||
|
||||
@@ -62,9 +63,10 @@ ClassFlowMakeImage::ClassFlowMakeImage(std::vector<ClassFlow*>* lfc) : ClassFlow
|
||||
SetInitialParameter();
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
int _brightness = -100;
|
||||
@@ -75,70 +77,76 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (aktparamgraph.compare("[MakeImage]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[MakeImage]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
if ((zerlegt[0] == "LogImageLocation") && (zerlegt.size() > 1))
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
if ((splitted[0] == "LogImageLocation") && (splitted.size() > 1))
|
||||
{
|
||||
LogImageLocation = "/sdcard" + zerlegt[1];
|
||||
LogImageLocation = "/sdcard" + splitted[1];
|
||||
isLogImage = true;
|
||||
}
|
||||
if ((zerlegt[0] == "ImageQuality") && (zerlegt.size() > 1))
|
||||
ImageQuality = std::stod(zerlegt[1]);
|
||||
if ((splitted[0] == "ImageQuality") && (splitted.size() > 1))
|
||||
ImageQuality = std::stod(splitted[1]);
|
||||
|
||||
if ((zerlegt[0] == "ImageSize") && (zerlegt.size() > 1))
|
||||
if ((splitted[0] == "ImageSize") && (splitted.size() > 1))
|
||||
{
|
||||
ImageSize = Camera.TextToFramesize(zerlegt[1].c_str());
|
||||
ImageSize = Camera.TextToFramesize(splitted[1].c_str());
|
||||
isImageSize = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SAVEALLFILES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SAVEALLFILES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
SaveAllFiles = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "WAITBEFORETAKINGPICTURE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "WAITBEFORETAKINGPICTURE") && (splitted.size() > 1))
|
||||
{
|
||||
waitbeforepicture = stoi(zerlegt[1]);
|
||||
waitbeforepicture = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LOGFILERETENTIONINDAYS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LOGFILERETENTIONINDAYS") && (splitted.size() > 1))
|
||||
{
|
||||
this->logfileRetentionInDays = std::stoi(zerlegt[1]);
|
||||
this->logfileRetentionInDays = std::stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "BRIGHTNESS") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "BRIGHTNESS") && (splitted.size() > 1))
|
||||
{
|
||||
_brightness = stoi(zerlegt[1]);
|
||||
_brightness = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "CONTRAST") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "CONTRAST") && (splitted.size() > 1))
|
||||
{
|
||||
_contrast = stoi(zerlegt[1]);
|
||||
_contrast = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "SATURATION") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "SATURATION") && (splitted.size() > 1))
|
||||
{
|
||||
_saturation = stoi(zerlegt[1]);
|
||||
_saturation = stoi(splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "FIXEDEXPOSURE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "FIXEDEXPOSURE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
FixedExposure = true;
|
||||
}
|
||||
|
||||
if ((toUpper(zerlegt[0]) == "LEDINTENSITY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(splitted[0]) == "LEDINTENSITY") && (splitted.size() > 1))
|
||||
{
|
||||
float ledintensity = stof(zerlegt[1]);
|
||||
float ledintensity = stof(splitted[1]);
|
||||
ledintensity = min((float) 100, ledintensity);
|
||||
ledintensity = max((float) 0, ledintensity);
|
||||
Camera.SetLEDIntensity(ledintensity);
|
||||
}
|
||||
|
||||
if ((toUpper(splitted[0]) == "DEMO") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
Camera.useDemoMode();
|
||||
}
|
||||
}
|
||||
|
||||
Camera.SetBrightnessContrastSaturation(_brightness, _contrast, _saturation);
|
||||
@@ -153,17 +161,18 @@ bool ClassFlowMakeImage::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (FixedExposure && (waitbeforepicture > 0))
|
||||
{
|
||||
// ESP_LOGD(TAG, "Fixed Exposure enabled!");
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
Camera.EnableAutoExposure(flashdauer);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
Camera.EnableAutoExposure(flash_duration);
|
||||
waitbeforepicture = 0.2;
|
||||
// flashdauer = (int) (waitbeforepicture * 1000);
|
||||
// takePictureWithFlash(flashdauer);
|
||||
// flash_duration = (int) (waitbeforepicture * 1000);
|
||||
// takePictureWithFlash(flash_duration);
|
||||
// rawImage->SaveToFile("/sdcard/init2.jpg");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowMakeImage::getHTMLSingleStep(string host)
|
||||
{
|
||||
string result;
|
||||
@@ -171,50 +180,52 @@ string ClassFlowMakeImage::getHTMLSingleStep(string host)
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
bool ClassFlowMakeImage::doFlow(string zwtime)
|
||||
{
|
||||
string logPath = CreateLogFolder(zwtime);
|
||||
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - Before takePictureWithFlash");
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_stop(); // to save power usage and
|
||||
#endif
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_stop(); // to save power usage and
|
||||
#endif
|
||||
|
||||
takePictureWithFlash(flashdauer);
|
||||
takePictureWithFlash(flash_duration);
|
||||
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_start();
|
||||
#endif
|
||||
#ifdef WIFITURNOFF
|
||||
esp_wifi_start();
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After takePictureWithFlash");
|
||||
#endif
|
||||
|
||||
LogImage(logPath, "raw", NULL, NULL, zwtime, rawImage);
|
||||
|
||||
RemoveOldLogs();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("ClassFlowMakeImage::doFlow - After RemoveOldLogs");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t ClassFlowMakeImage::SendRawJPG(httpd_req_t *req)
|
||||
{
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
return Camera.CaptureToHTTP(req, flashdauer);
|
||||
return Camera.CaptureToHTTP(req, flash_duration);
|
||||
}
|
||||
|
||||
|
||||
@@ -222,8 +233,8 @@ ImageData* ClassFlowMakeImage::SendRawImage()
|
||||
{
|
||||
CImageBasis *zw = new CImageBasis(rawImage);
|
||||
ImageData *id;
|
||||
int flashdauer = (int) (waitbeforepicture * 1000);
|
||||
Camera.CaptureToBasisImage(zw, flashdauer);
|
||||
int flash_duration = (int) (waitbeforepicture * 1000);
|
||||
Camera.CaptureToBasisImage(zw, flash_duration);
|
||||
time(&TimeImageTaken);
|
||||
localtime(&TimeImageTaken);
|
||||
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWMAKEIMAGE_H
|
||||
#define CLASSFFLOWMAKEIMAGE_H
|
||||
|
||||
#include "ClassFlowImage.h"
|
||||
#include "ClassControllCamera.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_4
|
||||
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
|
||||
|
||||
|
||||
class ClassFlowMakeImage :
|
||||
public ClassFlowImage
|
||||
{
|
||||
@@ -30,7 +29,7 @@ protected:
|
||||
void CopyFile(string input, string output);
|
||||
|
||||
esp_err_t camera_capture();
|
||||
void takePictureWithFlash(int flashdauer);
|
||||
void takePictureWithFlash(int flash_duration);
|
||||
|
||||
|
||||
void SetInitialParameter(void);
|
||||
@@ -53,3 +52,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif //CLASSFFLOWMAKEIMAGE_H
|
||||
@@ -11,15 +11,9 @@
|
||||
#include "time_sntp.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.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%z"
|
||||
#define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
|
||||
|
||||
static const char* TAG = "POSTPROC";
|
||||
|
||||
std::string ClassFlowPostProcessing::getNumbersName()
|
||||
{
|
||||
@@ -37,42 +31,51 @@ std::string ClassFlowPostProcessing::getNumbersName()
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string ClassFlowPostProcessing::GetJSON(std::string _id, std::string _mac, std::string _lineend)
|
||||
std::string ClassFlowPostProcessing::GetJSON(std::string _lineend)
|
||||
{
|
||||
std::string json="{" + _lineend;
|
||||
|
||||
for (int i = 0; i < NUMBERS.size(); ++i)
|
||||
{
|
||||
json += "\"" + NUMBERS[i]->name + "\":" + _lineend;
|
||||
json += " {" + _lineend;
|
||||
|
||||
if (_id.length() > 0)
|
||||
json += " \"ID\": \"" + _id + "\"," + _lineend;
|
||||
if (_mac.length() > 0)
|
||||
json += " \"MAC\": \"" + _mac + "\"," + _lineend;
|
||||
json += getJsonFromNumber(i, _lineend) + _lineend;
|
||||
|
||||
if (NUMBERS[i]->ReturnValue.length() > 0)
|
||||
json += " \"value\": \"" + NUMBERS[i]->ReturnValue + "\"," + _lineend;
|
||||
else
|
||||
json += " \"value\": \"\"," + _lineend;
|
||||
json += " \"raw\": \"" + NUMBERS[i]->ReturnRawValue + "\"," + _lineend;
|
||||
json += " \"error\": \"" + NUMBERS[i]->ErrorMessageText + "\"," + _lineend;
|
||||
if (NUMBERS[i]->ReturnRateValue.length() > 0)
|
||||
json += " \"rate\": " + NUMBERS[i]->ReturnRateValue + "," + _lineend;
|
||||
else
|
||||
json += " \"rate\": \"\"," + _lineend;
|
||||
|
||||
json += " \"timestamp\": \"" + NUMBERS[i]->timeStamp + "\"" + _lineend;
|
||||
if ((i+1) < NUMBERS.size())
|
||||
json += " }," + _lineend;
|
||||
else
|
||||
json += " }" + _lineend;
|
||||
json += "," + _lineend;
|
||||
}
|
||||
json += "}";
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowPostProcessing::getJsonFromNumber(int i, std::string _lineend) {
|
||||
std::string json = "";
|
||||
|
||||
json += " {" + _lineend;
|
||||
|
||||
if (NUMBERS[i]->ReturnValue.length() > 0)
|
||||
json += " \"value\": \"" + NUMBERS[i]->ReturnValue + "\"," + _lineend;
|
||||
else
|
||||
json += " \"value\": \"\"," + _lineend;
|
||||
|
||||
json += " \"raw\": \"" + NUMBERS[i]->ReturnRawValue + "\"," + _lineend;
|
||||
json += " \"pre\": \"" + NUMBERS[i]->ReturnPreValue + "\"," + _lineend;
|
||||
json += " \"error\": \"" + NUMBERS[i]->ErrorMessageText + "\"," + _lineend;
|
||||
|
||||
if (NUMBERS[i]->ReturnRateValue.length() > 0)
|
||||
json += " \"rate\": \"" + NUMBERS[i]->ReturnRateValue + "\"," + _lineend;
|
||||
else
|
||||
json += " \"rate\": \"\"," + _lineend;
|
||||
|
||||
json += " \"timestamp\": \"" + NUMBERS[i]->timeStamp + "\"" + _lineend;
|
||||
json += " }" + _lineend;
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
string ClassFlowPostProcessing::GetPreValue(std::string _number)
|
||||
{
|
||||
std::string result;
|
||||
@@ -119,13 +122,13 @@ void ClassFlowPostProcessing::SetPreValue(double zw, string _numbers, bool _exte
|
||||
|
||||
bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
FILE* pFile;
|
||||
char zw[1024];
|
||||
string zwtime, zwvalue, name;
|
||||
bool _done = false;
|
||||
|
||||
UpdatePreValueINI = false; // Konvertierung ins neue Format
|
||||
UpdatePreValueINI = false; // Conversion to the new format
|
||||
|
||||
|
||||
pFile = fopen(FilePreValue.c_str(), "r");
|
||||
@@ -138,21 +141,21 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
if (zwtime.length() == 0)
|
||||
return false;
|
||||
|
||||
zerlegt = HelperZerlegeZeile(zwtime, "\t");
|
||||
if (zerlegt.size() > 1) // neues Format
|
||||
splitted = HelperZerlegeZeile(zwtime, "\t");
|
||||
if (splitted.size() > 1) // Conversion to the new format
|
||||
{
|
||||
while ((zerlegt.size() > 1) && !_done)
|
||||
while ((splitted.size() > 1) && !_done)
|
||||
{
|
||||
name = trim(zerlegt[0]);
|
||||
zwtime = trim(zerlegt[1]);
|
||||
zwvalue = trim(zerlegt[2]);
|
||||
name = trim(splitted[0]);
|
||||
zwtime = trim(splitted[1]);
|
||||
zwvalue = trim(splitted[2]);
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
if (NUMBERS[j]->name == name)
|
||||
{
|
||||
NUMBERS[j]->PreValue = stod(zwvalue.c_str());
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // SIcherheitshalber 1 Stelle mehr, da ggf. Exgtended Resolution an ist (wird erst beim ersten Durchlauf gesetzt)
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma + 1); // To be on the safe side, 1 digit more, as Exgtended Resolution may be on (will only be set during the first run).
|
||||
|
||||
time_t tStart;
|
||||
int yy, month, dd, hh, mm, ss;
|
||||
@@ -185,18 +188,18 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
else
|
||||
{
|
||||
ESP_LOGD(TAG, "Read line Prevalue.ini: %s", zw);
|
||||
zerlegt = HelperZerlegeZeile(trim(std::string(zw)), "\t");
|
||||
if (zerlegt.size() > 1)
|
||||
splitted = HelperZerlegeZeile(trim(std::string(zw)), "\t");
|
||||
if (splitted.size() > 1)
|
||||
{
|
||||
name = trim(zerlegt[0]);
|
||||
zwtime = trim(zerlegt[1]);
|
||||
zwvalue = trim(zerlegt[2]);
|
||||
name = trim(splitted[0]);
|
||||
zwtime = trim(splitted[1]);
|
||||
zwvalue = trim(splitted[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(pFile);
|
||||
}
|
||||
else // altes Format
|
||||
else // Old Format
|
||||
{
|
||||
fgets(zw, 1024, pFile);
|
||||
fclose(pFile);
|
||||
@@ -236,7 +239,7 @@ bool ClassFlowPostProcessing::LoadPreValue(void)
|
||||
NUMBERS[0]->ReturnValue = RundeOutput(NUMBERS[0]->Value, NUMBERS[0]->Nachkomma);
|
||||
}
|
||||
|
||||
UpdatePreValueINI = true; // Konvertierung ins neue Format
|
||||
UpdatePreValueINI = true; // Conversion to the new format
|
||||
SavePreValue();
|
||||
}
|
||||
|
||||
@@ -248,7 +251,7 @@ void ClassFlowPostProcessing::SavePreValue()
|
||||
FILE* pFile;
|
||||
string _zw;
|
||||
|
||||
if (!UpdatePreValueINI) // PreValues unverändert --> File muss nicht neu geschrieben werden
|
||||
if (!UpdatePreValueINI) // PreValues unchanged --> File does not have to be rewritten
|
||||
return;
|
||||
|
||||
pFile = fopen(FilePreValue.c_str(), "w");
|
||||
@@ -262,7 +265,7 @@ void ClassFlowPostProcessing::SavePreValue()
|
||||
// ESP_LOGD(TAG, "SaverPreValue %d, Value: %f, Nachkomma %d", j, NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
|
||||
_zw = NUMBERS[j]->name + "\t" + NUMBERS[j]->timeStamp + "\t" + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + "\n";
|
||||
ESP_LOGD(TAG, "Write PreValue Zeile: %s", _zw.c_str());
|
||||
ESP_LOGD(TAG, "Write PreValue line: %s", _zw.c_str());
|
||||
if (pFile) {
|
||||
fputs(_zw.c_str(), pFile);
|
||||
}
|
||||
@@ -314,7 +317,7 @@ void ClassFlowPostProcessing::handleDecimalExtendedResolution(string _decsep, st
|
||||
if (toUpper(_value) == "TRUE")
|
||||
_zwdc = true;
|
||||
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->isExtendedResolution = _zwdc;
|
||||
}
|
||||
@@ -350,7 +353,7 @@ void ClassFlowPostProcessing::handleDecimalSeparator(string _decsep, string _val
|
||||
ESP_LOGD(TAG, "ERROR - Decimalshift is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->DecimalShift = _zwdc;
|
||||
NUMBERS[j]->DecimalShiftInitial = _zwdc;
|
||||
@@ -382,7 +385,7 @@ void ClassFlowPostProcessing::handleAnalogDigitalTransitionStart(string _decsep,
|
||||
{
|
||||
_zwdc = stof(_value);
|
||||
}
|
||||
if (_digit == "default" || NUMBERS[j]->name == _digit) // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default" || NUMBERS[j]->name == _digit) // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->AnalogDigitalTransitionStart = _zwdc;
|
||||
|
||||
@@ -390,6 +393,36 @@ void ClassFlowPostProcessing::handleAnalogDigitalTransitionStart(string _decsep,
|
||||
}
|
||||
}
|
||||
|
||||
void ClassFlowPostProcessing::handleAllowNegativeRate(string _decsep, string _value)
|
||||
{
|
||||
string _digit, _decpos;
|
||||
int _pospunkt = _decsep.find_first_of(".");
|
||||
// ESP_LOGD(TAG, "Name: %s, Pospunkt: %d", _decsep.c_str(), _pospunkt);
|
||||
if (_pospunkt > -1)
|
||||
_digit = _decsep.substr(0, _pospunkt);
|
||||
else
|
||||
_digit = "default";
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
bool _rt = false;
|
||||
|
||||
if (toUpper(_value) == "TRUE")
|
||||
_rt = true;
|
||||
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->AllowNegativeRates = _rt;
|
||||
}
|
||||
|
||||
if (NUMBERS[j]->name == _digit)
|
||||
{
|
||||
NUMBERS[j]->AllowNegativeRates = _rt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
{
|
||||
@@ -408,7 +441,7 @@ void ClassFlowPostProcessing::handleMaxRateType(string _decsep, string _value)
|
||||
if (toUpper(_value) == "RATECHANGE")
|
||||
_rt = RateChange;
|
||||
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->RateType = _rt;
|
||||
}
|
||||
@@ -444,7 +477,7 @@ void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
|
||||
ESP_LOGD(TAG, "ERROR - MaxRateValue is not a number: %s", _value.c_str());
|
||||
}
|
||||
*/
|
||||
if (_digit == "default") // erstmal auf default setzen (falls sonst nichts gesetzt)
|
||||
if (_digit == "default") // Set to default first (if nothing else is set)
|
||||
{
|
||||
NUMBERS[j]->useMaxRateValue = true;
|
||||
NUMBERS[j]->MaxRateValue = _zwdc;
|
||||
@@ -460,7 +493,7 @@ void ClassFlowPostProcessing::handleMaxRateValue(string _decsep, string _value)
|
||||
|
||||
bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
int _n;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
@@ -470,7 +503,7 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
return false;
|
||||
|
||||
|
||||
if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (aktparamgraph.compare("[PostProcessing]") != 0) // Paragraph does not fit MakeImage
|
||||
return false;
|
||||
|
||||
InitNUMBERS();
|
||||
@@ -478,65 +511,68 @@ bool ClassFlowPostProcessing::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
std::string _param = GetParameterName(zerlegt[0]);
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
std::string _param = GetParameterName(splitted[0]);
|
||||
|
||||
if ((toUpper(_param) == "EXTENDEDRESOLUTION") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "EXTENDEDRESOLUTION") && (splitted.size() > 1))
|
||||
{
|
||||
handleDecimalExtendedResolution(zerlegt[0], zerlegt[1]);
|
||||
handleDecimalExtendedResolution(splitted[0], splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(_param) == "DECIMALSHIFT") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "DECIMALSHIFT") && (splitted.size() > 1))
|
||||
{
|
||||
handleDecimalSeparator(zerlegt[0], zerlegt[1]);
|
||||
handleDecimalSeparator(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "ANALOGDIGITALTRANSITIONSTART") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ANALOGDIGITALTRANSITIONSTART") && (splitted.size() > 1))
|
||||
{
|
||||
handleAnalogDigitalTransitionStart(zerlegt[0], zerlegt[1]);
|
||||
handleAnalogDigitalTransitionStart(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "MAXRATEVALUE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "MAXRATEVALUE") && (splitted.size() > 1))
|
||||
{
|
||||
handleMaxRateValue(zerlegt[0], zerlegt[1]);
|
||||
handleMaxRateValue(splitted[0], splitted[1]);
|
||||
}
|
||||
if ((toUpper(_param) == "MAXRATETYPE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "MAXRATETYPE") && (splitted.size() > 1))
|
||||
{
|
||||
handleMaxRateType(zerlegt[0], zerlegt[1]);
|
||||
handleMaxRateType(splitted[0], splitted[1]);
|
||||
}
|
||||
|
||||
if ((toUpper(_param) == "PREVALUEUSE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "PREVALUEUSE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
{
|
||||
PreValueUse = true;
|
||||
}
|
||||
}
|
||||
if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "CHECKDIGITINCREASECONSISTENCY") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
for (_n = 0; _n < NUMBERS.size(); ++_n)
|
||||
NUMBERS[_n]->checkDigitIncreaseConsistency = true;
|
||||
}
|
||||
if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ALLOWNEGATIVERATES") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
handleAllowNegativeRate(splitted[0], splitted[1]);
|
||||
/* Updated to allow individual Settings
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
for (_n = 0; _n < NUMBERS.size(); ++_n)
|
||||
NUMBERS[_n]->AllowNegativeRates = true;
|
||||
*/
|
||||
}
|
||||
if ((toUpper(_param) == "ERRORMESSAGE") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "ERRORMESSAGE") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
ErrorMessage = true;
|
||||
}
|
||||
if ((toUpper(_param) == "IGNORELEADINGNAN") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "IGNORELEADINGNAN") && (splitted.size() > 1))
|
||||
{
|
||||
if (toUpper(zerlegt[1]) == "TRUE")
|
||||
if (toUpper(splitted[1]) == "TRUE")
|
||||
IgnoreLeadingNaN = true;
|
||||
}
|
||||
|
||||
|
||||
if ((toUpper(_param) == "PREVALUEAGESTARTUP") && (zerlegt.size() > 1))
|
||||
if ((toUpper(_param) == "PREVALUEAGESTARTUP") && (splitted.size() > 1))
|
||||
{
|
||||
PreValueAgeStartup = std::stoi(zerlegt[1]);
|
||||
PreValueAgeStartup = std::stoi(splitted[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,12 +591,12 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
|
||||
if (flowDigit)
|
||||
{
|
||||
anzDIGIT = flowDigit->getAnzahlGENERAL();
|
||||
anzDIGIT = flowDigit->getNumberGENERAL();
|
||||
flowDigit->UpdateNameNumbers(&name_numbers);
|
||||
}
|
||||
if (flowAnalog)
|
||||
{
|
||||
anzANALOG = flowAnalog->getAnzahlGENERAL();
|
||||
anzANALOG = flowAnalog->getNumberGENERAL();
|
||||
flowAnalog->UpdateNameNumbers(&name_numbers);
|
||||
}
|
||||
|
||||
@@ -591,9 +627,9 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
else
|
||||
_number->AnzahlAnalog = 0;
|
||||
|
||||
_number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0)
|
||||
_number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
_number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check
|
||||
_number->ReturnRawValue = ""; // Raw value (with N & leading 0).
|
||||
_number->ReturnValue = ""; // corrected return value, possibly with error message
|
||||
_number->ErrorMessageText = ""; // Error message for consistency check
|
||||
_number->ReturnPreValue = "";
|
||||
_number->PreValueOkay = false;
|
||||
_number->AllowNegativeRates = false;
|
||||
@@ -607,12 +643,12 @@ void ClassFlowPostProcessing::InitNUMBERS()
|
||||
_number->AnalogDigitalTransitionStart=9.2;
|
||||
|
||||
|
||||
_number->FlowRateAct = 0; // m3 / min
|
||||
_number->PreValue = 0; // letzter Wert, der gut ausgelesen wurde
|
||||
_number->Value = 0; // letzer ausgelesener Wert, inkl. Korrekturen
|
||||
_number->ReturnRawValue = ""; // Rohwert (mit N & führenden 0)
|
||||
_number->ReturnValue = ""; // korrigierter Rückgabewert, ggf. mit Fehlermeldung
|
||||
_number->ErrorMessageText = ""; // Fehlermeldung bei Consistency Check
|
||||
_number->FlowRateAct = 0; // m3 / min
|
||||
_number->PreValue = 0; // last value read out well
|
||||
_number->Value = 0; // last value read out, incl. corrections
|
||||
_number->ReturnRawValue = ""; // raw value (with N & leading 0)
|
||||
_number->ReturnValue = ""; // corrected return value, possibly with error message
|
||||
_number->ErrorMessageText = ""; // Error message for consistency check
|
||||
|
||||
_number->Nachkomma = _number->AnzahlAnalog;
|
||||
|
||||
@@ -644,7 +680,7 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
|
||||
|
||||
_pos_dec_neu = _pos_dec_org + _decShift;
|
||||
|
||||
if (_pos_dec_neu <= 0) { // Komma ist vor der ersten Ziffer
|
||||
if (_pos_dec_neu <= 0) { // comma is before the first digit
|
||||
for (int i = 0; i > _pos_dec_neu; --i){
|
||||
in = in.insert(0, "0");
|
||||
}
|
||||
@@ -652,7 +688,7 @@ string ClassFlowPostProcessing::ShiftDecimal(string in, int _decShift){
|
||||
return in;
|
||||
}
|
||||
|
||||
if (_pos_dec_neu > in.length()){ // Komma soll hinter String (123 --> 1230)
|
||||
if (_pos_dec_neu > in.length()){ // Comma should be after string (123 --> 1230)
|
||||
for (int i = in.length(); i < _pos_dec_neu; ++i){
|
||||
in = in.insert(in.length(), "0");
|
||||
}
|
||||
@@ -677,7 +713,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
time_t imagetime = 0;
|
||||
string rohwert;
|
||||
|
||||
// Update Nachkomma, da sich beim Wechsel von CNNType Auto --> xyz auch die Nachkommastellen ändern können:
|
||||
// Update decimal point, as the decimal places can also change when changing from CNNType Auto --> xyz:
|
||||
|
||||
imagetime = flowMakeImage->getTimeImageTaken();
|
||||
if (imagetime == 0)
|
||||
@@ -689,7 +725,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
zwtime = std::string(strftime_buf);
|
||||
|
||||
ESP_LOGD(TAG, "Anzahl NUMBERS: %d", NUMBERS.size());
|
||||
ESP_LOGD(TAG, "Quantity NUMBERS: %d", NUMBERS.size());
|
||||
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
@@ -699,6 +735,13 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ErrorMessageText = "";
|
||||
NUMBERS[j]->Value = -1;
|
||||
|
||||
/* calculate time difference BEFORE we overwrite the 'lastvalue' */
|
||||
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in seconds
|
||||
|
||||
/* TODO:
|
||||
* We could call `NUMBERS[j]->lastvalue = imagetime;` here and remove all other such calls further down.
|
||||
* But we should check nothing breaks! */
|
||||
|
||||
UpdateNachkommaDecimalShift();
|
||||
|
||||
int previous_value = -1;
|
||||
@@ -724,7 +767,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
if (NUMBERS[j]->analog_roi)
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, false, previous_value, NUMBERS[j]->analog_roi->ROI[0]->result_float, NUMBERS[j]->AnalogDigitalTransitionStart) + NUMBERS[j]->ReturnRawValue;
|
||||
else
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution nur falls es keine analogen Ziffern gibt
|
||||
NUMBERS[j]->ReturnRawValue = flowDigit->getReadout(j, NUMBERS[j]->isExtendedResolution, previous_value); // Extended Resolution only if there are no analogue digits
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After digital->getReadout: ReturnRaw %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
@@ -752,14 +795,19 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
}
|
||||
else
|
||||
{
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
/* TODO to be discussed, see https://github.com/jomjol/AI-on-the-edge-device/issues/1617 */
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
WriteDataLog(j);
|
||||
continue; // es gibt keinen Zahl, da noch ein N vorhanden ist.
|
||||
continue; // there is no number because there is still an N.
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After findDelimiterPos: ReturnValue %s", NUMBERS[j]->ReturnRawValue.c_str());
|
||||
#endif
|
||||
// Lösche führende Nullen (außer es ist nur noch einen 0)
|
||||
// Delete leading zeros (unless there is only one 0 left)
|
||||
while ((NUMBERS[j]->ReturnValue.length() > 1) && (NUMBERS[j]->ReturnValue[0] == '0'))
|
||||
NUMBERS[j]->ReturnValue.erase(0, 1);
|
||||
#ifdef SERIAL_DEBUG
|
||||
@@ -790,7 +838,6 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After checkDigitIncreaseConsistency: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
|
||||
|
||||
if (!NUMBERS[j]->AllowNegativeRates)
|
||||
{
|
||||
@@ -801,7 +848,7 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))
|
||||
) ;
|
||||
#endif
|
||||
// Bei isExtendedResolution Ungenauigkeit von 0.2 mit einrechnen.
|
||||
// Include inaccuracy of 0.2 for isExtendedResolution.
|
||||
if (NUMBERS[j]->Value >= (NUMBERS[j]->PreValue-(2/pow(10, NUMBERS[j]->Nachkomma))) && NUMBERS[j]->isExtendedResolution) {
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = to_string(NUMBERS[j]->PreValue);
|
||||
@@ -809,16 +856,21 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Neg. Rate - Read: " + zwvalue + " - Raw: " + NUMBERS[j]->ReturnRawValue + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " ";
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After AllowNegativeRates: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
double difference = difftime(imagetime, NUMBERS[j]->lastvalue); // in Sekunden
|
||||
|
||||
difference /= 60;
|
||||
NUMBERS[j]->FlowRateAct = (NUMBERS[j]->Value - NUMBERS[j]->PreValue) / difference;
|
||||
NUMBERS[j]->ReturnRateValue = to_string(NUMBERS[j]->FlowRateAct);
|
||||
@@ -833,22 +885,27 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
|
||||
if (abs(_ratedifference) > abs(NUMBERS[j]->MaxRateValue))
|
||||
{
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->ErrorMessageText = NUMBERS[j]->ErrorMessageText + "Rate too high - Read: " + RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma) + " - Pre: " + RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma) + " - Rate: " + RundeOutput(_ratedifference, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->Value = NUMBERS[j]->PreValue;
|
||||
NUMBERS[j]->ReturnValue = "";
|
||||
NUMBERS[j]->ReturnRateValue = "";
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef SERIAL_DEBUG
|
||||
ESP_LOGD(TAG, "After MaxRateCheck: Value %f", NUMBERS[j]->Value);
|
||||
#endif
|
||||
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
NUMBERS[j]->ReturnChangeAbsolute = RundeOutput(NUMBERS[j]->Value - NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->PreValue = NUMBERS[j]->Value;
|
||||
NUMBERS[j]->PreValueOkay = true;
|
||||
|
||||
NUMBERS[j]->lastvalue = imagetime;
|
||||
|
||||
NUMBERS[j]->ReturnValue = RundeOutput(NUMBERS[j]->Value, NUMBERS[j]->Nachkomma);
|
||||
NUMBERS[j]->ReturnPreValue = RundeOutput(NUMBERS[j]->PreValue, NUMBERS[j]->Nachkomma);
|
||||
@@ -856,9 +913,8 @@ bool ClassFlowPostProcessing::doFlow(string zwtime)
|
||||
NUMBERS[j]->ErrorMessageText = "no error";
|
||||
UpdatePreValueINI = true;
|
||||
|
||||
string _zw = "PostProcessing - Raw: " + NUMBERS[j]->ReturnRawValue + " Value: " + NUMBERS[j]->ReturnValue + " Error: " + NUMBERS[j]->ErrorMessageText;
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, _zw);
|
||||
string _zw = NUMBERS[j]->name + ": Raw: " + NUMBERS[j]->ReturnRawValue + ", Value: " + NUMBERS[j]->ReturnValue + ", Status: " + NUMBERS[j]->ErrorMessageText;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _zw);
|
||||
WriteDataLog(j);
|
||||
}
|
||||
|
||||
@@ -897,22 +953,22 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
{
|
||||
for (int j = 0; j < NUMBERS.size(); ++j)
|
||||
{
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi) // es gibt nur digitale ziffern
|
||||
if (NUMBERS[j]->digit_roi && !NUMBERS[j]->analog_roi) // There are only digital digits
|
||||
{
|
||||
// ESP_LOGD(TAG, "Nurdigital");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
|
||||
if (NUMBERS[j]->isExtendedResolution && flowDigit->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowDigit->isExtendedResolution()) // Extended resolution is on and should also be used for this digit.
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShift-1;
|
||||
|
||||
NUMBERS[j]->Nachkomma = -NUMBERS[j]->DecimalShift;
|
||||
}
|
||||
|
||||
if (!NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi) // es gibt nur analoge ziffern
|
||||
if (!NUMBERS[j]->digit_roi && NUMBERS[j]->analog_roi)
|
||||
{
|
||||
// ESP_LOGD(TAG, "Nur analog");
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution())
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShift-1;
|
||||
|
||||
NUMBERS[j]->Nachkomma = -NUMBERS[j]->DecimalShift;
|
||||
@@ -925,7 +981,7 @@ void ClassFlowPostProcessing::UpdateNachkommaDecimalShift()
|
||||
NUMBERS[j]->DecimalShift = NUMBERS[j]->DecimalShiftInitial;
|
||||
NUMBERS[j]->Nachkomma = NUMBERS[j]->analog_roi->ROI.size() - NUMBERS[j]->DecimalShift;
|
||||
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // extended resolution ist an und soll auch bei dieser Ziffer verwendet werden
|
||||
if (NUMBERS[j]->isExtendedResolution && flowAnalog->isExtendedResolution()) // Extended resolution is on and should also be used for this digit.
|
||||
NUMBERS[j]->Nachkomma = NUMBERS[j]->Nachkomma+1;
|
||||
|
||||
}
|
||||
@@ -989,7 +1045,7 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
bool no_nulldurchgang = false;
|
||||
|
||||
pot = _decilamshift;
|
||||
if (!_isanalog) // falls es keine analogwerte gibt, kann die letzte nicht bewertet werden
|
||||
if (!_isanalog) // if there are no analogue values, the last one cannot be evaluated
|
||||
{
|
||||
pot++;
|
||||
}
|
||||
@@ -1015,14 +1071,14 @@ float ClassFlowPostProcessing::checkDigitConsistency(double input, int _decilams
|
||||
{
|
||||
if (aktdigit != olddigit)
|
||||
{
|
||||
input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // Neue Digit wird durch alte Digit ersetzt;
|
||||
input = input + ((float) (olddigit - aktdigit)) * pow(10, pot); // New Digit is replaced by old Digit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (aktdigit == olddigit) // trotz Nulldurchgang wurde Stelle nicht hochgezählt --> addiere 1
|
||||
if (aktdigit == olddigit) // despite zero crossing, digit was not incremented --> add 1
|
||||
{
|
||||
input = input + ((float) (1)) * pow(10, pot); // addiere 1 an der Stelle
|
||||
input = input + ((float) (1)) * pow(10, pot); // add 1 at the point
|
||||
}
|
||||
}
|
||||
#ifdef SERIAL_DEBUG
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __FLOWPOSTPROCESSING__
|
||||
#define __FLOWPOSTPROCESSING__
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWPOSTPROCESSING_H
|
||||
#define CLASSFFLOWPOSTPROCESSING_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "ClassFlowMakeImage.h"
|
||||
@@ -18,7 +20,7 @@ protected:
|
||||
|
||||
int PreValueAgeStartup;
|
||||
bool ErrorMessage;
|
||||
bool IgnoreLeadingNaN; // SPEZIALFALL für User Gustl
|
||||
bool IgnoreLeadingNaN; // SPECIAL CASE for User Gustl ???
|
||||
|
||||
|
||||
ClassFlowCNNGeneral* flowAnalog;
|
||||
@@ -41,6 +43,8 @@ protected:
|
||||
void handleDecimalExtendedResolution(string _decsep, string _value);
|
||||
void handleMaxRateType(string _decsep, string _value);
|
||||
void handleAnalogDigitalTransitionStart(string _decsep, string _value);
|
||||
void handleAllowNegativeRate(string _decsep, string _value);
|
||||
|
||||
std::string GetStringReadouts(general);
|
||||
|
||||
void WriteDataLog(int _index);
|
||||
@@ -61,10 +65,11 @@ public:
|
||||
string getReadoutRate(int _number = 0);
|
||||
string getReadoutTimeStamp(int _number = 0);
|
||||
void SavePreValue();
|
||||
string getJsonFromNumber(int i, std::string _lineend);
|
||||
string GetPreValue(std::string _number = "");
|
||||
void SetPreValue(double zw, string _numbers, bool _extern = false);
|
||||
|
||||
std::string GetJSON(std::string _id = "", std::string _mac = "", std::string _lineend = "\n");
|
||||
std::string GetJSON(std::string _lineend = "\n");
|
||||
std::string getNumbersName();
|
||||
|
||||
void UpdateNachkommaDecimalShift();
|
||||
@@ -75,4 +80,4 @@ public:
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif //CLASSFFLOWPOSTPROCESSING_H
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "Helper.h"
|
||||
|
||||
#include "time_sntp.h"
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
@@ -37,7 +37,7 @@ ClassFlowWriteList::ClassFlowWriteList(std::vector<ClassFlow*>* lfc)
|
||||
|
||||
bool ClassFlowWriteList::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
{
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
aktparamgraph = trim(aktparamgraph);
|
||||
|
||||
@@ -45,18 +45,12 @@ bool ClassFlowWriteList::ReadParameter(FILE* pfile, string& aktparamgraph)
|
||||
if (!this->GetNextParagraph(pfile, aktparamgraph))
|
||||
return false;
|
||||
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0) // Paragraph passt nich zu MakeImage
|
||||
if (toUpper(aktparamgraph).compare("[MQTT]") != 0)
|
||||
return false;
|
||||
|
||||
while (this->getNextLine(pfile, &aktparamgraph) && !this->isNewParagraph(aktparamgraph))
|
||||
{
|
||||
zerlegt = ZerlegeZeile(aktparamgraph);
|
||||
/*
|
||||
if ((toUpper(zerlegt[0]) == "USER") && (zerlegt.size() > 1))
|
||||
{
|
||||
this->user = zerlegt[1];
|
||||
}
|
||||
*/
|
||||
splitted = ZerlegeZeile(aktparamgraph);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSFFLOWPWRITELIST_H
|
||||
#define CLASSFFLOWPWRITELIST_H
|
||||
|
||||
#include "ClassFlow.h"
|
||||
#include "ClassFlowPostProcessing.h"
|
||||
|
||||
@@ -20,3 +24,4 @@ public:
|
||||
string name(){return "ClassFlowWriteList";};
|
||||
};
|
||||
|
||||
#endif //CLASSFFLOWPWRITELIST_H
|
||||
@@ -1,101 +0,0 @@
|
||||
#ifndef CAMERADEFINED
|
||||
#define CAMERADEFINED
|
||||
|
||||
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM GPIO_NUM_32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM GPIO_NUM_0
|
||||
#define SIOD_GPIO_NUM GPIO_NUM_26
|
||||
#define SIOC_GPIO_NUM GPIO_NUM_27
|
||||
|
||||
#define Y9_GPIO_NUM GPIO_NUM_35
|
||||
#define Y8_GPIO_NUM GPIO_NUM_34
|
||||
#define Y7_GPIO_NUM GPIO_NUM_39
|
||||
#define Y6_GPIO_NUM GPIO_NUM_36
|
||||
#define Y5_GPIO_NUM GPIO_NUM_21
|
||||
#define Y4_GPIO_NUM GPIO_NUM_19
|
||||
#define Y3_GPIO_NUM GPIO_NUM_18
|
||||
#define Y2_GPIO_NUM GPIO_NUM_5
|
||||
#define VSYNC_GPIO_NUM GPIO_NUM_25
|
||||
#define HREF_GPIO_NUM GPIO_NUM_23
|
||||
#define PCLK_GPIO_NUM GPIO_NUM_22
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static camera_config_t camera_config = {
|
||||
.pin_pwdn = PWDN_GPIO_NUM,
|
||||
.pin_reset = RESET_GPIO_NUM,
|
||||
.pin_xclk = XCLK_GPIO_NUM,
|
||||
.pin_sscb_sda = SIOD_GPIO_NUM,
|
||||
.pin_sscb_scl = SIOC_GPIO_NUM,
|
||||
|
||||
.pin_d7 = Y9_GPIO_NUM,
|
||||
.pin_d6 = Y8_GPIO_NUM,
|
||||
.pin_d5 = Y7_GPIO_NUM,
|
||||
.pin_d4 = Y6_GPIO_NUM,
|
||||
.pin_d3 = Y5_GPIO_NUM,
|
||||
.pin_d2 = Y4_GPIO_NUM,
|
||||
.pin_d1 = Y3_GPIO_NUM,
|
||||
.pin_d0 = Y2_GPIO_NUM,
|
||||
.pin_vsync = VSYNC_GPIO_NUM,
|
||||
.pin_href = HREF_GPIO_NUM,
|
||||
.pin_pclk = PCLK_GPIO_NUM,
|
||||
|
||||
//XCLK 20MHz or 10MHz for OV2640 double FPS (Experimental)
|
||||
.xclk_freq_hz = 20000000,
|
||||
.ledc_timer = LEDC_TIMER_0,
|
||||
.ledc_channel = LEDC_CHANNEL_0,
|
||||
|
||||
.pixel_format = PIXFORMAT_JPEG,//YUV422,GRAYSCALE,RGB565,JPEG
|
||||
// .pixel_format = PIXFORMAT_RGB888,//YUV422,GRAYSCALE,RGB565,JPEG
|
||||
// .frame_size = FRAMESIZE_QVGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
|
||||
.frame_size = FRAMESIZE_SVGA,//QQVGA-QXGA Do not use sizes above QVGA when not JPEG
|
||||
|
||||
.jpeg_quality = 12, //0-63 lower number means higher quality
|
||||
.fb_count = 1 //if more than one, i2s runs in continuous mode. Use only with JPEG
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -22,6 +23,7 @@ extern "C" {
|
||||
|
||||
#include <string.h>
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
@@ -30,60 +32,66 @@ extern "C" {
|
||||
|
||||
static const char* TAG = "HELPER";
|
||||
|
||||
//#define ISWINDOWS_TRUE
|
||||
#define PATH_MAX_STRING_SIZE 256
|
||||
|
||||
using namespace std;
|
||||
|
||||
unsigned int systemStatus = 0;
|
||||
|
||||
sdmmc_cid_t SDCardCid;
|
||||
sdmmc_csd_t SDCardCsd;
|
||||
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
string getESPHeapInfo(){
|
||||
string espInfoResultStr = "";
|
||||
char aMsgBuf[80];
|
||||
|
||||
multi_heap_info_t aMultiHead_info ;
|
||||
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
|
||||
sprintf(aMsgBuf," Free Heap Size: %ld", (long) aFreeHeapSize);
|
||||
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
|
||||
sprintf(aMsgBuf," Heap: %ld", (long) aFreeHeapSize);
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
|
||||
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
|
||||
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
size_t aHeapIntLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
|
||||
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
|
||||
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
|
||||
|
||||
sprintf(aMsgBuf,"Heap Total: %ld", (long) aFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Min Free: %ld", (long) aMinFreeHeapSize);
|
||||
|
||||
sprintf(aMsgBuf," | SPI Free: %ld", (long) aFreeSPIHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," larg. Block: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf," | SPI Larg Block: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," SPI Heap: %ld", (long) aFreeSPIHeapSize);
|
||||
sprintf(aMsgBuf," | SPI Min Free: %ld", (long) aMinFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Min Free Heap Size: %ld", (long) aMinFreeHeadSize);
|
||||
sprintf(aMsgBuf," NOT_SPI Heap: %ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
|
||||
|
||||
sprintf(aMsgBuf," | Int Free: %ld", (long) (aFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," largest Block Size: %ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf," Internal Heap: %ld", (long) (aFreeInternalHeapSize));
|
||||
sprintf(aMsgBuf," | Int Larg Block: %ld", (long) aHeapIntLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf," Internal Min Heap free: %ld", (long) (aMinFreeInternalHeapSize));
|
||||
sprintf(aMsgBuf," | Int Min Free: %ld", (long) (aMinFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
|
||||
size_t getESPHeapSize(){
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
return aFreeHeapSize;
|
||||
size_t getESPHeapSize()
|
||||
{
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
}
|
||||
|
||||
size_t getInternalESPHeapSize() {
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
return aFreeInternalHeapSize;
|
||||
|
||||
size_t getInternalESPHeapSize()
|
||||
{
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardPartitionSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, tot_sect;
|
||||
@@ -97,6 +105,7 @@ string getSDCardPartitionSize(){
|
||||
return std::to_string(tot_sect);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardFreePartitionSpace(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, fre_sect;
|
||||
@@ -110,6 +119,7 @@ string getSDCardFreePartitionSpace(){
|
||||
return std::to_string(fre_sect);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardPartitionAllocationSize(){
|
||||
FATFS *fs;
|
||||
uint32_t fre_clust, allocation_size;
|
||||
@@ -129,6 +139,7 @@ void SaveSDCardInfo(sdmmc_card_t* card) {
|
||||
SDCardCsd = card->csd;
|
||||
}
|
||||
|
||||
|
||||
string getSDCardManufacturer(){
|
||||
string SDCardManufacturer = SDCardParseManufacturerIDs(SDCardCid.mfg_id);
|
||||
//ESP_LOGD(TAG, "SD Card Manufacturer: %s", SDCardManufacturer.c_str());
|
||||
@@ -136,6 +147,7 @@ string getSDCardManufacturer(){
|
||||
return (SDCardManufacturer + " (ID: " + std::to_string(SDCardCid.mfg_id) + ")");
|
||||
}
|
||||
|
||||
|
||||
string getSDCardName(){
|
||||
char *SDCardName = SDCardCid.name;
|
||||
//ESP_LOGD(TAG, "SD Card Name: %s", SDCardName);
|
||||
@@ -143,6 +155,7 @@ string getSDCardName(){
|
||||
return std::string(SDCardName);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardCapacity(){
|
||||
int SDCardCapacity = SDCardCsd.capacity / (1024/SDCardCsd.sector_size) / 1024; // total sectors * sector size --> Byte to MB (1024*1024)
|
||||
//ESP_LOGD(TAG, "SD Card Capacity: %s", std::to_string(SDCardCapacity).c_str());
|
||||
@@ -150,6 +163,7 @@ string getSDCardCapacity(){
|
||||
return std::to_string(SDCardCapacity);
|
||||
}
|
||||
|
||||
|
||||
string getSDCardSectorSize(){
|
||||
int SDCardSectorSize = SDCardCsd.sector_size;
|
||||
//ESP_LOGD(TAG, "SD Card Sector Size: %s bytes", std::to_string(SDCardSectorSize).c_str());
|
||||
@@ -166,24 +180,6 @@ void memCopyGen(uint8_t* _source, uint8_t* _target, int _size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec, bool silent)
|
||||
{
|
||||
FILE *pfile;
|
||||
|
||||
ESP_LOGD(TAG, "open file %s in mode %s", nm, _mode);
|
||||
|
||||
if ((pfile = fopen(nm, _mode)) != NULL) {
|
||||
if (!silent) ESP_LOGE(TAG, "File %s successfully opened", nm);
|
||||
}
|
||||
else {
|
||||
if (!silent) ESP_LOGE(TAG, "Error: file %s does not exist!", nm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pfile;
|
||||
}
|
||||
|
||||
std::string FormatFileName(std::string input)
|
||||
{
|
||||
#ifdef ISWINDOWS_TRUE
|
||||
@@ -227,6 +223,7 @@ void FindReplace(std::string& line, std::string& oldString, std::string& newStri
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool MakeDir(std::string _what)
|
||||
{
|
||||
int mk_ret = mkdir(_what.c_str(), 0775);
|
||||
@@ -239,7 +236,6 @@ bool MakeDir(std::string _what)
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool ctype_space(const char c, string adddelimiter)
|
||||
{
|
||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == 11)
|
||||
@@ -252,6 +248,7 @@ bool ctype_space(const char c, string adddelimiter)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
string trim(string istring, string adddelimiter)
|
||||
{
|
||||
bool trimmed = false;
|
||||
@@ -278,6 +275,7 @@ string trim(string istring, string adddelimiter)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
size_t findDelimiterPos(string input, string delimiter)
|
||||
{
|
||||
size_t pos = std::string::npos;
|
||||
@@ -304,9 +302,9 @@ size_t findDelimiterPos(string input, string delimiter)
|
||||
|
||||
bool RenameFile(string from, string to)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
|
||||
// ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(from.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(from.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGE(TAG, "DeleteFile: File %s existiert nicht!", from.c_str());
|
||||
@@ -319,11 +317,23 @@ bool RenameFile(string from, string to)
|
||||
}
|
||||
|
||||
|
||||
bool FileExists(string filename)
|
||||
{
|
||||
FILE* fpSourceFile = fopen(filename.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
return false;
|
||||
}
|
||||
fclose(fpSourceFile);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool DeleteFile(string fn)
|
||||
{
|
||||
// ESP_LOGI(logTag, "Deleting file : %s", fn.c_str());
|
||||
// ESP_LOGI(logTag, "Deleting file: %s", fn.c_str());
|
||||
/* Delete file */
|
||||
FILE* fpSourceFile = OpenFileAndWait(fn.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(fn.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGD(TAG, "DeleteFile: File %s existiert nicht!", fn.c_str());
|
||||
@@ -341,21 +351,21 @@ bool CopyFile(string input, string output)
|
||||
input = FormatFileName(input);
|
||||
output = FormatFileName(output);
|
||||
|
||||
if (toUpper(input).compare("/SDCARD/WLAN.INI") == 0)
|
||||
if (toUpper(input).compare(WLAN_CONFIG_FILE) == 0)
|
||||
{
|
||||
ESP_LOGD(TAG, "wlan.ini kann nicht kopiert werden!");
|
||||
return false;
|
||||
}
|
||||
|
||||
char cTemp;
|
||||
FILE* fpSourceFile = OpenFileAndWait(input.c_str(), "rb");
|
||||
FILE* fpSourceFile = fopen(input.c_str(), "rb");
|
||||
if (!fpSourceFile) // Sourcefile existiert nicht sonst gibt es einen Fehler beim Kopierversuch!
|
||||
{
|
||||
ESP_LOGD(TAG, "File %s existiert nicht!", input.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
FILE* fpTargetFile = OpenFileAndWait(output.c_str(), "wb");
|
||||
FILE* fpTargetFile = fopen(output.c_str(), "wb");
|
||||
|
||||
// Code Section
|
||||
|
||||
@@ -373,6 +383,7 @@ bool CopyFile(string input, string output)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
string getFileFullFileName(string filename)
|
||||
{
|
||||
size_t lastpos = filename.find_last_of('/');
|
||||
@@ -387,6 +398,7 @@ string getFileFullFileName(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
string getDirectory(string filename)
|
||||
{
|
||||
size_t lastpos = filename.find('/');
|
||||
@@ -403,6 +415,7 @@ string getDirectory(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
string getFileType(string filename)
|
||||
{
|
||||
size_t lastpos = filename.rfind(".", filename.length());
|
||||
@@ -421,16 +434,17 @@ string getFileType(string filename)
|
||||
return zw;
|
||||
}
|
||||
|
||||
|
||||
/* recursive mkdir */
|
||||
int mkdir_r(const char *dir, const mode_t mode) {
|
||||
char tmp[PATH_MAX_STRING_SIZE];
|
||||
char tmp[FILE_PATH_MAX];
|
||||
char *p = NULL;
|
||||
struct stat sb;
|
||||
size_t len;
|
||||
|
||||
/* copy path */
|
||||
len = strnlen (dir, PATH_MAX_STRING_SIZE);
|
||||
if (len == 0 || len == PATH_MAX_STRING_SIZE) {
|
||||
len = strnlen (dir, FILE_PATH_MAX);
|
||||
if (len == 0 || len == FILE_PATH_MAX) {
|
||||
return -1;
|
||||
}
|
||||
memcpy (tmp, dir, len);
|
||||
@@ -478,6 +492,7 @@ int mkdir_r(const char *dir, const mode_t mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
string toUpper(string in)
|
||||
{
|
||||
for (int i = 0; i < in.length(); ++i)
|
||||
@@ -486,6 +501,7 @@ string toUpper(string in)
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
string toLower(string in)
|
||||
{
|
||||
for (int i = 0; i < in.length(); ++i)
|
||||
@@ -494,6 +510,7 @@ string toLower(string in)
|
||||
return in;
|
||||
}
|
||||
|
||||
|
||||
// CPU Temp
|
||||
extern "C" uint8_t temprature_sens_read();
|
||||
float temperatureRead()
|
||||
@@ -501,18 +518,20 @@ float temperatureRead()
|
||||
return (temprature_sens_read() - 32) / 1.8;
|
||||
}
|
||||
|
||||
|
||||
time_t addDays(time_t startTime, int days) {
|
||||
struct tm* tm = localtime(&startTime);
|
||||
tm->tm_mday += days;
|
||||
return mktime(tm);
|
||||
}
|
||||
|
||||
|
||||
int removeFolder(const char* folderPath, const char* logTag) {
|
||||
//ESP_LOGD(logTag, "Delete content in path %s", folderPath);
|
||||
|
||||
DIR *dir = opendir(folderPath);
|
||||
if (!dir) {
|
||||
ESP_LOGE(logTag, "Failed to stat dir : %s", folderPath);
|
||||
ESP_LOGE(logTag, "Failed to stat dir: %s", folderPath);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -525,7 +544,7 @@ int removeFolder(const char* folderPath, const char* logTag) {
|
||||
if (unlink(path.c_str()) == 0) {
|
||||
deleted ++;
|
||||
} else {
|
||||
ESP_LOGE(logTag, "can't delete file : %s", path.c_str());
|
||||
ESP_LOGE(logTag, "can't delete file: %s", path.c_str());
|
||||
}
|
||||
} else if (entry->d_type == DT_DIR) {
|
||||
deleted += removeFolder(path.c_str(), logTag);
|
||||
@@ -534,7 +553,7 @@ int removeFolder(const char* folderPath, const char* logTag) {
|
||||
|
||||
closedir(dir);
|
||||
if (rmdir(folderPath) != 0) {
|
||||
ESP_LOGE(logTag, "can't delete folder : %s", folderPath);
|
||||
ESP_LOGE(logTag, "can't delete folder: %s", folderPath);
|
||||
}
|
||||
ESP_LOGD(logTag, "%d files in folder %s deleted.", deleted, folderPath);
|
||||
|
||||
@@ -554,7 +573,6 @@ std::vector<string> HelperZerlegeZeile(std::string input, std::string _delimiter
|
||||
}
|
||||
|
||||
|
||||
|
||||
std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
|
||||
{
|
||||
std::vector<string> Output;
|
||||
@@ -599,6 +617,17 @@ std::vector<string> ZerlegeZeile(std::string input, std::string delimiter)
|
||||
}
|
||||
|
||||
|
||||
std::string ReplaceString(std::string subject, const std::string& search,
|
||||
const std::string& replace) {
|
||||
size_t pos = 0;
|
||||
while ((pos = subject.find(search, pos)) != std::string::npos) {
|
||||
subject.replace(pos, search.length(), replace);
|
||||
pos += replace.length();
|
||||
}
|
||||
return subject;
|
||||
}
|
||||
|
||||
|
||||
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
|
||||
/* SD Card Manufacturer Database */
|
||||
struct SDCard_Manufacturer_database {
|
||||
@@ -607,6 +636,7 @@ struct SDCard_Manufacturer_database {
|
||||
string manufacturer;
|
||||
};
|
||||
|
||||
|
||||
/* Source: https://git.kernel.org/pub/scm/utils/mmc/mmc-utils.git/tree/lsmmc.c */
|
||||
/* SD Card Manufacturer Database */
|
||||
struct SDCard_Manufacturer_database database[] = {
|
||||
@@ -717,6 +747,7 @@ struct SDCard_Manufacturer_database database[] = {
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Parse SD Card Manufacturer Database */
|
||||
string SDCardParseManufacturerIDs(int id)
|
||||
{
|
||||
@@ -770,11 +801,52 @@ string getMac(void) {
|
||||
return macFormated;
|
||||
}
|
||||
|
||||
|
||||
void setSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
systemStatus = systemStatus | flag; // set bit
|
||||
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
|
||||
}
|
||||
|
||||
|
||||
void clearSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
systemStatus = systemStatus | ~flag; // clear bit
|
||||
|
||||
char buf[20];
|
||||
snprintf(buf, sizeof(buf), "0x%08X", getSystemStatus());
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "New System Status: " + std::string(buf));
|
||||
}
|
||||
|
||||
|
||||
int getSystemStatus(void) {
|
||||
return systemStatus;
|
||||
}
|
||||
|
||||
|
||||
bool isSetSystemStatusFlag(SystemStatusFlag_t flag) {
|
||||
//ESP_LOGE(TAG, "Flag (0x%08X) is set (0x%08X): %d", flag, systemStatus , ((systemStatus & flag) == flag));
|
||||
|
||||
if ((systemStatus & flag) == flag) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
time_t getUpTime(void) {
|
||||
return (uint32_t)(esp_timer_get_time()/1000/1000); // in seconds
|
||||
}
|
||||
|
||||
|
||||
string getResetReason(void) {
|
||||
std::string reasonText;
|
||||
|
||||
switch(esp_reset_reason()) {
|
||||
case ESP_RST_POWERON: reasonText = "Power-on event"; break; //!< Reset due to power-on event
|
||||
case ESP_RST_POWERON: reasonText = "Power-on event (or reset button)"; break; //!< Reset due to power-on event
|
||||
case ESP_RST_EXT: reasonText = "External pin"; break; //!< Reset by external pin (not applicable for ESP32)
|
||||
case ESP_RST_SW: reasonText = "Via esp_restart"; break; //!< Software reset via esp_restart
|
||||
case ESP_RST_PANIC: reasonText = "Exception/panic"; break; //!< Software reset due to exception/panic
|
||||
@@ -791,3 +863,40 @@ string getResetReason(void) {
|
||||
}
|
||||
return reasonText;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the current uptime formated ad xxf xxh xxm [xxs]
|
||||
*/
|
||||
std::string getFormatedUptime(bool compact) {
|
||||
char buf[20];
|
||||
#pragma GCC diagnostic ignored "-Wformat-truncation"
|
||||
|
||||
int uptime = getUpTime(); // in seconds
|
||||
|
||||
int days = int(floor(uptime / (3600*24)));
|
||||
int hours = int(floor((uptime - days * 3600*24) / (3600)));
|
||||
int minutes = int(floor((uptime - days * 3600*24 - hours * 3600) / (60)));
|
||||
int seconds = uptime - days * 3600*24 - hours * 3600 - minutes * 60;
|
||||
|
||||
if (compact) {
|
||||
snprintf(buf, sizeof(buf), "%dd%02dh%02dm%02ds", days, hours, minutes, seconds);
|
||||
}
|
||||
else {
|
||||
snprintf(buf, sizeof(buf), "%3dd %02dh %02dm %02ds", days, hours, minutes, seconds);
|
||||
}
|
||||
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
|
||||
const char* get404(void) {
|
||||
return
|
||||
"<pre>\n\n\n\n"
|
||||
" _\n"
|
||||
" .__(.)< ( oh oh! This page does not exist! )\n"
|
||||
" \\___)\n"
|
||||
"\n\n"
|
||||
" You could try your <a href=index.html target=_parent>luck</a> here!</pre>\n"
|
||||
"<script>document.cookie = \"page=overview.html\"</script>"; // Make sure we load the overview page
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef HELPER_H
|
||||
#define HELPER_H
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
@@ -14,13 +18,11 @@ bool CopyFile(string input, string output);
|
||||
bool DeleteFile(string fn);
|
||||
bool RenameFile(string from, string to);
|
||||
bool MakeDir(std::string _what);
|
||||
bool FileExists(string filename);
|
||||
|
||||
|
||||
string RundeOutput(double _in, int _anzNachkomma);
|
||||
|
||||
|
||||
FILE* OpenFileAndWait(const char* nm, const char* _mode, int _waitsec = 1, bool silent = true);
|
||||
|
||||
size_t findDelimiterPos(string input, string delimiter);
|
||||
//string trim(string istring);
|
||||
string trim(string istring, string adddelimiter = "");
|
||||
@@ -30,6 +32,7 @@ string getFileType(string filename);
|
||||
string getFileFullFileName(string filename);
|
||||
string getDirectory(string filename);
|
||||
|
||||
|
||||
int mkdir_r(const char *dir, const mode_t mode);
|
||||
int removeFolder(const char* folderPath, const char* logTag);
|
||||
|
||||
@@ -63,4 +66,31 @@ string getSDCardCapacity();
|
||||
string getSDCardSectorSize();
|
||||
|
||||
string getMac(void);
|
||||
string getResetReason(void);
|
||||
|
||||
|
||||
/* Error bit fields
|
||||
One bit per error
|
||||
Make sure it matches https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes */
|
||||
enum SystemStatusFlag_t { // One bit per error
|
||||
// First Byte
|
||||
SYSTEM_STATUS_PSRAM_BAD = 1 << 0, // 1, Critical Error
|
||||
SYSTEM_STATUS_HEAP_TOO_SMALL = 1 << 1, // 2, Critical Error
|
||||
SYSTEM_STATUS_CAM_BAD = 1 << 2, // 4, Critical Error
|
||||
|
||||
// Second Byte
|
||||
SYSTEM_STATUS_CAM_FB_BAD = 1 << (0+8), // 8, Flow still might work
|
||||
SYSTEM_STATUS_NTP_BAD = 1 << (1+8), // 9, Flow will work but time will be wrong
|
||||
};
|
||||
|
||||
void setSystemStatusFlag(SystemStatusFlag_t flag);
|
||||
void clearSystemStatusFlag(SystemStatusFlag_t flag);
|
||||
int getSystemStatus(void);
|
||||
bool isSetSystemStatusFlag(SystemStatusFlag_t flag);
|
||||
|
||||
time_t getUpTime(void);
|
||||
string getResetReason(void);
|
||||
std::string getFormatedUptime(bool compact);
|
||||
|
||||
const char* get404(void);
|
||||
|
||||
#endif //HELPER_H
|
||||
|
||||
178
code/components/jomjol_helper/esp_sys.cpp
Normal file
178
code/components/jomjol_helper/esp_sys.cpp
Normal file
@@ -0,0 +1,178 @@
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#include "esp_sys.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
#include "esp_chip_info.h"
|
||||
|
||||
|
||||
void Restart() {
|
||||
esp_restart();
|
||||
}
|
||||
|
||||
//source : https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/misc_system_api.html#_CPPv416esp_chip_model_t
|
||||
|
||||
//https://github.com/espressif/esp-idf/blob/8464186e67e34b417621df6b6f1f289a6c60b859/components/esp_hw_support/include/esp_chip_info.h
|
||||
/*
|
||||
typedef enum {
|
||||
CHIP_ESP32 = 1, //!< ESP32
|
||||
CHIP_ESP32S2 = 2, //!< ESP32-S2
|
||||
CHIP_ESP32S3 = 9, //!< ESP32-S3
|
||||
CHIP_ESP32C3 = 5, //!< ESP32-C3
|
||||
CHIP_ESP32H4 = 6, //!< ESP32-H4
|
||||
CHIP_ESP32C2 = 12, //!< ESP32-C2
|
||||
CHIP_ESP32C6 = 13, //!< ESP32-C6
|
||||
CHIP_ESP32H2 = 16, //!< ESP32-H2
|
||||
CHIP_POSIX_LINUX = 999, //!< The code is running on POSIX/Linux simulator
|
||||
} esp_chip_model_t;
|
||||
*/
|
||||
|
||||
char* GetChipModel(){
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
switch((int)chipInfo.model) {
|
||||
case 0 : return (char*)"ESP8266";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32 : return (char*)"ESP32";
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 0, 0)
|
||||
case (int)esp_chip_model_t::CHIP_ESP32S2 : return (char*)"ESP32-S2";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32S3 : return (char*)"ESP32-S3";
|
||||
case (int)esp_chip_model_t::CHIP_ESP32C3 : return (char*)"ESP32-C3";
|
||||
case 6 : return (char*)"ESP32-H4";
|
||||
case 12 : return (char*)"ESP32-C2";
|
||||
case 13 : return (char*)"ESP32-C6";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32H4 : return (char*)"ESP32-H4";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32C2 : return (char*)"ESP32-C2";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32C6 : return (char*)"ESP32-C6";
|
||||
//case (int)esp_chip_model_t::CHIP_ESP32H2 : return (char*)"ESP32-H2";
|
||||
case 16 : return (char*)"ESP32-H2";
|
||||
//case (int)esp_chip_model_t::CHIP_POSIX_LINUX : return (char*)"CHIP_POSIX_LINUX";
|
||||
|
||||
#endif
|
||||
}
|
||||
return (char*)"Chip Unknown";
|
||||
}
|
||||
|
||||
uint8_t GetChipCoreCount() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.cores;
|
||||
}
|
||||
|
||||
uint16_t GetChipRevision() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.revision;
|
||||
}
|
||||
|
||||
uint32_t GetChipfeatures() {
|
||||
esp_chip_info_t chipInfo;
|
||||
esp_chip_info(&chipInfo);
|
||||
return chipInfo.features;
|
||||
}
|
||||
|
||||
|
||||
uint32_t GetFreeHeap() {
|
||||
return esp_get_free_heap_size();
|
||||
}
|
||||
|
||||
uint32_t GetLeastHeapFreeSinceBoot() {
|
||||
return esp_get_minimum_free_heap_size();
|
||||
}
|
||||
|
||||
|
||||
std::string get_device_info()
|
||||
{
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
|
||||
std::string espInfoResultStr = "";
|
||||
char aMsgBuf[40];
|
||||
|
||||
espInfoResultStr += "Device Info:";
|
||||
espInfoResultStr += "---------------\n";
|
||||
espInfoResultStr += "Chip Model: " + std::string(GetChipModel()) +"\n";
|
||||
sprintf(aMsgBuf,"Chip Revision: %d\n", chip_info.revision);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"CPU Cores: %d\n", chip_info.cores);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"Flash Memory: %dMB\n", spi_flash_get_chip_size()/(1024*1024));
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
if(chip_info.features & CHIP_FEATURE_WIFI_BGN)
|
||||
//espInfoResultStr += "Base MAC: " + std::string(getMac()) +"\n";
|
||||
espInfoResultStr += "ESP-IDF version: " + std::string(esp_get_idf_version()) +"\n";
|
||||
if((chip_info.features & CHIP_FEATURE_WIFI_BGN) || (chip_info.features & CHIP_FEATURE_BT) ||
|
||||
(chip_info.features & CHIP_FEATURE_BLE) || (chip_info.features & CHIP_FEATURE_EMB_FLASH))
|
||||
{
|
||||
espInfoResultStr += "Characteristics:\n";
|
||||
if(chip_info.features & CHIP_FEATURE_WIFI_BGN)
|
||||
espInfoResultStr += " WiFi 2.4GHz\n";
|
||||
if(chip_info.features & CHIP_FEATURE_BT)
|
||||
espInfoResultStr += " Bluetooth Classic\n";
|
||||
if(chip_info.features & CHIP_FEATURE_BLE)
|
||||
espInfoResultStr += " Bluetooth Low Energy\n";
|
||||
if(chip_info.features & CHIP_FEATURE_EMB_FLASH)
|
||||
espInfoResultStr += " Embedded Flash memory\n";
|
||||
else
|
||||
espInfoResultStr += " External Flash memory\n";
|
||||
}
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
sprintf(aMsgBuf,"spiram size %u\n", esp_spiram_get_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem free %u\n", esp_himem_get_free_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem phys %u\n", esp_himem_get_phys_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"himem reserved %u\n", esp_himem_reserved_area_size());
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
#endif
|
||||
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
|
||||
size_t getFreeMemoryInternal(){ //Current Free Memory
|
||||
return heap_caps_get_free_size(MALLOC_CAP_8BIT) - heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
size_t getFreeMemorySPIRAM(){ //Current Free Memory
|
||||
return heap_caps_get_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
|
||||
size_t getLargestFreeBlockInternal(){ //Largest Free Block
|
||||
return heap_caps_get_largest_free_block(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
size_t getLargestFreeBlockSPIRAM(){ //Largest Free Block
|
||||
return heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
|
||||
size_t getMinEverFreeMemInternal(){ //Min. Ever Free Size
|
||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
|
||||
}
|
||||
|
||||
size_t getMinEverFreeMemSPIRAM(){ //Min. Ever Free Size
|
||||
return heap_caps_get_minimum_free_size(MALLOC_CAP_SPIRAM);
|
||||
}
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
size_t getHimemTotSpace(){
|
||||
return esp_himem_get_phys_size();
|
||||
}
|
||||
|
||||
size_t getHimemFreeSpace(){
|
||||
return esp_himem_get_free_size();
|
||||
}
|
||||
|
||||
size_t getHimemReservedArea(){
|
||||
return esp_himem_reserved_area_size();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
54
code/components/jomjol_helper/esp_sys.h
Normal file
54
code/components/jomjol_helper/esp_sys.h
Normal file
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#ifndef ESP_SYS_H
|
||||
#define ESP_SYS_H
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
// Device libraries (ESP-IDF)
|
||||
#include <esp_system.h>
|
||||
#include <esp_spi_flash.h>
|
||||
#include <esp_heap_caps.h>
|
||||
|
||||
// for esp_spiram_get_size
|
||||
extern "C" {
|
||||
#include <esp32/spiram.h>
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#include <esp32/himem.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Restart();
|
||||
char *GetChipModel();
|
||||
uint8_t GetChipCoreCount();
|
||||
uint16_t GetChipRevision();
|
||||
uint32_t GetChipfeatures();
|
||||
uint32_t GetFreeHeap();
|
||||
uint32_t GetLeastHeapFreeSinceBoot();
|
||||
|
||||
std::string get_device_info();
|
||||
|
||||
size_t getFreeMemoryInternal();
|
||||
size_t getFreeMemorySPIRAM();
|
||||
size_t getLargestFreeBlockInternal();
|
||||
size_t getLargestFreeBlockSPIRAM();
|
||||
size_t getMinEverFreeMemInternal();
|
||||
size_t getMinEverFreeMemSPIRAM();
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
size_t getHimemTotSpace();
|
||||
size_t getHimemFreeSpace();
|
||||
size_t getHimemReservedArea();
|
||||
#endif
|
||||
|
||||
|
||||
#endif //ESP_SYS_H
|
||||
|
||||
#endif // DEBUG_ENABLE_SYSINFO
|
||||
115
code/components/jomjol_helper/himem_memory_check.cpp
Normal file
115
code/components/jomjol_helper/himem_memory_check.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
|
||||
#include "himem_memory_check.h"
|
||||
|
||||
//source adapted from : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c
|
||||
|
||||
|
||||
//Fill memory with pseudo-random data generated from the given seed.
|
||||
//Fills the memory in 32-bit words for speed.
|
||||
static void fill_mem_seed(int seed, void *mem, int len)
|
||||
{
|
||||
uint32_t *p = (uint32_t *)mem;
|
||||
unsigned int rseed = seed ^ 0xa5a5a5a5;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
*p++ = rand_r(&rseed);
|
||||
}
|
||||
}
|
||||
|
||||
//Check the memory filled by fill_mem_seed. Returns true if the data matches the data
|
||||
//that fill_mem_seed wrote (when given the same seed).
|
||||
//Returns true if there's a match, false when the region differs from what should be there.
|
||||
static bool check_mem_seed(int seed, void *mem, int len, int phys_addr)
|
||||
{
|
||||
uint32_t *p = (uint32_t *)mem;
|
||||
unsigned int rseed = seed ^ 0xa5a5a5a5;
|
||||
for (int i = 0; i < len / 4; i++) {
|
||||
uint32_t ex = rand_r(&rseed);
|
||||
if (ex != *p) {
|
||||
//printf("check_mem_seed: %x has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", phys_addr+((char*)p-(char*)mem), *p, ex);
|
||||
return false;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//Allocate a himem region, fill it with data, check it and release it.
|
||||
static bool test_region(int check_size, int seed)
|
||||
{
|
||||
esp_himem_handle_t mh; //Handle for the address space we're using
|
||||
esp_himem_rangehandle_t rh; //Handle for the actual RAM.
|
||||
bool ret = true;
|
||||
|
||||
//Allocate the memory we're going to check.
|
||||
ESP_ERROR_CHECK(esp_himem_alloc(check_size, &mh));
|
||||
//Allocate a block of address range
|
||||
ESP_ERROR_CHECK(esp_himem_alloc_map_range(ESP_HIMEM_BLKSZ, &rh));
|
||||
for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
|
||||
uint32_t *ptr = NULL;
|
||||
//Map in block, write pseudo-random data, unmap block.
|
||||
ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
|
||||
fill_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ); //
|
||||
ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
|
||||
}
|
||||
vTaskDelay(5); //give the OS some time to do things so the task watchdog doesn't bark
|
||||
for (int i = 0; i < check_size; i += ESP_HIMEM_BLKSZ) {
|
||||
uint32_t *ptr;
|
||||
//Map in block, check against earlier written pseudo-random data, unmap block.
|
||||
ESP_ERROR_CHECK(esp_himem_map(mh, rh, i, 0, ESP_HIMEM_BLKSZ, 0, (void**)&ptr));
|
||||
if (!check_mem_seed(i ^ seed, ptr, ESP_HIMEM_BLKSZ, i)) {
|
||||
//printf("Error in block %d\n", i / ESP_HIMEM_BLKSZ);
|
||||
ret = false;
|
||||
}
|
||||
ESP_ERROR_CHECK(esp_himem_unmap(rh, ptr, ESP_HIMEM_BLKSZ));
|
||||
if (!ret) break; //don't check rest of blocks if error occurred
|
||||
}
|
||||
//Okay, all done!
|
||||
ESP_ERROR_CHECK(esp_himem_free(mh));
|
||||
ESP_ERROR_CHECK(esp_himem_free_map_range(rh));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::string himem_memory_check()
|
||||
{
|
||||
size_t memcnt=esp_himem_get_phys_size();
|
||||
size_t memfree=esp_himem_get_free_size();
|
||||
|
||||
std::string espInfoResultStr = "";
|
||||
char aMsgBuf[40];
|
||||
|
||||
espInfoResultStr += "Running HIMEM memory check";
|
||||
|
||||
sprintf(aMsgBuf,"Himem has %dKiB of memory", (int)memcnt/1024);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
|
||||
sprintf(aMsgBuf,"%dKiB of which is free", (int)memfree/1024);
|
||||
espInfoResultStr += std::string(aMsgBuf);
|
||||
|
||||
espInfoResultStr += "\n please wait ....\n";
|
||||
|
||||
//running memory checks
|
||||
//assert(test_region(memfree, 0xaaaa));
|
||||
|
||||
if(test_region(memfree, 0xaaaa)) {
|
||||
espInfoResultStr += "Himem check Failed!\n";
|
||||
} else {
|
||||
espInfoResultStr += "Himem check Done!\n";
|
||||
}
|
||||
|
||||
return espInfoResultStr;
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUG_HIMEM_MEMORY_CHECK
|
||||
41
code/components/jomjol_helper/himem_memory_check.h
Normal file
41
code/components/jomjol_helper/himem_memory_check.h
Normal file
@@ -0,0 +1,41 @@
|
||||
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
|
||||
#ifndef HIMEM_MEMORY_CHECK_H
|
||||
#define HIMEM_MEMORY_CHECK_H
|
||||
|
||||
|
||||
|
||||
//source : //source : https://github.com/espressif/esp-idf/blob/master/examples/system/himem/main/himem_example_main.c
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "esp32/himem.h"
|
||||
|
||||
#include <string>
|
||||
#include "esp32/himem.h"
|
||||
|
||||
|
||||
std::string himem_memory_check();
|
||||
|
||||
#endif //HIMEM_MEMORY_CHECK_H
|
||||
|
||||
#endif // DEBUG_HIMEM_MEMORY_CHECK
|
||||
87
code/components/jomjol_helper/perfmon.c
Normal file
87
code/components/jomjol_helper/perfmon.c
Normal file
@@ -0,0 +1,87 @@
|
||||
//source : https://github.com/Carbon225/esp32-perfmon
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
/*
|
||||
ESP32 CPU usage monitor
|
||||
Gives you a rough idea of how the Xtensa cores are utilized.
|
||||
|
||||
Works by attaching idle hooks and measuring how often they get called. The core usage is calculated: usage% = idle ticks since last measurement / expected idle ticks if core were idle * 100%. The expected idle tick count was measured by running an empty program.
|
||||
|
||||
Limitations:
|
||||
Should only be used for user information, not in logic that needs accurate values
|
||||
New IDF versions could optimize performance and therefore introduce an error to usage estimation.
|
||||
When one core is at 100% the other might report a negative value
|
||||
|
||||
Usage:
|
||||
#include "perfmon.h"
|
||||
Call perfmon_start() once
|
||||
|
||||
*/
|
||||
|
||||
#ifdef DEBUG_ENABLE_PERFMON
|
||||
|
||||
#include "perfmon.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_freertos_hooks.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
static const char *TAG = "perfmon";
|
||||
|
||||
static uint64_t idle0Calls = 0;
|
||||
static uint64_t idle1Calls = 0;
|
||||
|
||||
#if defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_240)
|
||||
static const uint64_t MaxIdleCalls = 1855000;
|
||||
#elif defined(CONFIG_ESP32_DEFAULT_CPU_FREQ_160)
|
||||
static const uint64_t MaxIdleCalls = 1233100;
|
||||
#else
|
||||
#error "Unsupported CPU frequency"
|
||||
#endif
|
||||
|
||||
static bool idle_task_0()
|
||||
{
|
||||
idle0Calls += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool idle_task_1()
|
||||
{
|
||||
idle1Calls += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void perfmon_task(void *args)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
float idle0 = idle0Calls;
|
||||
float idle1 = idle1Calls;
|
||||
idle0Calls = 0;
|
||||
idle1Calls = 0;
|
||||
|
||||
int cpu0 = 100.f - idle0 / MaxIdleCalls * 100.f;
|
||||
int cpu1 = 100.f - idle1 / MaxIdleCalls * 100.f;
|
||||
|
||||
ESP_LOGI(TAG, "Core 0 at %d%%", cpu0);
|
||||
ESP_LOGI(TAG, "Core 1 at %d%%", cpu1);
|
||||
// TODO configurable delay
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
esp_err_t perfmon_start()
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_task_0, 0));
|
||||
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_task_1, 1));
|
||||
// TODO calculate optimal stack size
|
||||
xTaskCreate(perfmon_task, "perfmon", 2048, NULL, 1, NULL);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
#endif // DEBUG_ENABLE_PERFMON
|
||||
24
code/components/jomjol_helper/perfmon.h
Normal file
24
code/components/jomjol_helper/perfmon.h
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#ifdef DEBUG_ENABLE_PERFMON
|
||||
|
||||
#ifndef COMPONENTS_PERFMON_INCLUDE_PERFMON_H_
|
||||
#define COMPONENTS_PERFMON_INCLUDE_PERFMON_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
esp_err_t perfmon_start();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPONENTS_PERFMON_INCLUDE_PERFMON_H_ */
|
||||
|
||||
#endif //DEBUG_ENABLE_PERFMON
|
||||
@@ -2,19 +2,13 @@
|
||||
#include "CRotateImage.h"
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char* TAG = "c_align_and_cut_image";
|
||||
|
||||
//#define GET_MEMORY malloc
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
CAlignAndCutImage::CAlignAndCutImage(CImageBasis *_org, CImageBasis *_temp)
|
||||
{
|
||||
rgb_image = _org->rgb_image;
|
||||
@@ -47,14 +41,14 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
|
||||
r0_x = _temp1->target_x;
|
||||
r0_y = _temp1->target_y;
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Before ft->FindTemplate(_temp1); %s", _temp1->image_file.c_str());
|
||||
isSimilar1 = ft->FindTemplate(_temp1);
|
||||
_temp1->width = ft->tpl_width;
|
||||
_temp1->height = ft->tpl_height;
|
||||
|
||||
r1_x = _temp2->target_x;
|
||||
r1_y = _temp2->target_y;
|
||||
ESP_LOGD(TAG, "Vor ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str());
|
||||
ESP_LOGD(TAG, "Before ft->FindTemplate(_temp2); %s", _temp2->image_file.c_str());
|
||||
isSimilar2 = ft->FindTemplate(_temp2);
|
||||
_temp2->width = ft->tpl_width;
|
||||
_temp2->height = ft->tpl_height;
|
||||
@@ -78,14 +72,14 @@ bool CAlignAndCutImage::Align(RefInfo *_temp1, RefInfo *_temp2)
|
||||
|
||||
d_winkel = (w_ist - w_org) * 180 / M_PI;
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\tdx:\t" + std::to_string(dx) + "\tdy:\t" + std::to_string(dy) + "\td_winkel:\t" + std::to_string(d_winkel);
|
||||
zw = zw + "\tt1_x_y:\t" + std::to_string(_temp1->found_x) + "\t" + std::to_string(_temp1->found_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(_temp1->fastalg_min) + "\t" + std::to_string(_temp1->fastalg_avg) + "\t" + std::to_string(_temp1->fastalg_max) + "\t"+ std::to_string(_temp1->fastalg_SAD);
|
||||
zw = zw + "\tt2_x_y:\t" + std::to_string(_temp2->found_x) + "\t" + std::to_string(_temp2->found_y);
|
||||
zw = zw + "\tpara2_found_min_avg_max:\t" + std::to_string(_temp2->fastalg_min) + "\t" + std::to_string(_temp2->fastalg_avg) + "\t" + std::to_string(_temp2->fastalg_max) + "\t"+ std::to_string(_temp2->fastalg_SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
CRotateImage rt(this, ImageTMP);
|
||||
rt.Translate(dx, dy);
|
||||
@@ -129,8 +123,12 @@ void CAlignAndCutImage::CutAndSave(std::string _template1, int x1, int y1, int d
|
||||
p_target[_channels] = p_source[_channels];
|
||||
}
|
||||
|
||||
// stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 0);
|
||||
#ifdef STBI_ONLY_JPEG
|
||||
stbi_write_jpg(_template1.c_str(), dx, dy, channels, odata, 100);
|
||||
#else
|
||||
stbi_write_bmp(_template1.c_str(), dx, dy, channels, odata);
|
||||
#endif
|
||||
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CALIGNANDCUTIMAGE_H
|
||||
#define CALIGNANDCUTIMAGE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
#include "CFindTemplate.h"
|
||||
|
||||
@@ -19,3 +24,4 @@ class CAlignAndCutImage : public CImageBasis
|
||||
void GetRefSize(int *ref_dx, int *ref_dy);
|
||||
};
|
||||
|
||||
#endif //CALIGNANDCUTIMAGE_H
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
@@ -67,11 +68,11 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
if ((_ref->alignment_algo == 2) && (_ref->fastalg_x > -1) && (_ref->fastalg_y > -1)) // für Testzwecke immer Berechnen
|
||||
{
|
||||
isSimilar = CalculateSimularities(rgb_template, _ref->fastalg_x, _ref->fastalg_y, ow, oh, min, avg, max, SAD, _ref->fastalg_SAD, _ref->fastalg_SAD_criteria);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\t" + _ref->image_file + "\tt1_x_y:\t" + std::to_string(_ref->fastalg_x) + "\t" + std::to_string(_ref->fastalg_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(min) + "\t" + std::to_string(avg) + "\t" + std::to_string(max) + "\t"+ std::to_string(SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
}
|
||||
|
||||
// ESP_LOGD(TAG, "FindTemplate 03");
|
||||
@@ -143,11 +144,11 @@ bool CFindTemplate::FindTemplate(RefInfo *_ref)
|
||||
_ref->fastalg_SAD = SAD;
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
/*#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "\t" + _ref->image_file + "\tt1_x_y:\t" + std::to_string(_ref->fastalg_x) + "\t" + std::to_string(_ref->fastalg_y);
|
||||
zw = zw + "\tpara1_found_min_avg_max_SAD:\t" + std::to_string(min) + "\t" + std::to_string(avg) + "\t" + std::to_string(max) + "\t"+ std::to_string(SAD);
|
||||
LogFile.WriteToDedicatedFile("/sdcard/alignment.txt", zw);
|
||||
#endif
|
||||
#endif*/
|
||||
|
||||
RGBImageRelease();
|
||||
stbi_image_free(rgb_template);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#ifndef __CFINDTEMPLATE_CLASS
|
||||
#define __CFINDTEMPLATE_CLASS
|
||||
#pragma once
|
||||
|
||||
#ifndef CFINDTEMPLATE_H
|
||||
#define CFINDTEMPLATE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
@@ -37,4 +39,4 @@ class CFindTemplate : public CImageBasis
|
||||
bool CalculateSimularities(uint8_t* _rgb_tmpl, int _startx, int _starty, int _sizex, int _sizey, int &min, float &avg, int &max, float &SAD, float _SADold, float _SADcrit);
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif //CFINDTEMPLATE_H
|
||||
@@ -4,33 +4,30 @@
|
||||
#include "server_ota.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
|
||||
#define _ESP32_PSRAM
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char *TAG = "C IMG BASIS";
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
uint8_t * CImageBasis::RGBImageLock(int _waitmaxsec)
|
||||
{
|
||||
if (islocked)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Image is locked: sleep for: %ds", _waitmaxsec);
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Image is locked: sleep for: %ds", _waitmaxsec);
|
||||
#endif
|
||||
TickType_t xDelay;
|
||||
xDelay = 1000 / portTICK_PERIOD_MS;
|
||||
for (int i = 0; i <= _waitmaxsec; ++i)
|
||||
@@ -47,18 +44,19 @@ uint8_t * CImageBasis::RGBImageLock(int _waitmaxsec)
|
||||
return rgb_image;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::RGBImageRelease()
|
||||
{
|
||||
islocked = false;
|
||||
}
|
||||
|
||||
|
||||
uint8_t * CImageBasis::RGBImageGet()
|
||||
{
|
||||
return rgb_image;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void writejpghelp(void *context, void *data, int size)
|
||||
{
|
||||
// ESP_LOGD(TAG, "Size all: %d, size %d", ((ImageData*)context)->size, size);
|
||||
@@ -74,8 +72,6 @@ void writejpghelp(void *context, void *data, int size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
|
||||
{
|
||||
ImageData* ii = new ImageData;
|
||||
@@ -87,7 +83,19 @@ ImageData* CImageBasis::writeToMemoryAsJPG(const int quality)
|
||||
return ii;
|
||||
}
|
||||
|
||||
#define HTTP_BUFFER_SENT 1024
|
||||
|
||||
void CImageBasis::writeToMemoryAsJPG(ImageData* i, const int quality)
|
||||
{
|
||||
ImageData* ii = new ImageData;
|
||||
|
||||
RGBImageLock();
|
||||
stbi_write_jpg_to_func(writejpghelp, ii, width, height, channels, rgb_image, quality);
|
||||
RGBImageRelease();
|
||||
|
||||
memCopy((uint8_t*) ii, (uint8_t*) i, sizeof(ImageData));
|
||||
delete ii;
|
||||
}
|
||||
|
||||
|
||||
struct SendJPGHTTP
|
||||
{
|
||||
@@ -97,13 +105,13 @@ struct SendJPGHTTP
|
||||
int size = 0;
|
||||
};
|
||||
|
||||
|
||||
inline void writejpgtohttphelp(void *context, void *data, int size)
|
||||
{
|
||||
SendJPGHTTP* _send = (SendJPGHTTP*) context;
|
||||
if ((_send->size + size) >= HTTP_BUFFER_SENT) // data passt nich mehr in buffer
|
||||
if ((_send->size + size) >= HTTP_BUFFER_SENT) // data no longer fits in buffer
|
||||
{
|
||||
httpd_req_t *_req = _send->req;
|
||||
if (httpd_resp_send_chunk(_req, _send->buf, _send->size) != ESP_OK)
|
||||
if (httpd_resp_send_chunk(_send->req, _send->buf, _send->size) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
_send->res = ESP_FAIL;
|
||||
@@ -115,7 +123,6 @@ inline void writejpgtohttphelp(void *context, void *data, int size)
|
||||
}
|
||||
|
||||
|
||||
|
||||
esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality)
|
||||
{
|
||||
SendJPGHTTP ii;
|
||||
@@ -125,28 +132,28 @@ esp_err_t CImageBasis::SendJPGtoHTTP(httpd_req_t *_req, const int quality)
|
||||
|
||||
RGBImageLock();
|
||||
stbi_write_jpg_to_func(writejpgtohttphelp, &ii, width, height, channels, rgb_image, quality);
|
||||
RGBImageRelease();
|
||||
|
||||
if (ii.size > 0)
|
||||
{
|
||||
if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) // verschicke noch den Rest
|
||||
if (httpd_resp_send_chunk(_req, (char*) ii.buf, ii.size) != ESP_OK) //still send the rest
|
||||
{
|
||||
ESP_LOGE(TAG, "File sending failed!");
|
||||
ii.res = ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
return ii.res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
|
||||
{
|
||||
int gr = height * width * channels;
|
||||
if (gr != _size) // Größe passt nicht
|
||||
if (gr != _size) // Size does not fit
|
||||
{
|
||||
ESP_LOGD(TAG, "Cannot copy image from memory - sizes do not match: should be %d, but is %d", _size, gr);
|
||||
ESP_LOGE(TAG, "Cannot copy image from memory - sizes do not match: should be %d, but is %d", _size, gr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -157,6 +164,7 @@ bool CImageBasis::CopyFromMemory(uint8_t* _source, int _size)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
uint8_t CImageBasis::GetPixelColor(int x, int y, int ch)
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -175,6 +183,7 @@ void CImageBasis::memCopy(uint8_t* _source, uint8_t* _target, int _size)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageBasis::isInImage(int x, int y)
|
||||
{
|
||||
if ((x < 0) || (x > width - 1))
|
||||
@@ -186,6 +195,7 @@ bool CImageBasis::isInImage(int x, int y)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -201,6 +211,7 @@ void CImageBasis::setPixelColor(int x, int y, int r, int g, int b)
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, int thickness)
|
||||
{
|
||||
int zwx1, zwx2, zwy1, zwy2;
|
||||
@@ -210,6 +221,9 @@ void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, in
|
||||
zwx2 = x + dx + thickness - 1;
|
||||
zwy1 = y;
|
||||
zwy2 = y;
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (_thick = 0; _thick < thickness; _thick++)
|
||||
for (_x = zwx1; _x <= zwx2; ++_x)
|
||||
for (_y = zwy1; _y <= zwy2; _y++)
|
||||
@@ -246,14 +260,18 @@ void CImageBasis::drawRect(int x, int y, int dx, int dy, int r, int g, int b, in
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x + _thick, _y, r, g, b);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b, int thickness)
|
||||
{
|
||||
int _x, _y, _thick;
|
||||
int _zwy1, _zwy2;
|
||||
thickness = (thickness-1) / 2;
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (_thick = 0; _thick <= thickness; ++_thick)
|
||||
for (_x = x1 - _thick; _x <= x2 + _thick; ++_x)
|
||||
{
|
||||
@@ -272,8 +290,11 @@ void CImageBasis::drawLine(int x1, int y1, int x2, int y2, int r, int g, int b,
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g, int b, int thickness)
|
||||
{
|
||||
float deltarad, aktrad;
|
||||
@@ -285,6 +306,8 @@ void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g,
|
||||
|
||||
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
|
||||
for (_thick = 0; _thick < thickness; ++_thick)
|
||||
{
|
||||
@@ -293,6 +316,8 @@ void CImageBasis::drawEllipse(int x1, int y1, int radx, int rady, int r, int g,
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
@@ -303,6 +328,8 @@ void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int t
|
||||
|
||||
deltarad = 1 / (4 * M_PI * (rad + thickness - 1));
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (aktrad = 0; aktrad <= (2 * M_PI); aktrad += deltarad)
|
||||
for (_thick = 0; _thick < thickness; ++_thick)
|
||||
{
|
||||
@@ -311,8 +338,11 @@ void CImageBasis::drawCircle(int x1, int y1, int rad, int r, int g, int b, int t
|
||||
if (isInImage(_x, _y))
|
||||
setPixelColor(_x, _y, r, g, b);
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis()
|
||||
{
|
||||
externalImage = false;
|
||||
@@ -323,6 +353,7 @@ CImageBasis::CImageBasis()
|
||||
islocked = false;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
{
|
||||
bpp = _channels;
|
||||
@@ -332,10 +363,21 @@ void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CreateEmptyImage");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
//ESP_LOGE(TAG, "CImageBasis::CreateEmptyImage: No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CreateEmptyImage: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CreateEmptyImage");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
stbi_uc* p_source;
|
||||
|
||||
@@ -348,30 +390,55 @@ void CImageBasis::CreateEmptyImage(int _width, int _height, int _channels)
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::EmptyImage()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::EmptyImage");
|
||||
#endif
|
||||
|
||||
stbi_uc* p_source;
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
for (int x = 0; x < width; ++x)
|
||||
for (int y = 0; y < height; ++y)
|
||||
{
|
||||
p_source = rgb_image + (channels * (y * width + x));
|
||||
for (int _channels = 0; _channels < channels; ++_channels)
|
||||
p_source[_channels] = (uint8_t) 0;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::LoadFromMemory(stbi_uc *_buffer, int len)
|
||||
{
|
||||
RGBImageLock();
|
||||
|
||||
if (rgb_image)
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
rgb_image = stbi_load_from_memory(_buffer, len, &width, &height, &channels, 3);
|
||||
bpp = channels;
|
||||
ESP_LOGD(TAG, "Image loaded from memory: %d, %d, %d", width, height, channels);
|
||||
|
||||
if ((width * height * channels) == 0)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Image with size 0 loaded --> reboot to be done! "
|
||||
"Check that your camera module is working and connected properly.");
|
||||
LogFile.WriteHeapInfo("CImageBasis::LoadFromMemory");
|
||||
|
||||
doReboot();
|
||||
|
||||
}
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
|
||||
CImageBasis::CImageBasis(CImageBasis *_copyfrom)
|
||||
{
|
||||
islocked = false;
|
||||
externalImage = false;
|
||||
@@ -382,30 +449,30 @@ CImageBasis::CImageBasis(CImageBasis *_copyfrom, int _anzrepeat)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_copyfrom - Start");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
int anz = 1;
|
||||
while (!rgb_image && (anz < _anzrepeat))
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "Create Image from Copy - Memory is full - try again: %d", anz);
|
||||
rgb_image = (unsigned char*) malloc(memsize);
|
||||
anz++;
|
||||
}
|
||||
|
||||
|
||||
if (!rgb_image)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-Copyfrom: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-Copyfrom");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
memCopy(_copyfrom->rgb_image, rgb_image, memsize);
|
||||
RGBImageRelease();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_copyfrom - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis(int _width, int _height, int _channels)
|
||||
{
|
||||
islocked = false;
|
||||
@@ -415,15 +482,28 @@ CImageBasis::CImageBasis(int _width, int _height, int _channels)
|
||||
height = _height;
|
||||
bpp = _channels;
|
||||
|
||||
int memsize = width * height * channels;
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_width,height,ch - Start");
|
||||
#endif
|
||||
|
||||
int memsize = width * height * channels;
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
if (!rgb_image)
|
||||
|
||||
if (rgb_image == NULL)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", getESPHeapInfo().c_str());
|
||||
ESP_LOGD(TAG, "No more free memory!! Needed: %d %d %d %d", width, height, channels, memsize);
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-width,height,ch: Can't allocate enough memory: " + std::to_string(memsize));
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-width,height,ch");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_width,height,ch - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -433,8 +513,6 @@ CImageBasis::CImageBasis(std::string _image)
|
||||
channels = 3;
|
||||
externalImage = false;
|
||||
filename = _image;
|
||||
long zwld = esp_get_free_heap_size();
|
||||
ESP_LOGD(TAG, "freeheapsize before: %ld", zwld);
|
||||
|
||||
if (file_size(_image.c_str()) == 0) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, _image + " is empty!");
|
||||
@@ -442,32 +520,39 @@ CImageBasis::CImageBasis(std::string _image)
|
||||
}
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_image - Start");
|
||||
#endif
|
||||
|
||||
rgb_image = stbi_load(_image.c_str(), &width, &height, &bpp, channels);
|
||||
|
||||
if (rgb_image == NULL) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to load " + _image + "! Is it corrupted?");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CImageBasis::CImageBasis-image: Failed to load " + _image + "! Is it corrupted?");
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis-image");
|
||||
RGBImageRelease();
|
||||
return;
|
||||
}
|
||||
|
||||
RGBImageRelease();
|
||||
|
||||
zwld = esp_get_free_heap_size();
|
||||
ESP_LOGD(TAG, "freeheapsize after : %ld", zwld);
|
||||
|
||||
std::string zw = "Image Load failed:" + _image;
|
||||
if (rgb_image == NULL)
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
std::string zw = "CImageBasis after load " + _image;
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
zw = "CImageBasis after load " + _image + "\n";
|
||||
ESP_LOGD(TAG, "%s", zw.c_str());
|
||||
ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels);
|
||||
ESP_LOGD(TAG, "w %d, h %d, b %d, c %d", width, height, bpp, channels);
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CImageBasis::CImageBasis_image - done");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool CImageBasis::ImageOkay(){
|
||||
return rgb_image != NULL;
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp)
|
||||
{
|
||||
islocked = false;
|
||||
@@ -479,6 +564,7 @@ CImageBasis::CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _he
|
||||
externalImage = true;
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Contrast(float _contrast) //input range [-100..100]
|
||||
{
|
||||
stbi_uc* p_source;
|
||||
@@ -500,28 +586,35 @@ void CImageBasis::Contrast(float _contrast) //input range [-100..100]
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
CImageBasis::~CImageBasis()
|
||||
{
|
||||
RGBImageLock();
|
||||
|
||||
if (!externalImage)
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::SaveToFile(std::string _imageout)
|
||||
{
|
||||
string typ = getFileType(_imageout);
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
if ((typ == "jpg") || (typ == "JPG")) // ACHTUNG PROBLEMATISCH IM ESP32
|
||||
if ((typ == "jpg") || (typ == "JPG")) // CAUTION PROBLEMATIC IN ESP32
|
||||
{
|
||||
stbi_write_jpg(_imageout.c_str(), width, height, channels, rgb_image, 0);
|
||||
}
|
||||
|
||||
|
||||
#ifndef STBI_ONLY_JPEG
|
||||
if ((typ == "bmp") || (typ == "BMP"))
|
||||
{
|
||||
stbi_write_bmp(_imageout.c_str(), width, height, channels, rgb_image);
|
||||
}
|
||||
#endif
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
@@ -533,25 +626,24 @@ void CImageBasis::Resize(int _new_dx, int _new_dy)
|
||||
|
||||
RGBImageLock();
|
||||
|
||||
|
||||
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
|
||||
|
||||
stbi_image_free(rgb_image);
|
||||
|
||||
rgb_image = (unsigned char*)GET_MEMORY(memsize);
|
||||
|
||||
memCopy(odata, rgb_image, memsize);
|
||||
RGBImageRelease();
|
||||
|
||||
width = _new_dx;
|
||||
height = _new_dy;
|
||||
stbi_image_free(odata);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
|
||||
{
|
||||
if ((_target->height != _new_dy) || (_target->width != _new_dx) || (_target->channels != channels))
|
||||
{
|
||||
ESP_LOGD(TAG, "CImageBasis::Resize - Target image size does not fit!");
|
||||
ESP_LOGE(TAG, "CImageBasis::Resize - Target image size does not fit!");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -559,6 +651,7 @@ void CImageBasis::Resize(int _new_dx, int _new_dy, CImageBasis *_target)
|
||||
|
||||
uint8_t* odata = _target->rgb_image;
|
||||
stbir_resize_uint8(rgb_image, width, height, 0, odata, _new_dx, _new_dy, 0, channels);
|
||||
|
||||
RGBImageRelease();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __CIMAGEBASIS
|
||||
#define __CIMAGEBASIS
|
||||
#ifndef CIMAGEBASIS_H
|
||||
#define CIMAGEBASIS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <esp_http_server.h>
|
||||
|
||||
#define _USE_MATH_DEFINES
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "stb_image.h"
|
||||
@@ -16,13 +17,6 @@
|
||||
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
//#define GET_MEMORY malloc
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
|
||||
#define MAX_JPG_SIZE 128000
|
||||
|
||||
|
||||
struct ImageData
|
||||
{
|
||||
uint8_t data[MAX_JPG_SIZE];
|
||||
@@ -67,20 +61,22 @@ class CImageBasis
|
||||
void SetIndepended(){externalImage = false;};
|
||||
|
||||
void CreateEmptyImage(int _width, int _height, int _channels);
|
||||
void EmptyImage();
|
||||
|
||||
|
||||
CImageBasis();
|
||||
CImageBasis(std::string _image);
|
||||
CImageBasis(uint8_t* _rgb_image, int _channels, int _width, int _height, int _bpp);
|
||||
CImageBasis(int _width, int _height, int _channels);
|
||||
CImageBasis(CImageBasis *_copyfrom, int _anzrepeat = 0);
|
||||
CImageBasis(CImageBasis *_copyfrom);
|
||||
|
||||
void Resize(int _new_dx, int _new_dy);
|
||||
void Resize(int _new_dx, int _new_dy, CImageBasis *_target);
|
||||
|
||||
void LoadFromMemory(stbi_uc *_buffer, int len);
|
||||
|
||||
ImageData* writeToMemoryAsJPG(const int quality = 90);
|
||||
ImageData* writeToMemoryAsJPG(const int quality = 90);
|
||||
void writeToMemoryAsJPG(ImageData* ii, const int quality = 90);
|
||||
|
||||
esp_err_t SendJPGtoHTTP(httpd_req_t *req, const int quality = 90);
|
||||
|
||||
@@ -92,5 +88,5 @@ class CImageBasis
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif //CIMAGEBASIS_H
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CROTATEIMAGE_H
|
||||
#define CROTATEIMAGE_H
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
@@ -19,3 +24,5 @@ class CRotateImage: public CImageBasis
|
||||
void Translate(int _dx, int _dy);
|
||||
void Mirror();
|
||||
};
|
||||
|
||||
#endif //CROTATEIMAGE_H
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
#include "interface_influxdb.h"
|
||||
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
#include <time.h>
|
||||
#include "ClassLogFile.h"
|
||||
#include "esp_http_client.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||
|
||||
static const char *TAG = "INFLUXDB";
|
||||
|
||||
@@ -111,4 +111,4 @@ void InfluxDBInit(std::string _uri, std::string _database, std::string _measurem
|
||||
void InfluxDBdestroy() {
|
||||
}
|
||||
|
||||
|
||||
#endif //ENABLE_INFLUXDB
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
#ifdef ENABLE_INFLUXDB
|
||||
|
||||
#pragma once
|
||||
#ifndef INTERFACE_INFLUXDB_H
|
||||
#define INTERFACE_INFLUXDB_H
|
||||
|
||||
@@ -11,3 +14,4 @@ void InfluxDBdestroy();
|
||||
void InfluxDBPublish(std::string _key, std::string _content, std::string _timestamp);
|
||||
|
||||
#endif //INTERFACE_INFLUXDB_H
|
||||
#endif //ENABLE_INFLUXDB
|
||||
@@ -15,55 +15,22 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "LOGFILE";
|
||||
|
||||
ClassLogFile LogFile("/sdcard/log/message", "log_%Y-%m-%d.txt", "/sdcard/log/data", "data_%Y-%m-%d.csv");
|
||||
|
||||
|
||||
void ClassLogFile::WriteHeapInfo(std::string _id)
|
||||
{
|
||||
std::string _zw = _id;
|
||||
if (loglevel >= ESP_LOG_DEBUG) {
|
||||
_zw = _zw + "\t" + getESPHeapInfo();
|
||||
std::string _zw = _id + "\t" + getESPHeapInfo();
|
||||
WriteToFile(ESP_LOG_DEBUG, "HEAP", _zw);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLogFile::getESPHeapInfo(){
|
||||
string espInfoResultStr = "";
|
||||
char aMsgBuf[80];
|
||||
|
||||
multi_heap_info_t aMultiHead_info ;
|
||||
heap_caps_get_info (&aMultiHead_info,MALLOC_CAP_8BIT);
|
||||
size_t aFreeHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeadSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aMinFreeHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT);
|
||||
size_t aHeapLargestFreeBlockSize = heap_caps_get_largest_free_block(MALLOC_CAP_8BIT);
|
||||
sprintf(aMsgBuf,"Free Heap Size: \t%ld", (long) aFreeHeapSize);
|
||||
size_t aFreeSPIHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_SPIRAM);
|
||||
size_t aFreeInternalHeapSize = heap_caps_get_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
size_t aMinFreeInternalHeapSize = heap_caps_get_minimum_free_size(MALLOC_CAP_8BIT| MALLOC_CAP_INTERNAL);
|
||||
|
||||
sprintf(aMsgBuf,"\tHeap:\t%ld", (long) aFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tMin Free:\t%ld", (long) aMinFreeHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tlarg. Block: \t%ld", (long) aHeapLargestFreeBlockSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tSPI Heap:\t%ld", (long) aFreeSPIHeapSize);
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tMin Free Heap Size:\t%ld", (long) aMinFreeHeadSize);
|
||||
sprintf(aMsgBuf,"\tNOT_SPI Heap:\t%ld", (long) (aFreeHeapSize - aFreeSPIHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tlargest Block Size: \t%ld", (long) aHeapLargestFreeBlockSize);
|
||||
sprintf(aMsgBuf,"\tInternal Heap:\t%ld", (long) (aFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
sprintf(aMsgBuf,"\tInternal Min Heap free:\t%ld", (long) (aMinFreeInternalHeapSize));
|
||||
espInfoResultStr += string(aMsgBuf);
|
||||
return espInfoResultStr;
|
||||
}
|
||||
|
||||
void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::string _ReturnRawValue, std::string _ReturnValue, std::string _ReturnPreValue, std::string _ReturnRateValue, std::string _ReturnChangeAbsolute, std::string _ErrorMessageText, std::string _digital, std::string _analog)
|
||||
{
|
||||
ESP_LOGD(TAG, "Start WriteToData");
|
||||
@@ -111,69 +78,6 @@ void ClassLogFile::WriteToData(std::string _timestamp, std::string _name, std::s
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time)
|
||||
{
|
||||
FILE* pFile;
|
||||
std::string zwtime;
|
||||
std::string 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+");
|
||||
// ESP_LOGD(TAG, "Logfile opened: %s", _fn.c_str());
|
||||
|
||||
if (pFile!=NULL) {
|
||||
if (_time)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[80];
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(buffer, 80, "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
|
||||
zwtime = std::string(buffer);
|
||||
logline = zwtime;
|
||||
}
|
||||
|
||||
std::string loglevelString;
|
||||
switch(level) {
|
||||
case ESP_LOG_ERROR:
|
||||
loglevelString = "ERR";
|
||||
break;
|
||||
case ESP_LOG_WARN:
|
||||
loglevelString = "WRN";
|
||||
break;
|
||||
case ESP_LOG_INFO:
|
||||
loglevelString = "INF";
|
||||
break;
|
||||
case ESP_LOG_DEBUG:
|
||||
loglevelString = "DBG";
|
||||
break;
|
||||
case ESP_LOG_VERBOSE:
|
||||
loglevelString = "VER";
|
||||
break;
|
||||
case ESP_LOG_NONE:
|
||||
default:
|
||||
loglevelString = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
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_LOGE(TAG, "Can't open log file %s", _fn.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
|
||||
loglevel = _logLevel;
|
||||
|
||||
@@ -207,43 +111,46 @@ void ClassLogFile::setLogLevel(esp_log_level_t _logLevel){
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetLogFileRetention(unsigned short _LogFileRetentionInDays){
|
||||
logFileRetentionInDays = _LogFileRetentionInDays;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetDataLogRetention(unsigned short _DataLogRetentionInDays){
|
||||
dataLogRetentionInDays = _DataLogRetentionInDays;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::SetDataLogToSD(bool _doDataLogToSD){
|
||||
doDataLogToSD = _doDataLogToSD;
|
||||
}
|
||||
|
||||
|
||||
bool ClassLogFile::GetDataLogToSD(){
|
||||
return doDataLogToSD;
|
||||
}
|
||||
|
||||
|
||||
static FILE* logFileAppendHandle = NULL;
|
||||
std::string fileNameDate;
|
||||
|
||||
void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::string message, bool _time)
|
||||
{
|
||||
/*
|
||||
struct stat path_stat;
|
||||
if (stat(logroot.c_str(), &path_stat) != 0) {
|
||||
ESP_LOGI(TAG, "Create log folder: %s", logroot.c_str());
|
||||
if (mkdir_r(logroot.c_str(), S_IRWXU) == -1) {
|
||||
ESP_LOGE(TAG, "Can't create log folder");
|
||||
}
|
||||
}
|
||||
*/
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
char buffer[30];
|
||||
std::string fileNameDateNew;
|
||||
|
||||
std::string zwtime;
|
||||
std::string ntpTime = "";
|
||||
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
char buf[30];
|
||||
strftime(buf, sizeof(buf), logfile.c_str(), timeinfo);
|
||||
fileNameDateNew = std::string(buf);
|
||||
|
||||
strftime(buffer, 30, logfile.c_str(), timeinfo);
|
||||
std::string logpath = logroot + "/" + buffer;
|
||||
|
||||
std::replace(message.begin(), message.end(), '\n', ' '); // Replace all newline characters
|
||||
|
||||
if (tag != "") {
|
||||
@@ -253,7 +160,89 @@ void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::stri
|
||||
else {
|
||||
ESP_LOG_LEVEL(level, "", "%s", message.c_str());
|
||||
}
|
||||
WriteToDedicatedFile(logpath, level, message, _time);
|
||||
|
||||
|
||||
if (level > loglevel) {// Only write to file if loglevel is below threshold
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_time)
|
||||
{
|
||||
char logLineDate[30];
|
||||
strftime(logLineDate, sizeof(logLineDate), "%Y-%m-%dT%H:%M:%S", timeinfo);
|
||||
ntpTime = std::string(logLineDate);
|
||||
}
|
||||
|
||||
std::string loglevelString;
|
||||
switch(level) {
|
||||
case ESP_LOG_ERROR:
|
||||
loglevelString = "ERR";
|
||||
break;
|
||||
case ESP_LOG_WARN:
|
||||
loglevelString = "WRN";
|
||||
break;
|
||||
case ESP_LOG_INFO:
|
||||
loglevelString = "INF";
|
||||
break;
|
||||
case ESP_LOG_DEBUG:
|
||||
loglevelString = "DBG";
|
||||
break;
|
||||
case ESP_LOG_VERBOSE:
|
||||
loglevelString = "VER";
|
||||
break;
|
||||
case ESP_LOG_NONE:
|
||||
default:
|
||||
loglevelString = "NONE";
|
||||
break;
|
||||
}
|
||||
|
||||
std::string formatedUptime = getFormatedUptime(true);
|
||||
|
||||
std::string fullmessage = "[" + formatedUptime + "] " + ntpTime + "\t<" + loglevelString + ">\t" + message + "\n";
|
||||
|
||||
|
||||
#ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING
|
||||
if (fileNameDateNew != fileNameDate) { // Filename changed
|
||||
// Make sure each day gets its own logfile
|
||||
// Also we need to re-open it in case it needed to get closed for reading
|
||||
std::string logpath = logroot + "/" + fileNameDateNew;
|
||||
|
||||
ESP_LOGI(TAG, "Opening logfile %s for appending", logpath.c_str());
|
||||
logFileAppendHandle = fopen(logpath.c_str(), "a+");
|
||||
if (logFileAppendHandle==NULL) {
|
||||
ESP_LOGE(TAG, "Can't open log file %s", logpath.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
fileNameDate = fileNameDateNew;
|
||||
}
|
||||
#else
|
||||
std::string logpath = logroot + "/" + fileNameDateNew;
|
||||
logFileAppendHandle = fopen(logpath.c_str(), "a+");
|
||||
if (logFileAppendHandle==NULL) {
|
||||
ESP_LOGE(TAG, "Can't open log file %s", logpath.c_str());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
fputs(fullmessage.c_str(), logFileAppendHandle);
|
||||
|
||||
#ifdef KEEP_LOGFILE_OPEN_FOR_APPENDING
|
||||
fflush(logFileAppendHandle);
|
||||
fsync(fileno(logFileAppendHandle));
|
||||
#else
|
||||
CloseLogFileAppendHandle();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::CloseLogFileAppendHandle() {
|
||||
if (logFileAppendHandle != NULL) {
|
||||
fclose(logFileAppendHandle);
|
||||
logFileAppendHandle = NULL;
|
||||
fileNameDate = "";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -261,6 +250,7 @@ void ClassLogFile::WriteToFile(esp_log_level_t level, std::string tag, std::stri
|
||||
LogFile.WriteToFile(level, tag, message, true);
|
||||
}
|
||||
|
||||
|
||||
std::string ClassLogFile::GetCurrentFileNameData()
|
||||
{
|
||||
time_t rawtime;
|
||||
@@ -292,13 +282,14 @@ std::string ClassLogFile::GetCurrentFileName()
|
||||
return logpath;
|
||||
}
|
||||
|
||||
|
||||
void ClassLogFile::RemoveOldLogFile()
|
||||
{
|
||||
if (logFileRetentionInDays == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Remove old log files");
|
||||
ESP_LOGD(TAG, "Remove old log files");
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
@@ -315,7 +306,7 @@ void ClassLogFile::RemoveOldLogFile()
|
||||
|
||||
DIR *dir = opendir(logroot.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", logroot.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir: %s", logroot.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -324,14 +315,14 @@ void ClassLogFile::RemoveOldLogFile()
|
||||
int notDeleted = 0;
|
||||
while ((entry = readdir(dir)) != NULL) {
|
||||
if (entry->d_type == DT_REG) {
|
||||
//ESP_LOGD(TAG, "compare log file : %s to %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_LOGD(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);
|
||||
ESP_LOGE(TAG, "can't delete file: %s", entry->d_name);
|
||||
notDeleted ++;
|
||||
}
|
||||
} else {
|
||||
@@ -350,7 +341,7 @@ void ClassLogFile::RemoveOldDataLog()
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Remove old data files");
|
||||
ESP_LOGD(TAG, "Remove old data files");
|
||||
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
@@ -366,7 +357,7 @@ void ClassLogFile::RemoveOldDataLog()
|
||||
|
||||
DIR *dir = opendir(dataroot.c_str());
|
||||
if (!dir) {
|
||||
ESP_LOGE(TAG, "Failed to stat dir : %s", dataroot.c_str());
|
||||
ESP_LOGE(TAG, "Failed to stat dir: %s", dataroot.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -375,14 +366,14 @@ void ClassLogFile::RemoveOldDataLog()
|
||||
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);
|
||||
//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);
|
||||
//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);
|
||||
ESP_LOGE(TAG, "can't delete file: %s", entry->d_name);
|
||||
notDeleted ++;
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CLASSLOGFILE_H
|
||||
#define CLASSLOGFILE_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "esp_log.h"
|
||||
@@ -17,8 +22,6 @@ private:
|
||||
public:
|
||||
ClassLogFile(std::string _logpath, std::string _logfile, std::string _logdatapath, std::string _datafile);
|
||||
|
||||
std::string getESPHeapInfo();
|
||||
|
||||
void WriteHeapInfo(std::string _id);
|
||||
|
||||
void setLogLevel(esp_log_level_t _logLevel);
|
||||
@@ -30,7 +33,7 @@ public:
|
||||
void WriteToFile(esp_log_level_t level, std::string tag, std::string message, bool _time);
|
||||
void WriteToFile(esp_log_level_t level, std::string tag, std::string message);
|
||||
|
||||
void WriteToDedicatedFile(std::string _fn, esp_log_level_t level, std::string message, bool _time = true);
|
||||
void CloseLogFileAppendHandle();
|
||||
|
||||
void CreateLogDirectories();
|
||||
void RemoveOldLogFile();
|
||||
@@ -44,4 +47,6 @@ public:
|
||||
std::string GetCurrentFileNameData();
|
||||
};
|
||||
|
||||
extern ClassLogFile LogFile;
|
||||
extern ClassLogFile LogFile;
|
||||
|
||||
#endif //CLASSLOGFILE_H
|
||||
@@ -2,4 +2,4 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES tflite-lib mqtt jomjol_tfliteclass jomjol_helper jomjol_mqtt jomjol_wlan)
|
||||
REQUIRES tflite-lib mqtt jomjol_tfliteclass jomjol_helper jomjol_mqtt jomjol_wlan)
|
||||
|
||||
@@ -1,38 +1,41 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
|
||||
//#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
#include "connect_wlan.h"
|
||||
#include "mqtt_client.h"
|
||||
#include "ClassLogFile.h"
|
||||
#include "server_tflite.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
static const char *TAG = "MQTT INTERFACE";
|
||||
static const char *TAG = "MQTT IF";
|
||||
|
||||
std::map<std::string, std::function<void()>>* connectFunktionMap = NULL;
|
||||
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
|
||||
|
||||
std::map<std::string, std::function<bool(std::string, char*, int)>>* subscribeFunktionMap = NULL;
|
||||
|
||||
int failedOnRound = -1;
|
||||
|
||||
esp_mqtt_event_id_t esp_mmqtt_ID = MQTT_EVENT_ANY;
|
||||
|
||||
esp_mqtt_event_id_t esp_mqtt_ID = MQTT_EVENT_ANY;
|
||||
// ESP_EVENT_ANY_ID
|
||||
|
||||
bool mqtt_enabled = false;
|
||||
bool mqtt_configOK = false;
|
||||
bool mqtt_initialized = false;
|
||||
bool mqtt_connected = false;
|
||||
|
||||
esp_mqtt_client_handle_t client = NULL;
|
||||
std::string uri, client_id, lwt_topic, lwt_connected, lwt_disconnected, user, password, maintopic;
|
||||
int keepalive, SetRetainFlag;
|
||||
void (*callbackOnConnected)(std::string, int) = NULL;
|
||||
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag) {
|
||||
int msg_id;
|
||||
std::string zw;
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag)
|
||||
{
|
||||
if (!mqtt_enabled) { // MQTT sevice not started / configured (MQTT_Init not called before)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (failedOnRound == getCountFlowRounds()) { // we already failed in this round, do not retry until the next round
|
||||
if (failedOnRound == getCountFlowRounds()) { // we already failed in this round, do not retry until the next round
|
||||
return true; // Fail quietly
|
||||
}
|
||||
|
||||
@@ -40,65 +43,67 @@ bool MQTTPublish(std::string _key, std::string _content, int retained_flag) {
|
||||
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!");
|
||||
MQTT_Init(); // Re-Init client if not initialized yet/anymore
|
||||
|
||||
if (mqtt_initialized && mqtt_connected) {
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
long long int starttime = esp_timer_get_time();
|
||||
#endif
|
||||
int msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime)/1000);
|
||||
#endif
|
||||
if (msg_id == -1) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to publish topic '" + _key + "', re-trying...");
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
starttime = esp_timer_get_time();
|
||||
#endif
|
||||
msg_id = esp_mqtt_client_publish(client, _key.c_str(), _content.c_str(), 0, 1, retained_flag);
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Publish msg_id %d in %lld ms", msg_id, (esp_timer_get_time() - starttime)/1000);
|
||||
#endif
|
||||
if (msg_id == -1) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to publish topic '" + _key + "', 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(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;
|
||||
if (_content.length() > 80) { // Truncate message if too long
|
||||
_content.resize(80);
|
||||
_content.append("..");
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Published topic: " + _key + ", content: " + _content + " (msg_id=" + std::to_string(msg_id) + ")");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_content.length() > 80) { // Truncate message if too long
|
||||
_content.resize(80);
|
||||
_content.append("..");
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publish skipped. Client not initalized or not connected. (topic: " + _key + ")");
|
||||
return false;
|
||||
}
|
||||
|
||||
zw = "Published topic: " + _key + ", content: " + _content + " (msg_id=" + std::to_string(msg_id) + ")";
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, zw);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
|
||||
{
|
||||
int msg_id;
|
||||
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_LOGD(TAG, "MQTT_EVENT_BEFORE_CONNECT");
|
||||
mqtt_initialized = true;
|
||||
break;
|
||||
case MQTT_EVENT_CONNECTED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_CONNECTED");
|
||||
mqtt_initialized = true;
|
||||
mqtt_connected = true;
|
||||
MQTTconnected();
|
||||
break;
|
||||
case 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);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Disconnected from broker");
|
||||
mqtt_connected = false;
|
||||
break;
|
||||
case MQTT_EVENT_SUBSCRIBED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_SUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
msg_id = esp_mqtt_client_publish(client, "/topic/qos0", "data", 0, 0, 0);
|
||||
ESP_LOGD(TAG, "sent publish successful, msg_id=%d", msg_id);
|
||||
break;
|
||||
case MQTT_EVENT_UNSUBSCRIBED:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_UNSUBSCRIBED, msg_id=%d", event->msg_id);
|
||||
@@ -108,12 +113,12 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
|
||||
break;
|
||||
case MQTT_EVENT_DATA:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_DATA");
|
||||
ESP_LOGD(TAG, "TOPIC=%.*s\r\n", event->topic_len, event->topic);
|
||||
ESP_LOGD(TAG, "DATA=%.*s\r\n", event->data_len, event->data);
|
||||
ESP_LOGD(TAG, "TOPIC=%.*s", event->topic_len, event->topic);
|
||||
ESP_LOGD(TAG, "DATA=%.*s", event->data_len, event->data);
|
||||
topic.assign(event->topic, event->topic_len);
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
if (subscribeFunktionMap->find(topic) != subscribeFunktionMap->end()) {
|
||||
ESP_LOGD(TAG, "call handler function\r\n");
|
||||
ESP_LOGD(TAG, "call subcribe function for topic %s", topic.c_str());
|
||||
(*subscribeFunktionMap)[topic](topic, event->data, event->data_len);
|
||||
}
|
||||
} else {
|
||||
@@ -121,8 +126,16 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
|
||||
}
|
||||
break;
|
||||
case MQTT_EVENT_ERROR:
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_ERROR");
|
||||
mqtt_connected = false; // Force re-init on next call
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "MQTT_EVENT_ERROR - esp_mqtt_error_codes:");
|
||||
ESP_LOGD(TAG, "error_type:%d", event->error_handle->error_type);
|
||||
ESP_LOGD(TAG, "connect_return_code:%d", event->error_handle->connect_return_code);
|
||||
ESP_LOGD(TAG, "esp_transport_sock_errno:%d", event->error_handle->esp_transport_sock_errno);
|
||||
ESP_LOGD(TAG, "esp_tls_last_esp_err:%d", event->error_handle->esp_tls_last_esp_err);
|
||||
ESP_LOGD(TAG, "esp_tls_stack_err:%d", event->error_handle->esp_tls_stack_err);
|
||||
ESP_LOGD(TAG, "esp_tls_cert_verify_flags:%d", event->error_handle->esp_tls_cert_verify_flags);
|
||||
#endif
|
||||
mqtt_connected = false;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGD(TAG, "Other event id:%d", event->event_id);
|
||||
@@ -131,22 +144,21 @@ static esp_err_t mqtt_event_handler_cb(esp_mqtt_event_handle_t event)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
|
||||
ESP_LOGD(TAG, "Event dispatched from event loop base=%s, event_id=%d", base, event_id);
|
||||
mqtt_event_handler_cb((esp_mqtt_event_handle_t) event_data);
|
||||
}
|
||||
|
||||
|
||||
void MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
|
||||
bool MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _user, std::string _password,
|
||||
std::string _maintopic, std::string _lwt, std::string _lwt_connected, std::string _lwt_disconnected,
|
||||
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 _keepalive, int _SetRetainFlag, void *_callbackOnConnected) {
|
||||
if ((_mqttURI.length() == 0) || (_maintopic.length() == 0) || (_clientid.length() == 0))
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Init aborted! Config error (URI, MainTopic or ClientID missing)");
|
||||
return false;
|
||||
}
|
||||
|
||||
uri = _mqttURI;
|
||||
client_id = _clientid;
|
||||
@@ -162,42 +174,74 @@ void MQTT_Configure(std::string _mqttURI, std::string _clientid, std::string _us
|
||||
user = _user;
|
||||
password = _password;
|
||||
}
|
||||
|
||||
#ifdef __HIDE_PASSWORD
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "URI: " + uri + ", clientname: " + client_id + ", user: " + user + ", password: XXXXXXXX, maintopic: "
|
||||
+ maintopic + ", last-will-topic: " + lwt_topic + ", keepAlive: " + std::to_string(keepalive) + ", RetainFlag: " + std::to_string(SetRetainFlag));
|
||||
#else
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "URI: " + uri + ", clientname: " + client_id + ", user: " + user + ", password: " + password + ", maintopic: "
|
||||
+ maintopic + ", last-will-topic: " + lwt_topic + ", keepAlive: " + std::to_string(keepalive) + ", RetainFlag: " + std::to_string(SetRetainFlag));
|
||||
#endif
|
||||
|
||||
mqtt_configOK = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MQTT_Init() {
|
||||
esp_err_t ret;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, std::string("Init"));
|
||||
|
||||
MQTTdestroy_client();
|
||||
int MQTT_Init() {
|
||||
if (mqtt_initialized) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string lw = lwt_disconnected;
|
||||
if (mqtt_configOK) {
|
||||
mqtt_enabled = true;
|
||||
} else {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init called, but client is not yet configured.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!getWIFIisConnected()) {
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Init called, but WIFI is not yet connected.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init");
|
||||
MQTTdestroy_client(false);
|
||||
|
||||
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_msg = lwt_disconnected.c_str(),
|
||||
.lwt_retain = 1,
|
||||
.lwt_msg_len = (int)(lw.length()),
|
||||
.keepalive = keepalive
|
||||
.lwt_msg_len = (int)(lwt_disconnected.length()),
|
||||
.keepalive = keepalive,
|
||||
.disable_auto_reconnect = false, // Reconnection routine active (Default: false)
|
||||
.buffer_size = 1536, // size of MQTT send/receive buffer (Default: 1024)
|
||||
.reconnect_timeout_ms = 15000, // Try to reconnect to broker (Default: 10000ms)
|
||||
.network_timeout_ms = 20000, // Network Timeout (Default: 10000ms)
|
||||
.message_retransmit_timeout = 3000 // Tiem after message resent when broker not acknowledged (QoS1, QoS2)
|
||||
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
ret = esp_mqtt_client_register_event(client, esp_mmqtt_ID, mqtt_event_handler, client);
|
||||
esp_err_t ret = esp_mqtt_client_register_event(client, esp_mqtt_ID, mqtt_event_handler, client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Could not register event (ret=" + std::to_string(ret) + ")!");
|
||||
return false;
|
||||
mqtt_initialized = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -206,36 +250,95 @@ bool MQTT_Init() {
|
||||
ret = esp_mqtt_client_start(client);
|
||||
if (ret != ESP_OK)
|
||||
{
|
||||
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;
|
||||
}
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Client start failed (retval=" + std::to_string(ret) + ")!");
|
||||
mqtt_initialized = false;
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Client started, waiting for established connection...");
|
||||
mqtt_initialized = true;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Could not init client!");
|
||||
return false;
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Init failed, no handle created!");
|
||||
mqtt_initialized = false;
|
||||
return -1;
|
||||
}
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Init successful");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void MQTTdestroy_client() {
|
||||
if (client != NULL) {
|
||||
void MQTTdestroy_client(bool _disable = false) {
|
||||
if (client) {
|
||||
if (mqtt_connected) {
|
||||
MQTTdestroySubscribeFunction();
|
||||
esp_mqtt_client_disconnect(client);
|
||||
mqtt_connected = false;
|
||||
}
|
||||
esp_mqtt_client_stop(client);
|
||||
esp_mqtt_client_destroy(client);
|
||||
client = NULL;
|
||||
mqtt_initialized = false;
|
||||
}
|
||||
|
||||
if (_disable) // Disable MQTT service, avoid restart with MQTTPublish
|
||||
mqtt_configOK = false;
|
||||
}
|
||||
|
||||
|
||||
bool getMQTTisEnabled() {
|
||||
return mqtt_enabled;
|
||||
}
|
||||
|
||||
|
||||
bool getMQTTisConnected() {
|
||||
return mqtt_connected;
|
||||
}
|
||||
|
||||
|
||||
bool mqtt_handler_flow_start(std::string _topic, char* _data, int _data_len) {
|
||||
ESP_LOGD(TAG, "Handler called: topic %s, data %.*s", _topic.c_str(), _data_len, _data);
|
||||
|
||||
if (_data_len > 0) {
|
||||
MQTTCtrlFlowStart(_topic);
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void MQTTconnected(){
|
||||
if (mqtt_connected) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected to broker");
|
||||
MQTTPublish(lwt_topic, lwt_connected, true); // Publish "connected" to maintopic/connection
|
||||
|
||||
if (connectFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
|
||||
it->second();
|
||||
ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
/* Subcribe to topics */
|
||||
std::function<bool(std::string topic, char* data, int data_len)> subHandler = mqtt_handler_flow_start;
|
||||
MQTTregisterSubscribeFunction(maintopic + "/ctrl/flow_start", subHandler); // subcribe to maintopic/ctrl/flow_start
|
||||
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
}
|
||||
}
|
||||
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS); // Delay execution of callback routine after connection got established
|
||||
if (callbackOnConnected) { // Call onConnected callback routine --> mqtt_server
|
||||
callbackOnConnected(maintopic, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MQTTisConnected() {
|
||||
return mqtt_connected;
|
||||
}
|
||||
|
||||
void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
ESP_LOGD(TAG, "MQTTregisteronnectFunction %s\r\n", name.c_str());
|
||||
@@ -255,6 +358,7 @@ void MQTTregisterConnectFunction(std::string name, std::function<void()> func){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTTunregisterConnectFunction(std::string name){
|
||||
ESP_LOGD(TAG, "unregisterConnnectFunction %s\r\n", name.c_str());
|
||||
if ((connectFunktionMap != NULL) && (connectFunktionMap->find(name) != connectFunktionMap->end())) {
|
||||
@@ -262,8 +366,9 @@ void MQTTunregisterConnectFunction(std::string name){
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::string, char*, int)> func){
|
||||
ESP_LOGD(TAG, "registerSubscribeFunction %s\r\n", topic.c_str());
|
||||
ESP_LOGD(TAG, "registerSubscribeFunction %s", topic.c_str());
|
||||
if (subscribeFunktionMap == NULL) {
|
||||
subscribeFunktionMap = new std::map<std::string, std::function<bool(std::string, char*, int)>>();
|
||||
}
|
||||
@@ -274,45 +379,15 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
|
||||
}
|
||||
|
||||
(*subscribeFunktionMap)[topic] = func;
|
||||
|
||||
if (mqtt_connected) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, topic.c_str(), 0);
|
||||
ESP_LOGD(TAG, "topic %s subscribe successful, msg_id=%d", topic.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTconnected(){
|
||||
if (mqtt_connected) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Connected");
|
||||
|
||||
MQTTPublish(lwt_topic, lwt_connected, true);
|
||||
|
||||
if (connectFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<void()>>::iterator it = connectFunktionMap->begin(); it != connectFunktionMap->end(); ++it) {
|
||||
it->second();
|
||||
ESP_LOGD(TAG, "call connect function %s", it->first.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_subscribe(client, it->first.c_str(), 0);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "topic " + it->first + " subscribe successful, msg_id=" + std::to_string(msg_id));
|
||||
}
|
||||
}
|
||||
|
||||
if (callbackOnConnected) {
|
||||
callbackOnConnected(maintopic, SetRetainFlag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MQTTdestroySubscribeFunction(){
|
||||
if (subscribeFunktionMap != NULL) {
|
||||
if (mqtt_connected) {
|
||||
for(std::map<std::string, std::function<bool(std::string, char*, int)>>::iterator it = subscribeFunktionMap->begin(); it != subscribeFunktionMap->end(); ++it) {
|
||||
int msg_id = esp_mqtt_client_unsubscribe(client, it->first.c_str());
|
||||
ESP_LOGI(TAG, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
ESP_LOGD(TAG, "topic %s unsubscribe successful, msg_id=%d", it->first.c_str(), msg_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -321,3 +396,4 @@ void MQTTdestroySubscribeFunction(){
|
||||
subscribeFunktionMap = NULL;
|
||||
}
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef INTERFACE_MQTT_H
|
||||
#define INTERFACE_MQTT_H
|
||||
|
||||
@@ -5,15 +9,16 @@
|
||||
#include <map>
|
||||
#include <functional>
|
||||
|
||||
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 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);
|
||||
int MQTT_Init();
|
||||
void MQTTdestroy_client(bool _disable);
|
||||
|
||||
bool MQTTPublish(std::string _key, std::string _content, int retained_flag = 1); // retained Flag as Standart
|
||||
|
||||
bool MQTTisConnected();
|
||||
bool getMQTTisEnabled();
|
||||
bool getMQTTisConnected();
|
||||
|
||||
void MQTTregisterConnectFunction(std::string name, std::function<void()> func);
|
||||
void MQTTunregisterConnectFunction(std::string name);
|
||||
@@ -21,4 +26,5 @@ void MQTTregisterSubscribeFunction(std::string topic, std::function<bool(std::st
|
||||
void MQTTdestroySubscribeFunction();
|
||||
void MQTTconnected();
|
||||
|
||||
#endif //INTERFACE_MQTT_H
|
||||
#endif //INTERFACE_MQTT_H
|
||||
#endif //#ENABLE_MQTT
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
@@ -9,6 +10,7 @@
|
||||
#include "server_mqtt.h"
|
||||
#include "interface_mqtt.h"
|
||||
#include "time_sntp.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
|
||||
@@ -55,7 +57,6 @@ void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
|
||||
std::string topicFull;
|
||||
std::string configTopic;
|
||||
std::string payload;
|
||||
std::string nl = "\n";
|
||||
|
||||
configTopic = field;
|
||||
|
||||
@@ -72,62 +73,70 @@ void sendHomeAssistantDiscoveryTopic(std::string group, std::string field,
|
||||
}
|
||||
|
||||
/* See https://www.home-assistant.io/docs/mqtt/discovery/ */
|
||||
payload = "{" + nl +
|
||||
"\"~\": \"" + maintopic + "\"," + nl +
|
||||
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," + nl +
|
||||
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + nl + // This used to generate the Entity ID
|
||||
"\"name\": \"" + name + "\"," + nl +
|
||||
"\"icon\": \"mdi:" + icon + "\"," + nl;
|
||||
payload = string("{") +
|
||||
"\"~\": \"" + maintopic + "\"," +
|
||||
"\"unique_id\": \"" + maintopic + "-" + configTopic + "\"," +
|
||||
"\"object_id\": \"" + maintopic + "_" + configTopic + "\"," + // This used to generate the Entity ID
|
||||
"\"name\": \"" + name + "\"," +
|
||||
"\"icon\": \"mdi:" + icon + "\",";
|
||||
|
||||
if (group != "") {
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
payload += "\"state_topic\": \"~/" + group + "/error\"," + nl;
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\"," + nl;
|
||||
payload += "\"state_topic\": \"~/" + group + "/error\",";
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + group + "/" + field + "\"," + nl;
|
||||
payload += "\"state_topic\": \"~/" + group + "/" + field + "\",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + field + "\"," + nl;
|
||||
if (field == "problem") { // Special binary sensor which is based on error topic
|
||||
payload += "\"state_topic\": \"~/error\",";
|
||||
payload += "\"value_template\": \"{{ 'OFF' if 'no error' in value else 'ON'}}\",";
|
||||
}
|
||||
else {
|
||||
payload += "\"state_topic\": \"~/" + field + "\",";
|
||||
}
|
||||
}
|
||||
|
||||
if (unit != "") {
|
||||
payload += "\"unit_of_meas\": \"" + unit + "\"," + nl;
|
||||
payload += "\"unit_of_meas\": \"" + unit + "\",";
|
||||
}
|
||||
|
||||
if (deviceClass != "") {
|
||||
payload += "\"device_class\": \"" + deviceClass + "\"," + nl;
|
||||
payload += "\"device_class\": \"" + deviceClass + "\",";
|
||||
}
|
||||
|
||||
if (stateClass != "") {
|
||||
payload += "\"state_class\": \"" + stateClass + "\"," + nl;
|
||||
payload += "\"state_class\": \"" + stateClass + "\",";
|
||||
}
|
||||
|
||||
if (entityCategory != "") {
|
||||
payload += "\"entity_category\": \"" + entityCategory + "\"," + nl;
|
||||
payload += "\"entity_category\": \"" + entityCategory + "\",";
|
||||
}
|
||||
|
||||
payload +=
|
||||
"\"availability_topic\": \"~/" + std::string(LWT_TOPIC) + "\"," + nl +
|
||||
"\"payload_available\": \"" + LWT_CONNECTED + "\"," + nl +
|
||||
"\"payload_not_available\": \"" + LWT_DISCONNECTED + "\"," + nl;
|
||||
"\"availability_topic\": \"~/" + std::string(LWT_TOPIC) + "\"," +
|
||||
"\"payload_available\": \"" + LWT_CONNECTED + "\"," +
|
||||
"\"payload_not_available\": \"" + LWT_DISCONNECTED + "\",";
|
||||
|
||||
payload +=
|
||||
"\"device\": {" + nl +
|
||||
"\"identifiers\": [\"" + maintopic + "\"]," + nl +
|
||||
"\"name\": \"" + maintopic + "\"," + nl +
|
||||
"\"model\": \"Meter Digitizer\"," + nl +
|
||||
"\"manufacturer\": \"AI on the Edge Device\"," + nl +
|
||||
"\"sw_version\": \"" + version + "\"," + nl +
|
||||
"\"configuration_url\": \"http://" + *getIPAddress() + "\"" + nl +
|
||||
"}" + nl +
|
||||
"}" + nl;
|
||||
payload += string("\"device\": {") +
|
||||
"\"identifiers\": [\"" + maintopic + "\"]," +
|
||||
"\"name\": \"" + maintopic + "\"," +
|
||||
"\"model\": \"Meter Digitizer\"," +
|
||||
"\"manufacturer\": \"AI on the Edge Device\"," +
|
||||
"\"sw_version\": \"" + version + "\"," +
|
||||
"\"configuration_url\": \"http://" + *getIPAddress() + "\"" +
|
||||
"}" +
|
||||
"}";
|
||||
|
||||
MQTTPublish(topicFull, payload, true);
|
||||
}
|
||||
|
||||
void MQTThomeassistantDiscovery() {
|
||||
void MQTThomeassistantDiscovery() {
|
||||
if (!getMQTTisConnected())
|
||||
return;
|
||||
|
||||
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
|
||||
@@ -144,7 +153,11 @@ void MQTThomeassistantDiscovery() {
|
||||
|
||||
|
||||
for (int i = 0; i < (*NUMBERS).size(); ++i) {
|
||||
std::string group = (*NUMBERS)[i]->name;
|
||||
std::string group = (*NUMBERS)[i]->name;
|
||||
if (group == "default") {
|
||||
group = "";
|
||||
}
|
||||
|
||||
// Group | Field | User Friendly Name | Icon | Unit | Device Class | State Class | Entity Category
|
||||
sendHomeAssistantDiscoveryTopic(group, "value", "Value", "gauge", valueUnit, meterType, "total_increasing", "");
|
||||
sendHomeAssistantDiscoveryTopic(group, "raw", "Raw Value", "raw", valueUnit, "", "total_increasing", "diagnostic");
|
||||
@@ -155,19 +168,22 @@ void MQTThomeassistantDiscovery() {
|
||||
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
|
||||
sendHomeAssistantDiscoveryTopic(group, "problem", "Problem", "alert-outline", "", "problem", "", ""); // Special binary sensor which is based on error topic
|
||||
}
|
||||
}
|
||||
|
||||
void publishSystemData() {
|
||||
if (!getMQTTisConnected())
|
||||
return;
|
||||
|
||||
char tmp_char[50];
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing system MQTT topics...");
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, 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());
|
||||
sprintf(tmp_char, "%lu", (long) getESPHeapSize());
|
||||
MQTTPublish(maintopic + "/" + "freeMem", std::string(tmp_char), retainFlag);
|
||||
|
||||
sprintf(tmp_char, "%d", get_WIFI_RSSI());
|
||||
@@ -179,7 +195,10 @@ void publishSystemData() {
|
||||
|
||||
|
||||
void publishStaticData() {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Publishing static MQTT topics...");
|
||||
if (!getMQTTisConnected())
|
||||
return;
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Publishing static MQTT topics...");
|
||||
MQTTPublish(maintopic + "/" + "MAC", getMac(), retainFlag);
|
||||
MQTTPublish(maintopic + "/" + "IP", *getIPAddress(), retainFlag);
|
||||
MQTTPublish(maintopic + "/" + "hostname", hostname, retainFlag);
|
||||
@@ -243,3 +262,5 @@ void mqttServer_setMainTopic( std::string _maintopic) {
|
||||
std::string mqttServer_getMainTopic() {
|
||||
return maintopic;
|
||||
}
|
||||
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
#ifdef ENABLE_MQTT
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERMQTT_H
|
||||
#define SERVERMQTT_H
|
||||
|
||||
#include "ClassFlowDefineTypes.h"
|
||||
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
|
||||
void SetHomeassistantDiscoveryEnabled(bool enabled);
|
||||
void mqttServer_setParameter(std::vector<NumberPost*>* _NUMBERS, int interval, float roundInterval);
|
||||
void mqttServer_setMeterType(std::string meterType, std::string valueUnit, std::string timeUnit,std::string rateUnit);
|
||||
@@ -17,4 +19,8 @@ void register_server_mqtt_uri(httpd_handle_t server);
|
||||
void publishSystemData();
|
||||
|
||||
std::string getTimeUnit(void);
|
||||
void GotConnected(std::string maintopic, int SetRetainFlag);
|
||||
void GotConnected(std::string maintopic, int SetRetainFlag);
|
||||
|
||||
|
||||
#endif //SERVERMQTT_H
|
||||
#endif //ENABLE_MQTT
|
||||
@@ -2,13 +2,14 @@
|
||||
#include "ClassLogFile.h"
|
||||
#include "Helper.h"
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
// #define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
static const char *TAG = "C TFLITE";
|
||||
static const char *TAG = "TFLITE";
|
||||
|
||||
float CTfLiteClass::GetOutputValue(int nr)
|
||||
{
|
||||
@@ -55,7 +56,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
|
||||
if (_bis >= numeroutput)
|
||||
{
|
||||
ESP_LOGD(TAG, "ANZAHL OUTPUT NEURONS passt nicht zu geforderter Classifizierung!");
|
||||
ESP_LOGD(TAG, "NUMBER OF OUTPUT NEURONS does not match required classification!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -73,6 +74,7 @@ int CTfLiteClass::GetOutClassification(int _von, int _bis)
|
||||
return (zw_class - _von);
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::GetInputDimension(bool silent = false)
|
||||
{
|
||||
TfLiteTensor* input2 = this->interpreter->input(0);
|
||||
@@ -91,6 +93,7 @@ void CTfLiteClass::GetInputDimension(bool silent = false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int CTfLiteClass::ReadInputDimenstion(int _dim)
|
||||
{
|
||||
if (_dim == 0)
|
||||
@@ -104,7 +107,6 @@ int CTfLiteClass::ReadInputDimenstion(int _dim)
|
||||
}
|
||||
|
||||
|
||||
|
||||
int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
{
|
||||
TfLiteTensor* output2 = this->interpreter->output(0);
|
||||
@@ -132,6 +134,7 @@ int CTfLiteClass::GetAnzOutPut(bool silent)
|
||||
return numeroutput;
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::Invoke()
|
||||
{
|
||||
if (interpreter != nullptr)
|
||||
@@ -139,10 +142,11 @@ void CTfLiteClass::Invoke()
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
{
|
||||
std::string zw = "ClassFlowCNNGeneral::doNeuralNetwork after LoadInputResizeImage: ";
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - Start");
|
||||
#endif
|
||||
|
||||
unsigned int w = rs->width;
|
||||
unsigned int h = rs->height;
|
||||
@@ -166,34 +170,54 @@ bool CTfLiteClass::LoadInputImageBasis(CImageBasis *rs)
|
||||
input_data_ptr++;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "Nach dem Laden in input");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::LoadInputImageBasis - done");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CTfLiteClass::MakeAllocate()
|
||||
bool CTfLiteClass::MakeAllocate()
|
||||
{
|
||||
static tflite::AllOpsResolver resolver;
|
||||
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::MakeAllocate");
|
||||
this->interpreter = new tflite::MicroInterpreter(this->model, resolver, this->tensor_arena, this->kTensorArenaSize, this->error_reporter);
|
||||
// ESP_LOGD(TAG, "%s", LogFile.getESPHeapInfo().c_str());
|
||||
|
||||
TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
|
||||
if (this->interpreter)
|
||||
{
|
||||
TfLiteStatus allocate_status = this->interpreter->AllocateTensors();
|
||||
if (allocate_status != kTfLiteOk) {
|
||||
TF_LITE_REPORT_ERROR(error_reporter, "AllocateTensors() failed");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "AllocateTensors() failed");
|
||||
|
||||
this->GetInputDimension();
|
||||
return;
|
||||
}
|
||||
// ESP_LOGD(TAG, "Allocate Done");
|
||||
this->GetInputDimension();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "new tflite::MicroInterpreter failed");
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::MakeAllocate-new tflite::MicroInterpreter failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc done");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CTfLiteClass::GetInputTensorSize(){
|
||||
|
||||
void CTfLiteClass::GetInputTensorSize()
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
float *zw = this->input;
|
||||
int test = sizeof(zw);
|
||||
@@ -201,6 +225,7 @@ void CTfLiteClass::GetInputTensorSize(){
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
long CTfLiteClass::GetFileSize(std::string filename)
|
||||
{
|
||||
struct stat stat_buf;
|
||||
@@ -209,90 +234,95 @@ long CTfLiteClass::GetFileSize(std::string filename)
|
||||
}
|
||||
|
||||
|
||||
unsigned char* CTfLiteClass::ReadFileToCharArray(std::string _fn)
|
||||
bool CTfLiteClass::ReadFileToModel(std::string _fn)
|
||||
{
|
||||
long size;
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::ReadFileToModel: " + _fn);
|
||||
|
||||
size = GetFileSize(_fn);
|
||||
long size = GetFileSize(_fn);
|
||||
|
||||
if (size == -1)
|
||||
{
|
||||
ESP_LOGD(TAG, "File doesn't exist");
|
||||
return NULL;
|
||||
ESP_LOGE(TAG, "CTfLiteClass::ReadFileToModel: Model file doesn't exist: %s", _fn.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned char *result = (unsigned char*) malloc(size);
|
||||
int anz = 1;
|
||||
while (!result && (anz < 6)) // maximal 5x versuchen (= 5s)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
ESP_LOGD(TAG, "Speicher ist voll - Versuche es erneut: %d", anz);
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile start");
|
||||
#endif
|
||||
result = (unsigned char*) malloc(size);
|
||||
anz++;
|
||||
}
|
||||
|
||||
modelfile = (unsigned char*)GET_MEMORY(size);
|
||||
|
||||
if(result != NULL) {
|
||||
FILE* f = OpenFileAndWait(_fn.c_str(), "rb"); // vorher nur "r"
|
||||
fread(result, 1, size, f);
|
||||
if(modelfile != NULL)
|
||||
{
|
||||
FILE* f = fopen(_fn.c_str(), "rb"); // previously only "r
|
||||
fread(modelfile, 1, size, f);
|
||||
fclose(f);
|
||||
}else {
|
||||
ESP_LOGD(TAG, "No free memory available");
|
||||
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("CTLiteClass::Alloc modelfile successful");
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "CTfLiteClass::ReadFileToModel: Can't allocate enough memory: " + std::to_string(size));
|
||||
LogFile.WriteHeapInfo("CTfLiteClass::ReadFileToModel");
|
||||
|
||||
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CTfLiteClass::LoadModel(std::string _fn){
|
||||
|
||||
bool CTfLiteClass::LoadModel(std::string _fn)
|
||||
{
|
||||
#ifdef SUPRESS_TFLITE_ERRORS
|
||||
this->error_reporter = new tflite::OwnMicroErrorReporter;
|
||||
#else
|
||||
this->error_reporter = new tflite::MicroErrorReporter;
|
||||
#endif
|
||||
|
||||
modelload = ReadFileToCharArray(_fn.c_str());
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "CTfLiteClass::LoadModel");
|
||||
|
||||
if (modelload == NULL)
|
||||
if (!ReadFileToModel(_fn.c_str())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
model = tflite::GetModel(modelload);
|
||||
// free(rd);
|
||||
TFLITE_MINIMAL_CHECK(model != nullptr);
|
||||
model = tflite::GetModel(modelfile);
|
||||
|
||||
if(model == nullptr)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CTfLiteClass::CTfLiteClass()
|
||||
{
|
||||
this->model = nullptr;
|
||||
this->modelfile = NULL;
|
||||
this->interpreter = nullptr;
|
||||
this->input = nullptr;
|
||||
this->output = nullptr;
|
||||
this->kTensorArenaSize = 800 * 1024; /// laut testfile: 108000 - bisher 600;; 2021-09-11: 200 * 1024
|
||||
this->tensor_arena = new uint8_t[kTensorArenaSize];
|
||||
this->kTensorArenaSize = 800 * 1024; /// according to testfile: 108000 - so far 600;; 2021-09-11: 200 * 1024
|
||||
this->tensor_arena = (uint8_t*)GET_MEMORY(kTensorArenaSize);
|
||||
}
|
||||
|
||||
|
||||
CTfLiteClass::~CTfLiteClass()
|
||||
{
|
||||
delete this->tensor_arena;
|
||||
free(modelfile);
|
||||
|
||||
free(this->tensor_arena);
|
||||
delete this->interpreter;
|
||||
delete this->error_reporter;
|
||||
if (modelload)
|
||||
free(modelload);
|
||||
}
|
||||
|
||||
|
||||
namespace tflite {
|
||||
|
||||
int OwnMicroErrorReporter::Report(const char* format, va_list args) {
|
||||
namespace tflite
|
||||
{
|
||||
int OwnMicroErrorReporter::Report(const char* format, va_list args)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define TFLITE_MINIMAL_CHECK(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
}
|
||||
#ifndef CTFLITECLASS_H
|
||||
#define CTFLITECLASS_H
|
||||
|
||||
#include "tensorflow/lite/micro/all_ops_resolver.h"
|
||||
#include "tensorflow/lite/micro/micro_error_reporter.h"
|
||||
@@ -15,10 +13,6 @@
|
||||
|
||||
#include "CImageBasis.h"
|
||||
|
||||
|
||||
|
||||
#define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE
|
||||
|
||||
#ifdef SUPRESS_TFLITE_ERRORS
|
||||
#include "tensorflow/lite/core/api/error_reporter.h"
|
||||
#include "tensorflow/lite/micro/compatibility.h"
|
||||
@@ -45,7 +39,7 @@ class CTfLiteClass
|
||||
int kTensorArenaSize;
|
||||
uint8_t *tensor_arena;
|
||||
|
||||
unsigned char *modelload = NULL;
|
||||
unsigned char *modelfile = NULL;
|
||||
|
||||
|
||||
float* input;
|
||||
@@ -53,13 +47,13 @@ class CTfLiteClass
|
||||
int im_height, im_width, im_channel;
|
||||
|
||||
long GetFileSize(std::string filename);
|
||||
unsigned char* ReadFileToCharArray(std::string _fn);
|
||||
|
||||
bool ReadFileToModel(std::string _fn);
|
||||
|
||||
public:
|
||||
CTfLiteClass();
|
||||
~CTfLiteClass();
|
||||
bool LoadModel(std::string _fn);
|
||||
void MakeAllocate();
|
||||
bool MakeAllocate();
|
||||
void GetInputTensorSize();
|
||||
bool LoadInputImageBasis(CImageBasis *rs);
|
||||
void Invoke();
|
||||
@@ -74,3 +68,4 @@ class CTfLiteClass
|
||||
int ReadInputDimenstion(int _dim);
|
||||
};
|
||||
|
||||
#endif //CTFLITECLASS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,3 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef SERVERTFLITE_H
|
||||
#define SERVERTFLITE_H
|
||||
|
||||
#include <esp_log.h>
|
||||
#include <string>
|
||||
|
||||
@@ -7,20 +12,22 @@
|
||||
|
||||
//#include "ClassControllCamera.h"
|
||||
|
||||
extern ClassFlowControll tfliteflow;
|
||||
void register_server_tflite_uri(httpd_handle_t server);
|
||||
|
||||
void KillTFliteTasks();
|
||||
|
||||
void TFliteDoAutoStart();
|
||||
|
||||
bool isSetupModusActive();
|
||||
|
||||
std::string GetMQTTMainTopic();
|
||||
|
||||
int getCountFlowRounds();
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
|
||||
void CheckIsPlannedReboot();
|
||||
|
||||
esp_err_t GetJPG(std::string _filename, httpd_req_t *req);
|
||||
esp_err_t GetRawJPG(httpd_req_t *req);
|
||||
|
||||
extern ClassFlowControll tfliteflow;
|
||||
#ifdef ENABLE_MQTT
|
||||
std::string GetMQTTMainTopic();
|
||||
esp_err_t MQTTCtrlFlowStart(std::string);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#endif //SERVERTFLITE_H
|
||||
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES tflite-lib jomjol_logfile)
|
||||
REQUIRES tflite-lib jomjol_logfile jomjol_configfile)
|
||||
|
||||
|
||||
|
||||
@@ -12,21 +12,24 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_sntp.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "configFile.h"
|
||||
#include "Helper.h"
|
||||
|
||||
|
||||
static const char *TAG = "SNTP";
|
||||
|
||||
time_t bootTime;
|
||||
static std::string timeZone = "";
|
||||
static std::string timeServer = "undefined";
|
||||
static bool useNtp = true;
|
||||
|
||||
static bool obtain_time(void);
|
||||
static void initialize_sntp(void);
|
||||
static void logNtpStatus(sntp_sync_status_t status);
|
||||
std::string getNtpStatusText(sntp_sync_status_t status);
|
||||
static void setTimeZone(std::string _tzstring);
|
||||
static std::string getServerName(void);
|
||||
|
||||
void time_sync_notification_cb(struct timeval *tv)
|
||||
{
|
||||
ESP_LOGI(TAG, "Notification of a time synchronization event");
|
||||
}
|
||||
|
||||
std::string ConvertTimeToString(time_t _time, const char * frm)
|
||||
{
|
||||
@@ -39,7 +42,8 @@ std::string ConvertTimeToString(time_t _time, const char * frm)
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string gettimestring(const char * frm)
|
||||
|
||||
std::string getCurrentTimeString(const char * frm)
|
||||
{
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
@@ -52,40 +56,14 @@ std::string gettimestring(const char * frm)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool setup_time()
|
||||
|
||||
void time_sync_notification_cb(struct timeval *tv)
|
||||
{
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
bool success = true;
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if (!getTimeIsSet()) {
|
||||
ESP_LOGI(TAG, "Time is not set yet. Getting time over NTP.");
|
||||
initialize_sntp();
|
||||
if (!obtain_time()) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
// update 'now' variable with current time
|
||||
time(&now);
|
||||
|
||||
setTimeZone("CET-1CEST,M3.5.0,M10.5.0/3");
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
}
|
||||
else {
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGI(TAG, "Time is already set (%s)", strftime_buf);
|
||||
}
|
||||
return success;
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is now successfully synced with NTP Server " +
|
||||
getServerName() + ": " + getCurrentTimeString("%Y-%m-%d %H:%M:%S"));
|
||||
}
|
||||
|
||||
|
||||
void setTimeZone(std::string _tzstring)
|
||||
{
|
||||
setenv("TZ", _tzstring.c_str(), 1);
|
||||
@@ -94,100 +72,25 @@ void setTimeZone(std::string _tzstring)
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, _tzstring);
|
||||
}
|
||||
|
||||
static bool obtain_time(void)
|
||||
{
|
||||
time_t now = 0;
|
||||
struct tm timeinfo = {};
|
||||
int retry = 0;
|
||||
const int retry_count = 10;
|
||||
bool success = true;
|
||||
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
|
||||
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) {
|
||||
std::string getNtpStatusText(sntp_sync_status_t status) {
|
||||
if (status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status OK");
|
||||
return "Synchronized";
|
||||
}
|
||||
else if (status == SNTP_SYNC_STATUS_IN_PROGRESS) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status: In Progress");
|
||||
return "In Progress";
|
||||
}
|
||||
else { // SNTP_SYNC_STATUS_RESET
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "NTP Status: Reset");
|
||||
return "Reset";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void reset_servername(std::string _servername)
|
||||
{
|
||||
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");
|
||||
ESP_LOGD(TAG, "Time ist %s", zw.c_str());
|
||||
}
|
||||
|
||||
static void initialize_sntp(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "Initializing SNTP");
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, "pool.ntp.org");
|
||||
// sntp_set_time_sync_notification_cb(time_sync_notification_cb);
|
||||
sntp_init();
|
||||
}
|
||||
|
||||
void setBootTime()
|
||||
{
|
||||
time(&bootTime);
|
||||
}
|
||||
|
||||
time_t getUpTime()
|
||||
{
|
||||
time_t now;
|
||||
time(&now);
|
||||
|
||||
return now - bootTime;
|
||||
}
|
||||
|
||||
bool getTimeIsSet(void) {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
char strftime_buf[64];
|
||||
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d_%H:%M:%S", &timeinfo);
|
||||
ESP_LOGD(TAG, "The current date/time in Berlin is: %s", strftime_buf);
|
||||
|
||||
// Is time set? If not, tm_year will be (1970 - 1900).
|
||||
if ((timeinfo.tm_year < (2022 - 1900))) {
|
||||
@@ -198,7 +101,132 @@ bool getTimeIsSet(void) {
|
||||
}
|
||||
}
|
||||
|
||||
void restartNtpClient(void) {
|
||||
sntp_restart();
|
||||
obtain_time();
|
||||
/*void restartNtpClient(void) {
|
||||
// sntp_restart();
|
||||
// obtain_time();
|
||||
}*/
|
||||
|
||||
|
||||
bool getUseNtp(void) {
|
||||
return useNtp;
|
||||
}
|
||||
|
||||
|
||||
std::string getServerName(void) {
|
||||
char buf[100];
|
||||
|
||||
if (sntp_getservername(0)){
|
||||
snprintf(buf, sizeof(buf), "%s", sntp_getservername(0));
|
||||
return std::string(buf);
|
||||
}
|
||||
else { // we have either IPv4 or IPv6 address
|
||||
ip_addr_t const *ip = sntp_getserver(0);
|
||||
if (ipaddr_ntoa_r(ip, buf, sizeof(buf)) != NULL) {
|
||||
return std::string(buf);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load the TimeZone and TimeServer from the config file and initialize the NTP client
|
||||
*/
|
||||
bool setupTime() {
|
||||
time_t now;
|
||||
struct tm timeinfo;
|
||||
char strftime_buf[64];
|
||||
|
||||
ConfigFile configFile = ConfigFile(CONFIG_FILE);
|
||||
|
||||
if (!configFile.ConfigFileExists()){
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "No ConfigFile defined - exit setupTime() ");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<std::string> splitted;
|
||||
std::string line = "";
|
||||
bool disabledLine = false;
|
||||
bool eof = false;
|
||||
|
||||
/* Load config from config file */
|
||||
while ((!configFile.GetNextParagraph(line, disabledLine, eof) ||
|
||||
(line.compare("[System]") != 0)) && !eof) {}
|
||||
if (eof) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (disabledLine) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (configFile.getNextLine(&line, disabledLine, eof) &&
|
||||
!configFile.isNewParagraph(line)) {
|
||||
splitted = ZerlegeZeile(line);
|
||||
|
||||
if (toUpper(splitted[0]) == "TIMEZONE") {
|
||||
timeZone = splitted[1];
|
||||
}
|
||||
|
||||
if (toUpper(splitted[0]) == "TIMESERVER") {
|
||||
if (splitted.size() <= 1) { // Key has no value => we use this to show it as disabled
|
||||
timeServer = "";
|
||||
}
|
||||
else {
|
||||
timeServer = splitted[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Setup NTP Server and Timezone */
|
||||
if (timeServer == "undefined") {
|
||||
timeServer = "pool.ntp.org";
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer not defined, using default: " + timeServer);
|
||||
}
|
||||
else if (timeServer == "") {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer config empty, disabling NTP");
|
||||
useNtp = false;
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeServer: " + timeServer);
|
||||
}
|
||||
|
||||
if (timeZone == "") {
|
||||
timeZone = "CET-1CEST,M3.5.0,M10.5.0/3";
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "TimeZone not set, using default: " + timeZone);
|
||||
}
|
||||
|
||||
|
||||
if (useNtp) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Configuring NTP Client...");
|
||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||
sntp_setservername(0, timeServer.c_str());
|
||||
sntp_init();
|
||||
|
||||
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
|
||||
|
||||
setTimeZone(timeZone);
|
||||
}
|
||||
|
||||
|
||||
/* The RTC keeps the time after a restart (Except on Power On or Pin Reset)
|
||||
* There should only be a minor correction through NTP */
|
||||
|
||||
// Get current time from RTC
|
||||
time(&now);
|
||||
localtime_r(&now, &timeinfo);
|
||||
strftime(strftime_buf, sizeof(strftime_buf), "%Y-%m-%d %H:%M:%S", &timeinfo);
|
||||
|
||||
if (getTimeIsSet()) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Time is already set: " + std::string(strftime_buf));
|
||||
}
|
||||
else {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "The local time is unknown, starting with " + std::string(strftime_buf));
|
||||
if (useNtp) {
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Once the NTP server provides a time, we will switch to that one");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef TIMESNTP_H
|
||||
#define TIMESNTP_H
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
@@ -9,18 +15,15 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
// #include "nvs_flash.h"
|
||||
#include "esp_sntp.h"
|
||||
|
||||
bool setup_time(void);
|
||||
|
||||
std::string gettimestring(const char * frm);
|
||||
std::string getCurrentTimeString(const char * frm);
|
||||
std::string ConvertTimeToString(time_t _time, const char * frm);
|
||||
|
||||
void setTimeZone(std::string _tzstring);
|
||||
void reset_servername(std::string _servername);
|
||||
|
||||
void setBootTime();
|
||||
time_t getUpTime();
|
||||
bool getTimeIsSet(void);
|
||||
void restartNtpClient(void);
|
||||
|
||||
bool getUseNtp(void);
|
||||
bool setupTime();
|
||||
|
||||
#endif //TIMESNTP_H
|
||||
@@ -2,6 +2,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_CURRENT_SOURCE_DIR}/*.*)
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES nvs_flash jomjol_helper)
|
||||
REQUIRES nvs_flash jomjol_helper jomjol_mqtt wpa_supplicant)
|
||||
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "interface_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
@@ -20,27 +23,36 @@
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
//////////////////////
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wnm.h"
|
||||
#include "esp_rrm.h"
|
||||
#include "esp_mbo.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
|
||||
|
||||
/////////////////////
|
||||
#include "../../include/defines.h"
|
||||
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY 1000
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected*/
|
||||
static EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
static const char *TAG = "WIFI";
|
||||
|
||||
static int s_retry_num = 0;
|
||||
bool WIFIConnected = false;
|
||||
|
||||
///////////////////////////////////////////////////////////
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
int BlinkDauer;
|
||||
int BlinkAnzahl;
|
||||
@@ -51,12 +63,248 @@ std::string hostname = "";
|
||||
std::string std_hostname = "watermeter";
|
||||
std::string ipadress = "";
|
||||
std::string ssid = "";
|
||||
int RSSIThreashold;
|
||||
|
||||
/////////////////////////////////
|
||||
/////////////////////////////////
|
||||
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
|
||||
int RSSI_Threshold = WLAN_WIFI_RSSI_THRESHOLD;
|
||||
|
||||
/* rrm ctx */
|
||||
int rrm_ctx = 0;
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected & ready to make a request */
|
||||
static EventGroupHandle_t wifi_event_group;
|
||||
|
||||
/* esp netif object representing the WIFI station */
|
||||
static esp_netif_t *sta_netif = NULL;
|
||||
|
||||
//static const char *TAG = "roaming_example";
|
||||
|
||||
static inline uint32_t WPA_GET_LE32(const uint8_t *a)
|
||||
{
|
||||
return ((uint32_t) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0];
|
||||
}
|
||||
|
||||
|
||||
#ifndef WLAN_EID_MEASURE_REPORT
|
||||
#define WLAN_EID_MEASURE_REPORT 39
|
||||
#endif
|
||||
#ifndef MEASURE_TYPE_LCI
|
||||
#define MEASURE_TYPE_LCI 9
|
||||
#endif
|
||||
#ifndef MEASURE_TYPE_LOCATION_CIVIC
|
||||
#define MEASURE_TYPE_LOCATION_CIVIC 11
|
||||
#endif
|
||||
#ifndef WLAN_EID_NEIGHBOR_REPORT
|
||||
#define WLAN_EID_NEIGHBOR_REPORT 52
|
||||
#endif
|
||||
#ifndef ETH_ALEN
|
||||
#define ETH_ALEN 6
|
||||
#endif
|
||||
|
||||
#define MAX_NEIGHBOR_LEN 512
|
||||
static char * get_btm_neighbor_list(uint8_t *report, size_t report_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
const uint8_t *data;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
* Neighbor Report element (IEEE P802.11-REVmc/D5.0)
|
||||
* BSSID[6]
|
||||
* BSSID Information[4]
|
||||
* Operating Class[1]
|
||||
* Channel Number[1]
|
||||
* PHY Type[1]
|
||||
* Optional Subelements[variable]
|
||||
*/
|
||||
#define NR_IE_MIN_LEN (ETH_ALEN + 4 + 1 + 1 + 1)
|
||||
|
||||
if (!report || report_len == 0) {
|
||||
ESP_LOGI(TAG, "RRM neighbor report is not valid");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *buf = (char*) calloc(1, MAX_NEIGHBOR_LEN);
|
||||
data = report;
|
||||
|
||||
while (report_len >= 2 + NR_IE_MIN_LEN) {
|
||||
const uint8_t *nr;
|
||||
char lci[256 * 2 + 1];
|
||||
char civic[256 * 2 + 1];
|
||||
uint8_t nr_len = data[1];
|
||||
const uint8_t *pos = data, *end;
|
||||
|
||||
if (pos[0] != WLAN_EID_NEIGHBOR_REPORT ||
|
||||
nr_len < NR_IE_MIN_LEN) {
|
||||
ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%u",
|
||||
data[0], nr_len);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (2U + nr_len > report_len) {
|
||||
ESP_LOGI(TAG, "CTRL: Invalid Neighbor Report element: id=%u len=%zu nr_len=%u",
|
||||
data[0], report_len, nr_len);
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
pos += 2;
|
||||
end = pos + nr_len;
|
||||
|
||||
nr = pos;
|
||||
pos += NR_IE_MIN_LEN;
|
||||
|
||||
lci[0] = '\0';
|
||||
civic[0] = '\0';
|
||||
while (end - pos > 2) {
|
||||
uint8_t s_id, s_len;
|
||||
|
||||
s_id = *pos++;
|
||||
s_len = *pos++;
|
||||
if (s_len > end - pos) {
|
||||
ret = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
if (s_id == WLAN_EID_MEASURE_REPORT && s_len > 3) {
|
||||
/* Measurement Token[1] */
|
||||
/* Measurement Report Mode[1] */
|
||||
/* Measurement Type[1] */
|
||||
/* Measurement Report[variable] */
|
||||
switch (pos[2]) {
|
||||
case MEASURE_TYPE_LCI:
|
||||
if (lci[0])
|
||||
break;
|
||||
memcpy(lci, pos, s_len);
|
||||
break;
|
||||
case MEASURE_TYPE_LOCATION_CIVIC:
|
||||
if (civic[0])
|
||||
break;
|
||||
memcpy(civic, pos, s_len);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pos += s_len;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "RMM neigbor report bssid=" MACSTR
|
||||
" info=0x%x op_class=%u chan=%u phy_type=%u%s%s%s%s",
|
||||
MAC2STR(nr), WPA_GET_LE32(nr + ETH_ALEN),
|
||||
nr[ETH_ALEN + 4], nr[ETH_ALEN + 5],
|
||||
nr[ETH_ALEN + 6],
|
||||
lci[0] ? " lci=" : "", lci,
|
||||
civic[0] ? " civic=" : "", civic);
|
||||
|
||||
/* neighbor start */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, " neighbor=");
|
||||
/* bssid */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, MACSTR, MAC2STR(nr));
|
||||
/* , */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* bssid info */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "0x%04x", WPA_GET_LE32(nr + ETH_ALEN));
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* operating class */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 4]);
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* channel number */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 5]);
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, ",");
|
||||
/* phy type */
|
||||
len += snprintf(buf + len, MAX_NEIGHBOR_LEN - len, "%u", nr[ETH_ALEN + 6]);
|
||||
/* optional elements, skip */
|
||||
|
||||
data = end;
|
||||
report_len -= 2 + nr_len;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (ret < 0) {
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
void neighbor_report_recv_cb(void *ctx, const uint8_t *report, size_t report_len)
|
||||
{
|
||||
int *val = (int*) ctx;
|
||||
uint8_t *pos = (uint8_t *)report;
|
||||
int cand_list = 0;
|
||||
|
||||
if (!report) {
|
||||
ESP_LOGE(TAG, "report is null");
|
||||
return;
|
||||
}
|
||||
if (*val != rrm_ctx) {
|
||||
ESP_LOGE(TAG, "rrm_ctx value didn't match, not initiated by us");
|
||||
return;
|
||||
}
|
||||
/* dump report info */
|
||||
ESP_LOGI(TAG, "rrm: neighbor report len=%d", report_len);
|
||||
ESP_LOG_BUFFER_HEXDUMP(TAG, pos, report_len, ESP_LOG_INFO);
|
||||
|
||||
/* create neighbor list */
|
||||
char *neighbor_list = get_btm_neighbor_list(pos + 1, report_len - 1);
|
||||
|
||||
/* In case neighbor list is not present issue a scan and get the list from that */
|
||||
if (!neighbor_list) {
|
||||
/* issue scan */
|
||||
wifi_scan_config_t params;
|
||||
memset(¶ms, 0, sizeof(wifi_scan_config_t));
|
||||
if (esp_wifi_scan_start(¶ms, true) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* cleanup from net802.11 */
|
||||
uint16_t number = 1;
|
||||
wifi_ap_record_t ap_records;
|
||||
esp_wifi_scan_get_ap_records(&number, &ap_records);
|
||||
cand_list = 1;
|
||||
}
|
||||
/* send AP btm query, this will cause STA to roam as well */
|
||||
esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, neighbor_list, cand_list);
|
||||
|
||||
cleanup:
|
||||
if (neighbor_list)
|
||||
free(neighbor_list);
|
||||
}
|
||||
|
||||
|
||||
static void esp_bss_rssi_low_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
wifi_event_bss_rssi_low_t *event = (wifi_event_bss_rssi_low_t*) event_data;
|
||||
|
||||
ESP_LOGI(TAG, "%s:bss rssi is=%d", __func__, event->rssi);
|
||||
/* Lets check channel conditions */
|
||||
rrm_ctx++;
|
||||
if (esp_rrm_send_neighbor_rep_request(neighbor_report_recv_cb, &rrm_ctx) < 0) {
|
||||
/* failed to send neighbor report request */
|
||||
ESP_LOGI(TAG, "failed to send neighbor report request");
|
||||
if (esp_wnm_send_bss_transition_mgmt_query(REASON_FRAME_LOSS, NULL, 0) < 0) {
|
||||
ESP_LOGI(TAG, "failed to send btm query");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//////////////////////////////////
|
||||
//////////////////////////////////
|
||||
|
||||
|
||||
std::string* getIPAddress()
|
||||
{
|
||||
return &ipadress;
|
||||
}
|
||||
|
||||
|
||||
std::string* getSSID()
|
||||
{
|
||||
return &ssid;
|
||||
@@ -99,23 +347,27 @@ void task_doBlink(void *pvParameter)
|
||||
vTaskDelete(NULL); //Delete this task if it exits from the loop above
|
||||
}
|
||||
|
||||
|
||||
void LEDBlinkTask(int _dauer, int _anz, bool _off)
|
||||
{
|
||||
BlinkDauer = _dauer;
|
||||
BlinkAnzahl = _anz;
|
||||
BlinkOff = _off;
|
||||
|
||||
xTaskCreate(&task_doBlink, "task_doBlink", configMINIMAL_STACK_SIZE * 8, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
xTaskCreate(&task_doBlink, "task_doBlink", 4 * 1024, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
}
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
WIFIConnected = false;
|
||||
LEDBlinkTask(200, 1, true);
|
||||
esp_wifi_connect();
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
WIFIConnected = false;
|
||||
// if (s_retry_num < EXAMPLE_ESP_MAXIMUM_RETRY) {
|
||||
esp_wifi_connect();
|
||||
s_retry_num++;
|
||||
@@ -131,9 +383,18 @@ static void event_handler(void* arg, esp_event_base_t event_base,
|
||||
s_retry_num = 0;
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||
LEDBlinkTask(1000, 5, true);
|
||||
|
||||
WIFIConnected = true;
|
||||
#ifdef ENABLE_MQTT
|
||||
if (getMQTTisEnabled()) {
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
MQTT_Init(); // Init when WIFI is getting connected
|
||||
}
|
||||
#endif //ENABLE_MQTT
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) {
|
||||
std::string zw = std::string(ip);
|
||||
std::stringstream s(zw);
|
||||
@@ -142,8 +403,9 @@ void strinttoip4(const char *ip, int &a, int &b, int &c, int &d) {
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns)
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreashold)
|
||||
{
|
||||
RSSI_Threshold = _rssithreashold;
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
@@ -153,20 +415,6 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
|
||||
if ((_ipadr != NULL) && (_gw != NULL) && (_netmask != NULL))
|
||||
{
|
||||
/*
|
||||
tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA);
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
int a, b, c, d;
|
||||
strinttoip4(_ipadr, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.ip, a, b, c, d);
|
||||
strinttoip4(_gw, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.gw, a, b, c, d);
|
||||
strinttoip4(_netmask, a, b, c, d);
|
||||
IP4_ADDR(&ip_info.netmask, a, b, c, d);
|
||||
|
||||
tcpip_adapter_set_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info);
|
||||
*/
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "set IP %s, GW %s, Netmask %s manual", _ipadr, _gw, _netmask);
|
||||
esp_netif_dhcpc_stop(my_sta);
|
||||
@@ -199,11 +447,9 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
ESP_ERROR_CHECK(esp_netif_set_dns_info(my_sta, ESP_NETIF_DNS_MAIN, &dns_info));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
esp_event_handler_instance_t instance_bss_rssi_low;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&event_handler,
|
||||
@@ -214,6 +460,15 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
&event_handler,
|
||||
NULL,
|
||||
&instance_got_ip));
|
||||
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
WIFI_EVENT_STA_BSS_RSSI_LOW,
|
||||
&esp_bss_rssi_low_handler,
|
||||
NULL,
|
||||
&instance_bss_rssi_low));
|
||||
#endif
|
||||
|
||||
wifi_config_t wifi_config = { };
|
||||
|
||||
strcpy((char*)wifi_config.sta.ssid, (const char*)_ssid);
|
||||
@@ -228,10 +483,10 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
esp_err_t ret = tcpip_adapter_set_hostname(TCPIP_ADAPTER_IF_STA , _hostname);
|
||||
hostname = std::string(_hostname);
|
||||
if(ret != ESP_OK ){
|
||||
ESP_LOGE(TAG,"failed to set hostname:%d",ret);
|
||||
ESP_LOGE(TAG,"Failed to set hostname: %d",ret);
|
||||
}
|
||||
else {
|
||||
ESP_LOGI(TAG,"Set Hostname to:%s", _hostname);
|
||||
ESP_LOGI(TAG,"Set hostname to: %s", _hostname);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -249,17 +504,17 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually
|
||||
* happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "connected to ap SSID: %s, password: XXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "connected to ap SSID: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "Connected with AP: %s, password: XXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Connected with AP: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID: %s, password: XXXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Failed to connect to SSID: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
#ifdef __HIDE_PASSWORD
|
||||
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: XXXXXXXX", _ssid);
|
||||
#else
|
||||
ESP_LOGI(TAG, "Failed to connect with AP: %s, password: %s", _ssid, _password);
|
||||
#endif
|
||||
} else {
|
||||
ESP_LOGE(TAG, "UNEXPECTED EVENT");
|
||||
}
|
||||
@@ -272,6 +527,7 @@ void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostna
|
||||
// vEventGroupDelete(s_wifi_event_group);
|
||||
}
|
||||
|
||||
|
||||
int get_WIFI_RSSI()
|
||||
{
|
||||
wifi_ap_record_t ap;
|
||||
@@ -279,13 +535,34 @@ int get_WIFI_RSSI()
|
||||
return ap.rssi;
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname)
|
||||
{
|
||||
wifi_init_sta(_ssid, _password, _hostname, NULL, NULL, NULL, NULL);
|
||||
wifi_init_sta(_ssid, _password, _hostname, NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password)
|
||||
{
|
||||
wifi_init_sta(_ssid, _password, NULL, NULL, NULL, NULL, NULL);
|
||||
wifi_init_sta(_ssid, _password, NULL, NULL, NULL, NULL, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
bool getWIFIisConnected()
|
||||
{
|
||||
return WIFIConnected;
|
||||
}
|
||||
|
||||
|
||||
void WIFIDestroy()
|
||||
{
|
||||
esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, event_handler);
|
||||
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, event_handler);
|
||||
#ifdef WLAN_USE_MESH_ROAMING
|
||||
esp_event_handler_unregister(WIFI_EVENT, WIFI_EVENT_STA_BSS_RSSI_LOW, esp_bss_rssi_low_handler);
|
||||
#endif
|
||||
|
||||
esp_wifi_stop();
|
||||
esp_wifi_deinit();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef CONNECT_WLAN_H
|
||||
#define CONNECT_WLAN_H
|
||||
|
||||
#include <string>
|
||||
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname, const char *_ipadr, const char *_gw, const char *_netmask, const char *_dns, int _rssithreashold);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password, const char *_hostname);
|
||||
void wifi_init_sta(const char *_ssid, const char *_password);
|
||||
|
||||
std::string* getIPAddress();
|
||||
std::string* getSSID();
|
||||
int get_WIFI_RSSI();
|
||||
bool getWIFIisConnected();
|
||||
void WIFIDestroy();
|
||||
|
||||
extern std::string hostname;
|
||||
extern std::string std_hostname;
|
||||
extern int RSSIThreashold;
|
||||
|
||||
#endif
|
||||
#endif //CONNECT_WLAN_H
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "../../include/defines.h"
|
||||
|
||||
static const char *TAG = "WLAN.INI";
|
||||
|
||||
@@ -25,7 +26,7 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
|
||||
input = trim(input, delimiter);
|
||||
size_t pos = findDelimiterPos(input, delimiter);
|
||||
std::string token;
|
||||
if (pos != std::string::npos) // Zerlegt nur bis ersten Gleichheitszeichen !!! Sonderfall für WLAN.ini
|
||||
if (pos != std::string::npos) // splitted only up to first equal sign !!! Special case for WLAN.ini
|
||||
{
|
||||
token = input.substr(0, pos);
|
||||
token = trim(token, delimiter);
|
||||
@@ -40,7 +41,7 @@ std::vector<string> ZerlegeZeileWLAN(std::string input, std::string _delimiter =
|
||||
|
||||
|
||||
|
||||
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns)
|
||||
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold)
|
||||
{
|
||||
std::string ssid = "";
|
||||
std::string passphrase = "";
|
||||
@@ -48,19 +49,23 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
std::string gw = "";
|
||||
std::string netmask = "";
|
||||
std::string dns = "";
|
||||
int rssithreshold = 0;
|
||||
|
||||
std::string line = "";
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
hostname = std_hostname;
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
if (!pFile)
|
||||
return false;
|
||||
|
||||
ESP_LOGD(TAG, "file loaded");
|
||||
|
||||
if (pFile == NULL)
|
||||
return;
|
||||
return false;
|
||||
|
||||
char zw[1024];
|
||||
fgets(zw, 1024, pFile);
|
||||
@@ -69,53 +74,62 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
// ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "HOSTNAME")){
|
||||
hostname = trim(zerlegt[1]);
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
|
||||
hostname = trim(splitted[1]);
|
||||
if ((hostname[0] == '"') && (hostname[hostname.length()-1] == '"')){
|
||||
hostname = hostname.substr(1, hostname.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "SSID")){
|
||||
ssid = trim(zerlegt[1]);
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "SSID")){
|
||||
ssid = trim(splitted[1]);
|
||||
if ((ssid[0] == '"') && (ssid[ssid.length()-1] == '"')){
|
||||
ssid = ssid.substr(1, ssid.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "PASSWORD")){
|
||||
passphrase = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHREASHOLD")){
|
||||
string _s = trim(splitted[1]);
|
||||
if ((_s[0] == '"') && (_s[_s.length()-1] == '"')){
|
||||
_s = _s.substr(1, ssid.length()-2);
|
||||
}
|
||||
rssithreshold = atoi(_s.c_str());
|
||||
}
|
||||
|
||||
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "PASSWORD")){
|
||||
passphrase = splitted[1];
|
||||
if ((passphrase[0] == '"') && (passphrase[passphrase.length()-1] == '"')){
|
||||
passphrase = passphrase.substr(1, passphrase.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "IP")){
|
||||
ipaddress = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "IP")){
|
||||
ipaddress = splitted[1];
|
||||
if ((ipaddress[0] == '"') && (ipaddress[ipaddress.length()-1] == '"')){
|
||||
ipaddress = ipaddress.substr(1, ipaddress.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "GATEWAY")){
|
||||
gw = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "GATEWAY")){
|
||||
gw = splitted[1];
|
||||
if ((gw[0] == '"') && (gw[gw.length()-1] == '"')){
|
||||
gw = gw.substr(1, gw.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "NETMASK")){
|
||||
netmask = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "NETMASK")){
|
||||
netmask = splitted[1];
|
||||
if ((netmask[0] == '"') && (netmask[netmask.length()-1] == '"')){
|
||||
netmask = netmask.substr(1, netmask.length()-2);
|
||||
}
|
||||
}
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "DNS")){
|
||||
dns = zerlegt[1];
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "DNS")){
|
||||
dns = splitted[1];
|
||||
if ((dns[0] == '"') && (dns[dns.length()-1] == '"')){
|
||||
dns = dns.substr(1, dns.length()-2);
|
||||
}
|
||||
@@ -179,6 +193,10 @@ void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_ho
|
||||
}
|
||||
else
|
||||
_dns = NULL;
|
||||
|
||||
_rssithreashold = rssithreshold;
|
||||
RSSIThreashold = rssithreshold;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -190,7 +208,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
return false;
|
||||
|
||||
string line = "";
|
||||
std::vector<string> zerlegt;
|
||||
std::vector<string> splitted;
|
||||
|
||||
bool found = false;
|
||||
|
||||
@@ -198,7 +216,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
pFile = OpenFileAndWait(fn.c_str(), "r");
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
ESP_LOGD(TAG, "file loaded\n");
|
||||
|
||||
@@ -212,10 +230,10 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", line.c_str());
|
||||
zerlegt = ZerlegeZeileWLAN(line, "=");
|
||||
zerlegt[0] = trim(zerlegt[0], " ");
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((zerlegt.size() > 1) && (toUpper(zerlegt[0]) == "HOSTNAME")){
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "HOSTNAME")){
|
||||
line = "hostname = \"" + _newhostname + "\"\n";
|
||||
found = true;
|
||||
}
|
||||
@@ -240,7 +258,7 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = OpenFileAndWait(fn.c_str(), "w+");
|
||||
pFile = fopen(fn.c_str(), "w+");
|
||||
|
||||
for (int i = 0; i < neuesfile.size(); ++i)
|
||||
{
|
||||
@@ -255,3 +273,75 @@ bool ChangeHostName(std::string fn, std::string _newhostname)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool ChangeRSSIThreashold(std::string fn, int _newrssithreashold)
|
||||
{
|
||||
if (RSSIThreashold == _newrssithreashold)
|
||||
return false;
|
||||
|
||||
string line = "";
|
||||
std::vector<string> splitted;
|
||||
|
||||
bool found = false;
|
||||
|
||||
std::vector<string> neuesfile;
|
||||
|
||||
FILE* pFile;
|
||||
fn = FormatFileName(fn);
|
||||
pFile = fopen(fn.c_str(), "r");
|
||||
|
||||
ESP_LOGD(TAG, "file loaded\n");
|
||||
|
||||
if (pFile == NULL)
|
||||
return false;
|
||||
|
||||
char zw[1024];
|
||||
fgets(zw, 1024, pFile);
|
||||
line = std::string(zw);
|
||||
|
||||
while ((line.size() > 0) || !(feof(pFile)))
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", line.c_str());
|
||||
splitted = ZerlegeZeileWLAN(line, "=");
|
||||
splitted[0] = trim(splitted[0], " ");
|
||||
|
||||
if ((splitted.size() > 1) && (toUpper(splitted[0]) == "RSSITHREASHOLD")){
|
||||
line = "RSSIThreashold = " + to_string(_newrssithreashold) + "\n";
|
||||
found = true;
|
||||
}
|
||||
|
||||
neuesfile.push_back(line);
|
||||
|
||||
if (fgets(zw, 1024, pFile) == NULL)
|
||||
{
|
||||
line = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
line = std::string(zw);
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
line = "RSSIThreashold = " + to_string(_newrssithreashold) + "\n";
|
||||
neuesfile.push_back(line);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
pFile = fopen(fn.c_str(), "w+");
|
||||
|
||||
for (int i = 0; i < neuesfile.size(); ++i)
|
||||
{
|
||||
ESP_LOGD(TAG, "%s", neuesfile[i].c_str());
|
||||
fputs(neuesfile[i].c_str(), pFile);
|
||||
}
|
||||
|
||||
fclose(pFile);
|
||||
|
||||
ESP_LOGD(TAG, "*** RSSIThreashold update done ***");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef READ_WLANINI_H
|
||||
#define READ_WLANINI_H
|
||||
|
||||
#include <string>
|
||||
|
||||
void LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns);
|
||||
bool LoadWlanFromFile(std::string fn, char *&_ssid, char *&_password, char *&_hostname, char *&_ipadr, char *&_gw, char *&_netmask, char *&_dns, int &_rssithreashold);
|
||||
|
||||
bool ChangeHostName(std::string fn, std::string _newhostname);
|
||||
bool ChangeRSSIThreashold(std::string fn, int _newrssithreashold);
|
||||
|
||||
|
||||
#endif
|
||||
#endif //READ_WLANINI_H
|
||||
@@ -1,2 +1,3 @@
|
||||
manifest_hash: 45994dbfed009907994c31f6d279c5861a1eacbf219ce8b58e74e39b3393816a
|
||||
manifest_hash: 4e37bb0f9273c4de05f38688720fe32aa6e5b892452694a4f7a2ca1659f02cf6
|
||||
target: esp32
|
||||
version: 1.0.0
|
||||
|
||||
@@ -1,6 +1,321 @@
|
||||
#pragma once
|
||||
#ifndef defines_h
|
||||
#define defines_h
|
||||
|
||||
#define CONFIG_FILE "/sdcard/config/config.ini"
|
||||
/////////////////////////////////////////////
|
||||
//// Global definitions ////
|
||||
/////////////////////////////////////////////
|
||||
|
||||
#endif // ifndef defines_h
|
||||
//********* debug options : *************
|
||||
|
||||
//can be set in platformio with -D OPTION_TO_ACTIVATE
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
//#define DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
//#define DEBUG_ENABLE_SYSINFO
|
||||
//#define DEBUG_ENABLE_PERFMON
|
||||
//#define DEBUG_HIMEM_MEMORY_CHECK
|
||||
// need [env:esp32cam-dev-himem]
|
||||
//=> CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
|
||||
//=> CONFIG_SPIRAM_BANKSWITCH_RESERVE=4
|
||||
|
||||
|
||||
// use himem //https://github.com/jomjol/AI-on-the-edge-device/issues/1842
|
||||
#define USE_HIMEM_IF_AVAILABLE
|
||||
|
||||
/* Uncomment this to generate task list with stack sizes using the /heap handler
|
||||
PLEASE BE AWARE: The following CONFIG parameters have to to be set in
|
||||
sdkconfig.defaults before use of this function is possible!!
|
||||
CONFIG_FREERTOS_USE_TRACE_FACILITY=1
|
||||
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
*/
|
||||
// server_tflite.cpp
|
||||
//#define TASK_ANALYSIS_ON
|
||||
|
||||
|
||||
//Memory leak tracing
|
||||
//https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/heap_debug.html#heap-information
|
||||
//need CONFIG_HEAP_TRACING_STANDALONE=y or #define CONFIG_HEAP_TRACING_STANDALONE
|
||||
//all setup is predifined in [env:esp32cam-dev-task-analysis]
|
||||
//#define HEAP_TRACING_MAIN_WIFI || HEAP_TRACING_MAIN_START //enable heap tracing per function in main.cpp
|
||||
//all defines in [env:esp32cam-dev-task-analysis]
|
||||
//#define HEAP_TRACING_MAIN_WIFI
|
||||
//#define HEAP_TRACING_MAIN_START
|
||||
//#define HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
|
||||
/* Uncomment this to keep the logfile open for appending.
|
||||
* If commented out, the logfile gets opened/closed for each log measage (old behaviour) */
|
||||
// ClassLogFile
|
||||
//#define KEEP_LOGFILE_OPEN_FOR_APPENDING
|
||||
|
||||
//****************************************
|
||||
|
||||
//compiler optimization for tflite-micro-esp-examples
|
||||
#define XTENSA
|
||||
//#define CONFIG_IDF_TARGET_ARCH_XTENSA //not needed with platformio/espressif32 @ 5.2.0
|
||||
|
||||
|
||||
//ClassControllCamera + ClassFlowMakeImage + connect_wlan + main
|
||||
#define FLASH_GPIO GPIO_NUM_4
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
//ClassFlowMQTT + interface_mqtt + connect_wlan + main
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
//ClassControllCamera
|
||||
#define USE_PWM_LEDFLASH // if __LEDGLOBAL is defined, a global variable is used for LED control, otherwise locally and each time a new
|
||||
|
||||
//server_GPIO
|
||||
#define __LEDGLOBAL
|
||||
|
||||
//ClassControllCamera + ClassFlowMakeImage
|
||||
#define CAMERA_MODEL_AI_THINKER
|
||||
#define BOARD_ESP32CAM_AITHINKER
|
||||
|
||||
//server_GPIO + server_file + SoftAP
|
||||
#define CONFIG_FILE "/sdcard/config/config.ini"
|
||||
|
||||
//ClassFlowControll + Main + SoftAP
|
||||
#define WLAN_CONFIG_FILE "/sdcard/wlan.ini"
|
||||
|
||||
//main
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
|
||||
// server_file + Helper
|
||||
#define FILE_PATH_MAX (255) //Max length a file path can have on storage
|
||||
|
||||
//server_file +(ota_page.html + upload_script.html)
|
||||
#define MAX_FILE_SIZE (8000*1024) // 8 MB Max size of an individual file. Make sure this value is same as that set in upload_script.html and ota_page.html!
|
||||
#define MAX_FILE_SIZE_STR "8MB"
|
||||
|
||||
#define LOGFILE_LAST_PART_BYTES 80 * 1024 // 80 kBytes // Size of partial log file to return
|
||||
|
||||
#define SERVER_FILER_SCRATCH_BUFSIZE 4096
|
||||
#define SERVER_HELPER_SCRATCH_BUFSIZE 8192
|
||||
#define SERVER_OTA_SCRATCH_BUFSIZE 1024
|
||||
|
||||
//server_file + server_help
|
||||
#define IS_FILE_EXT(filename, ext) \
|
||||
(strcasecmp(&filename[strlen(filename) - sizeof(ext) + 1], ext) == 0)
|
||||
|
||||
//server_ota
|
||||
#define HASH_LEN 32 // SHA-256 digest length
|
||||
#define OTA_URL_SIZE 256
|
||||
|
||||
//ClassFlow + ClassFlowImage + server_tflite
|
||||
#define LOGFILE_TIME_FORMAT "%Y%m%d-%H%M%S"
|
||||
#define LOGFILE_TIME_FORMAT_DATE_EXTR substr(0, 8)
|
||||
#define LOGFILE_TIME_FORMAT_HOUR_EXTR substr(9, 2)
|
||||
|
||||
//ClassFlowControll
|
||||
#define READOUT_TYPE_VALUE 0
|
||||
#define READOUT_TYPE_PREVALUE 1
|
||||
#define READOUT_TYPE_RAWVALUE 2
|
||||
#define READOUT_TYPE_ERROR 3
|
||||
|
||||
//ClassFlowControll: Serve alg_roi.jpg from memory as JPG
|
||||
#define ALGROI_LOAD_FROM_MEM_AS_JPG // Load ALG_ROI.JPG as rendered JPG from RAM
|
||||
#define ALGROI_LOAD_FROM_MEM_AS_JPG__SHOW_TAKE_IMAGE_PROCESS // Show take image image processing on webinterface (overview.html)
|
||||
|
||||
//ClassFlowMQTT
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
//ClassFlowPostProcessing
|
||||
#define PREVALUE_TIME_FORMAT_OUTPUT "%Y-%m-%dT%H:%M:%S%z"
|
||||
#define PREVALUE_TIME_FORMAT_INPUT "%d-%d-%dT%d:%d:%d"
|
||||
|
||||
//CImageBasis
|
||||
#define HTTP_BUFFER_SENT 1024
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
#define MAX_JPG_SIZE 128000
|
||||
|
||||
|
||||
//CAlignAndCutImage + CImageBasis
|
||||
#define _USE_MATH_DEFINES
|
||||
#define GET_MEMORY(X) heap_caps_malloc(X, MALLOC_CAP_SPIRAM)
|
||||
|
||||
//make_stb + stb_image_resize + stb_image_write + stb_image //do not work if not in make_stb.cpp
|
||||
//#define STB_IMAGE_IMPLEMENTATION
|
||||
//#define STB_IMAGE_WRITE_IMPLEMENTATION
|
||||
//#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#define STBI_ONLY_JPEG // (save 2% of Flash, but breaks the alignment mark generation, see https://github.com/jomjol/AI-on-the-edge-device/issues/1721)
|
||||
|
||||
//interface_influxdb
|
||||
#define MAX_HTTP_OUTPUT_BUFFER 2048
|
||||
|
||||
//server_mqtt
|
||||
#define LWT_TOPIC "connection"
|
||||
#define LWT_CONNECTED "connected"
|
||||
#define LWT_DISCONNECTED "connection lost"
|
||||
|
||||
//CTfLiteClass
|
||||
#define TFLITE_MINIMAL_CHECK(x) \
|
||||
if (!(x)) { \
|
||||
fprintf(stderr, "Error at %s:%d\n", __FILE__, __LINE__); \
|
||||
exit(1); \
|
||||
}
|
||||
#define SUPRESS_TFLITE_ERRORS // use, to avoid error messages from TFLITE
|
||||
|
||||
//connect_wlan
|
||||
#define WLAN_USE_MESH_ROAMING
|
||||
#define WLAN_WIFI_RSSI_THRESHOLD -50
|
||||
#define EXAMPLE_ESP_MAXIMUM_RETRY 1000
|
||||
/* The event group allows multiple bits for each event, but we only care about two events:
|
||||
* - we are connected to the AP with an IP
|
||||
* - we failed to connect after the maximum amount of retries */
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
|
||||
//ClassFlowCNNGeneral
|
||||
#define Analog_error 3
|
||||
#define AnalogToDigtalFehler 0.8
|
||||
#define Digital_Uncertainty 0.2
|
||||
#define DigitalBand 3
|
||||
#define Digital_Transition_Range_Predecessor 2
|
||||
#define Digital_Transition_Area_Predecessor 0.7 // 9.3 - 0.7
|
||||
#define Digital_Transition_Area_Forward 9.7 // Pre-run zero crossing only happens from approx. 9.7 onwards
|
||||
|
||||
|
||||
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
//// Conditionnal definitions ////
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//******* camera model
|
||||
#if defined(CAMERA_MODEL_WROVER_KIT)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM 21
|
||||
#define SIOD_GPIO_NUM 26
|
||||
#define SIOC_GPIO_NUM 27
|
||||
|
||||
#define Y9_GPIO_NUM 35
|
||||
#define Y8_GPIO_NUM 34
|
||||
#define Y7_GPIO_NUM 39
|
||||
#define Y6_GPIO_NUM 36
|
||||
#define Y5_GPIO_NUM 19
|
||||
#define Y4_GPIO_NUM 18
|
||||
#define Y3_GPIO_NUM 5
|
||||
#define Y2_GPIO_NUM 4
|
||||
#define VSYNC_GPIO_NUM 25
|
||||
#define HREF_GPIO_NUM 23
|
||||
#define PCLK_GPIO_NUM 22
|
||||
|
||||
#elif defined(CAMERA_MODEL_M5STACK_PSRAM)
|
||||
#define PWDN_GPIO_NUM -1
|
||||
#define RESET_GPIO_NUM 15
|
||||
#define XCLK_GPIO_NUM 27
|
||||
#define SIOD_GPIO_NUM 25
|
||||
#define SIOC_GPIO_NUM 23
|
||||
|
||||
#define Y9_GPIO_NUM 19
|
||||
#define Y8_GPIO_NUM 36
|
||||
#define Y7_GPIO_NUM 18
|
||||
#define Y6_GPIO_NUM 39
|
||||
#define Y5_GPIO_NUM 5
|
||||
#define Y4_GPIO_NUM 34
|
||||
#define Y3_GPIO_NUM 35
|
||||
#define Y2_GPIO_NUM 32
|
||||
#define VSYNC_GPIO_NUM 22
|
||||
#define HREF_GPIO_NUM 26
|
||||
#define PCLK_GPIO_NUM 21
|
||||
|
||||
#elif defined(CAMERA_MODEL_AI_THINKER)
|
||||
#define PWDN_GPIO_NUM GPIO_NUM_32
|
||||
#define RESET_GPIO_NUM -1
|
||||
#define XCLK_GPIO_NUM GPIO_NUM_0
|
||||
#define SIOD_GPIO_NUM GPIO_NUM_26
|
||||
#define SIOC_GPIO_NUM GPIO_NUM_27
|
||||
|
||||
#define Y9_GPIO_NUM GPIO_NUM_35
|
||||
#define Y8_GPIO_NUM GPIO_NUM_34
|
||||
#define Y7_GPIO_NUM GPIO_NUM_39
|
||||
#define Y6_GPIO_NUM GPIO_NUM_36
|
||||
#define Y5_GPIO_NUM GPIO_NUM_21
|
||||
#define Y4_GPIO_NUM GPIO_NUM_19
|
||||
#define Y3_GPIO_NUM GPIO_NUM_18
|
||||
#define Y2_GPIO_NUM GPIO_NUM_5
|
||||
#define VSYNC_GPIO_NUM GPIO_NUM_25
|
||||
#define HREF_GPIO_NUM GPIO_NUM_23
|
||||
#define PCLK_GPIO_NUM GPIO_NUM_22
|
||||
|
||||
#else
|
||||
#error "Camera model not selected"
|
||||
#endif //camera model
|
||||
|
||||
// ******* Board type
|
||||
#ifdef BOARD_WROVER_KIT // WROVER-KIT PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN -1 //power down is not used
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 21
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 19
|
||||
#define CAM_PIN_D2 18
|
||||
#define CAM_PIN_D1 5
|
||||
#define CAM_PIN_D0 4
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#endif //// WROVER-KIT PIN Map
|
||||
|
||||
|
||||
#ifdef BOARD_ESP32CAM_AITHINKER // ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
#define CAM_PIN_PWDN 32
|
||||
#define CAM_PIN_RESET -1 //software reset will be performed
|
||||
#define CAM_PIN_XCLK 0
|
||||
#define CAM_PIN_SIOD 26
|
||||
#define CAM_PIN_SIOC 27
|
||||
|
||||
#define CAM_PIN_D7 35
|
||||
#define CAM_PIN_D6 34
|
||||
#define CAM_PIN_D5 39
|
||||
#define CAM_PIN_D4 36
|
||||
#define CAM_PIN_D3 21
|
||||
#define CAM_PIN_D2 19
|
||||
#define CAM_PIN_D1 18
|
||||
#define CAM_PIN_D0 5
|
||||
#define CAM_PIN_VSYNC 25
|
||||
#define CAM_PIN_HREF 23
|
||||
#define CAM_PIN_PCLK 22
|
||||
|
||||
#endif // ESP32Cam (AiThinker) PIN Map
|
||||
|
||||
// ******* LED definition
|
||||
#ifdef USE_PWM_LEDFLASH
|
||||
|
||||
//// PWM für Flash-LED
|
||||
#define LEDC_TIMER LEDC_TIMER_1 // LEDC_TIMER_0
|
||||
#define LEDC_MODE LEDC_LOW_SPEED_MODE
|
||||
#define LEDC_OUTPUT_IO FLASH_GPIO // Define the output GPIO
|
||||
#define LEDC_CHANNEL LEDC_CHANNEL_1
|
||||
#define LEDC_DUTY_RES LEDC_TIMER_13_BIT // Set duty resolution to 13 bits
|
||||
//#define LEDC_DUTY (195) // Set duty to 50%. ((2 ** 13) - 1) * 50% = 4095
|
||||
#define LEDC_FREQUENCY (5000) // Frequency in Hertz. Set frequency at 5 kHz
|
||||
|
||||
#endif //USE_PWM_LEDFLASH
|
||||
|
||||
//softAP
|
||||
#ifdef ENABLE_SOFTAP
|
||||
#define EXAMPLE_ESP_WIFI_SSID "AI-on-the-Edge"
|
||||
#define EXAMPLE_ESP_WIFI_PASS ""
|
||||
#define EXAMPLE_ESP_WIFI_CHANNEL 11
|
||||
#define EXAMPLE_MAX_STA_CONN 1
|
||||
#endif // ENABLE_SOFTAP
|
||||
|
||||
#endif // ifndef defines_h
|
||||
|
||||
@@ -65,5 +65,6 @@ FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/main/*.*)
|
||||
# idf_component_register(SRCS ${app_sources})
|
||||
|
||||
idf_component_register(SRCS ${app_sources}
|
||||
INCLUDE_DIRS ".")
|
||||
|
||||
INCLUDE_DIRS "."
|
||||
# REQUIRES esp_psram) # comming in IDF 5.0
|
||||
)
|
||||
@@ -1,19 +1,24 @@
|
||||
#include <string>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
//#include <string>
|
||||
//#include "freertos/FreeRTOS.h"
|
||||
//#include "freertos/task.h"
|
||||
//#include "freertos/event_groups.h"
|
||||
|
||||
//#include "driver/gpio.h"
|
||||
//#include "sdkconfig.h"
|
||||
//#include "esp_psram.h" // Comming in IDF 5.0, see https://docs.espressif.com/projects/esp-idf/en/v5.0-beta1/esp32/migration-guides/release-5.x/system.html?highlight=esp_psram_get_size
|
||||
//#include "spiram.h"
|
||||
#include "esp32/spiram.h"
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// SD-Card ////////////////////
|
||||
#include "nvs_flash.h"
|
||||
//#include "nvs_flash.h"
|
||||
#include "esp_vfs_fat.h"
|
||||
#include "sdmmc_cmd.h"
|
||||
//#include "sdmmc_cmd.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
//#include "driver/sdmmc_defs.h"
|
||||
///////////////////////////////
|
||||
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
|
||||
#include "connect_wlan.h"
|
||||
@@ -24,37 +29,57 @@
|
||||
#include "server_file.h"
|
||||
#include "server_ota.h"
|
||||
#include "time_sntp.h"
|
||||
#include "ClassControllCamera.h"
|
||||
//#include "ClassControllCamera.h"
|
||||
#include "server_main.h"
|
||||
#include "server_camera.h"
|
||||
#include "server_mqtt.h"
|
||||
#include "Helper.h"
|
||||
#ifdef ENABLE_MQTT
|
||||
#include "server_mqtt.h"
|
||||
#endif //ENABLE_MQTT
|
||||
//#include "Helper.h"
|
||||
#include "../../include/defines.h"
|
||||
//#include "server_GPIO.h"
|
||||
|
||||
#ifdef ENABLE_SOFTAP
|
||||
#include "softAP.h"
|
||||
#endif //ENABLE_SOFTAP
|
||||
|
||||
#ifdef DISABLE_BROWNOUT_DETECTOR
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
|
||||
#include "esp_sys.h"
|
||||
#endif
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#include "esp32/himem.h"
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
#include "himem_memory_check.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
|
||||
#include <esp_heap_trace.h>
|
||||
#define NUM_RECORDS 300
|
||||
static heap_trace_record_t trace_record[NUM_RECORDS]; // This buffer must be in internal RAM
|
||||
#endif
|
||||
|
||||
extern const char* GIT_TAG;
|
||||
extern const char* GIT_REV;
|
||||
extern const char* GIT_BRANCH;
|
||||
extern const char* BUILD_TIME;
|
||||
|
||||
extern std::string getFwVersion(void);
|
||||
extern std::string getHTMLversion(void);
|
||||
extern std::string getHTMLcommit(void);
|
||||
|
||||
#define __HIDE_PASSWORD
|
||||
|
||||
// #include "jomjol_WS2812Slow.h"
|
||||
#include "SmartLeds.h"
|
||||
|
||||
|
||||
#define __SD_USE_ONE_LINE_MODE__
|
||||
|
||||
#include "server_GPIO.h"
|
||||
|
||||
|
||||
#define BLINK_GPIO GPIO_NUM_33
|
||||
|
||||
static const char *TAG = "MAIN";
|
||||
|
||||
//#define FLASH_GPIO GPIO_NUM_4
|
||||
|
||||
bool Init_NVS_SDCard()
|
||||
{
|
||||
esp_err_t ret = nvs_flash_init();
|
||||
@@ -93,7 +118,7 @@ bool Init_NVS_SDCard()
|
||||
// formatted in case when mounting fails.
|
||||
esp_vfs_fat_sdmmc_mount_config_t mount_config = {
|
||||
.format_if_mount_failed = false,
|
||||
.max_files = 7, // anstatt 5 (2022-09-21)
|
||||
.max_files = 12, // previously -> 2022-09-21: 5, 2023-01-02: 7
|
||||
.allocation_unit_size = 16 * 1024
|
||||
};
|
||||
|
||||
@@ -120,7 +145,7 @@ bool Init_NVS_SDCard()
|
||||
return true;
|
||||
}
|
||||
|
||||
void task_NoSDBlink(void *pvParameter)
|
||||
void task_MainInitError_blink(void *pvParameter)
|
||||
{
|
||||
gpio_pad_select_gpio(BLINK_GPIO);
|
||||
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
|
||||
@@ -144,8 +169,19 @@ void task_NoSDBlink(void *pvParameter)
|
||||
|
||||
extern "C" void app_main(void)
|
||||
{
|
||||
|
||||
//#ifdef CONFIG_HEAP_TRACING_STANDALONE
|
||||
#if defined HEAP_TRACING_MAIN_WIFI || defined HEAP_TRACING_MAIN_START
|
||||
//register a buffer to record the memory trace
|
||||
ESP_ERROR_CHECK( heap_trace_init_standalone(trace_record, NUM_RECORDS) );
|
||||
#endif
|
||||
|
||||
TickType_t xDelay;
|
||||
bool initSucessful = true;
|
||||
|
||||
#ifdef DISABLE_BROWNOUT_DETECTOR
|
||||
WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); //disable brownout detector
|
||||
#endif
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "\n\n\n\n\n"); // Add mark on log to see when it restarted
|
||||
|
||||
@@ -158,12 +194,13 @@ extern "C" void app_main(void)
|
||||
|
||||
if (!Init_NVS_SDCard())
|
||||
{
|
||||
xTaskCreate(&task_NoSDBlink, "task_NoSDBlink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
return;
|
||||
};
|
||||
xTaskCreate(&task_MainInitError_blink, "task_MainInitError_blink", configMINIMAL_STACK_SIZE * 64, NULL, tskIDLE_PRIORITY+1, NULL);
|
||||
return; // No way to continue without SD-Card!
|
||||
}
|
||||
|
||||
string versionFormated = "Branch: '" + std::string(GIT_BRANCH) + \
|
||||
"', Revision: " + std::string(GIT_REV) +", Date/Time: " + std::string(BUILD_TIME) + \
|
||||
setupTime();
|
||||
|
||||
string versionFormated = getFwVersion() + ", Date/Time: " + std::string(BUILD_TIME) + \
|
||||
", Web UI: " + getHTMLversion();
|
||||
|
||||
if (std::string(GIT_TAG) != "") { // We are on a tag, add it as prefix
|
||||
@@ -171,18 +208,44 @@ extern "C" void app_main(void)
|
||||
}
|
||||
|
||||
LogFile.CreateLogDirectories();
|
||||
MakeDir("/sdcard/demo"); // needed for demo mode
|
||||
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "==================== Startup ====================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, versionFormated);
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Reset reason: " + getResetReason());
|
||||
|
||||
#ifdef DEBUG_ENABLE_SYSINFO
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL( 4, 0, 0 )
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Device Info : " + get_device_info() );
|
||||
ESP_LOGD(TAG, "Device infos %s", get_device_info().c_str());
|
||||
#endif
|
||||
#endif //DEBUG_ENABLE_SYSINFO
|
||||
|
||||
#ifdef USE_HIMEM_IF_AVAILABLE
|
||||
#ifdef DEBUG_HIMEM_MEMORY_CHECK
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Himem mem check : " + himem_memory_check() );
|
||||
ESP_LOGD(TAG, "Himem mem check %s", himem_memory_check().c_str());
|
||||
#endif
|
||||
#endif
|
||||
|
||||
CheckIsPlannedReboot();
|
||||
CheckOTAUpdate();
|
||||
CheckUpdate();
|
||||
#ifdef ENABLE_SOFTAP
|
||||
CheckStartAPMode(); // if no wlan.ini and/or config.ini --> AP ist startet and this function does not exit anymore until reboot
|
||||
#endif
|
||||
|
||||
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL;
|
||||
LoadWlanFromFile("/sdcard/wlan.ini", ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
#ifdef HEAP_TRACING_MAIN_WIFI
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
char *ssid = NULL, *passwd = NULL, *hostname = NULL, *ip = NULL, *gateway = NULL, *netmask = NULL, *dns = NULL; int rssithreashold = 0;
|
||||
LoadWlanFromFile(WLAN_CONFIG_FILE, ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreashold);
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "WLAN-Settings - RSSI-Threashold: " + to_string(rssithreashold));
|
||||
|
||||
if (ssid != NULL && passwd != NULL)
|
||||
#ifdef __HIDE_PASSWORD
|
||||
@@ -195,7 +258,7 @@ extern "C" void app_main(void)
|
||||
ESP_LOGD(TAG, "No SSID and PASSWORD set!!!");
|
||||
|
||||
if (hostname != NULL)
|
||||
ESP_LOGD(TAG, "Hostename: %s", hostname);
|
||||
ESP_LOGD(TAG, "Hostname: %s", hostname);
|
||||
else
|
||||
ESP_LOGD(TAG, "Hostname not set");
|
||||
|
||||
@@ -205,38 +268,65 @@ extern "C" void app_main(void)
|
||||
ESP_LOGD(TAG, "DNS IP: %s", dns);
|
||||
|
||||
|
||||
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns);
|
||||
wifi_init_sta(ssid, passwd, hostname, ip, gateway, netmask, dns, rssithreashold);
|
||||
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay);
|
||||
vTaskDelay( xDelay );
|
||||
|
||||
#ifdef HEAP_TRACING_MAIN_WIFI
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
if (!setup_time()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "NTP Initialization failed. Will restart in 5 minutes!");
|
||||
initSucessful = false;
|
||||
}
|
||||
|
||||
setBootTime();
|
||||
#ifdef HEAP_TRACING_MAIN_START
|
||||
ESP_ERROR_CHECK( heap_trace_start(HEAP_TRACE_LEAKS) );
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "================== Main Started =================");
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "=================================================");
|
||||
|
||||
if (getHTMLcommit() != std::string(GIT_REV)) {
|
||||
if (getHTMLcommit().substr(0, 7) != std::string(GIT_REV).substr(0, 7)) { // Compare the first 7 characters of both hashes
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, std::string("Web UI version (") + getHTMLcommit() + ") does not match firmware version (" + std::string(GIT_REV) + ") !");
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Please make sure to setup the SD-Card properly (check the documentation) or re-install using the AI-on-the-edge-device__update__*.zip!");
|
||||
}
|
||||
|
||||
std::string zw = gettimestring("%Y%m%d-%H%M%S");
|
||||
std::string zw = getCurrentTimeString("%Y%m%d-%H%M%S");
|
||||
ESP_LOGD(TAG, "time %s", zw.c_str());
|
||||
|
||||
#ifdef HEAP_TRACING_MAIN_START
|
||||
ESP_ERROR_CHECK( heap_trace_stop() );
|
||||
heap_trace_dump();
|
||||
#endif
|
||||
|
||||
/* Check if PSRAM can be initalized */
|
||||
esp_err_t ret;
|
||||
ret = esp_spiram_init();
|
||||
if (ret == ESP_FAIL) { // Failed to init PSRAM, most likely not available or broken
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Failed to initialize PSRAM (" + std::to_string(ret) + ")!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Either your device misses the PSRAM chip or it is broken!");
|
||||
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
|
||||
}
|
||||
else { // PSRAM init ok
|
||||
/* Check if PSRAM provides at least 4 MB */
|
||||
size_t psram_size = esp_spiram_get_size();
|
||||
// size_t psram_size = esp_psram_get_size(); // comming in IDF 5.0
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "The device has " + std::to_string(psram_size/1024/1024) + " MBytes of PSRAM");
|
||||
if (psram_size < (4*1024*1024)) { // PSRAM is below 4 MBytes
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "At least 4 MBytes are required!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Does the device really have a 4 Mbytes PSRAM?");
|
||||
setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check available Heap memory */
|
||||
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 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 (_hsize < 4000000) { // Check available Heap memory for a bit less than 4 MB (a test on a good device showed 4187558 bytes to be available)
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Not enough Heap memory available. Expected around 4 MBytes, but only " + std::to_string(_hsize) + " Bytes are available! That is not enough for this firmware!");
|
||||
setSystemStatusFlag(SYSTEM_STATUS_HEAP_TOO_SMALL);
|
||||
} else { // Heap memory is ok
|
||||
if (camStatus != ESP_OK) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Failed to initialize camera module, retrying...");
|
||||
|
||||
@@ -248,25 +338,24 @@ extern "C" void app_main(void)
|
||||
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, "Failed to initialize camera module!");
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Check that your camera module is working and connected properly!");
|
||||
initSucessful = false;
|
||||
setSystemStatusFlag(SYSTEM_STATUS_CAM_BAD);
|
||||
}
|
||||
} else { // Test Camera
|
||||
camera_fb_t * fb = esp_camera_fb_get();
|
||||
if (!fb) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialzed. Will restart in 5 minutes!");
|
||||
initSucessful = false;
|
||||
} else { // Test Camera
|
||||
if (!Camera.testCamera()) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Camera Framebuffer cannot be initialized!");
|
||||
/* Easiest would be to simply restart here and try again,
|
||||
how ever there seem to be systems where it fails at startup but still work corectly later.
|
||||
Therefore we treat it still as successed! */
|
||||
setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
|
||||
}
|
||||
else {
|
||||
esp_camera_fb_return(fb);
|
||||
Camera.LightOnOff(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
xDelay = 2000 / portTICK_PERIOD_MS;
|
||||
ESP_LOGD(TAG, "main: sleep for: %ldms", (long) xDelay*10);
|
||||
vTaskDelay( xDelay );
|
||||
@@ -278,24 +367,34 @@ extern "C" void app_main(void)
|
||||
register_server_tflite_uri(server);
|
||||
register_server_file_uri(server, "/sdcard");
|
||||
register_server_ota_sdcard_uri(server);
|
||||
register_server_mqtt_uri(server);
|
||||
#ifdef ENABLE_MQTT
|
||||
register_server_mqtt_uri(server);
|
||||
#endif //ENABLE_MQTT
|
||||
|
||||
gpio_handler_create(server);
|
||||
|
||||
ESP_LOGD(TAG, "vor reg server main");
|
||||
ESP_LOGD(TAG, "Before reg server main");
|
||||
register_server_main_uri(server, "/sdcard");
|
||||
|
||||
if (initSucessful) {
|
||||
|
||||
/* Testing */
|
||||
//setSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD);
|
||||
//setSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD);
|
||||
|
||||
/* Main Init has successed or only an error which allows to continue operation */
|
||||
if (getSystemStatus() == 0) { // No error flag is set
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Initialization completed successfully!");
|
||||
ESP_LOGD(TAG, "vor do autostart");
|
||||
ESP_LOGD(TAG, "Before do autostart");
|
||||
TFliteDoAutoStart();
|
||||
}
|
||||
else { // 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();
|
||||
else if (isSetSystemStatusFlag(SYSTEM_STATUS_CAM_FB_BAD) || // Non critical errors occured, we try to continue...
|
||||
isSetSystemStatusFlag(SYSTEM_STATUS_NTP_BAD)) {
|
||||
LogFile.WriteToFile(ESP_LOG_WARN, TAG, "Initialization completed with errors, but trying to continue...");
|
||||
ESP_LOGD(TAG, "Before do autostart");
|
||||
TFliteDoAutoStart();
|
||||
}
|
||||
else { // Any other error is critical and makes running the flow impossible.
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "Initialization failed. Not starting flows!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
#include "server_tflite.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Helper.h"
|
||||
|
||||
//#define DEBUG_DETAIL_ON
|
||||
|
||||
|
||||
|
||||
httpd_handle_t server = NULL;
|
||||
std::string starttime = "";
|
||||
|
||||
@@ -48,155 +46,139 @@ esp_err_t info_get_handler(httpd_req_t *req)
|
||||
ESP_LOGD(TAG, "type is found: %s", _valuechar);
|
||||
_task = std::string(_valuechar);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
if (_task.compare("GitBranch") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_branch());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_branch());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("GitTag") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_version());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_version());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("GitRevision") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, libfive_git_revision());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, libfive_git_revision());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("BuildTime") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, build_time());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, build_time());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("FirmwareVersion") == 0)
|
||||
{
|
||||
string buf;
|
||||
if (std::string(GIT_TAG) == "") { // Tag not set, show branch
|
||||
buf = "Development-Branch: " + std::string(GIT_BRANCH);
|
||||
}
|
||||
else { // Tag is set, ignore branch
|
||||
buf = "Release: " + std::string(GIT_TAG);
|
||||
}
|
||||
buf = buf + " (Commit: " + std::string(GIT_REV) + ")";
|
||||
httpd_resp_sendstr_chunk(req, buf.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, getFwVersion().c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("HTMLVersion") == 0)
|
||||
{
|
||||
httpd_resp_sendstr_chunk(req, getHTMLversion().c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, getHTMLversion().c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("Hostname") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string(hostname);
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("IP") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getIPAddress();
|
||||
httpd_resp_sendstr_chunk(req, zw->c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw->c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SSID") == 0)
|
||||
{
|
||||
std::string *zw;
|
||||
zw = getSSID();
|
||||
httpd_resp_sendstr_chunk(req, zw->c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw->c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("FlowStatus") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = std::string("FlowStatus");
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("Round") == 0)
|
||||
{
|
||||
char formated[10] = "";
|
||||
snprintf(formated, sizeof(formated), "%d", getCountFlowRounds());
|
||||
httpd_resp_sendstr(req, formated);
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardFreePartitionSpace") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardFreePartitionSpace();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardPartitionAllocationSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardPartitionAllocationSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardManufacturer") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardManufacturer();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardName") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardName();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardCapacity") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardCapacity();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
else if (_task.compare("SDCardSectorSize") == 0)
|
||||
{
|
||||
std::string zw;
|
||||
zw = getSDCardSectorSize();
|
||||
httpd_resp_sendstr_chunk(req, zw.c_str());
|
||||
httpd_resp_sendstr_chunk(req, NULL);
|
||||
httpd_resp_sendstr(req, zw.c_str());
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t starttime_get_handler(httpd_req_t *req)
|
||||
{
|
||||
httpd_resp_send(req, starttime.c_str(), strlen(starttime.c_str()));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
|
||||
httpd_resp_send(req, starttime.c_str(), starttime.length());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
@@ -230,9 +212,33 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
}
|
||||
}
|
||||
|
||||
if (filetosend == "/sdcard/html/index.html" && isSetupModusActive()) {
|
||||
ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html");
|
||||
filetosend = "/sdcard/html/setup.html";
|
||||
if (filetosend == "/sdcard/html/index.html") {
|
||||
if (isSetSystemStatusFlag(SYSTEM_STATUS_PSRAM_BAD) || // Initialization failed with crritical errors!
|
||||
isSetSystemStatusFlag(SYSTEM_STATUS_CAM_BAD)) {
|
||||
LogFile.WriteToFile(ESP_LOG_ERROR, TAG, "We have a critical error, not serving main page!");
|
||||
|
||||
char buf[20];
|
||||
std::string message = "<h1>AI on the Edge Device</h1><b>We have one or more critical errors:</b><br>";
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
if (isSetSystemStatusFlag((SystemStatusFlag_t)(1<<i))) {
|
||||
snprintf(buf, sizeof(buf), "0x%08X", 1<<i);
|
||||
message += std::string(buf) + "<br>";
|
||||
}
|
||||
}
|
||||
|
||||
message += "<br>Please check <a href=\"https://jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes\" target=_blank>jomjol.github.io/AI-on-the-edge-device-docs/Error-Codes</a> for more information!";
|
||||
message += "<br><br><button onclick=\"window.location.href='/reboot';\">Reboot</button>";
|
||||
message += " <button onclick=\"window.open('/ota_page.html');\">OTA Update</button>";
|
||||
message += " <button onclick=\"window.open('/log.html');\">Log Viewer</button>";
|
||||
message += " <button onclick=\"window.open('/info.html');\">Show System Info</button>";
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, message.c_str());
|
||||
return ESP_FAIL;
|
||||
}
|
||||
else if (isSetupModusActive()) {
|
||||
ESP_LOGD(TAG, "System is in setup mode --> index.html --> setup.html");
|
||||
filetosend = "/sdcard/html/setup.html";
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Filename: %s", filename);
|
||||
@@ -241,8 +247,8 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
|
||||
if (!filename) {
|
||||
ESP_LOGE(TAG, "Filename is too long");
|
||||
/* Respond with 500 Internal Server Error */
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Filename too long");
|
||||
/* Respond with 414 Error */
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
@@ -264,6 +270,7 @@ esp_err_t hello_main_handler(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t img_tmp_handler(httpd_req_t *req)
|
||||
{
|
||||
char filepath[50];
|
||||
@@ -288,11 +295,12 @@ esp_err_t img_tmp_handler(httpd_req_t *req)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Start");
|
||||
#endif
|
||||
|
||||
char filepath[50];
|
||||
|
||||
@@ -308,33 +316,27 @@ esp_err_t img_tmp_virtual_handler(httpd_req_t *req)
|
||||
filetosend = std::string(filename);
|
||||
ESP_LOGD(TAG, "File to upload: %s", filetosend.c_str());
|
||||
|
||||
// Serve raw.jpg
|
||||
if (filetosend == "raw.jpg")
|
||||
{
|
||||
return GetRawJPG(req);
|
||||
}
|
||||
|
||||
esp_err_t zw = GetJPG(filetosend, req);
|
||||
|
||||
if (zw == ESP_OK)
|
||||
// Serve alg.jpg, alg_roi.jpg or digital and analog ROIs
|
||||
if (ESP_OK == GetJPG(filetosend, req))
|
||||
return ESP_OK;
|
||||
|
||||
// File wird nicht intern bereit gestellt --> klassischer weg:
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done");
|
||||
#endif
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("img_tmp_virtual_handler - Done");
|
||||
#endif
|
||||
|
||||
// File was not served already --> serve with img_tmp_handler
|
||||
return img_tmp_handler(req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t sysinfo_handler(httpd_req_t *req)
|
||||
{
|
||||
const char* resp_str;
|
||||
std::string zw;
|
||||
std::string cputemp = std::to_string(temperatureRead());
|
||||
std::string cputemp = std::to_string((int)temperatureRead());
|
||||
std::string gitversion = libfive_git_version();
|
||||
std::string buildtime = build_time();
|
||||
std::string gitbranch = libfive_git_branch();
|
||||
@@ -342,38 +344,33 @@ esp_err_t sysinfo_handler(httpd_req_t *req)
|
||||
std::string gitrevision = libfive_git_revision();
|
||||
std::string htmlversion = getHTMLversion();
|
||||
char freeheapmem[11];
|
||||
sprintf(freeheapmem, "%zu", esp_get_free_heap_size());
|
||||
sprintf(freeheapmem, "%lu", (long) getESPHeapSize());
|
||||
|
||||
tcpip_adapter_ip_info_t ip_info;
|
||||
ESP_ERROR_CHECK(tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &ip_info));
|
||||
const char *hostname;
|
||||
ESP_ERROR_CHECK(tcpip_adapter_get_hostname(TCPIP_ADAPTER_IF_STA, &hostname));
|
||||
|
||||
zw = "[\
|
||||
{\
|
||||
\"firmware\" : \"" + gitversion + "\",\
|
||||
\"buildtime\" : \"" + buildtime + "\",\
|
||||
\"gitbranch\" : \"" + gitbranch + "\",\
|
||||
\"gittag\" : \"" + gittag + "\",\
|
||||
\"gitrevision\" : \"" + gitrevision + "\",\
|
||||
\"html\" : \"" + htmlversion + "\",\
|
||||
\"cputemp\" : \"" + cputemp + "\",\
|
||||
\"hostname\" : \"" + hostname + "\",\
|
||||
\"IPv4\" : \"" + ip4addr_ntoa(&ip_info.ip) + "\",\
|
||||
\"freeHeapMem\" : \"" + freeheapmem + "\"\
|
||||
}\
|
||||
]";
|
||||
|
||||
resp_str = zw.c_str();
|
||||
zw = string("[{") +
|
||||
"\"firmware\": \"" + gitversion + "\"," +
|
||||
"\"buildtime\": \"" + buildtime + "\"," +
|
||||
"\"gitbranch\": \"" + gitbranch + "\"," +
|
||||
"\"gittag\": \"" + gittag + "\"," +
|
||||
"\"gitrevision\": \"" + gitrevision + "\"," +
|
||||
"\"html\": \"" + htmlversion + "\"," +
|
||||
"\"cputemp\": \"" + cputemp + "\"," +
|
||||
"\"hostname\": \"" + hostname + "\"," +
|
||||
"\"IPv4\": \"" + ip4addr_ntoa(&ip_info.ip) + "\"," +
|
||||
"\"freeHeapMem\": \"" + freeheapmem + "\"" +
|
||||
"}]";
|
||||
|
||||
httpd_resp_set_type(req, "application/json");
|
||||
httpd_resp_send(req, resp_str, strlen(resp_str));
|
||||
/* Respond with an empty chunk to signal HTTP response completion */
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
httpd_resp_send(req, zw.c_str(), zw.length());
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
{
|
||||
httpd_uri_t info_get_handle = {
|
||||
@@ -400,7 +397,6 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
};
|
||||
httpd_register_uri_handler(server, &starttime_tmp_handle);
|
||||
|
||||
|
||||
httpd_uri_t img_tmp_handle = {
|
||||
.uri = "/img_tmp/*", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
@@ -409,7 +405,6 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
};
|
||||
httpd_register_uri_handler(server, &img_tmp_handle);
|
||||
|
||||
|
||||
httpd_uri_t main_rest_handle = {
|
||||
.uri = "/*", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
@@ -421,24 +416,23 @@ void register_server_main_uri(httpd_handle_t server, const char *base_path)
|
||||
}
|
||||
|
||||
|
||||
|
||||
httpd_handle_t start_webserver(void)
|
||||
{
|
||||
httpd_handle_t server = NULL;
|
||||
httpd_config_t config = { };
|
||||
|
||||
config.task_priority = tskIDLE_PRIORITY+1; // 20210924 --> vorher +5
|
||||
config.stack_size = 32768; //20210921 --> vorher 32768 // bei 32k stürzt das Programm beim Bilderaufnehmen ab
|
||||
config.core_id = tskNO_AFFINITY;
|
||||
config.server_port = 80;
|
||||
config.ctrl_port = 32768;
|
||||
config.max_open_sockets = 5; //20210921 --> vorher 7
|
||||
config.max_uri_handlers = 37; // vorher 24, 20220511: 35
|
||||
config.max_resp_headers = 8;
|
||||
config.backlog_conn = 5;
|
||||
config.lru_purge_enable = true; // dadurch werden alte Verbindungen gekappt, falls neue benögt werden.
|
||||
config.recv_wait_timeout = 5; // default: 5 20210924 --> vorher 30
|
||||
config.send_wait_timeout = 5; // default: 5 20210924 --> vorher 30
|
||||
config.task_priority = tskIDLE_PRIORITY+3; // previously -> 2022-12-11: tskIDLE_PRIORITY+1; 2021-09-24: tskIDLE_PRIORITY+5
|
||||
config.stack_size = 12288; // previously -> 2023-01-02: 32768
|
||||
config.core_id = 1; // previously -> 2023-01-02: 0, 2022-12-11: tskNO_AFFINITY;
|
||||
config.server_port = 80;
|
||||
config.ctrl_port = 32768;
|
||||
config.max_open_sockets = 5; //20210921 --> previously 7
|
||||
config.max_uri_handlers = 38; // previously 24, 20220511: 35, 20221220: 37, 2023-01-02:38
|
||||
config.max_resp_headers = 8;
|
||||
config.backlog_conn = 5;
|
||||
config.lru_purge_enable = true; // this cuts old connections if new ones are needed.
|
||||
config.recv_wait_timeout = 5; // default: 5 20210924 --> previously 30
|
||||
config.send_wait_timeout = 5; // default: 5 20210924 --> previously 30
|
||||
config.global_user_ctx = NULL;
|
||||
config.global_user_ctx_free_fn = NULL;
|
||||
config.global_transport_ctx = NULL;
|
||||
@@ -448,7 +442,7 @@ httpd_handle_t start_webserver(void)
|
||||
// config.uri_match_fn = NULL;
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
|
||||
starttime = gettimestring("%Y%m%d-%H%M%S");
|
||||
starttime = getCurrentTimeString("%Y%m%d-%H%M%S");
|
||||
|
||||
// Start the httpd server
|
||||
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
|
||||
@@ -462,6 +456,7 @@ httpd_handle_t start_webserver(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void stop_webserver(httpd_handle_t server)
|
||||
{
|
||||
httpd_stop(server);
|
||||
@@ -479,6 +474,7 @@ void disconnect_handler(void* arg, esp_event_base_t event_base,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void connect_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
|
||||
490
code/main/softAP.cpp
Normal file
490
code/main/softAP.cpp
Normal file
@@ -0,0 +1,490 @@
|
||||
#ifdef ENABLE_SOFTAP
|
||||
//if ENABLE_SOFTAP = disabled, set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n in sdkconfig.defaults to save 28k of flash
|
||||
#include "../../include/defines.h"
|
||||
|
||||
|
||||
#include "softAP.h"
|
||||
|
||||
/* WiFi softAP Example
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include <string>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#include "stdio.h"
|
||||
|
||||
#include "ClassLogFile.h"
|
||||
#include "server_help.h"
|
||||
#include "defines.h"
|
||||
#include "Helper.h"
|
||||
#include "server_ota.h"
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
/* The examples use WiFi configuration that you can set via project configuration menu.
|
||||
If you'd rather not, just change the below entries to strings with
|
||||
the config you want - ie #define EXAMPLE_WIFI_SSID "mywifissid"
|
||||
*/
|
||||
|
||||
bool isConfigINI = false;
|
||||
bool isWlanINI = false;
|
||||
|
||||
static const char *TAG = "wifi softAP";
|
||||
|
||||
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void* event_data)
|
||||
{
|
||||
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
|
||||
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" join, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
|
||||
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
|
||||
ESP_LOGI(TAG, "station "MACSTR" leave, AID=%d",
|
||||
MAC2STR(event->mac), event->aid);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_init_softAP(void)
|
||||
{
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_ap();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT,
|
||||
ESP_EVENT_ANY_ID,
|
||||
&wifi_event_handler,
|
||||
NULL,
|
||||
NULL));
|
||||
|
||||
wifi_config_t wifi_config = { };
|
||||
|
||||
strcpy((char*)wifi_config.ap.ssid, (const char*) EXAMPLE_ESP_WIFI_SSID);
|
||||
strcpy((char*)wifi_config.ap.password, (const char*) EXAMPLE_ESP_WIFI_PASS);
|
||||
wifi_config.ap.channel = EXAMPLE_ESP_WIFI_CHANNEL;
|
||||
wifi_config.ap.max_connection = EXAMPLE_MAX_STA_CONN;
|
||||
wifi_config.ap.authmode = WIFI_AUTH_WPA_WPA2_PSK;
|
||||
|
||||
if (strlen(EXAMPLE_ESP_WIFI_PASS) == 0) {
|
||||
wifi_config.ap.authmode = WIFI_AUTH_OPEN;
|
||||
}
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &wifi_config));
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_softap finished. SSID:%s password:%s channel:%d",
|
||||
EXAMPLE_ESP_WIFI_SSID, EXAMPLE_ESP_WIFI_PASS, EXAMPLE_ESP_WIFI_CHANNEL);
|
||||
}
|
||||
|
||||
|
||||
void SendHTTPResponse(httpd_req_t *req)
|
||||
{
|
||||
std::string message = "<h1>AI-on-the-edge - BASIC SETUP</h1><p>This is an access point with a minimal server to setup the minimum required files and information on the device and the SD-card. ";
|
||||
message += "This mode is always startet if one of the following files is missing: /wlan.ini or the /config/config.ini.<p>";
|
||||
message += "The setup is done in 3 steps: 1. upload full inital configuration (sd-card content), 2. store WLAN acces information, 3. reboot (and connect to WLANs)<p><p>";
|
||||
message += "Please follow the below instructions.<p>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
isWlanINI = FileExists(WLAN_CONFIG_FILE);
|
||||
|
||||
if (!isConfigINI)
|
||||
{
|
||||
message = "<h3>1. Upload initial configuration to sd-card</h3><p>";
|
||||
message += "The configuration file config.ini is missing and most propably the full configuration and html folder on the sd-card. ";
|
||||
message += "This is normal after the first flashing of the firmware and an empty sd-card. Please upload \"remote_setup.zip\", which contains an full inital configuration.<p>";
|
||||
message += "<input id=\"newfile\" type=\"file\"><br>";
|
||||
message += "<button class=\"button\" style=\"width:300px\" id=\"doUpdate\" type=\"button\" onclick=\"upload()\">Upload File</button><p>";
|
||||
message += "The upload might take up to 60s. After a succesfull upload the page will be updated.";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
message = "<script language=\"JavaScript\">";
|
||||
message += "function upload() {";
|
||||
message += "var xhttp = new XMLHttpRequest();";
|
||||
message += "xhttp.onreadystatechange = function() {if (xhttp.readyState == 4) {if (xhttp.status == 200) {location.reload();}}};";
|
||||
message += "var filePath = document.getElementById(\"newfile\").value.split(/[\\\\/]/).pop();";
|
||||
message += "var file = document.getElementById(\"newfile\").files[0];";
|
||||
message += "if (!file.name.includes(\"remote-setup\")){if (!confirm(\"The zip file name should contain '...remote-setup...'. Are you sure that you have downloaded the correct file?\"))return;};";
|
||||
message += "var upload_path = \"/upload/firmware/\" + filePath; xhttp.open(\"POST\", upload_path, true); xhttp.send(file);document.reload();";
|
||||
message += "document.getElementById(\"doUpdate\").disabled = true;}";
|
||||
message += "</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
return;
|
||||
}
|
||||
if (!isWlanINI)
|
||||
{
|
||||
message = "<h3>2. WLAN access credentials</h3><p>";
|
||||
message += "<table>";
|
||||
message += "<tr><td>WLAN-SSID</td><td><input type=\"text\" name=\"ssid\" id=\"ssid\"></td><td>SSID of the WLAN</td></tr>";
|
||||
message += "<tr><td>WLAN-Password</td><td><input type=\"text\" name=\"password\" id=\"password\"></td><td>ATTENTION: the password will not be encrypted during the sending.</td><tr>";
|
||||
message += "</table><p>";
|
||||
message += "<h4>ATTENTION:<h4>Be sure about the WLAN settings. They cannot be reseted afterwards. If ssid or password is wrong, you need to take out the sd-card and manually change them in \"wlan.ini\"!<p>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
// message = "</tr><tr><td> Hostname</td><td><input type=\"text\" name=\"hostname\" id=\"hostname\"></td><td></td>";
|
||||
// message += "</tr><tr><td>Fixed IP</td><td><input type=\"text\" name=\"ip\" id=\"ip\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>gateway</td><td><input type=\"text\" name=\"gateway\" id=\"gateway\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>netmask</td><td><input type=\"text\" name=\"netmask\" id=\"netmask\"></td><td>Leave emtpy if set by router</td>";
|
||||
// message += "</tr><tr><td>DNS</td><td><input type=\"text\" name=\"dns\" id=\"dns\"></td><td>Leave emtpy if set by router</td></tr>";
|
||||
// message += "<tr><td>RSSI Threashold</td><td><input type=\"number\" name=\"name\" id=\"threashold\" min=\"-100\" max=\"0\" step=\"1\" value = \"0\"></td><td>WLAN Mesh Parameter: Threashold for RSSI value to check for start switching access point in a mesh system.Possible values: -100 to 0, 0 = disabled - Value will be transfered to wlan.ini at next startup)</td></tr>";
|
||||
// httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
|
||||
|
||||
message = "<button class=\"button\" type=\"button\" onclick=\"wr()\">Write wlan.ini</button>";
|
||||
message += "<script language=\"JavaScript\">async function wr(){";
|
||||
message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value;";
|
||||
// message += "api = \"/config?\"+\"ssid=\"+document.getElementById(\"ssid\").value+\"&pwd=\"+document.getElementById(\"password\").value+\"&hn=\"+document.getElementById(\"hostname\").value+\"&ip=\"+document.getElementById(\"ip\").value+\"&gw=\"+document.getElementById(\"gateway\").value+\"&nm=\"+document.getElementById(\"netmask\").value+\"&dns=\"+document.getElementById(\"dns\").value+\"&rssi=\"+document.getElementById(\"threashold\").value;";
|
||||
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
return;
|
||||
}
|
||||
|
||||
message = "<h3>3. Reboot</h3><p>";
|
||||
message += "After triggering the reboot, the zip-files gets extracted and written to the sd-card.<br>The ESP32 will restart two times and then connect to your access point. Please find the IP in your router settings and access it with the new ip-address.<p>";
|
||||
message += "The first update and initialization process can take up to 3 minutes before you find it in the wlan. Error logs can be found on the console / serial logout.<p>Have fun!<p>";
|
||||
message += "<button class=\"button\" type=\"button\" onclick=\"rb()\")>Reboot to first setup.</button>";
|
||||
message += "<script language=\"JavaScript\">async function rb(){";
|
||||
message += "api = \"/reboot\";";
|
||||
message += "fetch(api);await new Promise(resolve => setTimeout(resolve, 1000));location.reload();}</script>";
|
||||
httpd_resp_send_chunk(req, message.c_str(), strlen(message.c_str()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t test_handler(httpd_req_t *req)
|
||||
{
|
||||
SendHTTPResponse(req);
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t reboot_handlerAP(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Start");
|
||||
#endif
|
||||
LogFile.WriteToFile(ESP_LOG_INFO, TAG, "Trigger reboot due to firmware update.");
|
||||
doRebootOTA();
|
||||
return ESP_OK;
|
||||
};
|
||||
|
||||
|
||||
esp_err_t config_ini_handler(httpd_req_t *req)
|
||||
{
|
||||
#ifdef DEBUG_DETAIL_ON
|
||||
LogFile.WriteHeapInfo("handler_ota_update - Start");
|
||||
#endif
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "config_ini_handler");
|
||||
char _query[400];
|
||||
char _valuechar[100];
|
||||
std::string fn = "/sdcard/firmware/";
|
||||
std::string _task = "";
|
||||
std::string ssid = "";
|
||||
std::string pwd = "";
|
||||
std::string hn = ""; // hostname
|
||||
std::string ip = "";
|
||||
std::string gw = ""; // gateway
|
||||
std::string nm = ""; // nm
|
||||
std::string dns = "";
|
||||
std::string rssi = "";
|
||||
|
||||
|
||||
if (httpd_req_get_url_query_str(req, _query, 400) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "Query: %s", _query);
|
||||
|
||||
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
|
||||
ssid = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "pwd", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "pwd is found: %s", _valuechar);
|
||||
pwd = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "ssid", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ssid is found: %s", _valuechar);
|
||||
ssid = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "hn", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "hostname is found: %s", _valuechar);
|
||||
hn = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "ip", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "ip is found: %s", _valuechar);
|
||||
ip = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "gw", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "gateway is found: %s", _valuechar);
|
||||
gw = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "nm", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "netmask is found: %s", _valuechar);
|
||||
nm = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "dns", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "dns is found: %s", _valuechar);
|
||||
dns = std::string(_valuechar);
|
||||
}
|
||||
|
||||
if (httpd_query_key_value(_query, "rssi", _valuechar, 30) == ESP_OK)
|
||||
{
|
||||
ESP_LOGD(TAG, "rssi is found: %s", _valuechar);
|
||||
rssi = std::string(_valuechar);
|
||||
}
|
||||
};
|
||||
|
||||
FILE* configfilehandle = fopen(WLAN_CONFIG_FILE, "w");
|
||||
|
||||
if (ssid.length())
|
||||
ssid = "ssid = \"" + ssid + "\"\n";
|
||||
else
|
||||
ssid = ";ssid = \"\"\n";
|
||||
|
||||
fputs(ssid.c_str(), configfilehandle);
|
||||
|
||||
if (pwd.length())
|
||||
pwd = "password = \"" + pwd + "\"\n";
|
||||
else
|
||||
pwd = ";password = \"\"\n";
|
||||
fputs(pwd.c_str(), configfilehandle);
|
||||
|
||||
if (hn.length())
|
||||
hn = "hostname = \"" + hn + "\"\n";
|
||||
else
|
||||
hn = ";hostname = \"\"\n";
|
||||
fputs(hn.c_str(), configfilehandle);
|
||||
|
||||
if (ip.length())
|
||||
ip = "ip = \"" + ip + "\"\n";
|
||||
else
|
||||
ip = ";ip = \"\"\n";
|
||||
fputs(ip.c_str(), configfilehandle);
|
||||
|
||||
if (gw.length())
|
||||
gw = "gateway = \"" + gw + "\"\n";
|
||||
else
|
||||
gw = ";gateway = \"\"\n";
|
||||
fputs(gw.c_str(), configfilehandle);
|
||||
|
||||
if (nm.length())
|
||||
nm = "netmask = \"" + nm + "\"\n";
|
||||
else
|
||||
nm = ";netmask = \"\"\n";
|
||||
fputs(nm.c_str(), configfilehandle);
|
||||
|
||||
if (dns.length())
|
||||
dns = "dns = \"" + dns + "\"\n";
|
||||
else
|
||||
dns = ";dns = \"\"\n";
|
||||
fputs(dns.c_str(), configfilehandle);
|
||||
|
||||
if (rssi.length())
|
||||
rssi = "RSSIThreashold = \"" + rssi + "\"\n";
|
||||
else
|
||||
rssi = ";rssi = \"\"\n";
|
||||
fputs(rssi.c_str(), configfilehandle);
|
||||
|
||||
fflush(configfilehandle);
|
||||
fclose(configfilehandle);
|
||||
|
||||
std::string zw = "ota without parameter - should not be the case!";
|
||||
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
|
||||
httpd_resp_send(req, zw.c_str(), strlen(zw.c_str()));
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGE(TAG, "end config.ini");
|
||||
|
||||
|
||||
return ESP_OK;
|
||||
};
|
||||
|
||||
|
||||
esp_err_t upload_post_handlerAP(httpd_req_t *req)
|
||||
{
|
||||
printf("Start des Post Handlers\n");
|
||||
MakeDir("/sdcard/config");
|
||||
MakeDir("/sdcard/firmware");
|
||||
MakeDir("/sdcard/html");
|
||||
MakeDir("/sdcard/img_tmp");
|
||||
MakeDir("/sdcard/log");
|
||||
MakeDir("/sdcard/demo");
|
||||
printf("Nach Start des Post Handlers\n");
|
||||
|
||||
LogFile.WriteToFile(ESP_LOG_DEBUG, TAG, "upload_post_handlerAP");
|
||||
char filepath[FILE_PATH_MAX];
|
||||
FILE *fd = NULL;
|
||||
|
||||
const char *filename = get_path_from_uri(filepath, "/sdcard",
|
||||
req->uri + sizeof("/upload") - 1, sizeof(filepath));
|
||||
if (!filename) {
|
||||
httpd_resp_send_err(req, HTTPD_414_URI_TOO_LONG, "Filename too long");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
printf("filepath: %s, filename: %s\n", filepath, filename);
|
||||
|
||||
DeleteFile(std::string(filepath));
|
||||
|
||||
|
||||
|
||||
fd = fopen(filepath, "w");
|
||||
if (!fd) {
|
||||
ESP_LOGE(TAG, "Failed to create file: %s", filepath);
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to create file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Receiving file: %s...", filename);
|
||||
|
||||
char buf[1024];
|
||||
int received;
|
||||
|
||||
int remaining = req->content_len;
|
||||
|
||||
printf("remaining: %d\n", remaining);
|
||||
|
||||
|
||||
|
||||
while (remaining > 0) {
|
||||
|
||||
ESP_LOGI(TAG, "Remaining size: %d", remaining);
|
||||
if ((received = httpd_req_recv(req, buf, MIN(remaining, 1024))) <= 0) {
|
||||
if (received == HTTPD_SOCK_ERR_TIMEOUT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG, "File reception failed!");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to receive file");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (received && (received != fwrite(buf, 1, received, fd))) {
|
||||
fclose(fd);
|
||||
unlink(filepath);
|
||||
|
||||
ESP_LOGE(TAG, "File write failed!");
|
||||
httpd_resp_send_err(req, HTTPD_500_INTERNAL_SERVER_ERROR, "Failed to write file to storage");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
remaining -= received;
|
||||
}
|
||||
fclose(fd);
|
||||
isConfigINI = true;
|
||||
|
||||
FILE* pfile = fopen("/sdcard/update.txt", "w");
|
||||
std::string _s_zw= "/sdcard" + std::string(filename);
|
||||
fwrite(_s_zw.c_str(), strlen(_s_zw.c_str()), 1, pfile);
|
||||
fclose(pfile);
|
||||
|
||||
|
||||
ESP_LOGI(TAG, "File reception complete");
|
||||
httpd_resp_set_hdr(req, "Location", "/test");
|
||||
httpd_resp_set_status(req, "303 See Other");
|
||||
httpd_resp_set_hdr(req, "Location", "/test");
|
||||
httpd_resp_send_chunk(req, NULL, 0);
|
||||
|
||||
ESP_LOGI(TAG, "Update page send out");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
httpd_handle_t start_webserverAP(void)
|
||||
{
|
||||
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
|
||||
config.uri_match_fn = httpd_uri_match_wildcard;
|
||||
httpd_handle_t server = NULL;
|
||||
if (httpd_start(&server, &config) == ESP_OK) {
|
||||
// Do something
|
||||
}
|
||||
|
||||
httpd_uri_t reboot_handle = {
|
||||
.uri = "/reboot", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = reboot_handlerAP,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &reboot_handle);
|
||||
|
||||
httpd_uri_t config_ini_handle = {
|
||||
.uri = "/config", // Match all URIs of type /path/to/file
|
||||
.method = HTTP_GET,
|
||||
.handler = config_ini_handler,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &config_ini_handle);
|
||||
|
||||
/* URI handler for uploading files to server */
|
||||
httpd_uri_t file_uploadAP = {
|
||||
.uri = "/upload/*", // Match all URIs of type /upload/path/to/file
|
||||
.method = HTTP_POST,
|
||||
.handler = upload_post_handlerAP,
|
||||
.user_ctx = NULL // Pass server data as context
|
||||
};
|
||||
httpd_register_uri_handler(server, &file_uploadAP);
|
||||
|
||||
httpd_uri_t test_uri = {
|
||||
.uri = "*",
|
||||
.method = HTTP_GET,
|
||||
.handler = test_handler,
|
||||
.user_ctx = NULL
|
||||
};
|
||||
httpd_register_uri_handler(server, &test_uri);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void CheckStartAPMode()
|
||||
{
|
||||
isConfigINI = FileExists(CONFIG_FILE);
|
||||
isWlanINI = FileExists(WLAN_CONFIG_FILE);
|
||||
|
||||
if (!isConfigINI or !isWlanINI)
|
||||
{
|
||||
wifi_init_softAP();
|
||||
start_webserverAP();
|
||||
while(1) { // wait until reboot within task_do_Update_ZIP
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //#ifdef ENABLE_SOFTAP
|
||||
23
code/main/softAP.h
Normal file
23
code/main/softAP.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifdef ENABLE_SOFTAP
|
||||
|
||||
#ifndef SOFTAP_H
|
||||
#define SOFTAP_H
|
||||
|
||||
#include <esp_wifi.h>
|
||||
#include <esp_event.h>
|
||||
#include <esp_log.h>
|
||||
#include <esp_system.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <sys/param.h>
|
||||
#include "nvs_flash.h"
|
||||
#include "esp_netif.h"
|
||||
#include "esp_eth.h"
|
||||
#include "protocol_examples_common.h"
|
||||
#include "esp_tls_crypto.h"
|
||||
#include <esp_http_server.h>
|
||||
|
||||
void CheckStartAPMode();
|
||||
|
||||
#endif //SOFTAP_H
|
||||
|
||||
#endif //#ifdef ENABLE_SOFTAP
|
||||
@@ -15,6 +15,7 @@ extern "C"
|
||||
#include <string.h>
|
||||
#include "Helper.h"
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
|
||||
const char* build_time(void)
|
||||
@@ -38,6 +39,19 @@ const char* libfive_git_branch(void)
|
||||
}
|
||||
|
||||
|
||||
std::string getFwVersion(void) {
|
||||
std::string buf;
|
||||
if (std::string(GIT_TAG) == "") { // Tag not set, show branch
|
||||
buf = "Development-Branch: " + std::string(GIT_BRANCH);
|
||||
}
|
||||
else { // Tag is set, ignore branch
|
||||
buf = "Release: " + std::string(GIT_TAG);
|
||||
}
|
||||
buf = buf + " (Commit: " + std::string(GIT_REV) + ")";
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
std::string getHTMLversion(void){
|
||||
char buf[100]="?\0";
|
||||
FILE* pFile;
|
||||
@@ -50,7 +64,10 @@ std::string getHTMLversion(void){
|
||||
fgets(buf, sizeof(buf), pFile); // Line 1: Version
|
||||
fclose(pFile);
|
||||
|
||||
return std::string(buf);
|
||||
string value = string(buf);
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); // Remove any newlines
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string getHTMLcommit(void){
|
||||
@@ -66,7 +83,10 @@ std::string getHTMLcommit(void){
|
||||
fgets(buf, sizeof(buf), pFile); // Line 2: Commit
|
||||
fclose(pFile);
|
||||
|
||||
return std::string(buf);
|
||||
string value = string(buf);
|
||||
value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); // Remove any newlines
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#endif // _VERSION_H
|
||||
@@ -8,41 +8,207 @@
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
|
||||
[platformio]
|
||||
src_dir = main
|
||||
src_dir = main
|
||||
default_envs = esp32cam
|
||||
|
||||
[common:idf]
|
||||
build_flags =
|
||||
-DUSE_ESP_IDF
|
||||
lib_deps =
|
||||
|
||||
[common:esp32-idf]
|
||||
extends = common:idf
|
||||
platform = platformio/espressif32 @ 5.2.0
|
||||
framework = espidf
|
||||
lib_deps =
|
||||
${common:idf.lib_deps}
|
||||
build_flags =
|
||||
${common:idf.build_flags}
|
||||
-Wno-nonnull-compare
|
||||
-DUSE_ESP32
|
||||
-DUSE_ESP32_FRAMEWORK_ESP_IDF
|
||||
|
||||
|
||||
[flags:runtime]
|
||||
build_flags =
|
||||
-Wno-nonnull-compare
|
||||
-Wno-sign-compare
|
||||
-Wno-unused-but-set-variable
|
||||
-Wno-unused-variable
|
||||
-fno-exceptions
|
||||
|
||||
[flags:clangtidy]
|
||||
build_flags =
|
||||
-Wall
|
||||
-Wextra
|
||||
-Wunreachable-code
|
||||
;-Wshadow-compatible-local
|
||||
-fno-exceptions
|
||||
|
||||
; The main env - default
|
||||
[env:esp32cam]
|
||||
platform = espressif32@5.2.0
|
||||
extends = common:esp32-idf
|
||||
board = esp32cam
|
||||
;board = m5stack-core-esp32
|
||||
framework = espidf
|
||||
|
||||
;board_build.partitions = partitions_singleapp.csv
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:runtime.build_flags}
|
||||
; ### Sofware options : (can be set in defines.h)
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
-D ENABLE_SOFTAP
|
||||
board_build.partitions = partitions.csv
|
||||
|
||||
lib_deps =
|
||||
jomjol_configfile
|
||||
jomjol_helper
|
||||
jomjol_wlan
|
||||
jomjol_image_proc
|
||||
jomjol_controlcamera
|
||||
jomjol_flowcontroll
|
||||
jomjol_tfliteclass
|
||||
tflite-lib
|
||||
jomjol_fileserver_ota
|
||||
jomjol_time_sntp
|
||||
jomjol_logfile
|
||||
jomjol_mqtt
|
||||
jomjol_influxdb
|
||||
jomjol_controlGPIO
|
||||
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_rts = 0
|
||||
monitor_dtr = 0
|
||||
|
||||
debug_tool = esp-prog
|
||||
; full standalone dev mode
|
||||
; As sample, the board is nod32s instead of esp32cam (do not change nothing in fact :)
|
||||
; You can test newer platform_packages
|
||||
; or flash mode (board_build.flash_mode = qio)
|
||||
[env:esp32cam-dev]
|
||||
extends = common:esp32-idf
|
||||
board = esp32cam ; node32s
|
||||
;board_build.flash_mode = qio ;generate SPI_FAST_FLASH_BOOT boot loop
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Sofware options : (can be set in defines.h)
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
;-D ENABLE_SOFTAP
|
||||
; ### Debug options :
|
||||
;-D DEBUG_DETAIL_ON
|
||||
;-D DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
;-D DEBUG_ENABLE_SYSINFO
|
||||
;-D DEBUG_ENABLE_PERFMON
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;### test options
|
||||
-D CONFIG_ESP_TASK_WDT
|
||||
;-D CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL
|
||||
-D CONFIG_ESP_TASK_WDT_TIMEOUT_S ; fix for CONFIG_ESP_INT_WDT_TIMEOUT_MS
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
framework = espidf
|
||||
lib_ldf_mode = deep+
|
||||
platform = platformio/espressif32 @ 5.2.0
|
||||
platform_packages =
|
||||
;platformio/framework-espidf @ 3.40402.0 (4.4.2)
|
||||
;platformio/framework-espidf@^3.50000.0
|
||||
;platformio/tool-cmake @ 3.16.4
|
||||
;platformio/tool-cmake@^3.21.3
|
||||
;platformio/tool-esptoolpy @ 1.40201.0 (4.2.1)
|
||||
;platformio/tool-esptoolpy@^1.40400.0
|
||||
;platformio/tool-idf @ 1.0.1
|
||||
;platformio/tool-mconf @ 1.4060000.20190628 (406.0.0)
|
||||
;platformio/tool-ninja @ 1.9.0
|
||||
;platformio/tool-ninja @ 1.10.2
|
||||
;platformio/toolchain-esp32ulp @ 1.22851.191205 (2.28.51)
|
||||
;espressif/toolchain-esp32ulp @ 2.35.0-20220830
|
||||
;platformio/toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
|
||||
;platformio/toolchain-xtensa-esp32 @ 11.2.0+2022r1
|
||||
|
||||
; Enable and adapt for logging over USB
|
||||
;upload_port = /dev/ttyUSB0
|
||||
; platformio/espressif32 @ 5.3.0 dependencies :
|
||||
;platformio/framework-espidf @ 3.40403.0
|
||||
;platformio/tool-cmake @ 3.16.4
|
||||
;platformio/tool-esptoolpy@^1.40400.0
|
||||
;platformio/tool-idf @ 1.0.1
|
||||
;platformio/tool-mconf @ 1.4060000.20190628
|
||||
;platformio/tool-ninja @ 1.9.0
|
||||
;espressif/toolchain-esp32ulp @ 2.35.0-20220830
|
||||
;;;;espressif/toolchain-xtensa-esp32 @ 8.4.0+2021r2-patch5
|
||||
board_build.partitions = partitions.csv
|
||||
monitor_speed = 115200
|
||||
monitor_rts = 0
|
||||
monitor_dtr = 0
|
||||
|
||||
|
||||
; Activate all debug mode
|
||||
; Cannot be used alone, but must be added at the end of extends = env:esp32cam-dev, esp32cam-debug
|
||||
;If multiple items specified in the extends field then only values from the latter one will be used in the final configuration
|
||||
;https://docs.platformio.org/en/stable/projectconf/section_env_advanced.html
|
||||
[env:esp32cam-debug] ; activate all debug
|
||||
;extends nothing, only apply sdkconfig.esp32-debug.defaults, enable debug options and clangtidy
|
||||
build_flags =
|
||||
; ### clangtidy build flags:
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Debug options :
|
||||
-D DEBUG_DETAIL_ON
|
||||
;-D DEBUG_DISABLE_BROWNOUT_DETECTOR
|
||||
-D DEBUG_ENABLE_SYSINFO
|
||||
-D DEBUG_ENABLE_PERFMON
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
lib_ldf_mode = deep+
|
||||
|
||||
; Power management enabled
|
||||
;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/power_management.html
|
||||
;https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-pm-enable
|
||||
[env:esp32cam-power-management]
|
||||
build_flags =
|
||||
-D TCONFIG_PM_ENABLE
|
||||
-D CONFIG_PM_DFS_INIT_AUTO
|
||||
-D CONFIG_FREERTOS_USE_TICKLESS_IDLE
|
||||
;-D FREERTOS_IDLE_TIME_BEFORE_SLEEP=3
|
||||
|
||||
;**********************
|
||||
; next section use modified version CMakeLists.txt of to use sdkconfig.<pioenv>.defaults + sdkconfig.defaults
|
||||
; https://github.com/platformio/platform-espressif32/issues/638
|
||||
|
||||
|
||||
; set board to rev3
|
||||
[env:esp32cam-board-rev3]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
|
||||
; set CPU frequency to 240 instead of 160 default
|
||||
[env:esp32cam-cpu-freq-240]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-board-rev3.defaults override some sdkconfig.defaults
|
||||
|
||||
; set board to rev3 + CPU frequency to 240
|
||||
; look at the extends : it takes esp32cam-dev and add env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , esp32cam-debug parameters
|
||||
[env:esp32cam-board-rev3-cpu-freq-240]
|
||||
extends = env:esp32cam-dev, env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , esp32cam-debug
|
||||
|
||||
; set board to rev3 + CPU frequency to 240 + power management
|
||||
[env:esp32cam-board-rev3-cpu-freq-240-pow]
|
||||
extends = env:esp32cam-dev, env:esp32cam-board-rev3, env:esp32cam-cpu-freq-240 , env:esp32cam-power-management, esp32cam-debug
|
||||
|
||||
; Enable use of 8 MB PSRAM boards
|
||||
;https://github.com/espressif/esp-idf/blob/master/examples/system/himem/README.md
|
||||
[env:esp32cam-dev-himem]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-dev-himem.defaults override some sdkconfig.defaults
|
||||
build_flags =
|
||||
-DBOARD_HAS_PSRAM
|
||||
;-D DEBUG_HIMEM_MEMORY_CHECK
|
||||
;-D USE_HIMEM_IF_AVAILABLE
|
||||
|
||||
; set options for task analysis (PR #1751)
|
||||
[env:esp32cam-dev-task-analysis]
|
||||
extends = env:esp32cam-dev, esp32cam-debug
|
||||
; sdkconfig.esp32cam-dev-task-analysis.defaults override some sdkconfig.defaults
|
||||
build_flags =
|
||||
;-D DEBUG_DETAIL_ON ; if esp32cam-debug not in extends
|
||||
-D TASK_ANALYSIS_ON
|
||||
;please use only one HEAP tracing at time.
|
||||
-D HEAP_TRACING_MAIN_WIFI
|
||||
;-D HEAP_TRACING_MAIN_START
|
||||
;-D HEAP_TRACING_CLASS_FLOW_CNN_GENERAL_DO_ALING_AND_CUT
|
||||
|
||||
|
||||
; Overwrite espcam build_flags to not include ENABLE_SOFTAP
|
||||
; Nor the -U ENABLE_SOFTAP nor -D ENABLE_SOFTAP=0 works to unset defines actually
|
||||
; Set CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n in sdkconfig.esp32cam-no-softap.defaults to disable softap in the esp-idf compilation
|
||||
[env:esp32cam-no-softap] ;CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n saves 28k of flash
|
||||
extends = env:esp32cam
|
||||
build_flags =
|
||||
; ### common imported :
|
||||
${common:esp32-idf.build_flags}
|
||||
${flags:clangtidy.build_flags}
|
||||
; ### Sofware options :
|
||||
-D ENABLE_MQTT
|
||||
-D ENABLE_INFLUXDB
|
||||
;-D ENABLE_SOFTAP ; disabled
|
||||
|
||||
@@ -1,16 +1,78 @@
|
||||
##################################################
|
||||
##################################################
|
||||
# Application specific configuration
|
||||
# Edit this file instead of sdkconfig.esp32cam!
|
||||
# After editting, make sure to explicitly delete
|
||||
# sdkconfig.esp32cam to apply your changes!
|
||||
##################################################
|
||||
|
||||
#if ENABLE_SOFTAP = disabled, set
|
||||
#CONFIG_ESP_WIFI_SOFTAP_SUPPORT=n
|
||||
#to save 28k of flash
|
||||
|
||||
CONFIG_TASK_WDT=n
|
||||
CONFIG_TASK_WDT_CHECK_IDLE_TASK=n
|
||||
|
||||
CONFIG_COMPILER_OPTIMIZATION_DEFAULT=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||
|
||||
###### safe optimizations
|
||||
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y
|
||||
|
||||
#disable bootloader logging
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=y
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=0
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=y
|
||||
CONFIG_FREERTOS_ASSERT_DISABLE=y
|
||||
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=0
|
||||
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y
|
||||
#CONFIG_LOG_DEFAULT_LEVEL=0
|
||||
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
||||
CONFIG_LWIP_ESP_LWIP_ASSERT=n
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=y
|
||||
CONFIG_OPTIMIZATION_ASSERTION_LEVEL=0
|
||||
# CONFIG_LOG_COLORS is not set
|
||||
|
||||
#set default loggin to
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=1
|
||||
|
||||
#disable lookup function
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=n
|
||||
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
|
||||
|
||||
#no panic message
|
||||
ESP_SYSTEM_PANIC_SILENT_REBOOT=y
|
||||
|
||||
#disable ADC calibration (needed for external sensors)
|
||||
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=n
|
||||
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=n
|
||||
CONFIG_ADC_CAL_LUT_ENABLE=needed
|
||||
|
||||
#disable IPV6
|
||||
CONFIG_LWIP_IPV6=n
|
||||
|
||||
#Newlib format
|
||||
CONFIG_NEWLIB_NANO_FORMAT=y
|
||||
|
||||
|
||||
# ESP-NN
|
||||
#
|
||||
# CONFIG_NN_ANSI_C is not set
|
||||
CONFIG_NN_OPTIMIZED=y
|
||||
CONFIG_NN_OPTIMIZATIONS=1
|
||||
# end of ESP-NN
|
||||
|
||||
# ESP HTTP client
|
||||
#
|
||||
# CONFIG_ESP_HTTP_CLIENT_ENABLE_HTTPS is not set
|
||||
|
||||
###### end safe optimizations
|
||||
|
||||
CONFIG_ESP32_REV_MIN_0=y
|
||||
|
||||
CONFIG_ESP32_DPORT_WORKAROUND=y
|
||||
@@ -34,30 +96,33 @@ CONFIG_SPIRAM_BOOT_INIT=y
|
||||
CONFIG_SPIRAM_USE_MALLOC=y
|
||||
CONFIG_SPIRAM_MEMTEST=y
|
||||
CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
|
||||
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=32768
|
||||
CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL=40960
|
||||
CONFIG_SPIRAM_CACHE_WORKAROUND=y
|
||||
CONFIG_SPIRAM_IGNORE_NOTFOUND=y
|
||||
|
||||
CONFIG_ESP_INT_WDT_TIMEOUT_MS=300
|
||||
|
||||
CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
|
||||
|
||||
CONFIG_HTTPD_PURGE_BUF_LEN=16
|
||||
|
||||
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=16
|
||||
|
||||
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=16
|
||||
|
||||
CONFIG_FATFS_LFN_HEAP=y
|
||||
|
||||
CONFIG_FATFS_MAX_LFN=255
|
||||
CONFIG_FATFS_API_ENCODING_ANSI_OEM=y
|
||||
|
||||
CONFIG_FMB_TIMER_PORT_ENABLED=y
|
||||
|
||||
CONFIG_MQTT_MSG_ID_INCREMENTAL=y
|
||||
CONFIG_MQTT_SKIP_PUBLISH_IF_DISCONNECTED=y
|
||||
CONFIG_MQTT_TASK_CORE_SELECTION_ENABLED=y
|
||||
CONFIG_MQTT_USE_CORE_0=y
|
||||
|
||||
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n
|
||||
|
||||
CONFIG_CAMERA_CORE0=n
|
||||
CONFIG_CAMERA_CORE1=y
|
||||
CONFIG_OV7670_SUPPORT=n
|
||||
CONFIG_OV7725_SUPPORT=n
|
||||
CONFIG_NT99141_SUPPORT=n
|
||||
@@ -66,4 +131,16 @@ CONFIG_OV5640_SUPPORT=n
|
||||
CONFIG_GC2145_SUPPORT=n
|
||||
CONFIG_GC032A_SUPPORT=n
|
||||
CONFIG_GC0308_SUPPORT=n
|
||||
CONFIG_BF3005_SUPPORT=n
|
||||
CONFIG_BF3005_SUPPORT=n
|
||||
|
||||
#only necessary for task analysis (include/defines -> TASK_ANALYSIS_ON)
|
||||
#set in [env:esp32cam-dev-task-analysis]
|
||||
#CONFIG_FREERTOS_USE_TRACE_FACILITY=1
|
||||
#CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
|
||||
#CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
|
||||
|
||||
#force disable HIMEM as not used in default config, can be enabled with [env:esp32cam-dev-himem]
|
||||
#free 256kb of internal memory :
|
||||
#I (2112) esp_himem: Initialized. Using last 8 32KB address blocks for bank switching on 4352 KB of physical memory.
|
||||
CONFIG_SPIRAM_BANKSWITCH_ENABLE=n
|
||||
#CONFIG_SPIRAM_BANKSWITCH_RESERVE is not set
|
||||
|
||||
7
code/sdkconfig.esp32cam-board-rev3.defaults
Normal file
7
code/sdkconfig.esp32cam-board-rev3.defaults
Normal file
@@ -0,0 +1,7 @@
|
||||
CONFIG_ESP32_REV_MIN_0=n
|
||||
|
||||
ESP32_REV_MIN_3=y
|
||||
CONFIG_ESP32_REV_MIN_3=y
|
||||
|
||||
#https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/kconfig.html#config-spiram-cache-workaround
|
||||
CONFIG_ESP32_DPORT_WORKAROUND=n
|
||||
4
code/sdkconfig.esp32cam-cpu-freq-240.defaults
Normal file
4
code/sdkconfig.esp32cam-cpu-freq-240.defaults
Normal file
@@ -0,0 +1,4 @@
|
||||
CONFIG_FREERTOS_UNICORE=n
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
|
||||
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
|
||||
33
code/sdkconfig.esp32cam-debug.defaults
Normal file
33
code/sdkconfig.esp32cam-debug.defaults
Normal file
@@ -0,0 +1,33 @@
|
||||
#enable bootloader logging
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE=n
|
||||
CONFIG_COMPILER_OPTIMIZATION_ASSERTION_LEVEL=2
|
||||
CONFIG_COMPILER_OPTIMIZATION_CHECKS_SILENT=n
|
||||
CONFIG_FREERTOS_ASSERT_DISABLE=yn
|
||||
CONFIG_HAL_DEFAULT_ASSERTION_LEVEL=n
|
||||
#CONFIG_LOG_DEFAULT_LEVEL_NONE=y
|
||||
#CONFIG_LOG_DEFAULT_LEVEL=0
|
||||
CONFIG_LOG_MAXIMUM_EQUALS_DEFAULT=y
|
||||
CONFIG_LWIP_ESP_LWIP_ASSERT=n
|
||||
CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED=n
|
||||
CONFIG_OPTIMIZATION_ASSERTION_LEVEL=2
|
||||
# CONFIG_LOG_COLORS is not set
|
||||
|
||||
#set default loggin to
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_WARN is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_INFO is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_DEBUG is not set
|
||||
# CONFIG_BOOTLOADER_LOG_LEVEL_VERBOSE is not set
|
||||
CONFIG_BOOTLOADER_LOG_LEVEL=2
|
||||
|
||||
#disable lookup function
|
||||
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
|
||||
# CONFIG_ESP_ERR_TO_NAME_LOOKUP is not set
|
||||
|
||||
#no panic message
|
||||
ESP_SYSTEM_PANIC_SILENT_REBOOT=n
|
||||
|
||||
#disable ADC calibration (needed for external sensors)
|
||||
CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y
|
||||
CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y
|
||||
CONFIG_ADC_CAL_LUT_ENABLE=needed
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user