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', self) 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')