--Lua 5.4 --_G is read only, each script has a isolated _ENV --Only following modules are exported: --base, but not including collectgarbage, dofile, loadfile, load --table --string --math --utf8 --Scripts are called in main event loop thread, each call is limited to --10000 steps to prevent locking up the thread. --This example is for BCD integer storing in modbus regists (each byte 0~9) function m2b(context, mvalue) --conext: table, has 4 fields: --single: number, corresponds to "Byte order for single register" --defined for Modbus slave's parameter, 1 means "12", 2 means "21" --bigint: number, corresponds to "Byte order for big integer", 1 means -- "1234", 2 means "2143", 3 means "3412", 4 means "4321" --float: number, corresponds to "Byte order for float point", 1 means -- "1234", 2 means "2143", 3 means "3412", 4 means "4321" --regcnt: number, how many registers the Modbus value is --mvalue: string, Modbus value in bytes, the length is regcnt*2 --return BACnet value in float --In this example, we define bigint as the endian of Modbus value local endian = context.bigint local bvalue = 0.0 for i = 1, context.regcnt*2, 1 do local each = mvalue:byte(i) if each > 9 then return nil -- wrong data, we don't know how to process end if endian % 2 ~= i % 2 then -- high byte of register each = each * 10 end if endian >= 3 then -- 3 or 4 each = each * 100^(context.regcnt - (i+1)//2) else each = each * 100^((i-1)//2) end bvalue = bvalue + each end return bvalue; end function b2m(context, bvalue) --context: table, it is same as previous --bvalue: float, the BACnet value --return Modbus value in string, the length is regcnt*2 local endian = context.bigint bvalue = math.floor(bvalue + 0.5) --round if bvalue < 0 then bvalue = 0 end local mvalue = "" for i = 1, context.regcnt, 1 do local each = bvalue // (100^(context.regcnt - i)) if each > 99 then each = 99 end bvalue = bvalue - each * (100^(context.regcnt - i)) local high = each // 10 local low = each % 10 local regstr if endian % 2 == 0 then -- 2 or 4 regstr = string.char(high, low) else regstr = string.char(low, high) end if endian > 2 then --3 or 4 mvalue = mvalue .. regstr else mvalue = regstr .. mvalue end end return mvalue end --return 2 functions for conversion. The first is mandatory, from modbus to --bacnet, the second is optional, from bacnet to modbus return m2b, b2m