mirror of https://github.com/jgoerzen/xbnet.git
467 lines
15 KiB
Groff
467 lines
15 KiB
Groff
.\" Automatically generated by Pandoc 2.2.1
|
|
.\"
|
|
.TH "LORAPIPE" "1" "October 2019" "John Goerzen" "lorapipe Manual"
|
|
.hy
|
|
.SH NAME
|
|
.PP
|
|
lorapipe \- Transfer data and run a network over LoRa long\-range radios
|
|
.SH SYNOPSIS
|
|
.PP
|
|
\f[B]lorapipe\f[] [ \f[I]OPTIONS\f[] ] \f[B]PORT\f[] \f[B]COMMAND\f[] [
|
|
\f[I]command_options\f[] ]
|
|
.SH OVERVIEW
|
|
.PP
|
|
\f[B]lorapipe\f[] is designed to integrate LoRa long\-range radios into
|
|
a Unix/Linux system.
|
|
In particular, lorapipe can:
|
|
.IP \[bu] 2
|
|
Bidirectionally pipe data across a LoRa radio system
|
|
.IP \[bu] 2
|
|
Do an RF ping and report signal strength at each end
|
|
.IP \[bu] 2
|
|
Operate an AX.25 network using LoRa, and atop it, TCP/IP
|
|
.SH HARDWARE REQUIREMENTS
|
|
.PP
|
|
\f[B]lorapipe\f[] is designed to run with a Microchip RN2903/RN2483 as
|
|
implemented by LoStik.
|
|
.PP
|
|
Drivers for other hardware may be added in the future.
|
|
.PP
|
|
The Microchip firmware must be upgraded to 1.0.5 before running with
|
|
\f[B]lorapipe\f[].
|
|
Previous versions lacked the \f[C]radio\ rxstop\f[] command, which is a
|
|
severe limitation when receiving multiple packets rapidly.
|
|
.PP
|
|
See the documents tab for the
|
|
RN2093 (https://www.microchip.com/wwwproducts/en/RN2903) and the
|
|
firmware upgrade
|
|
guide (https://www.pocketmagic.net/rn2483-rn2903-firmware-upgrade-guide/)
|
|
\- note that the upgrade part is really finicky and you need the
|
|
\[lq]offset\[rq] file.
|
|
.SH PROTOCOL
|
|
.PP
|
|
The \f[B]lorapipe pipe\f[] command is the primary one of interest here.
|
|
It will receive data on stdin, break it up into LoRa\-sized packets (see
|
|
\f[B]\[en]maxpacketsize\f[]), and transmit it across the radio.
|
|
It also will receive data from the radio channel and send it to stdout.
|
|
No attempt at encryption or authentication is made; all packets
|
|
successfully decoded will be sent to stdout.
|
|
Authentication and filtering is left to other layers of the stack atop
|
|
\f[B]lorapipe\f[].
|
|
.PP
|
|
A thin layer atop \f[B]lorapipe pipe\f[] is \f[B]lorapipe kiss\f[],
|
|
which implements the AX.25 KISS protocol.
|
|
It transmits each KISS frame it receives as a LoRa frame, and
|
|
vice\-versa.
|
|
It performs rudimentary checking to ensure it is receiving valid KISS
|
|
data, and will not pass anything else to stdout.
|
|
This support can be used to build a TCP/IP network atop LoRa as will be
|
|
shown below.
|
|
Encryption and authentication could be added atop this by using tools
|
|
such as OpenVPN or SSH.
|
|
.PP
|
|
\f[B]lorapipe\f[] provides only the guarantees that LoRa itself does:
|
|
that raw LoRa frames which are decoded are intact, but not all frames
|
|
will be received.
|
|
It is somewhat akin to UDP in this sense.
|
|
Protocols such as UUCP, ZModem, or TCP can be layered atop
|
|
\f[B]lorapipe\f[] to transform this into a \[lq]reliable\[rq]
|
|
connection.
|
|
.SS Broadcast Use and Separate Frequencies
|
|
.PP
|
|
It is quite possible to use \f[B]lorapipe\f[] to broadcast data to
|
|
multiple listeners; an unlimited number of systems can run \f[B]lorapipe
|
|
pipe\f[] to receive data, and as long as there is nothing on stdin, they
|
|
will happily decode data received over the air without transmitting
|
|
anything.
|
|
.PP
|
|
Separate communication channels may be easily achieved by selecting
|
|
separate radio frequencies.
|
|
.SS Collision Mitigation
|
|
.PP
|
|
\f[B]lorapipe\f[] cannot provide collision detection or avoidance,
|
|
though it does impliement a collision mitigation strategy as described
|
|
below.
|
|
.PP
|
|
As LoRa radios are half\-duplex (they cannot receive while
|
|
transmitting), this poses challenges for quite a few applications that
|
|
expect full\-duplex communication or something like it.
|
|
In testing, a particular problem was observed with protocols that use
|
|
transmission windows and send data in packets.
|
|
These protocols send ACKs after a successful packet transmission, which
|
|
frequently collided with the next packet transmitted from the other
|
|
radio.
|
|
This caused serious performance degredations, and for some protocols,
|
|
complete failure.
|
|
.PP
|
|
There is no carrier detect signal from the LoRa radio.
|
|
Therefore, a turn\-based mechanism is implemented; with each frame
|
|
transmitted, a byte is prepended indicating whether the sender has more
|
|
data in queue to transmit or not.
|
|
The sender will continue transmitting until its transmit buffer is
|
|
empty.
|
|
When that condition is reached, the other end will begin transmitting
|
|
whatever is in its queue.
|
|
This enables protocols such as UUCP \[lq]g\[rq] and UUCP \[lq]i\[rq] to
|
|
work quite well.
|
|
.PP
|
|
A potential complication could arise if the \[lq]last\[rq] packet from
|
|
the transmitter never arrives at the receiver; the receiver might
|
|
therefore never take a turn to transmit.
|
|
To guard against this possibility, there is a timer, and after receiving
|
|
no packets for a certain amount of time, the receiver will assume it is
|
|
acceptable to transmit.
|
|
This timeout is set by the \f[B]\[en]eotwait\f[] option and defaults to
|
|
1000ms (1 second).
|
|
.PP
|
|
The signal about whether or not data remains in the queue takes the form
|
|
of a single byte prepended to every frame.
|
|
It is 0x00 if no data will follow immediately, and 0x01 if data exists
|
|
in the transmitters queue which will be sent immediately.
|
|
The receiving side processes this byte and strips it off before handing
|
|
the data to the application.
|
|
This byte is, however, visible under \f[B]\[en]debug\f[] mode, so you
|
|
can observe the protocol at this low level.
|
|
.SH RADIO PARAMETERS AND INITIALIZATION
|
|
.PP
|
|
The Microchip command reference, available at
|
|
<http://ww1.microchip.com/downloads/en/DeviceDoc/40001811A.pdf>,
|
|
describes the parameters available for the radio.
|
|
A LoRa data rate calculator is available at
|
|
<https://www.rfwireless-world.com/calculators/LoRa-Data-Rate-Calculator.html>
|
|
to give you a rough sense of the speed of different parameters.
|
|
In general, by sacrificing speed, you can increase range and robustness
|
|
of the signal.
|
|
The default initialization uses fairly slow and high\-range settings:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
sys\ get\ ver
|
|
mac\ reset
|
|
mac\ pause
|
|
radio\ get\ mod
|
|
radio\ get\ freq
|
|
radio\ get\ pwr
|
|
radio\ get\ sf
|
|
radio\ get\ bw
|
|
radio\ get\ cr
|
|
radio\ get\ wdt
|
|
radio\ set\ pwr\ 20
|
|
radio\ set\ sf\ sf12
|
|
radio\ set\ bw\ 125
|
|
radio\ set\ cr\ 4/5
|
|
radio\ set\ wdt\ 60000
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
The \f[C]get\f[] commands will cause the pre\-initialization settings to
|
|
be output to stderr if \f[C]\-\-debug\f[] is used.
|
|
A maximum speed init would look like this:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
sys\ get\ ver
|
|
mac\ reset
|
|
mac\ pause
|
|
radio\ get\ mod
|
|
radio\ get\ freq
|
|
radio\ get\ pwr
|
|
radio\ get\ sf
|
|
radio\ get\ bw
|
|
radio\ get\ cr
|
|
radio\ get\ wdt
|
|
radio\ set\ pwr\ 20
|
|
radio\ set\ sf\ sf7
|
|
radio\ set\ bw\ 500
|
|
radio\ set\ cr\ 4/5
|
|
radio\ set\ wdt\ 60000
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
You can craft your own parameters and pass them in with
|
|
\f[C]\-\-initfile\f[] to customize the performance of your RF link.
|
|
.PP
|
|
A particular hint: if \f[C]\-\-debug\f[] shows \f[C]radio_err\f[] after
|
|
a \f[C]radio\ rx\ 0\f[] command, the radio is seeing carrier but is
|
|
getting CRC errors decoding packets.
|
|
Increasing the code rate with \f[C]radio\ set\ cr\f[] to a higher value
|
|
such as \f[C]4/6\f[] or even \f[C]4/8\f[] will increase the FEC
|
|
redundancy and enable it to decode some of those packets.
|
|
Increasing code rate will not help if there is complete silence from the
|
|
radio during a transmission; for those situations, try decreasing
|
|
bandwidth or increasing the spreading factor.
|
|
Note that coderate \f[C]4/5\f[] to the radio is the same as \f[C]1\f[]
|
|
to the calculator, while \f[C]4/8\f[] is the same as \f[C]4\f[].
|
|
.SH PROTOCOL HINTS
|
|
.PP
|
|
Although \f[B]lorapipe pipe\f[] doesn't guarantee it preserves
|
|
application framing, in many cases it does.
|
|
For applications that have their own framing, it is highly desirable to
|
|
set their frame size to be less than the \f[B]lorapipe \&... pipe
|
|
\[en]maxpacketsize\f[] setting.
|
|
This will reduce the amount of data that would have to be retransmitted
|
|
due to lost frames.
|
|
.PP
|
|
As speed decreases, packet size should as well.
|
|
.SH APPLICATION HINTS
|
|
.SS SOCAT
|
|
.PP
|
|
The \f[B]socat\f[](1) program can be particularly helpful; it can
|
|
gateway TCP ports and various other sorts of things into
|
|
\f[B]lorapipe\f[].
|
|
This is helpful if the \f[B]lorapipe\f[] system is across a network from
|
|
the system you wish to run an application on.
|
|
\f[B]ssh\f[](1) can also be useful for this purpose.
|
|
.PP
|
|
A basic command might be like this:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
socat\ TCP\-LISTEN:12345\ EXEC:\[aq]lorapipe\ /dev/ttyUSB0\ pipe\[aq]
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
Some systems might require disabling buffering in some situations, or
|
|
using a pty.
|
|
In those instances, something like this may be in order:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
socat\ TCP\-LISTEN:10104\ EXEC:\[aq]stdbuf\ \-i0\ \-o0\ \-e0\ lorapipe\ /dev/ttyUSB4\ pipe,pty,rawer\[aq]
|
|
\f[]
|
|
.fi
|
|
.SS UUCP
|
|
.PP
|
|
For UUCP, I recommend protocol \f[C]i\f[] with the default window\-size
|
|
setting.
|
|
Use as large of a packet size as you can; for slow links, perhaps 32, up
|
|
to around 100 for fast, high\-quality links.
|
|
(LoRa seems to not do well with packets above 100 bytes).
|
|
.PP
|
|
Protocol \f[C]g\f[] (or \f[C]G\f[] with a smaller packet size) can also
|
|
work, but won't work as well.
|
|
.PP
|
|
Make sure to specify \f[C]half\-duplex\ true\f[] in
|
|
\f[C]/etc/uucp/port\f[].
|
|
.PP
|
|
Here is an example of settings in \f[C]sys\f[]:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
protocol\ i
|
|
protocol\-parameter\ i\ packet\-size\ 90
|
|
protocol\-parameter\ i\ timeout\ 30
|
|
chat\-timeout\ 60
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
Note that UUCP protocol i adds 10 bytes of overhead per packet, so this
|
|
is designed to work with the default recommended packet size of 100.
|
|
.PP
|
|
Then in \f[C]/etc/uucp/port\f[]:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
half\-duplex\ true
|
|
reliable\ false
|
|
\f[]
|
|
.fi
|
|
.SS YMODEM (and generic example of bidirectional pipe)
|
|
.PP
|
|
ZModem makes a poor fit for LoRa because its smallest block size is 1K.
|
|
YModem, however, uses a 128\-byte block size.
|
|
Here's an example of how to make it work.
|
|
Let's say we want to transmit /bin/true over the radio.
|
|
We could run this:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
socat\ EXEC:\[aq]sz\ \-\-ymodem\ /bin/true\[aq]\ EXEC:\[aq]lorapipe\ /dev/ttyUSB0\ pipe\[aq]
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
And on the receiving end:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
socat\ EXEC:\[aq]rz\ \-\-ymodem\[aq]\ EXEC:\[aq]lorapipe\ /dev/ttyUSB0\ pipe\[aq]
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
This approach can also be used with many other programs.
|
|
For instance, \f[C]uucico\ \-l\f[] for UUCP logins.
|
|
.SS KERMIT
|
|
.PP
|
|
Using the C\-kermit distribution (\f[B]apt\-get install ckermit\f[]),
|
|
you can configure for \f[B]lorapipe\f[] like this:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
set\ receive\ packet\-length\ 90
|
|
set\ send\ packet\-length\ 90
|
|
set\ duplex\ half
|
|
set\ window\ 2
|
|
set\ receive\ timeout\ 10
|
|
set\ send\ timeout\ 10
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
Then, on one side, run:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
pipe\ lorapipe\ /dev/ttyUSB0\ pipe
|
|
Ctrl\-\\\ c
|
|
server
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
And on the other:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
pipe\ lorapipe\ /dev/ttyUSB0\ pipe
|
|
Ctrl\-\\\ c
|
|
\f[]
|
|
.fi
|
|
.PP
|
|
Now you can do things like \f[C]rdir\f[] (to see ls from the remote),
|
|
\f[C]get\f[], \f[C]put\f[], etc.
|
|
.SS DEBUGGING WITH CU
|
|
.PP
|
|
To interact directly with the modem, something like this will work:
|
|
.IP
|
|
.nf
|
|
\f[C]
|
|
cu\ \-h\ \-\-line\ /dev/ttyUSB0\ \-s\ 57600\ \-e\ \-o\ \-f\ \-\-nostop
|
|
\f[]
|
|
.fi
|
|
.SH INSTALLATION
|
|
.PP
|
|
\f[B]lorapipe\f[] is a Rust program and can be built by running
|
|
\f[B]\f[BC]cargo\ build\ \-\-release\f[B]\f[].
|
|
The executable will then be placed in \f[B]target/release/lorapipe\f[].
|
|
Rust can be easily installed from <https://www.rust-lang.org/>.
|
|
.SH INVOCATION
|
|
.PP
|
|
Every invocation of \f[B]lorapipe\f[] requires at least the name of a
|
|
serial port (for instance, \f[B]/dev/ttyUSB0\f[]) and a subcommand to
|
|
run.
|
|
.SH GLOBAL OPTIONS
|
|
.PP
|
|
These options may be specified for any command, and must be given before
|
|
the port and command on the command line.
|
|
.TP
|
|
.B \f[B]\-d\f[], \f[B]\[en]debug\f[]
|
|
Activate debug mode.
|
|
Details of program operation will be sent to stderr.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\-h\f[], \f[B]\[en]help\f[]
|
|
Display brief help on program operation.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\[en]readqual\f[]
|
|
Attempt to read and log information about the RF quality of incoming
|
|
packets after each successful packet received.
|
|
There are some corner cases where this is not possible.
|
|
The details will be logged with \f[B]lorapipe\f[]'s logging facility,
|
|
and are therefore only visible if \f[B]\[en]debug\f[] is also used.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\-V\f[], \f[B]\[en]version\f[]
|
|
Display the version number of \f[B]lorapipe\f[].
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\[en]eotwait\f[] \f[I]TIME\f[]
|
|
The amount of time in milliseconds to wait after receiving a packet that
|
|
indicates more are coming before giving up on receiving an additional
|
|
packet and proceeding to transmit.
|
|
Ideally this would be at least the amount of time it takes to transmit 2
|
|
packets.
|
|
Default: 1000.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\[en]initfile\f[] \f[I]FILE\f[]
|
|
A file listing commands to send to the radio to initialize it.
|
|
If not given, a default set will be used.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[B]\[en]txwait\f[] \f[I]TIME\f[]
|
|
Amount of time in milliseconds to pause before transmitting each packet.
|
|
Due to processing delays on the receiving end, packets cannot be
|
|
transmitted immediately back to back.
|
|
Increase this if you are seeing frequent receive errors for
|
|
back\-to\-back packets, which may be indicative of a late listen.
|
|
Experimentation has shown that a value of 120 is needed for very large
|
|
packets, and is the default.
|
|
You may be able to use 50ms or less if you are sending small packets.
|
|
In my testing, with 100\-byte packets, a txwait of 50 was generally
|
|
sufficient.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[I]PORT\f[]
|
|
The name of the serial port to which the radio is attached.
|
|
.RS
|
|
.RE
|
|
.TP
|
|
.B \f[I]COMMAND\f[]
|
|
The subcommand which will be executed.
|
|
.RS
|
|
.RE
|
|
.SH SUBCOMMANDS
|
|
.SS lorapipe \&... pipe
|
|
.PP
|
|
The \f[B]pipe\f[] subcommand is the main workhorse of the application
|
|
and is described extensively above.
|
|
It has one optional parameter:
|
|
.TP
|
|
.B \f[B]\[en]maxpacketsize\f[] \f[I]BYTES\f[]
|
|
The maximum frame size, in the range of 10 \- 250.
|
|
The actual frame transmitted over the air will be one byte larger due to
|
|
\f[B]lorapipe\f[] collision mitigation as described above.
|
|
Experimentation myself, and reports from others, suggests that LoRa
|
|
works best when this is 100 or less.
|
|
.RS
|
|
.RE
|
|
.SS lorapipe \&... ping
|
|
.PP
|
|
The \f[B]ping\f[] subcommand will transmit a simple line of text every
|
|
10 seconds including an increasing counter.
|
|
It can be displayed at the other end with \f[B]lorapipe \&... pipe\f[]
|
|
or reflected with \f[B]lorapipe \&... pong\f[].
|
|
.SS lorapipe \&... pong
|
|
.PP
|
|
The \f[B]pong\f[] subcommand receives packets and crafts a reply.
|
|
It is intended to be used with \f[B]lorapipe \&... ping\f[].
|
|
Its replies include the signal quality SNR and RSSI if available.
|
|
.SH AUTHOR
|
|
.PP
|
|
John Goerzen <jgoerzen@complete.org>
|
|
.SH COPYRIGHT AND LICENSE
|
|
.PP
|
|
Copyright (C) 2019 John Goerzen <jgoerzen\@complete.org
|
|
.PP
|
|
This program is free software: you can redistribute it and/or modify it
|
|
under the terms of the GNU General Public License as published by the
|
|
Free Software Foundation, either version 3 of the License, or (at your
|
|
option) any later version.
|
|
.PP
|
|
This program is distributed in the hope that it will be useful, but
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
See the GNU General Public License for more details.
|
|
.PP
|
|
You should have received a copy of the GNU General Public License along
|
|
with this program.
|
|
If not, see <http://www.gnu.org/licenses/>.
|
|
.SH AUTHORS
|
|
John Goerzen.
|