129 lines
6.7 KiB
GDScript
129 lines
6.7 KiB
GDScript
class_name sch_3 extends Node
|
||
|
||
## Модуль Прибора Щ3
|
||
|
||
const ONLINE_TIMEOUT: int = 5000 ## Время ожидания данных
|
||
const REQUEST_PERIOD: int = 1000 ## Переиод запроса, мс
|
||
|
||
|
||
## Представление прибора Щ3
|
||
class Sch3 extends unit.Unit:
|
||
|
||
var mb_addr: = 0 ## Адрес устройства Modbus.
|
||
var cmd_state: = CmdState.DONE ## Состояние выполнения текущей команды.
|
||
var tick_rx: = 0 ## Время приёма крайнего сообщения.
|
||
var tick_tx: = 0 ## Время отправки крайнего сообщения.
|
||
|
||
static var json_conv: = JSON.new()
|
||
signal resp_input(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
|
||
signal resp_holding(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
|
||
signal resp_write() ## Вызывается при получении подтверждения, что команда записи выполнена
|
||
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
|
||
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
|
||
|
||
func _init(nm: String, u: int = 0):
|
||
mb_addr = u
|
||
name = nm
|
||
|
||
## Изменяет состояние. Вызывать периодически.[br]
|
||
## [param tick] - Текущщее время в мс.[br]
|
||
## Возвращает [b]Error.OK[/b] - если данные готовы для отправки.[br]
|
||
## Возвращает [b]Error.ERR_BUSY[/b] - если данных для отправки нет.[br]
|
||
func process(tick: int) -> Error:
|
||
if online and ((tick - rx_tick) > ONLINE_TIMEOUT):
|
||
online = false
|
||
emit_signal('line_changed', self)
|
||
if cmd_state == CmdState.WAIT:
|
||
if (tick - tx_tick) > ONLINE_TIMEOUT:
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('command_fail', self)
|
||
var rc = Error.ERR_BUSY
|
||
if cmd_state == CmdState.SEND:
|
||
tx_tick = tick
|
||
cmd_state = CmdState.WAIT
|
||
rc = Error.OK
|
||
return rc
|
||
|
||
|
||
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
|
||
## [param data] - Данные принятые на сокете.[br]
|
||
## [param tick] - Текущщее время в мс.[br]
|
||
func parse(data: PackedByteArray, tick: int) -> bool:
|
||
rx_tick = tick
|
||
if not online:
|
||
online = true
|
||
emit_signal('line_changed', self)
|
||
var utf8_data = data.get_string_from_utf8()
|
||
if Error.OK == json_conv.parse(utf8_data):
|
||
emit_signal('data_received', data)
|
||
var message: Dictionary = json_conv.get_data()
|
||
if message.has('code') and message.has('data'):
|
||
var rc: = true
|
||
var message_code = message['code']
|
||
var message_data = message['data']
|
||
match message_code:
|
||
'resp_holding', 'resp_input':
|
||
var addr = int(message_data[0])
|
||
var regs = message_data.slice(1)
|
||
for i in regs.size():
|
||
regs[i] = int(regs[i])
|
||
emit_signal(message_code, addr, regs)
|
||
'resp_write':
|
||
emit_signal(message_code)
|
||
'info':
|
||
var msg = message['data']
|
||
emit_signal('info_received', msg)
|
||
'exception':
|
||
var msg = message['data']
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('except_received', msg)
|
||
rc = false
|
||
_:
|
||
var msg: String = 'код команды \"%s\" - не распознан' % message_code
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('parse_failed', msg)
|
||
rc = false
|
||
if (cmd_state == CmdState.WAIT) and rc:
|
||
cmd_state = CmdState.DONE
|
||
emit_signal('command_done')
|
||
elif (cmd_state == CmdState.WAIT) and (not rc):
|
||
cmd_state = CmdState.FAIL
|
||
emit_signal('command_fail', self)
|
||
else:
|
||
var message = json_conv.get_error_message()
|
||
emit_signal('parse_failed', message)
|
||
return true
|
||
|
||
## Отправляет команду "записать в регистры".[br]
|
||
## [param addr] - Начальный адрес регистров.[br]
|
||
## [param count] - Данные для записи в регистры от начального адреса.[br]
|
||
func write(addr: int, data: Array) -> bool:
|
||
if cmd_state != CmdState.DONE: return false
|
||
var json_dict: = {'code': 'write', 'data': [addr] + data, 'unit': mb_addr}
|
||
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
|
||
tx_len = len(tx_data)
|
||
cmd_state = CmdState.SEND
|
||
return true
|
||
|
||
## Отправляет команду "читать регистры хранения".[br]
|
||
## [param addr] - Начальный адрес регистров.[br]
|
||
## [param count] - Количество регистров от начального адреса.[br]
|
||
func read_holding(addr: int, count: int = 1) -> bool:
|
||
if cmd_state != CmdState.DONE: return false
|
||
var json_dict: = {'code': 'read_holding', 'data': [addr, count], 'unit': mb_addr}
|
||
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
|
||
tx_len = len(tx_data)
|
||
cmd_state = CmdState.SEND
|
||
return true
|
||
|
||
## Отправляет команду "читать регистры входов".[br]
|
||
## [param addr] - Начальный адрес регистров.[br]
|
||
## [param count] - Количество регистров от начального адреса.[br]
|
||
func read_input(addr: int, count: int = 1) -> bool:
|
||
if cmd_state != CmdState.DONE: return false
|
||
var json_dict: = {'code': 'read_input', 'data': [addr, count], 'unit': mb_addr}
|
||
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
|
||
tx_len = len(tx_data)
|
||
cmd_state = CmdState.SEND
|
||
return true
|