From c5bb2d4d689150413615946998d8af6b38c79f3e Mon Sep 17 00:00:00 2001 From: John-Mark Gurney Date: Wed, 2 Feb 2022 18:04:48 -0800 Subject: [PATCH] break up the README to an overview and the parts.. --- LORA-IRR.md | 293 +++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 296 ++-------------------------------------------------- RS485HID.md | 54 ++++++++++ 3 files changed, 358 insertions(+), 285 deletions(-) create mode 100644 LORA-IRR.md create mode 100644 RS485HID.md diff --git a/LORA-IRR.md b/LORA-IRR.md new file mode 100644 index 0000000..c49153b --- /dev/null +++ b/LORA-IRR.md @@ -0,0 +1,293 @@ +LoRa Irrigation System +====================== + +This project is to build an irrigation system from LoRa capable +microcontrollers. The [Heltec Node151](https://heltec.org/project/lora-node-151/) +was chosen due to it's small size and inexpensive cost. + +Design Decisions +---------------- + +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, +not GPL licensed, and no proprietary components. This meant that using +IDE's like ST's STM32CubeIDE which is only available in binary form +was not a choice, as that would preclude building on an operating +system other than Windows/MacOSX/Linux. + +Architecture +------------ + +There are a number of components to make this system work. The overall +flow is: + +``` +************************************************************************************************ +* * +* +---------+ +-------------+ +-------------+ +--------------+ * +* | lora.py | multicast | loraserv.py | USB VCP | lora.gw.elf | LoRa | lora.irr.elf | * +* | +--------------+ +------------+ main.c +---------+ irr_main.c | * +* +---------+ +-------------+ +-------------+ +--------------+ * +* * +************************************************************************************************ +``` + +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 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 +pass messages between the former two. The `loraserv.py` program takes +multicast datagrams that are received on 239.192.76.111:21089, which +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 +provided by `lora.gw.elf`. The gateway firmware then decodes the +packet and transmits it via the LoRa radio to the irrigation +controller. Any received packet is returned similarly, but this time +with `data:` prepended, for `loraserv.py` to multicast back to +`lora.py`. + +The reason no particular framing is required for addressing or +destination is that the protocol is secure, and only the party that +is able to decrypt the proper packets will be accepted, and any invalid +packets will be ignored. + +Building +-------- + +The build system uses the BSD flavor of make. This is the default +make on the BSDs, originally called pmake, but also available as bsdmake +for MacOSX, and available as [bmake](https://crufty.net/help/sjg/bmake.html). + +It also depends upon ARM's [GNU Arm Embedded +Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm), +which uses gcc as the compiler. It would be good to get it +cross-compile with clang as well, but that requires finding a libc like +the nano libc that is provided by the toolchain. + +One of the required parameters of the build is the shared key used for +authentication. A random key can be made using the command: +`make irrigation_key`, or it can be provided via the make command by +setting the variable IRR_KEY. + +Note: Both IRR_KEY and the argument to `lora.py` will encode the +provided key to UTF-8. + +Once ARM's toolchain is in your path, the following should work: +``` +export MAKEOBJDIR=build +mkdir $MAKEOBJDIR +bsdmake all IRR_KEY= +``` + +And in the directory `build`, two files, `lora.irr.elf` and +`lora.gw.elf` should be present. The file `lora.irr.elf` should be +flashed on the Node151 device that is used for interfacing to the +irrigation system as described in [Deploying](#deploying). The file +`lora.gw.elf` should be used on another Node151 that will be attached +to a computer used as the gateway which runs the `loraserv.py` software +as described in [Using](#using). + +Flashing +-------- + +Flashing can be done via the open source tool +[OpenOCD](https://sourceforge.net/projects/openocd/). For this, I use +a Digilent HS1 JTAG programmer utilizing the [resistor +hack](https://github.com/ntfreak/openocd/blob/master/tcl/interface/ftdi/swd-resistor-hack.cfg) +to allow an FTDI JTAG programmer to control the bi-directional `SWIO` +pin. + +One caveat w/ MacOSX, is that it may be necessary to unload the kext +`com.apple.driver.AppleUSBFTDI` via the command: +``` +sudo kextunload -b com.apple.driver.AppleUSBFTDI +``` +as OpenOCD wants direct access to the FTDI driver. + +Once that happens, the device can be programmed using the following +command: +``` +sudo openocd -f interface/ftdi/digilent-hs1.cfg -f interface/ftdi/swd-resistor-hack.cfg -f target/stm32l1.cfg -c "init" -c "reset init" -c "program build/lora.irr.elf verify reset exit" +``` + +Pins +---- + +The [pinout guide for the Node151](https://resource.heltec.cn/download/LoRa_Node_151/LoRa_Node_151_Pinout_Diagram.pdf). + +The default pins PB5-7,9 are used as active low controls for the relays. +They are mapped to channels 0 through 3 respectively. The LED on PB8 +is mapped to channel 4. This is useful for testing if a command works +or not. + +The pin PB15 is used as an analog input for an RNG source. This pin +should be grounded. + +Deploying +--------- + +Here is a diagram of the connections: + +``` +******************************************************************************************* +* * +* GND * +* +--------------------------------------------------+ * +* | | * +* +--------+ ~/~ +-+-----------+ GND +---------+ GPIO +-+--------------+ * +* | 24V AC +--------+ +----------------+ Node151 +---------+ Relay | * +* +--------+ | | +-+-------+ +-+--------------+ * +* | | +5V -> VUSB | | * +* | AC-DC PS 5V +------------------+ | +5V -> JD-VCC * +* | | | * +* | | | * +* | +--------------------------------------+ * +* +-------------+ * +* * +******************************************************************************************* +``` + +The normal supply used for irrigation values is 24V AC. This means +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 +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 +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 +when a little bit of filtering was added after the rectifier (22uF), +enough to keep it happy w/ the relays, it was not enough when the +irrigation valves actuated. + +In order to control the values, a relay board, similar to [this +one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), +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. + +Using +----- + +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 +all installed Python software to prevent version conflicts, but is not +always necessary. The `requirements.txt` file contains the necessary +modules to be installed, but simply adding the directory +`strobe/python` to PYTHONPATH should be sufficient. + +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 +name is `/dev/cu.usbmodem1451` as I am on my MacBook Pro, so the command +to launch the gateway is simply: +``` +python3 loraserv.py /dev/cu.usbmodem1451 +``` + +Note: On FreeBSD, the default open mode echos characters back to the +gateway causing it not to work. It is advised to setup the modem tty +via the command: +``` +stty -f /dev/cuaU0.init gfmt1:cflag=cb00:iflag=2e02:lflag=43:oflag=2:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:erase2=8:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600 +``` +before running the `loraserv.py` command. Replace `/dev/cuaU0.init` +with the respective device. The above was generated by running +`cu -l /dev/cuaU0` in one terminal, while obtaining the info via +`stty -g -f /dev/cuaU0` in another terminal. + +Once that is running, then the `lora.py` program's multicast packets +will be forwarded out via the LoRa radio. + +To test it, a simple `ping` command can be used, or turning on or off +the on board LED via channel 4 using the `setunset` command. The ping +command: +``` +python3 lora.py -s ping +``` + +To turn off the LED (which defaults to on): +``` +python3 lora.py -s setunset 4 0 +``` + +Either of these commands should exit w/o message or error. + +Multiple commands may be specified by separating them w/ `--` (two +hyphens). For example: +``` +python3 lora.py -s -- setunset 4 0 -- setunset 1 1 +``` + +The first `--` is required to denote the end of option parsing, +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 execution. 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 argument, 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 argument, 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 milliseconds to run the command for before advancing to the next +command. The available commands are: +* `runfor`: And additional argument specifies the channel. The + channel will be set to on, and then when the command completes, The + channel will be set to off. +* `waitfor`: Wait for the specified time before advancing to the next + enqueued command. + +Notes +----- + +Significant portions of this code is copied from various reference +implementations. Basic review shows that it is of questionable quality. +It would be good to fully review all the code under stm32 and loramac +for any bugs and other issues. The buffer handling has already been +improved, but there is still plety of work that can be done to improve +it further. + + diff --git a/README.md b/README.md index c49153b..3e8d753 100644 --- a/README.md +++ b/README.md @@ -1,293 +1,19 @@ -LoRa Irrigation System -====================== +Syote: Secure IoT +================= -This project is to build an irrigation system from LoRa capable -microcontrollers. The [Heltec Node151](https://heltec.org/project/lora-node-151/) -was chosen due to it's small size and inexpensive cost. +This project started off as a project to control an [irrigation system +via a LoRa radio](LORA-IRR.md), but the core architecture of the +communication and security can easily be reused for other projects. -Design Decisions ----------------- +The projects that make use of the core protocol are included in this +repo to make development easier for now, but if/when the project gets +large enough, they will be broken out into their own repositories. -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, -not GPL licensed, and no proprietary components. This meant that using -IDE's like ST's STM32CubeIDE which is only available in binary form -was not a choice, as that would preclude building on an operating -system other than Windows/MacOSX/Linux. - -Architecture ------------- - -There are a number of components to make this system work. The overall -flow is: - -``` -************************************************************************************************ -* * -* +---------+ +-------------+ +-------------+ +--------------+ * -* | lora.py | multicast | loraserv.py | USB VCP | lora.gw.elf | LoRa | lora.irr.elf | * -* | +--------------+ +------------+ main.c +---------+ irr_main.c | * -* +---------+ +-------------+ +-------------+ +--------------+ * -* * -************************************************************************************************ -``` - -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 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 -pass messages between the former two. The `loraserv.py` program takes -multicast datagrams that are received on 239.192.76.111:21089, which -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 -provided by `lora.gw.elf`. The gateway firmware then decodes the -packet and transmits it via the LoRa radio to the irrigation -controller. Any received packet is returned similarly, but this time -with `data:` prepended, for `loraserv.py` to multicast back to -`lora.py`. - -The reason no particular framing is required for addressing or -destination is that the protocol is secure, and only the party that -is able to decrypt the proper packets will be accepted, and any invalid -packets will be ignored. - -Building +Projects -------- -The build system uses the BSD flavor of make. This is the default -make on the BSDs, originally called pmake, but also available as bsdmake -for MacOSX, and available as [bmake](https://crufty.net/help/sjg/bmake.html). - -It also depends upon ARM's [GNU Arm Embedded -Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm), -which uses gcc as the compiler. It would be good to get it -cross-compile with clang as well, but that requires finding a libc like -the nano libc that is provided by the toolchain. - -One of the required parameters of the build is the shared key used for -authentication. A random key can be made using the command: -`make irrigation_key`, or it can be provided via the make command by -setting the variable IRR_KEY. - -Note: Both IRR_KEY and the argument to `lora.py` will encode the -provided key to UTF-8. - -Once ARM's toolchain is in your path, the following should work: -``` -export MAKEOBJDIR=build -mkdir $MAKEOBJDIR -bsdmake all IRR_KEY= -``` - -And in the directory `build`, two files, `lora.irr.elf` and -`lora.gw.elf` should be present. The file `lora.irr.elf` should be -flashed on the Node151 device that is used for interfacing to the -irrigation system as described in [Deploying](#deploying). The file -`lora.gw.elf` should be used on another Node151 that will be attached -to a computer used as the gateway which runs the `loraserv.py` software -as described in [Using](#using). - -Flashing --------- - -Flashing can be done via the open source tool -[OpenOCD](https://sourceforge.net/projects/openocd/). For this, I use -a Digilent HS1 JTAG programmer utilizing the [resistor -hack](https://github.com/ntfreak/openocd/blob/master/tcl/interface/ftdi/swd-resistor-hack.cfg) -to allow an FTDI JTAG programmer to control the bi-directional `SWIO` -pin. - -One caveat w/ MacOSX, is that it may be necessary to unload the kext -`com.apple.driver.AppleUSBFTDI` via the command: -``` -sudo kextunload -b com.apple.driver.AppleUSBFTDI -``` -as OpenOCD wants direct access to the FTDI driver. - -Once that happens, the device can be programmed using the following -command: -``` -sudo openocd -f interface/ftdi/digilent-hs1.cfg -f interface/ftdi/swd-resistor-hack.cfg -f target/stm32l1.cfg -c "init" -c "reset init" -c "program build/lora.irr.elf verify reset exit" -``` - -Pins ----- - -The [pinout guide for the Node151](https://resource.heltec.cn/download/LoRa_Node_151/LoRa_Node_151_Pinout_Diagram.pdf). - -The default pins PB5-7,9 are used as active low controls for the relays. -They are mapped to channels 0 through 3 respectively. The LED on PB8 -is mapped to channel 4. This is useful for testing if a command works -or not. - -The pin PB15 is used as an analog input for an RNG source. This pin -should be grounded. - -Deploying ---------- - -Here is a diagram of the connections: - -``` -******************************************************************************************* -* * -* GND * -* +--------------------------------------------------+ * -* | | * -* +--------+ ~/~ +-+-----------+ GND +---------+ GPIO +-+--------------+ * -* | 24V AC +--------+ +----------------+ Node151 +---------+ Relay | * -* +--------+ | | +-+-------+ +-+--------------+ * -* | | +5V -> VUSB | | * -* | AC-DC PS 5V +------------------+ | +5V -> JD-VCC * -* | | | * -* | | | * -* | +--------------------------------------+ * -* +-------------+ * -* * -******************************************************************************************* -``` - -The normal supply used for irrigation values is 24V AC. This means -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 -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 -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 -when a little bit of filtering was added after the rectifier (22uF), -enough to keep it happy w/ the relays, it was not enough when the -irrigation valves actuated. - -In order to control the values, a relay board, similar to [this -one](https://www.amazon.com/ELEGOO-Channel-Optocoupler-Arduino-Raspberry/dp/B01HEQF5HU), -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. - -Using ------ - -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 -all installed Python software to prevent version conflicts, but is not -always necessary. The `requirements.txt` file contains the necessary -modules to be installed, but simply adding the directory -`strobe/python` to PYTHONPATH should be sufficient. - -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 -name is `/dev/cu.usbmodem1451` as I am on my MacBook Pro, so the command -to launch the gateway is simply: -``` -python3 loraserv.py /dev/cu.usbmodem1451 -``` - -Note: On FreeBSD, the default open mode echos characters back to the -gateway causing it not to work. It is advised to setup the modem tty -via the command: -``` -stty -f /dev/cuaU0.init gfmt1:cflag=cb00:iflag=2e02:lflag=43:oflag=2:discard=f:dsusp=19:eof=4:eol=ff:eol2=ff:erase=7f:erase2=8:intr=3:kill=15:lnext=16:min=1:quit=1c:reprint=12:start=11:status=14:stop=13:susp=1a:time=0:werase=17:ispeed=9600:ospeed=9600 -``` -before running the `loraserv.py` command. Replace `/dev/cuaU0.init` -with the respective device. The above was generated by running -`cu -l /dev/cuaU0` in one terminal, while obtaining the info via -`stty -g -f /dev/cuaU0` in another terminal. - -Once that is running, then the `lora.py` program's multicast packets -will be forwarded out via the LoRa radio. - -To test it, a simple `ping` command can be used, or turning on or off -the on board LED via channel 4 using the `setunset` command. The ping -command: -``` -python3 lora.py -s ping -``` - -To turn off the LED (which defaults to on): -``` -python3 lora.py -s setunset 4 0 -``` - -Either of these commands should exit w/o message or error. - -Multiple commands may be specified by separating them w/ `--` (two -hyphens). For example: -``` -python3 lora.py -s -- setunset 4 0 -- setunset 1 1 -``` - -The first `--` is required to denote the end of option parsing, -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 execution. 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 argument, 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 argument, 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 milliseconds to run the command for before advancing to the next -command. The available commands are: -* `runfor`: And additional argument specifies the channel. The - channel will be set to on, and then when the command completes, The - channel will be set to off. -* `waitfor`: Wait for the specified time before advancing to the next - enqueued command. - -Notes ------ +[LoRa Irrigation](LORA-IRR.md): Control over LoRa radio. -Significant portions of this code is copied from various reference -implementations. Basic review shows that it is of questionable quality. -It would be good to fully review all the code under stm32 and loramac -for any bugs and other issues. The buffer handling has already been -improved, but there is still plety of work that can be done to improve -it further. +[RS-485 USB HID KVM](RS485HID.md): USB Keyboard over RS-485 diff --git a/RS485HID.md b/RS485HID.md new file mode 100644 index 0000000..6011e4d --- /dev/null +++ b/RS485HID.md @@ -0,0 +1,54 @@ +USB Keyboard over RS-485 +======================== + +The project is to have a device that appears to a computer as a USB +keyboard, but it receives it's key presses from another computer via an +RS-485 multidrop bus. It will use the Syote library for communications, +and as there can be multiple devices on the bus, a single gateway +controller can service multiple such keyboards, making it a nice option +for an IPMI like solution. It is also expected that GPIOs of the device +can be used to control the power switches, along with observing various +LEDs. As most microcontrollers have an ADC, it could theoretically +support beeps from the PC speaker. + +Devices +------- + +These are the device that are under conideration for the project: + +### STM32F103C8 + +64KB flash + +Currently looking at USART3, B0 for DE, B1 for RE. + +Table 5 pin definitions of stm32f103c8.pdf +(all can be remapped) + +USART has idle line detction + +USART1_TX PA9 5v tollerant +USART1_RX PA10 5v tollerant +USART2_TX PA2 NOT 5v tollerant +USART2_RX PA3 NOT 5v tollerant +USART3_TX PB10 5v tollerant +USART3_RX PB11 5v tollerant + +flash: 0/x +boot loader (an2606) pattern 1: 1/0 +embedded sram: 1/1 +top jumper BOOT0/44 +bottom jumper BOOT1/PB2/20 + +### MAX485 + +This requires a 5V VCC. There is a 3.3V part called the MAX3485, but +as often micros can be 5V tollerant, and the MAX485 is fine w/ logic +levels down to 2V, this should be fine. + +D - Driver + DE Driver enable (high enable) + DI Driver input +R - Receiver + RO Receiver output + /RE Receiver enable (low enable)