frugal-iot-server 0.3.8 → 0.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALLATION.md +142 -43
- package/config.d/email.yaml +23 -0
- package/config.d/schema/devices.yaml +0 -2
- package/config.d/schema/modules.yaml +329 -2
- package/config.d/schema/topics.yaml +117 -46
- package/frugal-iot-server.js +142 -10
- package/lib/mailer.js +43 -0
- package/lib/resetcode.js +103 -0
- package/package.json +7 -4
- package/public/index.html +8 -0
- package/public/service-worker.js +26 -27
- package/scripts/addbridge-pi.zsh +36 -6
- package/scripts/addbridge-prod.zsh +9 -3
- package/scripts/clearretained.js +185 -0
- package/scripts/init.zsh +1 -1
- package/scripts/clearretained.zsh +0 -153
package/INSTALLATION.md
CHANGED
|
@@ -40,42 +40,6 @@ Any of these work. What differs is only how long the install takes, and how much
|
|
|
40
40
|
A Zero W runs the server perfectly well once installed. It is *installing* that is slow, because a
|
|
41
41
|
single 1 GHz core has to unpack several hundred packages and compile one of them.
|
|
42
42
|
|
|
43
|
-
## The short way: one script
|
|
44
|
-
|
|
45
|
-
Steps 3 to 8 below can be done for you. Once you can ssh into the Pi (steps 1 and 2, which need a
|
|
46
|
-
person with an SD card):
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
curl -fsSLO https://raw.githubusercontent.com/mitra42/frugal-iot-server/main/scripts/install-pi.sh
|
|
50
|
-
bash install-pi.sh --org myfarm --name "My Farm" --email you@example.com --phone +61123456789
|
|
51
|
-
```
|
|
52
|
-
|
|
53
|
-
It asks for anything it needs that you did not pass, says what it is doing as it goes, and stops at
|
|
54
|
-
the first thing that fails - leaving a log, and telling you to run `frugal-iot-diagnostic`. Running
|
|
55
|
-
it again after a failure carries on rather than starting over, which matters on a Pi Zero W where one
|
|
56
|
-
step takes about 40 minutes. `--dry-run` checks the arguments and shows the plan without touching the
|
|
57
|
-
machine.
|
|
58
|
-
|
|
59
|
-
**Passwords** are asked for, not invented, unless you say otherwise: it prompts for each (twice, not
|
|
60
|
-
echoed) and generates one if you just press Enter. Pass them as `--superuser-password`,
|
|
61
|
-
`--login-password` and `--broker-password` to skip the prompts, `--random-passwords` to have all
|
|
62
|
-
three generated, or `--yes` to ask nothing at all — which is what to use over ssh with no terminal.
|
|
63
|
-
A password you chose is not written to the log; a generated one has to be, since otherwise you would
|
|
64
|
-
have no way of knowing it.
|
|
65
|
-
|
|
66
|
-
**It tells you whether a reboot is needed**, rather than leaving you to wonder — it notices a kernel
|
|
67
|
-
or boot-firmware package in the upgrade, the images in `/boot` changing underneath it, and
|
|
68
|
-
`/var/run/reboot-required`. If none of those happened it says so, and there is nothing more to do.
|
|
69
|
-
|
|
70
|
-
Fetch it with `curl -O` and then run it, rather than piping curl into bash - piped, it has no
|
|
71
|
-
terminal to ask questions at.
|
|
72
|
-
|
|
73
|
-
It finishes with a live server and a tested broker. It cannot do step 9, pointing your nodes at it,
|
|
74
|
-
because a node learns its broker by being flashed with it - so it prints the settings to give them.
|
|
75
|
-
Nor step 10, HTTPS.
|
|
76
|
-
|
|
77
|
-
The steps below are what it does, in the same order, if you would rather do it by hand or need to
|
|
78
|
-
understand what went wrong.
|
|
79
43
|
|
|
80
44
|
---
|
|
81
45
|
### 0. What you need before you start
|
|
@@ -163,6 +127,7 @@ From your laptop's terminal:
|
|
|
163
127
|
```
|
|
164
128
|
ssh pi@frugaliot.local
|
|
165
129
|
```
|
|
130
|
+
> **Pi Zero W:** This can take a long time to connect, try `ping frugaliot.local` first to check it is alive
|
|
166
131
|
|
|
167
132
|
Say `yes` to the fingerprint question, then give the password you set in Imager.
|
|
168
133
|
|
|
@@ -213,6 +178,44 @@ the password — either way `nmtui` is the fix, and it is not worth more time th
|
|
|
213
178
|
(`sudo nmcli device wifi list` shows each nearby network's SSID and whether it is WPA2 or WPA3;
|
|
214
179
|
WPA3 cannot use a derived key at all.)
|
|
215
180
|
|
|
181
|
+
## 3-8. The short way: one script
|
|
182
|
+
|
|
183
|
+
Steps 3 to 8 below can be done for you. Once you can ssh into the Pi (steps 1 and 2, which need a
|
|
184
|
+
person with an SD card):
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
curl -fSLO https://raw.githubusercontent.com/mitra42/frugal-iot-server/main/scripts/install-pi.sh
|
|
188
|
+
bash install-pi.sh --org myfarm --name "My Farm" --email you@example.com --phone +61123456789
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
It asks for anything it needs that you did not pass, says what it is doing as it goes, and stops at
|
|
192
|
+
the first thing that fails - leaving a log, and telling you to run `frugal-iot-diagnostic`. Running
|
|
193
|
+
it again after a failure carries on rather than starting over, which matters on a Pi Zero W where one
|
|
194
|
+
step takes about 40 minutes. `--dry-run` checks the arguments and shows the plan without touching the
|
|
195
|
+
machine.
|
|
196
|
+
|
|
197
|
+
**Passwords** are asked for, not invented, unless you say otherwise: it prompts for each (twice, not
|
|
198
|
+
echoed) and generates one if you just press Enter. Pass them as `--superuser-password`,
|
|
199
|
+
`--login-password` and `--broker-password` to skip the prompts, `--random-passwords` to have all
|
|
200
|
+
three generated, or `--yes` to ask nothing at all — which is what to use over ssh with no terminal.
|
|
201
|
+
A password you chose is not written to the log; a generated one has to be, since otherwise you would
|
|
202
|
+
have no way of knowing it.
|
|
203
|
+
|
|
204
|
+
**It tells you whether a reboot is needed**, rather than leaving you to wonder — it notices a kernel
|
|
205
|
+
or boot-firmware package in the upgrade, the images in `/boot` changing underneath it, and
|
|
206
|
+
`/var/run/reboot-required`. If none of those happened it says so, and there is nothing more to do.
|
|
207
|
+
|
|
208
|
+
Fetch it with `curl -O` and then run it, rather than piping curl into bash - piped, it has no
|
|
209
|
+
terminal to ask questions at.
|
|
210
|
+
|
|
211
|
+
It finishes with a live server and a tested broker. It cannot do step 9, pointing your nodes at it,
|
|
212
|
+
because a node learns its broker by being flashed with it - so it prints the settings to give them.
|
|
213
|
+
Nor step 10, HTTPS.
|
|
214
|
+
|
|
215
|
+
The steps below are what it does, in the same order, if you would rather do it by hand or need to
|
|
216
|
+
understand what went wrong, otherwise skip to Step 9.
|
|
217
|
+
|
|
218
|
+
|
|
216
219
|
### 3. Update the operating system and install the prerequisites
|
|
217
220
|
|
|
218
221
|
Logged in, bring the system up to date and reboot:
|
|
@@ -692,6 +695,101 @@ mosquitto_sub -h localhost -u myfarm -P '<broker-password>' -t '#' -v
|
|
|
692
695
|
Every reading from every node should scroll past. Seeing anything here also proves the broker's
|
|
693
696
|
port 1883 is reachable from off the Pi, which is what the nodes need.
|
|
694
697
|
|
|
698
|
+
### 9a. Optional: outgoing mail, so people can reset a forgotten password
|
|
699
|
+
|
|
700
|
+
Without this, a forgotten password can only be fixed by you, on the Pi, with
|
|
701
|
+
`npx --no frugal-iot-setpassword <username> <new-password>`. The login page's "Forgot password?"
|
|
702
|
+
link says "Password reset is not available on this server" rather than pretending to send anything.
|
|
703
|
+
|
|
704
|
+
An offline Pi cannot send mail at all, so skip this unless it has internet access.
|
|
705
|
+
|
|
706
|
+
Mail sent straight from a home broadband connection is almost always treated as spam, so this
|
|
707
|
+
relays through somebody else's SMTP server rather than sending directly. Gmail is the usual choice
|
|
708
|
+
and is written out in full below; any other provider works the same way.
|
|
709
|
+
|
|
710
|
+
#### With Gmail
|
|
711
|
+
|
|
712
|
+
Use a Google account you are willing to have the Pi send as. A separate account for the purpose is
|
|
713
|
+
better than your own mailbox — the password ends up in a file on an SD card in a shed.
|
|
714
|
+
|
|
715
|
+
**1. Turn on 2-Step Verification** on that account, at
|
|
716
|
+
<https://myaccount.google.com/signinoptions/twosv>.
|
|
717
|
+
|
|
718
|
+
This is not optional and it is where most people get stuck: **app passwords do not exist until
|
|
719
|
+
2-Step Verification is on**. Until then the page in step 2 simply says the setting is not available,
|
|
720
|
+
without explaining why.
|
|
721
|
+
|
|
722
|
+
**2. Create an app password** at <https://myaccount.google.com/apppasswords>.
|
|
723
|
+
|
|
724
|
+
Type a name for it — anything you will recognise later, such as `Frugal IoT Pi` — and create it.
|
|
725
|
+
Google shows you **16 lowercase letters, in four groups of four**, once. Copy them now; you cannot
|
|
726
|
+
come back and read it again, only delete it and make another.
|
|
727
|
+
|
|
728
|
+
The groups are only there to make it readable. **Type it into the config with the spaces removed**,
|
|
729
|
+
as one 16-character word.
|
|
730
|
+
|
|
731
|
+
**3. Fill in `config.d/email.yaml`:**
|
|
732
|
+
|
|
733
|
+
```yaml
|
|
734
|
+
host: smtp.gmail.com
|
|
735
|
+
port: 587
|
|
736
|
+
user: yourname@gmail.com
|
|
737
|
+
pass: "abcdefghijklmnop" # the 16 characters from step 2, spaces removed
|
|
738
|
+
from: Frugal IoT <yourname@gmail.com>
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
Things that catch people out with Gmail specifically:
|
|
742
|
+
|
|
743
|
+
* **`from:` must be the same address as `user:`.** Gmail rewrites the sender to the account you
|
|
744
|
+
authenticated as, so a different address here does not fail — it quietly arrives as something
|
|
745
|
+
else, which is harder to diagnose than an error. (An address you have set up under Gmail's
|
|
746
|
+
"Send mail as" is the one exception.)
|
|
747
|
+
* **`user:` is the full address**, including `@gmail.com`, not just the part before it.
|
|
748
|
+
* **`Username and Password not accepted`** in the server's log means the login password was used
|
|
749
|
+
instead of an app password. Gmail has not accepted account passwords over SMTP for years.
|
|
750
|
+
* **Port 465 also works** if 587 is blocked where the Pi is; the software works out the encryption
|
|
751
|
+
from the port number, so change nothing else.
|
|
752
|
+
* **A free Gmail account can send around 500 messages a day.** Password resets will not come close.
|
|
753
|
+
* **Google Workspace administrators can switch app passwords off** for a whole domain. If step 2
|
|
754
|
+
offers you nothing on a work account, that is why, and you will need a real SMTP relay instead.
|
|
755
|
+
|
|
756
|
+
#### With any other provider
|
|
757
|
+
|
|
758
|
+
The same four settings, with that provider's SMTP host:
|
|
759
|
+
|
|
760
|
+
```yaml
|
|
761
|
+
host: smtp.example.org
|
|
762
|
+
port: 587 # 465 is implicit TLS, 587 and 25 are STARTTLS
|
|
763
|
+
user: frugaliot@example.org
|
|
764
|
+
pass: an-app-password-not-your-login-password
|
|
765
|
+
from: Frugal IoT <frugaliot@example.org>
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
Fastmail, Zoho, Proton (via its bridge) and the rest all issue app passwords in much the same way,
|
|
769
|
+
and for the same reason: one leaking off a Pi then costs you one mailbox rather than the account.
|
|
770
|
+
|
|
771
|
+
#### Checking it, either way
|
|
772
|
+
|
|
773
|
+
Restart the server and look at its output:
|
|
774
|
+
|
|
775
|
+
* `Sending mail via smtp.gmail.com:587 as ...` — configured.
|
|
776
|
+
* `Not sending mail (no host/from in config.d/email.yaml) ...` — it did not find a `host` and a
|
|
777
|
+
`from`, so the reset link will say it is unavailable.
|
|
778
|
+
|
|
779
|
+
Then use "Forgot password?" on the login page with your own account. If the mail never arrives, the
|
|
780
|
+
reason is in the server's log — the page deliberately gives the same answer whether or not the
|
|
781
|
+
address is known to it, so it cannot be used to find out who has an account here.
|
|
782
|
+
|
|
783
|
+
Two more things worth knowing:
|
|
784
|
+
|
|
785
|
+
* `pass` sits in a file on the SD card in plain text. Give that mailbox nothing else to lose.
|
|
786
|
+
* If the Pi is behind a proxy that does not set `X-Forwarded-Host`, the link in the mail will point
|
|
787
|
+
at the wrong address. Set `baseurl: https://your.address` in the same file.
|
|
788
|
+
|
|
789
|
+
The reset code itself is stored nowhere — it is a hash of the account, its current password and the
|
|
790
|
+
time, valid between five and ten minutes and dead the moment it is used. There is no table to
|
|
791
|
+
maintain and nothing to clean up. Restarting the server invalidates any code already sent.
|
|
792
|
+
|
|
695
793
|
### 10. HTTPS and over-the-air firmware updates
|
|
696
794
|
|
|
697
795
|
**To be written.** Everything above gives you a plain HTTP server on your local network, which is
|
|
@@ -726,9 +824,6 @@ It comes in three parts, and only the first is a one-off:
|
|
|
726
824
|
* **11b — authorizing this Pi on that server.** One command, run there, once per Pi.
|
|
727
825
|
* **11c — pointing this Pi at it.** One command, run here, once per Pi.
|
|
728
826
|
|
|
729
|
-
If someone has already done 11a for the server you are bridging to — the usual case once the first
|
|
730
|
-
Pi is working — **start at 11b**.
|
|
731
|
-
|
|
732
827
|
**What you get, and what you do not.** While the link is up, readings appear on production within
|
|
733
828
|
a second or so. While it is down, the Pi records everything as usual and production simply has a
|
|
734
829
|
gap — the readings taken during an outage never reach it. That is a deliberate choice: the
|
|
@@ -740,8 +835,8 @@ takes effect when it reconnects.
|
|
|
740
835
|
|
|
741
836
|
#### 11a. Preparing a production server to accept bridges
|
|
742
837
|
|
|
743
|
-
Once per production server, not per Pi — and
|
|
744
|
-
|
|
838
|
+
Once per production server, not per Pi — and if bridging to `frugaliot.naturalinnovation.org`
|
|
839
|
+
this has already been done. If so, skip to 11b.
|
|
745
840
|
|
|
746
841
|
**Add a listener for bridges.** A Mosquitto bridge speaks MQTT or MQTT-over-TLS and cannot use
|
|
747
842
|
WebSockets, so the existing `wss://` path that browsers and servers use cannot carry this. It needs
|
|
@@ -894,7 +989,7 @@ Once per Pi. Run the command 11b printed, from this installation's directory:
|
|
|
894
989
|
|
|
895
990
|
```
|
|
896
991
|
cd ~/frugal-iot
|
|
897
|
-
npx --no frugal-iot-addbridge-pi
|
|
992
|
+
npx --no frugal-iot-addbridge-pi <org-id> <prod-host> bridge-<site-name>
|
|
898
993
|
```
|
|
899
994
|
|
|
900
995
|
It asks for the password rather than taking it on the command line, so it stays out of your shell
|
|
@@ -1060,7 +1155,11 @@ npx --no frugal-iot-clearretained 'myfarm/lotus/+/sht/temperture/#'
|
|
|
1060
1155
|
```
|
|
1061
1156
|
|
|
1062
1157
|
Quote the pattern or the shell will expand it. That lists what is retained and changes nothing;
|
|
1063
|
-
add
|
|
1158
|
+
add the word `delete` at the end of the same command to remove it.
|
|
1159
|
+
|
|
1160
|
+
> `delete` is a bare word rather than a `--delete` flag on purpose. npm parses the command line of
|
|
1161
|
+
> an `npx` invocation itself and swallows any `--flag` it does not recognise, so `--delete` would
|
|
1162
|
+
> never reach the script and it would quietly list instead of deleting.
|
|
1064
1163
|
|
|
1065
1164
|
> Look before deleting. A node's `min`, `max`, `color` and `wired` settings are retained messages
|
|
1066
1165
|
> too, and they are how the dashboard knows how to draw it — delete those and the node has to be
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Outgoing mail. Only used by the password reset, which is unavailable until this is filled in -
|
|
2
|
+
# the login page says so rather than pretending to have sent something.
|
|
3
|
+
#
|
|
4
|
+
# Leave it commented out on a server that should not send mail.
|
|
5
|
+
#
|
|
6
|
+
# For Gmail - the common case, written out step by step in INSTALLATION.md section 9a:
|
|
7
|
+
# 1. Turn on 2-Step Verification: https://myaccount.google.com/signinoptions/twosv
|
|
8
|
+
# App passwords do not exist until you do, which is where most people get stuck.
|
|
9
|
+
# 2. Create an app password: https://myaccount.google.com/apppasswords
|
|
10
|
+
# You get 16 lowercase letters in four groups of four, shown once. Remove the spaces.
|
|
11
|
+
# 3. "from" must be the same address as "user" - Gmail silently rewrites anything else.
|
|
12
|
+
#
|
|
13
|
+
# host: smtp.gmail.com
|
|
14
|
+
# port: 587 # 465 is implicit TLS, 587 and 25 are STARTTLS; secure: is derived from this
|
|
15
|
+
# user: yourname@gmail.com
|
|
16
|
+
# pass: "abcdefghijklmnop" # the app password, NOT your Google account password
|
|
17
|
+
# from: Frugal IoT <yourname@gmail.com>
|
|
18
|
+
#
|
|
19
|
+
# Any other provider is the same four settings with its own SMTP host.
|
|
20
|
+
#
|
|
21
|
+
# The reset email contains a link back to this server. Set baseurl if the server cannot work out
|
|
22
|
+
# its own public address from the request - behind a proxy that does not set X-Forwarded-Host, say.
|
|
23
|
+
# baseurl: https://frugaliot.example.org
|
|
@@ -20,11 +20,89 @@ aht21:
|
|
|
20
20
|
topics:
|
|
21
21
|
- leaf: temperature
|
|
22
22
|
- leaf: humidity
|
|
23
|
+
# The DS18B20 probes on an FF-OpenMPPT board - see frugal-iot-irrigation. Separate modules rather
|
|
24
|
+
# than one, because the three measure quite different things and want different ranges; the class
|
|
25
|
+
# is the same Sensor_DS18B20 as the `ds18b20` module below.
|
|
26
|
+
airtemp:
|
|
27
|
+
name: Air Temperature
|
|
28
|
+
topics:
|
|
29
|
+
- leaf: airtemp
|
|
30
|
+
leaf_from: temperature
|
|
31
|
+
name: Air Temperature
|
|
32
|
+
min: -20
|
|
33
|
+
max: 60
|
|
34
|
+
analog:
|
|
35
|
+
name: "Analog Out"
|
|
36
|
+
topics:
|
|
37
|
+
- leaf: volts
|
|
23
38
|
battery:
|
|
24
39
|
name: "Battery"
|
|
25
40
|
insidefrugaliot: true
|
|
26
41
|
topics:
|
|
27
42
|
- leaf: battery
|
|
43
|
+
# How much of its rated capacity the battery still has, inferred from an overnight discharge.
|
|
44
|
+
# A trend over weeks, not a reading; see control_health.h. Named batteryhealth because `health` is
|
|
45
|
+
# already taken by the device's own reporting.
|
|
46
|
+
batteryhealth:
|
|
47
|
+
name: Battery Health
|
|
48
|
+
topics:
|
|
49
|
+
- leaf: health
|
|
50
|
+
leaf_from: percent
|
|
51
|
+
name: Health
|
|
52
|
+
duplicates:
|
|
53
|
+
significantdate: 86400000
|
|
54
|
+
significantvalue: 1
|
|
55
|
+
- leaf: state
|
|
56
|
+
leaf_from: controltext
|
|
57
|
+
name: State
|
|
58
|
+
rw: r
|
|
59
|
+
- leaf: soc
|
|
60
|
+
leaf_from: controlfloat
|
|
61
|
+
name: Charge
|
|
62
|
+
min: 0
|
|
63
|
+
max: 100
|
|
64
|
+
- leaf: capacity
|
|
65
|
+
leaf_from: controlfloat
|
|
66
|
+
name: Capacity Ah
|
|
67
|
+
min: 0
|
|
68
|
+
max: 500
|
|
69
|
+
wireable: false
|
|
70
|
+
- leaf: load
|
|
71
|
+
leaf_from: controlfloat
|
|
72
|
+
name: Average load A
|
|
73
|
+
min: 0
|
|
74
|
+
max: 50
|
|
75
|
+
wireable: false
|
|
76
|
+
- leaf: active
|
|
77
|
+
leaf_from: controlint
|
|
78
|
+
name: Irrigation active
|
|
79
|
+
min: 0
|
|
80
|
+
max: 16
|
|
81
|
+
- leaf: panelwatts
|
|
82
|
+
leaf_from: controlfloat
|
|
83
|
+
name: Panel watts
|
|
84
|
+
min: 0
|
|
85
|
+
max: 2000
|
|
86
|
+
wireable: false
|
|
87
|
+
- leaf: storageratio
|
|
88
|
+
leaf_from: controlfloat
|
|
89
|
+
name: Storage ratio
|
|
90
|
+
min: 0
|
|
91
|
+
max: 50
|
|
92
|
+
rw: r
|
|
93
|
+
wireable: false
|
|
94
|
+
- leaf: advice
|
|
95
|
+
leaf_from: controltext
|
|
96
|
+
name: Advice
|
|
97
|
+
rw: r
|
|
98
|
+
batttemp:
|
|
99
|
+
name: Battery Temperature
|
|
100
|
+
topics:
|
|
101
|
+
- leaf: batttemp
|
|
102
|
+
leaf_from: temperature
|
|
103
|
+
name: Battery Temperature
|
|
104
|
+
min: -20
|
|
105
|
+
max: 60
|
|
28
106
|
bme280:
|
|
29
107
|
name: "BME280"
|
|
30
108
|
topics:
|
|
@@ -131,11 +209,11 @@ ens160:
|
|
|
131
209
|
leaf_from: controlfloat
|
|
132
210
|
name: Temperature
|
|
133
211
|
max: 50
|
|
134
|
-
color:
|
|
212
|
+
color: "#ff0000"
|
|
135
213
|
- leaf: humidity
|
|
136
214
|
leaf_from: controlfloat
|
|
137
215
|
name: Humidity
|
|
138
|
-
color:
|
|
216
|
+
color: "#0000ff"
|
|
139
217
|
- leaf: aqi
|
|
140
218
|
- leaf: tvoc
|
|
141
219
|
- leaf: eco2
|
|
@@ -177,6 +255,16 @@ health:
|
|
|
177
255
|
topics:
|
|
178
256
|
- leaf: wifibars
|
|
179
257
|
- leaf: wifissid
|
|
258
|
+
# The charge controller's own heatsink. Either a DS18B20 or a pair of diodes read on an ADC pin,
|
|
259
|
+
# depending on the board - the reading means the same either way.
|
|
260
|
+
heatsink:
|
|
261
|
+
name: Heatsink Temperature
|
|
262
|
+
topics:
|
|
263
|
+
- leaf: heatsink
|
|
264
|
+
leaf_from: temperature
|
|
265
|
+
name: Heatsink Temperature
|
|
266
|
+
min: 0
|
|
267
|
+
max: 120
|
|
180
268
|
ht:
|
|
181
269
|
name: HT
|
|
182
270
|
topics:
|
|
@@ -190,11 +278,64 @@ ina219:
|
|
|
190
278
|
- leaf: current
|
|
191
279
|
- leaf: power
|
|
192
280
|
- leaf: load
|
|
281
|
+
irrigation:
|
|
282
|
+
name: Irrigation
|
|
283
|
+
topics:
|
|
284
|
+
- leaf: hour
|
|
285
|
+
leaf_from: controlint
|
|
286
|
+
name: Start hour
|
|
287
|
+
min: 0
|
|
288
|
+
max: 23
|
|
289
|
+
- leaf: minute
|
|
290
|
+
leaf_from: controlint
|
|
291
|
+
name: Start minute
|
|
292
|
+
min: 0
|
|
293
|
+
max: 59
|
|
294
|
+
- leaf: maxminutes
|
|
295
|
+
leaf_from: controlfloat
|
|
296
|
+
name: Max minutes per sector
|
|
297
|
+
min: 0
|
|
298
|
+
max: 120
|
|
299
|
+
- leaf: enabled
|
|
300
|
+
leaf_from: controlintoggle
|
|
301
|
+
name: Enabled
|
|
302
|
+
- leaf: tank
|
|
303
|
+
leaf_from: controlfloat
|
|
304
|
+
name: Tank level
|
|
305
|
+
color: "#0000ff"
|
|
306
|
+
- leaf: tankstart
|
|
307
|
+
leaf_from: controlfloat
|
|
308
|
+
name: Tank level to start
|
|
309
|
+
- leaf: tankempty
|
|
310
|
+
leaf_from: controlfloat
|
|
311
|
+
name: Tank level to stop
|
|
312
|
+
- leaf: power
|
|
313
|
+
leaf_from: controlintoggle
|
|
314
|
+
name: Power ok
|
|
315
|
+
wireable: true
|
|
316
|
+
- leaf: solar
|
|
317
|
+
leaf_from: controlintoggle
|
|
318
|
+
name: Input power
|
|
319
|
+
wireable: true
|
|
320
|
+
- leaf: pump
|
|
321
|
+
leaf_from: controlouttoggle
|
|
322
|
+
name: Pump
|
|
323
|
+
- leaf: active
|
|
324
|
+
leaf_from: controlint
|
|
325
|
+
name: Active sector
|
|
326
|
+
min: 0
|
|
327
|
+
max: 16
|
|
193
328
|
lcd:
|
|
194
329
|
summary: false # a message is not a reading
|
|
195
330
|
name: LCD
|
|
196
331
|
topics:
|
|
197
332
|
- leaf: message
|
|
333
|
+
# The switched load output - OSPIT's pin 14 in its "load" role, opened by the low-voltage
|
|
334
|
+
# disconnect. An Actuator_Digital, so the same shape as `relay`.
|
|
335
|
+
load:
|
|
336
|
+
name: Load
|
|
337
|
+
topics:
|
|
338
|
+
- leaf: on
|
|
198
339
|
ledbuiltin:
|
|
199
340
|
name: LED
|
|
200
341
|
slot: ledbuiltin
|
|
@@ -211,6 +352,96 @@ lux:
|
|
|
211
352
|
name: Light meter
|
|
212
353
|
topics:
|
|
213
354
|
- leaf: lux
|
|
355
|
+
# Solar charge control - see frugal-iot-irrigation. `step` is the raw DAC value because that is
|
|
356
|
+
# unambiguous; `vmpp` is what the node PREDICTS that step asks the hardware for, which is a guess
|
|
357
|
+
# until it has been checked against a meter.
|
|
358
|
+
mppt:
|
|
359
|
+
name: Charge Control
|
|
360
|
+
topics:
|
|
361
|
+
- leaf: automatic
|
|
362
|
+
leaf_from: controlintoggle
|
|
363
|
+
name: Automatic
|
|
364
|
+
- leaf: state
|
|
365
|
+
leaf_from: controltext
|
|
366
|
+
name: State
|
|
367
|
+
rw: r
|
|
368
|
+
- leaf: profile
|
|
369
|
+
leaf_from: controlint
|
|
370
|
+
name: Battery type
|
|
371
|
+
min: 0
|
|
372
|
+
max: 3
|
|
373
|
+
wireable: false
|
|
374
|
+
- leaf: chargeend
|
|
375
|
+
leaf_from: controlfloat
|
|
376
|
+
name: Charge end
|
|
377
|
+
min: 10000
|
|
378
|
+
max: 16000
|
|
379
|
+
wireable: false
|
|
380
|
+
- leaf: tempcoeff
|
|
381
|
+
leaf_from: controlfloat
|
|
382
|
+
name: Temp coefficient
|
|
383
|
+
min: 0
|
|
384
|
+
max: 60
|
|
385
|
+
wireable: false
|
|
386
|
+
- leaf: hotcharge
|
|
387
|
+
leaf_from: controlfloat
|
|
388
|
+
name: Hot battery
|
|
389
|
+
min: 10000
|
|
390
|
+
max: 16000
|
|
391
|
+
wireable: false
|
|
392
|
+
- leaf: batttemp
|
|
393
|
+
leaf_from: controlfloat
|
|
394
|
+
name: Battery temp
|
|
395
|
+
min: -20
|
|
396
|
+
max: 60
|
|
397
|
+
- leaf: heatsink
|
|
398
|
+
leaf_from: controlfloat
|
|
399
|
+
name: Heatsink temp
|
|
400
|
+
min: 0
|
|
401
|
+
max: 120
|
|
402
|
+
- leaf: target
|
|
403
|
+
leaf_from: controlfloat
|
|
404
|
+
name: Target
|
|
405
|
+
min: 10000
|
|
406
|
+
max: 16000
|
|
407
|
+
rw: r
|
|
408
|
+
wireable: false
|
|
409
|
+
- leaf: step
|
|
410
|
+
leaf_from: controlint
|
|
411
|
+
name: DAC step
|
|
412
|
+
min: 0
|
|
413
|
+
max: 255
|
|
414
|
+
wireable: false
|
|
415
|
+
- leaf: panel
|
|
416
|
+
leaf_from: controlfloat
|
|
417
|
+
name: Panel
|
|
418
|
+
min: 0
|
|
419
|
+
max: 30000
|
|
420
|
+
- leaf: battery
|
|
421
|
+
leaf_from: controlfloat
|
|
422
|
+
name: Battery
|
|
423
|
+
min: 0
|
|
424
|
+
max: 16000
|
|
425
|
+
- leaf: voc
|
|
426
|
+
leaf_from: controlfloat
|
|
427
|
+
name: Open circuit
|
|
428
|
+
min: 0
|
|
429
|
+
max: 30000
|
|
430
|
+
rw: r
|
|
431
|
+
wireable: false
|
|
432
|
+
- leaf: vmpp
|
|
433
|
+
leaf_from: controlfloat
|
|
434
|
+
name: Panel target
|
|
435
|
+
min: 0
|
|
436
|
+
max: 30
|
|
437
|
+
rw: r
|
|
438
|
+
wireable: false
|
|
439
|
+
- leaf: dacvolts
|
|
440
|
+
leaf_from: controlfloat
|
|
441
|
+
name: DAC volts
|
|
442
|
+
min: 0
|
|
443
|
+
max: 3.3
|
|
444
|
+
rw: r
|
|
214
445
|
ms5803:
|
|
215
446
|
name: MS5803
|
|
216
447
|
topics:
|
|
@@ -221,6 +452,25 @@ ota:
|
|
|
221
452
|
insidefrugaliot: true
|
|
222
453
|
topics:
|
|
223
454
|
- leaf: key
|
|
455
|
+
panel:
|
|
456
|
+
name: Solar Panel
|
|
457
|
+
topics:
|
|
458
|
+
- leaf: panel
|
|
459
|
+
leaf_from: voltage
|
|
460
|
+
name: Panel Voltage
|
|
461
|
+
max: 30000
|
|
462
|
+
pcbtemp:
|
|
463
|
+
name: Board Temperature
|
|
464
|
+
topics:
|
|
465
|
+
- leaf: pcbtemp
|
|
466
|
+
leaf_from: temperature
|
|
467
|
+
name: Board Temperature
|
|
468
|
+
min: -20
|
|
469
|
+
max: 100
|
|
470
|
+
pump:
|
|
471
|
+
name: Pump
|
|
472
|
+
topics:
|
|
473
|
+
- leaf: on
|
|
224
474
|
rain:
|
|
225
475
|
name: Rain
|
|
226
476
|
topics:
|
|
@@ -230,16 +480,93 @@ relay:
|
|
|
230
480
|
name: Relay
|
|
231
481
|
topics:
|
|
232
482
|
- leaf: on
|
|
483
|
+
# One sector of an irrigation run - see modules "irrigation". A node with several sectors publishes
|
|
484
|
+
# sector1, sector2... and the client resolves those numbered instances back to this entry, so only
|
|
485
|
+
# the one definition is needed here however many sectors a node has.
|
|
486
|
+
sector:
|
|
487
|
+
name: Irrigation sector
|
|
488
|
+
topics:
|
|
489
|
+
- leaf: moisture
|
|
490
|
+
leaf_from: controlfloat
|
|
491
|
+
name: Moisture
|
|
492
|
+
color: "#a52a2a"
|
|
493
|
+
- leaf: target
|
|
494
|
+
leaf_from: controlfloat
|
|
495
|
+
name: Target
|
|
496
|
+
- leaf: enable
|
|
497
|
+
leaf_from: controlintoggle
|
|
498
|
+
name: Enable
|
|
499
|
+
- leaf: valve
|
|
500
|
+
leaf_from: controlouttoggle
|
|
501
|
+
name: Valve
|
|
233
502
|
sht:
|
|
234
503
|
name: SHT
|
|
235
504
|
topics:
|
|
236
505
|
- leaf: temperature
|
|
237
506
|
- leaf: humidity
|
|
507
|
+
# State of charge, estimated from battery voltage - reporting only, never controlled from. See
|
|
508
|
+
# control_soc.h in frugal-iot-irrigation for what the estimate is and is not worth.
|
|
509
|
+
soc:
|
|
510
|
+
name: State of Charge
|
|
511
|
+
topics:
|
|
512
|
+
- leaf: soc
|
|
513
|
+
leaf_from: percent
|
|
514
|
+
name: Charge
|
|
515
|
+
duplicates:
|
|
516
|
+
significantdate: 900000
|
|
517
|
+
significantvalue: 1
|
|
518
|
+
- leaf: charging
|
|
519
|
+
leaf_from: controlouttoggle
|
|
520
|
+
name: Charging
|
|
521
|
+
- leaf: battery
|
|
522
|
+
leaf_from: controlfloat
|
|
523
|
+
name: Battery
|
|
524
|
+
min: 0
|
|
525
|
+
max: 16000
|
|
526
|
+
- leaf: panel
|
|
527
|
+
leaf_from: controlfloat
|
|
528
|
+
name: Panel
|
|
529
|
+
min: 0
|
|
530
|
+
max: 30000
|
|
531
|
+
- leaf: profile
|
|
532
|
+
leaf_from: controlint
|
|
533
|
+
name: Battery type
|
|
534
|
+
min: 0
|
|
535
|
+
max: 3
|
|
536
|
+
wireable: false
|
|
238
537
|
soil:
|
|
239
538
|
name: Soil
|
|
240
539
|
topics:
|
|
241
540
|
- leaf: soil
|
|
541
|
+
tank:
|
|
542
|
+
name: Water Tank
|
|
543
|
+
topics:
|
|
544
|
+
- leaf: tank
|
|
545
|
+
soilmodbus:
|
|
546
|
+
name: "Soil Probe"
|
|
547
|
+
topics:
|
|
548
|
+
# Reuses the shared humidity and temperature definitions - same ranges, logging and
|
|
549
|
+
# duplicate rules - overriding only what soil makes different from air.
|
|
550
|
+
- leaf: humidity
|
|
551
|
+
name: "Soil Moisture"
|
|
552
|
+
color: brown
|
|
553
|
+
units: "%" # Volumetric water content, not the relative humidity the shared leaf means
|
|
554
|
+
- leaf: temperature
|
|
555
|
+
name: "Soil Temperature"
|
|
556
|
+
color: brown
|
|
242
557
|
ultrasonic:
|
|
243
558
|
name: "Ultrasonic Distance"
|
|
244
559
|
topics:
|
|
245
560
|
- leaf: ultrasonic
|
|
561
|
+
# The irrigation valves - Actuator_Digital instances, so the same shape as `relay`. A node with
|
|
562
|
+
# several publishes valve1, valve2... which the client resolves back to this entry.
|
|
563
|
+
# A switched USB supply - an Actuator_Digital, so the same shape as `relay`. On the FF board this
|
|
564
|
+
# shares a pin with the third irrigation valve; a node has one or the other.
|
|
565
|
+
usb:
|
|
566
|
+
name: USB Supply
|
|
567
|
+
topics:
|
|
568
|
+
- leaf: on
|
|
569
|
+
valve:
|
|
570
|
+
name: Valve
|
|
571
|
+
topics:
|
|
572
|
+
- leaf: on
|