148 lines
6.1 KiB
GDScript
148 lines
6.1 KiB
GDScript
class_name sch_3 extends Node
|
||
|
||
const ONLINE_TIMEOUT = 5000
|
||
|
||
|
||
## Представление прибора Щ3
|
||
class Sch3 extends unit.Unit:
|
||
enum Sch3Fsm {
|
||
READ_INPUT,
|
||
READ_HOLDING,
|
||
WRITE,
|
||
CONNECT }
|
||
|
||
var step_fsm: Sch3Fsm = Sch3Fsm.CONNECT
|
||
var base_input_address: int = 0
|
||
var regs_input_count: int = 0
|
||
var base_holding_address: int = 0
|
||
var regs_holding_count: int = 0
|
||
var request_period: int = 300
|
||
var reconnect_period: int = ONLINE_TIMEOUT
|
||
var write_stack: Array
|
||
var tick_fsm: int = 0
|
||
var mbc: = ModbusClientRtu.new()
|
||
var tick_fsm_delta: = reconnect_period
|
||
|
||
|
||
func try_connect() -> bool:
|
||
var port = settings.UnitProfiles[name][1]
|
||
var params = settings.UnitProfiles[name][2]
|
||
mbc.thread_stop()
|
||
mbc.queue_clear()
|
||
mbc.flush()
|
||
mbc.close()
|
||
var rc = mbc.open(port, params[0], params[1], params[2], params[3], params[4])
|
||
if rc != Error.OK:
|
||
push_error('%s:%s %s' % [name, port, params])
|
||
return false
|
||
mbc.set_response_timeout(params[5])
|
||
mbc.thread_run()
|
||
return true
|
||
|
||
|
||
func push_write_holding(regs: Dictionary):
|
||
var keys = regs.keys()
|
||
keys.sort()
|
||
var data: = []
|
||
for k in keys:
|
||
data.append(regs[k])
|
||
write_stack.append([keys[0], data])
|
||
|
||
|
||
func _on_timeout(tick: int) -> void:
|
||
if step_fsm == Sch3Fsm.WRITE:
|
||
while write_stack.size():
|
||
var write_command = write_stack.pop_front()
|
||
mbc.request_write(write_command[0], write_command[1])
|
||
cmd_state = CmdState.WAIT
|
||
tx_tick = tick
|
||
step_fsm = Sch3Fsm.READ_INPUT
|
||
elif step_fsm == Sch3Fsm.READ_INPUT:
|
||
mbc.request_read_input(base_input_address, regs_input_count)
|
||
cmd_state = CmdState.WAIT
|
||
tx_tick = tick
|
||
step_fsm = Sch3Fsm.READ_HOLDING
|
||
elif step_fsm == Sch3Fsm.READ_HOLDING:
|
||
mbc.request_read(base_holding_address, regs_holding_count)
|
||
cmd_state = CmdState.WAIT
|
||
tx_tick = tick
|
||
step_fsm = Sch3Fsm.WRITE
|
||
elif step_fsm == Sch3Fsm.CONNECT:
|
||
try_connect()
|
||
mbc.request_read(base_input_address, regs_input_count)
|
||
cmd_state = CmdState.WAIT
|
||
tx_tick = tick
|
||
|
||
signal write (addr: int, data: Array) ## Вызывается при получении сообщения подтверждения записи
|
||
signal read (addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
|
||
signal read_input (addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
|
||
signal error(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
|
||
|
||
|
||
func _init(nm: String):
|
||
name = nm
|
||
mbc.connect('read', on_read)
|
||
mbc.connect('read_input', on_read_input)
|
||
mbc.connect('write', on_write)
|
||
|
||
|
||
func parse(return_code: Error, base_addr: int, data: Array, code: String):
|
||
if return_code == Error.OK:
|
||
rx_tick = Time.get_ticks_msec()
|
||
if cmd_state == CmdState.WAIT:
|
||
cmd_state = CmdState.DONE
|
||
emit_signal(code, base_addr, data)
|
||
if not online:
|
||
online = true
|
||
emit_signal('line_changed', online)
|
||
step_fsm = Sch3Fsm.WRITE
|
||
tick_fsm_delta = request_period
|
||
else:
|
||
if cmd_state == CmdState.WAIT:
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('error', [code, return_code, base_addr, data])
|
||
|
||
|
||
## Изменяет состояние. Вызывается периодически.[br]
|
||
## [param tick] - Текущщее время в мс.[br]
|
||
## Возвращает [b]Error.OK[/b] - если данные готовы для отправки.[br]
|
||
## Возвращает [b]Error.ERR_BUSY[/b] - если данных для отправки нет.[br]
|
||
func process(tick: int) -> Error:
|
||
if online:
|
||
if (tick - rx_tick) > ONLINE_TIMEOUT:
|
||
online = false
|
||
if cmd_state == CmdState.WAIT:
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('command_fail', name)
|
||
emit_signal('line_changed', online)
|
||
step_fsm = Sch3Fsm.CONNECT
|
||
tick_fsm_delta = reconnect_period
|
||
if (tick - tick_fsm) > tick_fsm_delta:
|
||
tick_fsm = tick
|
||
_on_timeout(tick)
|
||
return Error.ERR_BUSY
|
||
|
||
|
||
## Принимает результат команды "читать регистры хранения".[br]
|
||
## [param return_code] - Код выполнения команды.[br]
|
||
## [param base_addr] - Начальный адрес регистров.[br]
|
||
## [param data] - Данные прочитанные из регистров.[br]
|
||
func on_read(return_code: Error, base_addr: int, data: Array):
|
||
parse(return_code, base_addr, data, 'read')
|
||
|
||
|
||
## Принимает результат команды "читать регистры входов".[br]
|
||
## [param return_code] - Код выполнения команды.[br]
|
||
## [param base_addr] - Начальный адрес регистров.[br]
|
||
## [param data] - Данные прочитанные из регистров.[br]
|
||
func on_read_input(return_code: Error, base_addr: int, data: Array):
|
||
parse(return_code, base_addr, data, 'read_input')
|
||
|
||
|
||
## Принимает результат команды "записать в регистры".[br]
|
||
## [param return_code] - Код выполнения команды.[br]
|
||
## [param base_addr] - Начальный адрес регистров.[br]
|
||
## [param data] - Данные прочитанные из регистров.[br]
|
||
func on_write(return_code: Error, base_addr: int, data: Array):
|
||
parse(return_code, base_addr, data, 'write')
|