Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for tunneled LoRa module AT commands #316

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

janakj
Copy link
Contributor

@janakj janakj commented Jul 28, 2022

The aim of this patch series is to enable external LoRa modem management tools, such as my Python tool, to interact with the LoRa modem through the Tower Core module ATCI. To this end, this patch series takes the original AT$AT command implementation and extends it to forward all responses and event notifications from the LoRa modem over the Core module ATCI. This gives the management tool full access to the LoRa modem over the Core module ATCI.

In order to enable AT$AT to be used as an action with arguments, this PR also extends the ATCI in twr-sdk to support action parameters in the same way they are supported in setters.

The PR creates an alias for AT$AT called AT$LORA and introduces a new AT command AT$LORA>ATCI that can be used to enable or disable the forwarding of responses and event notifications from the LoRa modem over the Core module ATCI. The two AT commands are meant to be used together as follows:

AT$LORA>ATCI=1
AT$LORA AT$JOIN
OK
...
$LORA: +OK
$LORA: +EVENT=1,1
...
AT$LORA>ATCI=0

The above sequence allows the management tool to trigger a LoRaWAN OTAA Join in the modem and wait for the event notification that signals whether the Join has succeeded.

When the forwarding of responses and asynchronous notifications are enabled, the data is prefixed with $LORA: before it is written to the Core module ATCI to make it easy for the application to distinguish the data originating from the LoRa modem from other data.

Without setting AT$LORA>ATCI=1 and with the original syntax AT$AT=AT... the custom AT command code works as before, except that the implementation makes sure that the custom AT command was actually written to the LoRa modem before it sends an 'OK'.

Here is an example how this API is used by the LoRa modem Python management tool to obtain information about the modem through the Tower Core module:

(venv) janakj@holly python % ./lora.py -t -p /dev/tty.usbserial-14130
Device information for modem /dev/tty.usbserial-14130:
+---------------------+-------------------------------------------------------------------+
| Port configuration  | 9600 8N1                                                          |
| Device model        | ABZ                                                               |
| Firmware version    | 1.1.2-27-gbf5475f0 (modified) [LoRaMac-node 4.6.0-27-g772d29f4]   |
| Data encoding       | binary                                                            |
| LoRaWAN version     | 1.1.1 / 1.0.4 (1.0.4 for ABP)                                     |
| Regional parameters | RP002-1.0.3                                                       |
| Supported regions   | AS923 AU915 CN470 CN779 EU433 EU868 IN865 KR920 RU864 US915       |
| Device EUI          | 373836375E378F09                                                  |
+---------------------+-------------------------------------------------------------------+
Network activation information for modem /dev/tty.usbserial-14130:
+------------------+------------------+
| Network type     | public           |
| Activation       | OTAA             |
| Network ID       | 00000000         |
| Join EUI         | 0101010101010101 |
| Protocol version | LoRaWAN 1.0.4    |
| Device address   | 0010C300         |
+------------------+------------------+
Current state of modem /dev/tty.usbserial-14130:
+---------------------------+-------------------------------------------------------------+
| Current region            | EU868                                                       |
| LoRaWAN class             | A                                                           |
| Channel mask              | FF00                                                        |
| Data rate                 | SF12_125                                                    |
| Maximum message size      | 51 B                                                        |
| RF power index            | 0                                                           |
| ADR enabled               | True                                                        |
| Duty cycling enabled      | False                                                       |
| Join duty cycling enabled | False                                                       |
| Maximum EIRP              | 16 dBm                                                      |
| Uplink frame counter      | 0                                                           |
| Downlink frame counter    | 0                                                           |
| Last downlink RSSI        | 0 dBm                                                       |
| Last downlink SNR         | 0 dB                                                        |
| RX1 window                | Delay: 1000 ms                                              |
| RX2 window                | Delay: 2000 ms, Frequency: 869.525 MHz, Data rate: SF12_125 |
| Join response windows     | RX1: 5000 ms, RX2: 6000 ms                                  |
+---------------------------+-------------------------------------------------------------+

The command line tool lora.py (part of the Python package) gained new command line options -t / --twr-sdk that enable the integration. Almost all commands that the tool supports can now be performed directly through the Tower Core module ATCI.

janakj added 8 commits July 25, 2022 13:39
AT actions, i.e., AT commands that are neither setters nor getters, may
sometimes need to accept an optional argument delimited from the AT
command with a space, e.g., "AT$JOIN 1". This patch modifies the ATCI API
to support optional parameters in AT actions.
Previously, the only supported AT$AT syntax was AT$AT=AT... This can be
a bit confusing since, technically, the AT command is not a setter. It
just passes its argument to the LoRa modem. This patch adds support for
the following syntax:

AT$AT AT+....

That is, the AT$AT prefix and the actual AT command to be passed to the
LoRa modem are space-separated. The original setter syntax is also
retained.
When the buffer for custom AT commands isn't large enough to hold the
command, indicate an error to the caller rather than sending an
incomplete command to the LoRa module.
When an application invokes a custom LoRa command via AT$AT, pass the
response generated by the LoRa module to the upstream ATCI, on separate
lines prefixed with "$LORA: ". This feature provides applications using
the Tower Core module ATCI with full access to the LoRa module's ATCI in
a "tunneled" mode.

Also, only generate an "OK" response to AT$AT once the tunneled AT
command has been actually sent to LoRa module. If it cannot be sent,
e.g., because the command could not fit into an internal buffer, send an
"ERROR" instead.
This AT command can be used to enable or disable the forwarding of LoRa
responses and events over the ATCI. When set to 1, the responses
generated in response to custom AT commands and all asynchronous
notifications will be forwarded to the ATCI. Each such message will be
prefixed with "$LORA: ". When set to 0 (default), no LoRa responses and
asynchronous notification will be sent to the ATCI.

This command is meant to be used as a wrapper for custom LoRa AT
commands sent via AT$LORA that depend on asynchronous notifications, for
example:

AT$LORA>ATCI=1
AT$LORA AT$JOIN
OK
...
$LORA: +OK
$LORA: +EVENT=1,1
...
AT$LORA>ATCI=0
When two AT commands start with a common prefix, continue iterating
until you have found the right command.
@hubmartin
Copy link
Member

I like it a lot. 👍
This also solves not-so-elegant LoRa twr_cmwx1zzabz_set_debug() mode where the response is directed to the log console. But that works only in debug build and was more for debugging.

The AT$AT command is not documented and it is basically for internal use only. So I'm thinking that since we can get the same result by enabling AT$LORA>ATCI=1 so we might get rid of AT$AT. Am I right?

Will the AT$LORA>ATCI=1 print all the response from LoRa Module, or it just sends a single response based on a single AT$LORA command? I'm curious if it can for example redirect the join +EVENT response when I call join from API for example by button press.

Thanks.

@janakj
Copy link
Contributor Author

janakj commented Jul 29, 2022

I like it a lot. 👍 This also solves not-so-elegant LoRa twr_cmwx1zzabz_set_debug() mode where the response is directed to the log console. But that works only in debug build and was more for debugging.

The AT$AT command is not documented and it is basically for internal use only. So I'm thinking that since we can get the same result by enabling AT$LORA>ATCI=1 so we might get rid of AT$AT. Am I right?

This PR consists of two new AT commands: AT$LORA>ATCI and AT$LORA. AT$LORA shares implementation with AT$AT, so you could get rid of AT$AT, but we need to keep the functionality (custom AT commands). To me, the name AT$AT was a bit misleading, hence the alias AT$LORA.

Will the AT$LORA>ATCI=1 print all the response from LoRa Module, or it just sends a single response based on a single AT$LORA command? I'm curious if it can for example redirect the join +EVENT response when I call join from API for example by button press.

It will keep printing everything until you disable it again with AT$LORA>ATCI=0. Events are printed too, so Joins, factory resets, reboots, and link checks work.

The only type of event that doesn't work at the moment is +RECV (downlinks). Thus, everything but sending uplinks and receiving downlinks should work through the two new AT commands.

Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants