Compare commits
357 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fb1d343ee3 | ||
|
|
1f3c32e80a | ||
|
|
43fbca7099 | ||
|
|
7a36082564 | ||
|
|
fb2cfdfe01 | ||
|
|
6c3dca9344 | ||
|
|
cce5d75fd7 | ||
|
|
8fd411c1d6 | ||
|
|
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 | ||
|
|
8ac1e034b1 | ||
|
|
f446dff865 | ||
|
|
e1b2554af2 | ||
|
|
627a50ab50 | ||
|
|
a20d007b45 | ||
|
|
64840e13f0 | ||
|
|
34ebe9601a | ||
|
|
72f1d59338 | ||
|
|
07ed425320 | ||
|
|
2e75e1c4dc | ||
|
|
e6df68481f | ||
|
|
fa299198fc | ||
|
|
6d81b0a856 | ||
|
|
dd095da97b | ||
|
|
1b6ce203b7 | ||
|
|
2850be4e48 | ||
|
|
7eca31de84 | ||
|
|
a64f960cc7 | ||
|
|
ce3a47a7e6 | ||
|
|
8395e1dc77 | ||
|
|
39a4761415 | ||
|
|
dc25c147b9 | ||
|
|
867ab9d6c2 | ||
|
|
6a76144566 | ||
|
|
5e03e3d3c2 | ||
|
|
adb5050621 | ||
|
|
026cd25c8c | ||
|
|
06ec97b42a | ||
|
|
b420a0e6f4 | ||
|
|
7cd52d5689 | ||
|
|
ad78ff3082 | ||
|
|
fe7be81f1e | ||
|
|
7674fc2ad0 | ||
|
|
d50181c347 | ||
|
|
8ca771fa5a | ||
|
|
7d557b2679 | ||
|
|
2f0c912388 | ||
|
|
57e6d0fbe3 | ||
|
|
e7c25fafda | ||
|
|
2a4772fe25 | ||
|
|
f1f7408208 | ||
|
|
feb8e5007b | ||
|
|
c4af1ee74f | ||
|
|
992e1b6121 | ||
|
|
95d3008a66 | ||
|
|
04cd6ac387 | ||
|
|
584c7b1154 | ||
|
|
493c4b4337 | ||
|
|
488c969858 | ||
|
|
8b0d4185d3 | ||
|
|
9cc7529934 | ||
|
|
ef8715be6d | ||
|
|
e232b875fa | ||
|
|
f18171fecc | ||
|
|
a3c7a09211 | ||
|
|
a6f3bc3f71 | ||
|
|
44bcd386d1 | ||
|
|
01547f9a52 | ||
|
|
608470c5f7 | ||
|
|
940d38af5c | ||
|
|
4e451c51e1 | ||
|
|
43def1c311 | ||
|
|
2978116207 | ||
|
|
a055465ce0 | ||
|
|
68b3415a6c | ||
|
|
d8f3ae8b07 | ||
|
|
998b986604 | ||
|
|
7799431405 | ||
|
|
1a92cd1978 | ||
|
|
508c14a671 | ||
|
|
4a7ef87269 | ||
|
|
3a4fc707b0 | ||
|
|
5d2e320b07 | ||
|
|
d12613b91a | ||
|
|
e6a02f34ab | ||
|
|
0b2ffbfd77 | ||
|
|
cab6c54ed9 | ||
|
|
313024f273 | ||
|
|
91fc078c5e | ||
|
|
5b9d44a3e9 | ||
|
|
ed523bda24 | ||
|
|
e3a1a242d2 | ||
|
|
ddfade65d8 | ||
|
|
0ef8390df0 | ||
|
|
f43fe5f864 | ||
|
|
f9ddd7533a | ||
|
|
f9f18bc106 | ||
|
|
280dd8605b | ||
|
|
41324cf590 | ||
|
|
64132d5ce3 | ||
|
|
0e75732022 | ||
|
|
6975714922 | ||
|
|
7f3e0e6089 | ||
|
|
6ff5518738 | ||
|
|
be29daee77 | ||
|
|
a90ed40aee | ||
|
|
32ba6c31f0 | ||
|
|
caf00f99e3 | ||
|
|
aaa318e511 | ||
|
|
648cac0b06 | ||
|
|
a5d1a2c0ee | ||
|
|
55f1b4b129 | ||
|
|
b805363c60 | ||
|
|
846b166ae9 | ||
|
|
4e039c2cc9 | ||
|
|
e5556fe80b | ||
|
|
c5aa65a780 | ||
|
|
30cf1435da | ||
|
|
fca46a3f54 | ||
|
|
0dca85d67b | ||
|
|
d9a5a21fe0 | ||
|
|
68eaa7d39b | ||
|
|
3231d0747e | ||
|
|
2617956b38 | ||
|
|
07614226b3 | ||
|
|
cddb170f24 | ||
|
|
ba7915ca7c | ||
|
|
ee12db4f51 | ||
|
|
f01fbfca53 | ||
|
|
fab637cf60 | ||
|
|
b2e144efcf | ||
|
|
10308ce738 | ||
|
|
70f5b0f912 | ||
|
|
d724a90085 | ||
|
|
1ab529785a | ||
|
|
3a81e62bbe | ||
|
|
4882916b5c | ||
|
|
1f7e43256a | ||
|
|
a0d3632fd7 | ||
|
|
b25564a89f | ||
|
|
191d9fa562 | ||
|
|
e009b4e54e | ||
|
|
811625b706 | ||
|
|
15fa452c7c | ||
|
|
e725c01597 | ||
|
|
35b884713c | ||
|
|
d5fc9f6fc6 | ||
|
|
19c8396b1c | ||
|
|
f4622a068b | ||
|
|
9922862299 | ||
|
|
e7fc504975 | ||
|
|
6cdb943763 | ||
|
|
3e937a4e5d | ||
|
|
fcd3e3ca25 | ||
|
|
772004c0a2 | ||
|
|
c3e5ce344c | ||
|
|
b11b1d5e37 | ||
|
|
b5d34990df | ||
|
|
a287d310ac | ||
|
|
afe6190c46 | ||
|
|
2125945728 | ||
|
|
fb60127cf7 | ||
|
|
a07c55889f | ||
|
|
a675f56f9c | ||
|
|
0590ec375d | ||
|
|
48bd352619 | ||
|
|
40016f314e | ||
|
|
b9234f6f64 | ||
|
|
beafcd300b | ||
|
|
a92524eaf8 | ||
|
|
a60dd8a60a | ||
|
|
53296ccf42 | ||
|
|
42a627e32e | ||
|
|
c38034c69b | ||
|
|
0ec1a8ece3 | ||
|
|
45275c271e | ||
|
|
116761b46e | ||
|
|
a2c13fd0da | ||
|
|
b727f84c72 | ||
|
|
3706625760 | ||
|
|
0e1d2211ec | ||
|
|
785bec0269 | ||
|
|
2a4a199ae6 | ||
|
|
b6b9db5431 | ||
|
|
55bdd4437a | ||
|
|
3948fff184 | ||
|
|
c4b099b752 | ||
|
|
5cfcc015f4 | ||
|
|
724768afc4 | ||
|
|
efc20f1da9 | ||
|
|
b071344871 | ||
|
|
e0e98f0ec1 | ||
|
|
53d34852f1 | ||
|
|
c26073b2a3 | ||
|
|
b12a632618 | ||
|
|
420be1b943 | ||
|
|
142d280805 | ||
|
|
196b79e4c8 | ||
|
|
2ef1700cfe | ||
|
|
cbbb52d32a | ||
|
|
6bded12ec5 | ||
|
|
5ae56f265e | ||
|
|
705b3e34d1 | ||
|
|
fcb4ccb462 | ||
|
|
e0cd14e904 | ||
|
|
bb6e8838b4 | ||
|
|
5325f8f845 | ||
|
|
113b8bf820 | ||
|
|
7e41168606 | ||
|
|
0af2378d05 | ||
|
|
7f4498c062 | ||
|
|
6e9e988ff0 | ||
|
|
1f03013c98 | ||
|
|
6690e809fb | ||
|
|
b41dd862b6 | ||
|
|
04c269d982 | ||
|
|
f8a86058a1 | ||
|
|
47dda366e3 | ||
|
|
0700d22d43 | ||
|
|
bf633f20c4 | ||
|
|
297681bcff | ||
|
|
68906b54a6 | ||
|
|
0c1d666afd | ||
|
|
18a38e4104 | ||
|
|
ef0041caa6 | ||
|
|
1ce51f6c85 | ||
|
|
c23b2a477e | ||
|
|
0dd77dbaa8 | ||
|
|
29524c2123 | ||
|
|
e2fb5e2673 | ||
|
|
751a0edca7 | ||
|
|
a8e62e086c | ||
|
|
35eb69bebb | ||
|
|
5c7c0699b2 | ||
|
|
460482a6dc | ||
|
|
28db4873a0 | ||
|
|
98de734761 | ||
|
|
b742c8f3c6 | ||
|
|
4cfd274e52 | ||
|
|
4f7bd0436a | ||
|
|
7e31a60000 | ||
|
|
793bc877fc | ||
|
|
5ab6de21dc | ||
|
|
7c5a5bcf65 | ||
|
|
2e203d7713 | ||
|
|
db5e242ad8 | ||
|
|
5be921a342 | ||
|
|
ddd24b20aa | ||
|
|
7c1ee20e7b | ||
|
|
5f0adc0f10 | ||
|
|
244f78ad1a | ||
|
|
9066af8dc7 | ||
|
|
5cfb58c2e6 | ||
|
|
fb8d9e51a6 | ||
|
|
77ce5d8e90 | ||
|
|
8c69f9a738 | ||
|
|
dd87d70876 | ||
|
|
52992f09ee | ||
|
|
e8a56d5fc7 | ||
|
|
6aa02d54c8 | ||
|
|
9dbf9137c7 | ||
|
|
c0a9a01b41 | ||
|
|
7b203b196f | ||
|
|
a72f02a779 | ||
|
|
50c06e2cfe | ||
|
|
e4d4753181 | ||
|
|
04daf551fb | ||
|
|
4b51f0f235 | ||
|
|
5e4ccca663 | ||
|
|
6b0ec39759 | ||
|
|
1f7d845a32 | ||
|
|
6de5b719f3 | ||
|
|
f6d2bef285 | ||
|
|
c444a108a5 | ||
|
|
586c0cba25 | ||
|
|
18bc6753db | ||
|
|
b79e6112b1 | ||
|
|
2e4e4328f2 | ||
|
|
03089e92cb | ||
|
|
86939d4890 | ||
|
|
d7d25083dc | ||
|
|
92e8beadc0 |
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
custom: ["https://paypal.me/gskjold"]
|
||||||
6
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -24,16 +24,20 @@ A clear description of what you expected to happen.
|
|||||||
If applicable, add screenshots to help explain your problem.
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Hardware information:**
|
**Hardware information:**
|
||||||
|
- Country: [e.g. Norway]
|
||||||
- Meter: [e.g. Aidon]
|
- Meter: [e.g. Aidon]
|
||||||
|
- Encryption enabled [yes/no]
|
||||||
- AMS reader: [e.g. Pow-U, ESP32 etc]
|
- AMS reader: [e.g. Pow-U, ESP32 etc]
|
||||||
- M-bus adapter (if applicable):
|
- M-bus adapter (if applicable):
|
||||||
|
|
||||||
**Relevant firmware information:**
|
**Relevant firmware information:**
|
||||||
- Version: [e.g. 1.5.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]
|
||||||
|
- ENTSO-E API enabled: [yes/no]
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
7
.github/ISSUE_TEMPLATE/support.md
vendored
@@ -11,12 +11,17 @@ assignees: ''
|
|||||||
A clear and concise description of what the problem is.
|
A clear and concise description of what the problem is.
|
||||||
|
|
||||||
**Hardware information:**
|
**Hardware information:**
|
||||||
|
- Country: [e.g. Norway]
|
||||||
- Meter: [e.g. Aidon]
|
- Meter: [e.g. Aidon]
|
||||||
|
- Encryption enabled [yes/no]
|
||||||
- AMS reader: [e.g. Pow-U, ESP32 etc]
|
- AMS reader: [e.g. Pow-U, ESP32 etc]
|
||||||
- M-bus adapter (if applicable):
|
- M-bus adapter (if applicable):
|
||||||
|
|
||||||
**Relevant firmware information:**
|
**Relevant firmware information:**
|
||||||
- Version: [e.g. 1.5.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]
|
||||||
- Temperature sensors [e.g. 3xDS18B20]
|
- Temperature sensors [e.g. 3xDS18B20]
|
||||||
|
- ENTSO-E API enabled: [yes/no]
|
||||||
|
|||||||
25
.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:
|
||||||
@@ -32,16 +39,26 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ~/.pio/libdeps
|
path: ~/.pio/libdeps
|
||||||
key: ${{ runner.os }}-pio-${{ hashFiles('platformio.ini') }}
|
key: ${{ runner.os }}-pio-${{ hashFiles('platformio.ini') }}
|
||||||
- name: Set up Python 3.7
|
- name: Set up Python 3.9
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.9
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
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: Configure build targets
|
- name: Set up node
|
||||||
run: echo "[platformio]\ndefault_envs = esp8266, esp32" > platformio-user.ini
|
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
|
||||||
|
|||||||
87
.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:
|
||||||
@@ -33,18 +39,47 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ~/.pio/libdeps
|
path: ~/.pio/libdeps
|
||||||
key: ${{ runner.os }}-pio-${{ hashFiles('platformio.ini') }}
|
key: ${{ runner.os }}-pio-${{ hashFiles('platformio.ini') }}
|
||||||
- name: Set up Python 3.7
|
- name: Set up Python 3.9
|
||||||
uses: actions/setup-python@v1
|
uses: actions/setup-python@v1
|
||||||
with:
|
with:
|
||||||
python-version: 3.7
|
python-version: 3.9
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
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
|
- name: Build ESP8266 firmware
|
||||||
run: pio run
|
run: pio run -e esp8266
|
||||||
|
- name: Create ESP8266 zip file
|
||||||
|
run: /bin/sh scripts/esp8266/mkzip.sh
|
||||||
|
- name: Build ESP32 firmware
|
||||||
|
run: pio run -e esp32
|
||||||
|
- name: Create ESP32 zip file
|
||||||
|
run: /bin/sh scripts/esp32/mkzip.sh
|
||||||
|
- name: Build ESP32-S2 firmware
|
||||||
|
run: pio run -e esp32s2
|
||||||
|
- name: Create ESP32-S2 zip file
|
||||||
|
run: /bin/sh scripts/esp32s2/mkzip.sh
|
||||||
|
- name: Build ESP32-SOLO firmware
|
||||||
|
run: pio run -e esp32solo
|
||||||
|
- name: Create ESP32-SOLO zip file
|
||||||
|
run: /bin/sh scripts/esp32solo/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
|
||||||
@@ -55,6 +90,35 @@ jobs:
|
|||||||
release_name: Release ${{ github.ref }}
|
release_name: Release ${{ github.ref }}
|
||||||
draft: false
|
draft: false
|
||||||
prerelease: false
|
prerelease: false
|
||||||
|
|
||||||
|
- name: Upload esp8266 zip 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: esp8266.zip
|
||||||
|
asset_name: ams2mqtt-esp8266-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
- name: Upload esp32 zip 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: esp32.zip
|
||||||
|
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
- name: Upload esp32s2 zip 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: esp32s2.zip
|
||||||
|
asset_name: ams2mqtt-esp32s2-${{ steps.release_tag.outputs.tag }}.zip
|
||||||
|
asset_content_type: application/zip
|
||||||
|
|
||||||
- name: Upload esp8266 binary to release
|
- name: Upload esp8266 binary to release
|
||||||
uses: actions/upload-release-asset@v1
|
uses: actions/upload-release-asset@v1
|
||||||
env:
|
env:
|
||||||
@@ -73,12 +137,21 @@ jobs:
|
|||||||
asset_path: .pio/build/esp32/firmware.bin
|
asset_path: .pio/build/esp32/firmware.bin
|
||||||
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp32-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
asset_content_type: application/octet-stream
|
asset_content_type: application/octet-stream
|
||||||
- name: Upload esp32 partitions to release
|
- name: Upload esp32solo binary 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/esp32/partitions.bin
|
asset_path: .pio/build/esp32solo/firmware.bin
|
||||||
asset_name: ams2mqtt-esp32-partitions-${{ steps.release_tag.outputs.tag }}.bin
|
asset_name: ams2mqtt-esp32solo-${{ steps.release_tag.outputs.tag }}.bin
|
||||||
|
asset_content_type: application/octet-stream
|
||||||
|
- 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
|
asset_content_type: application/octet-stream
|
||||||
|
|||||||
6
.gitignore
vendored
@@ -7,10 +7,14 @@
|
|||||||
.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
|
||||||
/web/test.html
|
/web/test.html
|
||||||
/sdkconfig
|
/sdkconfig
|
||||||
/.tmp
|
/.tmp
|
||||||
|
/*.zip
|
||||||
|
node_modules
|
||||||
|
/gui/dist
|
||||||
|
/scripts/*dev
|
||||||
|
|||||||
617
LICENSE
Normal file
@@ -0,0 +1,617 @@
|
|||||||
|
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 19 November 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU Affero General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works, specifically designed to ensure
|
||||||
|
cooperation with the community in the case of network server software.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
our General Public Licenses are intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
Developers that use our General Public Licenses protect your rights
|
||||||
|
with two steps: (1) assert copyright on the software, and (2) offer
|
||||||
|
you this License which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
A secondary benefit of defending all users' freedom is that
|
||||||
|
improvements made in alternate versions of the program, if they
|
||||||
|
receive widespread use, become available for other developers to
|
||||||
|
incorporate. Many developers of free software are heartened and
|
||||||
|
encouraged by the resulting cooperation. However, in the case of
|
||||||
|
software used on network servers, this result may fail to come about.
|
||||||
|
The GNU General Public License permits making a modified version and
|
||||||
|
letting the public access it on a server without ever releasing its
|
||||||
|
source code to the public.
|
||||||
|
|
||||||
|
The GNU Affero General Public License is designed specifically to
|
||||||
|
ensure that, in such cases, the modified source code becomes available
|
||||||
|
to the community. It requires the operator of a network server to
|
||||||
|
provide the source code of the modified version running there to the
|
||||||
|
users of that server. Therefore, public use of a modified version, on
|
||||||
|
a publicly accessible server, gives the public access to the source
|
||||||
|
code of the modified version.
|
||||||
|
|
||||||
|
An older license, called the Affero General Public License and
|
||||||
|
published by Affero, was designed to accomplish similar goals. This is
|
||||||
|
a different license, not a version of the Affero GPL, but Affero has
|
||||||
|
released a new version of the Affero GPL which permits relicensing under
|
||||||
|
this license.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, if you modify the
|
||||||
|
Program, your modified version must prominently offer all users
|
||||||
|
interacting with it remotely through a computer network (if your version
|
||||||
|
supports such interaction) an opportunity to receive the Corresponding
|
||||||
|
Source of your version by providing access to the Corresponding Source
|
||||||
|
from a network server at no charge, through some standard or customary
|
||||||
|
means of facilitating copying of software. This Corresponding Source
|
||||||
|
shall include the Corresponding Source for any work covered by version 3
|
||||||
|
of the GNU General Public License that is incorporated pursuant to the
|
||||||
|
following paragraph.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the work with which it is combined will remain governed by version
|
||||||
|
3 of the GNU General Public License.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU Affero General Public License from time to time. Such new versions
|
||||||
|
will be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU Affero General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU Affero General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU Affero General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
1.1.2.8.0.255 - Active- Energy
|
1.1.2.8.0.255 - Active- Energy
|
||||||
1.1.3.8.0.255 - Reactive+ Energy
|
1.1.3.8.0.255 - Reactive+ Energy
|
||||||
1.1.4.8.0.255 - Reactive- Energy
|
1.1.4.8.0.255 - Reactive- Energy
|
||||||
1.1.0.0.1.255 - Electricity ID?
|
1.1.0.0.1.255 - Meter number 1
|
||||||
1.1.1.7.0.255 - Active+ Instantaneous value
|
1.1.1.7.0.255 - Active+ Instantaneous value
|
||||||
1.1.2.7.0.255 - Active- Instantaneous value
|
1.1.2.7.0.255 - Active- Instantaneous value
|
||||||
1.1.3.7.0.255 - Reactive+ Instantaneous value
|
1.1.3.7.0.255 - Reactive+ Instantaneous value
|
||||||
|
|||||||
BIN
doc/Germany/Anleitung_M-Bus_Protokoll_V1.0.pdf
Normal file
BIN
doc/M-Bus_DOC48.PDF
Normal file
BIN
doc/Switzerland/RWB_SmartMeter_Bedienungsanleitung.pdf
Normal file
BIN
doc/omnipower.technical.description.pdf
Normal file
51
frames/Kamstrup-1p.raw
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
7E A0 BA 2B 21 13 ED AA E6 E7 00 0F 00 00 00 00
|
||||||
|
0C 07 E6 02 05 06 0D 00 0A FF 80 00 00
|
||||||
|
02 19
|
||||||
|
0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31
|
||||||
|
09 06 01 01 00 00 05 FF 0A 10 35 37 30 36 35 36 37 32 37 31 35 33 33 32 30 37
|
||||||
|
09 06 01 01 60 01 01 FF 0A 12 36 38 36 31 31 31 31 42 4E 32 34 32 31 30 31 30 34 30
|
||||||
|
09 06 01 01 01 07 00 FF 06 00 00 02 68
|
||||||
|
09 06 01 01 02 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 07 00 FF 06 00 00 00 53
|
||||||
|
09 06 01 01 04 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 1F 07 00 FF 06 00 00 01 22
|
||||||
|
00 00 00 00
|
||||||
|
09 06 01 01 20 07 00 FF 12 00 E2
|
||||||
|
00 00 00 00
|
||||||
|
05 D8 7E
|
||||||
|
|
||||||
|
7E A0 BA 2B 21 13 ED AA E6 E7 00 0F 00 00 00 00
|
||||||
|
0C 07 E6 02 05 06 0D 00 14 FF 80 00 00
|
||||||
|
02 19
|
||||||
|
0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31
|
||||||
|
09 06 01 01 00 00 05 FF 0A 10 35 37 30 36 35 36 37 32 37 31 35 33 33 32 30 37
|
||||||
|
09 06 01 01 60 01 01 FF 0A 12 36 38 36 31 31 31 31 42 4E 32 34 32 31 30 31 30 34 30
|
||||||
|
09 06 01 01 01 07 00 FF 06 00 00 02 68
|
||||||
|
09 06 01 01 02 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 07 00 FF 06 00 00 00 53
|
||||||
|
09 06 01 01 04 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 1F 07 00 FF 06 00 00 01 23
|
||||||
|
00 00 00 00
|
||||||
|
09 06 01 01 20 07 00 FF 12 00 E1
|
||||||
|
00 00 00 00
|
||||||
|
8E 5E 7E
|
||||||
|
|
||||||
|
7E A1 04 2B 21 13 77 6E E6 E7 00 0F 00 00 00 00
|
||||||
|
0C 07 E6 02 05 06 0D 00 19 FF 80 00 00
|
||||||
|
02 23 0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31
|
||||||
|
09 06 01 01 00 00 05 FF 0A 10 35 37 30 36 35 36 37 32 37 31 35 33 33 32 30 37
|
||||||
|
09 06 01 01 60 01 01 FF 0A 12 36 38 36 31 31 31 31 42 4E 32 34 32 31 30 31 30 34 30
|
||||||
|
09 06 01 01 01 07 00 FF 06 00 00 02 6B
|
||||||
|
09 06 01 01 02 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 07 00 FF 06 00 00 00 54
|
||||||
|
09 06 01 01 04 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 1F 07 00 FF 06 00 00 01 25
|
||||||
|
00 00 00 00
|
||||||
|
09 06 01 01 20 07 00 FF 12 00 E1
|
||||||
|
00 00 00 00
|
||||||
|
09 06 00 01 01 00 00 FF 09 0C 07 E6 02 05 06 0D 00 19 FF 80 00 00
|
||||||
|
09 06 01 01 01 08 00 FF 06 00 12 CF 93
|
||||||
|
09 06 01 01 02 08 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 08 00 FF 06 00 00 8C CE
|
||||||
|
09 06 01 01 04 08 00 FF 06 00 05 E5 04
|
||||||
|
7F E9 7E
|
||||||
23
frames/Kamstrup-Sweden.raw
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
7E A1 2C 2B 21 13 FC 04 E6 E7 00 0F 00 00 00 00
|
||||||
|
0C 07 E6 02 12 05 16 00 23 FF 80 00 00
|
||||||
|
02 23
|
||||||
|
0A 0E 4B 61 6D 73 74 72 75 70 5F 56 30 30 30 31
|
||||||
|
09 06 01 01 00 00 05 FF 0A 10 35 37 30 36 35 36 37 33 33 31 33 32 33 35 32 36
|
||||||
|
09 06 01 01 60 01 01 FF 0A 12 36 38 34 31 31 33 31 42 4E 32 34 35 31 30 31 30 39 32
|
||||||
|
09 06 01 01 01 07 00 FF 06 00 00 08 DD
|
||||||
|
09 06 01 01 02 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 07 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 04 07 00 FF 06 00 00 01 90
|
||||||
|
09 06 01 01 1F 07 00 FF 06 00 00 01 1F
|
||||||
|
09 06 01 01 33 07 00 FF 06 00 00 02 57
|
||||||
|
09 06 01 01 47 07 00 FF 06 00 00 00 6A
|
||||||
|
09 06 01 01 20 07 00 FF 12 00 F1
|
||||||
|
09 06 01 01 34 07 00 FF 12 00 F0
|
||||||
|
09 06 01 01 48 07 00 FF 12 00 F3
|
||||||
|
09 06 00 01 01 00 00 FF 09 0C 07 E6 02 12 05 16 00 23 FF 80 00 00
|
||||||
|
09 06 01 01 01 08 00 FF 06 01 E8 7F 4E
|
||||||
|
09 06 01 01 02 08 00 FF 06 00 00 00 00
|
||||||
|
09 06 01 01 03 08 00 FF 06 00 58 71 8B
|
||||||
|
09 06 01 01 04 08 00 FF 06 00 10 60 23
|
||||||
|
B8 1C
|
||||||
|
7E
|
||||||
@@ -6,7 +6,7 @@ DB // Encrypted
|
|||||||
08 4B 41 4D 45 01 AC 4D 6E // System title
|
08 4B 41 4D 45 01 AC 4D 6E // System title
|
||||||
82 // Prefix for 2-byte length
|
82 // Prefix for 2-byte length
|
||||||
01 D0 // Length 464
|
01 D0 // Length 464
|
||||||
30 // Security tag 0011 0000, 0=Compression off, 0=Unicast, 1=Encryption, 0=Authentication, 0000= Security Suite ID
|
30 // Security tag 0011 0000, 0=Compression off, 0=Unicast, 1=Encryption, 1=Authentication, 0000= Security Suite ID
|
||||||
00 00 A3 2F // Frame counter
|
00 00 A3 2F // Frame counter
|
||||||
|
|
||||||
// Decrypted frame below
|
// Decrypted frame below
|
||||||
|
|||||||
79
frames/lng.raw
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
7E // Flag
|
||||||
|
A08B
|
||||||
|
CEFF03
|
||||||
|
13
|
||||||
|
EEE1
|
||||||
|
E6E700
|
||||||
|
E0 // GBT (Green book 9.4.6.13)
|
||||||
|
40 // Block control 0100 0000, last block=no, streaming=yes, remainig=window
|
||||||
|
0001 // Block sequence
|
||||||
|
0000 // Block sequence ack
|
||||||
|
77 // How many bytes in this block
|
||||||
|
|
||||||
|
0F 00000DB7 // APDU tag, Invoke ID and priority
|
||||||
|
|
||||||
|
0C07E604020607220FFF800000 // Date and time
|
||||||
|
0205 // Structure with 5 items
|
||||||
|
0105 // Array with 5 items
|
||||||
|
020412002809060008190900FF0F02120000 // Structure with 4 items, uint16, OBIS, int8, uint16 (0-8:25.9.0;2)
|
||||||
|
020412002809060008190900FF0F01120000 // Structure with 4 items, uint16, OBIS, int8, uint16 (0-8:25.9.0;1)
|
||||||
|
020412000109060000600101FF0F02120000 // Structure with 4 items, uint16, OBIS, int8, uint16 (96.1.1 - Meter model)
|
||||||
|
020412000309060100010700FF0F02120000 // Structure with 4 items, uint16, OBIS, int8, uint16 (1.7.0 Active import)
|
||||||
|
020412000309060100020700FF0F02120000 // Structure with 4 items, uint16, OBIS, int8, uint16 (2.7.0 Active export)
|
||||||
|
09060008190900 // OBIS 0-8:25.9.0 Object list push settings consumer information 1
|
||||||
|
ABA6
|
||||||
|
7E
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
7E
|
||||||
|
A024
|
||||||
|
CEFF03
|
||||||
|
13
|
||||||
|
D661
|
||||||
|
E0 // GBT
|
||||||
|
C0 // Block control 0100 0000, last block=yes, streaming=yes, remainig=window
|
||||||
|
0002 // Block sequence
|
||||||
|
0000 // Block sequence ack
|
||||||
|
13 // How many bytes in this block
|
||||||
|
|
||||||
|
FF // Last byte of OBIS in previous block
|
||||||
|
0906363031313039 // Device ID
|
||||||
|
0600000028 // Accumulated import
|
||||||
|
0600000000 // Accumulated export
|
||||||
|
8BA4
|
||||||
|
7E
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
7E A1 23 CE FF 03 13 21 55 E6 E7 00
|
||||||
|
|
||||||
|
0F 00 00 08 E2
|
||||||
|
0C 07 E5 07 13 01 0C 1A 0A FF 80 00 00
|
||||||
|
|
||||||
|
02 0B // 11
|
||||||
|
01 0B // 11
|
||||||
|
02 04 12 00 28 09 06 00 08 19 09 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 28 09 06 00 08 19 09 00 FF 0F 01 12 00 00
|
||||||
|
02 04 12 00 01 09 06 00 00 60 01 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 00 01 07 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 00 02 07 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 01 08 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 02 08 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 05 08 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 06 08 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 07 08 00 FF 0F 02 12 00 00
|
||||||
|
02 04 12 00 03 09 06 01 01 08 08 00 FF 0F 02 12 00 00
|
||||||
|
09 06 00 08 19 09 00 FF
|
||||||
|
09 08 34 33 30 39 34 33 35 31
|
||||||
|
06 00 00 00 0B
|
||||||
|
06 00 00 00 00
|
||||||
|
06 00 00 00 10
|
||||||
|
06 00 00 00 04
|
||||||
|
06 00 00 00 00
|
||||||
|
06 00 00 00 08
|
||||||
|
06 00 00 00 00
|
||||||
|
06 00 00 00 01
|
||||||
|
7C 8B
|
||||||
|
7E
|
||||||
34
hardware/wemos_mbus_shield/README.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
## Wemos shield
|
||||||
|
|
||||||
|
Fits D1 mini and S2 mini.
|
||||||
|
|
||||||
|
<img src="img1.jpg"/>
|
||||||
|
<img src="img2.jpg"/>
|
||||||
|
|
||||||
|
**WARNING** Not properly tested
|
||||||
|
|
||||||
|
**Resistors**
|
||||||
|
- R1: 470 (for U1)
|
||||||
|
- R2: 220 (for U1)
|
||||||
|
- R3: 82k (for U1)
|
||||||
|
- R4: 220 (for U1)
|
||||||
|
- R5: 100k (for U1)
|
||||||
|
- R6: 10k (for AP button)
|
||||||
|
- R7: 4.7k (for DS18B20)
|
||||||
|
- R8-R10: 1k (for RGB LED)
|
||||||
|
|
||||||
|
**Capacitors**
|
||||||
|
- C1: 100n (for U1)
|
||||||
|
- C2: 1u (for U1)
|
||||||
|
- C3: 100n (for U1)
|
||||||
|
|
||||||
|
**Other components**
|
||||||
|
- U1: TSS521 or TSS721
|
||||||
|
- U2: DS18B20 (Digital temperature sensor)
|
||||||
|
- D1: RGB LED
|
||||||
|
- J1: RJ45
|
||||||
|
- SW1: AP button (to D3 GPIO0)
|
||||||
|
|
||||||
|
**Jumper**
|
||||||
|
- JP1 & JP4: Jump these to receive power (5V) via RJ45 on pin 7 (GND) and 8 (+5)
|
||||||
|
- JP2 & JP3: Jump these to attach DS18B20 sensors via RJ45 on pin 4 (Data) and pin 5 (GND)
|
||||||
BIN
hardware/wemos_mbus_shield/img1.jpg
Normal file
|
After Width: | Height: | Size: 237 KiB |
BIN
hardware/wemos_mbus_shield/img2.jpg
Normal file
|
After Width: | Height: | Size: 296 KiB |
3
hardware/wemos_mbus_shield/kicad/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
gerber
|
||||||
|
rescue-backup
|
||||||
|
*-bak
|
||||||
326
hardware/wemos_mbus_shield/kicad/d1_mini_shield-cache.lib
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
EESchema-LIBRARY Version 2.4
|
||||||
|
#encoding utf-8
|
||||||
|
#
|
||||||
|
# Connector_RJ45
|
||||||
|
#
|
||||||
|
DEF Connector_RJ45 J 0 40 Y Y 1 F N
|
||||||
|
F0 "J" -200 550 50 H V R CNN
|
||||||
|
F1 "Connector_RJ45" 100 550 50 H V L CNN
|
||||||
|
F2 "" 0 25 50 V I C CNN
|
||||||
|
F3 "" 0 25 50 V I C CNN
|
||||||
|
ALIAS RJ31 RJ32 RJ33 RJ34 RJ35 RJ41 RJ45 RJ49 RJ61
|
||||||
|
$FPLIST
|
||||||
|
8P8C*
|
||||||
|
RJ31*
|
||||||
|
RJ32*
|
||||||
|
RJ33*
|
||||||
|
RJ34*
|
||||||
|
RJ35*
|
||||||
|
RJ41*
|
||||||
|
RJ45*
|
||||||
|
RJ49*
|
||||||
|
RJ61*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S 300 500 -300 -400 0 1 10 f
|
||||||
|
P 2 0 1 0 -200 175 -250 175 N
|
||||||
|
P 2 0 1 0 -200 225 -250 225 N
|
||||||
|
P 3 0 1 0 -250 -125 -200 -125 -200 -125 N
|
||||||
|
P 3 0 1 0 -250 -75 -200 -75 -200 -75 N
|
||||||
|
P 3 0 1 0 -250 -25 -200 -25 -200 -25 N
|
||||||
|
P 3 0 1 0 -250 25 -200 25 -200 25 N
|
||||||
|
P 3 0 1 0 -250 75 -200 75 -200 75 N
|
||||||
|
P 3 0 1 0 -200 125 -250 125 -250 125 N
|
||||||
|
P 14 0 1 0 -250 -175 -250 275 150 275 150 175 200 175 200 125 250 125 250 -25 200 -25 200 -75 150 -75 150 -175 -250 -175 -250 -175 N
|
||||||
|
X ~ 1 400 -300 100 L 50 50 1 1 P
|
||||||
|
X ~ 2 400 -200 100 L 50 50 1 1 P
|
||||||
|
X ~ 3 400 -100 100 L 50 50 1 1 P
|
||||||
|
X ~ 4 400 0 100 L 50 50 1 1 P
|
||||||
|
X ~ 5 400 100 100 L 50 50 1 1 P
|
||||||
|
X ~ 6 400 200 100 L 50 50 1 1 P
|
||||||
|
X ~ 7 400 300 100 L 50 50 1 1 P
|
||||||
|
X ~ 8 400 400 100 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_C
|
||||||
|
#
|
||||||
|
DEF Device_C C 0 10 N Y 1 F N
|
||||||
|
F0 "C" 25 100 50 H V L CNN
|
||||||
|
F1 "Device_C" 25 -100 50 H V L CNN
|
||||||
|
F2 "" 38 -150 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
C_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
P 2 0 1 20 -80 -30 80 -30 N
|
||||||
|
P 2 0 1 20 -80 30 80 30 N
|
||||||
|
X ~ 1 0 150 110 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 110 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_Jumper
|
||||||
|
#
|
||||||
|
DEF Device_Jumper JP 0 30 Y N 1 F N
|
||||||
|
F0 "JP" 0 150 50 H V C CNN
|
||||||
|
F1 "Device_Jumper" 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
|
||||||
|
A 0 -26 125 1426 373 0 1 0 N -98 50 99 50
|
||||||
|
C -100 0 35 0 1 0 N
|
||||||
|
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
|
||||||
|
#
|
||||||
|
# Device_LED_RGB
|
||||||
|
#
|
||||||
|
DEF Device_LED_RGB D 0 0 Y N 1 F N
|
||||||
|
F0 "D" 0 370 50 H V C CNN
|
||||||
|
F1 "Device_LED_RGB" 0 -350 50 H V C CNN
|
||||||
|
F2 "" 0 -50 50 H I C CNN
|
||||||
|
F3 "" 0 -50 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
LED*
|
||||||
|
LED_SMD:*
|
||||||
|
LED_THT:*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
T 0 -75 -250 50 0 0 0 B Normal 0 C C
|
||||||
|
T 0 -75 -50 50 0 0 0 G Normal 0 C C
|
||||||
|
T 0 -75 150 50 0 0 0 R Normal 0 C C
|
||||||
|
S 50 -50 50 50 0 1 0 N
|
||||||
|
S 50 50 50 50 0 1 0 N
|
||||||
|
S 50 150 50 250 0 1 0 N
|
||||||
|
S 50 250 50 250 0 1 0 N
|
||||||
|
S 110 330 -110 -300 0 1 10 f
|
||||||
|
P 2 0 1 0 -50 -200 -100 -200 N
|
||||||
|
P 2 0 1 0 -50 -200 50 -200 N
|
||||||
|
P 2 0 1 0 -50 -150 -50 -250 N
|
||||||
|
P 2 0 1 8 -50 -150 -50 -250 N
|
||||||
|
P 2 0 1 0 -50 0 -100 0 N
|
||||||
|
P 2 0 1 8 -50 50 -50 -50 N
|
||||||
|
P 2 0 1 0 -50 200 -100 200 N
|
||||||
|
P 2 0 1 0 -50 200 50 200 N
|
||||||
|
P 2 0 1 8 -50 250 -50 150 N
|
||||||
|
P 2 0 1 0 50 -200 100 -200 N
|
||||||
|
P 2 0 1 0 50 0 -50 0 N
|
||||||
|
P 2 0 1 0 50 0 100 0 N
|
||||||
|
P 2 0 1 0 50 200 100 200 N
|
||||||
|
P 3 0 1 0 -50 50 -50 -50 -50 -50 N
|
||||||
|
P 3 0 1 0 -50 250 -50 150 -50 150 N
|
||||||
|
P 4 0 1 8 50 -150 50 -250 -50 -200 50 -150 N
|
||||||
|
P 4 0 1 8 50 50 50 -50 -50 0 50 50 N
|
||||||
|
P 4 0 1 8 50 250 50 150 -50 200 50 250 N
|
||||||
|
P 5 0 1 0 -40 -150 20 -90 -10 -90 20 -90 20 -120 N
|
||||||
|
P 5 0 1 0 -40 50 20 110 -10 110 20 110 20 80 N
|
||||||
|
P 5 0 1 0 -40 250 20 310 -10 310 20 310 20 280 N
|
||||||
|
P 5 0 1 0 0 -150 60 -90 30 -90 60 -90 60 -120 N
|
||||||
|
P 5 0 1 0 0 50 60 110 30 110 60 110 60 80 N
|
||||||
|
P 5 0 1 0 0 250 60 310 30 310 60 310 60 280 N
|
||||||
|
X RK 1 -200 200 100 R 50 50 1 1 P
|
||||||
|
X GK 2 -200 0 100 R 50 50 1 1 P
|
||||||
|
X BK 3 -200 -200 100 R 50 50 1 1 P
|
||||||
|
X BA 4 200 -200 100 L 50 50 1 1 P
|
||||||
|
X GA 5 200 0 100 L 50 50 1 1 P
|
||||||
|
X RA 6 200 200 100 L 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Device_R
|
||||||
|
#
|
||||||
|
DEF Device_R R 0 0 N Y 1 F N
|
||||||
|
F0 "R" 80 0 50 V V C CNN
|
||||||
|
F1 "Device_R" 0 0 50 V V C CNN
|
||||||
|
F2 "" -70 0 50 V I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
$FPLIST
|
||||||
|
R_*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -40 -100 40 100 0 1 10 N
|
||||||
|
X ~ 1 0 150 50 D 50 50 1 1 P
|
||||||
|
X ~ 2 0 -150 50 U 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Sensor_Temperature_DS18B20
|
||||||
|
#
|
||||||
|
DEF Sensor_Temperature_DS18B20 U 0 40 Y Y 1 F N
|
||||||
|
F0 "U" -150 250 50 H V C CNN
|
||||||
|
F1 "Sensor_Temperature_DS18B20" 250 250 50 H V C CNN
|
||||||
|
F2 "Package_TO_SOT_THT:TO-92_Inline" -1000 -250 50 H I C CNN
|
||||||
|
F3 "" -150 250 50 H I C CNN
|
||||||
|
ALIAS DS1822 DS18B20 DS18S20 DS1821C
|
||||||
|
$FPLIST
|
||||||
|
TO*92*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
A -130 125 25 1 1799 0 1 10 N -105 125 -155 125
|
||||||
|
C -130 -100 50 0 1 10 F
|
||||||
|
S -200 200 200 -200 0 1 10 f
|
||||||
|
S -105 -75 -155 0 0 1 10 F
|
||||||
|
P 2 0 1 10 -155 25 -130 25 N
|
||||||
|
P 2 0 1 10 -155 50 -130 50 N
|
||||||
|
P 2 0 1 10 -155 75 -130 75 N
|
||||||
|
P 2 0 1 10 -155 100 -130 100 N
|
||||||
|
P 2 0 1 10 -155 125 -155 0 N
|
||||||
|
P 2 0 1 10 -155 125 -130 125 N
|
||||||
|
P 2 0 1 10 -105 125 -105 0 N
|
||||||
|
X GND 1 0 -300 100 U 50 50 1 1 W
|
||||||
|
X DQ 2 300 0 100 L 50 50 1 1 B
|
||||||
|
X VDD 3 0 300 100 D 50 50 1 1 W
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# Switch_SW_Push
|
||||||
|
#
|
||||||
|
DEF Switch_SW_Push SW 0 40 N N 1 F N
|
||||||
|
F0 "SW" 50 100 50 H V L CNN
|
||||||
|
F1 "Switch_SW_Push" 0 -60 50 H V C CNN
|
||||||
|
F2 "" 0 200 50 H I C CNN
|
||||||
|
F3 "" 0 200 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
C -80 0 20 0 1 0 N
|
||||||
|
C 80 0 20 0 1 0 N
|
||||||
|
P 2 0 1 0 0 50 0 120 N
|
||||||
|
P 2 0 1 0 100 50 -100 50 N
|
||||||
|
X 1 1 -200 0 100 R 50 50 0 1 P
|
||||||
|
X 2 2 200 0 100 L 50 50 0 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# d1_mini_shield-rescue_CONN_01X08
|
||||||
|
#
|
||||||
|
DEF d1_mini_shield-rescue_CONN_01X08 P 0 40 Y N 1 F N
|
||||||
|
F0 "P" 0 450 50 H V C CNN
|
||||||
|
F1 "d1_mini_shield-rescue_CONN_01X08" 100 0 50 V V C CNN
|
||||||
|
F2 "" 0 0 60 H V C CNN
|
||||||
|
F3 "" 0 0 60 H V C CNN
|
||||||
|
$FPLIST
|
||||||
|
Pin_Header_Straight_1X08
|
||||||
|
Pin_Header_Angled_1X08
|
||||||
|
Socket_Strip_Straight_1X08
|
||||||
|
Socket_Strip_Angled_1X08
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -50 -400 50 400 0 1 0 N
|
||||||
|
S -50 -345 10 -355 0 1 0 N
|
||||||
|
S -50 -245 10 -255 0 1 0 N
|
||||||
|
S -50 -145 10 -155 0 1 0 N
|
||||||
|
S -50 -45 10 -55 0 1 0 N
|
||||||
|
S -50 55 10 45 0 1 0 N
|
||||||
|
S -50 155 10 145 0 1 0 N
|
||||||
|
S -50 255 10 245 0 1 0 N
|
||||||
|
S -50 355 10 345 0 1 0 N
|
||||||
|
X P1 1 -200 350 150 R 50 50 1 1 P
|
||||||
|
X P2 2 -200 250 150 R 50 50 1 1 P
|
||||||
|
X P3 3 -200 150 150 R 50 50 1 1 P
|
||||||
|
X P4 4 -200 50 150 R 50 50 1 1 P
|
||||||
|
X P5 5 -200 -50 150 R 50 50 1 1 P
|
||||||
|
X P6 6 -200 -150 150 R 50 50 1 1 P
|
||||||
|
X P7 7 -200 -250 150 R 50 50 1 1 P
|
||||||
|
X P8 8 -200 -350 150 R 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# power_+3.3V
|
||||||
|
#
|
||||||
|
DEF power_+3.3V #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -150 50 H I C CNN
|
||||||
|
F1 "power_+3.3V" 0 140 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
ALIAS +3.3V
|
||||||
|
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
|
||||||
|
#
|
||||||
|
# power_+3V3
|
||||||
|
#
|
||||||
|
DEF power_+3V3 #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -150 50 H I C CNN
|
||||||
|
F1 "power_+3V3" 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
|
||||||
|
#
|
||||||
|
# power_+5V
|
||||||
|
#
|
||||||
|
DEF power_+5V #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -150 50 H I C CNN
|
||||||
|
F1 "power_+5V" 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 +5V 1 0 0 0 U 50 50 1 1 W N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# power_GND
|
||||||
|
#
|
||||||
|
DEF power_GND #PWR 0 0 Y Y 1 F P
|
||||||
|
F0 "#PWR" 0 -250 50 H I C CNN
|
||||||
|
F1 "power_GND" 0 -150 50 H V C CNN
|
||||||
|
F2 "" 0 0 50 H I C CNN
|
||||||
|
F3 "" 0 0 50 H I C CNN
|
||||||
|
DRAW
|
||||||
|
P 6 0 1 0 0 0 0 -50 50 -50 0 -100 -50 -50 0 -50 N
|
||||||
|
X GND 1 0 0 0 D 50 50 1 1 W N
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
# tss721_TSS721
|
||||||
|
#
|
||||||
|
DEF tss721_TSS721 U 0 40 Y Y 1 F N
|
||||||
|
F0 "U" 200 850 50 H V L CNN
|
||||||
|
F1 "tss721_TSS721" 200 750 50 H V L CNN
|
||||||
|
F2 "" 0 -850 50 H V C CIN
|
||||||
|
F3 "" -200 -800 50 H V C CNN
|
||||||
|
ALIAS TSS721A
|
||||||
|
$FPLIST
|
||||||
|
SOIC*3.9x9.9mm*Pitch1.27mm*
|
||||||
|
TSSOP*4.4x5mm*Pitch0.65mm*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -500 -700 500 700 0 1 10 f
|
||||||
|
X BUSL2 1 -600 400 100 R 50 50 1 1 I
|
||||||
|
X VS 10 -600 0 100 R 50 50 1 1 P
|
||||||
|
X VDD 11 0 800 100 D 50 50 1 1 W
|
||||||
|
X RX 12 600 500 100 L 50 50 1 1 I
|
||||||
|
X RXI 13 600 400 100 L 50 50 1 1 I I
|
||||||
|
X RIS 14 300 -800 100 U 50 50 1 1 I
|
||||||
|
X GND 15 0 -800 100 U 50 50 1 1 W
|
||||||
|
X BUSL1 16 -600 500 100 R 50 50 1 1 I
|
||||||
|
X VB 2 -600 -150 100 R 50 50 1 1 P
|
||||||
|
X STC 3 -600 -500 100 R 50 50 1 1 P
|
||||||
|
X RIDD 4 200 -800 100 U 50 50 1 1 O
|
||||||
|
X PF 5 -600 100 100 R 50 50 1 1 I
|
||||||
|
X SC 6 400 -800 100 U 50 50 1 1 P
|
||||||
|
X TXI 7 600 100 100 L 50 50 1 1 O I
|
||||||
|
X TX 8 600 200 100 L 50 50 1 1 O
|
||||||
|
X BAT 9 -100 800 100 D 50 50 1 1 I
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
#End Library
|
||||||
38
hardware/wemos_mbus_shield/kicad/d1_mini_shield-rescue.lib
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
EESchema-LIBRARY Version 2.4
|
||||||
|
#encoding utf-8
|
||||||
|
#
|
||||||
|
# CONN_01X08
|
||||||
|
#
|
||||||
|
DEF CONN_01X08 P 0 40 Y N 1 F N
|
||||||
|
F0 "P" 0 450 50 H V C CNN
|
||||||
|
F1 "CONN_01X08" 100 0 50 V V C CNN
|
||||||
|
F2 "" 0 0 60 H V C CNN
|
||||||
|
F3 "" 0 0 60 H V C CNN
|
||||||
|
$FPLIST
|
||||||
|
Pin_Header_Straight_1X08
|
||||||
|
Pin_Header_Angled_1X08
|
||||||
|
Socket_Strip_Straight_1X08
|
||||||
|
Socket_Strip_Angled_1X08
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -50 -400 50 400 0 1 0 N
|
||||||
|
S -50 -345 10 -355 0 1 0 N
|
||||||
|
S -50 -245 10 -255 0 1 0 N
|
||||||
|
S -50 -145 10 -155 0 1 0 N
|
||||||
|
S -50 -45 10 -55 0 1 0 N
|
||||||
|
S -50 55 10 45 0 1 0 N
|
||||||
|
S -50 155 10 145 0 1 0 N
|
||||||
|
S -50 255 10 245 0 1 0 N
|
||||||
|
S -50 355 10 345 0 1 0 N
|
||||||
|
X P1 1 -200 350 150 R 50 50 1 1 P
|
||||||
|
X P2 2 -200 250 150 R 50 50 1 1 P
|
||||||
|
X P3 3 -200 150 150 R 50 50 1 1 P
|
||||||
|
X P4 4 -200 50 150 R 50 50 1 1 P
|
||||||
|
X P5 5 -200 -50 150 R 50 50 1 1 P
|
||||||
|
X P6 6 -200 -150 150 R 50 50 1 1 P
|
||||||
|
X P7 7 -200 -250 150 R 50 50 1 1 P
|
||||||
|
X P8 8 -200 -350 150 R 50 50 1 1 P
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
#End Library
|
||||||
1852
hardware/wemos_mbus_shield/kicad/d1_mini_shield.kicad_pcb
Normal file
482
hardware/wemos_mbus_shield/kicad/d1_mini_shield.net
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
(export (version D)
|
||||||
|
(design
|
||||||
|
(source /home/gunnar/src/AmsToMqttBridge/hardware/wemos_mbus_shield/kicad/d1_mini_shield.sch)
|
||||||
|
(date "sø. 26. juni 2022 kl. 12.19 +0200")
|
||||||
|
(tool "Eeschema 5.1.5+dfsg1-2build2")
|
||||||
|
(sheet (number 1) (name /) (tstamps /)
|
||||||
|
(title_block
|
||||||
|
(title)
|
||||||
|
(company)
|
||||||
|
(rev)
|
||||||
|
(date)
|
||||||
|
(source d1_mini_shield.sch)
|
||||||
|
(comment (number 1) (value ""))
|
||||||
|
(comment (number 2) (value ""))
|
||||||
|
(comment (number 3) (value ""))
|
||||||
|
(comment (number 4) (value "")))))
|
||||||
|
(components
|
||||||
|
(comp (ref P1)
|
||||||
|
(value CONN_01X08)
|
||||||
|
(footprint D1_mini:D1_mini_Pin_Header)
|
||||||
|
(libsource (lib d1_mini_shield-rescue) (part CONN_01X08) (description ""))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 5763EB78))
|
||||||
|
(comp (ref P2)
|
||||||
|
(value CONN_01X08)
|
||||||
|
(footprint D1_mini:D1_mini_Pin_Header)
|
||||||
|
(libsource (lib d1_mini_shield-rescue) (part CONN_01X08) (description ""))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 5763EBF2))
|
||||||
|
(comp (ref U1)
|
||||||
|
(value TSS721)
|
||||||
|
(footprint Package_SO:SOIC-16_3.9x9.9mm_P1.27mm)
|
||||||
|
(datasheet http://www.ti.com/lit/ds/symlink/tss721a.pdf)
|
||||||
|
(libsource (lib tss721) (part TSS721) (description "TSS721A Meter Bus Transceiver, SOIC-16/TSSOP-16"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B826D2))
|
||||||
|
(comp (ref J1)
|
||||||
|
(value RJ45)
|
||||||
|
(footprint Connector_RJ:RJ45_Amphenol_54602-x08_Horizontal)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Connector) (part RJ45) (description "RJ connector, 8P8C (8 positions 8 connected)"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B8AC34))
|
||||||
|
(comp (ref R4)
|
||||||
|
(value 220)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B8CAA8))
|
||||||
|
(comp (ref R2)
|
||||||
|
(value 220)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B8DB92))
|
||||||
|
(comp (ref R3)
|
||||||
|
(value 82k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B9F861))
|
||||||
|
(comp (ref R1)
|
||||||
|
(value 470)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62B9FC37))
|
||||||
|
(comp (ref C2)
|
||||||
|
(value 1u)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part C) (description "Unpolarized capacitor"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62BA06BE))
|
||||||
|
(comp (ref C1)
|
||||||
|
(value 100n)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part C) (description "Unpolarized capacitor"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62BA09E7))
|
||||||
|
(comp (ref R5)
|
||||||
|
(value 100k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62BED413))
|
||||||
|
(comp (ref C3)
|
||||||
|
(value 100n)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part C) (description "Unpolarized capacitor"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62BED9ED))
|
||||||
|
(comp (ref JP1)
|
||||||
|
(value Jumper)
|
||||||
|
(footprint Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part Jumper) (description "Jumper, normally closed"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C331C0))
|
||||||
|
(comp (ref JP2)
|
||||||
|
(value Jumper)
|
||||||
|
(footprint Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part Jumper) (description "Jumper, normally closed"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C365CA))
|
||||||
|
(comp (ref JP3)
|
||||||
|
(value Jumper)
|
||||||
|
(footprint Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part Jumper) (description "Jumper, normally closed"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C36C70))
|
||||||
|
(comp (ref D1)
|
||||||
|
(value LED_RGB)
|
||||||
|
(footprint LED_SMD:LED_RGB_PLCC-6)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part LED_RGB) (description "RGB LED, 6 pin package"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C43A7B))
|
||||||
|
(comp (ref R9)
|
||||||
|
(value 1k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C495F7))
|
||||||
|
(comp (ref R8)
|
||||||
|
(value 1k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C4BDE9))
|
||||||
|
(comp (ref R10)
|
||||||
|
(value 1k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C4C336))
|
||||||
|
(comp (ref U2)
|
||||||
|
(value DS18B20)
|
||||||
|
(footprint Package_TO_SOT_THT:TO-92_Inline)
|
||||||
|
(datasheet http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf)
|
||||||
|
(libsource (lib Sensor_Temperature) (part DS18B20) (description "Programmable Resolution 1-Wire Digital Thermometer TO-92"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C6296F))
|
||||||
|
(comp (ref R7)
|
||||||
|
(value 4k7)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C6405D))
|
||||||
|
(comp (ref SW1)
|
||||||
|
(value SW_Push)
|
||||||
|
(footprint Button_Switch_SMD:SW_SPST_B3U-3000P)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Switch) (part SW_Push) (description "Push button switch, generic, two pins"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C73229))
|
||||||
|
(comp (ref R6)
|
||||||
|
(value 10k)
|
||||||
|
(footprint Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part R) (description Resistor))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62C73CE8))
|
||||||
|
(comp (ref JP4)
|
||||||
|
(value Jumper)
|
||||||
|
(footprint Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm)
|
||||||
|
(datasheet ~)
|
||||||
|
(libsource (lib Device) (part Jumper) (description "Jumper, normally closed"))
|
||||||
|
(sheetpath (names /) (tstamps /))
|
||||||
|
(tstamp 62D1E97A)))
|
||||||
|
(libparts
|
||||||
|
(libpart (lib Connector) (part 8P8C)
|
||||||
|
(aliases
|
||||||
|
(alias RJ31)
|
||||||
|
(alias RJ32)
|
||||||
|
(alias RJ33)
|
||||||
|
(alias RJ34)
|
||||||
|
(alias RJ35)
|
||||||
|
(alias RJ41)
|
||||||
|
(alias RJ45)
|
||||||
|
(alias RJ49)
|
||||||
|
(alias RJ61))
|
||||||
|
(description "RJ connector, 8P8C (8 positions 8 connected), RJ31/RJ32/RJ33/RJ34/RJ35/RJ41/RJ45/RJ49/RJ61")
|
||||||
|
(docs ~)
|
||||||
|
(footprints
|
||||||
|
(fp 8P8C*)
|
||||||
|
(fp RJ31*)
|
||||||
|
(fp RJ32*)
|
||||||
|
(fp RJ33*)
|
||||||
|
(fp RJ34*)
|
||||||
|
(fp RJ35*)
|
||||||
|
(fp RJ41*)
|
||||||
|
(fp RJ45*)
|
||||||
|
(fp RJ49*)
|
||||||
|
(fp RJ61*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) J)
|
||||||
|
(field (name Value) 8P8C))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name ~) (type passive))
|
||||||
|
(pin (num 2) (name ~) (type passive))
|
||||||
|
(pin (num 3) (name ~) (type passive))
|
||||||
|
(pin (num 4) (name ~) (type passive))
|
||||||
|
(pin (num 5) (name ~) (type passive))
|
||||||
|
(pin (num 6) (name ~) (type passive))
|
||||||
|
(pin (num 7) (name ~) (type passive))
|
||||||
|
(pin (num 8) (name ~) (type passive))))
|
||||||
|
(libpart (lib Device) (part C)
|
||||||
|
(description "Unpolarized capacitor")
|
||||||
|
(docs ~)
|
||||||
|
(footprints
|
||||||
|
(fp C_*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) C)
|
||||||
|
(field (name Value) C))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name ~) (type passive))
|
||||||
|
(pin (num 2) (name ~) (type passive))))
|
||||||
|
(libpart (lib Device) (part Jumper)
|
||||||
|
(description "Jumper, normally closed")
|
||||||
|
(docs ~)
|
||||||
|
(footprints
|
||||||
|
(fp SolderJumper*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) JP)
|
||||||
|
(field (name Value) Jumper))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name 1) (type passive))
|
||||||
|
(pin (num 2) (name 2) (type passive))))
|
||||||
|
(libpart (lib Device) (part LED_RGB)
|
||||||
|
(description "RGB LED, 6 pin package")
|
||||||
|
(docs ~)
|
||||||
|
(footprints
|
||||||
|
(fp LED*)
|
||||||
|
(fp LED_SMD:*)
|
||||||
|
(fp LED_THT:*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) D)
|
||||||
|
(field (name Value) LED_RGB))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name RK) (type passive))
|
||||||
|
(pin (num 2) (name GK) (type passive))
|
||||||
|
(pin (num 3) (name BK) (type passive))
|
||||||
|
(pin (num 4) (name BA) (type passive))
|
||||||
|
(pin (num 5) (name GA) (type passive))
|
||||||
|
(pin (num 6) (name RA) (type passive))))
|
||||||
|
(libpart (lib Device) (part R)
|
||||||
|
(description Resistor)
|
||||||
|
(docs ~)
|
||||||
|
(footprints
|
||||||
|
(fp R_*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) R)
|
||||||
|
(field (name Value) R))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name ~) (type passive))
|
||||||
|
(pin (num 2) (name ~) (type passive))))
|
||||||
|
(libpart (lib Sensor_Temperature) (part MAX31820)
|
||||||
|
(aliases
|
||||||
|
(alias DS1822)
|
||||||
|
(alias DS18B20)
|
||||||
|
(alias DS18S20)
|
||||||
|
(alias DS1821C))
|
||||||
|
(description "1-Wire Ambient Temperature Sensor TO-92")
|
||||||
|
(docs http://datasheets.maximintegrated.com/en/ds/MAX31820.pdf)
|
||||||
|
(footprints
|
||||||
|
(fp TO*92*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) U)
|
||||||
|
(field (name Value) MAX31820)
|
||||||
|
(field (name Footprint) Package_TO_SOT_THT:TO-92_Inline))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name GND) (type power_in))
|
||||||
|
(pin (num 2) (name DQ) (type BiDi))
|
||||||
|
(pin (num 3) (name VDD) (type power_in))))
|
||||||
|
(libpart (lib Switch) (part SW_Push)
|
||||||
|
(description "Push button switch, generic, two pins")
|
||||||
|
(docs ~)
|
||||||
|
(fields
|
||||||
|
(field (name Reference) SW)
|
||||||
|
(field (name Value) SW_Push))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name 1) (type passive))
|
||||||
|
(pin (num 2) (name 2) (type passive))))
|
||||||
|
(libpart (lib d1_mini_shield-rescue) (part CONN_01X08)
|
||||||
|
(footprints
|
||||||
|
(fp Pin_Header_Straight_1X08)
|
||||||
|
(fp Pin_Header_Angled_1X08)
|
||||||
|
(fp Socket_Strip_Straight_1X08)
|
||||||
|
(fp Socket_Strip_Angled_1X08))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) P)
|
||||||
|
(field (name Value) CONN_01X08))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name P1) (type passive))
|
||||||
|
(pin (num 2) (name P2) (type passive))
|
||||||
|
(pin (num 3) (name P3) (type passive))
|
||||||
|
(pin (num 4) (name P4) (type passive))
|
||||||
|
(pin (num 5) (name P5) (type passive))
|
||||||
|
(pin (num 6) (name P6) (type passive))
|
||||||
|
(pin (num 7) (name P7) (type passive))
|
||||||
|
(pin (num 8) (name P8) (type passive))))
|
||||||
|
(libpart (lib tss721) (part TSS721)
|
||||||
|
(aliases
|
||||||
|
(alias TSS721A))
|
||||||
|
(description "TSS721A Meter Bus Transceiver, SOIC-16/TSSOP-16")
|
||||||
|
(docs http://www.ti.com/lit/ds/symlink/tss721a.pdf)
|
||||||
|
(footprints
|
||||||
|
(fp SOIC*3.9x9.9mm*Pitch1.27mm*)
|
||||||
|
(fp TSSOP*4.4x5mm*Pitch0.65mm*))
|
||||||
|
(fields
|
||||||
|
(field (name Reference) U)
|
||||||
|
(field (name Value) TSS721))
|
||||||
|
(pins
|
||||||
|
(pin (num 1) (name BUSL2) (type input))
|
||||||
|
(pin (num 2) (name VB) (type passive))
|
||||||
|
(pin (num 3) (name STC) (type passive))
|
||||||
|
(pin (num 4) (name RIDD) (type output))
|
||||||
|
(pin (num 5) (name PF) (type input))
|
||||||
|
(pin (num 6) (name SC) (type passive))
|
||||||
|
(pin (num 7) (name TXI) (type output))
|
||||||
|
(pin (num 8) (name TX) (type output))
|
||||||
|
(pin (num 9) (name BAT) (type input))
|
||||||
|
(pin (num 10) (name VS) (type passive))
|
||||||
|
(pin (num 11) (name VDD) (type power_in))
|
||||||
|
(pin (num 12) (name RX) (type input))
|
||||||
|
(pin (num 13) (name RXI) (type input))
|
||||||
|
(pin (num 14) (name RIS) (type input))
|
||||||
|
(pin (num 15) (name GND) (type power_in))
|
||||||
|
(pin (num 16) (name BUSL1) (type input)))))
|
||||||
|
(libraries
|
||||||
|
(library (logical Connector)
|
||||||
|
(uri /usr/share/kicad/library/Connector.lib))
|
||||||
|
(library (logical Device)
|
||||||
|
(uri /usr/share/kicad/library/Device.lib))
|
||||||
|
(library (logical Sensor_Temperature)
|
||||||
|
(uri /usr/share/kicad/library/Sensor_Temperature.lib))
|
||||||
|
(library (logical Switch)
|
||||||
|
(uri /usr/share/kicad/library/Switch.lib))
|
||||||
|
(library (logical d1_mini_shield-rescue)
|
||||||
|
(uri /home/gunnar/src/AmsToMqttBridge/hardware/wemos_mbus_shield/kicad/d1_mini_shield-rescue.lib))
|
||||||
|
(library (logical tss721)
|
||||||
|
(uri /home/gunnar/src/AmsToMqttBridge/hardware/wemos_mbus_shield/kicad/tss721.lib)))
|
||||||
|
(nets
|
||||||
|
(net (code 1) (name TEMP)
|
||||||
|
(node (ref R7) (pin 2))
|
||||||
|
(node (ref U2) (pin 2))
|
||||||
|
(node (ref P1) (pin 5))
|
||||||
|
(node (ref JP3) (pin 2)))
|
||||||
|
(net (code 2) (name +3V3)
|
||||||
|
(node (ref R7) (pin 1))
|
||||||
|
(node (ref U1) (pin 9))
|
||||||
|
(node (ref P2) (pin 1))
|
||||||
|
(node (ref R6) (pin 2))
|
||||||
|
(node (ref D1) (pin 4))
|
||||||
|
(node (ref D1) (pin 5))
|
||||||
|
(node (ref D1) (pin 6))
|
||||||
|
(node (ref U2) (pin 3)))
|
||||||
|
(net (code 3) (name "Net-(D1-Pad1)")
|
||||||
|
(node (ref R9) (pin 2))
|
||||||
|
(node (ref D1) (pin 1)))
|
||||||
|
(net (code 4) (name "Net-(D1-Pad2)")
|
||||||
|
(node (ref D1) (pin 2))
|
||||||
|
(node (ref R8) (pin 2)))
|
||||||
|
(net (code 5) (name "Net-(D1-Pad3)")
|
||||||
|
(node (ref D1) (pin 3))
|
||||||
|
(node (ref R10) (pin 2)))
|
||||||
|
(net (code 6) (name MBUS2)
|
||||||
|
(node (ref J1) (pin 2))
|
||||||
|
(node (ref R4) (pin 1)))
|
||||||
|
(net (code 7) (name BTN_AP)
|
||||||
|
(node (ref P1) (pin 4))
|
||||||
|
(node (ref SW1) (pin 1))
|
||||||
|
(node (ref R6) (pin 1)))
|
||||||
|
(net (code 8) (name "Net-(R4-Pad2)")
|
||||||
|
(node (ref U1) (pin 1))
|
||||||
|
(node (ref R4) (pin 2)))
|
||||||
|
(net (code 9) (name "Net-(R2-Pad2)")
|
||||||
|
(node (ref R2) (pin 2))
|
||||||
|
(node (ref U1) (pin 16)))
|
||||||
|
(net (code 10) (name MBUS1)
|
||||||
|
(node (ref J1) (pin 1))
|
||||||
|
(node (ref R2) (pin 1)))
|
||||||
|
(net (code 11) (name LED_R)
|
||||||
|
(node (ref R9) (pin 1))
|
||||||
|
(node (ref P2) (pin 4)))
|
||||||
|
(net (code 12) (name "Net-(J1-Pad8)")
|
||||||
|
(node (ref J1) (pin 8))
|
||||||
|
(node (ref JP1) (pin 1)))
|
||||||
|
(net (code 13) (name "Net-(J1-Pad5)")
|
||||||
|
(node (ref J1) (pin 5))
|
||||||
|
(node (ref JP2) (pin 1)))
|
||||||
|
(net (code 14) (name "Net-(J1-Pad4)")
|
||||||
|
(node (ref J1) (pin 4))
|
||||||
|
(node (ref JP3) (pin 1)))
|
||||||
|
(net (code 15) (name +5V)
|
||||||
|
(node (ref P1) (pin 1))
|
||||||
|
(node (ref JP1) (pin 2)))
|
||||||
|
(net (code 16) (name "Net-(J1-Pad7)")
|
||||||
|
(node (ref J1) (pin 7))
|
||||||
|
(node (ref JP4) (pin 1)))
|
||||||
|
(net (code 17) (name GND)
|
||||||
|
(node (ref P1) (pin 2))
|
||||||
|
(node (ref C3) (pin 2))
|
||||||
|
(node (ref R3) (pin 1))
|
||||||
|
(node (ref R1) (pin 1))
|
||||||
|
(node (ref C2) (pin 1))
|
||||||
|
(node (ref C1) (pin 1))
|
||||||
|
(node (ref R5) (pin 2))
|
||||||
|
(node (ref U1) (pin 15))
|
||||||
|
(node (ref U2) (pin 1))
|
||||||
|
(node (ref SW1) (pin 2))
|
||||||
|
(node (ref JP4) (pin 2))
|
||||||
|
(node (ref JP2) (pin 2)))
|
||||||
|
(net (code 18) (name LED_G)
|
||||||
|
(node (ref R8) (pin 1))
|
||||||
|
(node (ref P2) (pin 5)))
|
||||||
|
(net (code 19) (name "Net-(U1-Pad10)")
|
||||||
|
(node (ref U1) (pin 10)))
|
||||||
|
(net (code 20) (name "Net-(U1-Pad12)")
|
||||||
|
(node (ref U1) (pin 12)))
|
||||||
|
(net (code 21) (name "Net-(U1-Pad13)")
|
||||||
|
(node (ref U1) (pin 13)))
|
||||||
|
(net (code 22) (name "Net-(U1-Pad2)")
|
||||||
|
(node (ref U1) (pin 2)))
|
||||||
|
(net (code 23) (name "Net-(U1-Pad5)")
|
||||||
|
(node (ref U1) (pin 5)))
|
||||||
|
(net (code 24) (name "Net-(U1-Pad7)")
|
||||||
|
(node (ref U1) (pin 7)))
|
||||||
|
(net (code 25) (name "Net-(J1-Pad3)")
|
||||||
|
(node (ref J1) (pin 3)))
|
||||||
|
(net (code 26) (name "Net-(J1-Pad6)")
|
||||||
|
(node (ref J1) (pin 6)))
|
||||||
|
(net (code 27) (name /RST)
|
||||||
|
(node (ref P2) (pin 8)))
|
||||||
|
(net (code 28) (name /D4)
|
||||||
|
(node (ref P1) (pin 3)))
|
||||||
|
(net (code 29) (name /D1)
|
||||||
|
(node (ref P1) (pin 6)))
|
||||||
|
(net (code 30) (name /RX)
|
||||||
|
(node (ref P1) (pin 7)))
|
||||||
|
(net (code 31) (name /TX)
|
||||||
|
(node (ref P1) (pin 8)))
|
||||||
|
(net (code 32) (name /D8)
|
||||||
|
(node (ref P2) (pin 2)))
|
||||||
|
(net (code 33) (name /D0)
|
||||||
|
(node (ref P2) (pin 6)))
|
||||||
|
(net (code 34) (name /A0)
|
||||||
|
(node (ref P2) (pin 7)))
|
||||||
|
(net (code 35) (name "Net-(R3-Pad2)")
|
||||||
|
(node (ref R3) (pin 2))
|
||||||
|
(node (ref U1) (pin 4)))
|
||||||
|
(net (code 36) (name HAN_TX)
|
||||||
|
(node (ref R10) (pin 1))
|
||||||
|
(node (ref U1) (pin 8))
|
||||||
|
(node (ref P2) (pin 3)))
|
||||||
|
(net (code 37) (name "Net-(C3-Pad1)")
|
||||||
|
(node (ref U1) (pin 11))
|
||||||
|
(node (ref C3) (pin 1))
|
||||||
|
(node (ref R5) (pin 1)))
|
||||||
|
(net (code 38) (name "Net-(R1-Pad2)")
|
||||||
|
(node (ref R1) (pin 2))
|
||||||
|
(node (ref U1) (pin 14)))
|
||||||
|
(net (code 39) (name "Net-(C2-Pad2)")
|
||||||
|
(node (ref C2) (pin 2))
|
||||||
|
(node (ref U1) (pin 3)))
|
||||||
|
(net (code 40) (name "Net-(C1-Pad2)")
|
||||||
|
(node (ref U1) (pin 6))
|
||||||
|
(node (ref C1) (pin 2)))))
|
||||||
246
hardware/wemos_mbus_shield/kicad/d1_mini_shield.pro
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
update=sø. 26. juni 2022 kl. 11.55 +0200
|
||||||
|
version=1
|
||||||
|
last_client=kicad
|
||||||
|
[general]
|
||||||
|
version=1
|
||||||
|
[cvpcb]
|
||||||
|
version=1
|
||||||
|
NetIExt=net
|
||||||
|
[eeschema]
|
||||||
|
version=1
|
||||||
|
LibDir=
|
||||||
|
[schematic_editor]
|
||||||
|
version=1
|
||||||
|
PageLayoutDescrFile=
|
||||||
|
PlotDirectoryName=
|
||||||
|
SubpartIdSeparator=0
|
||||||
|
SubpartFirstId=65
|
||||||
|
NetFmtName=Pcbnew
|
||||||
|
SpiceAjustPassiveValues=0
|
||||||
|
LabSize=50
|
||||||
|
ERC_TestSimilarLabels=1
|
||||||
|
[pcbnew]
|
||||||
|
version=1
|
||||||
|
PageLayoutDescrFile=
|
||||||
|
LastNetListRead=d1_mini_shield.net
|
||||||
|
CopperLayerCount=2
|
||||||
|
BoardThickness=1.6
|
||||||
|
AllowMicroVias=0
|
||||||
|
AllowBlindVias=0
|
||||||
|
RequireCourtyardDefinitions=0
|
||||||
|
ProhibitOverlappingCourtyards=1
|
||||||
|
MinTrackWidth=0.2
|
||||||
|
MinViaDiameter=0.4
|
||||||
|
MinViaDrill=0.3
|
||||||
|
MinMicroViaDiameter=0.2
|
||||||
|
MinMicroViaDrill=0.09999999999999999
|
||||||
|
MinHoleToHole=0.25
|
||||||
|
TrackWidth1=0.25
|
||||||
|
TrackWidth2=0.5
|
||||||
|
ViaDiameter1=0.6
|
||||||
|
ViaDrill1=0.4
|
||||||
|
dPairWidth1=0.2
|
||||||
|
dPairGap1=0.25
|
||||||
|
dPairViaGap1=0.25
|
||||||
|
SilkLineWidth=0.15
|
||||||
|
SilkTextSizeV=1
|
||||||
|
SilkTextSizeH=1
|
||||||
|
SilkTextSizeThickness=0.15
|
||||||
|
SilkTextItalic=0
|
||||||
|
SilkTextUpright=1
|
||||||
|
CopperLineWidth=0.2
|
||||||
|
CopperTextSizeV=1.5
|
||||||
|
CopperTextSizeH=1.5
|
||||||
|
CopperTextThickness=0.3
|
||||||
|
CopperTextItalic=0
|
||||||
|
CopperTextUpright=1
|
||||||
|
EdgeCutLineWidth=0.15
|
||||||
|
CourtyardLineWidth=0.05
|
||||||
|
OthersLineWidth=0.15
|
||||||
|
OthersTextSizeV=1
|
||||||
|
OthersTextSizeH=1
|
||||||
|
OthersTextSizeThickness=0.15
|
||||||
|
OthersTextItalic=0
|
||||||
|
OthersTextUpright=1
|
||||||
|
SolderMaskClearance=0.2
|
||||||
|
SolderMaskMinWidth=0
|
||||||
|
SolderPasteClearance=0
|
||||||
|
SolderPasteRatio=-0
|
||||||
|
[pcbnew/Layer.F.Cu]
|
||||||
|
Name=F.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.In1.Cu]
|
||||||
|
Name=In1.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In2.Cu]
|
||||||
|
Name=In2.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In3.Cu]
|
||||||
|
Name=In3.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In4.Cu]
|
||||||
|
Name=In4.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In5.Cu]
|
||||||
|
Name=In5.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In6.Cu]
|
||||||
|
Name=In6.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In7.Cu]
|
||||||
|
Name=In7.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In8.Cu]
|
||||||
|
Name=In8.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In9.Cu]
|
||||||
|
Name=In9.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In10.Cu]
|
||||||
|
Name=In10.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In11.Cu]
|
||||||
|
Name=In11.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In12.Cu]
|
||||||
|
Name=In12.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In13.Cu]
|
||||||
|
Name=In13.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In14.Cu]
|
||||||
|
Name=In14.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In15.Cu]
|
||||||
|
Name=In15.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In16.Cu]
|
||||||
|
Name=In16.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In17.Cu]
|
||||||
|
Name=In17.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In18.Cu]
|
||||||
|
Name=In18.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In19.Cu]
|
||||||
|
Name=In19.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In20.Cu]
|
||||||
|
Name=In20.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In21.Cu]
|
||||||
|
Name=In21.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In22.Cu]
|
||||||
|
Name=In22.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In23.Cu]
|
||||||
|
Name=In23.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In24.Cu]
|
||||||
|
Name=In24.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In25.Cu]
|
||||||
|
Name=In25.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In26.Cu]
|
||||||
|
Name=In26.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In27.Cu]
|
||||||
|
Name=In27.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In28.Cu]
|
||||||
|
Name=In28.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In29.Cu]
|
||||||
|
Name=In29.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.In30.Cu]
|
||||||
|
Name=In30.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Layer.B.Cu]
|
||||||
|
Name=B.Cu
|
||||||
|
Type=0
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.Adhes]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.Adhes]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.Paste]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.Paste]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.SilkS]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.SilkS]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.Mask]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.Mask]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Dwgs.User]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Cmts.User]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Eco1.User]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Eco2.User]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Edge.Cuts]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Margin]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.CrtYd]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.CrtYd]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.B.Fab]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.F.Fab]
|
||||||
|
Enabled=1
|
||||||
|
[pcbnew/Layer.Rescue]
|
||||||
|
Enabled=0
|
||||||
|
[pcbnew/Netclasses]
|
||||||
|
[pcbnew/Netclasses/Default]
|
||||||
|
Name=Default
|
||||||
|
Clearance=0.2
|
||||||
|
TrackWidth=0.25
|
||||||
|
ViaDiameter=0.6
|
||||||
|
ViaDrill=0.4
|
||||||
|
uViaDiameter=0.3
|
||||||
|
uViaDrill=0.1
|
||||||
|
dPairWidth=0.2
|
||||||
|
dPairGap=0.25
|
||||||
|
dPairViaGap=0.25
|
||||||
725
hardware/wemos_mbus_shield/kicad/d1_mini_shield.sch
Normal file
@@ -0,0 +1,725 @@
|
|||||||
|
EESchema Schematic File Version 4
|
||||||
|
EELAYER 30 0
|
||||||
|
EELAYER END
|
||||||
|
$Descr A4 11693 8268
|
||||||
|
encoding utf-8
|
||||||
|
Sheet 1 1
|
||||||
|
Title ""
|
||||||
|
Date ""
|
||||||
|
Rev ""
|
||||||
|
Comp ""
|
||||||
|
Comment1 ""
|
||||||
|
Comment2 ""
|
||||||
|
Comment3 ""
|
||||||
|
Comment4 ""
|
||||||
|
$EndDescr
|
||||||
|
$Comp
|
||||||
|
L d1_mini_shield-rescue:CONN_01X08 P1
|
||||||
|
U 1 1 5763EB78
|
||||||
|
P 8300 1850
|
||||||
|
F 0 "P1" H 8300 2300 50 0000 C CNN
|
||||||
|
F 1 "CONN_01X08" V 8400 1850 50 0000 C CNN
|
||||||
|
F 2 "D1_mini:D1_mini_Pin_Header" H 8300 1850 50 0001 C CNN
|
||||||
|
F 3 "" H 8300 1850 50 0000 C CNN
|
||||||
|
1 8300 1850
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L d1_mini_shield-rescue:CONN_01X08 P2
|
||||||
|
U 1 1 5763EBF2
|
||||||
|
P 9400 1850
|
||||||
|
F 0 "P2" H 9400 2300 50 0000 C CNN
|
||||||
|
F 1 "CONN_01X08" V 9500 1850 50 0000 C CNN
|
||||||
|
F 2 "D1_mini:D1_mini_Pin_Header" H 9400 1850 50 0001 C CNN
|
||||||
|
F 3 "" H 9400 1850 50 0000 C CNN
|
||||||
|
1 9400 1850
|
||||||
|
-1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Text Label 8100 1500 2 60 ~ 0
|
||||||
|
+5V
|
||||||
|
Text Label 8100 1600 2 60 ~ 0
|
||||||
|
GND
|
||||||
|
Text Label 8100 1700 2 60 ~ 0
|
||||||
|
D4
|
||||||
|
Text Label 8100 1800 2 60 ~ 0
|
||||||
|
D3
|
||||||
|
Text Label 8100 1900 2 60 ~ 0
|
||||||
|
D2
|
||||||
|
Text Label 8100 2000 2 60 ~ 0
|
||||||
|
D1
|
||||||
|
Text Label 8100 2100 2 60 ~ 0
|
||||||
|
RX
|
||||||
|
Text Label 8100 2200 2 60 ~ 0
|
||||||
|
TX
|
||||||
|
Text Label 9600 1500 0 60 ~ 0
|
||||||
|
+3.3V
|
||||||
|
Text Label 9600 1600 0 60 ~ 0
|
||||||
|
D8
|
||||||
|
Text Label 9600 1700 0 60 ~ 0
|
||||||
|
D7
|
||||||
|
Text Label 9600 1800 0 60 ~ 0
|
||||||
|
D6
|
||||||
|
Text Label 9600 1900 0 60 ~ 0
|
||||||
|
D5
|
||||||
|
Text Label 9600 2000 0 60 ~ 0
|
||||||
|
D0
|
||||||
|
Text Label 9600 2100 0 60 ~ 0
|
||||||
|
A0
|
||||||
|
Text Label 9600 2200 0 60 ~ 0
|
||||||
|
RST
|
||||||
|
Text Notes 8750 1750 2 60 ~ 0
|
||||||
|
GPIO2
|
||||||
|
Text Notes 8750 1850 2 60 ~ 0
|
||||||
|
GPIO0
|
||||||
|
Text Notes 8750 1950 2 60 ~ 0
|
||||||
|
GPIO4
|
||||||
|
Text Notes 8750 2050 2 60 ~ 0
|
||||||
|
GPIO5
|
||||||
|
Text Notes 8900 1650 0 60 ~ 0
|
||||||
|
GPIO15
|
||||||
|
Text Notes 8900 1750 0 60 ~ 0
|
||||||
|
GPIO13
|
||||||
|
Text Notes 8900 1850 0 60 ~ 0
|
||||||
|
GPIO12
|
||||||
|
Text Notes 8900 1950 0 60 ~ 0
|
||||||
|
GPIO14
|
||||||
|
Text Notes 8900 2050 0 60 ~ 0
|
||||||
|
GPIO16
|
||||||
|
Text Notes 7550 1050 0 60 ~ 0
|
||||||
|
D1 Mini Shield
|
||||||
|
$Comp
|
||||||
|
L tss721:TSS721 U1
|
||||||
|
U 1 1 62B826D2
|
||||||
|
P 3650 5550
|
||||||
|
F 0 "U1" H 3650 6621 50 0000 C CNN
|
||||||
|
F 1 "TSS721" H 3650 6530 50 0000 C CNN
|
||||||
|
F 2 "Package_SO:SOIC-16_3.9x9.9mm_P1.27mm" H 3650 4700 50 0001 C CIN
|
||||||
|
F 3 "http://www.ti.com/lit/ds/symlink/tss721a.pdf" H 3650 6439 50 0000 C CNN
|
||||||
|
1 3650 5550
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:+3.3V #PWR0101
|
||||||
|
U 1 1 62B89C7B
|
||||||
|
P 2850 4750
|
||||||
|
F 0 "#PWR0101" H 2850 4600 50 0001 C CNN
|
||||||
|
F 1 "+3.3V" V 2865 4878 50 0000 L CNN
|
||||||
|
F 2 "" H 2850 4750 50 0001 C CNN
|
||||||
|
F 3 "" H 2850 4750 50 0001 C CNN
|
||||||
|
1 2850 4750
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Connector:RJ45 J1
|
||||||
|
U 1 1 62B8AC34
|
||||||
|
P 1950 1850
|
||||||
|
F 0 "J1" H 2007 2517 50 0000 C CNN
|
||||||
|
F 1 "RJ45" H 2007 2426 50 0000 C CNN
|
||||||
|
F 2 "Connector_RJ:RJ45_Amphenol_54602-x08_Horizontal" V 1950 1875 50 0001 C CNN
|
||||||
|
F 3 "~" V 1950 1875 50 0001 C CNN
|
||||||
|
1 1950 1850
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R4
|
||||||
|
U 1 1 62B8CAA8
|
||||||
|
P 2750 5150
|
||||||
|
F 0 "R4" V 2957 5150 50 0000 C CNN
|
||||||
|
F 1 "220" V 2866 5150 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 2680 5150 50 0001 C CNN
|
||||||
|
F 3 "~" H 2750 5150 50 0001 C CNN
|
||||||
|
1 2750 5150
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R2
|
||||||
|
U 1 1 62B8DB92
|
||||||
|
P 2500 5050
|
||||||
|
F 0 "R2" V 2707 5050 50 0000 C CNN
|
||||||
|
F 1 "220" V 2616 5050 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 2430 5050 50 0001 C CNN
|
||||||
|
F 3 "~" H 2500 5050 50 0001 C CNN
|
||||||
|
1 2500 5050
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0102
|
||||||
|
U 1 1 62B9F029
|
||||||
|
P 1850 6050
|
||||||
|
F 0 "#PWR0102" H 1850 5800 50 0001 C CNN
|
||||||
|
F 1 "GND" H 1855 5877 50 0000 C CNN
|
||||||
|
F 2 "" H 1850 6050 50 0001 C CNN
|
||||||
|
F 3 "" H 1850 6050 50 0001 C CNN
|
||||||
|
1 1850 6050
|
||||||
|
-1 0 0 1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R3
|
||||||
|
U 1 1 62B9F861
|
||||||
|
P 2500 6300
|
||||||
|
F 0 "R3" H 2570 6346 50 0000 L CNN
|
||||||
|
F 1 "82k" H 2570 6255 50 0000 L CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 2430 6300 50 0001 C CNN
|
||||||
|
F 3 "~" H 2500 6300 50 0001 C CNN
|
||||||
|
1 2500 6300
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R1
|
||||||
|
U 1 1 62B9FC37
|
||||||
|
P 2250 6300
|
||||||
|
F 0 "R1" H 2320 6346 50 0000 L CNN
|
||||||
|
F 1 "470" H 2320 6255 50 0000 L CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 2180 6300 50 0001 C CNN
|
||||||
|
F 3 "~" H 2250 6300 50 0001 C CNN
|
||||||
|
1 2250 6300
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:C C2
|
||||||
|
U 1 1 62BA06BE
|
||||||
|
P 2850 6050
|
||||||
|
F 0 "C2" V 3102 6050 50 0000 C CNN
|
||||||
|
F 1 "1u" V 3011 6050 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 2888 5900 50 0001 C CNN
|
||||||
|
F 3 "~" H 2850 6050 50 0001 C CNN
|
||||||
|
1 2850 6050
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:C C1
|
||||||
|
U 1 1 62BA09E7
|
||||||
|
P 1850 6300
|
||||||
|
F 0 "C1" H 1965 6346 50 0000 L CNN
|
||||||
|
F 1 "100n" H 1965 6255 50 0000 L CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 1888 6150 50 0001 C CNN
|
||||||
|
F 3 "~" H 1850 6300 50 0001 C CNN
|
||||||
|
1 1850 6300
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
1850 6050 1850 6150
|
||||||
|
Wire Wire Line
|
||||||
|
2250 6050 2250 6150
|
||||||
|
Wire Wire Line
|
||||||
|
2500 6050 2500 6150
|
||||||
|
Connection ~ 1850 6050
|
||||||
|
Connection ~ 2250 6050
|
||||||
|
Wire Wire Line
|
||||||
|
2250 6050 2500 6050
|
||||||
|
Wire Wire Line
|
||||||
|
1850 6050 2250 6050
|
||||||
|
Connection ~ 2500 6050
|
||||||
|
Wire Wire Line
|
||||||
|
3850 6450 3850 6350
|
||||||
|
Wire Wire Line
|
||||||
|
2250 6450 2250 6550
|
||||||
|
Wire Wire Line
|
||||||
|
3950 6550 3950 6350
|
||||||
|
Wire Wire Line
|
||||||
|
1850 6450 1850 6650
|
||||||
|
Wire Wire Line
|
||||||
|
4050 6650 4050 6350
|
||||||
|
Wire Wire Line
|
||||||
|
3050 6050 3000 6050
|
||||||
|
Wire Wire Line
|
||||||
|
2500 6050 2700 6050
|
||||||
|
Wire Wire Line
|
||||||
|
2700 6050 2700 6350
|
||||||
|
Wire Wire Line
|
||||||
|
2700 6350 3650 6350
|
||||||
|
Connection ~ 2700 6050
|
||||||
|
Wire Wire Line
|
||||||
|
3850 6450 2500 6450
|
||||||
|
Wire Wire Line
|
||||||
|
2250 6550 3950 6550
|
||||||
|
Wire Wire Line
|
||||||
|
4050 6650 1850 6650
|
||||||
|
Text GLabel 4350 5350 2 50 Output ~ 0
|
||||||
|
HAN_TX
|
||||||
|
Wire Wire Line
|
||||||
|
4350 5350 4300 5350
|
||||||
|
Wire Wire Line
|
||||||
|
2850 4750 3550 4750
|
||||||
|
$Comp
|
||||||
|
L Device:R R5
|
||||||
|
U 1 1 62BED413
|
||||||
|
P 4650 4550
|
||||||
|
F 0 "R5" V 4857 4550 50 0000 C CNN
|
||||||
|
F 1 "100k" V 4766 4550 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 4580 4550 50 0001 C CNN
|
||||||
|
F 3 "~" H 4650 4550 50 0001 C CNN
|
||||||
|
1 4650 4550
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:C C3
|
||||||
|
U 1 1 62BED9ED
|
||||||
|
P 4650 4900
|
||||||
|
F 0 "C3" V 4902 4900 50 0000 C CNN
|
||||||
|
F 1 "100n" V 4811 4900 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" H 4688 4750 50 0001 C CNN
|
||||||
|
F 3 "~" H 4650 4900 50 0001 C CNN
|
||||||
|
1 4650 4900
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0103
|
||||||
|
U 1 1 62BF4151
|
||||||
|
P 4800 5050
|
||||||
|
F 0 "#PWR0103" H 4800 4800 50 0001 C CNN
|
||||||
|
F 1 "GND" H 4805 4877 50 0000 C CNN
|
||||||
|
F 2 "" H 4800 5050 50 0001 C CNN
|
||||||
|
F 3 "" H 4800 5050 50 0001 C CNN
|
||||||
|
1 4800 5050
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
4800 4550 4800 4900
|
||||||
|
Wire Wire Line
|
||||||
|
4800 4900 4800 5050
|
||||||
|
Connection ~ 4800 4900
|
||||||
|
Wire Wire Line
|
||||||
|
4500 4900 4500 4550
|
||||||
|
Wire Wire Line
|
||||||
|
4500 4550 3650 4550
|
||||||
|
Wire Wire Line
|
||||||
|
3650 4550 3650 4750
|
||||||
|
Connection ~ 4500 4550
|
||||||
|
Wire Notes Line
|
||||||
|
1500 4050 5050 4050
|
||||||
|
Wire Notes Line
|
||||||
|
5050 4050 5050 6850
|
||||||
|
Wire Notes Line
|
||||||
|
5050 6850 1500 6850
|
||||||
|
Wire Notes Line
|
||||||
|
1500 6850 1500 4050
|
||||||
|
Wire Notes Line
|
||||||
|
7550 950 10200 950
|
||||||
|
Wire Notes Line
|
||||||
|
10200 950 10200 2750
|
||||||
|
Wire Notes Line
|
||||||
|
10200 2750 7550 2750
|
||||||
|
Wire Notes Line
|
||||||
|
7550 2750 7550 950
|
||||||
|
Text GLabel 9800 1700 2 50 Input ~ 0
|
||||||
|
HAN_TX
|
||||||
|
Wire Wire Line
|
||||||
|
9800 1700 9600 1700
|
||||||
|
$Comp
|
||||||
|
L power:+3V3 #PWR0104
|
||||||
|
U 1 1 62C0EBC2
|
||||||
|
P 9850 1500
|
||||||
|
F 0 "#PWR0104" H 9850 1350 50 0001 C CNN
|
||||||
|
F 1 "+3V3" V 9865 1628 50 0000 L CNN
|
||||||
|
F 2 "" H 9850 1500 50 0001 C CNN
|
||||||
|
F 3 "" H 9850 1500 50 0001 C CNN
|
||||||
|
1 9850 1500
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
9850 1500 9600 1500
|
||||||
|
Text GLabel 9800 1800 2 50 Output ~ 0
|
||||||
|
LED_R
|
||||||
|
Text GLabel 9800 1900 2 50 Output ~ 0
|
||||||
|
LED_G
|
||||||
|
Wire Wire Line
|
||||||
|
9800 1800 9600 1800
|
||||||
|
Wire Wire Line
|
||||||
|
9800 1900 9600 1900
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0105
|
||||||
|
U 1 1 62C13452
|
||||||
|
P 7850 1600
|
||||||
|
F 0 "#PWR0105" H 7850 1350 50 0001 C CNN
|
||||||
|
F 1 "GND" V 7855 1472 50 0000 R CNN
|
||||||
|
F 2 "" H 7850 1600 50 0001 C CNN
|
||||||
|
F 3 "" H 7850 1600 50 0001 C CNN
|
||||||
|
1 7850 1600
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
8100 1600 7850 1600
|
||||||
|
Text GLabel 7950 1800 0 50 Input ~ 0
|
||||||
|
BTN_AP
|
||||||
|
Wire Wire Line
|
||||||
|
8100 1800 7950 1800
|
||||||
|
Text GLabel 7950 1900 0 50 Input ~ 0
|
||||||
|
TEMP
|
||||||
|
Wire Wire Line
|
||||||
|
8100 1900 7950 1900
|
||||||
|
Wire Wire Line
|
||||||
|
3050 5150 2900 5150
|
||||||
|
Wire Wire Line
|
||||||
|
3050 5050 2650 5050
|
||||||
|
Text GLabel 2200 5050 0 50 Input ~ 0
|
||||||
|
MBUS1
|
||||||
|
Text GLabel 2200 5150 0 50 Input ~ 0
|
||||||
|
MBUS2
|
||||||
|
Wire Wire Line
|
||||||
|
2350 5050 2200 5050
|
||||||
|
Wire Wire Line
|
||||||
|
2600 5150 2200 5150
|
||||||
|
Text GLabel 2500 2150 2 50 Output ~ 0
|
||||||
|
MBUS1
|
||||||
|
Text GLabel 2500 2050 2 50 Output ~ 0
|
||||||
|
MBUS2
|
||||||
|
Wire Wire Line
|
||||||
|
2500 2050 2350 2050
|
||||||
|
Wire Wire Line
|
||||||
|
2350 2150 2500 2150
|
||||||
|
$Comp
|
||||||
|
L Device:Jumper JP1
|
||||||
|
U 1 1 62C331C0
|
||||||
|
P 3300 1250
|
||||||
|
F 0 "JP1" H 3300 1514 50 0000 C CNN
|
||||||
|
F 1 "Jumper" H 3300 1423 50 0000 C CNN
|
||||||
|
F 2 "Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm" H 3300 1250 50 0001 C CNN
|
||||||
|
F 3 "~" H 3300 1250 50 0001 C CNN
|
||||||
|
1 3300 1250
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:Jumper JP2
|
||||||
|
U 1 1 62C365CA
|
||||||
|
P 3300 1850
|
||||||
|
F 0 "JP2" H 3300 2114 50 0000 C CNN
|
||||||
|
F 1 "Jumper" H 3300 2023 50 0000 C CNN
|
||||||
|
F 2 "Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm" H 3300 1850 50 0001 C CNN
|
||||||
|
F 3 "~" H 3300 1850 50 0001 C CNN
|
||||||
|
1 3300 1850
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:Jumper JP3
|
||||||
|
U 1 1 62C36C70
|
||||||
|
P 3300 2200
|
||||||
|
F 0 "JP3" H 3300 2464 50 0000 C CNN
|
||||||
|
F 1 "Jumper" H 3300 2373 50 0000 C CNN
|
||||||
|
F 2 "Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm" H 3300 2200 50 0001 C CNN
|
||||||
|
F 3 "~" H 3300 2200 50 0001 C CNN
|
||||||
|
1 3300 2200
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
3000 1850 2900 1850
|
||||||
|
Wire Wire Line
|
||||||
|
2900 1850 2900 1750
|
||||||
|
Wire Wire Line
|
||||||
|
2350 1750 2900 1750
|
||||||
|
Wire Wire Line
|
||||||
|
2350 1850 2850 1850
|
||||||
|
Wire Wire Line
|
||||||
|
2850 1850 2850 2200
|
||||||
|
Wire Wire Line
|
||||||
|
2850 2200 3000 2200
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0107
|
||||||
|
U 1 1 62C3D94F
|
||||||
|
P 3750 1850
|
||||||
|
F 0 "#PWR0107" H 3750 1600 50 0001 C CNN
|
||||||
|
F 1 "GND" V 3755 1722 50 0000 R CNN
|
||||||
|
F 2 "" H 3750 1850 50 0001 C CNN
|
||||||
|
F 3 "" H 3750 1850 50 0001 C CNN
|
||||||
|
1 3750 1850
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
Text GLabel 3750 2200 2 50 Output ~ 0
|
||||||
|
TEMP
|
||||||
|
Wire Wire Line
|
||||||
|
3750 1850 3600 1850
|
||||||
|
Wire Wire Line
|
||||||
|
3750 2200 3600 2200
|
||||||
|
Wire Notes Line
|
||||||
|
1450 950 4350 950
|
||||||
|
Wire Notes Line
|
||||||
|
4350 950 4350 2450
|
||||||
|
Wire Notes Line
|
||||||
|
4350 2450 1450 2450
|
||||||
|
Wire Notes Line
|
||||||
|
1450 2450 1450 950
|
||||||
|
$Comp
|
||||||
|
L Device:LED_RGB D1
|
||||||
|
U 1 1 62C43A7B
|
||||||
|
P 9550 4800
|
||||||
|
F 0 "D1" H 9550 5297 50 0000 C CNN
|
||||||
|
F 1 "LED_RGB" H 9550 5206 50 0000 C CNN
|
||||||
|
F 2 "LED_SMD:LED_RGB_PLCC-6" H 9550 4750 50 0001 C CNN
|
||||||
|
F 3 "~" H 9550 4750 50 0001 C CNN
|
||||||
|
1 9550 4800
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:+3.3V #PWR0108
|
||||||
|
U 1 1 62C44A94
|
||||||
|
P 10000 4800
|
||||||
|
F 0 "#PWR0108" H 10000 4650 50 0001 C CNN
|
||||||
|
F 1 "+3.3V" V 10015 4928 50 0000 L CNN
|
||||||
|
F 2 "" H 10000 4800 50 0001 C CNN
|
||||||
|
F 3 "" H 10000 4800 50 0001 C CNN
|
||||||
|
1 10000 4800
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
9750 4800 9900 4800
|
||||||
|
Wire Wire Line
|
||||||
|
9750 4600 9900 4600
|
||||||
|
Wire Wire Line
|
||||||
|
9900 4600 9900 4800
|
||||||
|
Connection ~ 9900 4800
|
||||||
|
Wire Wire Line
|
||||||
|
9900 4800 10000 4800
|
||||||
|
Wire Wire Line
|
||||||
|
9900 4800 9900 5000
|
||||||
|
Wire Wire Line
|
||||||
|
9900 5000 9750 5000
|
||||||
|
$Comp
|
||||||
|
L Device:R R9
|
||||||
|
U 1 1 62C495F7
|
||||||
|
P 9100 4600
|
||||||
|
F 0 "R9" V 9307 4600 50 0000 C CNN
|
||||||
|
F 1 "1k" V 9216 4600 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 9030 4600 50 0001 C CNN
|
||||||
|
F 3 "~" H 9100 4600 50 0001 C CNN
|
||||||
|
1 9100 4600
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R8
|
||||||
|
U 1 1 62C4BDE9
|
||||||
|
P 8850 4800
|
||||||
|
F 0 "R8" V 9057 4800 50 0000 C CNN
|
||||||
|
F 1 "1k" V 8966 4800 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 8780 4800 50 0001 C CNN
|
||||||
|
F 3 "~" H 8850 4800 50 0001 C CNN
|
||||||
|
1 8850 4800
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R10
|
||||||
|
U 1 1 62C4C336
|
||||||
|
P 9100 5000
|
||||||
|
F 0 "R10" V 9307 5000 50 0000 C CNN
|
||||||
|
F 1 "1k" V 9216 5000 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 9030 5000 50 0001 C CNN
|
||||||
|
F 3 "~" H 9100 5000 50 0001 C CNN
|
||||||
|
1 9100 5000
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
9350 4600 9250 4600
|
||||||
|
Wire Wire Line
|
||||||
|
9350 4800 9000 4800
|
||||||
|
Wire Wire Line
|
||||||
|
9350 5000 9250 5000
|
||||||
|
Text GLabel 8650 4600 0 50 Input ~ 0
|
||||||
|
LED_R
|
||||||
|
Text GLabel 8650 4800 0 50 Input ~ 0
|
||||||
|
LED_G
|
||||||
|
Text GLabel 8650 5000 0 50 Input ~ 0
|
||||||
|
LED_B
|
||||||
|
Wire Wire Line
|
||||||
|
8700 4800 8650 4800
|
||||||
|
Wire Wire Line
|
||||||
|
8950 4600 8650 4600
|
||||||
|
Wire Wire Line
|
||||||
|
8950 5000 8650 5000
|
||||||
|
Wire Notes Line
|
||||||
|
8200 4050 10550 4050
|
||||||
|
Wire Notes Line
|
||||||
|
10550 4050 10550 5400
|
||||||
|
Wire Notes Line
|
||||||
|
10550 5400 8200 5400
|
||||||
|
Wire Notes Line
|
||||||
|
8200 5400 8200 4050
|
||||||
|
$Comp
|
||||||
|
L Sensor_Temperature:DS18B20 U2
|
||||||
|
U 1 1 62C6296F
|
||||||
|
P 6600 4900
|
||||||
|
F 0 "U2" H 6370 4946 50 0000 R CNN
|
||||||
|
F 1 "DS18B20" H 6370 4855 50 0000 R CNN
|
||||||
|
F 2 "Package_TO_SOT_THT:TO-92_Inline" H 5600 4650 50 0001 C CNN
|
||||||
|
F 3 "http://datasheets.maximintegrated.com/en/ds/DS18B20.pdf" H 6450 5150 50 0001 C CNN
|
||||||
|
1 6600 4900
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0109
|
||||||
|
U 1 1 62C6373E
|
||||||
|
P 6600 5350
|
||||||
|
F 0 "#PWR0109" H 6600 5100 50 0001 C CNN
|
||||||
|
F 1 "GND" H 6605 5177 50 0000 C CNN
|
||||||
|
F 2 "" H 6600 5350 50 0001 C CNN
|
||||||
|
F 3 "" H 6600 5350 50 0001 C CNN
|
||||||
|
1 6600 5350
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:+3.3V #PWR0110
|
||||||
|
U 1 1 62C63C02
|
||||||
|
P 6600 4450
|
||||||
|
F 0 "#PWR0110" H 6600 4300 50 0001 C CNN
|
||||||
|
F 1 "+3.3V" H 6615 4623 50 0000 C CNN
|
||||||
|
F 2 "" H 6600 4450 50 0001 C CNN
|
||||||
|
F 3 "" H 6600 4450 50 0001 C CNN
|
||||||
|
1 6600 4450
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R7
|
||||||
|
U 1 1 62C6405D
|
||||||
|
P 6900 4600
|
||||||
|
F 0 "R7" H 6970 4646 50 0000 L CNN
|
||||||
|
F 1 "4k7" H 6970 4555 50 0000 L CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 6830 4600 50 0001 C CNN
|
||||||
|
F 3 "~" H 6900 4600 50 0001 C CNN
|
||||||
|
1 6900 4600
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
6600 5200 6600 5350
|
||||||
|
Wire Wire Line
|
||||||
|
6600 4600 6600 4450
|
||||||
|
Wire Wire Line
|
||||||
|
6900 4900 6900 4750
|
||||||
|
Wire Wire Line
|
||||||
|
6900 4450 6600 4450
|
||||||
|
Connection ~ 6600 4450
|
||||||
|
Text GLabel 7050 4900 2 50 Output ~ 0
|
||||||
|
TEMP
|
||||||
|
Wire Wire Line
|
||||||
|
7050 4900 6900 4900
|
||||||
|
Connection ~ 6900 4900
|
||||||
|
Wire Notes Line
|
||||||
|
5750 4050 7500 4050
|
||||||
|
Wire Notes Line
|
||||||
|
7500 4050 7500 5750
|
||||||
|
Wire Notes Line
|
||||||
|
7500 5750 5750 5750
|
||||||
|
Wire Notes Line
|
||||||
|
5750 5750 5750 4050
|
||||||
|
$Comp
|
||||||
|
L Switch:SW_Push SW1
|
||||||
|
U 1 1 62C73229
|
||||||
|
P 5950 1400
|
||||||
|
F 0 "SW1" H 5950 1685 50 0000 C CNN
|
||||||
|
F 1 "SW_Push" H 5950 1594 50 0000 C CNN
|
||||||
|
F 2 "Button_Switch_SMD:SW_SPST_B3U-3000P" H 5950 1600 50 0001 C CNN
|
||||||
|
F 3 "~" H 5950 1600 50 0001 C CNN
|
||||||
|
1 5950 1400
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:R R6
|
||||||
|
U 1 1 62C73CE8
|
||||||
|
P 5950 1700
|
||||||
|
F 0 "R6" V 6157 1700 50 0000 C CNN
|
||||||
|
F 1 "10k" V 6066 1700 50 0000 C CNN
|
||||||
|
F 2 "Resistor_SMD:R_0805_2012Metric_Pad1.15x1.40mm_HandSolder" V 5880 1700 50 0001 C CNN
|
||||||
|
F 3 "~" H 5950 1700 50 0001 C CNN
|
||||||
|
1 5950 1700
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:GND #PWR0111
|
||||||
|
U 1 1 62C76961
|
||||||
|
P 6350 1400
|
||||||
|
F 0 "#PWR0111" H 6350 1150 50 0001 C CNN
|
||||||
|
F 1 "GND" V 6355 1272 50 0000 R CNN
|
||||||
|
F 2 "" H 6350 1400 50 0001 C CNN
|
||||||
|
F 3 "" H 6350 1400 50 0001 C CNN
|
||||||
|
1 6350 1400
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L power:+3.3V #PWR0112
|
||||||
|
U 1 1 62C776AD
|
||||||
|
P 6350 1700
|
||||||
|
F 0 "#PWR0112" H 6350 1550 50 0001 C CNN
|
||||||
|
F 1 "+3.3V" V 6365 1828 50 0000 L CNN
|
||||||
|
F 2 "" H 6350 1700 50 0001 C CNN
|
||||||
|
F 3 "" H 6350 1700 50 0001 C CNN
|
||||||
|
1 6350 1700
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
6350 1400 6150 1400
|
||||||
|
Wire Wire Line
|
||||||
|
6350 1700 6100 1700
|
||||||
|
Wire Wire Line
|
||||||
|
5750 1400 5550 1400
|
||||||
|
Wire Wire Line
|
||||||
|
5550 1400 5550 1550
|
||||||
|
Wire Wire Line
|
||||||
|
5550 1700 5800 1700
|
||||||
|
Text GLabel 5450 1550 0 50 Output ~ 0
|
||||||
|
BTN_AP
|
||||||
|
Wire Wire Line
|
||||||
|
5450 1550 5550 1550
|
||||||
|
Connection ~ 5550 1550
|
||||||
|
Wire Wire Line
|
||||||
|
5550 1550 5550 1700
|
||||||
|
Wire Notes Line
|
||||||
|
5000 950 6850 950
|
||||||
|
Wire Notes Line
|
||||||
|
6850 950 6850 1950
|
||||||
|
Wire Notes Line
|
||||||
|
6850 1950 5000 1950
|
||||||
|
Wire Notes Line
|
||||||
|
5000 1950 5000 950
|
||||||
|
Text GLabel 4350 5450 2 50 Output ~ 0
|
||||||
|
LED_B
|
||||||
|
Wire Wire Line
|
||||||
|
4350 5450 4300 5450
|
||||||
|
Wire Wire Line
|
||||||
|
4300 5450 4300 5350
|
||||||
|
Connection ~ 4300 5350
|
||||||
|
Wire Wire Line
|
||||||
|
4300 5350 4250 5350
|
||||||
|
$Comp
|
||||||
|
L power:+5V #PWR0106
|
||||||
|
U 1 1 62D05402
|
||||||
|
P 7850 1500
|
||||||
|
F 0 "#PWR0106" H 7850 1350 50 0001 C CNN
|
||||||
|
F 1 "+5V" V 7865 1628 50 0000 L CNN
|
||||||
|
F 2 "" H 7850 1500 50 0001 C CNN
|
||||||
|
F 3 "" H 7850 1500 50 0001 C CNN
|
||||||
|
1 7850 1500
|
||||||
|
0 -1 -1 0
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
8100 1500 7850 1500
|
||||||
|
$Comp
|
||||||
|
L power:+5V #PWR0113
|
||||||
|
U 1 1 62D0B1E1
|
||||||
|
P 3750 1250
|
||||||
|
F 0 "#PWR0113" H 3750 1100 50 0001 C CNN
|
||||||
|
F 1 "+5V" V 3765 1378 50 0000 L CNN
|
||||||
|
F 2 "" H 3750 1250 50 0001 C CNN
|
||||||
|
F 3 "" H 3750 1250 50 0001 C CNN
|
||||||
|
1 3750 1250
|
||||||
|
0 1 1 0
|
||||||
|
$EndComp
|
||||||
|
$Comp
|
||||||
|
L Device:Jumper JP4
|
||||||
|
U 1 1 62D1E97A
|
||||||
|
P 3300 1550
|
||||||
|
F 0 "JP4" H 3300 1814 50 0000 C CNN
|
||||||
|
F 1 "Jumper" H 3300 1723 50 0000 C CNN
|
||||||
|
F 2 "Jumper:SolderJumper-2_P1.3mm_Open_RoundedPad1.0x1.5mm" H 3300 1550 50 0001 C CNN
|
||||||
|
F 3 "~" H 3300 1550 50 0001 C CNN
|
||||||
|
1 3300 1550
|
||||||
|
1 0 0 -1
|
||||||
|
$EndComp
|
||||||
|
Wire Wire Line
|
||||||
|
3000 1250 2350 1250
|
||||||
|
Wire Wire Line
|
||||||
|
2350 1250 2350 1450
|
||||||
|
Wire Wire Line
|
||||||
|
3600 1250 3750 1250
|
||||||
|
Wire Wire Line
|
||||||
|
3600 1550 3600 1850
|
||||||
|
Connection ~ 3600 1850
|
||||||
|
Wire Wire Line
|
||||||
|
2350 1550 3000 1550
|
||||||
|
$EndSCHEMATC
|
||||||
75272
hardware/wemos_mbus_shield/kicad/fp-info-cache
Normal file
3
hardware/wemos_mbus_shield/kicad/fp-lib-table
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
(fp_lib_table
|
||||||
|
(lib (name D1_mini)(type KiCad)(uri "$(KIPRJMOD)/lib/D1_mini.pretty")(options "")(descr ""))
|
||||||
|
)
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
(module Pin_Headers:Pin_Header_Straight_1x08 (layer F.Cu) (tedit 5766A5B6)
|
||||||
|
(descr "Through hole pin header")
|
||||||
|
(tags "pin header")
|
||||||
|
(fp_text reference P1 (at 0.11176 -2.43586) (layer F.SilkS)
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_text value CONN_01X08 (at 0 -3.1) (layer F.Fab) hide
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_line (start -1.75 -1.75) (end -1.75 19.55) (layer F.CrtYd) (width 0.05))
|
||||||
|
(fp_line (start 1.75 -1.75) (end 1.75 19.55) (layer F.CrtYd) (width 0.05))
|
||||||
|
(fp_line (start -1.75 -1.75) (end 1.75 -1.75) (layer F.CrtYd) (width 0.05))
|
||||||
|
(fp_line (start -1.75 19.55) (end 1.75 19.55) (layer F.CrtYd) (width 0.05))
|
||||||
|
(pad 1 thru_hole rect (at 0 0) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 2 thru_hole oval (at 0 2.54) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 3 thru_hole oval (at 0 5.08) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 4 thru_hole oval (at 0 7.62) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 5 thru_hole oval (at 0 10.16) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 6 thru_hole oval (at 0 12.7) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 7 thru_hole oval (at 0 15.24) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(pad 8 thru_hole oval (at 0 17.78) (size 1.8 1.8) (drill 1.016) (layers *.Cu *.Mask F.SilkS))
|
||||||
|
(model Pin_Headers.3dshapes/Pin_Header_Straight_1x08.wrl
|
||||||
|
(at (xyz 0 -0.35 0))
|
||||||
|
(scale (xyz 1 1 1))
|
||||||
|
(rotate (xyz 0 0 90))
|
||||||
|
)
|
||||||
|
)
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
(module OSHW (layer F.Cu) (tedit 5766B04E)
|
||||||
|
(descr OSHW)
|
||||||
|
(tags "Symbol, OSHW-Logo, Silk Screen,")
|
||||||
|
(fp_text reference "" (at 0.09906 -4.38912) (layer F.SilkS) hide
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_text value OSHW (at 0 5) (layer F.Fab) hide
|
||||||
|
(effects (font (size 1 1) (thickness 0.15)))
|
||||||
|
)
|
||||||
|
(fp_line (start -1.78054 0.92964) (end -2.03962 1.49098) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -2.03962 1.49098) (end -1.50114 2.00914) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.50114 2.00914) (end -0.98044 1.7399) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.98044 1.7399) (end -0.70104 1.89992) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.73914 1.8796) (end 1.06934 1.6891) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.06934 1.6891) (end 1.50876 2.0193) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.50876 2.0193) (end 1.9812 1.52908) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.9812 1.52908) (end 1.69926 1.04902) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.69926 1.04902) (end 1.88976 0.57912) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.88976 0.57912) (end 2.49936 0.39116) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 2.49936 0.39116) (end 2.49936 -0.28956) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 2.49936 -0.28956) (end 1.94056 -0.42926) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.94056 -0.42926) (end 1.7399 -1.00076) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.7399 -1.00076) (end 2.00914 -1.47066) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 2.00914 -1.47066) (end 1.53924 -1.9812) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.53924 -1.9812) (end 1.02108 -1.71958) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.02108 -1.71958) (end 0.55118 -1.92024) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.55118 -1.92024) (end 0.381 -2.46126) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.381 -2.46126) (end -0.30988 -2.47904) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.30988 -2.47904) (end -0.5207 -1.9304) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.5207 -1.9304) (end -0.9398 -1.76022) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.9398 -1.76022) (end -1.49098 -2.02946) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.49098 -2.02946) (end -2.00914 -1.50114) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -2.00914 -1.50114) (end -1.76022 -0.96012) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.76022 -0.96012) (end -1.9304 -0.48006) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.9304 -0.48006) (end -2.47904 -0.381) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -2.47904 -0.381) (end -2.4892 0.32004) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -2.4892 0.32004) (end -1.9304 0.5207) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.9304 0.5207) (end -1.7907 0.91948) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.35052 0.89916) (end 0.65024 0.7493) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.65024 0.7493) (end 0.8509 0.55118) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.8509 0.55118) (end 1.00076 0.14986) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.00076 0.14986) (end 1.00076 -0.24892) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 1.00076 -0.24892) (end 0.8509 -0.59944) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.8509 -0.59944) (end 0.39878 -0.94996) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.39878 -0.94996) (end -0.0508 -1.00076) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.0508 -1.00076) (end -0.44958 -0.89916) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.44958 -0.89916) (end -0.8509 -0.55118) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.8509 -0.55118) (end -1.00076 -0.09906) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -1.00076 -0.09906) (end -0.94996 0.39878) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.94996 0.39878) (end -0.70104 0.70104) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.70104 0.70104) (end -0.35052 0.89916) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start -0.35052 0.89916) (end -0.70104 1.89992) (layer F.SilkS) (width 0.15))
|
||||||
|
(fp_line (start 0.35052 0.89916) (end 0.7493 1.89992) (layer F.SilkS) (width 0.15))
|
||||||
|
)
|
||||||
BIN
hardware/wemos_mbus_shield/kicad/meta/brd.png
Normal file
|
After Width: | Height: | Size: 198 KiB |
BIN
hardware/wemos_mbus_shield/kicad/meta/icon.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
21
hardware/wemos_mbus_shield/kicad/meta/info.html
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<HTML>
|
||||||
|
<HEAD>
|
||||||
|
<title>D1Shield</title>
|
||||||
|
</HEAD>
|
||||||
|
<BODY>
|
||||||
|
<P>This project template is the basis of an expansion board for the
|
||||||
|
<A HREF="https://www.wemos.cc/en/latest/d1/d1_mini.html" TARGET="blank">D1 mini board</A>.
|
||||||
|
<BR><BR>This base project includes a PCB edge defined
|
||||||
|
as the same size as the D1 mini PCB with the connectors placed
|
||||||
|
correctly to align the two boards. All IO present on the D1 mini
|
||||||
|
board is connected to the project through the expansion
|
||||||
|
headers. <BR><BR>The board looks like the following:
|
||||||
|
</P>
|
||||||
|
<P><IMG SRC="brd.png">
|
||||||
|
</P>
|
||||||
|
<p><i>Dwgs.User</i> layer show mechanical components of the D1mini board.</p>
|
||||||
|
<P>©2016 Jérôme Labidurie<br/>
|
||||||
|
Licence: <a href="https://creativecommons.org/licenses/by-sa/3.0/">CC:BY-SA 3.0</a><br/>
|
||||||
|
<a href="http://dinask.eu">dinask.eu</a></P>
|
||||||
|
</BODY>
|
||||||
|
</HTML>
|
||||||
4
hardware/wemos_mbus_shield/kicad/sym-lib-table
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
(sym_lib_table
|
||||||
|
(lib (name d1_mini_shield-rescue)(type Legacy)(uri ${KIPRJMOD}/d1_mini_shield-rescue.lib)(options "")(descr ""))
|
||||||
|
(lib (name tss721)(type Legacy)(uri ${KIPRJMOD}/tss721.lib)(options "")(descr ""))
|
||||||
|
)
|
||||||
9
hardware/wemos_mbus_shield/kicad/tss721.dcm
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
EESchema-DOCLIB Version 2.0
|
||||||
|
#
|
||||||
|
$CMP TSS721
|
||||||
|
D TSS721A Meter Bus Transceiver, SOIC-16/TSSOP-16
|
||||||
|
K MBUS Tranciever
|
||||||
|
F http://www.ti.com/lit/ds/symlink/tss721a.pdf
|
||||||
|
$ENDCMP
|
||||||
|
#
|
||||||
|
#End Doc Library
|
||||||
37
hardware/wemos_mbus_shield/kicad/tss721.lib
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
EESchema-LIBRARY Version 2.4
|
||||||
|
#encoding utf-8
|
||||||
|
#
|
||||||
|
# TSS721
|
||||||
|
#
|
||||||
|
DEF TSS721 U 0 40 Y Y 1 F N
|
||||||
|
F0 "U" 200 850 50 H V L CNN
|
||||||
|
F1 "TSS721" 200 750 50 H V L CNN
|
||||||
|
F2 "" 0 -850 50 H V C CIN
|
||||||
|
F3 "" -200 -800 50 H V C CNN
|
||||||
|
ALIAS TSS721A
|
||||||
|
$FPLIST
|
||||||
|
SOIC*3.9x9.9mm*Pitch1.27mm*
|
||||||
|
TSSOP*4.4x5mm*Pitch0.65mm*
|
||||||
|
$ENDFPLIST
|
||||||
|
DRAW
|
||||||
|
S -500 -700 500 700 0 1 10 f
|
||||||
|
X BUSL2 1 -600 400 100 R 50 50 1 1 I
|
||||||
|
X VS 10 -600 0 100 R 50 50 1 1 P
|
||||||
|
X VDD 11 0 800 100 D 50 50 1 1 W
|
||||||
|
X RX 12 600 500 100 L 50 50 1 1 I
|
||||||
|
X RXI 13 600 400 100 L 50 50 1 1 I I
|
||||||
|
X RIS 14 300 -800 100 U 50 50 1 1 I
|
||||||
|
X GND 15 0 -800 100 U 50 50 1 1 W
|
||||||
|
X BUSL1 16 -600 500 100 R 50 50 1 1 I
|
||||||
|
X VB 2 -600 -150 100 R 50 50 1 1 P
|
||||||
|
X STC 3 -600 -500 100 R 50 50 1 1 P
|
||||||
|
X RIDD 4 200 -800 100 U 50 50 1 1 O
|
||||||
|
X PF 5 -600 100 100 R 50 50 1 1 I
|
||||||
|
X SC 6 400 -800 100 U 50 50 1 1 P
|
||||||
|
X TXI 7 600 100 100 L 50 50 1 1 O I
|
||||||
|
X TX 8 600 200 100 L 50 50 1 1 O
|
||||||
|
X BAT 9 -100 800 100 D 50 50 1 1 I
|
||||||
|
ENDDRAW
|
||||||
|
ENDDEF
|
||||||
|
#
|
||||||
|
#End Library
|
||||||
BIN
images/dashboard.png
Normal file
|
After Width: | Height: | Size: 136 KiB |
BIN
images/dayplot.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
BIN
images/future-energy-price.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
images/main-header.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
images/monthplot.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
images/real-time-calculation.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
images/sensor-displays.png
Normal file
|
After Width: | Height: | Size: 35 KiB |
BIN
images/status-bar.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
images/tempsensors.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
@@ -4,15 +4,18 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
#define EEPROM_SIZE 1024*3
|
#define EEPROM_SIZE 1024*3
|
||||||
#define EEPROM_CHECK_SUM 92 // 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 224
|
#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
|
||||||
|
#define CONFIG_ENERGYACCOUNTING_START 576
|
||||||
#define CONFIG_WEB_START 648
|
#define CONFIG_WEB_START 648
|
||||||
#define CONFIG_DEBUG_START 824
|
#define CONFIG_DEBUG_START 824
|
||||||
#define CONFIG_DOMOTICZ_START 856
|
#define CONFIG_DOMOTICZ_START 856
|
||||||
@@ -23,11 +26,16 @@
|
|||||||
#define CONFIG_METER_START_87 784
|
#define CONFIG_METER_START_87 784
|
||||||
#define CONFIG_ENTSOE_START_90 286
|
#define CONFIG_ENTSOE_START_90 286
|
||||||
#define CONFIG_WIFI_START_91 16
|
#define CONFIG_WIFI_START_91 16
|
||||||
|
#define CONFIG_METER_START_93 224
|
||||||
|
|
||||||
|
|
||||||
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[2];
|
||||||
|
}; // 6
|
||||||
|
|
||||||
struct WiFiConfig91 {
|
struct WiFiConfig91 {
|
||||||
char ssid[32];
|
char ssid[32];
|
||||||
@@ -51,7 +59,11 @@ struct WiFiConfig {
|
|||||||
char dns2[16];
|
char dns2[16];
|
||||||
char hostname[32];
|
char hostname[32];
|
||||||
bool mdns;
|
bool mdns;
|
||||||
}; // 209
|
uint8_t power;
|
||||||
|
uint8_t sleep;
|
||||||
|
uint8_t mode;
|
||||||
|
bool autoreboot;
|
||||||
|
}; // 213
|
||||||
|
|
||||||
struct MqttConfig86 {
|
struct MqttConfig86 {
|
||||||
char host[128];
|
char host[128];
|
||||||
@@ -84,6 +96,23 @@ 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;
|
uint32_t baud;
|
||||||
uint8_t parity;
|
uint8_t parity;
|
||||||
bool invert;
|
bool invert;
|
||||||
@@ -92,7 +121,30 @@ struct MeterConfig {
|
|||||||
uint8_t productionCapacity;
|
uint8_t productionCapacity;
|
||||||
uint8_t encryptionKey[16];
|
uint8_t encryptionKey[16];
|
||||||
uint8_t authenticationKey[16];
|
uint8_t authenticationKey[16];
|
||||||
}; // 41
|
uint32_t wattageMultiplier;
|
||||||
|
uint32_t voltageMultiplier;
|
||||||
|
uint32_t amperageMultiplier;
|
||||||
|
uint32_t accumulatedMultiplier;
|
||||||
|
uint8_t source;
|
||||||
|
uint8_t parser;
|
||||||
|
}; // 50
|
||||||
|
|
||||||
|
struct MeterConfig95 {
|
||||||
|
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];
|
||||||
|
uint16_t wattageMultiplier;
|
||||||
|
uint16_t voltageMultiplier;
|
||||||
|
uint16_t amperageMultiplier;
|
||||||
|
uint16_t accumulatedMultiplier;
|
||||||
|
uint8_t source;
|
||||||
|
uint8_t parser;
|
||||||
|
}; // 50
|
||||||
|
|
||||||
struct MeterConfig87 {
|
struct MeterConfig87 {
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
@@ -138,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;
|
||||||
@@ -150,73 +209,27 @@ 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 ConfigObject83 {
|
struct EnergyAccountingConfig {
|
||||||
uint8_t boardType;
|
uint8_t thresholds[10];
|
||||||
char wifiSsid[32];
|
uint8_t hours;
|
||||||
char wifiPassword[64];
|
}; // 11
|
||||||
char wifiIp[15];
|
|
||||||
char wifiGw[15];
|
|
||||||
char wifiSubnet[15];
|
|
||||||
char wifiDns1[15];
|
|
||||||
char wifiDns2[15];
|
|
||||||
char wifiHostname[32];
|
|
||||||
char mqttHost[128];
|
|
||||||
uint16_t mqttPort;
|
|
||||||
char mqttClientId[32];
|
|
||||||
char mqttPublishTopic[64];
|
|
||||||
char mqttSubscribeTopic[64];
|
|
||||||
char mqttUser[64];
|
|
||||||
char mqttPassword[64];
|
|
||||||
uint8_t mqttPayloadFormat;
|
|
||||||
bool mqttSsl;
|
|
||||||
uint8_t authSecurity;
|
|
||||||
char authUser[64];
|
|
||||||
char authPassword[64];
|
|
||||||
|
|
||||||
uint8_t meterType;
|
struct UiConfig {
|
||||||
uint8_t distributionSystem;
|
uint8_t showImport;
|
||||||
uint8_t mainFuse;
|
uint8_t showExport;
|
||||||
uint8_t productionCapacity;
|
uint8_t showVoltage;
|
||||||
uint8_t meterEncryptionKey[16];
|
uint8_t showAmperage;
|
||||||
uint8_t meterAuthenticationKey[16];
|
uint8_t showReactive;
|
||||||
bool substituteMissing;
|
uint8_t showRealtime;
|
||||||
bool sendUnknown;
|
uint8_t showPeaks;
|
||||||
|
uint8_t showPricePlot;
|
||||||
bool debugTelnet;
|
uint8_t showDayPlot;
|
||||||
bool debugSerial;
|
uint8_t showMonthPlot;
|
||||||
uint8_t debugLevel;
|
uint8_t showTemperaturePlot;
|
||||||
|
}; // 11
|
||||||
uint8_t hanPin;
|
|
||||||
uint8_t apPin;
|
|
||||||
uint8_t ledPin;
|
|
||||||
bool ledInverted;
|
|
||||||
uint8_t ledPinRed;
|
|
||||||
uint8_t ledPinGreen;
|
|
||||||
uint8_t ledPinBlue;
|
|
||||||
bool ledRgbInverted;
|
|
||||||
uint8_t tempSensorPin;
|
|
||||||
uint8_t vccPin;
|
|
||||||
int16_t vccOffset;
|
|
||||||
uint16_t vccMultiplier;
|
|
||||||
uint8_t vccBootLimit;
|
|
||||||
|
|
||||||
uint16_t domoELIDX;
|
|
||||||
uint16_t domoVL1IDX;
|
|
||||||
uint16_t domoVL2IDX;
|
|
||||||
uint16_t domoVL3IDX;
|
|
||||||
uint16_t domoCL1IDX;
|
|
||||||
|
|
||||||
bool mDnsEnable;
|
|
||||||
bool ntpEnable;
|
|
||||||
bool ntpDhcp;
|
|
||||||
int16_t ntpOffset;
|
|
||||||
int16_t ntpSummerOffset;
|
|
||||||
char ntpServer[64];
|
|
||||||
|
|
||||||
uint8_t tempAnalogSensorPin;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TempSensorConfig {
|
struct TempSensorConfig {
|
||||||
uint8_t address[8];
|
uint8_t address[8];
|
||||||
@@ -288,6 +301,16 @@ public:
|
|||||||
bool isEntsoeChanged();
|
bool isEntsoeChanged();
|
||||||
void ackEntsoeChange();
|
void ackEntsoeChange();
|
||||||
|
|
||||||
|
bool getEnergyAccountingConfig(EnergyAccountingConfig&);
|
||||||
|
bool setEnergyAccountingConfig(EnergyAccountingConfig&);
|
||||||
|
void clearEnergyAccountingConfig(EnergyAccountingConfig&);
|
||||||
|
bool isEnergyAccountingChanged();
|
||||||
|
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();
|
||||||
@@ -303,20 +326,22 @@ protected:
|
|||||||
private:
|
private:
|
||||||
uint8_t configVersion = 0;
|
uint8_t configVersion = 0;
|
||||||
|
|
||||||
bool wifiChanged, mqttChanged, meterChanged = true, domoChanged, ntpChanged = true, entsoeChanged = false;
|
bool wifiChanged, mqttChanged, meterChanged = true, domoChanged, ntpChanged = true, entsoeChanged = false, energyAccountingChanged = true;
|
||||||
|
|
||||||
uint8_t tempSensorCount = 0;
|
uint8_t tempSensorCount = 0;
|
||||||
TempSensorConfig** tempSensors = NULL;
|
TempSensorConfig** tempSensors = NULL;
|
||||||
|
|
||||||
bool loadConfig83(int address);
|
|
||||||
bool relocateConfig86();
|
|
||||||
bool relocateConfig87();
|
|
||||||
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 relocateConfig93(); // 2.1.0
|
||||||
|
bool relocateConfig94(); // 2.1.0
|
||||||
|
bool relocateConfig95(); // 2.1.4
|
||||||
|
bool relocateConfig96(); // 2.1.14
|
||||||
|
bool relocateConfig100(); // 2.2-dev
|
||||||
|
|
||||||
int readString(int pAddress, char* pString[]);
|
void saveToFs();
|
||||||
int readInt(int pAddress, int *pValue);
|
bool loadFromFs(uint8_t version);
|
||||||
int readBool(int pAddress, bool *pValue);
|
void deleteFromFs(uint8_t version);
|
||||||
int readByte(int pAddress, byte *pValue);
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -9,5 +9,8 @@
|
|||||||
|
|
||||||
#define FILE_DAYPLOT "/dayplot.bin"
|
#define FILE_DAYPLOT "/dayplot.bin"
|
||||||
#define FILE_MONTHPLOT "/monthplot.bin"
|
#define FILE_MONTHPLOT "/monthplot.bin"
|
||||||
|
#define FILE_ENERGYACCOUNTING "/energyaccounting.bin"
|
||||||
|
|
||||||
|
#define FILE_CFG "/configfile.cfg"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
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;
|
||||||
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "Arduino.h"
|
#include "Arduino.h"
|
||||||
|
|
||||||
String toHex(uint8_t* in);
|
String toHex(uint8_t* in);
|
||||||
String toHex(uint8_t* in, uint8_t size);
|
String toHex(uint8_t* in, uint16_t size);
|
||||||
void fromHex(uint8_t *out, String in, uint8_t size);
|
void fromHex(uint8_t *out, String in, uint16_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,12 +1,18 @@
|
|||||||
#include "AmsConfiguration.h"
|
#include "AmsConfiguration.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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -24,6 +30,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,15 +40,22 @@ 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;
|
||||||
wifiChanged |= strcmp(config.ip, existing.ip) != 0;
|
wifiChanged |= strcmp(config.ip, existing.ip) != 0;
|
||||||
wifiChanged |= strcmp(config.gateway, existing.gateway) != 0;
|
if(strlen(config.ip) > 0) {
|
||||||
wifiChanged |= strcmp(config.subnet, existing.subnet) != 0;
|
wifiChanged |= strcmp(config.gateway, existing.gateway) != 0;
|
||||||
wifiChanged |= strcmp(config.dns1, existing.dns1) != 0;
|
wifiChanged |= strcmp(config.subnet, existing.subnet) != 0;
|
||||||
wifiChanged |= strcmp(config.dns2, existing.dns2) != 0;
|
wifiChanged |= strcmp(config.dns1, existing.dns1) != 0;
|
||||||
|
wifiChanged |= strcmp(config.dns2, existing.dns2) != 0;
|
||||||
|
}
|
||||||
wifiChanged |= strcmp(config.hostname, existing.hostname) != 0;
|
wifiChanged |= strcmp(config.hostname, existing.hostname) != 0;
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -60,11 +74,14 @@ void AmsConfiguration::clearWifi(WiFiConfig& config) {
|
|||||||
uint16_t chipId;
|
uint16_t chipId;
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
chipId = ESP.getEfuseMac();
|
chipId = ESP.getEfuseMac();
|
||||||
|
config.power = 195;
|
||||||
#else
|
#else
|
||||||
chipId = ESP.getChipId();
|
chipId = ESP.getChipId();
|
||||||
|
config.power = 205;
|
||||||
#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) {
|
||||||
@@ -201,14 +218,20 @@ 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 = 0;
|
||||||
config.mainFuse = 0;
|
config.mainFuse = 0;
|
||||||
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);
|
||||||
|
config.wattageMultiplier = 0;
|
||||||
|
config.voltageMultiplier = 0;
|
||||||
|
config.amperageMultiplier = 0;
|
||||||
|
config.accumulatedMultiplier = 0;
|
||||||
|
config.source = 1; // Serial
|
||||||
|
config.parser = 0; // Auto
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::isMeterChanged() {
|
bool AmsConfiguration::isMeterChanged() {
|
||||||
@@ -232,6 +255,8 @@ bool AmsConfiguration::getDebugConfig(DebugConfig& config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::setDebugConfig(DebugConfig& config) {
|
bool AmsConfiguration::setDebugConfig(DebugConfig& config) {
|
||||||
|
if(!config.serial && !config.telnet)
|
||||||
|
config.level = 4; // Force warning level when debug is disabled
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.put(CONFIG_DEBUG_START, config);
|
EEPROM.put(CONFIG_DEBUG_START, config);
|
||||||
bool ret = EEPROM.commit();
|
bool ret = EEPROM.commit();
|
||||||
@@ -415,9 +440,8 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -439,9 +463,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) {
|
||||||
@@ -449,6 +472,9 @@ bool AmsConfiguration::getEntsoeConfig(EntsoeConfig& config) {
|
|||||||
EEPROM.begin(EEPROM_SIZE);
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
EEPROM.get(CONFIG_ENTSOE_START, config);
|
EEPROM.get(CONFIG_ENTSOE_START, config);
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
|
if(strlen(config.token) != 0 && strlen(config.token) != 36) {
|
||||||
|
clearEntsoe(config);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@@ -462,6 +488,7 @@ 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;
|
||||||
}
|
}
|
||||||
@@ -487,8 +514,112 @@ void AmsConfiguration::ackEntsoeChange() {
|
|||||||
entsoeChanged = false;
|
entsoeChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool AmsConfiguration::getEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||||
|
if(hasConfig()) {
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_ENERGYACCOUNTING_START, config);
|
||||||
|
EEPROM.end();
|
||||||
|
if(config.thresholds[9] != 255) {
|
||||||
|
clearEnergyAccountingConfig(config);
|
||||||
|
}
|
||||||
|
if(config.hours > 5) config.hours = 5;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::setEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||||
|
if(config.hours > 5) config.hours = 5;
|
||||||
|
EnergyAccountingConfig existing;
|
||||||
|
if(getEnergyAccountingConfig(existing)) {
|
||||||
|
for(int i = 0; i < 9; i++) {
|
||||||
|
if(existing.thresholds[i] != config.thresholds[i]) {
|
||||||
|
energyAccountingChanged = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
config.thresholds[9] = 255;
|
||||||
|
energyAccountingChanged |= config.hours != existing.hours;
|
||||||
|
} else {
|
||||||
|
energyAccountingChanged = true;
|
||||||
|
}
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, config);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsConfiguration::clearEnergyAccountingConfig(EnergyAccountingConfig& config) {
|
||||||
|
config.thresholds[0] = 5;
|
||||||
|
config.thresholds[1] = 10;
|
||||||
|
config.thresholds[2] = 15;
|
||||||
|
config.thresholds[3] = 20;
|
||||||
|
config.thresholds[4] = 25;
|
||||||
|
config.thresholds[5] = 50;
|
||||||
|
config.thresholds[6] = 75;
|
||||||
|
config.thresholds[7] = 100;
|
||||||
|
config.thresholds[8] = 150;
|
||||||
|
config.thresholds[9] = 255;
|
||||||
|
config.hours = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::isEnergyAccountingChanged() {
|
||||||
|
return energyAccountingChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsConfiguration::ackEnergyAccountingChange() {
|
||||||
|
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);
|
||||||
@@ -517,7 +648,19 @@ void AmsConfiguration::clear() {
|
|||||||
clearEntsoe(entsoe);
|
clearEntsoe(entsoe);
|
||||||
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
|
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
|
||||||
|
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, -1);
|
EnergyAccountingConfig eac;
|
||||||
|
clearEnergyAccountingConfig(eac);
|
||||||
|
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||||
|
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
@@ -528,54 +671,84 @@ bool AmsConfiguration::hasConfig() {
|
|||||||
configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
configVersion = EEPROM.read(EEPROM_CONFIG_ADDRESS);
|
||||||
EEPROM.end();
|
EEPROM.end();
|
||||||
}
|
}
|
||||||
switch(configVersion) {
|
if(configVersion > EEPROM_CHECK_SUM) {
|
||||||
case 83:
|
if(loadFromFs(EEPROM_CHECK_SUM)) {
|
||||||
configVersion = -1; // Prevent loop
|
configVersion = EEPROM_CHECK_SUM;
|
||||||
if(loadConfig83(EEPROM_CONFIG_ADDRESS+1)) {
|
} else {
|
||||||
configVersion = EEPROM_CHECK_SUM;
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
configVersion = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
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:
|
|
||||||
configVersion = -1; // Prevent loop
|
|
||||||
if(relocateConfig90()) {
|
|
||||||
configVersion = 91;
|
|
||||||
} else {
|
|
||||||
configVersion = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case 91:
|
|
||||||
configVersion = -1; // Prevent loop
|
|
||||||
if(relocateConfig91()) {
|
|
||||||
configVersion = 92;
|
|
||||||
} else {
|
|
||||||
configVersion = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
case EEPROM_CHECK_SUM:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
configVersion = 0;
|
configVersion = 0;
|
||||||
return false;
|
}
|
||||||
|
} else {
|
||||||
|
switch(configVersion) {
|
||||||
|
case 90:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig90()) {
|
||||||
|
configVersion = 91;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 91:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig91()) {
|
||||||
|
configVersion = 92;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 92:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig92()) {
|
||||||
|
configVersion = 93;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 93:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig93()) {
|
||||||
|
configVersion = 94;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
case 94:
|
||||||
|
configVersion = -1; // Prevent loop
|
||||||
|
if(relocateConfig94()) {
|
||||||
|
configVersion = 95;
|
||||||
|
} else {
|
||||||
|
configVersion = 0;
|
||||||
|
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:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
configVersion = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return configVersion == EEPROM_CHECK_SUM;
|
return configVersion == EEPROM_CHECK_SUM;
|
||||||
}
|
}
|
||||||
@@ -622,161 +795,6 @@ void AmsConfiguration::saveTempSensors() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmsConfiguration::loadConfig83(int address) {
|
|
||||||
ConfigObject83 c;
|
|
||||||
EEPROM.begin(EEPROM_SIZE);
|
|
||||||
EEPROM.get(address, c);
|
|
||||||
|
|
||||||
EntsoeConfig entsoe {"", "", "", 1000};
|
|
||||||
EEPROM.put(CONFIG_ENTSOE_START, entsoe);
|
|
||||||
|
|
||||||
NtpConfig ntp {
|
|
||||||
c.ntpEnable,
|
|
||||||
c.ntpDhcp,
|
|
||||||
c.ntpOffset,
|
|
||||||
c.ntpSummerOffset
|
|
||||||
};
|
|
||||||
strcpy(ntp.server, c.ntpServer);
|
|
||||||
EEPROM.put(CONFIG_NTP_START, ntp);
|
|
||||||
|
|
||||||
DomoticzConfig domo {
|
|
||||||
c.domoELIDX,
|
|
||||||
c.domoVL1IDX,
|
|
||||||
c.domoVL2IDX,
|
|
||||||
c.domoVL3IDX,
|
|
||||||
c.domoCL1IDX
|
|
||||||
};
|
|
||||||
EEPROM.put(CONFIG_DOMOTICZ_START, domo);
|
|
||||||
|
|
||||||
GpioConfig gpio {
|
|
||||||
c.hanPin,
|
|
||||||
c.apPin,
|
|
||||||
c.ledPin,
|
|
||||||
c.ledInverted,
|
|
||||||
c.ledPinRed,
|
|
||||||
c.ledPinGreen,
|
|
||||||
c.ledPinBlue,
|
|
||||||
c.ledRgbInverted,
|
|
||||||
c.tempSensorPin,
|
|
||||||
c.tempAnalogSensorPin,
|
|
||||||
c.vccPin,
|
|
||||||
c.vccOffset,
|
|
||||||
c.vccMultiplier,
|
|
||||||
c.vccBootLimit,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
};
|
|
||||||
EEPROM.put(CONFIG_GPIO_START, gpio);
|
|
||||||
|
|
||||||
DebugConfig debug {
|
|
||||||
c.debugTelnet,
|
|
||||||
c.debugSerial,
|
|
||||||
c.debugLevel
|
|
||||||
};
|
|
||||||
EEPROM.put(CONFIG_DEBUG_START, debug);
|
|
||||||
|
|
||||||
MeterConfig meter {
|
|
||||||
2400,
|
|
||||||
c.meterType == 3 || c.meterType == 4 ? 3 : 11,
|
|
||||||
false,
|
|
||||||
c.distributionSystem,
|
|
||||||
c.mainFuse,
|
|
||||||
c.productionCapacity,
|
|
||||||
{0},
|
|
||||||
{0}
|
|
||||||
};
|
|
||||||
memcpy(meter.encryptionKey, c.meterEncryptionKey, 16);
|
|
||||||
memcpy(meter.authenticationKey, c.meterAuthenticationKey, 16);
|
|
||||||
EEPROM.put(CONFIG_METER_START, meter);
|
|
||||||
|
|
||||||
WebConfig web {
|
|
||||||
c.authSecurity
|
|
||||||
};
|
|
||||||
strcpy(web.username, c.authUser);
|
|
||||||
strcpy(web.password, c.authPassword);
|
|
||||||
EEPROM.put(CONFIG_WEB_START, web);
|
|
||||||
|
|
||||||
MqttConfig mqtt;
|
|
||||||
strcpy(mqtt.host, c.mqttHost);
|
|
||||||
mqtt.port = c.mqttPort;
|
|
||||||
strcpy(mqtt.clientId, c.mqttClientId);
|
|
||||||
strcpy(mqtt.publishTopic, c.mqttPublishTopic);
|
|
||||||
strcpy(mqtt.subscribeTopic, c.mqttSubscribeTopic);
|
|
||||||
strcpy(mqtt.username, c.mqttUser);
|
|
||||||
strcpy(mqtt.password, c.mqttPassword);
|
|
||||||
mqtt.payloadFormat = c.mqttPayloadFormat;
|
|
||||||
mqtt.ssl = c.mqttSsl;
|
|
||||||
EEPROM.put(CONFIG_MQTT_START, mqtt);
|
|
||||||
|
|
||||||
WiFiConfig wifi;
|
|
||||||
strcpy(wifi.ssid, c.wifiSsid);
|
|
||||||
strcpy(wifi.psk, c.wifiPassword);
|
|
||||||
strcpy(wifi.ip, c.wifiIp);
|
|
||||||
strcpy(wifi.gateway, c.wifiGw);
|
|
||||||
strcpy(wifi.subnet, c.wifiSubnet);
|
|
||||||
strcpy(wifi.dns1, c.wifiDns1);
|
|
||||||
strcpy(wifi.dns2, c.wifiDns2);
|
|
||||||
strcpy(wifi.hostname, c.wifiHostname);
|
|
||||||
wifi.mdns = c.mDnsEnable;
|
|
||||||
EEPROM.put(CONFIG_WIFI_START, wifi);
|
|
||||||
|
|
||||||
SystemConfig sys {
|
|
||||||
c.boardType
|
|
||||||
};
|
|
||||||
EEPROM.put(CONFIG_SYSTEM_START, sys);
|
|
||||||
|
|
||||||
EEPROM.put(EEPROM_CONFIG_ADDRESS, EEPROM_CHECK_SUM);
|
|
||||||
bool ret = EEPROM.commit();
|
|
||||||
EEPROM.end();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
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);
|
||||||
@@ -809,6 +827,177 @@ bool AmsConfiguration::relocateConfig91() {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig92() {
|
||||||
|
WiFiConfig wifi;
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_WIFI_START, wifi);
|
||||||
|
#if defined(ESP32)
|
||||||
|
wifi.power = 195;
|
||||||
|
#elif defined(ESP8266)
|
||||||
|
wifi.power = 205;
|
||||||
|
#endif
|
||||||
|
EEPROM.put(CONFIG_WIFI_START, wifi);
|
||||||
|
|
||||||
|
EnergyAccountingConfig eac;
|
||||||
|
clearEnergyAccountingConfig(eac);
|
||||||
|
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||||
|
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 93);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig93() {
|
||||||
|
MeterConfig meter;
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_METER_START_93, meter);
|
||||||
|
meter.wattageMultiplier = 0;
|
||||||
|
meter.voltageMultiplier = 0;
|
||||||
|
meter.amperageMultiplier = 0;
|
||||||
|
meter.accumulatedMultiplier = 0;
|
||||||
|
EEPROM.put(CONFIG_METER_START, meter);
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 94);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsConfiguration::relocateConfig94() {
|
||||||
|
EnergyAccountingConfig eac;
|
||||||
|
EEPROM.begin(EEPROM_SIZE);
|
||||||
|
EEPROM.get(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||||
|
eac.hours = 1;
|
||||||
|
EEPROM.put(CONFIG_ENERGYACCOUNTING_START, eac);
|
||||||
|
EEPROM.put(EEPROM_CONFIG_ADDRESS, 95);
|
||||||
|
bool ret = EEPROM.commit();
|
||||||
|
EEPROM.end();
|
||||||
|
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);
|
||||||
@@ -874,37 +1063,16 @@ bool AmsConfiguration::isSensorAddressEqual(uint8_t a[8], uint8_t b[8]) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AmsConfiguration::saveToFs() {
|
||||||
int AmsConfiguration::readString(int pAddress, char* pString[]) {
|
|
||||||
int address = 0;
|
|
||||||
byte length = EEPROM.read(pAddress + address);
|
|
||||||
address++;
|
|
||||||
|
|
||||||
char* buffer = new char[length];
|
|
||||||
for (int i = 0; i<length; i++)
|
|
||||||
{
|
|
||||||
buffer[i] = EEPROM.read(pAddress + address++);
|
|
||||||
}
|
|
||||||
*pString = buffer;
|
|
||||||
return address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmsConfiguration::readInt(int address, int *value) {
|
bool AmsConfiguration::loadFromFs(uint8_t version) {
|
||||||
int lower = EEPROM.read(address);
|
return false;
|
||||||
int higher = EEPROM.read(address + 1);
|
|
||||||
*value = lower + (higher << 8);
|
|
||||||
return 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int AmsConfiguration::readBool(int address, bool *value) {
|
void AmsConfiguration::deleteFromFs(uint8_t version) {
|
||||||
byte y = EEPROM.read(address);
|
|
||||||
*value = (bool)y;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int AmsConfiguration::readByte(int address, byte *value) {
|
|
||||||
*value = EEPROM.read(address);
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AmsConfiguration::print(Print* debugger)
|
void AmsConfiguration::print(Print* debugger)
|
||||||
@@ -1033,8 +1201,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");
|
||||||
}
|
}
|
||||||
@@ -1045,12 +1212,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);
|
||||||
@@ -4,7 +4,7 @@ String toHex(uint8_t* in) {
|
|||||||
return toHex(in, sizeof(in)*2);
|
return toHex(in, sizeof(in)*2);
|
||||||
}
|
}
|
||||||
|
|
||||||
String toHex(uint8_t* in, uint8_t size) {
|
String toHex(uint8_t* in, uint16_t size) {
|
||||||
String hex;
|
String hex;
|
||||||
for(int i = 0; i < size; i++) {
|
for(int i = 0; i < size; i++) {
|
||||||
if(in[i] < 0x10) {
|
if(in[i] < 0x10) {
|
||||||
@@ -16,7 +16,7 @@ String toHex(uint8_t* in, uint8_t size) {
|
|||||||
return hex;
|
return hex;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fromHex(uint8_t *out, String in, uint8_t size) {
|
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);
|
||||||
}
|
}
|
||||||
@@ -10,7 +10,7 @@ enum AmsType {
|
|||||||
AmsTypeKaifa = 0x02,
|
AmsTypeKaifa = 0x02,
|
||||||
AmsTypeKamstrup = 0x03,
|
AmsTypeKamstrup = 0x03,
|
||||||
AmsTypeIskra = 0x08,
|
AmsTypeIskra = 0x08,
|
||||||
AmsTypeLandis = 0x09,
|
AmsTypeLandisGyr = 0x09,
|
||||||
AmsTypeSagemcom = 0x0A,
|
AmsTypeSagemcom = 0x0A,
|
||||||
AmsTypeCustom = 0x88,
|
AmsTypeCustom = 0x88,
|
||||||
AmsTypeUnknown = 0xFF
|
AmsTypeUnknown = 0xFF
|
||||||
@@ -53,14 +53,25 @@ public:
|
|||||||
float getL2PowerFactor();
|
float getL2PowerFactor();
|
||||||
float getL3PowerFactor();
|
float getL3PowerFactor();
|
||||||
|
|
||||||
float getActiveImportCounter();
|
float getL1ActiveImportPower();
|
||||||
float getReactiveImportCounter();
|
float getL2ActiveImportPower();
|
||||||
float getActiveExportCounter();
|
float getL3ActiveImportPower();
|
||||||
float getReactiveExportCounter();
|
|
||||||
|
float getL1ActiveExportPower();
|
||||||
|
float getL2ActiveExportPower();
|
||||||
|
float getL3ActiveExportPower();
|
||||||
|
|
||||||
|
double getActiveImportCounter();
|
||||||
|
double getReactiveImportCounter();
|
||||||
|
double getActiveExportCounter();
|
||||||
|
double getReactiveExportCounter();
|
||||||
|
|
||||||
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;
|
||||||
@@ -70,9 +81,14 @@ protected:
|
|||||||
time_t meterTimestamp = 0;
|
time_t meterTimestamp = 0;
|
||||||
uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
|
uint16_t activeImportPower = 0, reactiveImportPower = 0, activeExportPower = 0, reactiveExportPower = 0;
|
||||||
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
|
float l1voltage = 0, l2voltage = 0, l3voltage = 0, l1current = 0, l2current = 0, l3current = 0;
|
||||||
|
float l1activeImportPower = 0, l2activeImportPower = 0, l3activeImportPower = 0;
|
||||||
|
float l1activeExportPower = 0, l2activeExportPower = 0, l3activeExportPower = 0;
|
||||||
float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0;
|
float powerFactor = 0, l1PowerFactor = 0, l2PowerFactor = 0, l3PowerFactor = 0;
|
||||||
float 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
|
||||||
@@ -5,22 +5,27 @@
|
|||||||
#include <MQTT.h>
|
#include <MQTT.h>
|
||||||
#include "AmsData.h"
|
#include "AmsData.h"
|
||||||
#include "AmsConfiguration.h"
|
#include "AmsConfiguration.h"
|
||||||
|
#include "EnergyAccounting.h"
|
||||||
#include "HwTools.h"
|
#include "HwTools.h"
|
||||||
#include "entsoe/EntsoeApi.h"
|
#include "EntsoeApi.h"
|
||||||
|
|
||||||
class AmsMqttHandler {
|
class AmsMqttHandler {
|
||||||
public:
|
public:
|
||||||
AmsMqttHandler(MQTTClient* mqtt) {
|
AmsMqttHandler(MQTTClient* mqtt, char* buf) {
|
||||||
this->mqtt = mqtt;
|
this->mqtt = mqtt;
|
||||||
|
this->json = buf;
|
||||||
};
|
};
|
||||||
|
virtual ~AmsMqttHandler() {};
|
||||||
|
|
||||||
virtual bool publish(AmsData* data, AmsData* previousState);
|
virtual bool publish(AmsData* data, AmsData* previousState, EnergyAccounting* ea);
|
||||||
virtual bool publishTemperatures(AmsConfiguration*, HwTools*);
|
virtual bool publishTemperatures(AmsConfiguration*, HwTools*);
|
||||||
virtual bool publishPrices(EntsoeApi* eapi);
|
virtual bool publishPrices(EntsoeApi* eapi);
|
||||||
virtual bool publishSystem(HwTools*);
|
virtual bool publishSystem(HwTools*, EntsoeApi*, EnergyAccounting*);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MQTTClient* mqtt;
|
MQTTClient* mqtt;
|
||||||
|
char* json;
|
||||||
|
uint16_t BufferSize = 1024;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -40,11 +40,18 @@ void AmsData::apply(AmsData& other) {
|
|||||||
if(other.getListType() > this->listType)
|
if(other.getListType() > this->listType)
|
||||||
this->listType = other.getListType();
|
this->listType = other.getListType();
|
||||||
switch(other.getListType()) {
|
switch(other.getListType()) {
|
||||||
case 3:
|
case 4:
|
||||||
this->powerFactor = other.getPowerFactor();
|
this->powerFactor = other.getPowerFactor();
|
||||||
this->l1PowerFactor = other.getL1PowerFactor();
|
this->l1PowerFactor = other.getL1PowerFactor();
|
||||||
this->l2PowerFactor = other.getL2PowerFactor();
|
this->l2PowerFactor = other.getL2PowerFactor();
|
||||||
this->l3PowerFactor = other.getL3PowerFactor();
|
this->l3PowerFactor = other.getL3PowerFactor();
|
||||||
|
this->l1activeImportPower = other.getL1ActiveImportPower();
|
||||||
|
this->l2activeImportPower = other.getL2ActiveImportPower();
|
||||||
|
this->l3activeImportPower = other.getL3ActiveImportPower();
|
||||||
|
this->l1activeExportPower = other.getL1ActiveExportPower();
|
||||||
|
this->l2activeExportPower = other.getL2ActiveExportPower();
|
||||||
|
this->l3activeExportPower = other.getL3ActiveExportPower();
|
||||||
|
case 3:
|
||||||
this->meterTimestamp = other.getMeterTimestamp();
|
this->meterTimestamp = other.getMeterTimestamp();
|
||||||
this->activeImportCounter = other.getActiveImportCounter();
|
this->activeImportCounter = other.getActiveImportCounter();
|
||||||
this->activeExportCounter = other.getActiveExportCounter();
|
this->activeExportCounter = other.getActiveExportCounter();
|
||||||
@@ -57,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();
|
||||||
@@ -67,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() {
|
||||||
@@ -160,19 +170,43 @@ float AmsData::getL3PowerFactor() {
|
|||||||
return this->l3PowerFactor;
|
return this->l3PowerFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
float AmsData::getActiveImportCounter() {
|
float AmsData::getL1ActiveImportPower() {
|
||||||
|
return this->l1activeImportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmsData::getL2ActiveImportPower() {
|
||||||
|
return this->l2activeImportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmsData::getL3ActiveImportPower() {
|
||||||
|
return this->l3activeImportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmsData::getL1ActiveExportPower() {
|
||||||
|
return this->l1activeExportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmsData::getL2ActiveExportPower() {
|
||||||
|
return this->l2activeExportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AmsData::getL3ActiveExportPower() {
|
||||||
|
return this->l3activeExportPower;
|
||||||
|
}
|
||||||
|
|
||||||
|
double AmsData::getActiveImportCounter() {
|
||||||
return this->activeImportCounter;
|
return this->activeImportCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
float AmsData::getReactiveImportCounter() {
|
double AmsData::getReactiveImportCounter() {
|
||||||
return this->reactiveImportCounter;
|
return this->reactiveImportCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
float AmsData::getActiveExportCounter() {
|
double AmsData::getActiveExportCounter() {
|
||||||
return this->activeExportCounter;
|
return this->activeExportCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
float AmsData::getReactiveExportCounter() {
|
double AmsData::getReactiveExportCounter() {
|
||||||
return this->reactiveExportCounter;
|
return this->reactiveExportCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
77
lib/AmsDataStorage/include/AmsDataStorage.h
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
#ifndef _AMSDATASTORAGE_H
|
||||||
|
#define _AMSDATASTORAGE_H
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "AmsData.h"
|
||||||
|
#include "RemoteDebug.h"
|
||||||
|
#include "Timezone.h"
|
||||||
|
|
||||||
|
struct DayDataPoints {
|
||||||
|
uint8_t version;
|
||||||
|
uint16_t hImport[24];
|
||||||
|
time_t lastMeterReadTime;
|
||||||
|
uint32_t activeImport;
|
||||||
|
uint32_t activeExport;
|
||||||
|
uint16_t hExport[24];
|
||||||
|
uint8_t accuracy;
|
||||||
|
}; // 113 bytes
|
||||||
|
|
||||||
|
struct MonthDataPoints {
|
||||||
|
uint8_t version;
|
||||||
|
uint16_t dImport[31];
|
||||||
|
time_t lastMeterReadTime;
|
||||||
|
uint32_t activeImport;
|
||||||
|
uint32_t activeExport;
|
||||||
|
uint16_t dExport[31];
|
||||||
|
uint8_t accuracy;
|
||||||
|
}; // 142 bytes
|
||||||
|
|
||||||
|
class AmsDataStorage {
|
||||||
|
public:
|
||||||
|
AmsDataStorage(RemoteDebug*);
|
||||||
|
void setTimezone(Timezone*);
|
||||||
|
bool update(AmsData*);
|
||||||
|
uint32_t getHourImport(uint8_t);
|
||||||
|
uint32_t getHourExport(uint8_t);
|
||||||
|
uint32_t getDayImport(uint8_t);
|
||||||
|
uint32_t getDayExport(uint8_t);
|
||||||
|
bool load();
|
||||||
|
bool save();
|
||||||
|
|
||||||
|
DayDataPoints getDayData();
|
||||||
|
bool setDayData(DayDataPoints&);
|
||||||
|
MonthDataPoints getMonthData();
|
||||||
|
bool setMonthData(MonthDataPoints&);
|
||||||
|
|
||||||
|
uint8_t getDayAccuracy();
|
||||||
|
void setDayAccuracy(uint8_t);
|
||||||
|
uint8_t getMonthAccuracy();
|
||||||
|
void setMonthAccuracy(uint8_t);
|
||||||
|
|
||||||
|
bool isHappy();
|
||||||
|
bool isDayHappy();
|
||||||
|
bool isMonthHappy();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Timezone* tz;
|
||||||
|
DayDataPoints day = {
|
||||||
|
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 = {
|
||||||
|
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;
|
||||||
|
void setHourImport(uint8_t, uint32_t);
|
||||||
|
void setHourExport(uint8_t, uint32_t);
|
||||||
|
void setDayImport(uint8_t, uint32_t);
|
||||||
|
void setDayExport(uint8_t, uint32_t);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
590
lib/AmsDataStorage/src/AmsDataStorage.cpp
Normal file
@@ -0,0 +1,590 @@
|
|||||||
|
#include "AmsDataStorage.h"
|
||||||
|
#include <lwip/apps/sntp.h>
|
||||||
|
#include "LittleFS.h"
|
||||||
|
#include "AmsStorage.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
AmsDataStorage::AmsDataStorage(RemoteDebug* debugger) {
|
||||||
|
day.version = 5;
|
||||||
|
day.accuracy = 1;
|
||||||
|
month.version = 6;
|
||||||
|
month.accuracy = 1;
|
||||||
|
this->debugger = debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setTimezone(Timezone* tz) {
|
||||||
|
this->tz = tz;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::update(AmsData* data) {
|
||||||
|
if(isHappy()) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Data is up to date\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Time is: %lu\n", (int32_t) now);
|
||||||
|
if(tz == NULL) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(now < BUILD_EPOCH) {
|
||||||
|
if(data->getMeterTimestamp() > BUILD_EPOCH) {
|
||||||
|
now = data->getMeterTimestamp();
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Using meter timestamp, which is: %lu\n", (int32_t) now);
|
||||||
|
}
|
||||||
|
} else if(data->getPackageTimestamp() > BUILD_EPOCH) {
|
||||||
|
now = data->getPackageTimestamp();
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Using package timestamp, which is: %lu\n", (int32_t) now);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(now < BUILD_EPOCH) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Invalid time: %lu\n", (int32_t) now);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
tmElements_t utc, ltz, utcYesterday, ltzYesterDay;
|
||||||
|
breakTime(now, utc);
|
||||||
|
breakTime(tz->toLocal(now), ltz);
|
||||||
|
breakTime(now-3600, utcYesterday);
|
||||||
|
breakTime(tz->toLocal(now-3600), ltzYesterDay);
|
||||||
|
|
||||||
|
// Clear hours between last update and now
|
||||||
|
if(day.lastMeterReadTime > now) {
|
||||||
|
if(debugger->isActive(RemoteDebug::WARNING)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Invalid future timestamp for day plot, resetting\n");
|
||||||
|
}
|
||||||
|
day.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
day.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
day.lastMeterReadTime = now;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Last day update: %lu\n", (int32_t) day.lastMeterReadTime);
|
||||||
|
}
|
||||||
|
tmElements_t last;
|
||||||
|
breakTime(day.lastMeterReadTime, last);
|
||||||
|
for(int i = last.Hour; i < utc.Hour; i++) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Clearing hour: %d\n", i);
|
||||||
|
}
|
||||||
|
setHourImport(i, 0);
|
||||||
|
setHourExport(i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear days between last update and now
|
||||||
|
if(month.lastMeterReadTime > now) {
|
||||||
|
if(debugger->isActive(RemoteDebug::WARNING)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Invalid future timestamp for month plot, resetting\n");
|
||||||
|
}
|
||||||
|
month.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
month.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
month.lastMeterReadTime = now;
|
||||||
|
} else {
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Last month update: %lu\n", (int32_t) month.lastMeterReadTime);
|
||||||
|
}
|
||||||
|
tmElements_t last;
|
||||||
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
|
for(int i = last.Day; i < ltz.Day; i++) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Clearing day: %d\n", i);
|
||||||
|
}
|
||||||
|
setDayImport(i, 0);
|
||||||
|
setDayExport(i, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data->getListType() < 3) {
|
||||||
|
debugger->printf("(AmsDataStorage) Not enough data in list type: %d\n", data->getListType());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
// Update day plot
|
||||||
|
if(!isDayHappy()) {
|
||||||
|
if(day.activeImport == 0 || now - day.lastMeterReadTime > 86400) {
|
||||||
|
day.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
day.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
day.lastMeterReadTime = now;
|
||||||
|
if(debugger->isActive(RemoteDebug::WARNING)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Too long since last day update, clearing data\n");
|
||||||
|
}
|
||||||
|
for(int i = 0; i<24; i++) {
|
||||||
|
setHourImport(i, 0);
|
||||||
|
setHourExport(i, 0);
|
||||||
|
}
|
||||||
|
} else if(now - day.lastMeterReadTime < 4000) {
|
||||||
|
uint32_t imp = (data->getActiveImportCounter() * 1000) - day.activeImport;
|
||||||
|
uint32_t exp = (data->getActiveExportCounter() * 1000) - day.activeExport;
|
||||||
|
setHourImport(utcYesterday.Hour, imp);
|
||||||
|
setHourExport(utcYesterday.Hour, exp);
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::INFO)) debugger->printf("(AmsDataStorage) Usage for hour %d: %d - %d\n", ltzYesterDay.Hour, imp, exp);
|
||||||
|
day.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
day.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
day.lastMeterReadTime = now;
|
||||||
|
} else {
|
||||||
|
float mins = (now - day.lastMeterReadTime) / 60.0;
|
||||||
|
uint32_t im = (data->getActiveImportCounter() * 1000) - day.activeImport;
|
||||||
|
uint32_t ex = (data->getActiveExportCounter() * 1000) - day.activeExport;
|
||||||
|
float ipm = im / mins;
|
||||||
|
float epm = ex / mins;
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Since last day update, minutes: %.1f, import: %d (%.2f/min), export: %d (%.2f/min)\n", mins, im, ipm, ex, epm);
|
||||||
|
}
|
||||||
|
|
||||||
|
tmElements_t last;
|
||||||
|
breakTime(day.lastMeterReadTime, last);
|
||||||
|
day.lastMeterReadTime = day.lastMeterReadTime - (last.Minute * 60) - last.Second;
|
||||||
|
time_t stopAt = now - (utc.Minute * 60) - utc.Second;
|
||||||
|
while(day.lastMeterReadTime < stopAt) {
|
||||||
|
time_t cur = min(day.lastMeterReadTime + 3600, stopAt);
|
||||||
|
uint8_t minutes = round((cur - day.lastMeterReadTime) / 60.0);
|
||||||
|
if(minutes < 1) break;
|
||||||
|
|
||||||
|
breakTime(day.lastMeterReadTime, last);
|
||||||
|
float imp = (ipm * minutes);
|
||||||
|
float exp = (epm * minutes);
|
||||||
|
setHourImport(last.Hour, imp);
|
||||||
|
setHourExport(last.Hour, exp);
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Estimated usage for hour %u: %.1f - %.1f (%lu)\n", last.Hour, imp, exp, (int32_t) cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
day.activeImport += imp;
|
||||||
|
day.activeExport += exp;
|
||||||
|
day.lastMeterReadTime = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update month plot
|
||||||
|
if(ltz.Hour == 0 && !isMonthHappy()) {
|
||||||
|
if(month.activeImport == 0 || now - month.lastMeterReadTime > 2678400) {
|
||||||
|
month.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
month.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
month.lastMeterReadTime = now;
|
||||||
|
if(debugger->isActive(RemoteDebug::WARNING)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Too long since last month update, clearing data\n");
|
||||||
|
}
|
||||||
|
for(int i = 1; i<=31; i++) {
|
||||||
|
setDayImport(i, 0);
|
||||||
|
setDayExport(i, 0);
|
||||||
|
}
|
||||||
|
} else if(now - month.lastMeterReadTime < 86500 && now - month.lastMeterReadTime > 86300) {
|
||||||
|
int32_t imp = (data->getActiveImportCounter() * 1000) - month.activeImport;
|
||||||
|
int32_t exp = (data->getActiveExportCounter() * 1000) - month.activeExport;
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Usage for day %d: %d - %d\n", ltzYesterDay.Day, imp, exp);
|
||||||
|
}
|
||||||
|
|
||||||
|
setDayImport(ltzYesterDay.Day, imp);
|
||||||
|
setDayExport(ltzYesterDay.Day, exp);
|
||||||
|
month.activeImport = data->getActiveImportCounter() * 1000;
|
||||||
|
month.activeExport = data->getActiveExportCounter() * 1000;
|
||||||
|
month.lastMeterReadTime = now;
|
||||||
|
} else {
|
||||||
|
// Make sure last month read is at midnight
|
||||||
|
tmElements_t last;
|
||||||
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
|
month.lastMeterReadTime = month.lastMeterReadTime - (last.Hour * 3600) - (last.Minute * 60) - last.Second;
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Last month read after resetting to midnight: %lu\n", (int32_t) month.lastMeterReadTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
float hrs = (now - month.lastMeterReadTime) / 3600.0;
|
||||||
|
uint32_t im = (data->getActiveImportCounter() * 1000) - month.activeImport;
|
||||||
|
uint32_t ex = (data->getActiveExportCounter() * 1000) - month.activeExport;
|
||||||
|
float iph = im / hrs;
|
||||||
|
float eph = ex / hrs;
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::DEBUG)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Since last month update, hours: %.1f, import: %d (%.2f/hr), export: %d (%.2f/hr)\n", hrs, im, iph, ex, eph);
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t stopAt = now - (ltz.Hour * 3600) - (ltz.Minute * 60) - ltz.Second;
|
||||||
|
while(month.lastMeterReadTime < stopAt) {
|
||||||
|
time_t cur = min(month.lastMeterReadTime + 86400, stopAt);
|
||||||
|
uint8_t hours = round((cur - month.lastMeterReadTime) / 3600.0);
|
||||||
|
|
||||||
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
|
float imp = (iph * hours);
|
||||||
|
float exp = (eph * hours);
|
||||||
|
setDayImport(last.Day, imp);
|
||||||
|
setDayExport(last.Day, exp);
|
||||||
|
|
||||||
|
if(debugger->isActive(RemoteDebug::INFO)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Estimated usage for day %u: %.1f - %.1f (%lu)\n", last.Day, imp, exp, (int32_t) cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
month.activeImport += imp;
|
||||||
|
month.activeExport += exp;
|
||||||
|
month.lastMeterReadTime = cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setHourImport(uint8_t hour, uint32_t val) {
|
||||||
|
if(hour < 0 || hour > 24) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AmsDataStorage::getHourImport(uint8_t hour) {
|
||||||
|
if(hour < 0 || hour > 24) return 0;
|
||||||
|
return day.hImport[hour] * pow(10, day.accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setHourExport(uint8_t hour, uint32_t val) {
|
||||||
|
if(hour < 0 || hour > 24) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AmsDataStorage::getHourExport(uint8_t hour) {
|
||||||
|
if(hour < 0 || hour > 24) return 0;
|
||||||
|
return day.hExport[hour] * pow(10, day.accuracy);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setDayImport(uint8_t day, uint32_t val) {
|
||||||
|
if(day < 1 || day > 31) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AmsDataStorage::getDayImport(uint8_t day) {
|
||||||
|
if(day < 1 || day > 31) return 0;
|
||||||
|
return (month.dImport[day-1] * pow(10, month.accuracy));
|
||||||
|
}
|
||||||
|
|
||||||
|
void AmsDataStorage::setDayExport(uint8_t day, uint32_t val) {
|
||||||
|
if(day < 1 || day > 31) return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t AmsDataStorage::getDayExport(uint8_t day) {
|
||||||
|
if(day < 1 || day > 31) return 0;
|
||||||
|
return (month.dExport[day-1] * pow(10, month.accuracy));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::load() {
|
||||||
|
if(!LittleFS.begin()) {
|
||||||
|
if(debugger->isActive(RemoteDebug::ERROR)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Unable to load LittleFS\n");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
if(LittleFS.exists(FILE_DAYPLOT)) {
|
||||||
|
File file = LittleFS.open(FILE_DAYPLOT, "r");
|
||||||
|
char buf[file.size()];
|
||||||
|
file.readBytes(buf, file.size());
|
||||||
|
DayDataPoints* day = (DayDataPoints*) buf;
|
||||||
|
file.close();
|
||||||
|
ret = setDayData(*day);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(LittleFS.exists(FILE_MONTHPLOT)) {
|
||||||
|
File file = LittleFS.open(FILE_MONTHPLOT, "r");
|
||||||
|
char buf[file.size()];
|
||||||
|
file.readBytes(buf, file.size());
|
||||||
|
MonthDataPoints* month = (MonthDataPoints*) buf;
|
||||||
|
file.close();
|
||||||
|
ret = ret && setMonthData(*month);
|
||||||
|
}
|
||||||
|
|
||||||
|
LittleFS.end();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::save() {
|
||||||
|
if(!LittleFS.begin()) {
|
||||||
|
if(debugger->isActive(RemoteDebug::ERROR)) {
|
||||||
|
debugger->printf("(AmsDataStorage) Unable to load LittleFS\n");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
File file = LittleFS.open(FILE_DAYPLOT, "w");
|
||||||
|
char buf[sizeof(day)];
|
||||||
|
memcpy(buf, &day, sizeof(day));
|
||||||
|
for(unsigned long i = 0; i < sizeof(day); i++) {
|
||||||
|
file.write(buf[i]);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
File file = LittleFS.open(FILE_MONTHPLOT, "w");
|
||||||
|
char buf[sizeof(month)];
|
||||||
|
memcpy(buf, &month, sizeof(month));
|
||||||
|
for(unsigned long i = 0; i < sizeof(month); i++) {
|
||||||
|
file.write(buf[i]);
|
||||||
|
}
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
LittleFS.end();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DayDataPoints AmsDataStorage::getDayData() {
|
||||||
|
return day;
|
||||||
|
}
|
||||||
|
|
||||||
|
MonthDataPoints AmsDataStorage::getMonthData() {
|
||||||
|
return month;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::setDayData(DayDataPoints& day) {
|
||||||
|
if(day.version == 5) {
|
||||||
|
this->day = day;
|
||||||
|
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) {
|
||||||
|
this->day = day;
|
||||||
|
for(uint8_t i = 0; i < 24; i++) this->day.hExport[i] = 0;
|
||||||
|
this->day.accuracy = 1;
|
||||||
|
this->day.version = 5;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::setMonthData(MonthDataPoints& month) {
|
||||||
|
if(month.version == 6) {
|
||||||
|
this->month = month;
|
||||||
|
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) {
|
||||||
|
this->month = month;
|
||||||
|
for(uint8_t i = 0; i < 31; i++) this->month.dExport[i] = 0;
|
||||||
|
this->month.accuracy = 1;
|
||||||
|
this->month.version = 6;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
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() {
|
||||||
|
return isDayHappy() && isMonthHappy();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::isDayHappy() {
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(now < BUILD_EPOCH) return false;
|
||||||
|
tmElements_t tm, last;
|
||||||
|
|
||||||
|
if(now < day.lastMeterReadTime) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu < %lu\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(now-day.lastMeterReadTime > 3600) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %lu - %lu > 3600\n", (int32_t) now, (int32_t) day.lastMeterReadTime);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
breakTime(tz->toLocal(now), tm);
|
||||||
|
breakTime(tz->toLocal(day.lastMeterReadTime), last);
|
||||||
|
if(tm.Hour > last.Hour) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Day %d > %d\n", tm.Hour, last.Hour);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AmsDataStorage::isMonthHappy() {
|
||||||
|
if(tz == NULL) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Timezone is missing\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t now = time(nullptr);
|
||||||
|
if(now < BUILD_EPOCH) return false;
|
||||||
|
tmElements_t tm, last;
|
||||||
|
|
||||||
|
if(now < month.lastMeterReadTime) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu < %lu\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(now-month.lastMeterReadTime > 86400) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %lu - %lu > 3600\n", (int32_t) now, (int32_t) month.lastMeterReadTime);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
breakTime(tz->toLocal(now), tm);
|
||||||
|
breakTime(tz->toLocal(month.lastMeterReadTime), last);
|
||||||
|
if(tm.Day > last.Day) {
|
||||||
|
if(debugger->isActive(RemoteDebug::VERBOSE)) debugger->printf("(AmsDataStorage) Month %d > %d\n", tm.Day, last.Day);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
92
lib/AmsDecoder/include/Cosem.h
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
#ifndef _COSEM_H
|
||||||
|
#define _COSEM_H
|
||||||
|
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
// Blue book, Table 2
|
||||||
|
enum CosemType {
|
||||||
|
CosemTypeNull = 0x00,
|
||||||
|
CosemTypeArray = 0x01,
|
||||||
|
CosemTypeStructure = 0x02,
|
||||||
|
CosemTypeOctetString = 0x09,
|
||||||
|
CosemTypeString = 0x0A,
|
||||||
|
CosemTypeDLongSigned = 0x05,
|
||||||
|
CosemTypeDLongUnsigned = 0x06,
|
||||||
|
CosemTypeLongSigned = 0x10,
|
||||||
|
CosemTypeLongUnsigned = 0x12,
|
||||||
|
CosemTypeLong64Signed = 0x14,
|
||||||
|
CosemTypeLong64Unsigned = 0x15,
|
||||||
|
CosemTypeDateTime = 0x19
|
||||||
|
};
|
||||||
|
|
||||||
|
struct CosemBasic {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t length;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemString {
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t length;
|
||||||
|
uint8_t data[];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemLongSigned {
|
||||||
|
uint8_t type;
|
||||||
|
int16_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemLongUnsigned {
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemDLongSigned {
|
||||||
|
uint8_t type;
|
||||||
|
int32_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemDLongUnsigned {
|
||||||
|
uint8_t type;
|
||||||
|
uint32_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemLong64Signed {
|
||||||
|
uint8_t type;
|
||||||
|
int64_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemLong64Unsigned {
|
||||||
|
uint8_t type;
|
||||||
|
uint64_t data;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct CosemDateTime {
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t year;
|
||||||
|
uint8_t month;
|
||||||
|
uint8_t dayOfMonth;
|
||||||
|
uint8_t dayOfWeek;
|
||||||
|
uint8_t hour;
|
||||||
|
uint8_t minute;
|
||||||
|
uint8_t second;
|
||||||
|
uint8_t hundredths;
|
||||||
|
int16_t deviation;
|
||||||
|
uint8_t status;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
typedef union {
|
||||||
|
struct CosemBasic base;
|
||||||
|
struct CosemString str;
|
||||||
|
struct CosemString oct;
|
||||||
|
struct CosemLongSigned ls;
|
||||||
|
struct CosemLongUnsigned lu;
|
||||||
|
struct CosemDLongSigned dls;
|
||||||
|
struct CosemDLongUnsigned dlu;
|
||||||
|
struct CosemLong64Signed l64s;
|
||||||
|
struct CosemLong64Unsigned l64u;
|
||||||
|
struct CosemDateTime dt;
|
||||||
|
} CosemData;
|
||||||
|
|
||||||
|
time_t decodeCosemDateTime(CosemDateTime timestamp);
|
||||||
|
|
||||||
|
#endif
|
||||||
31
lib/AmsDecoder/include/DataParser.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#ifndef _DATAPASERSER_H
|
||||||
|
#define _DATAPASERSER_H
|
||||||
|
|
||||||
|
#define DATA_TAG_NONE 0x00
|
||||||
|
#define DATA_TAG_AUTO 0x01
|
||||||
|
#define DATA_TAG_HDLC 0x7E
|
||||||
|
#define DATA_TAG_LLC 0xE6
|
||||||
|
#define DATA_TAG_DLMS 0x0F
|
||||||
|
#define DATA_TAG_DSMR 0x2F
|
||||||
|
#define DATA_TAG_MBUS 0x68
|
||||||
|
#define DATA_TAG_GBT 0xE0
|
||||||
|
#define DATA_TAG_GCM 0xDB
|
||||||
|
|
||||||
|
#define DATA_PARSE_OK 0
|
||||||
|
#define DATA_PARSE_FAIL -1
|
||||||
|
#define DATA_PARSE_INCOMPLETE -2
|
||||||
|
#define DATA_PARSE_BOUNDRY_FLAG_MISSING -3
|
||||||
|
#define DATA_PARSE_HEADER_CHECKSUM_ERROR -4
|
||||||
|
#define DATA_PARSE_FOOTER_CHECKSUM_ERROR -5
|
||||||
|
#define DATA_PARSE_INTERMEDIATE_SEGMENT -6
|
||||||
|
#define DATA_PARSE_FINAL_SEGMENT -7
|
||||||
|
#define DATA_PARSE_UNKNOWN_DATA -9
|
||||||
|
|
||||||
|
struct DataParserContext {
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t length;
|
||||||
|
time_t timestamp;
|
||||||
|
uint8_t system_title[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/AmsDecoder/include/DataParsers.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _DATAPASERSERS_H
|
||||||
|
#define _DATAPASERSERS_H
|
||||||
|
|
||||||
|
#include "HdlcParser.h"
|
||||||
|
#include "DlmsParser.h"
|
||||||
|
#include "DsmrParser.h"
|
||||||
|
#include "MbusParser.h"
|
||||||
|
#include "GbtParser.h"
|
||||||
|
#include "GcmParser.h"
|
||||||
|
#include "LlcParser.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
12
lib/AmsDecoder/include/DlmsParser.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _DLMSPARSER_H
|
||||||
|
#define _DLMSPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
class DLMSParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
13
lib/AmsDecoder/include/DsmrParser.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _DSMRPARSER_H
|
||||||
|
#define _DSMRPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
class DSMRParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx, bool verified);
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
26
lib/AmsDecoder/include/GbtParser.h
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#ifndef _GBTPARSER_H
|
||||||
|
#define _GBTPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
#define GBT_TAG 0xE0
|
||||||
|
|
||||||
|
typedef struct GBTHeader {
|
||||||
|
uint8_t flag;
|
||||||
|
uint8_t control;
|
||||||
|
uint16_t sequence;
|
||||||
|
uint16_t sequenceAck;
|
||||||
|
uint8_t size;
|
||||||
|
} __attribute__((packed)) GBTHeader;
|
||||||
|
|
||||||
|
class GBTParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
private:
|
||||||
|
uint8_t lastSequenceNumber = 0;
|
||||||
|
uint16_t pos = 0;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
27
lib/AmsDecoder/include/GcmParser.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#ifndef _GCMPARSER_H
|
||||||
|
#define _GCMPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
#define GCM_TAG 0xDB
|
||||||
|
#define GCM_AUTH_FAILED -51
|
||||||
|
#define GCM_DECRYPT_FAILED -52
|
||||||
|
#define GCM_ENCRYPTION_KEY_FAILED -53
|
||||||
|
|
||||||
|
typedef struct GCMSizeDef {
|
||||||
|
uint8_t flag;
|
||||||
|
uint16_t format;
|
||||||
|
} __attribute__((packed)) GCMSizeDef;
|
||||||
|
|
||||||
|
|
||||||
|
class GCMParser {
|
||||||
|
public:
|
||||||
|
GCMParser(uint8_t *encryption_key, uint8_t *authentication_key);
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
private:
|
||||||
|
uint8_t encryption_key[16];
|
||||||
|
uint8_t authentication_key[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
29
lib/AmsDecoder/include/HdlcParser.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#ifndef _HDLCPARSER_H
|
||||||
|
#define _HDLCPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
#define HDLC_FLAG 0x7E
|
||||||
|
|
||||||
|
typedef struct HDLCHeader {
|
||||||
|
uint8_t flag;
|
||||||
|
uint16_t format;
|
||||||
|
} __attribute__((packed)) HDLCHeader;
|
||||||
|
|
||||||
|
typedef struct HDLCFooter {
|
||||||
|
uint16_t fcs;
|
||||||
|
uint8_t flag;
|
||||||
|
} __attribute__((packed)) HDLCFooter;
|
||||||
|
|
||||||
|
typedef struct HDLC3CtrlHcs {
|
||||||
|
uint8_t control;
|
||||||
|
uint16_t hcs;
|
||||||
|
} __attribute__((packed)) HDLC3CtrlHcs;
|
||||||
|
|
||||||
|
class HDLCParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
18
lib/AmsDecoder/include/LlcParser.h
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#ifndef _LLCPARSER_H
|
||||||
|
#define _LLCPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
typedef struct LLCHeader {
|
||||||
|
uint8_t dst;
|
||||||
|
uint8_t src;
|
||||||
|
uint8_t control;
|
||||||
|
} __attribute__((packed)) LLCHeader;
|
||||||
|
|
||||||
|
class LLCParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
34
lib/AmsDecoder/include/MbusParser.h
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#ifndef _MBUSPARSER_H
|
||||||
|
#define _MBUSPARSER_H
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
#include "DataParser.h"
|
||||||
|
|
||||||
|
#define MBUS_START 0x68
|
||||||
|
#define MBUS_END 0x16
|
||||||
|
#define MBUS_FRAME_LENGTH_NOT_EQUAL -41
|
||||||
|
|
||||||
|
typedef struct MbusHeader {
|
||||||
|
uint8_t flag1;
|
||||||
|
uint8_t len1;
|
||||||
|
uint8_t len2;
|
||||||
|
uint8_t flag2;
|
||||||
|
} __attribute__((packed)) MbusHeader;
|
||||||
|
|
||||||
|
typedef struct MbusFooter {
|
||||||
|
uint8_t fcs;
|
||||||
|
uint8_t flag;
|
||||||
|
} __attribute__((packed)) MbusFooter;
|
||||||
|
|
||||||
|
class MBUSParser {
|
||||||
|
public:
|
||||||
|
int8_t parse(uint8_t *buf, DataParserContext &ctx);
|
||||||
|
uint16_t write(const uint8_t* d, DataParserContext &ctx);
|
||||||
|
private:
|
||||||
|
uint8_t lastSequenceNumber = 0;
|
||||||
|
uint16_t pos = 0;
|
||||||
|
uint8_t *buf = NULL;
|
||||||
|
uint8_t checksum(const uint8_t* p, int len);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -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
|
||||||
8
lib/AmsDecoder/include/ntohll.h
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#ifndef _NTOHLL_H
|
||||||
|
#define _NTOHLL_H
|
||||||
|
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
uint64_t ntohll(uint64_t x);
|
||||||
|
|
||||||
|
#endif
|
||||||
24
lib/AmsDecoder/src/Cosem.cpp
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
#include "Cosem.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include <TimeLib.h>
|
||||||
|
|
||||||
|
time_t decodeCosemDateTime(CosemDateTime timestamp) {
|
||||||
|
tmElements_t tm;
|
||||||
|
uint16_t year = ntohs(timestamp.year);
|
||||||
|
if(year < 1970) return 0;
|
||||||
|
tm.Year = year - 1970;
|
||||||
|
tm.Month = timestamp.month;
|
||||||
|
tm.Day = timestamp.dayOfMonth;
|
||||||
|
tm.Hour = timestamp.hour;
|
||||||
|
tm.Minute = timestamp.minute;
|
||||||
|
tm.Second = timestamp.second;
|
||||||
|
|
||||||
|
//Serial.printf("\nY: %d, M: %d, D: %d, h: %d, m: %d, s: %d, deviation: 0x%2X, status: 0x%1X\n", tm.Year, tm.Month, tm.Day, tm.Hour, tm.Minute, tm.Second, timestamp.deviation, timestamp.status);
|
||||||
|
|
||||||
|
time_t time = makeTime(tm);
|
||||||
|
int16_t deviation = ntohs(timestamp.deviation);
|
||||||
|
if(deviation >= -720 && deviation <= 720) {
|
||||||
|
time -= deviation * 60;
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
}
|
||||||
38
lib/AmsDecoder/src/DlmsParser.cpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#include "DlmsParser.h"
|
||||||
|
#include "Cosem.h"
|
||||||
|
|
||||||
|
int8_t DLMSParser::parse(uint8_t *buf, DataParserContext &ctx) {
|
||||||
|
if(ctx.length < 6) return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
uint8_t* ptr = buf+1;
|
||||||
|
ptr += 4; // Skip invoke ID and priority
|
||||||
|
|
||||||
|
CosemData* item = (CosemData*) ptr;
|
||||||
|
if(item->base.type == CosemTypeOctetString) {
|
||||||
|
if(item->base.length == 0x0C) {
|
||||||
|
CosemDateTime* dateTime = (CosemDateTime*) (ptr+1);
|
||||||
|
ctx.timestamp = decodeCosemDateTime(*dateTime);
|
||||||
|
}
|
||||||
|
uint8_t len = 5+14;
|
||||||
|
ctx.length -= len;
|
||||||
|
return len;
|
||||||
|
} else if(item->base.type == CosemTypeNull) {
|
||||||
|
ctx.timestamp = 0;
|
||||||
|
uint8_t len = 5+1;
|
||||||
|
ctx.length -= len;
|
||||||
|
return len;
|
||||||
|
} else if(item->base.type == CosemTypeDateTime) {
|
||||||
|
CosemDateTime* dateTime = (CosemDateTime*) (ptr);
|
||||||
|
ctx.timestamp = decodeCosemDateTime(*dateTime);
|
||||||
|
uint8_t len = 5+13;
|
||||||
|
ctx.length -= len;
|
||||||
|
return len;
|
||||||
|
} else if(item->base.type == 0x0C) { // Kamstrup bug...
|
||||||
|
CosemDateTime* dateTime = (CosemDateTime*) (ptr);
|
||||||
|
ctx.timestamp = decodeCosemDateTime(*dateTime);
|
||||||
|
uint8_t len = 5+13;
|
||||||
|
ctx.length -= len;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
return DATA_PARSE_UNKNOWN_DATA;
|
||||||
|
}
|
||||||
29
lib/AmsDecoder/src/DsmrParser.cpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#include "DsmrParser.h"
|
||||||
|
#include "crc.h"
|
||||||
|
#include "hexutils.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
int8_t DSMRParser::parse(uint8_t *buf, DataParserContext &ctx, bool verified) {
|
||||||
|
uint16_t crcPos = 0;
|
||||||
|
bool reachedEnd = verified;
|
||||||
|
uint8_t lastByte = 0x00;
|
||||||
|
for(int pos = 0; pos < ctx.length; pos++) {
|
||||||
|
uint8_t b = *(buf+pos);
|
||||||
|
if(pos == 0 && b != '/') return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
if(pos > 0 && b == '!' && lastByte == '\n') crcPos = pos+1;
|
||||||
|
if(crcPos > 0 && b == '\n') reachedEnd = true;
|
||||||
|
lastByte = b;
|
||||||
|
}
|
||||||
|
if(!reachedEnd) return DATA_PARSE_INCOMPLETE;
|
||||||
|
buf[ctx.length+1] = '\0';
|
||||||
|
if(crcPos > 0) {
|
||||||
|
uint16_t crc_calc = crc16(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;
|
||||||
|
}
|
||||||
32
lib/AmsDecoder/src/GbtParser.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include "GbtParser.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
|
||||||
|
int8_t GBTParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||||
|
GBTHeader* h = (GBTHeader*) (d);
|
||||||
|
uint16_t sequence = ntohs(h->sequence);
|
||||||
|
|
||||||
|
if(h->flag != GBT_TAG) return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
|
||||||
|
if(sequence == 1) {
|
||||||
|
if(buf == NULL) buf = (uint8_t *)malloc((size_t)1024); // TODO find out from first package ?
|
||||||
|
pos = 0;
|
||||||
|
} else if(lastSequenceNumber != sequence-1) {
|
||||||
|
return DATA_PARSE_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(buf == NULL) return DATA_PARSE_FAIL;
|
||||||
|
|
||||||
|
uint8_t* ptr = (uint8_t*) &h[1];
|
||||||
|
memcpy(buf + pos, ptr, h->size);
|
||||||
|
pos += h->size;
|
||||||
|
lastSequenceNumber = sequence;
|
||||||
|
|
||||||
|
if((h->control & 0x80) == 0x00) {
|
||||||
|
return DATA_PARSE_INTERMEDIATE_SEGMENT;
|
||||||
|
} else {
|
||||||
|
memcpy((uint8_t *) d, buf, pos);
|
||||||
|
}
|
||||||
|
ctx.length = pos;
|
||||||
|
return DATA_PARSE_OK;
|
||||||
|
|
||||||
|
}
|
||||||
131
lib/AmsDecoder/src/GcmParser.cpp
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
#include "GcmParser.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#if defined(ESP8266)
|
||||||
|
#include "bearssl/bearssl.h"
|
||||||
|
#elif defined(ESP32)
|
||||||
|
#include "mbedtls/gcm.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GCMParser::GCMParser(uint8_t *encryption_key, uint8_t *authentication_key) {
|
||||||
|
memcpy(this->encryption_key, encryption_key, 16);
|
||||||
|
memcpy(this->authentication_key, authentication_key, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t GCMParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||||
|
if(ctx.length < 12) return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
uint8_t* ptr = (uint8_t*) d;
|
||||||
|
if(*ptr != GCM_TAG) return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
ptr++;
|
||||||
|
// Encrypted APDU
|
||||||
|
// http://www.weigu.lu/tutorials/sensors2bus/04_encryption/index.html
|
||||||
|
|
||||||
|
uint8_t systemTitleLength = *ptr;
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
uint8_t initialization_vector[12];
|
||||||
|
memcpy(ctx.system_title, ptr, systemTitleLength);
|
||||||
|
memcpy(initialization_vector, ctx.system_title, systemTitleLength);
|
||||||
|
|
||||||
|
int len = 0;
|
||||||
|
int headersize = 2 + systemTitleLength;
|
||||||
|
ptr += systemTitleLength;
|
||||||
|
if(((*ptr) & 0xFF) == 0x81) {
|
||||||
|
ptr++;
|
||||||
|
len = *ptr;
|
||||||
|
// 1-byte payload length
|
||||||
|
ptr++;
|
||||||
|
headersize += 2;
|
||||||
|
} else if(((*ptr) & 0xFF) == 0x82) {
|
||||||
|
GCMSizeDef* h = (GCMSizeDef*) ptr;
|
||||||
|
|
||||||
|
// 2-byte payload length
|
||||||
|
len = (ntohs(h->format) & 0xFFFF);
|
||||||
|
|
||||||
|
ptr += 3;
|
||||||
|
headersize += 3;
|
||||||
|
}
|
||||||
|
if(len + headersize > ctx.length)
|
||||||
|
return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
//Serial.printf("\nL: %d : %d, %d\n", length, len, headersize);
|
||||||
|
|
||||||
|
uint8_t additional_authenticated_data[17];
|
||||||
|
memcpy(additional_authenticated_data, ptr, 1);
|
||||||
|
|
||||||
|
// Security tag
|
||||||
|
uint8_t sec = *ptr;
|
||||||
|
ptr++;
|
||||||
|
headersize++;
|
||||||
|
|
||||||
|
// Frame counter
|
||||||
|
memcpy(initialization_vector + 8, ptr, 4);
|
||||||
|
ptr += 4;
|
||||||
|
headersize += 4;
|
||||||
|
|
||||||
|
int footersize = 0;
|
||||||
|
|
||||||
|
// Authentication enabled
|
||||||
|
uint8_t authentication_tag[12];
|
||||||
|
uint8_t authkeylen = 0, aadlen = 0;
|
||||||
|
if((sec & 0x10) == 0x10) {
|
||||||
|
authkeylen = 12;
|
||||||
|
aadlen = 17;
|
||||||
|
footersize += authkeylen;
|
||||||
|
memcpy(additional_authenticated_data + 1, authentication_key, 16);
|
||||||
|
memcpy(authentication_tag, ptr + len - footersize - 5, authkeylen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
|
br_gcm_context gcmCtx;
|
||||||
|
br_aes_ct_ctr_keys bc;
|
||||||
|
br_aes_ct_ctr_init(&bc, encryption_key, 16);
|
||||||
|
br_gcm_init(&gcmCtx, &bc.vtable, br_ghash_ctmul32);
|
||||||
|
br_gcm_reset(&gcmCtx, initialization_vector, sizeof(initialization_vector));
|
||||||
|
if(authkeylen > 0) {
|
||||||
|
br_gcm_aad_inject(&gcmCtx, additional_authenticated_data, aadlen);
|
||||||
|
}
|
||||||
|
br_gcm_flip(&gcmCtx);
|
||||||
|
br_gcm_run(&gcmCtx, 0, (void*) (ptr), len - authkeylen - 5); // 5 == security tag and frame counter
|
||||||
|
if(authkeylen > 0 && br_gcm_check_tag_trunc(&gcmCtx, authentication_tag, authkeylen) != 1) {
|
||||||
|
return GCM_AUTH_FAILED;
|
||||||
|
}
|
||||||
|
#elif defined(ESP32)
|
||||||
|
uint8_t cipher_text[len - authkeylen - 5];
|
||||||
|
memcpy(cipher_text, ptr, len - authkeylen - 5);
|
||||||
|
|
||||||
|
mbedtls_gcm_context m_ctx;
|
||||||
|
mbedtls_gcm_init(&m_ctx);
|
||||||
|
int success = mbedtls_gcm_setkey(&m_ctx, MBEDTLS_CIPHER_ID_AES, encryption_key, 128);
|
||||||
|
if (0 != success) {
|
||||||
|
return GCM_ENCRYPTION_KEY_FAILED;
|
||||||
|
}
|
||||||
|
if (0 < authkeylen) {
|
||||||
|
success = mbedtls_gcm_auth_decrypt(&m_ctx, sizeof(cipher_text), initialization_vector, sizeof(initialization_vector),
|
||||||
|
additional_authenticated_data, aadlen, authentication_tag, authkeylen,
|
||||||
|
cipher_text, (unsigned char*)(ptr));
|
||||||
|
if (authkeylen > 0 && success == MBEDTLS_ERR_GCM_AUTH_FAILED) {
|
||||||
|
mbedtls_gcm_free(&m_ctx);
|
||||||
|
return GCM_AUTH_FAILED;
|
||||||
|
} else if(success == MBEDTLS_ERR_GCM_BAD_INPUT) {
|
||||||
|
mbedtls_gcm_free(&m_ctx);
|
||||||
|
return GCM_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success = mbedtls_gcm_starts(&m_ctx, MBEDTLS_GCM_DECRYPT, initialization_vector, sizeof(initialization_vector),NULL, 0);
|
||||||
|
if (0 != success) {
|
||||||
|
mbedtls_gcm_free(&m_ctx);
|
||||||
|
return GCM_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
success = mbedtls_gcm_update(&m_ctx, sizeof(cipher_text), cipher_text, (unsigned char*)(ptr));
|
||||||
|
if (0 != success) {
|
||||||
|
mbedtls_gcm_free(&m_ctx);
|
||||||
|
return GCM_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mbedtls_gcm_free(&m_ctx);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ctx.length -= footersize + headersize;
|
||||||
|
return ptr-d;
|
||||||
|
}
|
||||||
56
lib/AmsDecoder/src/HdlcParser.cpp
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
#include "HdlcParser.h"
|
||||||
|
#include "lwip/def.h"
|
||||||
|
#include "crc.h"
|
||||||
|
|
||||||
|
int8_t HDLCParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||||
|
int len;
|
||||||
|
|
||||||
|
uint8_t* ptr;
|
||||||
|
if(ctx.length < 3)
|
||||||
|
return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
HDLCHeader* h = (HDLCHeader*) d;
|
||||||
|
ptr = (uint8_t*) &h[1];
|
||||||
|
|
||||||
|
// Frame format type 3
|
||||||
|
if((h->format & 0xF0) == 0xA0) {
|
||||||
|
// Length field (11 lsb of format)
|
||||||
|
len = (ntohs(h->format) & 0x7FF) + 2;
|
||||||
|
if(len > ctx.length)
|
||||||
|
return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
HDLCFooter* f = (HDLCFooter*) (d + len - sizeof *f);
|
||||||
|
|
||||||
|
// First and last byte should be HDLC_FLAG
|
||||||
|
if(h->flag != HDLC_FLAG || f->flag != HDLC_FLAG)
|
||||||
|
return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
|
||||||
|
// Verify FCS
|
||||||
|
if(ntohs(f->fcs) != crc16_x25(d + 1, len - sizeof *f - 1))
|
||||||
|
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
|
||||||
|
|
||||||
|
// Skip destination address, LSB marks last byte
|
||||||
|
while(((*ptr) & 0x01) == 0x00) {
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
// Skip source address, LSB marks last byte
|
||||||
|
while(((*ptr) & 0x01) == 0x00) {
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
|
||||||
|
HDLC3CtrlHcs* t3 = (HDLC3CtrlHcs*) (ptr);
|
||||||
|
|
||||||
|
// Verify HCS
|
||||||
|
if(ntohs(t3->hcs) != crc16_x25(d + 1, ptr-d))
|
||||||
|
return DATA_PARSE_HEADER_CHECKSUM_ERROR;
|
||||||
|
ptr += 3;
|
||||||
|
|
||||||
|
// Exclude all of header and 3 byte footer
|
||||||
|
ctx.length -= ptr-d+3;
|
||||||
|
return ptr-d;
|
||||||
|
}
|
||||||
|
return DATA_PARSE_UNKNOWN_DATA;
|
||||||
|
}
|
||||||
6
lib/AmsDecoder/src/LlcParser.cpp
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
#include "LlcParser.h"
|
||||||
|
|
||||||
|
int8_t LLCParser::parse(uint8_t *buf, DataParserContext &ctx) {
|
||||||
|
ctx.length -= 3;
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
87
lib/AmsDecoder/src/MbusParser.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "MbusParser.h"
|
||||||
|
|
||||||
|
int8_t MBUSParser::parse(uint8_t *d, DataParserContext &ctx) {
|
||||||
|
int len;
|
||||||
|
int headersize = 3;
|
||||||
|
int footersize = 1;
|
||||||
|
|
||||||
|
uint8_t* ptr;
|
||||||
|
|
||||||
|
// https://m-bus.com/documentation-wired/06-application-layer
|
||||||
|
if(ctx.length < 4)
|
||||||
|
return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
MbusHeader* mh = (MbusHeader*) d;
|
||||||
|
if(mh->flag1 != MBUS_START || mh->flag2 != MBUS_START)
|
||||||
|
return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
|
||||||
|
// First two bytes is 1-byte length value repeated. Only used for last segment
|
||||||
|
if(mh->len1 != mh->len2)
|
||||||
|
return MBUS_FRAME_LENGTH_NOT_EQUAL;
|
||||||
|
len = mh->len1;
|
||||||
|
ptr = (uint8_t*) &mh[1];
|
||||||
|
headersize = 4;
|
||||||
|
footersize = 2;
|
||||||
|
|
||||||
|
if(len == 0x00)
|
||||||
|
len = ctx.length - headersize - footersize;
|
||||||
|
// Payload can max be 255 bytes, so I think the following case is only valid for austrian meters
|
||||||
|
if(len < headersize)
|
||||||
|
len += 256;
|
||||||
|
|
||||||
|
if((headersize + footersize + len) > ctx.length)
|
||||||
|
return DATA_PARSE_INCOMPLETE;
|
||||||
|
|
||||||
|
MbusFooter* mf = (MbusFooter*) (d + len + headersize);
|
||||||
|
if(mf->flag != MBUS_END)
|
||||||
|
return DATA_PARSE_BOUNDRY_FLAG_MISSING;
|
||||||
|
if(checksum(d + headersize, len) != mf->fcs)
|
||||||
|
return DATA_PARSE_FOOTER_CHECKSUM_ERROR;
|
||||||
|
|
||||||
|
ptr += 2; len -= 2;
|
||||||
|
|
||||||
|
// Control information field
|
||||||
|
uint8_t ci = *ptr;
|
||||||
|
|
||||||
|
// Skip CI, STSAP and DTSAP
|
||||||
|
ptr += 3; len -= 3;
|
||||||
|
|
||||||
|
// Bits 7 6 5 4 3 2 1 0
|
||||||
|
// 0 0 0 Finished Sequence number
|
||||||
|
uint8_t sequenceNumber = (ci & 0x0F);
|
||||||
|
if((ci & 0x10) == 0x00) { // Not finished yet
|
||||||
|
if(sequenceNumber == 0) {
|
||||||
|
if(buf == NULL) buf = (uint8_t *)malloc((size_t)1024); // TODO find out from first package ?
|
||||||
|
pos = 0;
|
||||||
|
} else if(buf == NULL || pos + len > 1024 || sequenceNumber != (lastSequenceNumber + 1)) {
|
||||||
|
return DATA_PARSE_FAIL;
|
||||||
|
}
|
||||||
|
memcpy(buf+pos, ptr, len);
|
||||||
|
pos += len;
|
||||||
|
lastSequenceNumber = sequenceNumber;
|
||||||
|
return DATA_PARSE_INTERMEDIATE_SEGMENT;
|
||||||
|
} else if(sequenceNumber > 0) { // This is the last frame of multiple, assembly needed
|
||||||
|
if(buf == NULL || pos + len > 1024 || sequenceNumber != (lastSequenceNumber + 1)) {
|
||||||
|
return DATA_PARSE_FAIL;
|
||||||
|
}
|
||||||
|
memcpy(buf+pos, ptr, len);
|
||||||
|
pos += len;
|
||||||
|
return DATA_PARSE_FINAL_SEGMENT;
|
||||||
|
}
|
||||||
|
return ptr-d;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t MBUSParser::write(const uint8_t* d, DataParserContext &ctx) {
|
||||||
|
if(buf != NULL) {
|
||||||
|
memcpy((uint8_t *) d, buf, pos);
|
||||||
|
ctx.length = pos;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t MBUSParser::checksum(const uint8_t* p, int len) {
|
||||||
|
uint8_t ret = 0;
|
||||||
|
while(len--)
|
||||||
|
ret += *p++;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
5
lib/AmsDecoder/src/ntohll.cpp
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
#include "ntohll.h"
|
||||||
|
|
||||||
|
uint64_t ntohll(uint64_t x) {
|
||||||
|
return (((uint64_t)ntohl((uint32_t)x)) << 32) + ntohl(x >> 32);
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
var nextVersion;
|
var nextVersion;
|
||||||
var im, em;
|
var im, em;
|
||||||
|
var ds = 0;
|
||||||
|
var currency = "";
|
||||||
|
var swatt = false;
|
||||||
|
|
||||||
// Price plot
|
// Price plot
|
||||||
var pp;
|
var pp;
|
||||||
@@ -29,6 +32,7 @@ var eo = {
|
|||||||
titleTextStyle: {
|
titleTextStyle: {
|
||||||
fontSize: 14
|
fontSize: 14
|
||||||
},
|
},
|
||||||
|
colors: ['#6f42c1', '#6f42c1'],
|
||||||
backgroundColor: { fill:'transparent' },
|
backgroundColor: { fill:'transparent' },
|
||||||
bar: { groupWidth: '90%' },
|
bar: { groupWidth: '90%' },
|
||||||
legend: { position: 'none' },
|
legend: { position: 'none' },
|
||||||
@@ -38,6 +42,7 @@ var eo = {
|
|||||||
},
|
},
|
||||||
tooltip: { trigger: 'none'},
|
tooltip: { trigger: 'none'},
|
||||||
enableInteractivity: false,
|
enableInteractivity: false,
|
||||||
|
isStacked: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Month plot
|
// Month plot
|
||||||
@@ -48,6 +53,7 @@ var mo = {
|
|||||||
titleTextStyle: {
|
titleTextStyle: {
|
||||||
fontSize: 14
|
fontSize: 14
|
||||||
},
|
},
|
||||||
|
colors: ['#6f42c1', '#6f42c1'],
|
||||||
backgroundColor: { fill:'transparent' },
|
backgroundColor: { fill:'transparent' },
|
||||||
bar: { groupWidth: '90%' },
|
bar: { groupWidth: '90%' },
|
||||||
legend: { position: 'none' },
|
legend: { position: 'none' },
|
||||||
@@ -57,6 +63,7 @@ var mo = {
|
|||||||
},
|
},
|
||||||
tooltip: { trigger: 'none'},
|
tooltip: { trigger: 'none'},
|
||||||
enableInteractivity: false,
|
enableInteractivity: false,
|
||||||
|
isStacked: true
|
||||||
};
|
};
|
||||||
|
|
||||||
// Voltage plot
|
// Voltage plot
|
||||||
@@ -231,9 +238,9 @@ $(function() {
|
|||||||
// For wifi
|
// For wifi
|
||||||
$('#st').on('change', function() {
|
$('#st').on('change', function() {
|
||||||
if($(this).is(':checked')) {
|
if($(this).is(':checked')) {
|
||||||
$('#i').show();
|
$('.sip').prop('disabled', false);
|
||||||
} else {
|
} else {
|
||||||
$('#i').hide();
|
$('.sip').prop('disabled', true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('#st').trigger('change');
|
$('#st').trigger('change');
|
||||||
@@ -262,6 +269,11 @@ $(function() {
|
|||||||
});
|
});
|
||||||
$('#n').trigger('change');
|
$('#n').trigger('change');
|
||||||
|
|
||||||
|
$('.ipo,.epo').on('click', function() {
|
||||||
|
swatt = !swatt;
|
||||||
|
$('.ipo,.epo').html('wait');
|
||||||
|
});
|
||||||
|
|
||||||
// Navbar
|
// Navbar
|
||||||
switch(window.location.pathname) {
|
switch(window.location.pathname) {
|
||||||
case '/temperature':
|
case '/temperature':
|
||||||
@@ -284,6 +296,7 @@ $(function() {
|
|||||||
break;
|
break;
|
||||||
case '/gpio':
|
case '/gpio':
|
||||||
case '/debugging':
|
case '/debugging':
|
||||||
|
case '/configfile':
|
||||||
case '/firmware':
|
case '/firmware':
|
||||||
$('#firmware-warn').show();
|
$('#firmware-warn').show();
|
||||||
case '/reset':
|
case '/reset':
|
||||||
@@ -303,6 +316,7 @@ $(function() {
|
|||||||
url: swv.data('url'),
|
url: swv.data('url'),
|
||||||
dataType: 'json'
|
dataType: 'json'
|
||||||
}).done(function(releases) {
|
}).done(function(releases) {
|
||||||
|
var isnew = false;
|
||||||
if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(swv.text()) && fwl.length == 0) {
|
if(/^v\d{1,2}\.\d{1,2}\.\d{1,2}$/.test(swv.text()) && fwl.length == 0) {
|
||||||
releases.reverse();
|
releases.reverse();
|
||||||
var next_patch;
|
var next_patch;
|
||||||
@@ -339,10 +353,13 @@ $(function() {
|
|||||||
});
|
});
|
||||||
if(next_minor) {
|
if(next_minor) {
|
||||||
nextVersion = next_minor;
|
nextVersion = next_minor;
|
||||||
|
isnew = true;
|
||||||
} else if(next_major) {
|
} else if(next_major) {
|
||||||
nextVersion = next_major;
|
nextVersion = next_major;
|
||||||
|
isnew = true;
|
||||||
} else if(next_patch) {
|
} else if(next_patch) {
|
||||||
nextVersion = next_patch;
|
nextVersion = next_patch;
|
||||||
|
isnew = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
nextVersion = releases[0];
|
nextVersion = releases[0];
|
||||||
@@ -362,9 +379,11 @@ $(function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
$('#newVersionTag').text(nextVersion.tag_name);
|
if(isnew) {
|
||||||
$('#newVersionUrl').prop('href', nextVersion.html_url);
|
$('#newVersionTag').text(nextVersion.tag_name);
|
||||||
$('#newVersion').removeClass('d-none');
|
$('#newVersionUrl').prop('href', nextVersion.html_url);
|
||||||
|
$('#newVersion').removeClass('d-none');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -431,6 +450,7 @@ var drawPrices = function() {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
|
currency = json.currency;
|
||||||
data = [['Hour',json.currency + '/kWh', { role: 'style' }, { role: 'annotation' }]];
|
data = [['Hour',json.currency + '/kWh', { role: 'style' }, { role: 'annotation' }]];
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var hour = moment.utc().hours();
|
var hour = moment.utc().hours();
|
||||||
@@ -464,24 +484,27 @@ var drawDay = function() {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
data = [['Hour','kWh', { role: 'style' }, { role: 'annotation' }]];
|
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]];
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var hour = moment.utc().hours();
|
var hour = moment.utc().hours();
|
||||||
var offset = moment().utcOffset()/60;
|
var offset = moment().utcOffset()/60;
|
||||||
var min = 0;
|
var min = 0;
|
||||||
for(var i = hour; i<24; i++) {
|
for(var i = hour; i<24; i++) {
|
||||||
var val = json["h"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
var exp = json["e"+zeropad(i)];
|
||||||
Math.min(0, val);
|
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)];
|
||||||
|
min = Math.min(0, -exp);
|
||||||
};
|
};
|
||||||
for(var i = 0; i < hour; i++) {
|
for(var i = 0; i < hour; i++) {
|
||||||
var val = json["h"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
data[r++] = [zeropad((i+offset)%24), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(1)];
|
var exp = json["e"+zeropad(i)];
|
||||||
Math.min(0, val);
|
data[r++] = [zeropad((i+offset)%24), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(1), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(1)];
|
||||||
|
min = Math.min(0, -exp);
|
||||||
};
|
};
|
||||||
ea = google.visualization.arrayToDataTable(data);
|
ea = google.visualization.arrayToDataTable(data);
|
||||||
if(min == 0)
|
if(min == 0)
|
||||||
eo.vAxis.minValue = 0;
|
eo.vAxis.minValue = 0;
|
||||||
|
|
||||||
ep.draw(ea, eo);
|
ep.draw(ea, eo);
|
||||||
|
|
||||||
setTimeout(drawDay, (61-moment().minute())*60000);
|
setTimeout(drawDay, (61-moment().minute())*60000);
|
||||||
@@ -494,20 +517,22 @@ var drawMonth = function() {
|
|||||||
timeout: 30000,
|
timeout: 30000,
|
||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
data = [['Day','kWh', { role: 'style' }, { role: 'annotation' }]];
|
data = [['Hour', 'Import', { role: 'style' }, { role: 'annotation' }, 'Export', { role: 'style' }, { role: 'annotation' }]];
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var day = moment().date();
|
var day = moment().date();
|
||||||
var eom = moment().subtract(1, 'months').endOf('month').date();
|
var eom = moment().subtract(1, 'months').endOf('month').date();
|
||||||
var min = 0;
|
var min = 0;
|
||||||
for(var i = day; i<=eom; i++) {
|
for(var i = day; i<=eom; i++) {
|
||||||
var val = json["d"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
var exp = json["e"+zeropad(i)];
|
||||||
Math.min(0, val);
|
data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)];
|
||||||
|
min = Math.min(0, -exp);
|
||||||
}
|
}
|
||||||
for(var i = 1; i < day; i++) {
|
for(var i = 1; i < day; i++) {
|
||||||
var val = json["d"+zeropad(i)];
|
var imp = json["i"+zeropad(i)];
|
||||||
data[r++] = [zeropad((i)), val, "color: #6f42c1;opacity: 0.9;", val.toFixed(0)];
|
var exp = json["e"+zeropad(i)];
|
||||||
Math.min(0, val);
|
data[r++] = [zeropad(i), imp, "opacity: 0.9;", imp == 0 ? "" : imp.toFixed(0), exp == 0 ? 0 : -exp, "opacity: 0.9;", exp == 0 ? "" : -exp.toFixed(0)];
|
||||||
|
min = Math.min(0, -exp);
|
||||||
}
|
}
|
||||||
ma = google.visualization.arrayToDataTable(data);
|
ma = google.visualization.arrayToDataTable(data);
|
||||||
if(min == 0)
|
if(min == 0)
|
||||||
@@ -581,10 +606,10 @@ var voltcol = function(pct) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
var ampcol = function(pct) {
|
var ampcol = function(pct) {
|
||||||
if(pct > 85) return '#d90000';
|
if(pct > 90) return '#d90000';
|
||||||
else if(pct > 75) return'#e32100';
|
else if(pct > 85) return'#e32100';
|
||||||
else if(pct > 70) return '#ffb800';
|
else if(pct > 80) return '#ffb800';
|
||||||
else if(pct > 65) return '#dcd800';
|
else if(pct > 75) return '#dcd800';
|
||||||
else return '#32d900';
|
else return '#32d900';
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -597,12 +622,6 @@ var fetch = function() {
|
|||||||
dataType: 'json',
|
dataType: 'json',
|
||||||
}).done(function(json) {
|
}).done(function(json) {
|
||||||
retrycount = 0;
|
retrycount = 0;
|
||||||
if(im) {
|
|
||||||
$(".SimpleMeter").hide();
|
|
||||||
im.show();
|
|
||||||
em.show();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
for(var id in json) {
|
for(var id in json) {
|
||||||
var str = json[id];
|
var str = json[id];
|
||||||
@@ -622,6 +641,8 @@ var fetch = function() {
|
|||||||
$('.ju').html(moment.duration(parseInt(json.u), 'seconds').humanize());
|
$('.ju').html(moment.duration(parseInt(json.u), 'seconds').humanize());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ds = parseInt(json.ds);
|
||||||
|
|
||||||
var kib = parseInt(json.m)/1000;
|
var kib = parseInt(json.m)/1000;
|
||||||
$('.jm').html(kib.toFixed(1));
|
$('.jm').html(kib.toFixed(1));
|
||||||
if(kib > 32) {
|
if(kib > 32) {
|
||||||
@@ -636,9 +657,9 @@ 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) {
|
if(v > 1000 && !swatt) {
|
||||||
v = (v/1000).toFixed(1);
|
v = (v/1000).toFixed(1);
|
||||||
append = "kW";
|
append = "kW";
|
||||||
}
|
}
|
||||||
@@ -655,28 +676,45 @@ var fetch = function() {
|
|||||||
ip.draw(ia, io);
|
ip.draw(ia, io);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(xp) {
|
var om = parseInt(json.om);
|
||||||
var v = parseInt(json.e);
|
|
||||||
var pct = (v*100)/(parseInt(json.om)*1000);
|
if(om > 0) {
|
||||||
var append = "W";
|
$('.rex').show();
|
||||||
if(v > 1000) {
|
$('.rim').hide();
|
||||||
v = (v/1000).toFixed(1);
|
if(xp) {
|
||||||
append = "kW";
|
var v = parseInt(json.e);
|
||||||
|
var pct = Math.min((v*100)/(om*1000), 100);
|
||||||
|
var append = "W";
|
||||||
|
if(v > 1000 && !swatt) {
|
||||||
|
v = (v/1000).toFixed(1);
|
||||||
|
append = "kW";
|
||||||
|
}
|
||||||
|
$('.epo').html(v);
|
||||||
|
$('.epoa').html(append);
|
||||||
|
var arr = [
|
||||||
|
['Slice', 'Value'],
|
||||||
|
['', (pct*2.88)],
|
||||||
|
['', ((100-pct)*2.88)],
|
||||||
|
['', 72],
|
||||||
|
];
|
||||||
|
xo.slices[0].color = ampcol(pct);
|
||||||
|
xa = google.visualization.arrayToDataTable(arr);
|
||||||
|
xp.draw(xa, xo);
|
||||||
}
|
}
|
||||||
$('.epo').html(v);
|
} else {
|
||||||
$('.epoa').html(append);
|
$('.rex').hide();
|
||||||
var arr = [
|
$('.rim').show();
|
||||||
['Slice', 'Value'],
|
|
||||||
['', (pct*2.88)],
|
|
||||||
['', ((100-pct)*2.88)],
|
|
||||||
['', 72],
|
|
||||||
];
|
|
||||||
xo.slices[0].color = ampcol(pct);
|
|
||||||
xa = google.visualization.arrayToDataTable(arr);
|
|
||||||
xp.draw(xa, xo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vp) {
|
if(vp) {
|
||||||
|
switch(ds) {
|
||||||
|
case 1:
|
||||||
|
vo.title = 'Voltage between';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
vo.title = 'Phase voltage';
|
||||||
|
break;
|
||||||
|
}
|
||||||
var c = 0;
|
var c = 0;
|
||||||
var t = 0;
|
var t = 0;
|
||||||
var r = 1;
|
var r = 1;
|
||||||
@@ -685,22 +723,22 @@ 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++] = ['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++] = ['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++] = ['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;
|
||||||
if(v > 0) {
|
if(v > 0) {
|
||||||
@@ -710,33 +748,62 @@ var fetch = function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(ap && json.mf) {
|
if(ap && json.mf) {
|
||||||
var a = 0;
|
switch(ds) {
|
||||||
|
case 1:
|
||||||
|
ao.title = 'Line current';
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
ao.title = 'Phase current';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
var dA = false;
|
||||||
var r = 1;
|
var r = 1;
|
||||||
var arr = [['Phase', 'Amperage', { role: 'style' }, { role: 'annotation' }]];
|
var arr = [['Phase', 'Amperage', { role: 'style' }, { role: 'annotation' }]];
|
||||||
if(json.i1) {
|
if(json.i1 || json.u1) {
|
||||||
var i1 = parseFloat(json.i1);
|
var i1 = parseFloat(json.i1);
|
||||||
a = Math.max(a, i1);
|
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) {
|
if(json.i2 || json.u2) {
|
||||||
var i2 = parseFloat(json.i2);
|
var i2 = parseFloat(json.i2);
|
||||||
a = Math.max(a, i2);
|
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) {
|
if(json.i3 || json.u3) {
|
||||||
var i3 = parseFloat(json.i3);
|
var i3 = parseFloat(json.i3);
|
||||||
a = Math.max(a, i3);
|
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(a > 0) {
|
if(dA) {
|
||||||
aa = google.visualization.arrayToDataTable(arr);
|
aa = google.visualization.arrayToDataTable(arr);
|
||||||
ap.draw(aa, ao);
|
ap.draw(aa, ao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(json.ea) {
|
||||||
|
$('#each').html(json.ea.h.u.toFixed(2));
|
||||||
|
$('#eachc').html(json.ea.h.c.toFixed(2));
|
||||||
|
$('#eacd').html(json.ea.d.u.toFixed(1));
|
||||||
|
$('#eacdc').html(json.ea.d.c.toFixed(1));
|
||||||
|
$('#eacm').html(json.ea.m.u.toFixed(0));
|
||||||
|
$('#eacmc').html(json.ea.m.c.toFixed(0));
|
||||||
|
$('#eax').html(json.ea.x.toFixed(1));
|
||||||
|
$('#eat').html(json.ea.t.toFixed(0));
|
||||||
|
$('.cr').html(currency);
|
||||||
|
if(currency) {
|
||||||
|
$('.sp').show();
|
||||||
|
}
|
||||||
|
if(om > 0) {
|
||||||
|
$('.se').removeClass('d-none');
|
||||||
|
$('#eache').html(json.ea.h.p.toFixed(2));
|
||||||
|
$('#eacde').html(json.ea.d.p.toFixed(1));
|
||||||
|
$('#eacme').html(json.ea.m.p.toFixed(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(json.me) {
|
if(json.me) {
|
||||||
$('.me').addClass('d-none');
|
$('.me').addClass('d-none');
|
||||||
$('.me'+json.me).removeClass('d-none');
|
$('.me'+json.me).removeClass('d-none');
|
||||||
@@ -787,10 +854,10 @@ 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("Sagecom");
|
$('.jmt').html("Sagemcom");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
$('.jmt').html("");
|
$('.jmt').html("");
|
||||||
@@ -823,7 +890,7 @@ var fetch = function() {
|
|||||||
|
|
||||||
var upgrade = function() {
|
var upgrade = function() {
|
||||||
if(nextVersion) {
|
if(nextVersion) {
|
||||||
if(confirm("Are you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) {
|
if(confirm("WARNING: If you have a M-BUS powered device (Pow-U), please keep USB power connected while upgrading.\n\nAre you sure you want to perform upgrade to " + nextVersion.tag_name + "?")) {
|
||||||
$('#loading-indicator').show();
|
$('#loading-indicator').show();
|
||||||
window.location.href="/upgrade?version=" + nextVersion.tag_name;
|
window.location.href="/upgrade?version=" + nextVersion.tag_name;
|
||||||
}
|
}
|
||||||
71
lib/ClassicUi/html/configfile.html
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
<form method="get" action="/configfile.cfg">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<h6>Download configuration</h6>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="iw" value="true" checked/> WiFi</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="im" value="true" checked/> MQTT</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="ie" value="true" checked/> Web</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="it" value="true" checked/> Meter</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="ih" value="true" checked/> Thresholds</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="ig" value="true" checked/> GPIO</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="id" value="true" checked/> Domoticz</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="in" value="true" checked/> NTP</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-2 col-md-3 col-sm-6">
|
||||||
|
<label><input type="checkbox" name="is" value="true" checked/> ENTSO-E</label>
|
||||||
|
</div>
|
||||||
|
<div class="col-xl-6 col-md-8">
|
||||||
|
<label><input type="checkbox" name="ic" value="true"/> Include Secrets (SSID, PSK, passwords and tokens)</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 text-right">
|
||||||
|
<button class="btn btn-primary">Download</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<form method="post" enctype="multipart/form-data" class="upload-form">
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<h6>Upload configuration</h6>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group mb-3">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Upload</span>
|
||||||
|
</div>
|
||||||
|
<div class="custom-file">
|
||||||
|
<input name="file" type="file" class="custom-file-input" id="fileUploadField">
|
||||||
|
<label class="custom-file-label" for="fileUploadField">Choose file</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 text-right">
|
||||||
|
<button class="btn btn-primary">Upload</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="/" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
60
lib/ClassicUi/html/data.json
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"im" : %d,
|
||||||
|
"om" : %d,
|
||||||
|
"mf" : %d,
|
||||||
|
"i" : %d,
|
||||||
|
"e" : %d,
|
||||||
|
"ri" : %d,
|
||||||
|
"re" : %d,
|
||||||
|
"ic" : %.3f,
|
||||||
|
"ec" : %.3f,
|
||||||
|
"ric" : %.3f,
|
||||||
|
"rec" : %.3f,
|
||||||
|
"u1" : %.2f,
|
||||||
|
"u2" : %.2f,
|
||||||
|
"u3" : %.2f,
|
||||||
|
"i1" : %.2f,
|
||||||
|
"i2" : %.2f,
|
||||||
|
"i3" : %.2f,
|
||||||
|
"f" : %.2f,
|
||||||
|
"f1" : %.2f,
|
||||||
|
"f2" : %.2f,
|
||||||
|
"f3" : %.2f,
|
||||||
|
"v" : %.3f,
|
||||||
|
"r" : %d,
|
||||||
|
"t" : %.2f,
|
||||||
|
"u" : %u,
|
||||||
|
"m" : %u,
|
||||||
|
"em" : %d,
|
||||||
|
"hm" : %d,
|
||||||
|
"wm" : %d,
|
||||||
|
"mm" : %d,
|
||||||
|
"me" : %d,
|
||||||
|
"p" : %s,
|
||||||
|
"mt" : %d,
|
||||||
|
"ds" : %d,
|
||||||
|
"ea" : {
|
||||||
|
"x" : %.1f,
|
||||||
|
"p" : [ %s ],
|
||||||
|
"t" : %d,
|
||||||
|
"h" : {
|
||||||
|
"u" : %.2f,
|
||||||
|
"c" : %.2f,
|
||||||
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
|
},
|
||||||
|
"d" : {
|
||||||
|
"u" : %.2f,
|
||||||
|
"c" : %.2f,
|
||||||
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
|
},
|
||||||
|
"m" : {
|
||||||
|
"u" : %.2f,
|
||||||
|
"c" : %.2f,
|
||||||
|
"p" : %.2f,
|
||||||
|
"i" : %.2f
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"c" : %u
|
||||||
|
}
|
||||||
50
lib/ClassicUi/html/dayplot.json
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
{
|
||||||
|
"i00" : %.2f,
|
||||||
|
"i01" : %.2f,
|
||||||
|
"i02" : %.2f,
|
||||||
|
"i03" : %.2f,
|
||||||
|
"i04" : %.2f,
|
||||||
|
"i05" : %.2f,
|
||||||
|
"i06" : %.2f,
|
||||||
|
"i07" : %.2f,
|
||||||
|
"i08" : %.2f,
|
||||||
|
"i09" : %.2f,
|
||||||
|
"i10" : %.2f,
|
||||||
|
"i11" : %.2f,
|
||||||
|
"i12" : %.2f,
|
||||||
|
"i13" : %.2f,
|
||||||
|
"i14" : %.2f,
|
||||||
|
"i15" : %.2f,
|
||||||
|
"i16" : %.2f,
|
||||||
|
"i17" : %.2f,
|
||||||
|
"i18" : %.2f,
|
||||||
|
"i19" : %.2f,
|
||||||
|
"i20" : %.2f,
|
||||||
|
"i21" : %.2f,
|
||||||
|
"i22" : %.2f,
|
||||||
|
"i23" : %.2f,
|
||||||
|
"e00" : %.2f,
|
||||||
|
"e01" : %.2f,
|
||||||
|
"e02" : %.2f,
|
||||||
|
"e03" : %.2f,
|
||||||
|
"e04" : %.2f,
|
||||||
|
"e05" : %.2f,
|
||||||
|
"e06" : %.2f,
|
||||||
|
"e07" : %.2f,
|
||||||
|
"e08" : %.2f,
|
||||||
|
"e09" : %.2f,
|
||||||
|
"e10" : %.2f,
|
||||||
|
"e11" : %.2f,
|
||||||
|
"e12" : %.2f,
|
||||||
|
"e13" : %.2f,
|
||||||
|
"e14" : %.2f,
|
||||||
|
"e15" : %.2f,
|
||||||
|
"e16" : %.2f,
|
||||||
|
"e17" : %.2f,
|
||||||
|
"e18" : %.2f,
|
||||||
|
"e19" : %.2f,
|
||||||
|
"e20" : %.2f,
|
||||||
|
"e21" : %.2f,
|
||||||
|
"e22" : %.2f,
|
||||||
|
"e23" : %.2f
|
||||||
|
}
|
||||||
@@ -11,21 +11,20 @@
|
|||||||
<h6>Debugging</h6>
|
<h6>Debugging</h6>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-2 col-md-3">
|
<div class="col-xl-2 col-md-3">
|
||||||
<label><input type="checkbox" name="debugTelnet" value="true" ${config.debugTelnet}/> Telnet debugger</label>
|
<label><input type="checkbox" name="debugTelnet" value="true" %s/> Telnet debugger</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-2 col-md-3">
|
<div class="col-xl-2 col-md-3">
|
||||||
<label><input type="checkbox" name="debugSerial" value="true" ${config.debugSerial}/> Serial debugger</label>
|
<label><input type="checkbox" name="debugSerial" value="true" %s/> Serial debugger</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-3 col-md-4">
|
<div class="col-xl-3 col-md-4">
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<label class="col-6">Debug level</label>
|
<label class="col-6">Debug level</label>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<select class="form-control form-control-sm" name="debugLevel">
|
<select class="form-control form-control-sm" name="debugLevel">
|
||||||
<option value="1" ${config.debugLevel1}>Verbose</option>
|
<option value="1" %s>Verbose</option>
|
||||||
<option value="2" ${config.debugLevel2}>Debug</option>
|
<option value="2" %s>Debug</option>
|
||||||
<option value="3" ${config.debugLevel3}>Info</option>
|
<option value="3" %s>Info</option>
|
||||||
<option value="4" ${config.debugLevel4}>Warning</option>
|
<option value="4" %s>Warning</option>
|
||||||
<option value="5" ${config.debugLevel5}>Error</option>
|
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -6,13 +6,13 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Electricity IDX</span>
|
<span class="input-group-text">Electricity IDX</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" class="form-control" name="elidx" value="{elidx}" min="0" max="65535"/>
|
<input type="number" class="form-control" name="elidx" value="%d" min="0" max="65535"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 240px;">
|
<div class="m-2 input-group input-group-sm" style="width: 240px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Current (3 Phase) IDX</span>
|
<span class="input-group-text">Current (3 Phase) IDX</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" class="form-control" name="cl1idx" value="{cl1idx}" min="0" max="65535"/>
|
<input type="number" class="form-control" name="cl1idx" value="%d" min="0" max="65535"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex flex-row flex-wrap">
|
<div class="d-flex flex-row flex-wrap">
|
||||||
@@ -20,26 +20,26 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Voltage L1 IDX</span>
|
<span class="input-group-text">Voltage L1 IDX</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" class="form-control" name="vl1idx" value="{vl1idx}" min="0" max="65535"/>
|
<input type="number" class="form-control" name="vl1idx" value="%d" min="0" max="65535"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Voltage L1 IDX</span>
|
<span class="input-group-text">Voltage L2 IDX</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" class="form-control" name="vl2idx" value="{vl2idx}" min="0" max="65535"/>
|
<input type="number" class="form-control" name="vl2idx" value="%d" min="0" max="65535"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Voltage L1 IDX</span>
|
<span class="input-group-text">Voltage L3 IDX</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" class="form-control" name="vl3idx" value="{vl3idx}" min="0" max="65535"/>
|
<input type="number" class="form-control" name="vl3idx" value="%d" min="0" max="65535"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<a href="/" class="btn btn-outline-secondary">Back</a>
|
<a href="/mqtt" class="btn btn-outline-secondary">Back</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-right">
|
<div class="col-6 text-right">
|
||||||
<button class="btn btn-primary">Save</button>
|
<button class="btn btn-primary">Save</button>
|
||||||
@@ -1,18 +1,21 @@
|
|||||||
<div class="alert alert-danger">
|
<div class="alert alert-danger">
|
||||||
WARNING: Units powered over M-bus must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit.
|
WARNING: Units powered by M-BUS (Pow-U) must be connected to an external power supply during firmware upload. Failure to do so may cause power-down during upload resulting in non-functioning unit.
|
||||||
</div>
|
</div>
|
||||||
<div class="alert alert-warning">
|
<div class="alert alert-warning">
|
||||||
Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit.
|
Your board is using {chipset} chipset. Only upload firmware designed for this chipset. Failure to do so may result in non-functioning unit.
|
||||||
<span id="fwDownload" style="display: none;"><br/>Download latest firmware file <a id="fwLink" href="#" data-chipset="{chipset}">here</a></span>
|
<span id="fwDownload" style="display: none;"><br/>Download latest firmware file <a id="fwLink" href="#" data-chipset="{chipset}">here</a></span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
When using URL, only a valid ESP OTA server response will be accepted.
|
||||||
|
</div>
|
||||||
|
|
||||||
<form method="post" enctype="multipart/form-data" class="upload-form">
|
<form method="post" enctype="multipart/form-data" class="upload-form">
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<div class="input-group mb-3">
|
<div class="input-group">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Upload</span>
|
<span class="input-group-text">Upload file</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="custom-file">
|
<div class="custom-file">
|
||||||
<input name="file" type="file" class="custom-file-input" id="fileUploadField">
|
<input name="file" type="file" class="custom-file-input" id="fileUploadField">
|
||||||
@@ -21,6 +24,19 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">or</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-6">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Use URL</span>
|
||||||
|
</div>
|
||||||
|
<input type="text" name="url" class="form-control"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
@@ -28,7 +44,7 @@
|
|||||||
<a href="javascript:history.back();" class="btn btn-outline-secondary">Back</a>
|
<a href="javascript:history.back();" class="btn btn-outline-secondary">Back</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-6 text-right">
|
<div class="col-6 text-right">
|
||||||
<button class="btn btn-primary">Upload</button>
|
<button class="btn btn-primary">Upgrade firmware</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<div id="newVersion" class="alert alert-info d-none">New version <span id="newVersionTag"></span>!
|
<div id="newVersion" class="alert alert-info d-none">New version <span id="newVersionTag"></span>!
|
||||||
<a id="newVersionUrl" href="#" target="_blank">view</a>
|
<a id="newVersionUrl" href="#" target="_blank">view</a> or <a href="javascript:upgrade();">click here to upgrade</a>
|
||||||
<span class="d-none ssl-capable"> or <a href="javascript:upgrade();">upgrade</a></span>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
@@ -10,9 +9,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js" integrity="sha512-qTXRIMyZIFb8iQcfjXWCO8+M5Tbc38Qi5WzdPOYZHIlZpzBHG3L3by84BBBOiRGiEb7KKtAOAs5qYdUiZiQNNQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://code.jquery.com/jquery-3.6.0.min.js" integrity="sha256-/xUj+3OJU5yExlq6GSYGSHk7tPXikynS7ogEvDej/m4=" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
|
||||||
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
|
||||||
<script src="https://www.gstatic.com/charts/loader.js"></script>
|
<script src="https://www.gstatic.com/charts/loader.js"></script>
|
||||||
<script src="application-${version}.js"></script>
|
<script src="application-${version}.js"></script>
|
||||||
|
|
||||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,6 +1,6 @@
|
|||||||
<div class="alert alert-warning">!!WARNING!!<br/>Do not change anything here unless you know exactly what you are doing! Changing things here could cause the device to stop responding</div>
|
<div class="alert alert-warning">!!WARNING!!<br/>Do not change anything here unless you know exactly what you are doing! Changing things here could cause the device to stop responding</div>
|
||||||
<form method="post" action="/save">
|
<form method="post" action="/save">
|
||||||
<input type="hidden" name="gpioConfig" value="true"/>
|
<input type="hidden" name="gc" value="true"/>
|
||||||
<div class="my-3 p-3 bg-white rounded shadow">
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
<h6>GPIO settings</h6>
|
<h6>GPIO settings</h6>
|
||||||
<div class="d-flex flex-row flex-wrap">
|
<div class="d-flex flex-row flex-wrap">
|
||||||
@@ -8,18 +8,18 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">HAN</span>
|
<span class="input-group-text">HAN</span>
|
||||||
</div>
|
</div>
|
||||||
<select name="hanPin" class="form-control">
|
<select name="h" class="form-control">
|
||||||
${options.han}
|
${h}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">LED</span>
|
<span class="input-group-text">LED</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="ledPin" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPin}"/>
|
<input name="l" type="number" min="2" max="${g}" class="form-control" value="${l}"/>
|
||||||
<div class="input-group-append" title="Inverted">
|
<div class="input-group-append" title="Inverted">
|
||||||
<label class="input-group-text">
|
<label class="input-group-text">
|
||||||
<input type="checkbox" name="ledInverted" value="true" ${config.ledInverted}/> inv
|
<input type="checkbox" name="i" value="true" ${i}/> inv
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,12 +27,12 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">RGB</span>
|
<span class="input-group-text">RGB</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="ledPinRed" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinRed}"/>
|
<input name="r" type="number" min="2" max="${g}" class="form-control" value="${r}"/>
|
||||||
<input name="ledPinGreen" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinGreen}"/>
|
<input name="e" type="number" min="2" max="${g}" class="form-control" value="${e}"/>
|
||||||
<input name="ledPinBlue" type="number" min="2" max="${gpio.max}" class="form-control" value="${config.ledPinBlue}"/>
|
<input name="b" type="number" min="2" max="${g}" class="form-control" value="${b}"/>
|
||||||
<div class="input-group-append" title="Inverted">
|
<div class="input-group-append" title="Inverted">
|
||||||
<label class="input-group-text">
|
<label class="input-group-text">
|
||||||
<input type="checkbox" name="ledRgbInverted" value="true" ${config.ledRgbInverted}/> inv
|
<input type="checkbox" name="n" value="true" ${n}/> inv
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -40,31 +40,31 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">AP button</span>
|
<span class="input-group-text">AP button</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="apPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.apPin}"/>
|
<input name="a" type="number" min="0" max="${g}" class="form-control" value="${a}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Temperature</span>
|
<span class="input-group-text">Temperature</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="tempSensorPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.tempSensorPin}"/>
|
<input name="t" type="number" min="0" max="${g}" class="form-control" value="${t}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
<div class="m-2 input-group input-group-sm" style="width: 150px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Analog temp</span>
|
<span class="input-group-text">Analog temp</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="tempAnalogSensorPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.tempAnalogSensorPin}"/>
|
<input name="m" type="number" min="0" max="${g}" class="form-control" value="${m}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 100px;">
|
<div class="m-2 input-group input-group-sm" style="width: 100px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Vcc</span>
|
<span class="input-group-text">Vcc</span>
|
||||||
</div>
|
</div>
|
||||||
<input name="vccPin" type="number" min="0" max="${gpio.max}" class="form-control" value="${config.vccPin}"/>
|
<input name="v" type="number" min="0" max="${g}" class="form-control" value="${v}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
<div class="m-2 input-group input-group-sm" style="width: 200px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">GND resistor</span>
|
<span class="input-group-text">GND resistor</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="vccResistorGnd" value="${config.vccResistorGnd}" />
|
<input type="number" min="1" max="1000" step="1" class="form-control" name="d" value="${d}" />
|
||||||
<div class="input-group-append" title="Inverted">
|
<div class="input-group-append" title="Inverted">
|
||||||
<label class="input-group-text">kΩ</label>
|
<label class="input-group-text">kΩ</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -73,7 +73,7 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Vcc resistor</span>
|
<span class="input-group-text">Vcc resistor</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" min="1" max="1000" step="1" class="form-control" name="vccResistorVcc" value="${config.vccResistorVcc}" />
|
<input type="number" min="1" max="1000" step="1" class="form-control" name="s" value="${s}" />
|
||||||
<div class="input-group-append" title="Inverted">
|
<div class="input-group-append" title="Inverted">
|
||||||
<label class="input-group-text">kΩ</label>
|
<label class="input-group-text">kΩ</label>
|
||||||
</div>
|
</div>
|
||||||
@@ -82,19 +82,19 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Multiplier</span>
|
<span class="input-group-text">Multiplier</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" min="0.1" max="10" step="0.01" class="form-control" name="vccMultiplier" value="${config.vccMultiplier}" />
|
<input type="number" min="0.1" max="10" step="0.01" class="form-control" name="u" value="${u}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 120px;">
|
<div class="m-2 input-group input-group-sm" style="width: 120px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Offset</span>
|
<span class="input-group-text">Offset</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" min="0.0" max="3.5" step="0.01" class="form-control" name="vccOffset" value="${config.vccOffset}" />
|
<input type="number" min="0.0" max="3.5" step="0.01" class="form-control" name="o" value="${o}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="m-2 input-group input-group-sm" style="width: 130px;">
|
<div class="m-2 input-group input-group-sm" style="width: 130px;">
|
||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Boot limit</span>
|
<span class="input-group-text">Boot limit</span>
|
||||||
</div>
|
</div>
|
||||||
<input type="number" min="2.5" max="3.5" step="0.1" class="form-control" name="vccBootLimit" value="${config.vccBootLimit}" />
|
<input type="number" min="2.5" max="3.5" step="0.1" class="form-control" name="c" value="${c}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>AMS reader</title>
|
<title>AMS reader</title>
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.1/dist/css/bootstrap.min.css" integrity="sha384-zCbKRCUGaJDkqS1kPbPd7TveP5iyJE0EjAuZQTgFLD2ylzuqKfdKlfG/eSrtxUkn" crossorigin="anonymous" referrerpolicy="no-referrer">
|
||||||
<style>
|
<style>
|
||||||
.navbar-expand .navbar-nav .nav-link,.navbar-brand {
|
.navbar-expand .navbar-nav .nav-link,.navbar-brand {
|
||||||
padding-top: 0px;
|
padding-top: 0px;
|
||||||
@@ -30,10 +31,11 @@
|
|||||||
width: 50%;
|
width: 50%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
.ipo,.xpo {
|
.ipo,.epo {
|
||||||
font-size: 1.7rem;
|
font-size: 1.7rem;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
.ipoa,.xpoa {
|
.ipoa,.epoa {
|
||||||
font-size: 1.0rem;
|
font-size: 1.0rem;
|
||||||
color: grey;
|
color: grey;
|
||||||
}
|
}
|
||||||
@@ -62,7 +64,7 @@
|
|||||||
<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" 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/gskjold/AmsToMqttBridge/wiki" target="_blank">Documentation</a>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,6 +78,7 @@
|
|||||||
<div class="dropdown-menu" aria-labelledby="system-link">
|
<div class="dropdown-menu" aria-labelledby="system-link">
|
||||||
<a class="dropdown-item" href="/gpio">GPIO</a>
|
<a class="dropdown-item" href="/gpio">GPIO</a>
|
||||||
<a class="dropdown-item" href="/debugging">Debugging</a>
|
<a class="dropdown-item" href="/debugging">Debugging</a>
|
||||||
|
<a class="dropdown-item" href="/configfile">Configuration file</a>
|
||||||
<a class="dropdown-item" href="/firmware">Firmware</a>
|
<a class="dropdown-item" href="/firmware">Firmware</a>
|
||||||
<div class="dropdown-divider"></div>
|
<div class="dropdown-divider"></div>
|
||||||
<a class="dropdown-item" href="/restart">Restart</a>
|
<a class="dropdown-item" href="/restart">Restart</a>
|
||||||
@@ -1,21 +1,21 @@
|
|||||||
<div class="bg-white rounded shadow p-1 mb-3">
|
<div class="bg-white rounded shadow p-1 mb-3">
|
||||||
<div class="d-flex flex-wrap">
|
<div class="d-flex flex-wrap">
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<div class="text-center">Up <span class="ju">{cs}</span></div>
|
<div class="text-center">Up <span class="ju">-</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-fill rt">
|
<div class="flex-fill rt">
|
||||||
<div class="text-center">Temperature: <span class="jt">{temp}</span>°C</div>
|
<div class="text-center">Temperature: <span class="jt">-</span>°C</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-fill rv">
|
<div class="flex-fill rv">
|
||||||
<div class="text-center">ESP volt: <span class="jv">{vcc}</span>V</div>
|
<div class="text-center">ESP volt: <span class="jv">-</span>V</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<div class="text-center">WiFi RSSI: <span class="jr">{rssi}</span>dBm</div>
|
<div class="text-center">WiFi RSSI: <span class="jr">-</span>dBm</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-fill">
|
<div class="flex-fill">
|
||||||
<div class="text-center">Free mem: <span class="jm">{mem}</span>kb</div>
|
<div class="text-center">Free mem: <span class="jm">-</span>kb</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-fill rc">
|
<div class="flex-fill rc">
|
||||||
<div class="text-center"><span class="jc"></span></div>
|
<div class="text-center"><span class="jc"></span></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -27,31 +27,31 @@
|
|||||||
<div class="text-center overlay-plot">
|
<div class="text-center overlay-plot">
|
||||||
<div id="ip" class="plot1"></div>
|
<div id="ip" class="plot1"></div>
|
||||||
<span class="plot-overlay">
|
<span class="plot-overlay">
|
||||||
<span class="ipo">{P}</span>
|
<span class="ipo">-</span>
|
||||||
<span class="ipoa">W</span>
|
<span class="ipoa">W</span>
|
||||||
<br/>
|
<br/>
|
||||||
<span class="pol">{ti}</span>
|
<span class="pol">Import</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row ric" style="display: {da};">
|
<div class="row ric" style="display: none;">
|
||||||
<div class="col-5"><span class="jmt"></span></div>
|
<div class="col-5"><span class="jmt"></span></div>
|
||||||
<div class="col-7 text-right"><span class="jic">{tPI}</span> kWh</div>
|
<div class="col-7 text-right"><span class="jic">-</span> kWh</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 col-sm-6 mb-3" style="display: {de};">
|
<div class="col-lg-3 col-sm-6 mb-3 rex" style="display: none;">
|
||||||
<div class="bg-white rounded shadow p-3">
|
<div class="bg-white rounded shadow p-3">
|
||||||
<div class="text-center overlay-plot">
|
<div class="text-center overlay-plot">
|
||||||
<div id="xp" class="plot1"></div>
|
<div id="xp" class="plot1"></div>
|
||||||
<span class="plot-overlay">
|
<span class="plot-overlay">
|
||||||
<span class="xpo">{PO}</span>
|
<span class="epo">-</span>
|
||||||
<span class="xpoa">W</span>
|
<span class="epoa">W</span>
|
||||||
<br/>
|
<br/>
|
||||||
<span class="pol">Export</span>
|
<span class="pol">Export</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row rec" style="display: {da};">
|
<div class="row rec" style="display: none;">
|
||||||
<div class="col-12 text-right"><span class="jec">{tPO}</span> kWh</div>
|
<div class="col-12 text-right"><span class="jec">-</span> kWh</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -69,44 +69,116 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 col-sm-6 mb-3" style="display: {dn};">
|
<div class="col-lg-3 col-sm-6 mb-3 rim" style="display: none;">
|
||||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
<div class="bg-white rounded shadow p-3">
|
||||||
<h5 class="text-center">Reactive</h5>
|
<h5 class="text-center">Reactive</h5>
|
||||||
<div class="row rri">
|
<div class="row rri">
|
||||||
<div class="col-12 font-weight-bold">Instant</div>
|
<div class="col-12 font-weight-bold">Instant</div>
|
||||||
<div class="col-4">In</div>
|
<div class="col-4">In</div>
|
||||||
<div class="col-8 text-right"><span class="jri">{Q}</span> VAr</div>
|
<div class="col-8 text-right"><span class="jri">-</span> VAr</div>
|
||||||
<div class="col-4">Out</div>
|
<div class="col-4">Out</div>
|
||||||
<div class="col-8 text-right"><span class="jre">{QO}</span> VAr</div>
|
<div class="col-8 text-right"><span class="jre">-</span> VAr</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row rric">
|
<div class="row rric">
|
||||||
<div class="col-12 font-weight-bold">Total</div>
|
<div class="col-12 font-weight-bold">Total</div>
|
||||||
<div class="col-4">In</div>
|
<div class="col-4">In</div>
|
||||||
<div class="col-8 text-right"><span class="jric">{tQI}</span> kVArh</div>
|
<div class="col-8 text-right"><span class="jric">-</span> kVArh</div>
|
||||||
<div class="col-4">Out</div>
|
<div class="col-4">Out</div>
|
||||||
<div class="col-8 text-right"><span class="jrec">{tQO}</span> kVArh</div>
|
<div class="col-8 text-right"><span class="jrec">-</span> kVArh</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 mb-3" style="display: {de};">
|
<div class="col-lg-6 mb-3 rex" style="display: none;">
|
||||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
<div class="bg-white rounded shadow p-3">
|
||||||
<div class="row rrec">
|
<div class="row rrec">
|
||||||
<div class="col-sm-4 font-weight-bold">Instant reactive</div>
|
<div class="col-sm-4 font-weight-bold">Instant reactive</div>
|
||||||
<div class="col-4 col-sm-1">In</div>
|
<div class="col-4 col-sm-1">In</div>
|
||||||
<div class="col-8 col-sm-3 text-right"><span class="jri">{Q}</span> VAr</div>
|
<div class="col-8 col-sm-3 text-right"><span class="jri">-</span> VAr</div>
|
||||||
<div class="col-4 col-sm-1">Out</div>
|
<div class="col-4 col-sm-1">Out</div>
|
||||||
<div class="col-8 col-sm-3 text-right"><span class="jre">{QO}</span> VAr</div>
|
<div class="col-8 col-sm-3 text-right"><span class="jre">-</span> VAr</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6 mb-3" style="display: {de};">
|
<div class="col-lg-6 mb-3 rex" style="display: none;">
|
||||||
<div class="bg-white rounded shadow p-3" style="display: {da};">
|
<div class="bg-white rounded shadow p-3">
|
||||||
<div class="row rrec">
|
<div class="row rrec">
|
||||||
<div class="col-sm-4 font-weight-bold">Total reactive</div>
|
<div class="col-sm-4 font-weight-bold">Total reactive</div>
|
||||||
<div class="col-4 col-sm-1">In</div>
|
<div class="col-4 col-sm-1">In</div>
|
||||||
<div class="col-8 col-sm-3 text-right"><span class="jric">{tQI}</span> kVArh</div>
|
<div class="col-8 col-sm-3 text-right"><span class="jric">-</span> kVArh</div>
|
||||||
<div class="col-4 col-sm-1">Out</div>
|
<div class="col-4 col-sm-1">Out</div>
|
||||||
<div class="col-8 col-sm-3 text-right"><span class="jrec">{tQO}</span> kVArh</div>
|
<div class="col-8 col-sm-3 text-right"><span class="jrec">-</span> kVArh</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-xl-12 mb-3">
|
||||||
|
<div class="bg-white rounded shadow pt-3 pb-3" style="font-size: 14px;">
|
||||||
|
<strong class="mr-3 ml-3">Real time consumption</strong><br/>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Hour</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="each"></span> kWh
|
||||||
|
<span class="sp text-nowrap" style="display: none;">(<span id="eachc"></span> <span class="cr"></span>)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Day</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacd"></span> kWh
|
||||||
|
<span class="sp text-nowrap" style="display: none;">(<span id="eacdc"></span> <span class="cr"></span>)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Month</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacm"></span> kWh
|
||||||
|
<span class="sp text-nowrap" style="display: none;">(<span id="eacmc"></span> <span class="cr"></span>)</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Max</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eax"></span> / <span id="eat"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<strong class="mr-3 ml-3 se d-none">Real time production</strong><br/>
|
||||||
|
<div class="row se d-none">
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Hour</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eache"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Day</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacde"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6">
|
||||||
|
<div class="mr-3 ml-3 d-flex">
|
||||||
|
<div>Month</div>
|
||||||
|
<div class="flex-fill text-right">
|
||||||
|
<span id="eacme"></span> kWh
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-sm-6"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -35,8 +35,13 @@
|
|||||||
<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="9600" {b9600}>9600</option>
|
<option value="9600" {b9600}>9600</option>
|
||||||
|
<option value="19200" {b19200}>19200</option>
|
||||||
|
<option value="38400" {b38400}>38400</option>
|
||||||
|
<option value="57600" {b57600}>57600</option>
|
||||||
<option value="115200" {b115200}>115200</option>
|
<option value="115200" {b115200}>115200</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -54,14 +59,17 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-3 col-md-4 col-sm-3 col-6">
|
<div class="col-lg-2 col-md-4 col-sm-3 col-6">
|
||||||
<div class="m-2">
|
<div class="m-2">
|
||||||
<label class="small"><input type="checkbox" name="i" value="true" {i}/> Invert <span class="d-none d-md-inline">signal</span></label>
|
<label class="small"><input type="checkbox" name="i" value="true" {i}/> Invert <span class="d-none d-md-inline">signal</span></label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-6">
|
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-7">
|
||||||
<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">Distribution system</span>
|
<span class="input-group-text">Distribution system</span>
|
||||||
@@ -73,22 +81,15 @@
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-2 col-md-3 col-sm-5">
|
<div class="col-lg-3 col-md-4 col-sm-5">
|
||||||
<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">Main fuse</span>
|
<span class="input-group-text">Main fuse</span>
|
||||||
</div>
|
</div>
|
||||||
<select class="form-control" name="f">
|
<input class="form-control text-right" name="f" type="number" min="5" max="255" step="1" value="{f}"/>
|
||||||
<option value="0" {f0}></option>
|
<div class="input-group-append">
|
||||||
<option value="16" {f16}>16A</option>
|
<span class="input-group-text">A</span>
|
||||||
<option value="20" {f20}>20A</option>
|
</div>
|
||||||
<option value="25" {f25}>25A</option>
|
|
||||||
<option value="32" {f32}>32A</option>
|
|
||||||
<option value="35" {f35}>35A</option>
|
|
||||||
<option value="40" {f40}>40A</option>
|
|
||||||
<option value="50" {f50}>50A</option>
|
|
||||||
<option value="63" {f63}>63A</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-7">
|
<div class="col-xl-3 col-lg-4 col-md-5 col-sm-7">
|
||||||
@@ -96,7 +97,7 @@
|
|||||||
<div class="input-group-prepend">
|
<div class="input-group-prepend">
|
||||||
<span class="input-group-text">Production capacity</span>
|
<span class="input-group-text">Production capacity</span>
|
||||||
</div>
|
</div>
|
||||||
<input class="form-control" name="p" type="number" min="0" max="50" value="{p}"/>
|
<input class="form-control text-right" name="p" type="number" min="0" max="255" step="1" value="{p}"/>
|
||||||
<div class="input-group-append">
|
<div class="input-group-append">
|
||||||
<span class="input-group-text">kWp</span>
|
<span class="input-group-text">kWp</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -121,6 +122,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row mt-3">
|
||||||
|
<div class="col-sm-6">
|
||||||
|
<a href="/thresholds">Configure tariff thresholds</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 text-right">
|
||||||
|
<a href="/meteradvanced">Multipliers</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row form-group">
|
<div class="row form-group">
|
||||||
49
lib/ClassicUi/html/meteradvanced.html
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<form method="post" action="/save">
|
||||||
|
<input type="hidden" name="ma" value="true"/>
|
||||||
|
<div class="my-3 p-3 bg-white rounded shadow">
|
||||||
|
<h6>Multipliers</h6>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Instant</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control text-right" name="wm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Voltage</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control text-right" name="vm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Amperage</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control text-right" name="am" value="%.2f" min="0.00" max="655.35" step="0.01"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-3 col-md-4 col-sm-6">
|
||||||
|
<div class="m-2 input-group input-group-sm">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<span class="input-group-text">Accumulated</span>
|
||||||
|
</div>
|
||||||
|
<input type="number" class="form-control text-right" name="cm" value="%.2f" min="0.00" max="655.35" step="0.01"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<hr/>
|
||||||
|
<div class="row form-group">
|
||||||
|
<div class="col-6">
|
||||||
|
<a href="/meter" class="btn btn-outline-secondary">Back</a>
|
||||||
|
</div>
|
||||||
|
<div class="col-6 text-right">
|
||||||
|
<button class="btn btn-primary">Save</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
64
lib/ClassicUi/html/monthplot.json
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
{
|
||||||
|
"i01" : %.2f,
|
||||||
|
"i02" : %.2f,
|
||||||
|
"i03" : %.2f,
|
||||||
|
"i04" : %.2f,
|
||||||
|
"i05" : %.2f,
|
||||||
|
"i06" : %.2f,
|
||||||
|
"i07" : %.2f,
|
||||||
|
"i08" : %.2f,
|
||||||
|
"i09" : %.2f,
|
||||||
|
"i10" : %.2f,
|
||||||
|
"i11" : %.2f,
|
||||||
|
"i12" : %.2f,
|
||||||
|
"i13" : %.2f,
|
||||||
|
"i14" : %.2f,
|
||||||
|
"i15" : %.2f,
|
||||||
|
"i16" : %.2f,
|
||||||
|
"i17" : %.2f,
|
||||||
|
"i18" : %.2f,
|
||||||
|
"i19" : %.2f,
|
||||||
|
"i20" : %.2f,
|
||||||
|
"i21" : %.2f,
|
||||||
|
"i22" : %.2f,
|
||||||
|
"i23" : %.2f,
|
||||||
|
"i24" : %.2f,
|
||||||
|
"i25" : %.2f,
|
||||||
|
"i26" : %.2f,
|
||||||
|
"i27" : %.2f,
|
||||||
|
"i28" : %.2f,
|
||||||
|
"i29" : %.2f,
|
||||||
|
"i30" : %.2f,
|
||||||
|
"i31" : %.2f,
|
||||||
|
"e01" : %.2f,
|
||||||
|
"e02" : %.2f,
|
||||||
|
"e03" : %.2f,
|
||||||
|
"e04" : %.2f,
|
||||||
|
"e05" : %.2f,
|
||||||
|
"e06" : %.2f,
|
||||||
|
"e07" : %.2f,
|
||||||
|
"e08" : %.2f,
|
||||||
|
"e09" : %.2f,
|
||||||
|
"e10" : %.2f,
|
||||||
|
"e11" : %.2f,
|
||||||
|
"e12" : %.2f,
|
||||||
|
"e13" : %.2f,
|
||||||
|
"e14" : %.2f,
|
||||||
|
"e15" : %.2f,
|
||||||
|
"e16" : %.2f,
|
||||||
|
"e17" : %.2f,
|
||||||
|
"e18" : %.2f,
|
||||||
|
"e19" : %.2f,
|
||||||
|
"e20" : %.2f,
|
||||||
|
"e21" : %.2f,
|
||||||
|
"e22" : %.2f,
|
||||||
|
"e23" : %.2f,
|
||||||
|
"e24" : %.2f,
|
||||||
|
"e25" : %.2f,
|
||||||
|
"e26" : %.2f,
|
||||||
|
"e27" : %.2f,
|
||||||
|
"e28" : %.2f,
|
||||||
|
"e29" : %.2f,
|
||||||
|
"e30" : %.2f,
|
||||||
|
"e31" : %.2f
|
||||||
|
}
|
||||||
@@ -59,9 +59,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<select id="f" class="form-control mc" name="f">
|
<select id="f" class="form-control mc" name="f">
|
||||||
<option value="0" {f0}>JSON</option>
|
<option value="0" {f0}>JSON</option>
|
||||||
<option value="1" {f1}>Raw (minimal)</option>
|
<option value="1" {f1}>Raw values (minimal)</option>
|
||||||
<option value="2" {f2}>Raw (full)</option>
|
<option value="2" {f2}>Raw values (full)</option>
|
||||||
<option value="3" {f3}>Domoticz</option>
|
<option value="3" {f3}>Domoticz</option>
|
||||||
|
<option value="4" {f4}>Home-Assistant</option>
|
||||||
|
<option value="255" {f255}>Raw data (bytes)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||