Skip to content

Payload Parsing and Saving

In this example we will not only explain the phase of creating the scene for Payload Parsing, but also the whole preliminary phase, which consists in creating the node with its components.
At the end of the page there will also be some practical examples of currently present node models.

Create the node

The real first step consists in having to create a new node, to do this you have to click on the left menu the section "Node / Devices" and then immediately click on the option with the same name. ( For more information about the nodes click HERE )
In the new page click on the "Add Custom Node" button and then fill in the fields with your sensor data, fill the sector "Node Fields" with all the tags that will contain the value of the data sent by the sensor (example, "Temperature", "Humidity", etc.) and then save.
Keep in mind, however, that the "Latitude", "Longitude", and "Altitude" tags will be created automatically, so if you need to serve one or more of these tags, you do not need to add them.
Reopen the node and go down until you find the field called "Payload parsing scene mode", click it and select the Manual Lua Scene option, and at this point you should find yourself with a very large field where you can write your code.

How to create the scene

  • Step 1: Get the initial data Each scene for parsing the node payload always starts like this:
    Origin = resiot_startfrom() -- Variable that contains a string to understand from which origin the scene started
    if Origin == "Manual" then -- This scene was started manually by clicking the "play" button below this screen
        -- If the scene has been started manually then these test values are taken into account
        AppEUI = "0102030405060708"
        DevEUI = "0102030405060708"
        Port = "1"
        Payload = resiot_hexdecode("07FB04BA")
    else -- If the scene has not been started manually
        -- In this case, the function "resiot_comm_getparam" is used to obtain the data of the node that can be used later
        AppEUI = resiot_comm_getparam("appeui") -- To derive the value of the Application EUI you have to write "appeui" inside the function
        DevEUI = resiot_comm_getparam("deveui") -- To derive the value of the Device EUI you have to write "deveui" inside the function
        Port = resiot_comm_getparam("port") -- To know from which door the message has been sent, write "port"
        -- To get the payload just arrived write "payload" inside the function, however this returns the payload in string format, 
        -- so to get instead an array of Bytes we must add the function "resiot_hexdecode" as shown below
        Payload = resiot_hexdecode(resiot_comm_getparam("payload"))
    end
  • Step 2: Get the data from the Payload The second step consists in obtaining the data that will then be processed to obtain the desired values.
    Here are some functions that are usually used:
    ByteArray2 = {Payload[1],Payload[2]}
    ByteArray4 = {Payload[1],Payload[2],Payload[3],Payload[4]}
    -- Functions "resiot_ba2int" to convert an array of Bytes into an integer

    ValueBE16 = resiot_ba2intBE16(ByteArray2) -- Converts two Bytes in BigEndian format
    resiot_debug(ValueBE16)  --This is the returned value: 22043
    ValueBE32 = resiot_ba2intBE32(ByteArray4) -- Converts four Bytes in BigEndian format
    resiot_debug(ValueBE32)  --This is the returned value: 133891257
    --But this is how it's showed: 1.33891257e+08
    ValueLE16 = resiot_ba2intLE16(ByteArray2) -- Converts two Bytes in LittleEndian format
    resiot_debug(ValueBE16) --This is the returned value: 64263
    ValueLE32 = resiot_ba2intLE32(ByteArray4) -- Converts four Bytes in LittleEndian format
    resiot_debug(ValueBE32)  --This is the returned value: 3104111367
    --But this is how it's showed: 3.104111367e+09

    -- Functions "resiot_ba2float32" to convert four Bytes into a float value

    ValueF32BE = resiot_ba2float32BE(ByteArray4) -- Converts four Bytes in BigEndian format
    resiot_debug(ByteArray4)  --This is the returned value:3.776905823108983e-34
    ValueF32LE = resiot_ba2float32LE(ByteArray4) -- Converts four Bytes in LittleEndian format
    resiot_debug(ByteArray4)  --This is the returned value: -0.00012682015949394554

    -- Function to read a bit inside of a Byte, it will return "true" if the bit is 1 or "false" on the other case
    Byte=Payload[3]
    Index=2
    BitValue = resiot_readbit(Byte, Index)
    -- 0x33 = 0 0 1 1 0 0 1 1 -- Example of Byte
    -- Index  0 1 2 3 4 5 6 7 -- Index value for bit position
  • Step 3: Process the data obtained (if necessary) If the data obtained in step 2 must be further processed, this is done during this step.

  • Step 4: Save the final values within the Node Tags Last step, at the end of all calculations, the values obtained must be saved inside the node tags.
    The functions to perform this action are 2:

    AllWorked, Error = resiot_setnodevalue(AppEUI, DevEUI, TagName, Value)

    -- The resiot_setnodevalue function allows you to save a value within a tag, and the tag name 
    -- can be found under the "Field Tag" column in the "Node Fields" section of a node.
    -- The variable "Value" must be of string type, in case it is not, you can convert it using the internal function of lua "tostring ()".
    -- Example: resiot_setnodevalue(AppEUI, DevEUI, TagName, tostring(Value))
    -- The function return 2 values:
    --
    -- AllWorked = Boolean value that is true when everything went well
    -- Error = if AllWorked is false the error message is written here

    Date = os.time() - 14400
    AllWorked, Error = resiot_setnodevaluewithtime(AppEUI, DevEUI, Tag, Value, Date)

    -- The resiot_setnodevaluewithtime function is the same thing as the other one, 
    -- the only difference is that with this one you can decide at what time save the value.
    -- The Variable "Date" is the date in Epoch format, that is, the date expressed in seconds.
    -- To configure this variable you need to use the function "os.time()" to get the current Epoch, 
    -- and then subtract the time of difference to the date you want to save the value in.
    -- Example:
    --
    -- 1 Hour ago: Date = os.time() - 3600 -- 3600 is 1 Hour in seconds
    -- 2 Hours ago: Date = os.time() - 7200 -- 7200 is 2 Hours in seconds
    -- 12 Hours ago: Date = os.time() - 43200 -- 43200 is 12 Hours in seconds
    -- 1 Day ago: Date = os.time() - 86400 -- 86400 is 1 Day in seconds
    -- 1 Week ago: Date = os.time() - 604800 -- 604800 is 1 Week in seconds

Practical Examples

Model GlobalSat LT100 Parsing Scene Example

  • Node Fields

Table

  • Parsing Scene
-- Step 1:
LDSourceOrigin = resiot_startfrom()

if LDSourceOrigin == "Manual" then 
    Payload = resiot_hexdecode("")
    Port = "99"
    DevEUI = ""
    AppEUI = ""
else
    Payload, err = resiot_hexdecode(resiot_comm_getparam("payload"))
    Port = resiot_comm_getparam("port")
    DevEUI = resiot_payload_getparam("deveui")
    AppEUI = resiot_payload_getparam("appeui")
end

-- Step 2:

GPSFixStatus1 = resiot_readbit(Payload[2], 0)
GPSFixStatus2 = resiot_readbit(Payload[2], 1)
GPSFixStatus = ""

ReportType1 = resiot_readbit(Payload[2], 2)
ReportType2 = resiot_readbit(Payload[2], 3)
ReportType3 = resiot_readbit(Payload[2], 4)
ReportType4 = resiot_readbit(Payload[2], 5)
ReportType5 = resiot_readbit(Payload[2], 6)
ReportType6 = resiot_readbit(Payload[2], 7)
ReportType = 0
ReportTypeStr = ""

Battery = Payload[3] -- MU: %

Latitude = resiot_ba2intBE32({Payload[4], Payload[5], Payload[6], Payload[7]}) * 0.000001 -- MU: degree (°)
Longitude = resiot_ba2intBE32({Payload[8], Payload[9], Payload[10], Payload[11]}) * 0.000001 -- MU: degree (°)

-- Step 3:

if GPSFixStatus1 == false and GPSFixStatus2 == false then
    GPSFixStatus = "Not Fix"
elseif GPSFixStatus1 and GPSFixStatus2 == false then
    GPSFixStatus = "3D"
elseif GPSFixStatus1 == false and GPSFixStatus2 then
    GPSFixStatus = "2D"
end

if ReportType6 then
    ReportType = ReportType + 1
end
if ReportType5 then
    ReportType = ReportType + 2
end
if ReportType4 then
    ReportType = ReportType + 4
end
if ReportType3 then
    ReportType = ReportType + 8
end
if ReportType2 then
    ReportType = ReportType + 16
end
if ReportType1 then
    ReportType = ReportType + 32
end

if ReportType == 2 then
    ReportTypeStr = "Periodic mode report"
elseif ReportType == 4 then
    ReportTypeStr = "Motion mode static report"
elseif ReportType == 5 then
    ReportTypeStr = "Motion mode moving report"
elseif ReportType == 6 then
    ReportTypeStr = "Motion mode static to motion report"
elseif ReportType == 7 then
    ReportTypeStr = "Motion mode moving to static report"
elseif ReportType == 14 then
    ReportTypeStr = "SOS alarm report"
    resiot_raiseevent(AppEUI, DevEUI, "SOS")
elseif ReportType == 15 then
    ReportTypeStr = "Low battery alarm report"
    resiot_raiseevent(AppEUI, DevEUI, "Low_Battery")
elseif ReportType == 17 then
    ReportTypeStr = "Power on(temperature)"
elseif ReportType == 19 then
    ReportTypeStr = "Power off(low battery)"
elseif ReportType == 20 then
    ReportTypeStr = "Power off(temperature)"
end

-- Step 4:

resiot_setnodevalue(AppEUI, DevEUI, "GPS_Fix_Status", GPSFixStatus)
resiot_setnodevalue(AppEUI, DevEUI, "Report_Type", tostring(ReportType))
resiot_setnodevalue(AppEUI, DevEUI, "Report_Type_Str", ReportTypeStr)
resiot_setnodevalue(AppEUI, DevEUI, "Battery", tostring(Battery))
resiot_setlatitudelongitude(AppEUI, DevEUI, Latitude, Longitude)