#559 supervisor updates to handle busy errors
This commit is contained in:
parent
1190fe2dd5
commit
cd4caf0163
@ -105,27 +105,39 @@ function boilerv.new(session_id, unit_id, advert, out_queue)
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query if the multiblock is formed
|
||||
local function _request_formed()
|
||||
---@param time_now integer
|
||||
local function _request_formed(time_now)
|
||||
-- read discrete input 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
end
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 12 (start = 1, count = 12)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 12 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 12 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read input registers 13 through 15 (start = 13, count = 3)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 13, 3 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 13, 3 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 16 through 27 (start = 16, count = 12)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 16, 12 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 16, 12 }) ~= false then
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -210,26 +222,12 @@ function boilerv.new(session_id, unit_id, advert, out_queue)
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if self.periodics.next_formed_req <= time_now then
|
||||
_request_formed()
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
if self.periodics.next_formed_req <= time_now then _request_formed(time_now) end
|
||||
|
||||
if self.db.formed then
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
|
||||
@ -42,6 +42,8 @@ local PERIODICS = {
|
||||
TANKS = 500
|
||||
}
|
||||
|
||||
local WRITE_BUSY_WAIT = 1000
|
||||
|
||||
-- create a new dynamicv rtu session runner
|
||||
---@nodiscard
|
||||
---@param session_id integer RTU gateway session ID
|
||||
@ -63,6 +65,8 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
|
||||
local self = {
|
||||
session = unit_session.new(session_id, unit_id, advert, out_queue, log_tag, TXN_TAGS),
|
||||
has_build = false,
|
||||
mode_cmd = nil, ---@type container_mode|nil
|
||||
resend_mode = false,
|
||||
periodics = {
|
||||
next_formed_req = 0,
|
||||
next_build_req = 0,
|
||||
@ -101,45 +105,77 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
|
||||
|
||||
-- increment the container mode
|
||||
local function _inc_cont_mode()
|
||||
-- set mode command
|
||||
if self.mode_cmd == "BOTH" then self.mode_cmd = "FILL"
|
||||
elseif self.mode_cmd == "FILL" then self.mode_cmd = "EMPTY"
|
||||
elseif self.mode_cmd == "EMPTY" then self.mode_cmd = "BOTH"
|
||||
end
|
||||
|
||||
-- write coil 1 with unused value 0
|
||||
self.session.send_request(TXN_TYPES.INC_CONT, MODBUS_FCODE.WRITE_SINGLE_COIL, { 1, 0 })
|
||||
if self.session.send_request(TXN_TYPES.INC_CONT, MODBUS_FCODE.WRITE_SINGLE_COIL, { 1, 0 }, WRITE_BUSY_WAIT) == false then
|
||||
self.resend_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
-- decrement the container mode
|
||||
local function _dec_cont_mode()
|
||||
-- set mode command
|
||||
if self.mode_cmd == "BOTH" then self.mode_cmd = "EMPTY"
|
||||
elseif self.mode_cmd == "EMPTY" then self.mode_cmd = "FILL"
|
||||
elseif self.mode_cmd == "FILL" then self.mode_cmd = "BOTH"
|
||||
end
|
||||
|
||||
-- write coil 2 with unused value 0
|
||||
self.session.send_request(TXN_TYPES.DEC_CONT, MODBUS_FCODE.WRITE_SINGLE_COIL, { 2, 0 })
|
||||
if self.session.send_request(TXN_TYPES.DEC_CONT, MODBUS_FCODE.WRITE_SINGLE_COIL, { 2, 0 , WRITE_BUSY_WAIT}) == false then
|
||||
self.resend_mode = false
|
||||
end
|
||||
end
|
||||
|
||||
-- set the container mode
|
||||
---@param mode container_mode
|
||||
local function _set_cont_mode(mode)
|
||||
self.mode_cmd = mode
|
||||
|
||||
-- write holding register 1
|
||||
self.session.send_request(TXN_TYPES.SET_CONT, MODBUS_FCODE.WRITE_SINGLE_HOLD_REG, { 1, mode })
|
||||
if self.session.send_request(TXN_TYPES.SET_CONT, MODBUS_FCODE.WRITE_SINGLE_HOLD_REG, { 1, mode }, WRITE_BUSY_WAIT) == false then
|
||||
self.resend_mode = false
|
||||
end
|
||||
end
|
||||
|
||||
-- query if the multiblock is formed
|
||||
local function _request_formed()
|
||||
---@param time_now integer
|
||||
local function _request_formed(time_now)
|
||||
-- read discrete input 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
end
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 7 (start = 1, count = 7)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 7 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 7 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read holding register 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_MUL_HOLD_REGS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_MUL_HOLD_REGS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 8 through 9 (start = 8, count = 2)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 8, 2 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 8, 2 }) ~= false then
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -182,6 +218,10 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
|
||||
if m_pkt.length == 1 then
|
||||
self.db.state.last_update = util.time_ms()
|
||||
self.db.state.container_mode = m_pkt.data[1]
|
||||
|
||||
if self.mode_cmd == nil then
|
||||
self.mode_cmd = self.db.state.container_mode
|
||||
end
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
@ -247,30 +287,22 @@ function dynamicv.new(session_id, unit_id, advert, out_queue)
|
||||
end
|
||||
end
|
||||
|
||||
-- try to resend mode if needed
|
||||
if self.resend_mode then
|
||||
self.resend_mode = false
|
||||
_set_cont_mode(self.mode_cmd)
|
||||
end
|
||||
|
||||
time_now = util.time()
|
||||
|
||||
-- handle periodics
|
||||
|
||||
if self.periodics.next_formed_req <= time_now then
|
||||
_request_formed()
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
if self.periodics.next_formed_req <= time_now then _request_formed(time_now) end
|
||||
|
||||
if self.db.formed then
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
|
||||
@ -58,9 +58,12 @@ function envd.new(session_id, unit_id, advert, out_queue)
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query the radiation readings of the device
|
||||
local function _request_radiation()
|
||||
---@param time_now integer
|
||||
local function _request_radiation(time_now)
|
||||
-- read input registers 1 and 2 (start = 1, count = 2)
|
||||
self.session.send_request(TXN_TYPES.RAD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 2 })
|
||||
if self.session.send_request(TXN_TYPES.RAD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 2 }) ~= false then
|
||||
self.periodics.next_rad_req = time_now + PERIODICS.RAD
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -90,10 +93,7 @@ function envd.new(session_id, unit_id, advert, out_queue)
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if self.periodics.next_rad_req <= time_now then
|
||||
_request_radiation()
|
||||
self.periodics.next_rad_req = time_now + PERIODICS.RAD
|
||||
end
|
||||
if self.periodics.next_rad_req <= time_now then _request_radiation(time_now) end
|
||||
|
||||
self.session.post_update()
|
||||
end
|
||||
|
||||
@ -89,27 +89,39 @@ function imatrix.new(session_id, unit_id, advert, out_queue)
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query if the multiblock is formed
|
||||
local function _request_formed()
|
||||
---@param time_now integer
|
||||
local function _request_formed(time_now)
|
||||
-- read discrete input 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
end
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 9 (start = 1, count = 9)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 9 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 9 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read input register 10 through 11 (start = 10, count = 2)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 10, 2 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 10, 2 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 12 through 15 (start = 12, count = 3)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 12, 3 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 12, 3 }) ~= false then
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -181,26 +193,12 @@ function imatrix.new(session_id, unit_id, advert, out_queue)
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if self.periodics.next_formed_req <= time_now then
|
||||
_request_formed()
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
if self.periodics.next_formed_req <= time_now then _request_formed(time_now) end
|
||||
|
||||
if self.db.formed then
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
|
||||
@ -80,21 +80,30 @@ function sna.new(session_id, unit_id, advert, out_queue)
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 2 (start = 1, count = 2)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 2 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 2 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read input registers 3 through 4 (start = 3, count = 2)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 3, 2 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 3, 2 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 5 through 10 (start = 5, count = 6)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 5, 6 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 5, 6 }) ~= false then
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -152,20 +161,9 @@ function sna.new(session_id, unit_id, advert, out_queue)
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
|
||||
self.session.post_update()
|
||||
end
|
||||
|
||||
@ -94,27 +94,39 @@ function sps.new(session_id, unit_id, advert, out_queue)
|
||||
-- PRIVATE FUNCTIONS --
|
||||
|
||||
-- query if the multiblock is formed
|
||||
local function _request_formed()
|
||||
---@param time_now integer
|
||||
local function _request_formed(time_now)
|
||||
-- read discrete input 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
end
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 9 (start = 1, count = 9)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 9 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 9 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read input register 10 (start = 10, count = 1)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 10, 1 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 10, 1 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 11 through 19 (start = 11, count = 9)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 11, 9 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 11, 9 }) ~= false then
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -191,26 +203,12 @@ function sps.new(session_id, unit_id, advert, out_queue)
|
||||
-- update this runner
|
||||
---@param time_now integer milliseconds
|
||||
function public.update(time_now)
|
||||
if self.periodics.next_formed_req <= time_now then
|
||||
_request_formed()
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
if self.periodics.next_formed_req <= time_now then _request_formed(time_now) end
|
||||
|
||||
if self.db.formed then
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
|
||||
@ -42,6 +42,8 @@ local PERIODICS = {
|
||||
TANKS = 1000
|
||||
}
|
||||
|
||||
local WRITE_BUSY_WAIT = 1000
|
||||
|
||||
-- create a new turbinev rtu session runner
|
||||
---@nodiscard
|
||||
---@param session_id integer RTU gateway session ID
|
||||
@ -63,6 +65,8 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
|
||||
local self = {
|
||||
session = unit_session.new(session_id, unit_id, advert, out_queue, log_tag, TXN_TAGS),
|
||||
has_build = false,
|
||||
mode_cmd = nil, ---@type dumping_mode|nil
|
||||
resend_mode = false,
|
||||
periodics = {
|
||||
next_formed_req = 0,
|
||||
next_build_req = 0,
|
||||
@ -116,45 +120,77 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
|
||||
|
||||
-- increment the dumping mode
|
||||
local function _inc_dump_mode()
|
||||
-- set mode command
|
||||
if self.mode_cmd == "IDLE" then self.mode_cmd = "DUMPING_EXCESS"
|
||||
elseif self.mode_cmd == "DUMPING_EXCESS" then self.mode_cmd = "DUMPING"
|
||||
elseif self.mode_cmd == "DUMPING" then self.mode_cmd = "IDLE"
|
||||
end
|
||||
|
||||
-- write coil 1 with unused value 0
|
||||
self.session.send_request(TXN_TYPES.INC_DUMP, MODBUS_FCODE.WRITE_SINGLE_COIL, { 1, 0 })
|
||||
if self.session.send_request(TXN_TYPES.INC_DUMP, MODBUS_FCODE.WRITE_SINGLE_COIL, { 1, 0 }, WRITE_BUSY_WAIT) == false then
|
||||
self.resend_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
-- decrement the dumping mode
|
||||
local function _dec_dump_mode()
|
||||
-- set mode command
|
||||
if self.mode_cmd == "IDLE" then self.mode_cmd = "DUMPING"
|
||||
elseif self.mode_cmd == "DUMPING_EXCESS" then self.mode_cmd = "IDLE"
|
||||
elseif self.mode_cmd == "DUMPING" then self.mode_cmd = "DUMPING_EXCESS"
|
||||
end
|
||||
|
||||
-- write coil 2 with unused value 0
|
||||
self.session.send_request(TXN_TYPES.DEC_DUMP, MODBUS_FCODE.WRITE_SINGLE_COIL, { 2, 0 })
|
||||
if self.session.send_request(TXN_TYPES.DEC_DUMP, MODBUS_FCODE.WRITE_SINGLE_COIL, { 2, 0 }, WRITE_BUSY_WAIT) == false then
|
||||
self.resend_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
-- set the dumping mode
|
||||
---@param mode dumping_mode
|
||||
local function _set_dump_mode(mode)
|
||||
self.mode_cmd = mode
|
||||
|
||||
-- write holding register 1
|
||||
self.session.send_request(TXN_TYPES.SET_DUMP, MODBUS_FCODE.WRITE_SINGLE_HOLD_REG, { 1, mode })
|
||||
if self.session.send_request(TXN_TYPES.SET_DUMP, MODBUS_FCODE.WRITE_SINGLE_HOLD_REG, { 1, mode }, WRITE_BUSY_WAIT) == false then
|
||||
self.resend_mode = true
|
||||
end
|
||||
end
|
||||
|
||||
-- query if the multiblock is formed
|
||||
local function _request_formed()
|
||||
---@param time_now integer
|
||||
local function _request_formed(time_now)
|
||||
-- read discrete input 1 (start = 1, count = 1)
|
||||
self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 })
|
||||
if self.session.send_request(TXN_TYPES.FORMED, MODBUS_FCODE.READ_DISCRETE_INPUTS, { 1, 1 }) ~= false then
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
end
|
||||
|
||||
-- query the build of the device
|
||||
local function _request_build()
|
||||
---@param time_now integer
|
||||
local function _request_build(time_now)
|
||||
-- read input registers 1 through 15 (start = 1, count = 15)
|
||||
self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 15 })
|
||||
if self.session.send_request(TXN_TYPES.BUILD, MODBUS_FCODE.READ_INPUT_REGS, { 1, 15 }) ~= false then
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
end
|
||||
|
||||
-- query the state of the device
|
||||
local function _request_state()
|
||||
---@param time_now integer
|
||||
local function _request_state(time_now)
|
||||
-- read input registers 16 through 19 (start = 16, count = 4)
|
||||
self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 16, 4 })
|
||||
if self.session.send_request(TXN_TYPES.STATE, MODBUS_FCODE.READ_INPUT_REGS, { 16, 4 }) ~= false then
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
end
|
||||
|
||||
-- query the tanks of the device
|
||||
local function _request_tanks()
|
||||
---@param time_now integer
|
||||
local function _request_tanks(time_now)
|
||||
-- read input registers 20 through 25 (start = 20, count = 6)
|
||||
self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 20, 6 })
|
||||
if self.session.send_request(TXN_TYPES.TANKS, MODBUS_FCODE.READ_INPUT_REGS, { 20, 6 }) ~= false then
|
||||
self.periodic.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
end
|
||||
|
||||
-- PUBLIC FUNCTIONS --
|
||||
@ -208,6 +244,10 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
|
||||
self.db.state.prod_rate = m_pkt.data[2]
|
||||
self.db.state.steam_input_rate = m_pkt.data[3]
|
||||
self.db.state.dumping_mode = m_pkt.data[4]
|
||||
|
||||
if self.mode_cmd == nil then
|
||||
self.mode_cmd = self.db.state.dumping_mode
|
||||
end
|
||||
else
|
||||
log.debug(log_tag .. "MODBUS transaction reply length mismatch (" .. TXN_TAGS[txn_type] .. ")")
|
||||
end
|
||||
@ -277,30 +317,22 @@ function turbinev.new(session_id, unit_id, advert, out_queue)
|
||||
end
|
||||
end
|
||||
|
||||
-- try to resend mode if needed
|
||||
if self.resend_mode then
|
||||
self.resend_mode = false
|
||||
_set_dump_mode(self.mode_cmd)
|
||||
end
|
||||
|
||||
time_now = util.time()
|
||||
|
||||
-- handle periodics
|
||||
|
||||
if self.periodics.next_formed_req <= time_now then
|
||||
_request_formed()
|
||||
self.periodics.next_formed_req = time_now + PERIODICS.FORMED
|
||||
end
|
||||
if self.periodics.next_formed_req <= time_now then _request_formed(time_now) end
|
||||
|
||||
if self.db.formed then
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then
|
||||
_request_build()
|
||||
self.periodics.next_build_req = time_now + PERIODICS.BUILD
|
||||
end
|
||||
|
||||
if self.periodics.next_state_req <= time_now then
|
||||
_request_state()
|
||||
self.periodics.next_state_req = time_now + PERIODICS.STATE
|
||||
end
|
||||
|
||||
if self.periodics.next_tanks_req <= time_now then
|
||||
_request_tanks()
|
||||
self.periodics.next_tanks_req = time_now + PERIODICS.TANKS
|
||||
end
|
||||
if not self.has_build and self.periodics.next_build_req <= time_now then _request_build(time_now) end
|
||||
if self.periodics.next_state_req <= time_now then _request_state(time_now) end
|
||||
if self.periodics.next_tanks_req <= time_now then _request_tanks(time_now) end
|
||||
end
|
||||
|
||||
self.session.post_update()
|
||||
|
||||
@ -22,6 +22,8 @@ local RTU_US_DATA = {
|
||||
unit_session.RTU_US_CMDS = RTU_US_CMDS
|
||||
unit_session.RTU_US_DATA = RTU_US_DATA
|
||||
|
||||
local DEFAULT_BUSY_WAIT = 3000
|
||||
|
||||
-- create a new unit session runner
|
||||
---@nodiscard
|
||||
---@param session_id integer RTU gateway session ID
|
||||
@ -36,7 +38,8 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
|
||||
reactor = advert.reactor,
|
||||
transaction_controller = txnctrl.new(),
|
||||
connected = true,
|
||||
device_fail = false
|
||||
device_fail = false,
|
||||
last_busy = 0
|
||||
}
|
||||
|
||||
---@class _unit_session
|
||||
@ -53,14 +56,21 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
|
||||
---@param txn_type integer transaction type
|
||||
---@param f_code MODBUS_FCODE function code
|
||||
---@param register_param (number|string)[] register range or register and values
|
||||
---@return integer txn_id transaction ID of this transaction
|
||||
function protected.send_request(txn_type, f_code, register_param)
|
||||
---@param busy_wait integer|nil milliseconds to wait (>0), or uses the default
|
||||
---@return integer|false txn_id transaction ID of this transaction or false if not sent due to being busy
|
||||
function protected.send_request(txn_type, f_code, register_param, busy_wait)
|
||||
local txn_id = false ---@type integer|false
|
||||
|
||||
busy_wait = busy_wait or DEFAULT_BUSY_WAIT
|
||||
|
||||
if (util.time_ms() - self.last_busy) >= busy_wait then
|
||||
local m_pkt = comms.modbus_packet()
|
||||
local txn_id = self.transaction_controller.create(txn_type)
|
||||
txn_id = self.transaction_controller.create(txn_type)
|
||||
|
||||
m_pkt.make(txn_id, unit_id, f_code, register_param)
|
||||
|
||||
out_queue.push_packet(m_pkt)
|
||||
end
|
||||
|
||||
return txn_id
|
||||
end
|
||||
@ -99,9 +109,9 @@ function unit_session.new(session_id, unit_id, advert, out_queue, log_tag, txn_t
|
||||
-- will have to wait on reply, renew the transaction
|
||||
self.transaction_controller.renew(m_pkt.txn_id, txn_type)
|
||||
elseif ex == MODBUS_EXCODE.SERVER_DEVICE_BUSY then
|
||||
-- will have to wait on reply, renew the transaction
|
||||
self.transaction_controller.renew(m_pkt.txn_id, txn_type)
|
||||
log.debug(log_tag .. "MODBUS: device busy" .. txn_tag)
|
||||
-- will have to try again later
|
||||
self.last_busy = util.time_ms()
|
||||
log.warning(log_tag .. "MODBUS: device busy" .. txn_tag)
|
||||
elseif ex == MODBUS_EXCODE.NEG_ACKNOWLEDGE then
|
||||
-- general failure
|
||||
log.error(log_tag .. "MODBUS: negative acknowledge (bad request)" .. txn_tag)
|
||||
|
||||
@ -22,7 +22,7 @@ local supervisor = require("supervisor.supervisor")
|
||||
|
||||
local svsessions = require("supervisor.session.svsessions")
|
||||
|
||||
local SUPERVISOR_VERSION = "v1.6.1"
|
||||
local SUPERVISOR_VERSION = "v1.6.2"
|
||||
|
||||
local println = util.println
|
||||
local println_ts = util.println_ts
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user