Compare commits
130 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d777040c0a | ||
|
|
a5636a60f8 | ||
|
|
6f817b2ed5 | ||
|
|
e4fec4f4c2 | ||
|
|
3a25964ec4 | ||
|
|
1227dff412 | ||
|
|
26ee2e6efc | ||
|
|
d6a8d31278 | ||
|
|
3f2b534baa | ||
|
|
70f413013c | ||
|
|
6edcd174bb | ||
|
|
3170ef6ce9 | ||
|
|
fb56f4d012 | ||
|
|
c5756f0cba | ||
|
|
95c9ecc8b2 | ||
|
|
bdee066c33 | ||
|
|
957039d0c0 | ||
|
|
dd23a0fa60 | ||
|
|
7777a0a059 | ||
|
|
e8fc6d48bf | ||
|
|
c98148c886 | ||
|
|
6ba2b4060e | ||
|
|
762c17ca8e | ||
|
|
fad6ada1e0 | ||
|
|
fb1d343ee3 | ||
|
|
1f3c32e80a | ||
|
|
43fbca7099 | ||
|
|
7a36082564 | ||
|
|
fb2cfdfe01 | ||
|
|
6c3dca9344 | ||
|
|
cce5d75fd7 | ||
|
|
8fd411c1d6 | ||
|
|
4b15ac74fc | ||
|
|
508b2e6c45 | ||
|
|
af630615db | ||
|
|
222a4f13e2 | ||
|
|
3bc6c75c5a | ||
|
|
dbb3eac709 | ||
|
|
1cee48eab4 | ||
|
|
c28752a00a | ||
|
|
365061df29 | ||
|
|
870617f780 | ||
|
|
4972b980ba | ||
|
|
51c70abda3 | ||
|
|
8d448533c7 | ||
|
|
43cb9a0000 | ||
|
|
d49b7eac09 | ||
|
|
8f057e687c | ||
|
|
5b4f680114 | ||
|
|
fabdfbadf4 | ||
|
|
afa47ea633 | ||
|
|
461d76e651 | ||
|
|
c40e20c8e9 | ||
|
|
4e97554514 | ||
|
|
28a9d6746b | ||
|
|
7ea4fe881c | ||
|
|
c4eaf8184b | ||
|
|
312972f77d | ||
|
|
27b9058af5 | ||
|
|
bc4d61098c | ||
|
|
b2de6472cf | ||
|
|
6c3ddc57b5 | ||
|
|
2ff7044c85 | ||
|
|
0145be851e | ||
|
|
6b0d540f39 | ||
|
|
2218ac4e8a | ||
|
|
33bd3da310 | ||
|
|
a239e1a63d | ||
|
|
8a809ec128 | ||
|
|
b48a0f13fe | ||
|
|
b07ed075f4 | ||
|
|
0927cab8e2 | ||
|
|
eed35b7bbc | ||
|
|
e34da5fd83 | ||
|
|
148fb14c93 | ||
|
|
000cfd8697 | ||
|
|
1ef5703971 | ||
|
|
cda3b80b35 | ||
|
|
c7b8090634 | ||
|
|
63a8d79b95 | ||
|
|
02ae3fc7f5 | ||
|
|
2dcc874592 | ||
|
|
d4d9d2224f | ||
|
|
902e43979b | ||
|
|
8e54f23367 | ||
|
|
ab7128c53a | ||
|
|
6563700df4 | ||
|
|
538de5ea99 | ||
|
|
042e2bcc85 | ||
|
|
b6f630b134 | ||
|
|
65a09dcecf | ||
|
|
775e5a0881 | ||
|
|
6c0d5fcc09 | ||
|
|
69d8fa9254 | ||
|
|
71d261bf34 | ||
|
|
9f4f5b4620 | ||
|
|
c38c305bab | ||
|
|
bfee2a1d64 | ||
|
|
ec7edae9a1 | ||
|
|
d8e265b7ac | ||
|
|
1987cddab7 | ||
|
|
e18be5f97c | ||
|
|
537597d6d1 | ||
|
|
a89013cec3 | ||
|
|
9c7a0cb7ff | ||
|
|
ade12199b9 | ||
|
|
92692c6eaf | ||
|
|
e4114c3e74 | ||
|
|
39b68aca51 | ||
|
|
feffbb53a3 | ||
|
|
e1b2554af2 | ||
|
|
627a50ab50 | ||
|
|
a20d007b45 | ||
|
|
64840e13f0 | ||
|
|
72f1d59338 | ||
|
|
07ed425320 | ||
|
|
2e75e1c4dc | ||
|
|
e6df68481f | ||
|
|
dc25c147b9 | ||
|
|
6a76144566 | ||
|
|
95d3008a66 | ||
|
|
04cd6ac387 | ||
|
|
584c7b1154 | ||
|
|
493c4b4337 | ||
|
|
488c969858 | ||
|
|
8b0d4185d3 | ||
|
|
608470c5f7 | ||
|
|
68b3415a6c | ||
|
|
d8f3ae8b07 | ||
|
|
1a92cd1978 |
2
.github/FUNDING.yml
vendored
@@ -1 +1 @@
|
|||||||
custom: ["https://paypal.me/gskjold"]
|
custom: ["https://amsleser.no"]
|
||||||
|
|||||||
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -33,6 +33,7 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
**Relevant firmware information:**
|
**Relevant firmware information:**
|
||||||
- Version: [e.g. 2.1.0]
|
- Version: [e.g. 2.1.0]
|
||||||
- MQTT: [yes/no]
|
- MQTT: [yes/no]
|
||||||
|
- MQTT payload type: [e.g. JSON]
|
||||||
- HAN GPIO: [e.g. GPIO5]
|
- HAN GPIO: [e.g. GPIO5]
|
||||||
- HAN baud and parity: [e.g. 2400 8E1]
|
- HAN baud and parity: [e.g. 2400 8E1]
|
||||||
- Temperature sensors [e.g. 3xDS18B20]
|
- Temperature sensors [e.g. 3xDS18B20]
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,8 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Meter configuration
|
- name: Meter configuration
|
||||||
url: https://github.com/gskjold/AmsToMqttBridge/wiki/Known-hardware-configurations
|
url: https://github.com/UtilitechAS/amsreader-firmware/wiki/Known-hardware-configurations
|
||||||
about: Please check your meter configuration here first.
|
about: Please check your meter configuration here first.
|
||||||
- name: Frequently asked questions
|
- name: Frequently asked questions
|
||||||
url: https://github.com/gskjold/AmsToMqttBridge/wiki/FAQ
|
url: https://github.com/UtilitechAS/amsreader-firmware/wiki/FAQ
|
||||||
about: Please check frequently asked questions first.
|
about: Please check frequently asked questions first.
|
||||||
|
|||||||
1
.github/ISSUE_TEMPLATE/support.md
vendored
@@ -20,6 +20,7 @@ A clear and concise description of what the problem is.
|
|||||||
**Relevant firmware information:**
|
**Relevant firmware information:**
|
||||||
- Version: [e.g. 2.1.0]
|
- Version: [e.g. 2.1.0]
|
||||||
- MQTT: [yes/no]
|
- MQTT: [yes/no]
|
||||||
|
- MQTT payload type: [e.g. JSON]
|
||||||
- HAN GPIO: [e.g. GPIO5]
|
- HAN GPIO: [e.g. GPIO5]
|
||||||
- HAN baud and parity: [e.g. 2400 8E1]
|
- HAN baud and parity: [e.g. 2400 8E1]
|
||||||
- Temperature sensors [e.g. 3xDS18B20]
|
- Temperature sensors [e.g. 3xDS18B20]
|
||||||
|
|||||||
19
.github/workflows/build.yml
vendored
@@ -8,6 +8,7 @@ on:
|
|||||||
- scripts/**
|
- scripts/**
|
||||||
- web/**
|
- web/**
|
||||||
- platformio.ini
|
- platformio.ini
|
||||||
|
- .github/workflows/**
|
||||||
branches:
|
branches:
|
||||||
- '*'
|
- '*'
|
||||||
tags:
|
tags:
|
||||||
@@ -22,6 +23,12 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Check out code from repo
|
- name: Check out code from repo
|
||||||
uses: actions/checkout@v1
|
uses: actions/checkout@v1
|
||||||
|
|
||||||
|
- name: Inject secrets into ini file
|
||||||
|
run: |
|
||||||
|
sed -i 's/NO_AMS2MQTT_PRICE_KEY/AMS2MQTT_PRICE_KEY="${{secrets.AMS2MQTT_PRICE_KEY}}"/g' platformio.ini
|
||||||
|
sed -i 's/NO_AMS2MQTT_PRICE_AUTHENTICATION/AMS2MQTT_PRICE_AUTHENTICATION="${{secrets.AMS2MQTT_PRICE_AUTHENTICATION}}"/g' platformio.ini
|
||||||
|
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
@@ -40,6 +47,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio css_html_js_minify
|
pip install -U platformio css_html_js_minify
|
||||||
|
- name: Set up node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '16.x'
|
||||||
|
- name: Build with node
|
||||||
|
run: |
|
||||||
|
cd lib/SvelteUi/app
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
cd -
|
||||||
|
env:
|
||||||
|
CI: true
|
||||||
- name: PlatformIO lib install
|
- name: PlatformIO lib install
|
||||||
run: pio lib install
|
run: pio lib install
|
||||||
- name: PlatformIO run
|
- name: PlatformIO run
|
||||||
|
|||||||
96
.github/workflows/release.yml
vendored
@@ -23,6 +23,12 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_REF: ${{ github.ref }}
|
GITHUB_REF: ${{ github.ref }}
|
||||||
run: echo "GITHUB_TAG=$(echo ${GITHUB_REF##*/})" >> $GITHUB_ENV
|
run: echo "GITHUB_TAG=$(echo ${GITHUB_REF##*/})" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
- name: Inject secrets into ini file
|
||||||
|
run: |
|
||||||
|
sed -i 's/NO_AMS2MQTT_PRICE_KEY/AMS2MQTT_PRICE_KEY="${{secrets.AMS2MQTT_PRICE_KEY}}"/g' platformio.ini
|
||||||
|
sed -i 's/NO_AMS2MQTT_PRICE_AUTHENTICATION/AMS2MQTT_PRICE_AUTHENTICATION="${{secrets.AMS2MQTT_PRICE_AUTHENTICATION}}"/g' platformio.ini
|
||||||
|
|
||||||
- name: Cache Python dependencies
|
- name: Cache Python dependencies
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v1
|
||||||
with:
|
with:
|
||||||
@@ -41,12 +47,23 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install -U platformio css_html_js_minify
|
pip install -U platformio css_html_js_minify
|
||||||
|
|
||||||
|
- name: Set up node
|
||||||
|
uses: actions/setup-node@v1
|
||||||
|
with:
|
||||||
|
node-version: '16.x'
|
||||||
|
- name: Build with node
|
||||||
|
run: |
|
||||||
|
cd lib/SvelteUi/app
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
cd -
|
||||||
|
env:
|
||||||
|
CI: false
|
||||||
|
|
||||||
- name: PlatformIO lib install
|
- name: PlatformIO lib install
|
||||||
run: pio lib install
|
run: pio lib install
|
||||||
- name: PlatformIO run
|
|
||||||
run: pio run
|
|
||||||
- name: Create zip files
|
|
||||||
run: /bin/sh scripts/mkzip.sh
|
|
||||||
- name: Create Release
|
- name: Create Release
|
||||||
id: create_release
|
id: create_release
|
||||||
uses: actions/create-release@v1.0.0
|
uses: actions/create-release@v1.0.0
|
||||||
@@ -58,6 +75,19 @@ jobs:
|
|||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
||||||
|
- name: Build esp8266 firmware
|
||||||
|
run: pio run -e esp8266
|
||||||
|
- name: Create esp8266 zip file
|
||||||
|
run: /bin/sh scripts/esp8266/mkzip.sh
|
||||||
|
- name: Upload esp8266 binary to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: .pio/build/esp8266/firmware.bin
|
||||||
|
asset_name: ams2mqtt-esp8266-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp8266 zip to release
|
- name: Upload esp8266 zip to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
@@ -67,6 +97,20 @@ jobs:
|
|||||||
asset_path: esp8266.zip
|
asset_path: esp8266.zip
|
||||||
asset_name: ams2mqtt-esp8266-${{ steps.release_tag.outputs.tag }}.zip
|
asset_name: ams2mqtt-esp8266-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: Build esp32 firmware
|
||||||
|
run: pio run -e esp32
|
||||||
|
- name: Create esp32 zip file
|
||||||
|
run: /bin/sh scripts/esp32/mkzip.sh
|
||||||
|
- name: Upload esp32 binary to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: .pio/build/esp32/firmware.bin
|
||||||
|
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp32 zip to release
|
- name: Upload esp32 zip to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
@@ -76,6 +120,20 @@ jobs:
|
|||||||
asset_path: esp32.zip
|
asset_path: esp32.zip
|
||||||
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.zip
|
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
|
- name: Build esp32s2 firmware
|
||||||
|
run: pio run -e esp32s2
|
||||||
|
- name: Create esp32s2 zip file
|
||||||
|
run: /bin/sh scripts/esp32s2/mkzip.sh
|
||||||
|
- name: Upload esp32s2 binary to release
|
||||||
|
uses: actions/upload-release-asset@v1
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
with:
|
||||||
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
|
asset_path: .pio/build/esp32s2/firmware.bin
|
||||||
|
asset_name: ams2mqtt-esp32s2-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp32s2 zip to release
|
- name: Upload esp32s2 zip to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
@@ -86,24 +144,10 @@ jobs:
|
|||||||
asset_name: ams2mqtt-esp32s2-${{ steps.release_tag.outputs.tag }}.zip
|
asset_name: ams2mqtt-esp32s2-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
asset_content_type: application/zip
|
asset_content_type: application/zip
|
||||||
|
|
||||||
- name: Upload esp8266 binary to release
|
- name: Build esp32solo firmware
|
||||||
uses: actions/upload-release-asset@v1
|
run: pio run -e esp32solo
|
||||||
env:
|
- name: Create esp32solo zip file
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
run: /bin/sh scripts/esp32solo/mkzip.sh
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: .pio/build/esp8266/firmware.bin
|
|
||||||
asset_name: ams2mqtt-esp8266-${{ steps.release_tag.outputs.tag }}.bin
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
- name: Upload esp32 binary to release
|
|
||||||
uses: actions/upload-release-asset@v1
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
with:
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
asset_path: .pio/build/esp32/firmware.bin
|
|
||||||
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
|
||||||
asset_content_type: application/octet-stream
|
|
||||||
- name: Upload esp32solo binary to release
|
- name: Upload esp32solo binary to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
@@ -113,12 +157,12 @@ jobs:
|
|||||||
asset_path: .pio/build/esp32solo/firmware.bin
|
asset_path: .pio/build/esp32solo/firmware.bin
|
||||||
asset_name: ams2mqtt-esp32solo-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp32solo-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp32s2 binary to release
|
- name: Upload esp32solo zip to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||||
asset_path: .pio/build/esp32s2/firmware.bin
|
asset_path: esp32solo.zip
|
||||||
asset_name: ams2mqtt-esp32s2-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp32solo-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/zip
|
||||||
|
|||||||
5
.gitignore
vendored
@@ -7,7 +7,7 @@
|
|||||||
.vscode
|
.vscode
|
||||||
.pio
|
.pio
|
||||||
platformio-user.ini
|
platformio-user.ini
|
||||||
/src/version.h
|
/lib/AmsConfiguration/include/version.h
|
||||||
/src/web/root
|
/src/web/root
|
||||||
/src/AmsToMqttBridge.ino.cpp
|
/src/AmsToMqttBridge.ino.cpp
|
||||||
/test
|
/test
|
||||||
@@ -15,3 +15,6 @@ platformio-user.ini
|
|||||||
/sdkconfig
|
/sdkconfig
|
||||||
/.tmp
|
/.tmp
|
||||||
/*.zip
|
/*.zip
|
||||||
|
node_modules
|
||||||
|
/gui/dist
|
||||||
|
/scripts/*dev
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# AMS MQTT Bridge
|
# AMS Reader
|
||||||
This code is designed to decode data from electric smart meters installed in many countries in Europe these days. The data is presented in a graphical web interface and can also send the data to a MQTT broker which makes it suitable for home automation project. Originally it was only designed to work with Norwegian meters, but has since been adapter to read any IEC-62056-7-5 or IEC-62056-21 compliant meters.
|
This code is designed to decode data from electric smart meters installed in many countries in Europe these days. The data is presented in a graphical web interface and can also send the data to a MQTT broker which makes it suitable for home automation project. Originally it was only designed to work with Norwegian meters, but has since been adapter to read any IEC-62056-7-5 or IEC-62056-21 compliant meters.
|
||||||
|
|
||||||
Later development have added Energy usage graph for both day and month, as well as future energy price (Prices only available for ESP32). The code can run on any ESP8266 or ESP32 hardware which you can read more about in the [WiKi](https://github.com/gskjold/AmsToMqttBridge/wiki). If you don't have the knowledge to set up a ESP device yourself, have a look at the shop at [amsleser.no](https://amsleser.no/).
|
Later development have added Energy usage graph for both day and month, as well as future energy price. The code can run on any ESP8266 or ESP32 hardware which you can read more about in the [WiKi](https://github.com/UtilitechAS/amsreader-firmware/wiki). If you don't have the knowledge to set up a ESP device yourself, have a look at the shop at [amsleser.no](https://amsleser.no/).
|
||||||
|
|
||||||
|
|
||||||
<img src="webui.png">
|
<img src="images/dashboard.png">
|
||||||
|
|
||||||
Go to the [WiKi](https://github.com/gskjold/AmsToMqttBridge/wiki) for information on how to get your own device! And find the latest prebuilt firmware file at the [release section](https://github.com/gskjold/AmsToMqttBridge/releases).
|
Go to the [WiKi](https://github.com/UtilitechAS/amsreader-firmware/wiki) for information on how to get your own device! And find the latest prebuilt firmware file at the [release section](https://github.com/UtilitechAS/amsreader-firmware/releases).
|
||||||
|
|
||||||
## Building this project with PlatformIO
|
## Building this project with PlatformIO
|
||||||
To build this project, you need [PlatformIO](https://platformio.org/) installed.
|
To build this project, you need [PlatformIO](https://platformio.org/) installed.
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
[See Hardware page in Wiki](https://github.com/gskjold/AmsToMqttBridge/wiki)
|
[See Hardware page in Wiki](https://github.com/UtilitechAS/amsreader-firmware/wiki)
|
||||||
|
|||||||
76
hardware/v1/kicad/HAN_ESP_TSS721.kicad_prl
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"active_layer_preset": "",
|
||||||
|
"auto_track_width": true,
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"pads": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 0.6
|
||||||
|
},
|
||||||
|
"ratsnest_display_mode": 0,
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": true,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"visible_layers": "fffffff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "HAN_ESP_TSS721.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
}
|
||||||
440
hardware/v1/kicad/HAN_ESP_TSS721.kicad_pro
Normal file
@@ -0,0 +1,440 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.15,
|
||||||
|
"copper_line_width": 0.19999999999999998,
|
||||||
|
"copper_text_italic": false,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"copper_text_thickness": 0.3,
|
||||||
|
"copper_text_upright": false,
|
||||||
|
"courtyard_line_width": 0.049999999999999996,
|
||||||
|
"dimension_precision": 4,
|
||||||
|
"dimension_units": 3,
|
||||||
|
"dimensions": {
|
||||||
|
"arrow_length": 1270000,
|
||||||
|
"extension_offset": 500000,
|
||||||
|
"keep_text_aligned": true,
|
||||||
|
"suppress_zeroes": false,
|
||||||
|
"text_position": 0,
|
||||||
|
"units_format": 1
|
||||||
|
},
|
||||||
|
"fab_line_width": 0.09999999999999999,
|
||||||
|
"fab_text_italic": false,
|
||||||
|
"fab_text_size_h": 1.0,
|
||||||
|
"fab_text_size_v": 1.0,
|
||||||
|
"fab_text_thickness": 0.15,
|
||||||
|
"fab_text_upright": false,
|
||||||
|
"other_line_width": 0.09999999999999999,
|
||||||
|
"other_text_italic": false,
|
||||||
|
"other_text_size_h": 1.0,
|
||||||
|
"other_text_size_v": 1.0,
|
||||||
|
"other_text_thickness": 0.15,
|
||||||
|
"other_text_upright": false,
|
||||||
|
"pads": {
|
||||||
|
"drill": 0.762,
|
||||||
|
"height": 1.524,
|
||||||
|
"width": 1.524
|
||||||
|
},
|
||||||
|
"silk_line_width": 0.15,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.15,
|
||||||
|
"silk_text_upright": false,
|
||||||
|
"zones": {
|
||||||
|
"45_degree_only": true,
|
||||||
|
"min_clearance": 0.508
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"filename": "board_design_settings.json",
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"rule_severities": {
|
||||||
|
"annular_width": "error",
|
||||||
|
"clearance": "error",
|
||||||
|
"copper_edge_clearance": "error",
|
||||||
|
"courtyards_overlap": "error",
|
||||||
|
"diff_pair_gap_out_of_range": "error",
|
||||||
|
"diff_pair_uncoupled_length_too_long": "error",
|
||||||
|
"drill_out_of_range": "error",
|
||||||
|
"duplicate_footprints": "warning",
|
||||||
|
"extra_footprint": "warning",
|
||||||
|
"footprint_type_mismatch": "error",
|
||||||
|
"hole_clearance": "error",
|
||||||
|
"hole_near_hole": "error",
|
||||||
|
"invalid_outline": "error",
|
||||||
|
"item_on_disabled_layer": "error",
|
||||||
|
"items_not_allowed": "error",
|
||||||
|
"length_out_of_range": "error",
|
||||||
|
"malformed_courtyard": "error",
|
||||||
|
"microvia_drill_out_of_range": "error",
|
||||||
|
"missing_courtyard": "ignore",
|
||||||
|
"missing_footprint": "warning",
|
||||||
|
"net_conflict": "warning",
|
||||||
|
"npth_inside_courtyard": "ignore",
|
||||||
|
"padstack": "error",
|
||||||
|
"pth_inside_courtyard": "ignore",
|
||||||
|
"shorting_items": "error",
|
||||||
|
"silk_over_copper": "warning",
|
||||||
|
"silk_overlap": "warning",
|
||||||
|
"skew_out_of_range": "error",
|
||||||
|
"through_hole_pad_without_hole": "error",
|
||||||
|
"too_many_vias": "error",
|
||||||
|
"track_dangling": "warning",
|
||||||
|
"track_width": "error",
|
||||||
|
"tracks_crossing": "error",
|
||||||
|
"unconnected_items": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"via_dangling": "warning",
|
||||||
|
"zone_has_empty_net": "error",
|
||||||
|
"zones_intersect": "error"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"allow_blind_buried_vias": false,
|
||||||
|
"allow_microvias": false,
|
||||||
|
"max_error": 0.005,
|
||||||
|
"min_clearance": 0.0,
|
||||||
|
"min_copper_edge_clearance": 0.075,
|
||||||
|
"min_hole_clearance": 0.25,
|
||||||
|
"min_hole_to_hole": 0.25,
|
||||||
|
"min_microvia_diameter": 0.19999999999999998,
|
||||||
|
"min_microvia_drill": 0.09999999999999999,
|
||||||
|
"min_silk_clearance": 0.0,
|
||||||
|
"min_through_hole_diameter": 0.3,
|
||||||
|
"min_track_width": 0.19999999999999998,
|
||||||
|
"min_via_annular_width": 0.049999999999999996,
|
||||||
|
"min_via_diameter": 0.39999999999999997,
|
||||||
|
"use_height_for_length_calcs": true
|
||||||
|
},
|
||||||
|
"track_widths": [
|
||||||
|
0.0,
|
||||||
|
0.2,
|
||||||
|
0.4,
|
||||||
|
0.6,
|
||||||
|
1.0
|
||||||
|
],
|
||||||
|
"via_dimensions": [],
|
||||||
|
"zones_allow_external_fillets": false,
|
||||||
|
"zones_use_no_outline": true
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"pin_map": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rule_severities": {
|
||||||
|
"bus_definition_conflict": "error",
|
||||||
|
"bus_entry_needed": "error",
|
||||||
|
"bus_label_syntax": "error",
|
||||||
|
"bus_to_bus_conflict": "error",
|
||||||
|
"bus_to_net_conflict": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"extra_units": "error",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"lib_symbol_issues": "warning",
|
||||||
|
"multiple_net_names": "warning",
|
||||||
|
"net_not_bus_member": "warning",
|
||||||
|
"no_connect_connected": "warning",
|
||||||
|
"no_connect_dangling": "warning",
|
||||||
|
"pin_not_connected": "error",
|
||||||
|
"pin_not_driven": "error",
|
||||||
|
"pin_to_pin": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "HAN_ESP_TSS721.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12.0,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.25,
|
||||||
|
"via_diameter": 0.6,
|
||||||
|
"via_drill": 0.4,
|
||||||
|
"wire_width": 6.0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"bus_width": 12.0,
|
||||||
|
"clearance": 0.5,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.5,
|
||||||
|
"microvia_drill": 0.2,
|
||||||
|
"name": "PWR",
|
||||||
|
"nets": [
|
||||||
|
"+3V3"
|
||||||
|
],
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.5,
|
||||||
|
"via_diameter": 0.8,
|
||||||
|
"via_drill": 0.6,
|
||||||
|
"wire_width": 6.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"net_colors": null
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"drawing": {
|
||||||
|
"default_line_thickness": 6.0,
|
||||||
|
"default_text_size": 50.0,
|
||||||
|
"field_names": [],
|
||||||
|
"intersheets_ref_own_page": false,
|
||||||
|
"intersheets_ref_prefix": "",
|
||||||
|
"intersheets_ref_short": false,
|
||||||
|
"intersheets_ref_show": false,
|
||||||
|
"intersheets_ref_suffix": "",
|
||||||
|
"junction_size_choice": 3,
|
||||||
|
"label_size_ratio": 0.25,
|
||||||
|
"pin_symbol_size": 0.0,
|
||||||
|
"text_offset_ratio": 0.08
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "",
|
||||||
|
"ngspice": {
|
||||||
|
"fix_include_paths": true,
|
||||||
|
"fix_passive_vals": false,
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"model_mode": 0,
|
||||||
|
"workbook_filename": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"spice_adjust_passive_values": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
1
hardware/v1/kicad/fp-info-cache
Normal file
@@ -0,0 +1 @@
|
|||||||
|
0
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
EESchema-DOCLIB Version 2.0
|
||||||
|
#
|
||||||
|
#End Doc Library
|
||||||
@@ -1,6 +1,21 @@
|
|||||||
EESchema-LIBRARY Version 2.4
|
EESchema-LIBRARY Version 2.4
|
||||||
#encoding utf-8
|
#encoding utf-8
|
||||||
#
|
#
|
||||||
|
# +3.3V-power
|
||||||
|
#
|
||||||
|
DEF +3.3V-power #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -150 50 H I C CNN
|
||||||
|
F1 "+3.3V-power" 0 140 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 0 -30 50 0 100 N
|
||||||
|
P 2 0 1 0 0 0 0 100 N
|
||||||
|
P 2 0 1 0 0 100 30 50 N
|
||||||
|
X +3V3 1 0 0 0 U 50 50 1 1 W N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
# CONN_01X08
|
# CONN_01X08
|
||||||
#
|
#
|
||||||
DEF CONN_01X08 P 0 40 Y N 1 F N
|
DEF CONN_01X08 P 0 40 Y N 1 F N
|
||||||
@@ -35,4 +50,23 @@ X P8 8 -200 -350 150 R 50 50 1 1 P
|
|||||||
ENDDRAW
|
ENDDRAW
|
||||||
ENDDEF
|
ENDDEF
|
||||||
#
|
#
|
||||||
|
# Jumper-Device
|
||||||
|
#
|
||||||
|
DEF Jumper-Device JP 0 30 Y N 1 F N
|
||||||
|
F0 "JP" 0 150 50 H V C CNN
|
||||||
|
F1 "Jumper-Device" 0 -80 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
SolderJumper*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
C -100 0 35 0 1 0 N
|
||||||
|
A 0 -26 125 375 1422 0 1 0 N 99 50 -98 50
|
||||||
|
C 100 0 35 0 1 0 N
|
||||||
|
X 1 1 -300 0 165 R 50 50 0 1 P
|
||||||
|
X 2 2 300 0 165 L 50 50 0 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
#End Library
|
#End Library
|
||||||
|
|||||||
75
hardware/wemos_mbus_shield/kicad/d1_mini_shield.kicad_prl
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"active_layer": 0,
|
||||||
|
"active_layer_preset": "",
|
||||||
|
"auto_track_width": true,
|
||||||
|
"hidden_nets": [],
|
||||||
|
"high_contrast_mode": 0,
|
||||||
|
"net_color_mode": 1,
|
||||||
|
"opacity": {
|
||||||
|
"pads": 1.0,
|
||||||
|
"tracks": 1.0,
|
||||||
|
"vias": 1.0,
|
||||||
|
"zones": 0.6
|
||||||
|
},
|
||||||
|
"ratsnest_display_mode": 0,
|
||||||
|
"selection_filter": {
|
||||||
|
"dimensions": true,
|
||||||
|
"footprints": true,
|
||||||
|
"graphics": true,
|
||||||
|
"keepouts": true,
|
||||||
|
"lockedItems": true,
|
||||||
|
"otherItems": true,
|
||||||
|
"pads": true,
|
||||||
|
"text": true,
|
||||||
|
"tracks": true,
|
||||||
|
"vias": true,
|
||||||
|
"zones": true
|
||||||
|
},
|
||||||
|
"visible_items": [
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4,
|
||||||
|
5,
|
||||||
|
8,
|
||||||
|
9,
|
||||||
|
10,
|
||||||
|
11,
|
||||||
|
12,
|
||||||
|
13,
|
||||||
|
14,
|
||||||
|
15,
|
||||||
|
16,
|
||||||
|
17,
|
||||||
|
18,
|
||||||
|
19,
|
||||||
|
20,
|
||||||
|
21,
|
||||||
|
22,
|
||||||
|
23,
|
||||||
|
24,
|
||||||
|
25,
|
||||||
|
26,
|
||||||
|
27,
|
||||||
|
28,
|
||||||
|
29,
|
||||||
|
30,
|
||||||
|
32,
|
||||||
|
33,
|
||||||
|
34,
|
||||||
|
35,
|
||||||
|
36
|
||||||
|
],
|
||||||
|
"visible_layers": "fffffff_ffffffff",
|
||||||
|
"zone_display_mode": 0
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "d1_mini_shield.kicad_prl",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"project": {
|
||||||
|
"files": []
|
||||||
|
}
|
||||||
|
}
|
||||||
356
hardware/wemos_mbus_shield/kicad/d1_mini_shield.kicad_pro
Normal file
@@ -0,0 +1,356 @@
|
|||||||
|
{
|
||||||
|
"board": {
|
||||||
|
"design_settings": {
|
||||||
|
"defaults": {
|
||||||
|
"board_outline_line_width": 0.15,
|
||||||
|
"copper_line_width": 0.2,
|
||||||
|
"copper_text_italic": false,
|
||||||
|
"copper_text_size_h": 1.5,
|
||||||
|
"copper_text_size_v": 1.5,
|
||||||
|
"copper_text_thickness": 0.3,
|
||||||
|
"copper_text_upright": true,
|
||||||
|
"courtyard_line_width": 0.05,
|
||||||
|
"other_line_width": 0.15,
|
||||||
|
"other_text_italic": false,
|
||||||
|
"other_text_size_h": 1.0,
|
||||||
|
"other_text_size_v": 1.0,
|
||||||
|
"other_text_thickness": 0.15,
|
||||||
|
"other_text_upright": true,
|
||||||
|
"silk_line_width": 0.15,
|
||||||
|
"silk_text_italic": false,
|
||||||
|
"silk_text_size_h": 1.0,
|
||||||
|
"silk_text_size_v": 1.0,
|
||||||
|
"silk_text_thickness": 0.15,
|
||||||
|
"silk_text_upright": true
|
||||||
|
},
|
||||||
|
"diff_pair_dimensions": [
|
||||||
|
{
|
||||||
|
"gap": 0.25,
|
||||||
|
"via_gap": 0.25,
|
||||||
|
"width": 0.2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"drc_exclusions": [],
|
||||||
|
"rule_severitieslegacy_courtyards_overlap": true,
|
||||||
|
"rule_severitieslegacy_no_courtyard_defined": false,
|
||||||
|
"rules": {
|
||||||
|
"allow_blind_buried_vias": false,
|
||||||
|
"allow_microvias": false,
|
||||||
|
"min_hole_to_hole": 0.25,
|
||||||
|
"min_microvia_diameter": 0.2,
|
||||||
|
"min_microvia_drill": 0.09999999999999999,
|
||||||
|
"min_through_hole_diameter": 0.3,
|
||||||
|
"min_track_width": 0.2,
|
||||||
|
"min_via_diameter": 0.4,
|
||||||
|
"solder_mask_clearance": 0.2,
|
||||||
|
"solder_mask_min_width": 0.0,
|
||||||
|
"solder_paste_clearance": 0.0,
|
||||||
|
"solder_paste_margin_ratio": -0.0
|
||||||
|
},
|
||||||
|
"track_widths": [
|
||||||
|
0.25,
|
||||||
|
0.5
|
||||||
|
],
|
||||||
|
"via_dimensions": [
|
||||||
|
{
|
||||||
|
"diameter": 0.6,
|
||||||
|
"drill": 0.4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"layer_presets": []
|
||||||
|
},
|
||||||
|
"boards": [],
|
||||||
|
"cvpcb": {
|
||||||
|
"equivalence_files": []
|
||||||
|
},
|
||||||
|
"erc": {
|
||||||
|
"erc_exclusions": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"pin_map": [
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
2
|
||||||
|
],
|
||||||
|
[
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2,
|
||||||
|
2
|
||||||
|
]
|
||||||
|
],
|
||||||
|
"rule_severities": {
|
||||||
|
"bus_definition_conflict": "error",
|
||||||
|
"bus_entry_needed": "error",
|
||||||
|
"bus_label_syntax": "error",
|
||||||
|
"bus_to_bus_conflict": "error",
|
||||||
|
"bus_to_net_conflict": "error",
|
||||||
|
"different_unit_footprint": "error",
|
||||||
|
"different_unit_net": "error",
|
||||||
|
"duplicate_reference": "error",
|
||||||
|
"duplicate_sheet_names": "error",
|
||||||
|
"extra_units": "error",
|
||||||
|
"global_label_dangling": "warning",
|
||||||
|
"hier_label_mismatch": "error",
|
||||||
|
"label_dangling": "error",
|
||||||
|
"lib_symbol_issues": "warning",
|
||||||
|
"multiple_net_names": "warning",
|
||||||
|
"net_not_bus_member": "warning",
|
||||||
|
"no_connect_connected": "warning",
|
||||||
|
"no_connect_dangling": "warning",
|
||||||
|
"pin_not_connected": "error",
|
||||||
|
"pin_not_driven": "error",
|
||||||
|
"pin_to_pin": "warning",
|
||||||
|
"power_pin_not_driven": "error",
|
||||||
|
"similar_labels": "warning",
|
||||||
|
"unannotated": "error",
|
||||||
|
"unit_value_mismatch": "error",
|
||||||
|
"unresolved_variable": "error",
|
||||||
|
"wire_dangling": "error"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"libraries": {
|
||||||
|
"pinned_footprint_libs": [],
|
||||||
|
"pinned_symbol_libs": []
|
||||||
|
},
|
||||||
|
"meta": {
|
||||||
|
"filename": "d1_mini_shield.kicad_pro",
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_settings": {
|
||||||
|
"classes": [
|
||||||
|
{
|
||||||
|
"bus_width": 12.0,
|
||||||
|
"clearance": 0.2,
|
||||||
|
"diff_pair_gap": 0.25,
|
||||||
|
"diff_pair_via_gap": 0.25,
|
||||||
|
"diff_pair_width": 0.2,
|
||||||
|
"line_style": 0,
|
||||||
|
"microvia_diameter": 0.3,
|
||||||
|
"microvia_drill": 0.1,
|
||||||
|
"name": "Default",
|
||||||
|
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||||
|
"track_width": 0.25,
|
||||||
|
"via_diameter": 0.8,
|
||||||
|
"via_drill": 0.4,
|
||||||
|
"wire_width": 6.0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"meta": {
|
||||||
|
"version": 2
|
||||||
|
},
|
||||||
|
"net_colors": null
|
||||||
|
},
|
||||||
|
"pcbnew": {
|
||||||
|
"last_paths": {
|
||||||
|
"gencad": "",
|
||||||
|
"idf": "",
|
||||||
|
"netlist": "d1_mini_shield.net",
|
||||||
|
"specctra_dsn": "",
|
||||||
|
"step": "",
|
||||||
|
"vrml": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": ""
|
||||||
|
},
|
||||||
|
"schematic": {
|
||||||
|
"annotate_start_num": 0,
|
||||||
|
"drawing": {
|
||||||
|
"default_line_thickness": 6.0,
|
||||||
|
"default_text_size": 50.0,
|
||||||
|
"field_names": [],
|
||||||
|
"intersheets_ref_own_page": false,
|
||||||
|
"intersheets_ref_prefix": "",
|
||||||
|
"intersheets_ref_short": false,
|
||||||
|
"intersheets_ref_show": false,
|
||||||
|
"intersheets_ref_suffix": "",
|
||||||
|
"junction_size_choice": 3,
|
||||||
|
"label_size_ratio": 0.25,
|
||||||
|
"pin_symbol_size": 0.0,
|
||||||
|
"text_offset_ratio": 0.08
|
||||||
|
},
|
||||||
|
"legacy_lib_dir": "",
|
||||||
|
"legacy_lib_list": [],
|
||||||
|
"meta": {
|
||||||
|
"version": 1
|
||||||
|
},
|
||||||
|
"net_format_name": "Pcbnew",
|
||||||
|
"ngspice": {
|
||||||
|
"fix_include_paths": true,
|
||||||
|
"fix_passive_vals": false,
|
||||||
|
"meta": {
|
||||||
|
"version": 0
|
||||||
|
},
|
||||||
|
"model_mode": 0,
|
||||||
|
"workbook_filename": ""
|
||||||
|
},
|
||||||
|
"page_layout_descr_file": "",
|
||||||
|
"plot_directory": "",
|
||||||
|
"spice_adjust_passive_values": false,
|
||||||
|
"spice_external_command": "spice \"%I\"",
|
||||||
|
"subpart_first_id": 65,
|
||||||
|
"subpart_id_separator": 0
|
||||||
|
},
|
||||||
|
"sheets": [],
|
||||||
|
"text_variables": {}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 136 KiB After Width: | Height: | Size: 173 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 32 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 33 KiB |
|
Before Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 32 KiB |
@@ -4,12 +4,14 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
#define EEPROM_SIZE 1024*3
|
#define EEPROM_SIZE 1024*3
|
||||||
#define EEPROM_CHECK_SUM 95 // Used to check if config is stored. Change if structure changes
|
#define EEPROM_CHECK_SUM 101 // Used to check if config is stored. Change if structure changes
|
||||||
|
#define EEPROM_CLEARED_INDICATOR 0xFC
|
||||||
#define EEPROM_CONFIG_ADDRESS 0
|
#define EEPROM_CONFIG_ADDRESS 0
|
||||||
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
|
#define EEPROM_TEMP_CONFIG_ADDRESS 2048
|
||||||
|
|
||||||
#define CONFIG_SYSTEM_START 8
|
#define CONFIG_SYSTEM_START 8
|
||||||
#define CONFIG_METER_START 32
|
#define CONFIG_METER_START 32
|
||||||
|
#define CONFIG_UI_START 248
|
||||||
#define CONFIG_GPIO_START 266
|
#define CONFIG_GPIO_START 266
|
||||||
#define CONFIG_ENTSOE_START 290
|
#define CONFIG_ENTSOE_START 290
|
||||||
#define CONFIG_WIFI_START 360
|
#define CONFIG_WIFI_START 360
|
||||||
@@ -29,7 +31,11 @@
|
|||||||
|
|
||||||
struct SystemConfig {
|
struct SystemConfig {
|
||||||
uint8_t boardType;
|
uint8_t boardType;
|
||||||
}; // 1
|
bool vendorConfigured;
|
||||||
|
bool userConfigured;
|
||||||
|
uint8_t dataCollectionConsent; // 0 = unknown, 1 = accepted, 2 = declined
|
||||||
|
char country[3];
|
||||||
|
}; // 7
|
||||||
|
|
||||||
struct WiFiConfig91 {
|
struct WiFiConfig91 {
|
||||||
char ssid[32];
|
char ssid[32];
|
||||||
@@ -54,7 +60,10 @@ struct WiFiConfig {
|
|||||||
char hostname[32];
|
char hostname[32];
|
||||||
bool mdns;
|
bool mdns;
|
||||||
uint8_t power;
|
uint8_t power;
|
||||||
}; // 210
|
uint8_t sleep;
|
||||||
|
uint8_t mode;
|
||||||
|
bool autoreboot;
|
||||||
|
}; // 213
|
||||||
|
|
||||||
struct MqttConfig86 {
|
struct MqttConfig86 {
|
||||||
char host[128];
|
char host[128];
|
||||||
@@ -87,6 +96,40 @@ struct WebConfig {
|
|||||||
}; // 129
|
}; // 129
|
||||||
|
|
||||||
struct MeterConfig {
|
struct MeterConfig {
|
||||||
|
uint32_t baud;
|
||||||
|
uint8_t parity;
|
||||||
|
bool invert;
|
||||||
|
uint8_t distributionSystem;
|
||||||
|
uint16_t mainFuse;
|
||||||
|
uint16_t productionCapacity;
|
||||||
|
uint8_t encryptionKey[16];
|
||||||
|
uint8_t authenticationKey[16];
|
||||||
|
uint32_t wattageMultiplier;
|
||||||
|
uint32_t voltageMultiplier;
|
||||||
|
uint32_t amperageMultiplier;
|
||||||
|
uint32_t accumulatedMultiplier;
|
||||||
|
uint8_t source;
|
||||||
|
uint8_t parser;
|
||||||
|
}; // 52
|
||||||
|
|
||||||
|
struct MeterConfig100 {
|
||||||
|
uint32_t baud;
|
||||||
|
uint8_t parity;
|
||||||
|
bool invert;
|
||||||
|
uint8_t distributionSystem;
|
||||||
|
uint8_t mainFuse;
|
||||||
|
uint8_t productionCapacity;
|
||||||
|
uint8_t encryptionKey[16];
|
||||||
|
uint8_t authenticationKey[16];
|
||||||
|
uint32_t wattageMultiplier;
|
||||||
|
uint32_t voltageMultiplier;
|
||||||
|
uint32_t amperageMultiplier;
|
||||||
|
uint32_t accumulatedMultiplier;
|
||||||
|
uint8_t source;
|
||||||
|
uint8_t parser;
|
||||||
|
}; // 50
|
||||||
|
|
||||||
|
struct MeterConfig95 {
|
||||||
uint32_t baud;
|
uint32_t baud;
|
||||||
uint8_t parity;
|
uint8_t parity;
|
||||||
bool invert;
|
bool invert;
|
||||||
@@ -147,6 +190,13 @@ struct DomoticzConfig {
|
|||||||
}; // 10
|
}; // 10
|
||||||
|
|
||||||
struct NtpConfig {
|
struct NtpConfig {
|
||||||
|
bool enable;
|
||||||
|
bool dhcp;
|
||||||
|
char server[64];
|
||||||
|
char timezone[32];
|
||||||
|
}; // 98
|
||||||
|
|
||||||
|
struct NtpConfig96 {
|
||||||
bool enable;
|
bool enable;
|
||||||
bool dhcp;
|
bool dhcp;
|
||||||
int16_t offset;
|
int16_t offset;
|
||||||
@@ -159,6 +209,7 @@ struct EntsoeConfig {
|
|||||||
char area[17];
|
char area[17];
|
||||||
char currency[4];
|
char currency[4];
|
||||||
uint32_t multiplier;
|
uint32_t multiplier;
|
||||||
|
bool enabled;
|
||||||
}; // 62
|
}; // 62
|
||||||
|
|
||||||
struct EnergyAccountingConfig {
|
struct EnergyAccountingConfig {
|
||||||
@@ -166,6 +217,20 @@ struct EnergyAccountingConfig {
|
|||||||
uint8_t hours;
|
uint8_t hours;
|
||||||
}; // 11
|
}; // 11
|
||||||
|
|
||||||
|
struct UiConfig {
|
||||||
|
uint8_t showImport;
|
||||||
|
uint8_t showExport;
|
||||||
|
uint8_t showVoltage;
|
||||||
|
uint8_t showAmperage;
|
||||||
|
uint8_t showReactive;
|
||||||
|
uint8_t showRealtime;
|
||||||
|
uint8_t showPeaks;
|
||||||
|
uint8_t showPricePlot;
|
||||||
|
uint8_t showDayPlot;
|
||||||
|
uint8_t showMonthPlot;
|
||||||
|
uint8_t showTemperaturePlot;
|
||||||
|
}; // 11
|
||||||
|
|
||||||
struct TempSensorConfig {
|
struct TempSensorConfig {
|
||||||
uint8_t address[8];
|
uint8_t address[8];
|
||||||
char name[16];
|
char name[16];
|
||||||
@@ -242,6 +307,10 @@ public:
|
|||||||
bool isEnergyAccountingChanged();
|
bool isEnergyAccountingChanged();
|
||||||
void ackEnergyAccountingChange();
|
void ackEnergyAccountingChange();
|
||||||
|
|
||||||
|
bool getUiConfig(UiConfig&);
|
||||||
|
bool setUiConfig(UiConfig&);
|
||||||
|
void clearUiConfig(UiConfig&);
|
||||||
|
|
||||||
void loadTempSensors();
|
void loadTempSensors();
|
||||||
void saveTempSensors();
|
void saveTempSensors();
|
||||||
uint8_t getTempSensorCount();
|
uint8_t getTempSensorCount();
|
||||||
@@ -262,13 +331,14 @@ private:
|
|||||||
uint8_t tempSensorCount = 0;
|
uint8_t tempSensorCount = 0;
|
||||||
TempSensorConfig** tempSensors = NULL;
|
TempSensorConfig** tempSensors = NULL;
|
||||||
|
|
||||||
bool relocateConfig86(); // 1.5.0
|
|
||||||
bool relocateConfig87(); // 1.5.4
|
|
||||||
bool relocateConfig90(); // 2.0.0
|
bool relocateConfig90(); // 2.0.0
|
||||||
bool relocateConfig91(); // 2.0.2
|
bool relocateConfig91(); // 2.0.2
|
||||||
bool relocateConfig92(); // 2.0.3
|
bool relocateConfig92(); // 2.0.3
|
||||||
bool relocateConfig93(); // 2.1.0
|
bool relocateConfig93(); // 2.1.0
|
||||||
bool relocateConfig94(); // 2.1.4
|
bool relocateConfig94(); // 2.1.0
|
||||||
|
bool relocateConfig95(); // 2.1.4
|
||||||
|
bool relocateConfig96(); // 2.1.14
|
||||||
|
bool relocateConfig100(); // 2.2-dev
|
||||||
|
|
||||||
void saveToFs();
|
void saveToFs();
|
||||||
bool loadFromFs(uint8_t version);
|
bool loadFromFs(uint8_t version);
|
||||||
86
lib/AmsConfiguration/include/Timezones.h
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
#include <Timezone.h>
|
||||||
|
|
||||||
|
#define JULY1970 15634800
|
||||||
|
|
||||||
|
TimeChangeRule TC_GMT = {"GMT", Last, Sun, Jan, 0, 0};
|
||||||
|
TimeChangeRule TC_WET = {"WET", Last, Sun, Oct, 2, 0};
|
||||||
|
TimeChangeRule TC_WEST = {"WEST", Last, Sun, Mar, 1, 60};
|
||||||
|
TimeChangeRule TC_CET = {"CET", Last, Sun, Oct, 3, 60};
|
||||||
|
TimeChangeRule TC_CEST = {"CEST", Last, Sun, Mar, 2, 120};
|
||||||
|
TimeChangeRule TC_EET = {"EET", Last, Sun, Oct, 4, 120};
|
||||||
|
TimeChangeRule TC_EEST = {"EEST", Last, Sun, Mar, 3, 180};
|
||||||
|
|
||||||
|
Timezone GMT = Timezone(TC_GMT);
|
||||||
|
Timezone WesterEuropean = Timezone(TC_WET, TC_WEST);
|
||||||
|
Timezone CentralEuropean = Timezone(TC_CET, TC_CEST);
|
||||||
|
Timezone EasternEuropean = Timezone(TC_EET, TC_EEST);
|
||||||
|
|
||||||
|
Timezone* resolveTimezone(char* name) {
|
||||||
|
if(strncmp_P(name, PSTR("Europe/"), 7) == 0) {
|
||||||
|
if(strncmp_P(name+7, PSTR("Amsterdam"), 9) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Athens"), 6) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Belfast"), 7) == 0)
|
||||||
|
return &WesterEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Berlin"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Bratislava"), 10) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Brussels"), 8) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Bucharest"), 9) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Budapest"), 8) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Copenhagen"), 10) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Dublin"), 6) == 0)
|
||||||
|
return &WesterEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Helsinki"), 8) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Lisbon"), 6) == 0)
|
||||||
|
return &WesterEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Ljubljana"), 9) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("London"), 6) == 0)
|
||||||
|
return &WesterEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Luxembourg"), 10) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Madrid"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Malta"), 5) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Nicosia"), 7) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Oslo"), 4) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Paris"), 5) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Podgorica"), 9) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Prague"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Riga"), 4) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Rome"), 4) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Sofia"), 5) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Stockholm"), 9) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Tallinn"), 7) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Vienna"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Vilnius"), 7) == 0)
|
||||||
|
return &EasternEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Warsaw"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Zagreb"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
if(strncmp_P(name+7, PSTR("Zurich"), 6) == 0)
|
||||||
|
return &CentralEuropean;
|
||||||
|
}
|
||||||
|
return &GMT;
|
||||||
|
}
|
||||||
@@ -7,5 +7,6 @@
|
|||||||
String toHex(uint8_t* in);
|
String toHex(uint8_t* in);
|
||||||
String toHex(uint8_t* in, uint16_t size);
|
String toHex(uint8_t* in, uint16_t size);
|
||||||
void fromHex(uint8_t *out, String in, uint16_t size);
|
void fromHex(uint8_t *out, String in, uint16_t size);
|
||||||
|
void stripNonAscii(uint8_t* in, uint16_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,18 +1,26 @@
|
|||||||
#include "AmsConfiguration.h"
|
#include "AmsConfiguration.h"
|
||||||
|
#include "hexutils.h"
|
||||||
|
|
||||||
bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
bool AmsConfiguration::getSystemConfig(SystemConfig& config) {
|
||||||
if(hasConfig()) {
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
uint8_t configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||||
|
if(configVersion == EEPROM_CHECK_SUM || configVersion == EEPROM_CLEARED_INDICATOR) {
|
||||||
EEPROM.get(CONFIG_SYSTEM_START, config);
|
EEPROM.get(CONFIG_SYSTEM_START, config);
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
config.boardType = 0xFF;
|
||||||
|
config.vendorConfigured = false;
|
||||||
|
config.userConfigured = false;
|
||||||
|
config.dataCollectionConsent = 0;
|
||||||
|
strcpy(config.country, "");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
bool AmsConfiguration::setSystemConfig(SystemConfig& config) {
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
stripNonAscii((uint8_t*) config.country, 2);
|
||||||
EEPROM.put(CONFIG_SYSTEM_START, config);
|
EEPROM.put(CONFIG_SYSTEM_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
@@ -24,6 +32,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
|
|||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.get(CONFIG_WIFI_START, config);
|
EEPROM.get(CONFIG_WIFI_START, config);
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
|
if(config.sleep > 2) config.sleep = 1;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
clearWifi(config);
|
clearWifi(config);
|
||||||
@@ -33,6 +42,7 @@ bool AmsConfiguration::getWiFiConfig(WiFiConfig& config) {
|
|||||||
|
|
||||||
bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
|
bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
|
||||||
WiFiConfig existing;
|
WiFiConfig existing;
|
||||||
|
if(config.sleep > 2) config.sleep = 1;
|
||||||
if(getWiFiConfig(existing)) {
|
if(getWiFiConfig(existing)) {
|
||||||
wifiChanged |= strcmp(config.ssid, existing.ssid) != 0;
|
wifiChanged |= strcmp(config.ssid, existing.ssid) != 0;
|
||||||
wifiChanged |= strcmp(config.psk, existing.psk) != 0;
|
wifiChanged |= strcmp(config.psk, existing.psk) != 0;
|
||||||
@@ -45,9 +55,22 @@ bool AmsConfiguration::setWiFiConfig(WiFiConfig& config) {
|
|||||||
}
|
}
|
||||||
wifiChanged |= strcmp(config.hostname, existing.hostname) != 0;
|
wifiChanged |= strcmp(config.hostname, existing.hostname) != 0;
|
||||||
wifiChanged |= config.power != existing.power;
|
wifiChanged |= config.power != existing.power;
|
||||||
|
wifiChanged |= config.sleep != existing.sleep;
|
||||||
|
wifiChanged |= config.mode != existing.mode;
|
||||||
|
wifiChanged |= config.autoreboot != existing.autoreboot;
|
||||||
} else {
|
} else {
|
||||||
wifiChanged = true;
|
wifiChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stripNonAscii((uint8_t*) config.ssid, 32);
|
||||||
|
stripNonAscii((uint8_t*) config.psk, 64);
|
||||||
|
stripNonAscii((uint8_t*) config.ip, 16);
|
||||||
|
stripNonAscii((uint8_t*) config.gateway, 16);
|
||||||
|
stripNonAscii((uint8_t*) config.subnet, 16);
|
||||||
|
stripNonAscii((uint8_t*) config.dns1, 16);
|
||||||
|
stripNonAscii((uint8_t*) config.dns2, 16);
|
||||||
|
stripNonAscii((uint8_t*) config.hostname, 32);
|
||||||
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_WIFI_START, config);
|
EEPROM.put(CONFIG_WIFI_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -70,6 +93,7 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) {
|
|||||||
#endif
|
#endif
|
||||||
strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str());
|
strcpy(config.hostname, (String("ams-") + String(chipId, HEX)).c_str());
|
||||||
config.mdns = true;
|
config.mdns = true;
|
||||||
|
config.sleep = 0xFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsConfiguration::clearWifiIp(WiFiConfig& config) {
|
void AmsConfiguration::clearWifiIp(WiFiConfig& config) {
|
||||||
@@ -115,6 +139,14 @@ bool AmsConfiguration::setMqttConfig(MqttConfig& config) {
|
|||||||
} else {
|
} else {
|
||||||
mqttChanged = true;
|
mqttChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stripNonAscii((uint8_t*) config.host, 128);
|
||||||
|
stripNonAscii((uint8_t*) config.clientId, 32);
|
||||||
|
stripNonAscii((uint8_t*) config.publishTopic, 64);
|
||||||
|
stripNonAscii((uint8_t*) config.subscribeTopic, 64);
|
||||||
|
stripNonAscii((uint8_t*) config.username, 128);
|
||||||
|
stripNonAscii((uint8_t*) config.password, 256);
|
||||||
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_MQTT_START, config);
|
EEPROM.put(CONFIG_MQTT_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -159,6 +191,10 @@ bool AmsConfiguration::getWebConfig(WebConfig& config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::setWebConfig(WebConfig& config) {
|
bool AmsConfiguration::setWebConfig(WebConfig& config) {
|
||||||
|
|
||||||
|
stripNonAscii((uint8_t*) config.username, 64);
|
||||||
|
stripNonAscii((uint8_t*) config.password, 64);
|
||||||
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_WEB_START, config);
|
EEPROM.put(CONFIG_WEB_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -206,11 +242,11 @@ bool AmsConfiguration::setMeterConfig(MeterConfig& config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AmsConfiguration::clearMeter(MeterConfig& config) {
|
void AmsConfiguration::clearMeter(MeterConfig& config) {
|
||||||
config.baud = 2400;
|
config.baud = 0;
|
||||||
config.parity = 11; // 8E1
|
config.parity = 0;
|
||||||
config.invert = false;
|
config.invert = false;
|
||||||
config.distributionSystem = 0;
|
config.distributionSystem = 2;
|
||||||
config.mainFuse = 0;
|
config.mainFuse = 40;
|
||||||
config.productionCapacity = 0;
|
config.productionCapacity = 0;
|
||||||
memset(config.encryptionKey, 0, 16);
|
memset(config.encryptionKey, 0, 16);
|
||||||
memset(config.authenticationKey, 0, 16);
|
memset(config.authenticationKey, 0, 16);
|
||||||
@@ -218,6 +254,8 @@ void AmsConfiguration::clearMeter(MeterConfig& config) {
|
|||||||
config.voltageMultiplier = 0;
|
config.voltageMultiplier = 0;
|
||||||
config.amperageMultiplier = 0;
|
config.amperageMultiplier = 0;
|
||||||
config.accumulatedMultiplier = 0;
|
config.accumulatedMultiplier = 0;
|
||||||
|
config.source = 1; // Serial
|
||||||
|
config.parser = 0; // Auto
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::isMeterChanged() {
|
bool AmsConfiguration::isMeterChanged() {
|
||||||
@@ -426,12 +464,15 @@ bool AmsConfiguration::setNtpConfig(NtpConfig& config) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ntpChanged |= config.dhcp != existing.dhcp;
|
ntpChanged |= config.dhcp != existing.dhcp;
|
||||||
ntpChanged |= config.offset != existing.offset;
|
|
||||||
ntpChanged |= config.summerOffset != existing.summerOffset;
|
|
||||||
ntpChanged |= strcmp(config.server, existing.server) != 0;
|
ntpChanged |= strcmp(config.server, existing.server) != 0;
|
||||||
|
ntpChanged |= strcmp(config.timezone, existing.timezone) != 0;
|
||||||
} else {
|
} else {
|
||||||
ntpChanged = true;
|
ntpChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stripNonAscii((uint8_t*) config.server, 64);
|
||||||
|
stripNonAscii((uint8_t*) config.timezone, 32);
|
||||||
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_NTP_START, config);
|
EEPROM.put(CONFIG_NTP_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -450,9 +491,8 @@ void AmsConfiguration::ackNtpChange() {
|
|||||||
void AmsConfiguration::clearNtp(NtpConfig& config) {
|
void AmsConfiguration::clearNtp(NtpConfig& config) {
|
||||||
config.enable = true;
|
config.enable = true;
|
||||||
config.dhcp = true;
|
config.dhcp = true;
|
||||||
config.offset = 360;
|
|
||||||
config.summerOffset = 360;
|
|
||||||
strcpy(config.server, "pool.ntp.org");
|
strcpy(config.server, "pool.ntp.org");
|
||||||
|
strcpy(config.timezone, "Europe/Oslo");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::getEntsoeConfig(EntsoeConfig& config) {
|
bool AmsConfiguration::getEntsoeConfig(EntsoeConfig& config) {
|
||||||
@@ -476,9 +516,15 @@ bool AmsConfiguration::setEntsoeConfig(EntsoeConfig& config) {
|
|||||||
entsoeChanged |= strcmp(config.area, existing.area) != 0;
|
entsoeChanged |= strcmp(config.area, existing.area) != 0;
|
||||||
entsoeChanged |= strcmp(config.currency, existing.currency) != 0;
|
entsoeChanged |= strcmp(config.currency, existing.currency) != 0;
|
||||||
entsoeChanged |= config.multiplier != existing.multiplier;
|
entsoeChanged |= config.multiplier != existing.multiplier;
|
||||||
|
entsoeChanged |= config.enabled != existing.enabled;
|
||||||
} else {
|
} else {
|
||||||
entsoeChanged = true;
|
entsoeChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stripNonAscii((uint8_t*) config.token, 37);
|
||||||
|
stripNonAscii((uint8_t*) config.area, 17);
|
||||||
|
stripNonAscii((uint8_t*) config.currency, 4);
|
||||||
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_ENTSOE_START, config);
|
EEPROM.put(CONFIG_ENTSOE_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -491,6 +537,7 @@ void AmsConfiguration::clearEntsoe(EntsoeConfig& config) {
|
|||||||
strcpy(config.area, "");
|
strcpy(config.area, "");
|
||||||
strcpy(config.currency, "");
|
strcpy(config.currency, "");
|
||||||
config.multiplier = 1000;
|
config.multiplier = 1000;
|
||||||
|
config.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::isEntsoeChanged() {
|
bool AmsConfiguration::isEntsoeChanged() {
|
||||||
@@ -510,6 +557,7 @@ bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config)
|
|||||||
if(config.thresholds[9] != 255) {
|
if(config.thresholds[9] != 255) {
|
||||||
clearEnergyAccountingConfig(config);
|
clearEnergyAccountingConfig(config);
|
||||||
}
|
}
|
||||||
|
if(config.hours > 5) config.hours = 5;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -535,7 +583,6 @@ bool AmsConfiguration::setEnergyAccountingConfig(EnergyAccountingConfig& config)
|
|||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||||
@@ -549,6 +596,7 @@ void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& confi
|
|||||||
config.thresholds[7] = 100;
|
config.thresholds[7] = 100;
|
||||||
config.thresholds[8] = 150;
|
config.thresholds[8] = 150;
|
||||||
config.thresholds[9] = 255;
|
config.thresholds[9] = 255;
|
||||||
|
config.hours = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::isEnergyAccountingChanged() {
|
bool AmsConfiguration::isEnergyAccountingChanged() {
|
||||||
@@ -559,9 +607,53 @@ void AmsConfiguration::ackEnergyAccountingChange() {
|
|||||||
energyAccountingChanged = false;
|
energyAccountingChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::getUiConfig(UiConfig& config) {
|
||||||
|
if(hasConfig()) {
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_UI_START, config);
|
||||||
|
if(config.showImport > 2) clearUiConfig(config); // Must be wrong
|
||||||
|
EEPROM.end();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
clearUiConfig(config);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::setUiConfig(UiConfig& config) {
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.put(CONFIG_UI_START, config);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsConfiguration::clearUiConfig(UiConfig& config) {
|
||||||
|
// 1 = Always, 2 = If value present, 0 = Hidden
|
||||||
|
config.showImport = 1;
|
||||||
|
config.showExport = 2;
|
||||||
|
config.showVoltage = 2;
|
||||||
|
config.showAmperage = 2;
|
||||||
|
config.showReactive = 0;
|
||||||
|
config.showRealtime = 1;
|
||||||
|
config.showPeaks = 2;
|
||||||
|
config.showPricePlot = 2;
|
||||||
|
config.showDayPlot = 1;
|
||||||
|
config.showMonthPlot = 1;
|
||||||
|
config.showTemperaturePlot = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void AmsConfiguration::clear() {
|
void AmsConfiguration::clear() {
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
|
||||||
|
SystemConfig sys;
|
||||||
|
EEPROM.get(CONFIG_SYSTEM_START, sys);
|
||||||
|
sys.userConfigured = false;
|
||||||
|
sys.dataCollectionConsent = 0;
|
||||||
|
strcpy(sys.country, "");
|
||||||
|
EEPROM.put(CONFIG_SYSTEM_START, sys);
|
||||||
|
|
||||||
MeterConfig meter;
|
MeterConfig meter;
|
||||||
clearMeter(meter);
|
clearMeter(meter);
|
||||||
EEPROM.put(CONFIG_METER_START, meter);
|
EEPROM.put(CONFIG_METER_START, meter);
|
||||||
@@ -594,7 +686,15 @@ void AmsConfiguration::clear() {
|
|||||||
clearEnergyAccountingConfig(eac);
|
clearEnergyAccountingConfig(eac);
|
||||||
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||||
|
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, -1);
|
DebugConfig debug;
|
||||||
|
clearDebug(debug);
|
||||||
|
EEPROM.put(CONFIG_DEBUG_START, debug);
|
||||||
|
|
||||||
|
UiConfig ui;
|
||||||
|
clearUiConfig(ui);
|
||||||
|
EEPROM.put(CONFIG_UI_START, ui);
|
||||||
|
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CLEARED_INDICATOR);
|
||||||
EEPROM.commit();
|
EEPROM.commit();
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
}
|
}
|
||||||
@@ -613,22 +713,6 @@ bool AmsConfiguration::hasConfig() {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(configVersion) {
|
switch(configVersion) {
|
||||||
case 86:
|
|
||||||
configVersion = -1; // Prevent loop
|
|
||||||
if(relocateConfig86()) {
|
|
||||||
configVersion = 87;
|
|
||||||
} else {
|
|
||||||
configVersion = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 87:
|
|
||||||
configVersion = -1; // Prevent loop
|
|
||||||
if(relocateConfig87()) {
|
|
||||||
configVersion = 88;
|
|
||||||
} else {
|
|
||||||
configVersion = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 90:
|
case 90:
|
||||||
configVersion = -1; // Prevent loop
|
configVersion = -1; // Prevent loop
|
||||||
if(relocateConfig90()) {
|
if(relocateConfig90()) {
|
||||||
@@ -669,6 +753,30 @@ bool AmsConfiguration::hasConfig() {
|
|||||||
configVersion = 0;
|
configVersion = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
case 95:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig95()) {
|
||||||
|
configVersion = 96;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 96:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig96()) {
|
||||||
|
configVersion = 100;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 100:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig100()) {
|
||||||
|
configVersion = 101;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
case EEPROM_CHECK_SUM:
|
case EEPROM_CHECK_SUM:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@@ -721,51 +829,6 @@ void AmsConfiguration::saveTempSensors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::relocateConfig86() {
|
|
||||||
MqttConfig86 mqtt86;
|
|
||||||
MqttConfig mqtt;
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
|
||||||
EEPROM.get(CONFIG_MQTT_START_86, mqtt86);
|
|
||||||
strcpy(mqtt.host, mqtt86.host);
|
|
||||||
mqtt.port = mqtt86.port;
|
|
||||||
strcpy(mqtt.clientId, mqtt86.clientId);
|
|
||||||
strcpy(mqtt.publishTopic, mqtt86.publishTopic);
|
|
||||||
strcpy(mqtt.subscribeTopic, mqtt86.subscribeTopic);
|
|
||||||
strcpy(mqtt.username, mqtt86.username);
|
|
||||||
strcpy(mqtt.password, mqtt86.password);
|
|
||||||
mqtt.payloadFormat = mqtt86.payloadFormat;
|
|
||||||
mqtt.ssl = mqtt86.ssl;
|
|
||||||
EEPROM.put(CONFIG_MQTT_START, mqtt);
|
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, 87);
|
|
||||||
bool ret = EEPROM.commit();
|
|
||||||
EEPROM.end();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AmsConfiguration::relocateConfig87() {
|
|
||||||
MeterConfig87 meter87 = {0,0,0,0,0,0,0};
|
|
||||||
MeterConfig meter;
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
|
||||||
EEPROM.get(CONFIG_METER_START_87, meter87);
|
|
||||||
if(meter87.type < 5) {
|
|
||||||
meter.baud = 2400;
|
|
||||||
meter.parity = meter87.type == 3 || meter87.type == 4 ? 3 : 11;
|
|
||||||
meter.invert = false;
|
|
||||||
} else {
|
|
||||||
meter.baud = 115200;
|
|
||||||
meter.parity = 3;
|
|
||||||
meter.invert = meter87.type == 6;
|
|
||||||
}
|
|
||||||
meter.distributionSystem = meter87.distributionSystem;
|
|
||||||
meter.mainFuse = meter87.mainFuse;
|
|
||||||
meter.productionCapacity = meter87.productionCapacity;
|
|
||||||
EEPROM.put(CONFIG_METER_START, meter);
|
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, 88);
|
|
||||||
bool ret = EEPROM.commit();
|
|
||||||
EEPROM.end();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AmsConfiguration::relocateConfig90() {
|
bool AmsConfiguration::relocateConfig90() {
|
||||||
EntsoeConfig entsoe;
|
EntsoeConfig entsoe;
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
@@ -846,6 +909,129 @@ bool AmsConfiguration::relocateConfig94() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig95() {
|
||||||
|
MeterConfig meter;
|
||||||
|
MeterConfig95 meter95;
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_METER_START, meter);
|
||||||
|
EEPROM.get(CONFIG_METER_START, meter95);
|
||||||
|
meter.wattageMultiplier = meter95.wattageMultiplier;
|
||||||
|
meter.voltageMultiplier = meter95.voltageMultiplier;
|
||||||
|
meter.amperageMultiplier = meter95.amperageMultiplier;
|
||||||
|
meter.accumulatedMultiplier = meter95.accumulatedMultiplier;
|
||||||
|
EEPROM.put(CONFIG_METER_START, meter);
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 96);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig96() {
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
SystemConfig sys;
|
||||||
|
EEPROM.get(CONFIG_SYSTEM_START, sys);
|
||||||
|
|
||||||
|
MeterConfig meter;
|
||||||
|
EEPROM.get(CONFIG_METER_START, meter);
|
||||||
|
meter.source = 1; // Serial
|
||||||
|
meter.parser = 0; // Auto
|
||||||
|
EEPROM.put(CONFIG_METER_START, meter);
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
GpioConfig gpio;
|
||||||
|
EEPROM.get(CONFIG_GPIO_START, gpio);
|
||||||
|
|
||||||
|
switch(sys.boardType) {
|
||||||
|
case 3: // Pow UART0 -- Now Pow-K UART0
|
||||||
|
case 4: // Pow GPIO12 -- Now Pow-U UART0
|
||||||
|
case 5: // Pow-K+ -- Now also Pow-K GPIO12
|
||||||
|
case 7: // Pow-U+ -- Now also Pow-U GPIO12
|
||||||
|
if(meter.baud == 2400 && meter.parity == 3) { // 3 == 8N1, assuming Pow-K
|
||||||
|
if(gpio.hanPin == 3) { // UART0
|
||||||
|
sys.boardType = 3;
|
||||||
|
} else if(gpio.hanPin == 12) {
|
||||||
|
sys.boardType = 5;
|
||||||
|
}
|
||||||
|
} else { // Assuming Pow-U
|
||||||
|
if(gpio.hanPin == 3) { // UART0
|
||||||
|
sys.boardType = 4;
|
||||||
|
} else if(gpio.hanPin == 12) {
|
||||||
|
sys.boardType = 7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
sys.vendorConfigured = true;
|
||||||
|
sys.userConfigured = true;
|
||||||
|
sys.dataCollectionConsent = 0;
|
||||||
|
strcpy(sys.country, "");
|
||||||
|
EEPROM.put(CONFIG_SYSTEM_START, sys);
|
||||||
|
|
||||||
|
WiFiConfig wifi;
|
||||||
|
EEPROM.get(CONFIG_WIFI_START, wifi);
|
||||||
|
wifi.mode = 1; // WIFI_STA
|
||||||
|
wifi.autoreboot = true;
|
||||||
|
EEPROM.put(CONFIG_WIFI_START, wifi);
|
||||||
|
|
||||||
|
NtpConfig ntp;
|
||||||
|
NtpConfig96 ntp96;
|
||||||
|
EEPROM.get(CONFIG_NTP_START, ntp96);
|
||||||
|
ntp.enable = ntp96.enable;
|
||||||
|
ntp.dhcp = ntp96.dhcp;
|
||||||
|
if(ntp96.offset == 360 && ntp96.summerOffset == 360) {
|
||||||
|
strcpy(ntp.timezone, "Europe/Oslo");
|
||||||
|
} else {
|
||||||
|
strcpy(ntp.timezone, "GMT");
|
||||||
|
}
|
||||||
|
strcpy(ntp.server, ntp96.server);
|
||||||
|
EEPROM.put(CONFIG_NTP_START, ntp);
|
||||||
|
|
||||||
|
EntsoeConfig entsoe;
|
||||||
|
EEPROM.get(CONFIG_ENTSOE_START, entsoe);
|
||||||
|
entsoe.enabled = strlen(entsoe.token) > 0;
|
||||||
|
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
|
||||||
|
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 100);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig100() {
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
|
||||||
|
MeterConfig100 meter100;
|
||||||
|
EEPROM.get(CONFIG_METER_START, meter100);
|
||||||
|
MeterConfig meter;
|
||||||
|
meter.baud = meter100.baud;
|
||||||
|
meter.parity = meter100.parity;
|
||||||
|
meter.invert = meter100.invert;
|
||||||
|
meter.distributionSystem = meter100.distributionSystem;
|
||||||
|
meter.mainFuse = meter100.mainFuse;
|
||||||
|
meter.productionCapacity = meter100.productionCapacity;
|
||||||
|
memcpy(meter.encryptionKey, meter100.encryptionKey, 16);
|
||||||
|
memcpy(meter.authenticationKey, meter100.authenticationKey, 16);
|
||||||
|
meter.wattageMultiplier = meter100.wattageMultiplier;
|
||||||
|
meter.voltageMultiplier = meter100.voltageMultiplier;
|
||||||
|
meter.amperageMultiplier = meter100.amperageMultiplier;
|
||||||
|
meter.accumulatedMultiplier = meter100.accumulatedMultiplier;
|
||||||
|
meter.source = meter100.source;
|
||||||
|
meter.parser = meter100.parser;
|
||||||
|
|
||||||
|
EEPROM.put(CONFIG_METER_START, meter);
|
||||||
|
|
||||||
|
UiConfig ui;
|
||||||
|
clearUiConfig(ui);
|
||||||
|
EEPROM.put(CONFIG_UI_START, ui);
|
||||||
|
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 101);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::save() {
|
bool AmsConfiguration::save() {
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
||||||
@@ -1049,8 +1235,7 @@ void AmsConfiguration::print(Print* debugger)
|
|||||||
debugger->println("--NTP configuration--");
|
debugger->println("--NTP configuration--");
|
||||||
debugger->printf("Enabled: %s\r\n", ntp.enable ? "Yes" : "No");
|
debugger->printf("Enabled: %s\r\n", ntp.enable ? "Yes" : "No");
|
||||||
if(ntp.enable) {
|
if(ntp.enable) {
|
||||||
debugger->printf("Offset: %i\r\n", ntp.offset);
|
debugger->printf("Timezone: %s\r\n", ntp.timezone);
|
||||||
debugger->printf("Summer offset: %i\r\n", ntp.summerOffset);
|
|
||||||
debugger->printf("Server: %s\r\n", ntp.server);
|
debugger->printf("Server: %s\r\n", ntp.server);
|
||||||
debugger->printf("DHCP: %s\r\n", ntp.dhcp ? "Yes" : "No");
|
debugger->printf("DHCP: %s\r\n", ntp.dhcp ? "Yes" : "No");
|
||||||
}
|
}
|
||||||
@@ -1061,12 +1246,12 @@ void AmsConfiguration::print(Print* debugger)
|
|||||||
|
|
||||||
EntsoeConfig entsoe;
|
EntsoeConfig entsoe;
|
||||||
if(getEntsoeConfig(entsoe)) {
|
if(getEntsoeConfig(entsoe)) {
|
||||||
debugger->println("--ENTSO-E configuration--");
|
if(strlen(entsoe.area) > 0) {
|
||||||
debugger->printf("Token: %s\r\n", entsoe.token);
|
debugger->println("--ENTSO-E configuration--");
|
||||||
if(strlen(entsoe.token) > 0) {
|
|
||||||
debugger->printf("Area: %s\r\n", entsoe.area);
|
debugger->printf("Area: %s\r\n", entsoe.area);
|
||||||
debugger->printf("Currency: %s\r\n", entsoe.currency);
|
debugger->printf("Currency: %s\r\n", entsoe.currency);
|
||||||
debugger->printf("Multiplier: %f\r\n", entsoe.multiplier / 1000.0);
|
debugger->printf("Multiplier: %f\r\n", entsoe.multiplier / 1000.0);
|
||||||
|
debugger->printf("Token: %s\r\n", entsoe.token);
|
||||||
}
|
}
|
||||||
debugger->println("");
|
debugger->println("");
|
||||||
delay(10);
|
delay(10);
|
||||||
@@ -20,4 +20,17 @@ void fromHex(uint8_t *out, String in, uint16_t size) {
|
|||||||
for(int i = 0; i < size*2; i += 2) {
|
for(int i = 0; i < size*2; i += 2) {
|
||||||
out[i/2] = strtol(in.substring(i, i+2).c_str(), 0, 16);
|
out[i/2] = strtol(in.substring(i, i+2).c_str(), 0, 16);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void stripNonAscii(uint8_t* in, uint16_t size) {
|
||||||
|
for(uint16_t i = 0; i < size; i++) {
|
||||||
|
if(in[i] == 0) { // Clear the rest with null-terminator
|
||||||
|
memset(in+i, 0, size-i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(in[i] < 32 || in[i] > 126) {
|
||||||
|
memset(in+i, ' ', 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(in+size-1, 0, 1); // Make sure the last character is null-terminator
|
||||||
}
|
}
|
||||||
@@ -10,9 +10,8 @@ enum AmsType {
|
|||||||
AmsTypeKaifa = 0x02,
|
AmsTypeKaifa = 0x02,
|
||||||
AmsTypeKamstrup = 0x03,
|
AmsTypeKamstrup = 0x03,
|
||||||
AmsTypeIskra = 0x08,
|
AmsTypeIskra = 0x08,
|
||||||
AmsTypeLandis = 0x09,
|
AmsTypeLandisGyr = 0x09,
|
||||||
AmsTypeSagemcom = 0x0A,
|
AmsTypeSagemcom = 0x0A,
|
||||||
AmsTypeLng = 0x0B,
|
|
||||||
AmsTypeCustom = 0x88,
|
AmsTypeCustom = 0x88,
|
||||||
AmsTypeUnknown = 0xFF
|
AmsTypeUnknown = 0xFF
|
||||||
};
|
};
|
||||||
@@ -70,6 +69,9 @@ public:
|
|||||||
bool isThreePhase();
|
bool isThreePhase();
|
||||||
bool isTwoPhase();
|
bool isTwoPhase();
|
||||||
|
|
||||||
|
int8_t getLastError();
|
||||||
|
void setLastError(int8_t);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
unsigned long lastUpdateMillis = 0;
|
unsigned long lastUpdateMillis = 0;
|
||||||
unsigned long lastList2 = 0;
|
unsigned long lastList2 = 0;
|
||||||
@@ -84,6 +86,9 @@ protected:
|
|||||||
float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0;
|
float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0;
|
||||||
double activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0;
|
double activeImportCounter = 0, reactiveImportCounter = 0, activeExportCounter = 0, reactiveExportCounter = 0;
|
||||||
bool threePhase = false, twoPhase = false, counterEstimated = false;
|
bool threePhase = false, twoPhase = false, counterEstimated = false;
|
||||||
|
|
||||||
|
int8_t lastError = 0x00;
|
||||||
|
uint8_t lastErrorCount = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "AmsConfiguration.h"
|
#include "AmsConfiguration.h"
|
||||||
#include "EnergyAccounting.h"
|
#include "EnergyAccounting.h"
|
||||||
#include "HwTools.h"
|
#include "HwTools.h"
|
||||||
#include "entsoe/EntsoeApi.h"
|
#include "EntsoeApi.h"
|
||||||
|
|
||||||
class AmsMqttHandler {
|
class AmsMqttHandler {
|
||||||
public:
|
public:
|
||||||
@@ -64,7 +64,6 @@ void AmsData::apply(AmsData& other) {
|
|||||||
this->meterType = other.getMeterType();
|
this->meterType = other.getMeterType();
|
||||||
this->meterModel = other.getMeterModel();
|
this->meterModel = other.getMeterModel();
|
||||||
this->reactiveImportPower = other.getReactiveImportPower();
|
this->reactiveImportPower = other.getReactiveImportPower();
|
||||||
this->activeExportPower = other.getActiveExportPower();
|
|
||||||
this->reactiveExportPower = other.getReactiveExportPower();
|
this->reactiveExportPower = other.getReactiveExportPower();
|
||||||
this->l1current = other.getL1Current();
|
this->l1current = other.getL1Current();
|
||||||
this->l2current = other.getL2Current();
|
this->l2current = other.getL2Current();
|
||||||
@@ -74,9 +73,13 @@ void AmsData::apply(AmsData& other) {
|
|||||||
this->l3voltage = other.getL3Voltage();
|
this->l3voltage = other.getL3Voltage();
|
||||||
this->threePhase = other.isThreePhase();
|
this->threePhase = other.isThreePhase();
|
||||||
this->twoPhase = other.isTwoPhase();
|
this->twoPhase = other.isTwoPhase();
|
||||||
case 1:
|
|
||||||
this->activeImportPower = other.getActiveImportPower();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Moved outside switch to handle meters alternating between sending active and accumulated values
|
||||||
|
if(other.getListType() == 1 || (other.getActiveImportPower() > 0 || other.getActiveExportPower() > 0))
|
||||||
|
this->activeImportPower = other.getActiveImportPower();
|
||||||
|
if(other.getListType() == 2 || (other.getActiveImportPower() > 0 || other.getActiveExportPower() > 0))
|
||||||
|
this->activeExportPower = other.getActiveExportPower();
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long AmsData::getLastUpdateMillis() {
|
unsigned long AmsData::getLastUpdateMillis() {
|
||||||
@@ -214,3 +217,16 @@ bool AmsData::isThreePhase() {
|
|||||||
bool AmsData::isTwoPhase() {
|
bool AmsData::isTwoPhase() {
|
||||||
return this->twoPhase;
|
return this->twoPhase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t AmsData::getLastError() {
|
||||||
|
return lastErrorCount > 3 ? lastError : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsData::setLastError(int8_t lastError) {
|
||||||
|
this->lastError = lastError;
|
||||||
|
if(lastError == 0) {
|
||||||
|
lastErrorCount = 0;
|
||||||
|
} else {
|
||||||
|
lastErrorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,31 +7,33 @@
|
|||||||
|
|
||||||
struct DayDataPoints {
|
struct DayDataPoints {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
int16_t hImport[24];
|
uint16_t hImport[24];
|
||||||
time_t lastMeterReadTime;
|
time_t lastMeterReadTime;
|
||||||
uint32_t activeImport;
|
uint32_t activeImport;
|
||||||
uint32_t activeExport;
|
uint32_t activeExport;
|
||||||
int16_t hExport[24];
|
uint16_t hExport[24];
|
||||||
}; // 112 bytes
|
uint8_t accuracy;
|
||||||
|
}; // 113 bytes
|
||||||
|
|
||||||
struct MonthDataPoints {
|
struct MonthDataPoints {
|
||||||
uint8_t version;
|
uint8_t version;
|
||||||
int16_t dImport[31];
|
uint16_t dImport[31];
|
||||||
time_t lastMeterReadTime;
|
time_t lastMeterReadTime;
|
||||||
uint32_t activeImport;
|
uint32_t activeImport;
|
||||||
uint32_t activeExport;
|
uint32_t activeExport;
|
||||||
int16_t dExport[31];
|
uint16_t dExport[31];
|
||||||
}; // 141 bytes
|
uint8_t accuracy;
|
||||||
|
}; // 142 bytes
|
||||||
|
|
||||||
class AmsDataStorage {
|
class AmsDataStorage {
|
||||||
public:
|
public:
|
||||||
AmsDataStorage(RemoteDebug*);
|
AmsDataStorage(RemoteDebug*);
|
||||||
void setTimezone(Timezone*);
|
void setTimezone(Timezone*);
|
||||||
bool update(AmsData*);
|
bool update(AmsData*);
|
||||||
int32_t getHourImport(uint8_t);
|
uint32_t getHourImport(uint8_t);
|
||||||
int32_t getHourExport(uint8_t);
|
uint32_t getHourExport(uint8_t);
|
||||||
int32_t getDayImport(uint8_t);
|
uint32_t getDayImport(uint8_t);
|
||||||
int32_t getDayExport(uint8_t);
|
uint32_t getDayExport(uint8_t);
|
||||||
bool load();
|
bool load();
|
||||||
bool save();
|
bool save();
|
||||||
|
|
||||||
@@ -40,6 +42,11 @@ public:
|
|||||||
MonthDataPoints getMonthData();
|
MonthDataPoints getMonthData();
|
||||||
bool setMonthData(MonthDataPoints&);
|
bool setMonthData(MonthDataPoints&);
|
||||||
|
|
||||||
|
uint8_t getDayAccuracy();
|
||||||
|
void setDayAccuracy(uint8_t);
|
||||||
|
uint8_t getMonthAccuracy();
|
||||||
|
void setMonthAccuracy(uint8_t);
|
||||||
|
|
||||||
bool isHappy();
|
bool isHappy();
|
||||||
bool isDayHappy();
|
bool isDayHappy();
|
||||||
bool isMonthHappy();
|
bool isMonthHappy();
|
||||||
@@ -50,19 +57,21 @@ private:
|
|||||||
0,
|
0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
10
|
||||||
};
|
};
|
||||||
MonthDataPoints month = {
|
MonthDataPoints month = {
|
||||||
0,
|
0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
0, 0, 0,
|
0, 0, 0,
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
10
|
||||||
};
|
};
|
||||||
RemoteDebug* debugger;
|
RemoteDebug* debugger;
|
||||||
void setHourImport(uint8_t, int32_t);
|
void setHourImport(uint8_t, uint32_t);
|
||||||
void setHourExport(uint8_t, int32_t);
|
void setHourExport(uint8_t, uint32_t);
|
||||||
void setDayImport(uint8_t, int32_t);
|
void setDayImport(uint8_t, uint32_t);
|
||||||
void setDayExport(uint8_t, int32_t);
|
void setDayExport(uint8_t, uint32_t);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -5,8 +5,10 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) {
|
AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) {
|
||||||
day.version = 4;
|
day.version = 5;
|
||||||
month.version = 5;
|
day.accuracy = 1;
|
||||||
|
month.version = 6;
|
||||||
|
month.accuracy = 1;
|
||||||
this->debugger = debugger;
|
this->debugger = debugger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -21,7 +23,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
time_t now = time(nullptr);
|
time_t now = time(nullptr);
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Time is: %lld\n", (int64_t) now);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Time is: %lu\n", (int32_t) now);
|
||||||
if(tz == NULL) {
|
if(tz == NULL) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n");
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n");
|
||||||
return false;
|
return false;
|
||||||
@@ -30,18 +32,18 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
if(data->getMeterTimestamp() > BUILD_EPOCH) {
|
if(data->getMeterTimestamp() > BUILD_EPOCH) {
|
||||||
now = data->getMeterTimestamp();
|
now = data->getMeterTimestamp();
|
||||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %lld\n", (int64_t) now);
|
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %lu\n", (int32_t) now);
|
||||||
}
|
}
|
||||||
} else if(data->getPackageTimestamp() > BUILD_EPOCH) {
|
} else if(data->getPackageTimestamp() > BUILD_EPOCH) {
|
||||||
now = data->getPackageTimestamp();
|
now = data->getPackageTimestamp();
|
||||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugger->printf("(AmsDataStorage) Using package timestamp, which is: %lld\n", (int64_t) now);
|
debugger->printf("(AmsDataStorage) Using package timestamp, which is: %lu\n", (int32_t) now);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(now < BUILD_EPOCH) {
|
if(now < BUILD_EPOCH) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||||
debugger->printf("(AmsDataStorage) Invalid time: %lld\n", (int64_t) now);
|
debugger->printf("(AmsDataStorage) Invalid time: %lu\n", (int32_t) now);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -63,7 +65,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugger->printf("(AmsDataStorage) Last day update: %lld\n", (int64_t) day.lastMeterReadTime);
|
debugger->printf("(AmsDataStorage) Last day update: %lu\n", (int32_t) day.lastMeterReadTime);
|
||||||
}
|
}
|
||||||
tmElements_t last;
|
tmElements_t last;
|
||||||
breakTime(day.lastMeterReadTime, last);
|
breakTime(day.lastMeterReadTime, last);
|
||||||
@@ -86,7 +88,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
month.lastMeterReadTime = now;
|
month.lastMeterReadTime = now;
|
||||||
} else {
|
} else {
|
||||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugger->printf("(AmsDataStorage) Last month update: %lld\n", (int64_t) month.lastMeterReadTime);
|
debugger->printf("(AmsDataStorage) Last month update: %lu\n", (int32_t) month.lastMeterReadTime);
|
||||||
}
|
}
|
||||||
tmElements_t last;
|
tmElements_t last;
|
||||||
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
@@ -156,7 +158,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
setHourExport(last.Hour, exp);
|
setHourExport(last.Hour, exp);
|
||||||
|
|
||||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||||
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lld)\n", last.Hour, imp, exp, (int64_t) cur);
|
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lu)\n", last.Hour, imp, exp, (int32_t) cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
day.activeImport += imp;
|
day.activeImport += imp;
|
||||||
@@ -199,7 +201,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
month.lastMeterReadTime = month.lastMeterReadTime - (last.Hour * 3600) - (last.Minute * 60) - last.Second;
|
month.lastMeterReadTime = month.lastMeterReadTime - (last.Hour * 3600) - (last.Minute * 60) - last.Second;
|
||||||
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lld\n", (int64_t) month.lastMeterReadTime);
|
debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lu\n", (int32_t) month.lastMeterReadTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
float hrs = (now - month.lastMeterReadTime) / 3600.0;
|
float hrs = (now - month.lastMeterReadTime) / 3600.0;
|
||||||
@@ -224,7 +226,7 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
setDayExport(last.Day, exp);
|
setDayExport(last.Day, exp);
|
||||||
|
|
||||||
if(debugger->isActive(RemoteDebug::INFO)) {
|
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||||
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lld)\n", last.Day, imp, exp, (int64_t) cur);
|
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lu)\n", last.Day, imp, exp, (int32_t) cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
month.activeImport += imp;
|
month.activeImport += imp;
|
||||||
@@ -237,44 +239,160 @@ bool AmsDataStorage::update(AmsData* data) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsDataStorage::setHourImport(uint8_t hour, int32_t val) {
|
void AmsDataStorage::setHourImport(uint8_t hour, uint32_t val) {
|
||||||
if(hour < 0 || hour > 24) return;
|
if(hour < 0 || hour > 24) return;
|
||||||
day.hImport[hour] = val / 10;
|
|
||||||
|
uint8_t accuracy = day.accuracy;
|
||||||
|
uint32_t update = val / pow(10, accuracy);
|
||||||
|
while(update > UINT16_MAX) {
|
||||||
|
accuracy++;
|
||||||
|
update = val / pow(10, accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != day.accuracy) {
|
||||||
|
setDayAccuracy(accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
day.hImport[hour] = update;
|
||||||
|
|
||||||
|
uint32_t max = 0;
|
||||||
|
for(uint8_t i = 0; i < 24; i++) {
|
||||||
|
if(day.hImport[i] > max)
|
||||||
|
max = day.hImport[i];
|
||||||
|
if(day.hExport[i] > max)
|
||||||
|
max = day.hExport[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(max < UINT16_MAX/10 && accuracy > 0) {
|
||||||
|
accuracy--;
|
||||||
|
max = max*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != day.accuracy) {
|
||||||
|
setDayAccuracy(accuracy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AmsDataStorage::getHourImport(uint8_t hour) {
|
uint32_t AmsDataStorage::getHourImport(uint8_t hour) {
|
||||||
if(hour < 0 || hour > 24) return 0;
|
if(hour < 0 || hour > 24) return 0;
|
||||||
return day.hImport[hour] * 10;
|
return day.hImport[hour] * pow(10, day.accuracy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsDataStorage::setHourExport(uint8_t hour, int32_t val) {
|
void AmsDataStorage::setHourExport(uint8_t hour, uint32_t val) {
|
||||||
if(hour < 0 || hour > 24) return;
|
if(hour < 0 || hour > 24) return;
|
||||||
day.hExport[hour] = val / 10;
|
|
||||||
|
uint8_t accuracy = day.accuracy;
|
||||||
|
uint32_t update = val / pow(10, accuracy);
|
||||||
|
while(update > UINT16_MAX) {
|
||||||
|
accuracy++;
|
||||||
|
update = val / pow(10, accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != day.accuracy) {
|
||||||
|
setDayAccuracy(accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
day.hExport[hour] = update;
|
||||||
|
|
||||||
|
uint32_t max = 0;
|
||||||
|
for(uint8_t i = 0; i < 24; i++) {
|
||||||
|
if(day.hImport[i] > max)
|
||||||
|
max = day.hImport[i];
|
||||||
|
if(day.hExport[i] > max)
|
||||||
|
max = day.hExport[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(max < UINT16_MAX/10 && accuracy > 0) {
|
||||||
|
accuracy--;
|
||||||
|
max = max*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != day.accuracy) {
|
||||||
|
setDayAccuracy(accuracy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AmsDataStorage::getHourExport(uint8_t hour) {
|
uint32_t AmsDataStorage::getHourExport(uint8_t hour) {
|
||||||
if(hour < 0 || hour > 24) return 0;
|
if(hour < 0 || hour > 24) return 0;
|
||||||
return day.hExport[hour] * 10;
|
return day.hExport[hour] * pow(10, day.accuracy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsDataStorage::setDayImport(uint8_t day, int32_t val) {
|
void AmsDataStorage::setDayImport(uint8_t day, uint32_t val) {
|
||||||
if(day < 1 || day > 31) return;
|
if(day < 1 || day > 31) return;
|
||||||
month.dImport[day-1] = val / 10;
|
|
||||||
|
uint8_t accuracy = month.accuracy;
|
||||||
|
uint32_t update = val / pow(10, accuracy);
|
||||||
|
while(update > UINT16_MAX) {
|
||||||
|
accuracy++;
|
||||||
|
update = val / pow(10, accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != month.accuracy) {
|
||||||
|
setMonthAccuracy(accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
month.dImport[day-1] = update;
|
||||||
|
|
||||||
|
uint32_t max = 0;
|
||||||
|
for(uint8_t i = 0; i < 31; i++) {
|
||||||
|
if(month.dImport[i] > max)
|
||||||
|
max = month.dImport[i];
|
||||||
|
if(month.dExport[i] > max)
|
||||||
|
max = month.dExport[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(max < UINT16_MAX/10 && accuracy > 0) {
|
||||||
|
accuracy--;
|
||||||
|
max = max*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != month.accuracy) {
|
||||||
|
setMonthAccuracy(accuracy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AmsDataStorage::getDayImport(uint8_t day) {
|
uint32_t AmsDataStorage::getDayImport(uint8_t day) {
|
||||||
if(day < 1 || day > 31) return 0;
|
if(day < 1 || day > 31) return 0;
|
||||||
return (month.dImport[day-1] * 10);
|
return (month.dImport[day-1] * pow(10, month.accuracy));
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsDataStorage::setDayExport(uint8_t day, int32_t val) {
|
void AmsDataStorage::setDayExport(uint8_t day, uint32_t val) {
|
||||||
if(day < 1 || day > 31) return;
|
if(day < 1 || day > 31) return;
|
||||||
month.dExport[day-1] = val / 10;
|
|
||||||
|
uint8_t accuracy = month.accuracy;
|
||||||
|
uint32_t update = val / pow(10, accuracy);
|
||||||
|
while(update > UINT16_MAX) {
|
||||||
|
accuracy++;
|
||||||
|
update = val / pow(10, accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != month.accuracy) {
|
||||||
|
setMonthAccuracy(accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
month.dExport[day-1] = update;
|
||||||
|
|
||||||
|
uint32_t max = 0;
|
||||||
|
for(uint8_t i = 0; i < 31; i++) {
|
||||||
|
if(month.dImport[i] > max)
|
||||||
|
max = month.dImport[i];
|
||||||
|
if(month.dExport[i] > max)
|
||||||
|
max = month.dExport[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
while(max < UINT16_MAX/10 && accuracy > 0) {
|
||||||
|
accuracy--;
|
||||||
|
max = max*10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(accuracy != month.accuracy) {
|
||||||
|
setMonthAccuracy(accuracy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t AmsDataStorage::getDayExport(uint8_t day) {
|
uint32_t AmsDataStorage::getDayExport(uint8_t day) {
|
||||||
if(day < 1 || day > 31) return 0;
|
if(day < 1 || day > 31) return 0;
|
||||||
return (month.dExport[day-1] * 10);
|
return (month.dExport[day-1] * pow(10, month.accuracy));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsDataStorage::load() {
|
bool AmsDataStorage::load() {
|
||||||
@@ -348,31 +466,74 @@ MonthDataPoints AmsDataStorage::getMonthData() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AmsDataStorage::setDayData(DayDataPoints& day) {
|
bool AmsDataStorage::setDayData(DayDataPoints& day) {
|
||||||
if(day.version == 4) {
|
if(day.version == 5) {
|
||||||
this->day = day;
|
this->day = day;
|
||||||
return true;
|
return true;
|
||||||
|
} else if(day.version == 4) {
|
||||||
|
this->day = day;
|
||||||
|
this->day.accuracy = 1;
|
||||||
|
this->day.version = 5;
|
||||||
|
return true;
|
||||||
} else if(day.version == 3) {
|
} else if(day.version == 3) {
|
||||||
this->day = day;
|
this->day = day;
|
||||||
for(uint8_t i = 0; i < 24; i++) this->day.hExport[i] = 0;
|
for(uint8_t i = 0; i < 24; i++) this->day.hExport[i] = 0;
|
||||||
this->day.version = 4;
|
this->day.accuracy = 1;
|
||||||
|
this->day.version = 5;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsDataStorage::setMonthData(MonthDataPoints& month) {
|
bool AmsDataStorage::setMonthData(MonthDataPoints& month) {
|
||||||
if(month.version == 5) {
|
if(month.version == 6) {
|
||||||
this->month = month;
|
this->month = month;
|
||||||
return true;
|
return true;
|
||||||
|
} else if(month.version == 5) {
|
||||||
|
this->month = month;
|
||||||
|
this->month.accuracy = 1;
|
||||||
|
this->month.version = 6;
|
||||||
|
return true;
|
||||||
} else if(month.version == 4) {
|
} else if(month.version == 4) {
|
||||||
this->month = month;
|
this->month = month;
|
||||||
for(uint8_t i = 0; i < 31; i++) this->month.dExport[i] = 0;
|
for(uint8_t i = 0; i < 31; i++) this->month.dExport[i] = 0;
|
||||||
this->month.version = 5;
|
this->month.accuracy = 1;
|
||||||
|
this->month.version = 6;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t AmsDataStorage::getDayAccuracy() {
|
||||||
|
return day.accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setDayAccuracy(uint8_t accuracy) {
|
||||||
|
if(day.accuracy != accuracy) {
|
||||||
|
uint16_t multiplier = pow(10, day.accuracy)/pow(10, accuracy);
|
||||||
|
for(uint8_t i = 0; i < 24; i++) {
|
||||||
|
day.hImport[i] = day.hImport[i] * multiplier;
|
||||||
|
day.hExport[i] = day.hExport[i] * multiplier;
|
||||||
|
}
|
||||||
|
day.accuracy = accuracy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t AmsDataStorage::getMonthAccuracy() {
|
||||||
|
return month.accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setMonthAccuracy(uint8_t accuracy) {
|
||||||
|
if(month.accuracy != accuracy) {
|
||||||
|
uint16_t multiplier = pow(10, month.accuracy)/pow(10, accuracy);
|
||||||
|
for(uint8_t i = 0; i < 31; i++) {
|
||||||
|
month.dImport[i] = month.dImport[i] * multiplier;
|
||||||
|
month.dExport[i] = month.dExport[i] * multiplier;
|
||||||
|
}
|
||||||
|
month.accuracy = accuracy;
|
||||||
|
}
|
||||||
|
month.accuracy = accuracy;
|
||||||
|
}
|
||||||
|
|
||||||
bool AmsDataStorage::isHappy() {
|
bool AmsDataStorage::isHappy() {
|
||||||
return isDayHappy() && isMonthHappy();
|
return isDayHappy() && isMonthHappy();
|
||||||
}
|
}
|
||||||
@@ -383,11 +544,11 @@ bool AmsDataStorage::isDayHappy() {
|
|||||||
tmElements_t tm, last;
|
tmElements_t tm, last;
|
||||||
|
|
||||||
if(now < day.lastMeterReadTime) {
|
if(now < day.lastMeterReadTime) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld < %lld\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu < %lu\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(now-day.lastMeterReadTime > 3600) {
|
if(now-day.lastMeterReadTime > 3600) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lld - %lld > 3600\n", (int64_t) now, (int64_t) day.lastMeterReadTime);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu - %lu > 3600\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
breakTime(tz->toLocal(now), tm);
|
breakTime(tz->toLocal(now), tm);
|
||||||
@@ -411,11 +572,11 @@ bool AmsDataStorage::isMonthHappy() {
|
|||||||
tmElements_t tm, last;
|
tmElements_t tm, last;
|
||||||
|
|
||||||
if(now < month.lastMeterReadTime) {
|
if(now < month.lastMeterReadTime) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld < %lld\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu < %lu\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(now-month.lastMeterReadTime > 86400) {
|
if(now-month.lastMeterReadTime > 86400) {
|
||||||
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lld - %lld > 3600\n", (int64_t) now, (int64_t) month.lastMeterReadTime);
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu - %lu > 3600\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
breakTime(tz->toLocal(now), tm);
|
breakTime(tz->toLocal(now), tm);
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
uint16_t crc16(const uint8_t* p, int len);
|
||||||
uint16_t crc16_x25(const uint8_t* p, int len);
|
uint16_t crc16_x25(const uint8_t* p, int len);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
#include "DsmrParser.h"
|
#include "DsmrParser.h"
|
||||||
|
#include "crc.h"
|
||||||
|
#include "hexutils.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
|
int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
|
||||||
uint16_t crcPos = 0;
|
uint16_t crcPos = 0;
|
||||||
@@ -14,8 +17,13 @@ int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
|
|||||||
if(!reachedEnd) return DATA_PARSE_INCOMPLETE;
|
if(!reachedEnd) return DATA_PARSE_INCOMPLETE;
|
||||||
buf[ctx.length+1] = '\0';
|
buf[ctx.length+1] = '\0';
|
||||||
if(crcPos > 0) {
|
if(crcPos > 0) {
|
||||||
// TODO: CRC
|
uint16_t crc_calc = crc16(buf, crcPos);
|
||||||
Serial.printf("CRC: %s\n", buf+crcPos);
|
uint16_t crc = 0x0000;
|
||||||
|
fromHex((uint8_t*) &crc, String((char*) buf+crcPos), 2);
|
||||||
|
crc = ntohs(crc);
|
||||||
|
|
||||||
|
if(crc != crc_calc)
|
||||||
|
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
|
||||||
}
|
}
|
||||||
return DATA_PARSE_OK;
|
return DATA_PARSE_OK;
|
||||||
}
|
}
|
||||||
@@ -10,3 +10,20 @@ uint16_t crc16_x25(const uint8_t* p, int len)
|
|||||||
|
|
||||||
return (~crc << 8) | (~crc >> 8 & 0xff);
|
return (~crc << 8) | (~crc >> 8 & 0xff);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t crc16 (const uint8_t *p, int len) {
|
||||||
|
uint16_t crc = 0;
|
||||||
|
|
||||||
|
while (len--) {
|
||||||
|
int i;
|
||||||
|
crc ^= *p++;
|
||||||
|
for (i = 0 ; i < 8 ; ++i) {
|
||||||
|
if (crc & 1)
|
||||||
|
crc = (crc >> 1) ^ 0xa001;
|
||||||
|
else
|
||||||
|
crc = (crc >> 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return crc;
|
||||||
|
}
|
||||||
@@ -657,7 +657,7 @@ var fetch = function() {
|
|||||||
|
|
||||||
if(ip) {
|
if(ip) {
|
||||||
var v = parseInt(json.i);
|
var v = parseInt(json.i);
|
||||||
var pct = (v*100)/parseInt(json.im);
|
var pct = Math.min((v*100)/parseInt(json.im), 100);
|
||||||
var append = "W";
|
var append = "W";
|
||||||
if(v > 1000 && !swatt) {
|
if(v > 1000 && !swatt) {
|
||||||
v = (v/1000).toFixed(1);
|
v = (v/1000).toFixed(1);
|
||||||
@@ -683,7 +683,7 @@ var fetch = function() {
|
|||||||
$('.rim').hide();
|
$('.rim').hide();
|
||||||
if(xp) {
|
if(xp) {
|
||||||
var v = parseInt(json.e);
|
var v = parseInt(json.e);
|
||||||
var pct = (v*100)/(om*1000);
|
var pct = Math.min((v*100)/(om*1000), 100);
|
||||||
var append = "W";
|
var append = "W";
|
||||||
if(v > 1000 && !swatt) {
|
if(v > 1000 && !swatt) {
|
||||||
v = (v/1000).toFixed(1);
|
v = (v/1000).toFixed(1);
|
||||||
@@ -723,21 +723,21 @@ var fetch = function() {
|
|||||||
var u1 = parseFloat(json.u1);
|
var u1 = parseFloat(json.u1);
|
||||||
t += u1;
|
t += u1;
|
||||||
c++;
|
c++;
|
||||||
var pct = (Math.max(parseFloat(json.u1)-195.5, 1)*100/69);
|
var pct = Math.min(Math.max(parseFloat(json.u1)-195.5, 1)*100/69, 100);
|
||||||
arr[r++] = [ds == 1 ? 'L1-L2' : 'L1', u1, "color: " + voltcol(pct) + ";opacity: 0.9;", u1 + "V"];
|
arr[r++] = [ds == 1 ? 'L1-L2' : 'L1', u1, "color: " + voltcol(pct) + ";opacity: 0.9;", u1 + "V"];
|
||||||
}
|
}
|
||||||
if(json.u2) {
|
if(json.u2) {
|
||||||
var u2 = parseFloat(json.u2);
|
var u2 = parseFloat(json.u2);
|
||||||
t += u2;
|
t += u2;
|
||||||
c++;
|
c++;
|
||||||
var pct = (Math.max(parseFloat(json.u2)-195.5, 1)*100/69);
|
var pct = Math.min(Math.max(parseFloat(json.u2)-195.5, 1)*100/69, 100);
|
||||||
arr[r++] = [ds == 1 ? 'L1-L3' : 'L2', u2, "color: " + voltcol(pct) + ";opacity: 0.9;", u2 + "V"];
|
arr[r++] = [ds == 1 ? 'L1-L3' : 'L2', u2, "color: " + voltcol(pct) + ";opacity: 0.9;", u2 + "V"];
|
||||||
}
|
}
|
||||||
if(json.u3) {
|
if(json.u3) {
|
||||||
var u3 = parseFloat(json.u3);
|
var u3 = parseFloat(json.u3);
|
||||||
t += u3;
|
t += u3;
|
||||||
c++;
|
c++;
|
||||||
var pct = (Math.max(parseFloat(json.u3)-195.5, 1)*100/69);
|
var pct = Math.min(Math.max(parseFloat(json.u3)-195.5, 1)*100/69, 100);
|
||||||
arr[r++] = [ds == 1 ? 'L2-L3' : 'L3', u3, "color: " + voltcol(pct) + ";opacity: 0.9;", u3 + "V"];
|
arr[r++] = [ds == 1 ? 'L2-L3' : 'L3', u3, "color: " + voltcol(pct) + ";opacity: 0.9;", u3 + "V"];
|
||||||
}
|
}
|
||||||
v = t/c;
|
v = t/c;
|
||||||
@@ -762,19 +762,19 @@ var fetch = function() {
|
|||||||
if(json.i1 || json.u1) {
|
if(json.i1 || json.u1) {
|
||||||
var i1 = parseFloat(json.i1);
|
var i1 = parseFloat(json.i1);
|
||||||
dA = true;
|
dA = true;
|
||||||
var pct = (parseFloat(json.i1)/parseInt(json.mf))*100;
|
var pct = Math.min((parseFloat(json.i1)/parseInt(json.mf))*100, 100);
|
||||||
arr[r++] = ['L1', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i1 + "A"];
|
arr[r++] = ['L1', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i1 + "A"];
|
||||||
}
|
}
|
||||||
if(json.i2 || json.u2) {
|
if(json.i2 || json.u2) {
|
||||||
var i2 = parseFloat(json.i2);
|
var i2 = parseFloat(json.i2);
|
||||||
dA = true;
|
dA = true;
|
||||||
var pct = (parseFloat(json.i2)/parseInt(json.mf))*100;
|
var pct = Math.min((parseFloat(json.i2)/parseInt(json.mf))*100, 100);
|
||||||
arr[r++] = ['L2', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i2 + "A"];
|
arr[r++] = ['L2', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i2 + "A"];
|
||||||
}
|
}
|
||||||
if(json.i3 || json.u3) {
|
if(json.i3 || json.u3) {
|
||||||
var i3 = parseFloat(json.i3);
|
var i3 = parseFloat(json.i3);
|
||||||
dA = true;
|
dA = true;
|
||||||
var pct = (parseFloat(json.i3)/parseInt(json.mf))*100;
|
var pct = Math.min((parseFloat(json.i3)/parseInt(json.mf))*100, 100);
|
||||||
arr[r++] = ['L3', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i3 + "A"];
|
arr[r++] = ['L3', pct, "color: " + ampcol(pct) + ";opacity: 0.9;", i3 + "A"];
|
||||||
}
|
}
|
||||||
if(dA) {
|
if(dA) {
|
||||||
@@ -854,7 +854,7 @@ var fetch = function() {
|
|||||||
$('.jmt').html("Iskra");
|
$('.jmt').html("Iskra");
|
||||||
break;
|
break;
|
||||||
case 9:
|
case 9:
|
||||||
$('.jmt').html("Landis");
|
$('.jmt').html("Landis+Gyr");
|
||||||
break;
|
break;
|
||||||
case 10:
|
case 10:
|
||||||
$('.jmt').html("Sagemcom");
|
$('.jmt').html("Sagemcom");
|
||||||
@@ -40,17 +40,20 @@
|
|||||||
"h" : {
|
"h" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f,
|
"c" : %.2f,
|
||||||
"p" : %.2f
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
},
|
},
|
||||||
"d" : {
|
"d" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f,
|
"c" : %.2f,
|
||||||
"p" : %.2f
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
},
|
},
|
||||||
"m" : {
|
"m" : {
|
||||||
"u" : %.2f,
|
"u" : %.2f,
|
||||||
"c" : %.2f,
|
"c" : %.2f,
|
||||||
"p" : %.2f
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"c" : %u
|
"c" : %u
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -48,7 +48,7 @@
|
|||||||
<main role="main" class="container">
|
<main role="main" class="container">
|
||||||
<header class="navbar navbar-expand navbar-dark flex-column flex-lg-row rounded shadow mt-2 mb-3" style="background-color: var(--purple);">
|
<header class="navbar navbar-expand navbar-dark flex-column flex-lg-row rounded shadow mt-2 mb-3" style="background-color: var(--purple);">
|
||||||
<a href="/" class="">
|
<a href="/" class="">
|
||||||
<h6 class="navbar-brand">AMS reader <small id="swVersion" data-url="https://api.github.com/repos/gskjold/AmsToMqttBridge/releases">${version}</small></h6>
|
<h6 class="navbar-brand">AMS reader <small id="swVersion" data-url="https://api.github.com/repos/UtilitechAS/amsreader-firmware/releases">${version}</small></h6>
|
||||||
</a>
|
</a>
|
||||||
<div class="navbar-nav-scroll">
|
<div class="navbar-nav-scroll">
|
||||||
<ul class="navbar-nav bd-navbar-nav flex-row">
|
<ul class="navbar-nav bd-navbar-nav flex-row">
|
||||||
@@ -64,9 +64,9 @@
|
|||||||
<a class="dropdown-item" href="/mqtt">MQTT</a>
|
<a class="dropdown-item" href="/mqtt">MQTT</a>
|
||||||
<a class="dropdown-item" href="/web">Web</a>
|
<a class="dropdown-item" href="/web">Web</a>
|
||||||
<a class="dropdown-item" href="/ntp">NTP</a>
|
<a class="dropdown-item" href="/ntp">NTP</a>
|
||||||
<a class="dropdown-item d-none ssl-capable" href="/entsoe">ENTSO-E API</a>
|
<a class="dropdown-item" href="/priceapi">Price API</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item" href="https://github.com/gskjold/AmsToMqttBridge/wiki" target="_blank">Documentation</a>
|
<a class="dropdown-item" href="https://github.com/UtilitechAS/amsreader-firmware/wiki" target="_blank">Documentation</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-lg-flex">
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-lg-flex">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
<a class="nav-link p-2" href="https://github.com/UtilitechAS/amsreader-firmware" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -35,6 +35,7 @@
|
|||||||
<span class="input-group-text">Baud rate</span>
|
<span class="input-group-text">Baud rate</span>
|
||||||
</div>
|
</div>
|
||||||
<select class="form-control sd" name="b">
|
<select class="form-control sd" name="b">
|
||||||
|
<option value="300" {b300}>300</option>
|
||||||
<option value="2400" {b2400}>2400</option>
|
<option value="2400" {b2400}>2400</option>
|
||||||
<option value="4800" {b4800}>4800</option>
|
<option value="4800" {b4800}>4800</option>
|
||||||
<option value="9600" {b9600}>9600</option>
|
<option value="9600" {b9600}>9600</option>
|
||||||
@@ -64,7 +65,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-4 col-sm-8">
|
<div class="col-lg-4 col-sm-8">
|
||||||
<a href="https://github.com/gskjold/AmsToMqttBridge/wiki/Known-hardware-configurations" target="_blank">Known hardware configurations</a>
|
<a href="https://github.com/UtilitechAS/amsreader-firmware/wiki/Known-hardware-configurations" target="_blank">Known hardware configurations</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -1,38 +1,31 @@
|
|||||||
<form method="post" action="/save">
|
<form method="post" action="/save">
|
||||||
<input type="hidden" name="ec" value="true"/>
|
<input type="hidden" name="ec" value="true"/>
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<h6>ENTSO-E API</h6>
|
<h6>Price API</h6>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-4 col-lg-6 col-md-8">
|
|
||||||
<div class="m-2 input-group input-group-sm">
|
|
||||||
<div class="input-group-prepend">
|
|
||||||
<span class="input-group-text">Token</span>
|
|
||||||
</div>
|
|
||||||
<input type="text" name="et" class="form-control" value="{et}"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-6">
|
<div class="col-xl-2 col-lg-3 col-md-4 col-sm-6">
|
||||||
<div class="m-2 input-group input-group-sm">
|
<div class="m-2 input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Region</span>
|
<span class="input-group-text">Region</span>
|
||||||
</div>
|
</div>
|
||||||
<select name="ea" class="form-control">
|
<select name="ea" class="form-control">
|
||||||
|
<option value="">None</option>
|
||||||
<optgroup label="Norway">
|
<optgroup label="Norway">
|
||||||
<option value="10YNO-1--------2" {eaNo1}>NO1</option>
|
<option value="10YNO-1--------2" {no1}>NO1</option>
|
||||||
<option value="10YNO-2--------T" {eaNo2}>NO2</option>
|
<option value="10YNO-2--------T" {no2}>NO2</option>
|
||||||
<option value="10YNO-3--------J" {eaNo3}>NO3</option>
|
<option value="10YNO-3--------J" {no3}>NO3</option>
|
||||||
<option value="10YNO-4--------9" {eaNo4}>NO4</option>
|
<option value="10YNO-4--------9" {no4}>NO4</option>
|
||||||
<option value="10Y1001A1001A48H" {eaNo5}>NO5</option>
|
<option value="10Y1001A1001A48H" {no5}>NO5</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Sweden">
|
<optgroup label="Sweden">
|
||||||
<option value="10Y1001A1001A44P" {eaSe1}>SE1</option>
|
<option value="10Y1001A1001A44P" {se1}>SE1</option>
|
||||||
<option value="10Y1001A1001A45N" {eaSe2}>SE2</option>
|
<option value="10Y1001A1001A45N" {se2}>SE2</option>
|
||||||
<option value="10Y1001A1001A46L" {eaSe3}>SE3</option>
|
<option value="10Y1001A1001A46L" {se3}>SE3</option>
|
||||||
<option value="10Y1001A1001A47J" {eaSe4}>SE4</option>
|
<option value="10Y1001A1001A47J" {se4}>SE4</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<optgroup label="Denmark">
|
<optgroup label="Denmark">
|
||||||
<option value="10YDK-1--------W" {eaDk1}>DK1</option>
|
<option value="10YDK-1--------W" {dk1}>DK1</option>
|
||||||
<option value="10YDK-2--------M" {eaDk2}>DK2</option>
|
<option value="10YDK-2--------M" {dk2}>DK2</option>
|
||||||
</optgroup>
|
</optgroup>
|
||||||
<option value="10YAT-APG------L" {at}>Austria</option>
|
<option value="10YAT-APG------L" {at}>Austria</option>
|
||||||
<option value="10YBE----------2" {be}>Belgium</option>
|
<option value="10YBE----------2" {be}>Belgium</option>
|
||||||
@@ -56,10 +49,10 @@
|
|||||||
<span class="input-group-text">Currency</span>
|
<span class="input-group-text">Currency</span>
|
||||||
</div>
|
</div>
|
||||||
<select name="ecu" class="form-control">
|
<select name="ecu" class="form-control">
|
||||||
<option value="NOK" {ecNOK}>NOK</option>
|
<option value="NOK" {nok}>NOK</option>
|
||||||
<option value="SEK" {ecSEK}>SEK</option>
|
<option value="SEK" {sek}>SEK</option>
|
||||||
<option value="DKK" {ecDKK}>DKK</option>
|
<option value="DKK" {dkk}>DKK</option>
|
||||||
<option value="EUR" {ecEUR}>EUR</option>
|
<option value="EUR" {eur}>EUR</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -71,6 +64,14 @@
|
|||||||
<input name="em" type="number" min="0.001" max="1000" step="0.001" class="form-control" value="{em}"/>
|
<input name="em" type="number" min="0.001" max="1000" step="0.001" class="form-control" value="{em}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-xl-4 col-lg-6 col-md-8 {dt}">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">ENTSO-E token</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="et" class="form-control" value="{et}" placeholder="Optional"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
<a class="nav-link p-2" href="https://github.com/UtilitechAS/amsreader-firmware" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
<img class="d-inline-block align-text-top" style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
<a href="/" class=""><h6 class="navbar-brand">AMS reader <small>${version}</small></h6></a>
|
||||||
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
<ul class="navbar-nav flex-row ml-md-auto d-none d-md-flex">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link p-2" href="https://github.com/gskjold/AmsToMqttBridge" target="_blank" rel="noopener" aria-label="GitHub">
|
<a class="nav-link p-2" href="https://github.com/UtilitechAS/amsreader-firmware" target="_blank" rel="noopener" aria-label="GitHub">
|
||||||
<img style="width: 2rem; height: 2rem;" src="github.svg"/>
|
<img style="width: 2rem; height: 2rem;" src="github.svg"/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row" id="i">
|
<div class="row" id="i">
|
||||||
<div class="col-xl-3 col-lg-4 form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">IP</span>
|
<span class="input-group-text">IP</span>
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
<input type="text" name="i" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{i}"/>
|
<input type="text" name="i" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{i}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-3 col-lg-4 form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Netmask</span>
|
<span class="input-group-text">Netmask</span>
|
||||||
@@ -53,7 +53,7 @@
|
|||||||
<input type="text" name="sn" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{sn}"/>
|
<input type="text" name="sn" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{sn}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-3 col-lg-4 form-group">
|
<div class="col-xl-3 col-lg-4 col-md-6 form-group">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Gateway</span>
|
<span class="input-group-text">Gateway</span>
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
<input type="text" name="g" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{g}"/>
|
<input type="text" name="g" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{g}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-4 col-lg-5 form-group">
|
<div class="col-xl-4 col-lg-5 col-md-6 form-group">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">DNS 1</span>
|
<span class="input-group-text">DNS 1</span>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<input type="text" name="d1" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{d1}"/>
|
<input type="text" name="d1" class="form-control sip" pattern="\d?\d?\d.\d?\d?\d.\d?\d?\d.\d?\d?\d" value="{d1}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-4 col-lg-5 form-group">
|
<div class="col-xl-4 col-lg-5 col-md-6 form-group">
|
||||||
<div class="input-group input-group-sm">
|
<div class="input-group input-group-sm">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">DNS 2</span>
|
<span class="input-group-text">DNS 2</span>
|
||||||
@@ -89,7 +89,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6 form-group">
|
||||||
|
<div class="input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Power saving</span>
|
||||||
|
</div>
|
||||||
|
<select name="z" class="form-control">
|
||||||
|
<option value="255">Default</option>
|
||||||
|
<option value="0" {z0}>Off</option>
|
||||||
|
<option value="1" {z1}>Minimum</option>
|
||||||
|
<option value="2" {z2}>Maximum</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
1
lib/ClassicUi/include/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
root/*.h
|
||||||
@@ -2,6 +2,7 @@ static const char HEADER_CACHE_CONTROL[] PROGMEM = "Cache-Control";
|
|||||||
static const char HEADER_PRAGMA[] PROGMEM = "Pragma";
|
static const char HEADER_PRAGMA[] PROGMEM = "Pragma";
|
||||||
static const char HEADER_EXPIRES[] PROGMEM = "Expires";
|
static const char HEADER_EXPIRES[] PROGMEM = "Expires";
|
||||||
static const char HEADER_AUTHENTICATE[] PROGMEM = "WWW-Authenticate";
|
static const char HEADER_AUTHENTICATE[] PROGMEM = "WWW-Authenticate";
|
||||||
|
static const char HEADER_LOCATION[] PROGMEM = "Location";
|
||||||
|
|
||||||
static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate";
|
static const char CACHE_CONTROL_NO_CACHE[] PROGMEM = "no-cache, no-store, must-revalidate";
|
||||||
static const char CACHE_1HR[] PROGMEM = "public, max-age=3600";
|
static const char CACHE_1HR[] PROGMEM = "public, max-age=3600";
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
#include "EnergyAccounting.h"
|
#include "EnergyAccounting.h"
|
||||||
#include "Uptime.h"
|
#include "Uptime.h"
|
||||||
#include "RemoteDebug.h"
|
#include "RemoteDebug.h"
|
||||||
#include "entsoe/EntsoeApi.h"
|
#include "EntsoeApi.h"
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
@@ -89,7 +89,7 @@ private:
|
|||||||
void configMqttHtml();
|
void configMqttHtml();
|
||||||
void configWebHtml();
|
void configWebHtml();
|
||||||
void configDomoticzHtml();
|
void configDomoticzHtml();
|
||||||
void configEntsoeHtml();
|
void configPriceApiHtml();
|
||||||
void configNtpHtml();
|
void configNtpHtml();
|
||||||
void configGpioHtml();
|
void configGpioHtml();
|
||||||
void configDebugHtml();
|
void configDebugHtml();
|
||||||
@@ -25,8 +25,8 @@ except:
|
|||||||
print("WARN: Unable to load minifier")
|
print("WARN: Unable to load minifier")
|
||||||
|
|
||||||
|
|
||||||
webroot = "web"
|
webroot = "lib/ClassicUi/html"
|
||||||
srcroot = "src/web/root"
|
srcroot = "lib/ClassicUi/include/root"
|
||||||
|
|
||||||
version = os.environ.get('GITHUB_TAG')
|
version = os.environ.get('GITHUB_TAG')
|
||||||
if version == None:
|
if version == None:
|
||||||
1
lib/DomoticzMqttHandler/include/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
json/*.h
|
||||||