LoRaWAN
LoRaWAN Functions
This category contains functions specific to LoRaWAN devices.
| API Name | Brief Description |
|---|---|
| api.loraSend(ack, timeout, msg, port) | Sends and receives LoRaWAN frames. |
| api.loraJoin(int, dr) | Sends a join request. |
| api.loraSetup() | Configures LoRaWAN parameters. Multiple variants. See below. |
| api.loraListenClassBC(timeout, class) | Listens for messages until timeout in class B or C. |
| api.loraSetCredential() | Sets one LoRa credential. Multiple variants. See below. |
| api.loraSetCredentials(devADDR, devEUI, nwsKey, appsKey, appEUI) | Sets LoRa credentials. |
| api.loraGetDevEui(format) | Retrieves the devEUI. |
| api.getDeviceAddress() | Retrieves the device address. |
api.loraSend(ack, timeout, msg, port)
api.loraSend(1, 20000, "HELLO")
Sends and receives LoRaWAN frames.
Arguments
- ack (integer):
1for acknowledged mode.0for unacknowledged mode.
- timeout (integer): Maximum execution time in milliseconds (used in acknowledged mode).
- msg (string): Message sent to LoRaWAN.
Optional
- port (integer, optional): Port number.
Return
- status (integer): Positive or zero for success, negative for failure.
- Positive: Number of bytes received.
0: "No data received".-1: "Not acknowledged" ("NACK").-2: "Cannot send, LoRaMAC keeps busy!".-3: "Failed sending!".-4: "Failed sending LoRaWAN frame! (sent count = %d)".-5: "Cannot send - too long payload for current SF!".
- port (integer):
nilor port on which the answer was received. - answer (string):
nilor non-zero length string containing gateway answer.
Example
-- Sends 0xCCBBAA35 to LoRa with 20s timeout and acknowledged mode
msg = pack.pack('<b4', 0xCC, 0xBB, 0xAA, 0x35)
status, port, answer = api.loraSend(1, 20000, msg)
--------------------------------
if status >= 1 then -- Checks if device received more than one byte
api.dumpArray(answer) -- If true, print the data
end
for i = 1, 5 do
status, _, answer = api.loraSend(1, timeout, bootMsg, port)
if status >= 0 then break
elseif i == 5 and status < 0 then
print("Failed to send boot message to LoRaWAN, restarting ...")
ex("_reset")
end
timeout = timeout + 2000
end
print("BOOT UP DONE! " .. msgPrint)
-- dividing the LoRaWAN messages to limit it to 50 bytes in size
function loraSendBig(raw, filterId)
ret, port, cfg = api.loraSend(ack, 5000, string.char(1)..string.sub(raw,1,50), filterId)
processConfig(ret, port, cfg)
if #raw > 50 then
ret, port, cfg = api.loraSend(ack, 5000, string.char(2)..string.sub(raw,51,100), filterId)
processConfig(ret, port, cfg)
if #raw > 100 then -- and so on
api.loraJoin(int, dr)
api.loraJoin()
Sends a join request.
Info: Rejoining occurs automatically every 7 days by default. This interval can be modified using api.loraSetup().
Arguments
Optional
- int (integer, optional):
0for security context check (sends join request if none).1for forced join request.
- dr (integer, optional): Sets join Data Rate (0 to 5).
Return
- status (integer):
0for success, negative for failure.0: Success.-3: "Timeout, busy!".-4: "General error!".-5: "No answer!".-6: "Error joining!".
Example
-- Check if joined, if not join
api.loraJoin()
--------------------------------
-- Force join
api.loraJoin(1)
--------------------------------
-- Join request send only if ATAA is used
if joinMethod == "OTAA" then api.loraJoin() end
api.loraSetup()
Configures LoRaWAN parameters.
| API Name | Brief Description |
|---|---|
| api.loraSetup("ACTIVATION", method) | Sets the activation type ("OTAA" or "ABP"). Resets previous activation settings and sends a join request each time. |
| api.loraSetup("ADR", state) | Enables or disables Adaptive Data Rate (1 for on, 0 for off). |
| api.loraSetup("DR", value) | Sets the Data Rate (0-5). If ADR is off and a join request is performed, it assigns a different DR during the join. |
| api.loraSetup("DC", state) | Sets or gets the Duty Cycle state ("ON", "OFF", "DCTIME", "GET"). |
| api.loraSetup("RUN_FSM", timeout) | Runs the internal LoRaWAN FSM for the specified milliseconds. |
| api.loraSetup("CLASS", class) | Sets or gets the current LoRaWAN class ("A", "B", or "C"). Verify network server support before setting. |
| api.loraSetup("OTAA-REJOIN-CONFIRMED-FAILED-COUNTER", value) | Sets the number of confirmed messages that must fail before forcing a new join. |
| api.loraSetup("OTAA-MINIMAL-CONFIRMED-PERIOD", value) | Sets the period (in milliseconds) to send a join request (default 7 days). |
| api.loraSetup("OTAA-REJOIN-CONFIRMED-COUNTER", number) | Sets the maximum number of unconfirmed messages in a row (default/minimal 5), forcing every Nth message as confirmed. |
| api.loraSetup("POWER", power) | Sets the power to a defined value in dBm (0, 2, 4, 6, 8, 10, 12, 14). |
| api.loraSetup("TIME_SYNC", force, zone) | Schedules a time synchronization request (requires network server support, compatible with LoRaWAN 1.0.3+). |
api.loraSetup("ACTIVATION", method)
api.loraSetup("ACTIVATION", "ABP")
Sets the activation type.
Warning: Resets previous activation settings and sends a join request each time.
Arguments
-
"ACTIVATION" (string, command)
❗command - the argument needs to have this exact form❗ -
method (string):
"OTAA"- use OTAA as activation type."ABP"- ABP as activation type.
Example
-- Set activation type as ABP
api.loraSetup("ACTIVATION", "ABP")
--------------------------------
local joinMethod = "OTAA"
api.loraSetup("ACTIVATION", joinMethod)
api.loraSetup("ADR", state)
api.loraSetup("ADR", 1)
Enables or disables Adaptive Data Rate.
Warning: If ABP activation and ADR is on, setting DR always assigns DR = 0.
Arguments
-
"ADR" (string, command)
❗command - the argument needs to have this exact form❗ -
state (integer):
1for on.0for off.
Example
-- Enable ADR
api.loraSetup("ADR", 1)
api.loraSetup("DR", value)
api.loraSetup("DR", 0)
Sets the Data Rate.
Warning: If ADR is off and a join request is performed, it assigns a different DR during the join.
Arguments
-
"DR" (string, command)
❗command - the argument needs to have this exact form❗ -
value (integer): Data Rate (0-5).
Example
-- Set data rate to 0
api.loraSetup("DR", 0)
--------------------------------
-- Set a scan size limit based on the data rate
if iface == "lorawan" then
dataRate = api.loraSetup("DR")
scanLimitSize = drToMaxLength[dataRate]-2
else
scanLimitSize = 500
end
api.loraSetup("DC", state)
api.loraSetup("DC", "ON")
Sets or gets the Duty Cycle state.
Arguments
-
"DC" (string, command)
❗command - the argument needs to have this exact form❗ -
state (string):
"ON"- turns it on."OFF"- turns it off."DCTIME""GET"
Example
-- Set duty cycle on
api.loraSetup("DC", "ON")
api.loraSetup("RUN_FSM", timeout)
api.loraSetup("RUN_FSM", 1000)
Runs the internal LoRaWAN FSM for the specified milliseconds.
Arguments
-
"RUN_FSM" (string, command)
❗command - the argument needs to have this exact form❗ -
timeout (integer): Milliseconds to run FSM.
Example
-- Run FSM for 1000 ms
api.loraSetup("RUN_FSM", 1000)
api.loraSetup("CLASS", class)
api.loraSetup("CLASS", "C")
Sets or gets the current LoRaWAN class.
Info: Verify network server support before setting to B or C.
Arguments
-
"CLASS" (string, command)
❗command - the argument needs to have this exact form❗ -
class (string):
"A"- LoRaWAN class A."B"- LoRaWAN class B."C"- LoRaWAN class C.
Example
-- Set class to C
api.loraSetup("CLASS", "C")
--------------------------------
-- LoRa setup as part of the bootMessage function
api.loraSetup("ACTIVATION", joinMethod)
api.loraSetup("CLASS", "A")
if joinMethod == "OTAA" then api.loraJoin() end
api.loraSetup("OTAA-REJOIN-CONFIRMED-FAILED-COUNTER", value)
api.loraSetup("OTAA-REJOIN-CONFIRMED-FAILED-COUNTER", 10)
Sets the number of confirmed messages that must fail before forcing a new join.
Arguments
-
"OTAA-REJOIN-CONFIRMED-FAILED-COUNTER" (string, command)
❗command - the argument needs to have this exact form❗ -
value (integer): Number of failed confirmed messages.
Example
-- Set failed counter to 10
api.loraSetup("OTAA-REJOIN-CONFIRMED-FAILED-COUNTER", 10)
api.loraSetup("OTAA-MINIMAL-CONFIRMED-PERIOD", value)
api.loraSetup("OTAA-MINIMAL-CONFIRMED-PERIOD", 86400000)
Sets the period (in milliseconds) to send a join request.
Arguments
-
"OTAA-MINIMAL-CONFIRMED-PERIOD" (string, command)
❗command - the argument needs to have this exact form❗ -
value (integer): Period in milliseconds (default 7 days).
Example
-- Set period to 1 day
api.loraSetup("OTAA-MINIMAL-CONFIRMED-PERIOD", 86400000)
api.loraSetup("OTAA-REJOIN-CONFIRMED-COUNTER", number)
api.loraSetup("OTAA-REJOIN-CONFIRMED-COUNTER", 10)
Sets the maximum number of unconfirmed messages in a row, forcing every Nth as confirmed.
Arguments
-
"OTAA-REJOIN-CONFIRMED-COUNTER" (string, command)
❗command - the argument needs to have this exact form❗ -
number (integer): Max unconfirmed messages (default/minimal 5).
Example
-- Set counter to 10
api.loraSetup("OTAA-REJOIN-CONFIRMED-COUNTER", 10)
api.loraSetup("POWER", power)
api.loraSetup("POWER", 14)
Sets the power to a defined value in dBm.
Arguments
-
"POWER" (string, command)
❗command - the argument needs to have this exact form❗ -
power (integer): Power value (0, 2, 4, 6, 8, 10, 12, 14).
Example
-- Set power to 14 dBm
api.loraSetup("POWER", 14)
api.loraSetup("TIME_SYNC", force, zone)
api.loraSetup("TIME_SYNC")
Schedules a time synchronization request.
Info: Requires network server support, compatible with LoRaWAN 1.0.3+.
Arguments
-
"TIME_SYNC" (string, command)
❗command - the argument needs to have this exact form❗
Optional
- force (integer, optional):
1for force time sync.0for not forcing time sync.
- zone (string, optional): Time zone:
"UTC"for UTC time zone."LOCAL"for local time zone.
Example
-- Schedule time sync
api.loraSetup("TIME_SYNC", 1)
api.loraListenClassBC(timeout, class)
status, port, buffer = api.loraListenClassBC(10000)
Listens for messages until timeout in class B or C.
Warning: Device must be set to Class B or C and supported by the Network Server.
Arguments
- timeout (integer): Timeout in milliseconds.
Optional
- class (string, optional):
"B"- class B."C"- class C (default so not needed to be explicit).
Return
- status (integer): Positive or zero for success, negative for failure.
- port (integer):
nilor port on which the message was received. - buffer (string): Message received from LoRa.
Example
-- Listen on LoRa for a message with timeout of 10 seconds
api.loraSetup("CLASS", "C")
status, port, buffer = api.loraListenClassBC(10000)
api.loraSetCredential()
Sets one LoRa credential.
| API Name | Brief Description |
|---|---|
| api.loraSetCredential("devADDR", address) | Sets the device address (32-bit). Sends a join request automatically. |
| api.loraSetCredential("devEUI", eui) | Sets the device EUI (64-bit). Sends a join request automatically. |
| api.loraSetCredential("nwkSKey", key) | Sets the network session key (128-bit). Sends a join request automatically. |
| api.loraSetCredential("appSKey", key) | Sets the application session key (128-bit). Sends a join request automatically. |
| api.loraSetCredential("appEUI", eui) | Sets the application EUI (64-bit). Sends a join request automatically. |
api.loraSetCredential("devADDR", address)
api.loraSetCredential("devADDR", "22011221")
Sets the device address.
Info: Automatically sends a join request.
Arguments
-
"devADDR" (string, command)
❗command - the argument needs to have this exact form❗ -
address (string): 32-bit address.
Example
-- Set devADDR
api.loraSetCredential("devADDR", "22011221")
api.loraSetCredential("devEUI", eui)
api.loraSetCredential("devEUI", "3333333333333333")
Sets the device EUI.
Info: Automatically sends a join request.
Arguments
-
"devADDR" (string, command)
❗command - the argument needs to have this exact form❗ -
eui (string): 64-bit end-device identifier.
Example
-- Set devEUI
api.loraSetCredential("devEUI", "3333333333333333")
api.loraSetCredential("nwkSKey", key)
api.loraSetCredential("nwkSKey", "44444444444444444444444444444444")
Sets the network session key.
Info: Automatically sends a join request.
Arguments
-
"nwkSKey" (string, command)
❗command - the argument needs to have this exact form❗ -
key (string): 128-bit network session key.
Example
-- Set nwkSKey
api.loraSetCredential("nwkSKey", "44444444444444444444444444444444")
api.loraSetCredential("appSKey", key)
api.loraSetCredential("appSKey", "55555555555555555555555555555555")
Sets the application session key.
Info: Automatically sends a join request.
Arguments
-
"appSKey" (string, command)
❗command - the argument needs to have this exact form❗ -
key (string): 128-bit application session key.
Example
-- Set appSKey
api.loraSetCredential("appSKey", "55555555555555555555555555555555")
api.loraSetCredential("appEUI", eui)
api.loraSetCredential("appEUI", "70B344440013333")
Sets the application EUI.
Info: Automatically sends a join request.
Arguments
-
"appEUI" (string, command)
❗command - the argument needs to have this exact form❗ -
eui (string): 64-bit application identifier.
Example
-- Set appEUI
api.loraSetCredential("appEUI", "70B344440013333")
api.loraSetCredentials(devADDR, devEUI, nwsKey, appsKey, appEUI)
api.loraSetCredentials("22011221", "3333333333333333", "44444444444444444444444444444444", "55555555555555555555555555555555", "70B344440013333")
Sets LoRa credentials.
Info: Automatically sends a join request.
Arguments
- devADDR (string): 32-bit address.
- devEUI (string): 64-bit end-device identifier.
- nwsKey (string): 128-bit network session key.
- appsKey (string): 128-bit application session key.
Optional
- appEUI (string, optional): 64-bit application identifier.
Example
-- Set LoRa credentials
api.loraSetCredentials("22011221", "3333333333333333", "44444444444444444444444444444444", "55555555555555555555555555555555", "70B344440013333")
--------------------------------
if usedInterfaces == "both" or usedInterfaces == "lorawan" then
-- use SIM card number as IMSI
-- ensures join
api.loraSetCredentials("00000000", "0"..imsi, "00"..imsi..imsi, "00"..imsi..imsi, "00"..imsi..imsi)
end
api.loraGetDevEui(format)
api.loraGetDevEui("bin")
Retrieves the devEUI.
Arguments
- format (string): Output format:
"bin"- output is in binary."hex"- output is in hexagonal.
Return
- eui (string): 64-bit end-device identifier.
Example
-- Get LoRa devEUI
eui = api.loraGetDevEui("bin")
api.dumpArray(eui)
print(api.loraGetDevEui("hex"))
if tonumber(fwma) >= 2 and tonumber(fwmi) >= 14 then
local eui = api.loraGetDevEui("bin")
bootMsg = eui .. bootMsg
local euiHEX = api.loraGetDevEui("hex")
msgPrint = "devEUI: " .. euiHEX .. ", " .. msgPrint
end
api.getDeviceAddress()
api.getDeviceAddress()
Retrieves the device address.
Return
- device address (hex): 64-bit end-device identifier.
Example
-- Get LoRa device address and print it
wmbusID, _, _ = api.getDeviceAddress()
print("wMBus identification: ", string.format("0x%08X", wmbusID))