/** * @brief Initializes the device and connects to the network using Activation By Personalization. * @param devADDR provided by LoRaWAN Network server registration. * @param appSKey provided by LoRaWAN Network server registration. * @param nwkSKey provided by LoRaWAN Network server registration. * @return Returns true if the parameters were valid and able to save settings. */ bool RN2483::initABP(const uint8_t devAddr[4], const uint8_t appSKey[16], const uint8_t nwkSKey[16], bool adr) { init(); if(resetDevice() && setMacParam(STR_DEV_ADDR, devAddr, 4) && setMacParam(STR_APP_SESSION_KEY, appSKey, 16) && setMacParam(STR_NETWORK_SESSION_KEY, nwkSKey, 16) && setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && joinABP()) { if(saveConfiguration()) { return true; } } return false; }
/** * @brief Initialise settings and connect to network using Over The Air activation. * @param devEUI provided by LoRaWAN Network server registration. * @param appEUI provided by LoRaWAN Network server registration. * @param appKey provided by LoRaWAN Network server registration. * @return Returns true if network confirmation and able to save settings. */ bool RN2483::initOTAA(const uint8_t devEUI[8], const uint8_t appEUI[8], const uint8_t appKey[16], bool adr) { printf("RN2483: Init OTAA\n"); init(); if(resetDevice() && setMacParam(STR_DEV_EUI, devEUI, 8) && setMacParam(STR_APP_EUI, appEUI, 8) && setMacParam(STR_APP_KEY, appKey, 16) && setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && joinOTAA()) { if(saveConfiguration()) { return true; } } return false; }
// Initializes the device and connects to the network using Activation By Personalization. // Returns true on successful connection. bool Sodaq_RN2483::initABP(Stream& stream, const uint8_t devAddr[4], const uint8_t appSKey[16], const uint8_t nwkSKey[16]) { debugPrintLn("[initABP]"); init(stream); return resetDevice() && setMacParam(STR_DEV_ADDR, devAddr, 4) && setMacParam(STR_APP_SESSION_KEY, appSKey, 16) && setMacParam(STR_NETWORK_SESSION_KEY, nwkSKey, 16) && //setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && joinNetwork(STR_ABP); }
// Initializes the device and connects to the network using Over-The-Air Activation. // Returns true on successful connection. bool Sodaq_RN2483::initOTA(Stream& stream, const uint8_t devEUI[8], const uint8_t appEUI[8], const uint8_t appKey[16]) { debugPrintLn("[initOTA]"); init(stream); return resetDevice() && setMacParam(STR_DEV_EUI, devEUI, 8) && setMacParam(STR_APP_EUI, appEUI, 8) && setMacParam(STR_APP_KEY, appKey, 16) && // setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && joinNetwork(STR_OTAA); }
// Initializes the device and connects to the network using Over-The-Air Activation. // Uses HWEUI // Returns true on successful connection. bool Sodaq_RN2483::initOTA(SerialType& stream, const uint8_t appEUI[8], const uint8_t appKey[16], bool adr) { uint8_t devEUI[8]; debugPrintLn("[initOTA]: using hweui"); // assign Serial port init(stream); if (resetDevice()) { getHWEUI(devEUI, 8); // returns ASCII HWEUI from RN module return resetDevice() && setMacParam(STR_DEV_EUI, devEUI, 8) && setMacParam(STR_APP_EUI, appEUI, 8) && setMacParam(STR_APP_KEY, appKey, 16) && setMacParam(STR_ADR, BOOL_TO_ONOFF(adr)) && joinNetwork(STR_OTAA); } return 0; // reset command failed }
/** * @brief Sets the data rate for a given channel ID. * Please refer to the LoRaWAN spec for the actual values. * @param Channel ID from 0 - 15. * @param Number representing the minimum data rate range from 0 to 7. * @param Number representing the maximum data rate range from 0 to 7 * @return Returns true if parameters are valid or false if not. */ bool RN2483::setDrRange(uint8_t channelID, uint8_t minRange, uint8_t maxRange) { if((channelID <= 15)&&(minRange<=7)&&(maxRange<=7)) { char buffer [15]; int bytesWritten = sprintf(buffer, "%d %d %d", channelID, minRange, maxRange); // Check to make sure sprintf did not return an error before sending. if(bytesWritten > 0) { return setMacParam(STR_CH_DRRANGE, buffer); } } return false; }
// Sends the given payload with acknowledgement. // Returns 0 (NoError) when transmission is successful or one of the MacTransmitErrorCodes otherwise. uint8_t Sodaq_RN2483::sendReqAck(uint8_t port, const uint8_t* payload, uint8_t size, uint8_t maxRetries) { debugPrintLn("[sendReqAck]"); if (!setMacParam(STR_RETRIES, maxRetries)) { // not a fatal error -just show a debug message debugPrintLn("[sendReqAck] Non-fatal error: setting number of retries failed."); } return macTransmit(STR_CONFIRMED, port, payload, size); }
/** * @brief Sets the module operation frequency on a given channel ID. * @param Channel ID from 3 - 15. * @param Decimal number representing the frequency. * 863000000 to 870000000 or 433050000 to 434790000 in Hz * @return Returns true if parameters are valid or false if not. */ bool RN2483::setChannelFreq(uint8_t channelID, uint32_t frequency) { if((channelID <= 15 && channelID >= 3)) { if((frequency <=870000000 && frequency >= 863000000)||(frequency <=434790000 && frequency >= 433050000)) { char buffer [15]; int bytesWritten = sprintf(buffer, "%d %lu", channelID, frequency); // Check to make sure sprintf did not return an error before sending. if(bytesWritten > 0) { return setMacParam(STR_CH_FREQ, buffer); } } } return false; }
/** * @brief Sets the duty cycle allowed on the given channel ID. * @param Channel ID to set duty cycle (0-15), * @param Duty cycle is 0 - 100% as a float. * @return Returns true if parameters are valid or false if not. */ bool RN2483::setDutyCycle(uint8_t channelID, float dutyCycle) { // Convert duty cycle into the required value using equation (100 / X) - 1 if((dutyCycle <= (float)100 && dutyCycle >=(float)0) && (channelID > 15)) { uint8_t dutyCycleSetting = ((float)100 / dutyCycle) - 1; // Create the string for the settings char buffer [15]; int bytesWritten = sprintf(buffer, "%d %d", channelID, dutyCycleSetting); // Check to make sure sprintf did not return an error before sending. if(bytesWritten > 0) { return setMacParam(STR_CH_DCYCLE, buffer); } } return false; }
/** * @brief Sets the spreading factor. * @param Spreading factor parameter. * @return Returns true if was set successfully. */ bool RN2483::setSpreadingFactor(uint8_t spreadingFactor) { int8_t datarate; if (!isRN2903) { // RN2483 SF(DR) = 7(5), 8(4), 9(3), 10(2), 11(1), 12(0) datarate = 12 - spreadingFactor; } else { // RN2903 SF(DR) = 7(3), 8(2), 9(1), 10(0) datarate = 10 - spreadingFactor; } if (datarate > -1) { return setMacParam(STR_DATARATE, datarate); } return false; }
/** * @brief Sets the battery level required for the Device Status Answer frame in LoRaWAN Class A Protocol. * @param temperature Decimal number between 0-255 representing battery level. 0 means external power, 1 means * low level, 254 means high level, 255 means the device was unable to measure battery level. * @return Returns true if battery level is valid or false if value not valid. */ bool RN2483::setBattery(uint8_t batLvl) { return setMacParam(STR_BAT, batLvl); }
/** * @brief Sets the time interval for the link check process. When the time expires, the next application * packet will include a link check command to the server. * @param Decimal number that sets the time interval in seconds, from 0 to 65535. 0 disables link check process. * @return Returns true if parameter is valid or false if time interval is not valid. */ bool RN2483::setLinkCheckInterval(uint8_t linkCheckInterval) { return setMacParam(STR_LNK_CHK, linkCheckInterval); }
/** * @brief Sets the power index * @param 868MHz: 1 to 5 / 915MHz: 5, 7, 8, 9 or 10. * @return Returns true if succesful. */ bool RN2483::setPowerIndex(uint8_t powerIndex) { return setMacParam(STR_PWR_IDX, powerIndex); }
// Provides a quick test of several methods as a pseudo-unit test. void Sodaq_RN2483::runTestSequence(Stream& stream) { debugPrint("free ram: "); debugPrintLn(freeRam()); init(stream); this->loraStream = &stream; this->diagStream = &stream; // expectString debugPrintLn("write \"testString\" and then CRLF"); if (expectString("testString", 5000)) { debugPrintLn("[expectString] positive case works!"); } debugPrintLn(""); debugPrintLn("write something other than \"testString\" and then CRLF"); if (!expectString("testString", 5000)) { debugPrintLn("[expectString] negative case works!"); } debugPrint("free ram: "); debugPrintLn(freeRam()); // setMacParam(array) debugPrintLn(""); debugPrintLn(""); uint8_t testValue[] = {0x01, 0x02, 0xDE, 0xAD, 0xBE, 0xEF}; setMacParam("testParam ", testValue, ARRAY_SIZE(testValue)); // macTransmit debugPrintLn(""); debugPrintLn(""); uint8_t testValue2[] = {0x01, 0x02, 0xDE, 0xAD, 0xBE, 0xEF}; macTransmit(STR_CONFIRMED, 1, testValue2, ARRAY_SIZE(testValue2)); debugPrint("free ram: "); debugPrintLn(freeRam()); // receive debugPrintLn(""); debugPrintLn("==== receive"); char mockResult[] = "303132333435363738"; memcpy(this->receivedPayloadBuffer, mockResult, strlen(mockResult) + 1); uint8_t payload[64]; debugPrintLn("* without having received packet"); uint8_t length = receive(payload, sizeof(payload)); debugPrintLn(reinterpret_cast<char*>(payload)); debugPrint("Length: "); debugPrintLn(length); debugPrintLn("* having received packet"); this->packetReceived = true; length = receive(payload, sizeof(payload)); debugPrintLn(reinterpret_cast<char*>(payload)); debugPrint("Length: "); debugPrintLn(length); // onMacRX debugPrintLn(""); debugPrintLn("==== onMacRX"); char mockRx[] = "mac_rx 1 303132333435363738"; memcpy(this->inputBuffer, mockRx, strlen(mockRx) + 1); this->packetReceived = false;// reset debugPrint("Input buffer now is: "); debugPrintLn(this->inputBuffer); debugPrint("onMacRX result code: "); debugPrintLn(onMacRX()); uint8_t payload2[64]; if (receive(payload2, sizeof(payload2)) != 9) { debugPrintLn("len is wrong!"); } debugPrintLn(reinterpret_cast<char*>(payload2)); if (receive(payload2, sizeof(payload2), 2) != 7) { debugPrintLn("len is wrong!"); } debugPrintLn(reinterpret_cast<char*>(payload2)); if (receive(payload2, sizeof(payload2), 3) != 6) { debugPrintLn("len is wrong!"); } debugPrintLn(reinterpret_cast<char*>(payload2)); debugPrint("free ram: "); debugPrintLn(freeRam()); // lookup error debugPrintLn(""); debugPrintLn(""); debugPrint("empty string: "); debugPrintLn((lookupMacTransmitError("") == NoResponse) ? "passed" : "wrong"); debugPrint("\"random\": "); debugPrintLn((lookupMacTransmitError("random") == NoResponse) ? "passed" : "wrong"); debugPrint("\"invalid_param\": "); debugPrintLn((lookupMacTransmitError("invalid_param") == InternalError) ? "passed" : "wrong"); debugPrint("\"not_joined\": "); debugPrintLn((lookupMacTransmitError("not_joined") == NotConnected) ? "passed" : "wrong"); debugPrint("\"busy\": "); debugPrintLn((lookupMacTransmitError("busy") == Busy) ? "passed" : "wrong"); debugPrint("\"invalid_param\": "); debugPrintLn((lookupMacTransmitError("invalid_param") == InternalError) ? "passed" : "wrong"); debugPrint("free ram: "); debugPrintLn(freeRam()); }