#118 RTU/PLC code cleanup
This commit is contained in:
@@ -7,22 +7,15 @@ local MODBUS_FCODE = types.MODBUS_FCODE
|
||||
local MODBUS_EXCODE = types.MODBUS_EXCODE
|
||||
|
||||
-- new modbus comms handler object
|
||||
---@nodiscard
|
||||
---@param rtu_dev rtu_device|rtu_rs_device RTU device
|
||||
---@param use_parallel_read boolean whether or not to use parallel calls when reading
|
||||
function modbus.new(rtu_dev, use_parallel_read)
|
||||
local self = {
|
||||
rtu = rtu_dev,
|
||||
use_parallel = use_parallel_read
|
||||
}
|
||||
|
||||
---@class modbus
|
||||
local public = {}
|
||||
|
||||
local insert = table.insert
|
||||
|
||||
-- read a span of coils (digital outputs)
|
||||
--
|
||||
-- read a span of coils (digital outputs)<br>
|
||||
-- returns a table of readings or a MODBUS_EXCODE error code
|
||||
---@nodiscard
|
||||
---@param c_addr_start integer
|
||||
---@param count integer
|
||||
---@return boolean ok, table|MODBUS_EXCODE readings
|
||||
@@ -30,20 +23,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
local tasks = {}
|
||||
local readings = {} ---@type table|MODBUS_EXCODE
|
||||
local access_fault = false
|
||||
local _, coils, _, _ = self.rtu.io_count()
|
||||
local _, coils, _, _ = rtu_dev.io_count()
|
||||
local return_ok = ((c_addr_start + count) <= (coils + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = c_addr_start + i - 1
|
||||
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
insert(tasks, function ()
|
||||
local reading, fault = self.rtu.read_coil(addr)
|
||||
local reading, fault = rtu_dev.read_coil(addr)
|
||||
if fault then access_fault = true else readings[i] = reading end
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = self.rtu.read_coil(addr)
|
||||
readings[i], access_fault = rtu_dev.read_coil(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -54,7 +47,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- run parallel tasks if configured
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
parallel.waitForAll(table.unpack(tasks))
|
||||
end
|
||||
|
||||
@@ -69,9 +62,9 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
return return_ok, readings
|
||||
end
|
||||
|
||||
-- read a span of discrete inputs (digital inputs)
|
||||
--
|
||||
-- read a span of discrete inputs (digital inputs)<br>
|
||||
-- returns a table of readings or a MODBUS_EXCODE error code
|
||||
---@nodiscard
|
||||
---@param di_addr_start integer
|
||||
---@param count integer
|
||||
---@return boolean ok, table|MODBUS_EXCODE readings
|
||||
@@ -79,20 +72,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
local tasks = {}
|
||||
local readings = {} ---@type table|MODBUS_EXCODE
|
||||
local access_fault = false
|
||||
local discrete_inputs, _, _, _ = self.rtu.io_count()
|
||||
local discrete_inputs, _, _, _ = rtu_dev.io_count()
|
||||
local return_ok = ((di_addr_start + count) <= (discrete_inputs + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = di_addr_start + i - 1
|
||||
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
insert(tasks, function ()
|
||||
local reading, fault = self.rtu.read_di(addr)
|
||||
local reading, fault = rtu_dev.read_di(addr)
|
||||
if fault then access_fault = true else readings[i] = reading end
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = self.rtu.read_di(addr)
|
||||
readings[i], access_fault = rtu_dev.read_di(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -103,7 +96,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- run parallel tasks if configured
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
parallel.waitForAll(table.unpack(tasks))
|
||||
end
|
||||
|
||||
@@ -118,9 +111,9 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
return return_ok, readings
|
||||
end
|
||||
|
||||
-- read a span of holding registers (analog outputs)
|
||||
--
|
||||
-- read a span of holding registers (analog outputs)<br>
|
||||
-- returns a table of readings or a MODBUS_EXCODE error code
|
||||
---@nodiscard
|
||||
---@param hr_addr_start integer
|
||||
---@param count integer
|
||||
---@return boolean ok, table|MODBUS_EXCODE readings
|
||||
@@ -128,20 +121,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
local tasks = {}
|
||||
local readings = {} ---@type table|MODBUS_EXCODE
|
||||
local access_fault = false
|
||||
local _, _, _, hold_regs = self.rtu.io_count()
|
||||
local _, _, _, hold_regs = rtu_dev.io_count()
|
||||
local return_ok = ((hr_addr_start + count) <= (hold_regs + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = hr_addr_start + i - 1
|
||||
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
insert(tasks, function ()
|
||||
local reading, fault = self.rtu.read_holding_reg(addr)
|
||||
local reading, fault = rtu_dev.read_holding_reg(addr)
|
||||
if fault then access_fault = true else readings[i] = reading end
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = self.rtu.read_holding_reg(addr)
|
||||
readings[i], access_fault = rtu_dev.read_holding_reg(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -152,7 +145,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- run parallel tasks if configured
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
parallel.waitForAll(table.unpack(tasks))
|
||||
end
|
||||
|
||||
@@ -167,9 +160,9 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
return return_ok, readings
|
||||
end
|
||||
|
||||
-- read a span of input registers (analog inputs)
|
||||
--
|
||||
-- read a span of input registers (analog inputs)<br>
|
||||
-- returns a table of readings or a MODBUS_EXCODE error code
|
||||
---@nodiscard
|
||||
---@param ir_addr_start integer
|
||||
---@param count integer
|
||||
---@return boolean ok, table|MODBUS_EXCODE readings
|
||||
@@ -177,20 +170,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
local tasks = {}
|
||||
local readings = {} ---@type table|MODBUS_EXCODE
|
||||
local access_fault = false
|
||||
local _, _, input_regs, _ = self.rtu.io_count()
|
||||
local _, _, input_regs, _ = rtu_dev.io_count()
|
||||
local return_ok = ((ir_addr_start + count) <= (input_regs + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = ir_addr_start + i - 1
|
||||
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
insert(tasks, function ()
|
||||
local reading, fault = self.rtu.read_input_reg(addr)
|
||||
local reading, fault = rtu_dev.read_input_reg(addr)
|
||||
if fault then access_fault = true else readings[i] = reading end
|
||||
end)
|
||||
else
|
||||
readings[i], access_fault = self.rtu.read_input_reg(addr)
|
||||
readings[i], access_fault = rtu_dev.read_input_reg(addr)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -201,7 +194,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- run parallel tasks if configured
|
||||
if self.use_parallel then
|
||||
if use_parallel_read then
|
||||
parallel.waitForAll(table.unpack(tasks))
|
||||
end
|
||||
|
||||
@@ -217,16 +210,17 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- write a single coil (digital output)
|
||||
---@nodiscard
|
||||
---@param c_addr integer
|
||||
---@param value any
|
||||
---@return boolean ok, MODBUS_EXCODE
|
||||
local function _5_write_single_coil(c_addr, value)
|
||||
local response = nil
|
||||
local _, coils, _, _ = self.rtu.io_count()
|
||||
local _, coils, _, _ = rtu_dev.io_count()
|
||||
local return_ok = c_addr <= coils
|
||||
|
||||
if return_ok then
|
||||
local access_fault = self.rtu.write_coil(c_addr, value)
|
||||
local access_fault = rtu_dev.write_coil(c_addr, value)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -240,16 +234,17 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- write a single holding register (analog output)
|
||||
---@nodiscard
|
||||
---@param hr_addr integer
|
||||
---@param value any
|
||||
---@return boolean ok, MODBUS_EXCODE
|
||||
local function _6_write_single_holding_register(hr_addr, value)
|
||||
local response = nil
|
||||
local _, _, _, hold_regs = self.rtu.io_count()
|
||||
local _, _, _, hold_regs = rtu_dev.io_count()
|
||||
local return_ok = hr_addr <= hold_regs
|
||||
|
||||
if return_ok then
|
||||
local access_fault = self.rtu.write_holding_reg(hr_addr, value)
|
||||
local access_fault = rtu_dev.write_holding_reg(hr_addr, value)
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -263,19 +258,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- write multiple coils (digital outputs)
|
||||
---@nodiscard
|
||||
---@param c_addr_start integer
|
||||
---@param values any
|
||||
---@return boolean ok, MODBUS_EXCODE
|
||||
local function _15_write_multiple_coils(c_addr_start, values)
|
||||
local response = nil
|
||||
local _, coils, _, _ = self.rtu.io_count()
|
||||
local _, coils, _, _ = rtu_dev.io_count()
|
||||
local count = #values
|
||||
local return_ok = ((c_addr_start + count) <= (coils + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = c_addr_start + i - 1
|
||||
local access_fault = self.rtu.write_coil(addr, values[i])
|
||||
local access_fault = rtu_dev.write_coil(addr, values[i])
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -291,19 +287,20 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- write multiple holding registers (analog outputs)
|
||||
---@nodiscard
|
||||
---@param hr_addr_start integer
|
||||
---@param values any
|
||||
---@return boolean ok, MODBUS_EXCODE
|
||||
local function _16_write_multiple_holding_registers(hr_addr_start, values)
|
||||
local response = nil
|
||||
local _, _, _, hold_regs = self.rtu.io_count()
|
||||
local _, _, _, hold_regs = rtu_dev.io_count()
|
||||
local count = #values
|
||||
local return_ok = ((hr_addr_start + count) <= (hold_regs + 1)) and (count > 0)
|
||||
|
||||
if return_ok then
|
||||
for i = 1, count do
|
||||
local addr = hr_addr_start + i - 1
|
||||
local access_fault = self.rtu.write_holding_reg(addr, values[i])
|
||||
local access_fault = rtu_dev.write_holding_reg(addr, values[i])
|
||||
|
||||
if access_fault then
|
||||
return_ok = false
|
||||
@@ -318,7 +315,11 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
return return_ok, response
|
||||
end
|
||||
|
||||
---@class modbus
|
||||
local public = {}
|
||||
|
||||
-- validate a request without actually executing it
|
||||
---@nodiscard
|
||||
---@param packet modbus_frame
|
||||
---@return boolean return_code, modbus_packet reply
|
||||
function public.check_request(packet)
|
||||
@@ -360,6 +361,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- handle a MODBUS TCP packet and generate a reply
|
||||
---@nodiscard
|
||||
---@param packet modbus_frame
|
||||
---@return boolean return_code, modbus_packet reply
|
||||
function public.handle_packet(packet)
|
||||
@@ -420,6 +422,7 @@ function modbus.new(rtu_dev, use_parallel_read)
|
||||
end
|
||||
|
||||
-- return a SERVER_DEVICE_BUSY error reply
|
||||
---@nodiscard
|
||||
---@param packet modbus_frame MODBUS packet frame
|
||||
---@return modbus_packet reply
|
||||
function modbus.reply__srv_device_busy(packet)
|
||||
@@ -432,6 +435,7 @@ function modbus.reply__srv_device_busy(packet)
|
||||
end
|
||||
|
||||
-- return a NEG_ACKNOWLEDGE error reply
|
||||
---@nodiscard
|
||||
---@param packet modbus_frame MODBUS packet frame
|
||||
---@return modbus_packet reply
|
||||
function modbus.reply__neg_ack(packet)
|
||||
@@ -444,6 +448,7 @@ function modbus.reply__neg_ack(packet)
|
||||
end
|
||||
|
||||
-- return a GATEWAY_PATH_UNAVAILABLE error reply
|
||||
---@nodiscard
|
||||
---@param packet modbus_frame MODBUS packet frame
|
||||
---@return modbus_packet reply
|
||||
function modbus.reply__gw_unavailable(packet)
|
||||
|
||||
Reference in New Issue
Block a user