579 lines
17 KiB
Lua
579 lines
17 KiB
Lua
|
|
--
|
||
|
|
-- liuyognsheng 2023.4.20
|
||
|
|
--
|
||
|
|
-- port 44818 and ( UDP or TCP )
|
||
|
|
-- header size == 24
|
||
|
|
--
|
||
|
|
--
|
||
|
|
--
|
||
|
|
--
|
||
|
|
--
|
||
|
|
|
||
|
|
function loga(...)
|
||
|
|
if (run_mode == "debug") then
|
||
|
|
print(...)
|
||
|
|
else
|
||
|
|
APP.log_debug(...)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
function APPdataDump()
|
||
|
|
--ret = "";
|
||
|
|
--for i = 1,#APP.data do
|
||
|
|
-- ret = ret..string.format("%02x ",string.byte(APP.data,i,i + 1))
|
||
|
|
--end
|
||
|
|
ret1,ret2 = string.byte(APP.data,5,7)
|
||
|
|
loga("APP.data:",type(ret1),ret1,ret2)
|
||
|
|
end
|
||
|
|
function file2byte(filename)
|
||
|
|
local file = io.open(filename, "rb")
|
||
|
|
if (file == nil ) then
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
io.input(file)
|
||
|
|
local ret = io.read("*a")
|
||
|
|
io.close(file)
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
function byte_unpack(a , b ,c)
|
||
|
|
--print(debug.traceback())
|
||
|
|
if (string.len(a) < c) then
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
return string.byte(a , b , c)
|
||
|
|
end
|
||
|
|
|
||
|
|
function byte_unpack_1(data)
|
||
|
|
local ret = byte_unpack(data , offset,offset)
|
||
|
|
offset = offset + 1
|
||
|
|
--loga("offset=",offset)
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
function byte_unpack_2(data)
|
||
|
|
--print(debug.traceback())
|
||
|
|
local ret1,ret2 = byte_unpack(data , offset , offset + 1)
|
||
|
|
local ret = ret1*256 + ret2
|
||
|
|
--loga(string.format("data[%d,%d] = %x",offset , offset +1,ret))
|
||
|
|
offset = offset + 2
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
function byte_unpack_4(data , offset)
|
||
|
|
local ret1,ret2,ret3,ret4 = byte_unpack(data , offset , offset + 3)
|
||
|
|
offset = offset + 4
|
||
|
|
local ret = ret1*256*256*256 + ret2*256*256 + ret3*256 + ret4
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
function Xor(num1,num2)
|
||
|
|
local tmp1 = num1
|
||
|
|
local tmp2 = num2
|
||
|
|
local str = ""
|
||
|
|
repeat
|
||
|
|
local s1 = tmp1 % 2
|
||
|
|
local s2 = tmp2 % 2
|
||
|
|
if s1 == s2 then
|
||
|
|
str = "0"..str
|
||
|
|
else
|
||
|
|
str = "1"..str
|
||
|
|
end
|
||
|
|
tmp1 = math.modf(tmp1/2)
|
||
|
|
tmp2 = math.modf(tmp2/2)
|
||
|
|
until(tmp1 == 0 and tmp2 == 0)
|
||
|
|
return tonumber(str,2)
|
||
|
|
end
|
||
|
|
|
||
|
|
function And(num1,num2)
|
||
|
|
local tmp1 = num1
|
||
|
|
local tmp2 = num2
|
||
|
|
local str = ""
|
||
|
|
repeat
|
||
|
|
local s1 = tmp1 % 2
|
||
|
|
local s2 = tmp2 % 2
|
||
|
|
if s1 == s2 then
|
||
|
|
if s1 == 1 then
|
||
|
|
str = "1"..str
|
||
|
|
else
|
||
|
|
str = "0"..str
|
||
|
|
end
|
||
|
|
else
|
||
|
|
str = "0"..str
|
||
|
|
end
|
||
|
|
tmp1 = math.modf(tmp1/2)
|
||
|
|
tmp2 = math.modf(tmp2/2)
|
||
|
|
until(tmp1 == 0 and tmp2 == 0)
|
||
|
|
return tonumber(str,2)
|
||
|
|
end
|
||
|
|
|
||
|
|
function Or(num1,num2)
|
||
|
|
local tmp1 = num1
|
||
|
|
local tmp2 = num2
|
||
|
|
local str = ""
|
||
|
|
repeat
|
||
|
|
local s1 = tmp1 % 2
|
||
|
|
local s2 = tmp2 % 2
|
||
|
|
if s1 == s2 then
|
||
|
|
if s1 == 0 then
|
||
|
|
str = "0"..str
|
||
|
|
else
|
||
|
|
str = "1"..str
|
||
|
|
end
|
||
|
|
else
|
||
|
|
str = "1"..str
|
||
|
|
end
|
||
|
|
tmp1 = math.modf(tmp1/2)
|
||
|
|
tmp2 = math.modf(tmp2/2)
|
||
|
|
until(tmp1 == 0 and tmp2 == 0)
|
||
|
|
return tonumber(str,2)
|
||
|
|
end
|
||
|
|
|
||
|
|
|
||
|
|
run_mode = "release"
|
||
|
|
D_prefix = "D"
|
||
|
|
local function str2data(str)
|
||
|
|
local i = 1;
|
||
|
|
local len = string.len(str)
|
||
|
|
local ret = {}
|
||
|
|
for pos = 1 , len ,2 do
|
||
|
|
ret[i] = tonumber(string.sub(str, pos,pos+1),16)
|
||
|
|
i = i + 1
|
||
|
|
end
|
||
|
|
return ret
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
local function datadump(indata)
|
||
|
|
for i, v in ipairs(indata) do
|
||
|
|
loga(indata[i])
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
-- create test env
|
||
|
|
local function testenv()
|
||
|
|
APP = { context = {appname = nil }}
|
||
|
|
--APP.data = str2data("6f0016000001021200000000d36d8601701ee10000000000000000000500020000000000b20006008e0000000200")
|
||
|
|
APP.data = file2byte("./modbus.bin")
|
||
|
|
APP.append_extra_info = loga
|
||
|
|
run_mode = "debug"
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
---------------------- Modbus start -----------------------
|
||
|
|
---
|
||
|
|
--- 0 1 2
|
||
|
|
-- unknow yes no
|
||
|
|
--
|
||
|
|
local app_define= {}
|
||
|
|
app_define["HEAD_LEN"] = 7
|
||
|
|
app_define["PDU_MIN_LEN"] = 2
|
||
|
|
app_define["PDU_MAX_LEN"] = 254
|
||
|
|
app_define["PORT"] = 502
|
||
|
|
app_define["FUNC"] = {}
|
||
|
|
|
||
|
|
app_define["FUNC"][0x01] = { desc="FUNC_READCOILS",read=1 , write=0}
|
||
|
|
app_define["FUNC"][0x02] = {desc="FUNC_READDISCINPUTS",read=1 , write=0}
|
||
|
|
app_define["FUNC"][0x03] = {desc="FUNC_READHOLDREGS",read=1 , write=0}
|
||
|
|
app_define["FUNC"][0x04] = {desc="FUNC_READINPUTREGS",read=1 , write=0}
|
||
|
|
app_define["FUNC"][0x05] = {desc="FUNC_WRITESINGLECOIL",read=0 , write=1}
|
||
|
|
app_define["FUNC"][0x06] = {desc="FUNC_WRITESINGLEREG",read=0 , write=1}
|
||
|
|
app_define["FUNC"][0x07] = {desc="FUNC_READEXCSTATUS"}
|
||
|
|
app_define["FUNC"][0x08] = {desc="FUNC_DIAGNOSTIC"}
|
||
|
|
app_define["FUNC"][0x0b] = {desc="FUNC_GETCOMEVTCOUNTER"}
|
||
|
|
app_define["FUNC"][0x0c] = {desc="FUNC_GETCOMEVTLOG"}
|
||
|
|
app_define["FUNC"][0x0f] = {desc="FUNC_WRITEMULTCOILS",read=0 , write=1}
|
||
|
|
app_define["FUNC"][0x10] = {desc="FUNC_WRITEMULTREGS",read=0 , write=1}
|
||
|
|
app_define["FUNC"][0x11] = {desc="FUNC_REPORTSERVERID"}
|
||
|
|
app_define["FUNC"][0x14] = {desc="FUNC_READFILERECORD"}
|
||
|
|
app_define["FUNC"][0x15] = {desc="FUNC_WRITEFILERECORD"}
|
||
|
|
app_define["FUNC"][0x16] = {desc="FUNC_MASKWRITEREG",read=0 , write=1}
|
||
|
|
app_define["FUNC"][0x17] = {desc="FUNC_READWRITEMULTREGS",read=1 , write=1}
|
||
|
|
app_define["FUNC"][0x18] = {desc="FUNC_READFIFOQUEUE"}
|
||
|
|
app_define["FUNC"][0x2b] = {desc="FUNC_ENCAPINTTRANS"}
|
||
|
|
app_define["FUNC"][0x7f] = {desc="FUNC_MASK"}
|
||
|
|
app_define["FUNC"][0x80] = {desc="FUNC_ERRORMASK"}
|
||
|
|
|
||
|
|
app_define["SUB_FUNC"] = {
|
||
|
|
{func=0x00,desc="SUBFUNC_QUERY_DATA"},
|
||
|
|
{func=0x01,desc="SUBFUNC_RESTART_COM"},
|
||
|
|
{func=0x02,desc="SUBFUNC_DIAG_REGS"},
|
||
|
|
{func=0x03,desc="SUBFUNC_CHANGE_DELIMITER"},
|
||
|
|
{func=0x04,desc="SUBFUNC_LISTEN_MODE"},
|
||
|
|
{func=0x0a,desc="SUBFUNC_CLEAR_REGS"},
|
||
|
|
{func=0x0b,desc="SUBFUNC_BUS_MSG_COUNT"},
|
||
|
|
{func=0x0c,desc="SUBFUNC_COM_ERR_COUNT"},
|
||
|
|
{func=0x0d,desc="SUBFUNC_EXCEPT_ERR_COUNT"},
|
||
|
|
{func=0x0e,desc="SUBFUNC_SERVER_MSG_COUNT"},
|
||
|
|
{func=0x0f,desc="SUBFUNC_SERVER_NO_RSP_COUNT"},
|
||
|
|
{func=0x10,desc="SUBFUNC_SERVER_NAK_COUNT"},
|
||
|
|
{func=0x11,desc="SUBFUNC_SERVER_BUSY_COUNT"},
|
||
|
|
{func=0x12,desc="SUBFUNC_SERVER_CHAR_COUNT"},
|
||
|
|
{func=0x14,desc="SUBFUNC_CLEAR_COUNT"},
|
||
|
|
}
|
||
|
|
|
||
|
|
local function is_modbus()
|
||
|
|
if (APP.context.appname == nil) then
|
||
|
|
return 0
|
||
|
|
end
|
||
|
|
|
||
|
|
if (APP.context.not_modbus== 1) then
|
||
|
|
return 2
|
||
|
|
elseif (APP.context.appname == "modbus") then
|
||
|
|
return 1
|
||
|
|
end
|
||
|
|
|
||
|
|
return 0
|
||
|
|
end
|
||
|
|
|
||
|
|
-- 合法性检测
|
||
|
|
local function ModbusChk()
|
||
|
|
if (APP.context.seq == nil) then
|
||
|
|
APP.context.seq = 1
|
||
|
|
else
|
||
|
|
APP.context.seq = APP.context.seq + 1
|
||
|
|
end
|
||
|
|
if (APP.data == nil or string.len(APP.data) < app_define["HEAD_LEN"]) then
|
||
|
|
loga("not modbus !!!")
|
||
|
|
APP.context.not_modbus = 1
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
local function ModbusDumpData(tx)
|
||
|
|
local ret = ""
|
||
|
|
--print(debug.traceback(),tx.data,tx.data["D1"])
|
||
|
|
for i, v in pairs(tx.data) do
|
||
|
|
--loga("ModbusDumpData in for",i,v)
|
||
|
|
ret = ret..(string.format("%02x",tx.data[i]))
|
||
|
|
end
|
||
|
|
return ret
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseHeader()
|
||
|
|
local header = {}
|
||
|
|
|
||
|
|
header.transaction_id = byte_unpack_2(APP.data)
|
||
|
|
header.protocol_id = byte_unpack_2(APP.data)
|
||
|
|
header.length = byte_unpack_2(APP.data)
|
||
|
|
header.unit_id = byte_unpack_1(APP.data)
|
||
|
|
loga(string.format("transaction_id %x protocol_id %x length %x unit_id %x offset:%d",header.transaction_id,header.protocol_id,header.length,header.unit_id,offset))
|
||
|
|
return header
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusCheckHeader( header )
|
||
|
|
if (header.protocol_id ~= 0) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid protocol id"
|
||
|
|
end
|
||
|
|
|
||
|
|
if ((header.length < app_define["PDU_MIN_LEN"])
|
||
|
|
or (header.length > app_define["PDU_MAX_LEN"])) then
|
||
|
|
loga(header.length)
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid length"
|
||
|
|
end
|
||
|
|
|
||
|
|
if ((header.unit_id > 247) and (header.unit_id < 255) ) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid unit identifier"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseReadRequest()
|
||
|
|
local ret = 0
|
||
|
|
modbus.tx.read = {}
|
||
|
|
modbus.tx.read.address = byte_unpack_2(APP.data)
|
||
|
|
modbus.tx.read.quantity = byte_unpack_2(APP.data)
|
||
|
|
if (And(modbus.tx.read.quantity , 0x0c) ~= 0 ) then
|
||
|
|
if (modbus.tx.read.quantity == 0 or modbus.tx.read.quantity > 2000) then
|
||
|
|
ret = 1
|
||
|
|
end
|
||
|
|
else
|
||
|
|
if (modbus.tx.read.quantity == 0 or modbus.tx.read.quantity > 125) then
|
||
|
|
ret = 1
|
||
|
|
end
|
||
|
|
end
|
||
|
|
if (ret == 1) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid decoder invalid value"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseWriteRequest()
|
||
|
|
modbus.tx.write = {}
|
||
|
|
modbus.tx.write.count = 0
|
||
|
|
modbus.tx.write.address = byte_unpack_2(APP.data)
|
||
|
|
loga("modbus.tx.write.address:",modbus.tx.write.address)
|
||
|
|
loga("modbus.tx.func:",modbus.tx.func)
|
||
|
|
if (string.find(app_define["FUNC"][modbus.tx.func].desc,"SINGLE") ~= nil) then
|
||
|
|
modbus.tx.write.quantity = 1
|
||
|
|
elseif (string.find(app_define["FUNC"][modbus.tx.func].desc,"MUL") ~= nil) then
|
||
|
|
modbus.tx.write.quantity = byte_unpack_2(APP.data)
|
||
|
|
modbus.tx.write.count = byte_unpack_1(APP.data , offset)
|
||
|
|
if ( modbus.tx.write.quantity == nil or modbus.tx.write.count == nil) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid decoder invalid value"
|
||
|
|
return
|
||
|
|
end
|
||
|
|
else
|
||
|
|
modbus.tx.write.quantity = 2
|
||
|
|
end
|
||
|
|
--get data
|
||
|
|
modbus.tx.data = {}
|
||
|
|
-- get last info , max 20
|
||
|
|
for key_name = 1,20 do
|
||
|
|
local tmp = byte_unpack_1(APP.data , offset)
|
||
|
|
if (tmp == nil) then
|
||
|
|
break
|
||
|
|
end
|
||
|
|
--loga("key_name:",key_name , "tmp:",tmp)
|
||
|
|
modbus.tx.data[D_prefix..key_name] = tmp
|
||
|
|
end
|
||
|
|
loga(ModbusDumpData(modbus.tx))
|
||
|
|
return
|
||
|
|
|
||
|
|
--[[
|
||
|
|
if (string.find(app_define["FUNC"][modbus.tx.func].desc,"COILS") ~= nil) then
|
||
|
|
if (string.find(app_define["FUNC"][modbus.tx.func].desc,"SINGLE") ~= nil) then
|
||
|
|
tx.data[D_prefix..key_name] = byte_unpack_2(APP.data)
|
||
|
|
key_name = key_name + 1
|
||
|
|
loga("1")
|
||
|
|
else
|
||
|
|
for pos=1 , modbus.tx.write.count do
|
||
|
|
modbus.tx.data[D_prefix..key_name] = byte_unpack_1(APP.data , offset)
|
||
|
|
key_name = key_name + 1
|
||
|
|
loga("2")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
else
|
||
|
|
for pos=1 , modbus.tx.write.count do
|
||
|
|
modbus.tx.data[D_prefix..key_name] = byte_unpack_2(APP.data)
|
||
|
|
key_name = key_name + 1
|
||
|
|
loga("3")
|
||
|
|
end
|
||
|
|
end
|
||
|
|
ModbusDumpData(modbus.tx)
|
||
|
|
]]
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseRequestPDU()
|
||
|
|
modbus.tx.func = byte_unpack_1(APP.data , offset)
|
||
|
|
loga("modbus.tx.func:",modbus.tx.func)
|
||
|
|
if (modbus.tx.func == 0x00) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid function code"
|
||
|
|
return false
|
||
|
|
elseif (app_define["FUNC"][modbus.tx.func] == nil) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid function code"
|
||
|
|
return false
|
||
|
|
elseif ((app_define["FUNC"][modbus.tx.func].desc == "FUNC_READFILERECORD"
|
||
|
|
or app_define["FUNC"][modbus.tx.func].desc == "FUNC_WRITEFILERECORD") ) then
|
||
|
|
local tmp1 = byte_unpack_1(APP.data , offset)
|
||
|
|
elseif (app_define["FUNC"][modbus.tx.func].desc == "FUNC_DIAGNOSTIC" ) then
|
||
|
|
modbus.tx.subfunc = byte_unpack_2(APP.data)
|
||
|
|
local data = byte_unpack_2(APP.data)
|
||
|
|
elseif (app_define["FUNC"][modbus.tx.func].desc == "FUNC_ENCAPINTTRANS" ) then
|
||
|
|
local tmp1 = byte_unpack_1(APP.data , offset)
|
||
|
|
end
|
||
|
|
|
||
|
|
if (app_define["FUNC"][modbus.tx.func].read == 1) then
|
||
|
|
ModbusParseReadRequest()
|
||
|
|
modbus.tx.action = "read"
|
||
|
|
end
|
||
|
|
|
||
|
|
if (app_define["FUNC"][modbus.tx.func].write == 1) then
|
||
|
|
ModbusParseWriteRequest()
|
||
|
|
if (modbus.tx.action == nil) then
|
||
|
|
modbus.tx.action = "write"
|
||
|
|
else
|
||
|
|
modbus.tx.action = "|write"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseReadResponse()
|
||
|
|
modbus.tx.read = {}
|
||
|
|
modbus.tx.read.count = byte_unpack_1(APP.data , offset)
|
||
|
|
if (modbus.tx.read.count == nil ) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid decoder invalid value"
|
||
|
|
return
|
||
|
|
end
|
||
|
|
loga("ModbusParseReadResponse",modbus.tx.read.count,modbus.req_tx.read.quantity)
|
||
|
|
if (modbus.tx.read.count == 2*modbus.req_tx.read.quantity
|
||
|
|
or modbus.tx.read.count == (modbus.req_tx.read.quantity + 7)/8) then
|
||
|
|
modbus.tx.data = {}
|
||
|
|
loga("modbus.tx.read.count :",modbus.tx.read.count)
|
||
|
|
if (modbus.tx.func == 1 or modbus.tx.func == 2) then
|
||
|
|
for i = 1 , modbus.tx.read.count do
|
||
|
|
modbus.tx.data[#modbus.tx.data + 1] = byte_unpack_1(APP.data)
|
||
|
|
end
|
||
|
|
else
|
||
|
|
for i = 1 , modbus.tx.read.count/2 do
|
||
|
|
--loga("#modbus.tx.data:",#modbus.tx.data)
|
||
|
|
modbus.tx.data[#modbus.tx.data + 1] = byte_unpack_2(APP.data)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseWriteResponse()
|
||
|
|
modbus.tx.write = {}
|
||
|
|
modbus.tx.write.address = byte_unpack_2(APP.data)
|
||
|
|
if (modbus.tx.write.address ~= modbus.req_tx.write.address) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid decoder invalid address"
|
||
|
|
return
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseResponsePDU()
|
||
|
|
modbus.tx.func = byte_unpack_1(APP.data)
|
||
|
|
if (modbus.tx.func == 0x00) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid function code"
|
||
|
|
return
|
||
|
|
elseif (app_define["FUNC"][modbus.tx.func] == nil) then
|
||
|
|
modbus.event[#modbus.event + 1] = "invalid function code"
|
||
|
|
return
|
||
|
|
elseif ( app_define["FUNC"][modbus.tx.func].desc == "FUNC_READFILERECORD"
|
||
|
|
or app_define["FUNC"][modbus.tx.func].desc == "FUNC_WRITEFILERECORD" ) then
|
||
|
|
local tmp1 = byte_unpack_1(APP.data , offset)
|
||
|
|
end
|
||
|
|
if (app_define["FUNC"][modbus.tx.func].read == 1) then
|
||
|
|
ModbusParseReadResponse()
|
||
|
|
modbus.tx.action = "read"
|
||
|
|
end
|
||
|
|
if (app_define["FUNC"][modbus.tx.func].write == 1) then
|
||
|
|
ModbusParseWriteResponse()
|
||
|
|
if (modbus.tx.action == nil) then
|
||
|
|
modbus.tx.action = "write"
|
||
|
|
else
|
||
|
|
modbus.tx.action = "|write"
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
local function ModbustxFindbyid(findid)
|
||
|
|
if (APP.context.modbus == nil ) then
|
||
|
|
loga("APP.context.modbus == nil")
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
loga("findid : ", findid)
|
||
|
|
for k , v in pairs(APP.context.modbus) do
|
||
|
|
loga("findidBy:", k ,type(v.tx.header.transaction_id)," id:", v.tx.header.transaction_id)
|
||
|
|
if (findid == v.tx.header.transaction_id) then
|
||
|
|
return v.tx
|
||
|
|
end
|
||
|
|
|
||
|
|
end
|
||
|
|
return nil
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusUpdate(modbus)
|
||
|
|
for k , v in pairs(APP.context.modbus) do
|
||
|
|
if (modbus.tx.header.transaction_id == v.tx.header.transaction_id) then
|
||
|
|
loga("ModbusUpdate ",modbus.tx.func)
|
||
|
|
APP.context.modbus[k] = modbus
|
||
|
|
end
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusAddtx(modbus)
|
||
|
|
local search_tx = ModbustxFindbyid(modbus.tx.header.transaction_id)
|
||
|
|
loga("ModbusAddtx",modbus.tx.func)
|
||
|
|
if (APP.context.modbus == nil) then
|
||
|
|
APP.context.modbus = {}
|
||
|
|
APP.context.modbusNum = 1
|
||
|
|
elseif (search_tx == nil) then
|
||
|
|
APP.context.modbusNum = APP.context.modbusNum + 1
|
||
|
|
else
|
||
|
|
ModbusUpdate(modbus)
|
||
|
|
return
|
||
|
|
end
|
||
|
|
APP.context.modbus["m"..APP.context.modbusNum] = modbus
|
||
|
|
loga("ModbusAddtx ",APP.context.modbusNum ," APP.context.modbus ")
|
||
|
|
if (APP.context.modbus == nil) then
|
||
|
|
loga("APP.context.modbus == nil")
|
||
|
|
else
|
||
|
|
loga("tx.header.transaction_id: ",APP.context.modbus.m1.tx.header.transaction_id)
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
local function ModbusParseRequest()
|
||
|
|
if (not ModbusChk()) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
modbus = {tx = {},event = {}}
|
||
|
|
header = ModbusParseHeader()
|
||
|
|
ModbusCheckHeader(header)
|
||
|
|
|
||
|
|
if (#modbus.event >0) then
|
||
|
|
loga(modbus.event[1])
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
modbus.tx.header = header
|
||
|
|
ModbusParseRequestPDU()
|
||
|
|
if (#modbus.event >0) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
ModbusAddtx(modbus)
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
local function ModbusParseResponse()
|
||
|
|
if (not ModbusChk()) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
|
||
|
|
modbus = {tx = {},event = {}}
|
||
|
|
|
||
|
|
header = ModbusParseHeader()
|
||
|
|
ModbusCheckHeader(header)
|
||
|
|
if (#modbus.event >0) then
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
-- find tx
|
||
|
|
tx = ModbustxFindbyid(header.transaction_id)
|
||
|
|
if (tx == nil ) then
|
||
|
|
loga("Error: not find transaction id")
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
modbus.req_tx = tx
|
||
|
|
modbus.tx.length = header.length
|
||
|
|
ModbusParseResponsePDU()
|
||
|
|
if (#modbus.event >0) then
|
||
|
|
loga("Error : ",modbus.event[1])
|
||
|
|
return false
|
||
|
|
end
|
||
|
|
APP.append_extra_info("app_type","Modbus")
|
||
|
|
APP.append_extra_info("action",modbus.req_tx.action)
|
||
|
|
--loga("###################")
|
||
|
|
if (string.find(modbus.tx.action , "read") ~= nil) then
|
||
|
|
APP.append_extra_info("address",modbus.req_tx.read.address)
|
||
|
|
APP.append_extra_info("quantity",modbus.req_tx.read.quantity)
|
||
|
|
APP.append_extra_info("data",ModbusDumpData(modbus.tx))
|
||
|
|
else
|
||
|
|
APP.append_extra_info("address",modbus.tx.write.address)
|
||
|
|
APP.append_extra_info("quantity",modbus.req_tx.write.quantity)
|
||
|
|
APP.append_extra_info("data",ModbusDumpData(modbus.req_tx))
|
||
|
|
end
|
||
|
|
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
|
||
|
|
---------------------- Modbus end -----------------------
|
||
|
|
|
||
|
|
--testenv()
|
||
|
|
--for APP.data
|
||
|
|
--datadump(APP.data)
|
||
|
|
--
|
||
|
|
|
||
|
|
--miss null data
|
||
|
|
if (string.len(APP.data) == 0) then
|
||
|
|
return true
|
||
|
|
end
|
||
|
|
offset = 1
|
||
|
|
if(APP.get_payload_direction()==1) then
|
||
|
|
--loga("request")
|
||
|
|
return ModbusParseRequest()
|
||
|
|
elseif (APP.get_payload_direction()==2) then
|
||
|
|
--loga("response")
|
||
|
|
return ModbusParseResponse()
|
||
|
|
end
|