From 4fabddac727cf28d2c9b83b9e0a8489b2634f1a2 Mon Sep 17 00:00:00 2001 From: dialvarez Date: Tue, 17 May 2022 17:33:41 -0600 Subject: [PATCH 1/8] Changes to include support for SAMR34-based boards with the RN parser firmware from Microchip (repo: https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser). Tested with MLS 1_0_P_6 (Parser_ECC608) and WLR089 Xplained Pro. Should be backwards-compatible with standard RN2xx3 modules. --- src/TheThingsNetwork.cpp | 128 ++++++++++++++++++++++++++++++++++++--- src/TheThingsNetwork.h | 8 +++ 2 files changed, 126 insertions(+), 10 deletions(-) diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index d0888e9..92674d2 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -14,7 +14,8 @@ debugStream->print(__VA_ARGS__); \ } -#define TTN_HEX_CHAR_TO_NIBBLE(c) ((c >= 'A') ? (c - 'A' + 0x0A) : (c - '0')) +#define TTN_HEX_CHAR_DETECT_CASE(c) ((c >= 'a') ? (c - 'a' + 0x0A) : (c - 'A' + 0x0A)) +#define TTN_HEX_CHAR_TO_NIBBLE(c) ((c >= 'A') ? (TTN_HEX_CHAR_DETECT_CASE(c)) : (c - '0')) #define TTN_HEX_PAIR_TO_BYTE(h, l) ((TTN_HEX_CHAR_TO_NIBBLE(h) << 4) + TTN_HEX_CHAR_TO_NIBBLE(l)) const char ok[] PROGMEM = "ok"; @@ -28,8 +29,9 @@ const char rn2483[] PROGMEM = "RN2483"; const char rn2483a[] PROGMEM = "RN2483A"; const char rn2903[] PROGMEM = "RN2903"; const char rn2903as[] PROGMEM = "RN2903AS"; +const char samr34[] PROGMEM = "SAMR34"; -const char *const compare_table[] PROGMEM = {ok, on, off, accepted, mac_tx_ok, mac_rx, mac_err, rn2483, rn2483a, rn2903, rn2903as}; +const char *const compare_table[] PROGMEM = {ok, on, off, accepted, mac_tx_ok, mac_rx, mac_err, rn2483, rn2483a, rn2903, rn2903as, samr34}; #define CMP_OK 0 #define CMP_ON 1 @@ -42,6 +44,7 @@ const char *const compare_table[] PROGMEM = {ok, on, off, accepted, mac_tx_ok, m #define CMP_RN2483A 8 #define CMP_RN2903 9 #define CMP_RN2903AS 10 +#define CMP_SAMR34 11 // CMP OK const char busy[] PROGMEM = "busy"; @@ -115,7 +118,7 @@ const char response_is_not_ok[] PROGMEM = "Response is not OK: "; const char error_key_length[] PROGMEM = "One or more keys are of invalid length."; const char check_configuration[] PROGMEM = "Check your coverage, keys and backend status."; const char no_response[] PROGMEM = "No response from RN module."; -const char invalid_module[] PROGMEM = "Invalid module (must be RN2xx3[xx])."; +const char invalid_module[] PROGMEM = "Invalid module (must be RN2xx3[xx]/SAMR34)."; const char *const error_msg[] PROGMEM = {invalid_sf, invalid_fp, unexpected_response, send_command_failed, join_failed, join_not_accepted, personalize_not_accepted, response_is_not_ok, error_key_length, check_configuration, no_response, invalid_module}; @@ -190,8 +193,9 @@ const char sys_get_vdd[] PROGMEM = "vdd"; const char sys_get_hweui[] PROGMEM = "hweui"; const char sys_set_get_nvm[] PROGMEM = "nvm"; const char sys_set_pindig[] PROGMEM = "pindig"; +const char sys_sleep_standby[] PROGMEM = "standby"; -const char *const sys_table[] PROGMEM = {sys_prefix, sys_sleep, sys_reset, sys_erase_fw, sys_factory_rst, sys_set, sys_get, sys_get_ver, sys_get_vdd, sys_get_hweui, sys_set_get_nvm, sys_set_pindig}; +const char *const sys_table[] PROGMEM = {sys_prefix, sys_sleep, sys_reset, sys_erase_fw, sys_factory_rst, sys_set, sys_get, sys_get_ver, sys_get_vdd, sys_get_hweui, sys_set_get_nvm, sys_set_pindig, sys_sleep_standby}; #define SYS_PREFIX 0 #define SYS_SLEEP 1 @@ -205,6 +209,7 @@ const char *const sys_table[] PROGMEM = {sys_prefix, sys_sleep, sys_reset, sys_e #define SYS_GET_HWEUI 9 #define SYS_SET_GET_NVM 10 #define SYS_SET_PINDIG 11 +#define SYS_SLEEP_STANDBY 12 const char mac_prefix[] PROGMEM = "mac"; const char mac_reset[] PROGMEM = "reset"; @@ -230,6 +235,44 @@ const char *const mac_table[] PROGMEM = {mac_prefix, mac_reset, mac_tx, mac_join #define MAC_SET 8 #define MAC_GET 9 +const char mac_reset_868[] PROGMEM = "868"; // EU868 +const char mac_reset_433[] PROGMEM = "433"; // EU433 +const char mac_reset_na915[] PROGMEM = "na915"; // NA915 +const char mac_reset_au915[] PROGMEM = "au915"; // AU915 +const char mac_reset_kr920[] PROGMEM = "kr920"; // KR920 +const char mac_reset_jpn923[] PROGMEM = "jpn923"; // JPN932 +const char mac_reset_brn923[] PROGMEM = "brn923"; // AS923 +const char mac_reset_cmb923[] PROGMEM = "cmb923"; // AS923 +const char mac_reset_ins923[] PROGMEM = "ins923"; // AS923 +const char mac_reset_laos923[] PROGMEM = "laos923"; // AS923 +const char mac_reset_nz923[] PROGMEM = "nz923"; // AS923 +const char mac_reset_sp923[] PROGMEM = "sp923"; // AS923 +const char mac_reset_twn923[] PROGMEM = "twn923"; // AS923 +const char mac_reset_thai923[] PROGMEM = "thai923"; // AS923 +const char mac_reset_vtm923[] PROGMEM = "vtm923"; // AS923 +const char mac_reset_ind865[] PROGMEM = "ind865"; // IND865 + +const char *const mac_reset_table[] PROGMEM = {mac_reset_868, mac_reset_433, mac_reset_na915, mac_reset_au915, mac_reset_kr920, + mac_reset_jpn923, mac_reset_brn923, mac_reset_cmb923, mac_reset_ins923, mac_reset_laos923, mac_reset_nz923, mac_reset_sp923, + mac_reset_twn923, mac_reset_thai923, mac_reset_vtm923, mac_reset_ind865}; + +#define MAC_RESET_868 0 +#define MAC_RESET_433 1 +#define MAC_RESET_NA915 2 +#define MAC_RESET_AU915 3 +#define MAC_RESET_KR920 4 +#define MAC_RESET_JPN923 5 +#define MAC_RESET_BRN923 6 +#define MAC_RESET_CMB923 7 +#define MAC_RESET_INS923 8 +#define MAC_RESET_LAOS923 9 +#define MAC_RESET_NZ923 10 +#define MAC_RESET_SP923 11 +#define MAC_RESET_TWN923 12 +#define MAC_RESET_THAI923 13 +#define MAC_RESET_VTM923 14 +#define MAC_RESET_IND865 15 + const char mac_devaddr[] PROGMEM = "devaddr"; const char mac_deveui[] PROGMEM = "deveui"; const char mac_appeui[] PROGMEM = "appeui"; @@ -322,6 +365,7 @@ const char *const mac_tx_table[] PROGMEM = {mac_tx_type_cnf, mac_tx_type_ucnf}; #define SUCCESS_MESSAGE 8 #define CMP_TABLE 9 #define CMP_ERR_TABLE 10 +#define MAC_RESET_TABLE 11 int pgmstrcmp(const char *str1, uint8_t str2Index, uint8_t table = CMP_TABLE) { @@ -645,6 +689,50 @@ void TheThingsNetwork::autoBaud() baudDetermined = true; } +bool TheThingsNetwork::macReset() +{ + clearReadBuffer(); + sendCommand(MAC_TABLE, MAC_PREFIX, true, false); + // only for SAMR34-based boards + if(this->modemType == TTN_MODEM_TYPE_SAMR34) + { + sendCommand(MAC_TABLE, MAC_RESET, true, false); + // check which default FP will be set + switch (fp) + { + case TTN_FP_EU868: + sendCommand(MAC_RESET_TABLE, MAC_RESET_868, false, false); + break; + case TTN_FP_US915: + sendCommand(MAC_RESET_TABLE, MAC_RESET_NA915, false, false); + break; + case TTN_FP_AU915: + sendCommand(MAC_RESET_TABLE, MAC_RESET_AU915, false, false); + break; + case TTN_FP_KR920_923: + sendCommand(MAC_RESET_TABLE, MAC_RESET_KR920, false, false); + break; + case TTN_FP_AS920_923: + case TTN_FP_AS923_925: + sendCommand(MAC_RESET_TABLE, MAC_RESET_BRN923, false, false); // TODO: fix, SAMR34 implements individual FPs for each AS923 country, while TTN only sets a general AS923/AS925 FP + break; + case TTN_FP_IN865_867: + sendCommand(MAC_RESET_TABLE, MAC_RESET_IND865, false, false); + break; + default: + debugPrintMessage(ERR_MESSAGE, ERR_INVALID_FP); + break; + } + } + // for RN2XX3-based boards + else + { + sendCommand(MAC_TABLE, MAC_RESET, false, false); + } + modemStream->write(SEND_MSG); + return waitForOk(); +} + void TheThingsNetwork::reset(bool adr) { // autobaud and send "sys reset" @@ -925,10 +1013,14 @@ void TheThingsNetwork::showStatus() { readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_EUI, buffer); - readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer)); - debugPrintIndex(SHOW_BATTERY, buffer); - readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, sizeof(buffer)); - debugPrintIndex(SHOW_APPEUI, buffer); + // these commands are not implemented for RN parser firmware for SAMR34/WLR089 + if(this->modemType != TTN_MODEM_TYPE_SAMR34) + { + readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer)); + debugPrintIndex(SHOW_BATTERY, buffer); + readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, sizeof(buffer)); + debugPrintIndex(SHOW_APPEUI, buffer); + } readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DEVEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_DEVEUI, buffer); readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DR, buffer, sizeof(buffer)); @@ -957,12 +1049,19 @@ bool TheThingsNetwork::checkValidModuleConnected(bool autoBaudFirst) // buffer contains "RN2xx3[xx] x.x.x ...", getting only model (RN2xx3[xx]) char *model = strtok(buffer, " "); debugPrintIndex(SHOW_MODEL, model); - // check if module is valid (must be RN2483, RN2483A, RN2903 or RN2903AS) + // check if module is valid (must be RN2483, RN2483A, RN2903, RN2903AS or SAMR34) if(pgmstrcmp(model, CMP_RN2483) == 0 || pgmstrcmp(model, CMP_RN2483A) == 0 || pgmstrcmp(model, CMP_RN2903) == 0 || pgmstrcmp(model, CMP_RN2903AS) == 0) { + this->modemType = TTN_MODEM_TYPE_RN; debugPrintMessage(SUCCESS_MESSAGE, SCS_VALID_MODULE); return true; // module responded and is valid (recognized/supported) } + else if(pgmstrcmp(model, CMP_SAMR34) == 0) + { + this->modemType = TTN_MODEM_TYPE_SAMR34; + debugPrintMessage(SUCCESS_MESSAGE, SCS_VALID_MODULE); // module responded and is valid (recognized/supported) + return true; + } debugPrintMessage(ERR_MESSAGE, ERR_INVALID_MODULE); return false; // module responded but is invalid (unrecognized/unsupported) } @@ -1338,6 +1437,9 @@ void TheThingsNetwork::sendCommand(uint8_t table, uint8_t index, bool appendSpac case RADIO_TABLE: strcpy_P(command, (char *)pgm_read_word(&(radio_table[index]))); break; + case MAC_RESET_TABLE: + strcpy_P(command, (char *)pgm_read_word(&(mac_reset_table[index]))); + break; default: return; } @@ -1486,7 +1588,8 @@ bool TheThingsNetwork::sendPayload(uint8_t mode, uint8_t port, uint8_t *payload, void TheThingsNetwork::sleep(uint32_t mseconds) { - if (mseconds < 100) + uint16_t minSleepTime = (this->modemType == TTN_MODEM_TYPE_SAMR34) ? 1000 : 100; // min sleep time for SAMR34 is 1000 ms + if (mseconds < minSleepTime) { return; } @@ -1494,6 +1597,11 @@ void TheThingsNetwork::sleep(uint32_t mseconds) debugPrint(F(SENDING)); sendCommand(SYS_TABLE, SYS_PREFIX, true); sendCommand(SYS_TABLE, SYS_SLEEP, true); + // send standby for SAMR34-based boards + if(this->modemType == TTN_MODEM_TYPE_SAMR34) + { + sendCommand(SYS_TABLE, SYS_SLEEP_STANDBY, true); + } sprintf(buffer, "%lu", mseconds); modemStream->write(buffer); diff --git a/src/TheThingsNetwork.h b/src/TheThingsNetwork.h index ebcc59f..2a9aa7f 100644 --- a/src/TheThingsNetwork.h +++ b/src/TheThingsNetwork.h @@ -87,6 +87,12 @@ enum ttn_modem_status_t TTN_MODEM_C_RX2 }; +enum ttn_modem_type_t +{ + TTN_MODEM_TYPE_RN, + TTN_MODEM_TYPE_SAMR34 +}; + class TheThingsNetwork { private: @@ -133,8 +139,10 @@ class TheThingsNetwork public: bool needsHardReset = false; + ttn_modem_type_t modemType = TTN_MODEM_TYPE_RN; // assume RN modem, this can be changed using checkValidModuleConnected TheThingsNetwork(Stream &modemStream, Stream &debugStream, ttn_fp_t fp, uint8_t sf = TTN_DEFAULT_SF, uint8_t fsb = TTN_DEFAULT_FSB); + bool macReset(); void reset(bool adr = true); void resetHard(uint8_t resetPin); void showStatus(); From 572496fc1c308833c2e761b6509c56c622e2eccd Mon Sep 17 00:00:00 2001 From: danalvarez Date: Wed, 18 May 2022 16:23:56 -0600 Subject: [PATCH 2/8] Updated documentation to reflect changes for SAMR34 compatibility. --- README.md | 12 +++++++++++- docs/TheThingsNetwork.md | 22 +++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ec363b4..e05089e 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ This is an [Arduino Library](https://www.arduino.cc/en/Guide/Libraries) for Arduino devices like [The Things Uno](https://www.thethingsnetwork.org/docs/devices/uno/) and [Node](https://www.thethingsnetwork.org/docs/devices/node/) to communicate via [The Things Network](https://www.thethingsnetwork.org). -> At the moment this library requires devices to feature a [Microchip RN2xx3 module](http://www.microchip.com/design-centers/wireless-connectivity/embedded-wireless/lora-technology). +> At the moment this library requires devices to feature a [Microchip RN2xx3 module](http://www.microchip.com/design-centers/wireless-connectivity/embedded-wireless/lora-technology). You may also use a `SAMR34`-based board, for more information on that see [SAM34 Usage](#user-content-samr34-usage). ## Installation @@ -17,6 +17,16 @@ This is an [Arduino Library](https://www.arduino.cc/en/Guide/Libraries) for Ardu * [TheThingsNetwork](docs/TheThingsNetwork.md) * [TheThingsMessage](docs/TheThingsMessage.md) +## SAM34 Usage + +Compatibility between this library and the `SAMR34`-based boards is, at the moment, experimental. Boards that can be used are the [SAMR34 Xplained Pro](https://www.microchip.com/en-us/development-tool/dm320111), the [WLR089 Xplained Pro](https://www.microchip.com/en-us/development-tool/EV23M25A) or a proprietary board containing the `SAMR34`. + +Before usage, please note the following: + +1. If using a `SAMR34`-based board, you must first program your board with the [RN Parser](https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser) firmware. This firmware emulates the behaviour of the `RN2xx3` devices on the `SAMR34`. Specifically, you **must** use the `MLS 1_0_P_6 (Parser_ECC608)` firmware contained [here](https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser/tree/master/software/MLS_1_0_P_6/Parser_ECC608), since several bugs that made the firmware unusable where fixed for this release. +2. Some commands available in the `RN2xx3` modems are not implemented in the RN Parser firmware for `SAMR34`. For a complete list of the implemented commands and their possible differences, see the [Command User Guide](https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser/blob/master/02_command_guide/README.md#top) for the RN Parser firmware. +3. The `autoBaud` feature is not available in the RN parser firmware, but this is easily circumvented by manually modifying the default baud rate in the `conf_sio2host.h` file within the firmware's source code. Default baud rate is `115200`. + ## Examples The library comes with [examples](examples). After installing the library you need to restart the Arduino IDE before they can be found under **File > Examples > TheThingsNetwork**. diff --git a/docs/TheThingsNetwork.md b/docs/TheThingsNetwork.md index 4511a6e..dff3293 100644 --- a/docs/TheThingsNetwork.md +++ b/docs/TheThingsNetwork.md @@ -38,6 +38,16 @@ void hardReset(uint8_t resetPin); - `uint8_t resetPin`: The output pin that is connected to the module's reset pin. The output pin should be configured as output and set to high by the user. +## Method: `macReset` + +Resets the LoRaWAN stack and initializes it with the parameters for the selected band. + +```c +void macReset() +``` + +Note that, for `SAMR34`-based devices, where this command requires a `` parameter, it will use the configured FP in the initialization of the TTN object (e.g. `TTN_FP_US915`). + ## Method: `getHardwareEui` Gets the unique hardware EUI, often used as the DevEUI. @@ -82,6 +92,8 @@ RX Delay 1: 1000 RX Delay 2: 2000 ``` +Note that for `SAMR34`-based boards, it will not print out the `Battery` and `AppEUI` parameters, since the `sys get vdd` and `mac get appeui` commands are not currently implemented in the RN parser firmware for these modems. + See the [DeviceInfo](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/DeviceInfo/DeviceInfo.ino) example. ## Method: `onMessage` @@ -216,7 +228,9 @@ Sleep the LoRa module for a specified number of milliseconds. void sleep(unsigned long mseconds); ``` -- `unsigned long mseconds`: number of milliseconds to sleep. +- `unsigned long mseconds`: number of milliseconds to sleep. Must be >= 100 ms for `RN2xx3` modems, >= 1000 ms for `SAMR34`-based boards. + +Note that, for `SAMR34`-based boards, this command will send `sys sleep standby ` to the modem. For all other `RN2xx3` modems, it will only send `sys sleep `. ## Method: `wake` @@ -449,10 +463,10 @@ bool setRX1Delay(uint16_t delay); Checks if a valid module is connected to the configured serial port. Useful to check for connectivity with a supported module before performing any other actions. ```c -bool checkValidModuleConnected(bool autobaud_first); +bool checkValidModuleConnected(bool autoBaudFirst); ``` -- `bool autobaud_first`: Perform a call to `autoBaud()` before checking connection. Default is `false`. +- `bool autoBaudFirst`: Perform a call to `autoBaud()` before checking connection. Default is `false`. Returns: @@ -462,7 +476,9 @@ Returns: * `RN2483A` * `RN2903` * `RN2903AS` + * `SAMR34` (or boards based on this device) * `true` if the module responded (i.e. `needsHardReset` is `false`) and is valid (supported). + * Also sets the `modemType` attribute to either `TTN_MODEM_TYPE_RN` (for all `RN2xx3` devices) or `TTN_MODEM_TYPE_SAMR34`, depending on the detected modem. See the [CheckModule](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/CheckModule/CheckModule.ino) example. From e85dff649b1653b030a20b9de241144f99be6165 Mon Sep 17 00:00:00 2001 From: danalvarez Date: Tue, 30 Aug 2022 18:39:04 -0600 Subject: [PATCH 3/8] Change wake method depending on modem type (via digital pin for SAMR34 and autobaud for RN boards) --- src/TheThingsNetwork.cpp | 15 +++++++++++++-- src/TheThingsNetwork.h | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index 92674d2..2ab3397 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -1609,9 +1609,20 @@ void TheThingsNetwork::sleep(uint32_t mseconds) debugPrintLn(buffer); } -void TheThingsNetwork::wake() +void TheThingsNetwork::wake(uint8_t resetPin) { - autoBaud(); + // only for SAMR34-based boards + if(this->modemType == TTN_MODEM_TYPE_SAMR34) + { + digitalWrite(resetPin, LOW); + delay(1000); + digitalWrite(resetPin, HIGH); + } + // for RN2XX3-based boards + else + { + autoBaud(); + } } void TheThingsNetwork::linkCheck(uint16_t seconds) diff --git a/src/TheThingsNetwork.h b/src/TheThingsNetwork.h index 2a9aa7f..853bf9b 100644 --- a/src/TheThingsNetwork.h +++ b/src/TheThingsNetwork.h @@ -174,7 +174,7 @@ class TheThingsNetwork ttn_response_t sendBytes(const uint8_t *payload, size_t length, port_t port = 1, bool confirm = false, uint8_t sf = 0); ttn_response_t poll(port_t port = 1, bool confirm = false, bool modem_only = false); void sleep(uint32_t mseconds); - void wake(); + void wake(uint8_t resetPin = 3); void saveState(); void linkCheck(uint16_t seconds); uint8_t getLinkCheckGateways(); From 6ed1103840fbd81dbdb3abf8ca13109fef6bf75f Mon Sep 17 00:00:00 2001 From: danalvarez Date: Tue, 30 Aug 2022 18:42:42 -0600 Subject: [PATCH 4/8] Changed name of pin argument in wake function --- src/TheThingsNetwork.cpp | 6 +++--- src/TheThingsNetwork.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index 2ab3397..1c47a58 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -1609,14 +1609,14 @@ void TheThingsNetwork::sleep(uint32_t mseconds) debugPrintLn(buffer); } -void TheThingsNetwork::wake(uint8_t resetPin) +void TheThingsNetwork::wake(uint8_t interruptPin) { // only for SAMR34-based boards if(this->modemType == TTN_MODEM_TYPE_SAMR34) { - digitalWrite(resetPin, LOW); + digitalWrite(interruptPin, LOW); delay(1000); - digitalWrite(resetPin, HIGH); + digitalWrite(interruptPin, HIGH); } // for RN2XX3-based boards else diff --git a/src/TheThingsNetwork.h b/src/TheThingsNetwork.h index 853bf9b..885f9bf 100644 --- a/src/TheThingsNetwork.h +++ b/src/TheThingsNetwork.h @@ -174,7 +174,7 @@ class TheThingsNetwork ttn_response_t sendBytes(const uint8_t *payload, size_t length, port_t port = 1, bool confirm = false, uint8_t sf = 0); ttn_response_t poll(port_t port = 1, bool confirm = false, bool modem_only = false); void sleep(uint32_t mseconds); - void wake(uint8_t resetPin = 3); + void wake(uint8_t interruptPin = 3); void saveState(); void linkCheck(uint16_t seconds); uint8_t getLinkCheckGateways(); From b5f83100f8fb68aced6a8d2a2355a17e6b8f08d6 Mon Sep 17 00:00:00 2001 From: danalvarez Date: Tue, 30 Aug 2022 18:54:12 -0600 Subject: [PATCH 5/8] Updated documentation for wake function --- docs/TheThingsNetwork.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/TheThingsNetwork.md b/docs/TheThingsNetwork.md index dff3293..7134733 100644 --- a/docs/TheThingsNetwork.md +++ b/docs/TheThingsNetwork.md @@ -237,9 +237,12 @@ Note that, for `SAMR34`-based boards, this command will send `sys sleep standby Wake up the LoRa module from sleep before the expiration of the defined time. ```c -void wake(); +void wake(uint8_t interruptPin); ``` +- `uint8_t interruptPin`: Only required for `SAMR34`-based boards. Will not be used for `RN2XX3` modems, as these are woken up by a call to `autoBaud()`. Default value is `3`. + - On `SAMR34`-based boards, this pin must be set to `OUTPUT` and `HIGH` by the user, and provided in the call to `wake(interruptPin)`. More information on how this works available [here](https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser/blob/master/02_command_guide/README.md#sys-sleep-mode-length). + ## Method: `linkCheck` Sets the time interval for the link check process to be triggered. The next uplink will include a Link Check Request MAC command when the interval expires. This method should be called after joining has been completed. From bfe8adf688bba5c7000b9370e4666f57291646e6 Mon Sep 17 00:00:00 2001 From: danalvarez Date: Mon, 5 Sep 2022 20:03:11 -0600 Subject: [PATCH 6/8] Changes to improve support of SAMR34. Modified some examples to work both with RN2xx3 or SAMR34. Removed CheckModule.ino example, this procedure has been moved to DeviceInfo.ino, where it makes more sense. Changes to TheThingsNetwork.cpp: 1. Added the mac_joineui command to mac_options, which is used to obtain the appeui in SAMR34 RN parser firmware 2. Added the mac_edclass command to mac_options, which is used to set the LoRaWAN class in SAMR34 parser firmware 3. Added getModemType and setModemType functions 4. Modified personalize: only perform soft reset on RN2xx3 boards 5. Modified provision: only perform soft reset on RN2xx3 boards 6. Modified provision: send mac set appeui or mac set joineui for RN2xx3 or SAMR34 boards, respectively 7. Modified provision: only send mac save on RN2xx3 boards 8. Modified setClass: send mac set class or mac set edclass for RN2xx3 or SAMR34 boards, respectively 9. Modified showStatus: optain appeui via mac get appeui or mac get joineui for RN2xx3 or SAMR34 boards, respectively --- examples/CheckModule/CheckModule.ino | 73 ---------------------------- examples/DeviceInfo/DeviceInfo.ino | 30 ++++++++++++ examples/Receive/Receive.ino | 10 ++++ examples/SendABP/SendABP.ino | 10 ++++ examples/SendOTAA/SendOTAA.ino | 10 ++++ src/TheThingsNetwork.cpp | 67 +++++++++++++++++++------ src/TheThingsNetwork.h | 2 + 7 files changed, 114 insertions(+), 88 deletions(-) delete mode 100644 examples/CheckModule/CheckModule.ino diff --git a/examples/CheckModule/CheckModule.ino b/examples/CheckModule/CheckModule.ino deleted file mode 100644 index c67a6fc..0000000 --- a/examples/CheckModule/CheckModule.ino +++ /dev/null @@ -1,73 +0,0 @@ -#include - -// Set your DevAddr, NwkSKey, AppSKey and the frequency plan -const char *devAddr = "00000000"; -const char *nwkSKey = "00000000000000000000000000000000"; -const char *appSKey = "00000000000000000000000000000000"; - -#define loraSerial Serial1 -#define debugSerial Serial - -// Replace REPLACE_ME with TTN_FP_EU868 or TTN_FP_US915 -#define freqPlan REPLACE_ME - -TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan); - -void setup() -{ - loraSerial.begin(57600); - debugSerial.begin(9600); - - // Wait a maximum of 10s for Serial Monitor - while (!debugSerial && millis() < 10000) - ; - - // RN2XX3 reset pin connected to Arduino pin 12 - pinMode(12, OUTPUT); - digitalWrite(12, HIGH); - // hard reset module and wait for startup - debugSerial.println("-- CHECK COMM"); - ttn.resetHard(12); - delay(100); - // check if a valid module responded - // (if no module is connected or wiring is bad, checkValidModuleConnected() will - // take about ~30s to return (another ~30s if autobaud_first is true)) - if(!ttn.checkValidModuleConnected(true)) - { - if(ttn.needsHardReset) - { - debugSerial.println("Module unresponsive, please power cycle or hard reset board!"); - } - else - { - debugSerial.println("Module unsupported!"); // module must be RN2483, RN2483A, RN2903, RN2903AS - } - while(true) // stop code execution - { - ; - } - } - - // do an ABP join - debugSerial.println("-- PERSONALIZE"); - // false is added as fourth argument to the personalize() call so that it - // does not perform a soft reset, because the module was already hard reset before via pin 12. - ttn.personalize(devAddr, nwkSKey, appSKey, false); - - debugSerial.println("-- STATUS"); - ttn.showStatus(); -} - -void loop() -{ - debugSerial.println("-- LOOP"); - - // Prepare payload of 1 byte to indicate LED status - byte payload[1]; - payload[0] = (digitalRead(LED_BUILTIN) == HIGH) ? 1 : 0; - - // Send it off - ttn.sendBytes(payload, sizeof(payload)); - - delay(10000); -} diff --git a/examples/DeviceInfo/DeviceInfo.ino b/examples/DeviceInfo/DeviceInfo.ino index 5cc525a..fd0e2b0 100644 --- a/examples/DeviceInfo/DeviceInfo.ino +++ b/examples/DeviceInfo/DeviceInfo.ino @@ -10,8 +10,38 @@ TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan); void setup() { + // For SAMR34, configure baudrate to the speed set in RN parser firmware (default is 115200) loraSerial.begin(57600); debugSerial.begin(9600); + + // RN2XX3/SAMR34 reset pin connected to Arduino pin 12 + pinMode(12, OUTPUT); + digitalWrite(12, HIGH); + // hard reset module and wait for startup + debugSerial.println("-- CHECK COMM"); + ttn.resetHard(12); + delay(1000); + // check if a valid module responded + // (if no module is connected or wiring is bad, checkValidModuleConnected() will + // take about ~30s to return (another ~30s if autobaud_first is true)) + if(!ttn.checkValidModuleConnected(true)) + { + if(ttn.needsHardReset) + { + debugSerial.println("Module unresponsive, please power cycle or hard reset board!"); + } + else + { + debugSerial.println("Module unsupported!"); // module must be RN2483, RN2483A, RN2903, RN2903AS, SAMR34 + } + while(true) // stop code execution + { + ; + } + } + // init LoRaWAN stack (only necessary in SAMR34) + if(ttn.getModemType() == TTN_MODEM_TYPE_SAMR34) + ttn.macReset(); } void loop() diff --git a/examples/Receive/Receive.ino b/examples/Receive/Receive.ino index 3dd95ed..da191b4 100644 --- a/examples/Receive/Receive.ino +++ b/examples/Receive/Receive.ino @@ -14,6 +14,7 @@ TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan); void setup() { + // For SAMR34, configure baudrate to the speed set in RN parser firmware (default is 115200) loraSerial.begin(57600); debugSerial.begin(9600); @@ -21,6 +22,15 @@ void setup() while (!debugSerial && millis() < 10000) ; + pinMode(12, OUTPUT); // RN2XX3/SAMR34 reset pin connected to Arduino pin 12 + digitalWrite(12, HIGH); + debugSerial.println("-- CHECK COMM"); + ttn.resetHard(12); // hard-reset the module + delay(1000); // wait for module startup + ttn.checkValidModuleConnected(true); // check a valid module is connected (RN2xx3 or SAMR34) + if(ttn.getModemType() == TTN_MODEM_TYPE_SAMR34) // if SAMR34, init LoRaWAN stack + ttn.macReset(); + // Set callback for incoming messages ttn.onMessage(message); diff --git a/examples/SendABP/SendABP.ino b/examples/SendABP/SendABP.ino index f8f22f0..7b0eadd 100644 --- a/examples/SendABP/SendABP.ino +++ b/examples/SendABP/SendABP.ino @@ -15,6 +15,7 @@ TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan); void setup() { + // For SAMR34, configure baudrate to the speed set in RN parser firmware (default is 115200) loraSerial.begin(57600); debugSerial.begin(9600); @@ -22,6 +23,15 @@ void setup() while (!debugSerial && millis() < 10000) ; + pinMode(12, OUTPUT); // RN2XX3/SAMR34 reset pin connected to Arduino pin 12 + digitalWrite(12, HIGH); + debugSerial.println("-- CHECK COMM"); + ttn.resetHard(12); // hard-reset the module + delay(1000); // wait for module startup + ttn.checkValidModuleConnected(true); // check a valid module is connected (RN2xx3 or SAMR34) + if(ttn.getModemType() == TTN_MODEM_TYPE_SAMR34) // if SAMR34, init LoRaWAN stack + ttn.macReset(); + debugSerial.println("-- PERSONALIZE"); ttn.personalize(devAddr, nwkSKey, appSKey); diff --git a/examples/SendOTAA/SendOTAA.ino b/examples/SendOTAA/SendOTAA.ino index 033874c..936ef07 100644 --- a/examples/SendOTAA/SendOTAA.ino +++ b/examples/SendOTAA/SendOTAA.ino @@ -14,6 +14,7 @@ TheThingsNetwork ttn(loraSerial, debugSerial, freqPlan); void setup() { + // For SAMR34, configure baudrate to the speed set in RN parser firmware (default is 115200) loraSerial.begin(57600); debugSerial.begin(9600); @@ -21,6 +22,15 @@ void setup() while (!debugSerial && millis() < 10000) ; + pinMode(12, OUTPUT); // RN2XX3/SAMR34 reset pin connected to Arduino pin 12 + digitalWrite(12, HIGH); + debugSerial.println("-- CHECK COMM"); + ttn.resetHard(12); // hard-reset the module + delay(1000); // wait for module startup + ttn.checkValidModuleConnected(true); // check a valid module is connected (RN2xx3 or SAMR34) + if(ttn.getModemType() == TTN_MODEM_TYPE_SAMR34) // if SAMR34, init LoRaWAN stack + ttn.macReset(); + debugSerial.println("-- STATUS"); ttn.showStatus(); diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index 1c47a58..301143a 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -297,9 +297,11 @@ const char mac_class[] PROGMEM = "class"; const char mac_status[] PROGMEM = "status"; const char mac_upctr[] PROGMEM = "upctr"; const char mac_dnctr[] PROGMEM = "dnctr"; +const char mac_joineui[] PROGMEM = "joineui"; +const char mac_edclass[] PROGMEM = "edclass"; const char *const mac_options[] PROGMEM = {mac_devaddr, mac_deveui, mac_appeui, mac_nwkskey, mac_appskey, mac_appkey, mac_pwridx, mac_dr, mac_adr, mac_bat, mac_retx, mac_linkchk, mac_rxdelay1, mac_rxdelay2, mac_band, - mac_ar, mac_rx2, mac_ch, mac_gwnb, mac_mrgn, mac_class, mac_status, mac_upctr, mac_dnctr}; + mac_ar, mac_rx2, mac_ch, mac_gwnb, mac_mrgn, mac_class, mac_status, mac_upctr, mac_dnctr, mac_joineui, mac_edclass}; #define MAC_DEVADDR 0 #define MAC_DEVEUI 1 @@ -325,6 +327,8 @@ const char *const mac_options[] PROGMEM = {mac_devaddr, mac_deveui, mac_appeui, #define MAC_STATUS 21 #define MAC_UPCTR 22 #define MAC_DNCTR 23 +#define MAC_JOINEUI 24 +#define MAC_EDCLASS 25 const char mac_join_mode_otaa[] PROGMEM = "otaa"; const char mac_join_mode_abp[] PROGMEM = "abp"; @@ -694,7 +698,7 @@ bool TheThingsNetwork::macReset() clearReadBuffer(); sendCommand(MAC_TABLE, MAC_PREFIX, true, false); // only for SAMR34-based boards - if(this->modemType == TTN_MODEM_TYPE_SAMR34) + if(getModemType() == TTN_MODEM_TYPE_SAMR34) { sendCommand(MAC_TABLE, MAC_RESET, true, false); // check which default FP will be set @@ -779,7 +783,9 @@ void TheThingsNetwork::onMessage(void (*cb)(const uint8_t *payload, size_t size, bool TheThingsNetwork::personalize(const char *devAddr, const char *nwkSKey, const char *appSKey, bool resetFirst) { - if(resetFirst) { + // a sys reset before personalize should only be done in RN2xx3 modules + // for SAMR34, best not to do it because a mac reset would be required afterwards + if(resetFirst && getModemType() != TTN_MODEM_TYPE_SAMR34) { reset(adr); } if (strlen(devAddr) != 8 || strlen(appSKey) != 32 || strlen(nwkSKey) != 32) @@ -813,7 +819,9 @@ bool TheThingsNetwork::personalize() bool TheThingsNetwork::provision(const char *appEui, const char *appKey, bool resetFirst) { - if(resetFirst) { + // a sys reset before provision should only be done in RN2xx3 modules + // for SAMR34, best not to do it because a mac reset would be required afterwards + if(resetFirst && getModemType() != TTN_MODEM_TYPE_SAMR34) { reset(adr); } if (strlen(appEui) != 16 || strlen(appKey) != 32) @@ -823,9 +831,17 @@ bool TheThingsNetwork::provision(const char *appEui, const char *appKey, bool re } readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer)); sendMacSet(MAC_DEVEUI, buffer); - sendMacSet(MAC_APPEUI, appEui); + // send 'mac get appeui' on RN modules + if(getModemType() == TTN_MODEM_TYPE_RN) + sendMacSet(MAC_APPEUI, appEui); + // send 'mac get joineui' on SAMR34-based modules + else + sendMacSet(MAC_JOINEUI, appEui); sendMacSet(MAC_APPKEY, appKey); - saveState(); + // 'mac save' is not implemented (and reduntant) in SAMR34 RN parser firmware + // see: https://github.com/MicrochipTech/atsamr34_lorawan_rn_parser/blob/master/02_command_guide/README.md#limitations + if(getModemType() == TTN_MODEM_TYPE_RN) + saveState(); return true; } @@ -868,14 +884,19 @@ bool TheThingsNetwork::setClass(lorawan_class_t p_lw_class) case CLASS_A: { lw_class = p_lw_class; - return sendMacSet(MAC_CLASS, "a"); + // 'mac set class ' command is for RN2xx3 + // 'mac set edclass ' command is for SAMR34 + if(getModemType() == TTN_MODEM_TYPE_RN) + return sendMacSet(MAC_CLASS, "a"); + else + return sendMacSet(MAC_EDCLASS, "a"); } // case CLASS_B: // Not yet supported. Use default case. case CLASS_C: { - bool result = sendMacSet(MAC_CLASS, "c"); + bool result = (getModemType() == TTN_MODEM_TYPE_RN) ? sendMacSet(MAC_CLASS, "c") : sendMacSet(MAC_EDCLASS, "c"); // Older firmware does not support Class C. If setting change fails, keep on using Class A. if(result) lw_class = p_lw_class; return result; @@ -1013,14 +1034,20 @@ void TheThingsNetwork::showStatus() { readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_HWEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_EUI, buffer); - // these commands are not implemented for RN parser firmware for SAMR34/WLR089 - if(this->modemType != TTN_MODEM_TYPE_SAMR34) + // 'sys get vdd' not implemented in RN parser firmware for SAMR34/WLR089 + if(getModemType() == TTN_MODEM_TYPE_RN) { readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer)); debugPrintIndex(SHOW_BATTERY, buffer); readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_APPEUI, buffer); } + // appeui is retrieved by sending 'mac get joineui' in SAMR34 + else + { + readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_JOINEUI, buffer, sizeof(buffer)); + debugPrintIndex(SHOW_APPEUI, buffer); + } readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DEVEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_DEVEUI, buffer); readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DR, buffer, sizeof(buffer)); @@ -1031,6 +1058,16 @@ void TheThingsNetwork::showStatus() debugPrintIndex(SHOW_RX_DELAY_2, buffer); } +void TheThingsNetwork::setModemType(ttn_modem_type_t modemType) +{ + this->modemType = modemType; +} + +ttn_modem_type_t TheThingsNetwork::getModemType() +{ + return this->modemType; +} + bool TheThingsNetwork::checkValidModuleConnected(bool autoBaudFirst) { // check if we want to autobaud first @@ -1052,13 +1089,13 @@ bool TheThingsNetwork::checkValidModuleConnected(bool autoBaudFirst) // check if module is valid (must be RN2483, RN2483A, RN2903, RN2903AS or SAMR34) if(pgmstrcmp(model, CMP_RN2483) == 0 || pgmstrcmp(model, CMP_RN2483A) == 0 || pgmstrcmp(model, CMP_RN2903) == 0 || pgmstrcmp(model, CMP_RN2903AS) == 0) { - this->modemType = TTN_MODEM_TYPE_RN; + setModemType(TTN_MODEM_TYPE_RN); debugPrintMessage(SUCCESS_MESSAGE, SCS_VALID_MODULE); return true; // module responded and is valid (recognized/supported) } else if(pgmstrcmp(model, CMP_SAMR34) == 0) { - this->modemType = TTN_MODEM_TYPE_SAMR34; + setModemType(TTN_MODEM_TYPE_SAMR34); debugPrintMessage(SUCCESS_MESSAGE, SCS_VALID_MODULE); // module responded and is valid (recognized/supported) return true; } @@ -1588,7 +1625,7 @@ bool TheThingsNetwork::sendPayload(uint8_t mode, uint8_t port, uint8_t *payload, void TheThingsNetwork::sleep(uint32_t mseconds) { - uint16_t minSleepTime = (this->modemType == TTN_MODEM_TYPE_SAMR34) ? 1000 : 100; // min sleep time for SAMR34 is 1000 ms + uint16_t minSleepTime = (getModemType() == TTN_MODEM_TYPE_SAMR34) ? 1000 : 100; // min sleep time for SAMR34 is 1000 ms if (mseconds < minSleepTime) { return; @@ -1598,7 +1635,7 @@ void TheThingsNetwork::sleep(uint32_t mseconds) sendCommand(SYS_TABLE, SYS_PREFIX, true); sendCommand(SYS_TABLE, SYS_SLEEP, true); // send standby for SAMR34-based boards - if(this->modemType == TTN_MODEM_TYPE_SAMR34) + if(getModemType() == TTN_MODEM_TYPE_SAMR34) { sendCommand(SYS_TABLE, SYS_SLEEP_STANDBY, true); } @@ -1612,7 +1649,7 @@ void TheThingsNetwork::sleep(uint32_t mseconds) void TheThingsNetwork::wake(uint8_t interruptPin) { // only for SAMR34-based boards - if(this->modemType == TTN_MODEM_TYPE_SAMR34) + if(getModemType() == TTN_MODEM_TYPE_SAMR34) { digitalWrite(interruptPin, LOW); delay(1000); diff --git a/src/TheThingsNetwork.h b/src/TheThingsNetwork.h index 885f9bf..b0b42f9 100644 --- a/src/TheThingsNetwork.h +++ b/src/TheThingsNetwork.h @@ -146,6 +146,8 @@ class TheThingsNetwork void reset(bool adr = true); void resetHard(uint8_t resetPin); void showStatus(); + void setModemType(ttn_modem_type_t modemType); + ttn_modem_type_t getModemType(); size_t getHardwareEui(char *buffer, size_t size); size_t getAppEui(char *buffer, size_t size); size_t getVersion(char *buffer, size_t size); From 1f42526aa8571b211830527451c444d6a4a4193f Mon Sep 17 00:00:00 2001 From: danalvarez Date: Mon, 5 Sep 2022 20:22:39 -0600 Subject: [PATCH 7/8] Update TheThingsNetwork class documentation --- docs/TheThingsNetwork.md | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/docs/TheThingsNetwork.md b/docs/TheThingsNetwork.md index 7134733..f953b08 100644 --- a/docs/TheThingsNetwork.md +++ b/docs/TheThingsNetwork.md @@ -92,7 +92,7 @@ RX Delay 1: 1000 RX Delay 2: 2000 ``` -Note that for `SAMR34`-based boards, it will not print out the `Battery` and `AppEUI` parameters, since the `sys get vdd` and `mac get appeui` commands are not currently implemented in the RN parser firmware for these modems. +Note that for `SAMR34`-based boards, it will not print out the `Battery` parameter, since `sys get vdd` is not implemented in the RN parser firmware for these modems. See the [DeviceInfo](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/DeviceInfo/DeviceInfo.ino) example. @@ -134,14 +134,14 @@ Call the method without the first two arguments if the device's LoRa module come Activate the device via ABP. ```c -bool personalize(const char *devAddr, const char *nwkSKey, const char *appSKey, bool reset_first); +bool personalize(const char *devAddr, const char *nwkSKey, const char *appSKey, bool resetFirst); bool personalize(); ``` - `const char *devAddr`: Device Address assigned to the device. - `const char *nwkSKey`: Network Session Key assigned to the device for identification. - `const char *appSKey`: Application Session Key assigned to the device for encryption. -- `bool reset_first`: Soft reset the module before performing any other action. Default is `true`. +- `bool resetFirst`: Soft reset the module before performing any other action. Only performed on RN2xx3 modules. Default is `true`. Returns `true` or `false` depending on whether the activation was successful. @@ -213,12 +213,12 @@ See the [Receive](https://github.com/TheThingsNetwork/arduino-device-lib/blob/ma Sets the information needed to activate the device via OTAA, without actually activating. Call join() without the first 2 arguments to activate. ```c -bool provision(const char *appEui, const char *appKey, bool reset_first); +bool provision(const char *appEui, const char *appKey, bool resetFirst); ``` - `const char *appEui`: Application Identifier for the device. - `const char *appKey`: Application Key assigned to the device. -- `bool reset_first`: Soft reset the module before performing any other action. Default is `true`. +- `bool resetFirst`: Soft reset the module before performing any other action. Only performed on RN2xx3 modules. Default is `true`. ## Method: `sleep` @@ -483,7 +483,27 @@ Returns: * `true` if the module responded (i.e. `needsHardReset` is `false`) and is valid (supported). * Also sets the `modemType` attribute to either `TTN_MODEM_TYPE_RN` (for all `RN2xx3` devices) or `TTN_MODEM_TYPE_SAMR34`, depending on the detected modem. -See the [CheckModule](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/CheckModule/CheckModule.ino) example. +See the [DeviceInfo](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/DeviceInfo/DeviceInfo.ino) example. + +## Method: `setModemType` + +Sets the `modemType` attribute. It is best to call `checkValidModuleConnected()`, as this automatically sets the modem type depending on the modem's response. + +```c +void setModemType(ttn_modem_type_t modemType); +``` + +- `ttn_modem_type_t modemType`: The modem type. Can be `TTN_MODEM_TYPE_RN` (for all `RN2xx3` devices) or `TTN_MODEM_TYPE_SAMR34`. + +## Method: `getModemType` + +Returns the `modemType` attribute. Can be used to check what modem is connected (make sure to call `checkValidModuleConnected()` before to automatically set `modemType`). + +```c +ttn_modem_type_t getModemType(); +``` + +See the [DeviceInfo](https://github.com/TheThingsNetwork/arduino-device-lib/blob/master/examples/DeviceInfo/DeviceInfo.ino) example. # Additional for statistics From 867ab97bad13d2ce65b96b3210d0f959c8242d57 Mon Sep 17 00:00:00 2001 From: danalvarez Date: Thu, 8 Sep 2022 10:55:11 -0600 Subject: [PATCH 8/8] Added modemType verification to getAppEui, use getAppEui in showStatus to automatically check modemType --- src/TheThingsNetwork.cpp | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/TheThingsNetwork.cpp b/src/TheThingsNetwork.cpp index 301143a..ce432d3 100644 --- a/src/TheThingsNetwork.cpp +++ b/src/TheThingsNetwork.cpp @@ -431,7 +431,16 @@ TheThingsNetwork::TheThingsNetwork(Stream &modemStream, Stream &debugStream, ttn size_t TheThingsNetwork::getAppEui(char *buffer, size_t size) { - return readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, size); + // for RN2xx3 + if(getModemType() == TTN_MODEM_TYPE_RN) + { + return readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, size); + } + // for SAMR34 + else + { + return readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_JOINEUI, buffer, size); + } } size_t TheThingsNetwork::getHardwareEui(char *buffer, size_t size) @@ -1039,15 +1048,9 @@ void TheThingsNetwork::showStatus() { readResponse(SYS_TABLE, SYS_TABLE, SYS_GET_VDD, buffer, sizeof(buffer)); debugPrintIndex(SHOW_BATTERY, buffer); - readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_APPEUI, buffer, sizeof(buffer)); - debugPrintIndex(SHOW_APPEUI, buffer); - } - // appeui is retrieved by sending 'mac get joineui' in SAMR34 - else - { - readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_JOINEUI, buffer, sizeof(buffer)); - debugPrintIndex(SHOW_APPEUI, buffer); } + getAppEui(buffer, sizeof(buffer)); + debugPrintIndex(SHOW_APPEUI, buffer); readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DEVEUI, buffer, sizeof(buffer)); debugPrintIndex(SHOW_DEVEUI, buffer); readResponse(MAC_TABLE, MAC_GET_SET_TABLE, MAC_DR, buffer, sizeof(buffer));