|
@@ -8,14 +8,15 @@ was chosen due to it's small size and inexpensive cost. |
|
|
Design Decisions |
|
|
Design Decisions |
|
|
---------------- |
|
|
---------------- |
|
|
|
|
|
|
|
|
While investigating this, the LoraWAN protocol was investigated, but |
|
|
|
|
|
after looking at the code complexity and other operational requirements, |
|
|
|
|
|
if was decided that for this project, it was safer to target a direct |
|
|
|
|
|
Node to Node style communication system. This would allow the |
|
|
|
|
|
implementation to be more simple, and security to be built in (LoRaWAN |
|
|
|
|
|
does have a crypto layer, BUT, trusting/auditing it and any library that |
|
|
|
|
|
implements it would be a larger task than I want to undertake). It |
|
|
|
|
|
could also be used for other projects that need security. |
|
|
|
|
|
|
|
|
While investigating this project, the LoraWAN protocol was investigated, |
|
|
|
|
|
but after looking at the code complexity and other operational |
|
|
|
|
|
requirements, if was decided that for this project, it was safer to |
|
|
|
|
|
target a direct Node to Node style communication system. This would |
|
|
|
|
|
allow the implementation to be more simple, and security to be built in |
|
|
|
|
|
(LoRaWAN does have a crypto layer, BUT, trusting/auditing it and any |
|
|
|
|
|
library that implements it would be a larger task than I want to |
|
|
|
|
|
undertake). It could also be used for other projects that need |
|
|
|
|
|
security. |
|
|
|
|
|
|
|
|
One of the other requirements is that the code be 100% open sourced, |
|
|
One of the other requirements is that the code be 100% open sourced, |
|
|
not GPL licensed, and no proprietary components. This meant that using |
|
|
not GPL licensed, and no proprietary components. This meant that using |
|
@@ -42,8 +43,8 @@ flow is: |
|
|
|
|
|
|
|
|
The `lora.py` component is the front end/UI that is used to send commands |
|
|
The `lora.py` component is the front end/UI that is used to send commands |
|
|
to controller. This program establishes a secure communications channel |
|
|
to controller. This program establishes a secure communications channel |
|
|
to the controller. It's firmware is in `lora.irr.elf`, and the main |
|
|
|
|
|
source file is `irr_main.c`. |
|
|
|
|
|
|
|
|
to the controller. The controller's firmware is in `lora.irr.elf`, and |
|
|
|
|
|
the main source file is `irr_main.c`. |
|
|
|
|
|
|
|
|
The middle to components, `loraserv.py` and `lora.gw.elf` are used to |
|
|
The middle to components, `loraserv.py` and `lora.gw.elf` are used to |
|
|
pass messages between the former two. The `loraserv.py` program takes |
|
|
pass messages between the former two. The `loraserv.py` program takes |
|
@@ -52,14 +53,14 @@ are with out any framing, prepends `pkt:`, hex encodes the data and |
|
|
terminated w/ the new line character, and sends them via the USB VCP |
|
|
terminated w/ the new line character, and sends them via the USB VCP |
|
|
provided by `lora.gw.elf`. The gateway firmware then decodes the |
|
|
provided by `lora.gw.elf`. The gateway firmware then decodes the |
|
|
packet and transmits it via the LoRa radio to the irrigation |
|
|
packet and transmits it via the LoRa radio to the irrigation |
|
|
controller. The received packet is returned similarly, but this time |
|
|
|
|
|
|
|
|
controller. Any received packet is returned similarly, but this time |
|
|
with `data:` prepended, for `loraserv.py` to multicast back to |
|
|
with `data:` prepended, for `loraserv.py` to multicast back to |
|
|
`lora.py`. |
|
|
`lora.py`. |
|
|
|
|
|
|
|
|
The reason no particular framing is required for addressing or |
|
|
The reason no particular framing is required for addressing or |
|
|
destination is that the protocol is secure, and only the party that |
|
|
destination is that the protocol is secure, and only the party that |
|
|
is able to encrypt or decrypt the proper packets will be accepted, |
|
|
|
|
|
and any invalid packets will be ignored. |
|
|
|
|
|
|
|
|
is able to decrypt the proper packets will be accepted, and any invalid |
|
|
|
|
|
packets will be ignored. |
|
|
|
|
|
|
|
|
Building |
|
|
Building |
|
|
-------- |
|
|
-------- |
|
@@ -160,7 +161,7 @@ Here is a diagram of the connections: |
|
|
The noral supply used for irrigation values is 24V AC. This means |
|
|
The noral supply used for irrigation values is 24V AC. This means |
|
|
an additional power supply is needed to convert to the 5V supply that |
|
|
an additional power supply is needed to convert to the 5V supply that |
|
|
is used by the Node151. Make sure this is well filtered as both the |
|
|
is used by the Node151. Make sure this is well filtered as both the |
|
|
relays on the board (talked about below), and the irrigation values |
|
|
|
|
|
|
|
|
relays on the board (talked about below), and the irrigation valves |
|
|
will cause significant noise. The first PS I made was a simple DC-DC |
|
|
will cause significant noise. The first PS I made was a simple DC-DC |
|
|
buck converter + a full wave rectifier which, while alone was enough |
|
|
buck converter + a full wave rectifier which, while alone was enough |
|
|
to power the uC, was not enough when the relays were actuated, and even |
|
|
to power the uC, was not enough when the relays were actuated, and even |
|
@@ -170,25 +171,25 @@ irrigation valves actuated. |
|
|
|
|
|
|
|
|
In order to control the values, a relay board, similar to [this |
|
|
In order to control the values, a relay board, similar to [this |
|
|
one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), |
|
|
one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), |
|
|
can be used. The nice thing about this board is that the GPIO pins |
|
|
|
|
|
on the Node151 are 3.3V, while the relays need 5V to work. The jumper |
|
|
|
|
|
on the right side, VCC-JD-VCC, can be removed to allow this. The GND |
|
|
|
|
|
on the input/VCC pinout is used for the relay power via JD-VCC, and |
|
|
|
|
|
NOT for the VCC->INx pins, despite them being next to each other. The |
|
|
|
|
|
GND and JD-VCC should be connected to the 5V power supply, while VCC |
|
|
|
|
|
is connected to VDD on the Node151, and INx pins to the respective |
|
|
|
|
|
|
|
|
can be used. Despite the GPIO on the Node151 being 3.3V, and the |
|
|
|
|
|
relays requiring 5V, the jumper on the right side, VCC-JD-VCC, can be |
|
|
|
|
|
removed to allow dual voltage operation. The GND on the input/VCC |
|
|
|
|
|
pinout actually belongs to the relay power via JD-VCC, and NOT for the |
|
|
|
|
|
VCC->INx pins, despite them being next to each other. The GND and |
|
|
|
|
|
JD-VCC should be connected to the 5V power supply, while VCC is |
|
|
|
|
|
connected to VDD on the Node151, and INx pins to the respective |
|
|
GPIO pins. |
|
|
GPIO pins. |
|
|
|
|
|
|
|
|
Using |
|
|
Using |
|
|
----- |
|
|
----- |
|
|
|
|
|
|
|
|
The `lora.py` requires at least Python 3.8. It also using the |
|
|
|
|
|
strobe library that in distributed with this program. In general a |
|
|
|
|
|
|
|
|
The `lora.py` script requires at least Python 3.8. It also uses the |
|
|
|
|
|
strobe library that in distributed in this repo. In general a |
|
|
[virtualenv](https://virtualenv.pypa.io/en/latest/) is recommended for |
|
|
[virtualenv](https://virtualenv.pypa.io/en/latest/) is recommended for |
|
|
all installed Python software to prevent version conflicts, but is not |
|
|
all installed Python software to prevent version conflicts, but is not |
|
|
always necessary. The `requirements.txt` file contains the necessary |
|
|
always necessary. The `requirements.txt` file contains the necessary |
|
|
modules to be installed, but simply addeding the directory |
|
|
modules to be installed, but simply addeding the directory |
|
|
`strobe/python` to PYTHONPATH is also sufficient. |
|
|
|
|
|
|
|
|
`strobe/python` to PYTHONPATH should be sufficient. |
|
|
|
|
|
|
|
|
The program `loraserv.py` takes a single argument, which is the device |
|
|
The program `loraserv.py` takes a single argument, which is the device |
|
|
file for the VCP that runs on the gateway. In my case, the device |
|
|
file for the VCP that runs on the gateway. In my case, the device |
|
@@ -215,4 +216,57 @@ python lora.py -s <sharedkey> setunset 4 0 |
|
|
|
|
|
|
|
|
Either of these commands should exit w/o message or error. |
|
|
Either of these commands should exit w/o message or error. |
|
|
|
|
|
|
|
|
|
|
|
Multiple commands may be specified by separating them w/ `--` (two |
|
|
|
|
|
hyphens). For example: |
|
|
|
|
|
``` |
|
|
|
|
|
python lora.py -s <sharedkey> -- setunset 4 0 -- setunset 1 1 |
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
The first `--` is required to denote the end of option pasing, |
|
|
|
|
|
otherwise the second `--` will be used, and the first `setunset` |
|
|
|
|
|
command will be tried to be parsed as an argument. |
|
|
|
|
|
|
|
|
|
|
|
If you have regular set of commands to run, they can be stored in a |
|
|
|
|
|
file. Each line will be a single command, so you can have a file |
|
|
|
|
|
similar to: |
|
|
|
|
|
``` |
|
|
|
|
|
waitfor 5000 |
|
|
|
|
|
setunset 0 0 |
|
|
|
|
|
setunset 1 0 |
|
|
|
|
|
setunset 2 0 |
|
|
|
|
|
setunset 3 0 |
|
|
|
|
|
runfor 60000 0 |
|
|
|
|
|
waitfor 2000 |
|
|
|
|
|
runfor 60000 1 |
|
|
|
|
|
waitfor 2000 |
|
|
|
|
|
runfor 60000 2 |
|
|
|
|
|
waitfor 2000 |
|
|
|
|
|
runfor 60000 3 |
|
|
|
|
|
``` |
|
|
|
|
|
|
|
|
|
|
|
which will make sure all the valves are turned off, then run each one |
|
|
|
|
|
in succession for 60 seconds, with a 2 second wait between. |
|
|
|
|
|
|
|
|
|
|
|
There are two types of commands, ones that execute immediately, and ones |
|
|
|
|
|
that are queued up for future exectuion. The immediate commands are: |
|
|
|
|
|
* `adv`: Sets the current executing command to 0. An optional argument |
|
|
|
|
|
specifies how many commands to advance by. Note that only the time |
|
|
|
|
|
they are run is set to zero, so channels will be very briefly |
|
|
|
|
|
activated. See the clear command to avoid this. |
|
|
|
|
|
* `clear`: No arguemnt, removes any future commands. Current command |
|
|
|
|
|
remains executing. To clear all commands and stop all operations, |
|
|
|
|
|
first do a `clear`, followed by an `adv`. |
|
|
|
|
|
* `ping`: No arguemnt, used to verify communication works. |
|
|
|
|
|
* `setunset`: First argument is channel, second argument is 0 or 1, |
|
|
|
|
|
specifying to turn the channel off (0) or on (1). |
|
|
|
|
|
|
|
|
|
|
|
The following commands are queued. The first argument is the number |
|
|
|
|
|
of miliseconds to run the command for before advancing to the next |
|
|
|
|
|
command. The available commands are: |
|
|
|
|
|
* `runfor`: And additional arugment specifies the channel. The |
|
|
|
|
|
channel will be set to on, and then when the command completes, The |
|
|
|
|
|
chanell will be set to off. |
|
|
|
|
|
* `waitfor`: Wait for the specified time before advancing to the next |
|
|
|
|
|
enqueued command. |
|
|
|
|
|
|
|
|
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |
|
|
<!-- Markdeep: --><style class="fallback">body{visibility:hidden;white-space:pre;font-family:monospace}</style><script src="markdeep.min.js" charset="utf-8"></script><script src="https://casual-effects.com/markdeep/latest/markdeep.min.js" charset="utf-8"></script><script>window.alreadyProcessedMarkdeep||(document.body.style.visibility="visible")</script> |