Доработка. Встроенные клиент протокола modbus для Щ3
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
class_name Network extends Node
|
||||
|
||||
|
||||
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'json-capsrpb': capsrpb.CapsRpb, 'udp-json-mbcs': sch3.Sch3}
|
||||
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'json-capsrpb': capsrpb.CapsRpb}
|
||||
const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28}
|
||||
const SERIAL_PROTO: = {'uart': spt25.SPT25 }
|
||||
const SERIAL_PROTO: = {'uart': spt25.SPT25}
|
||||
const MODBUS_PROTO: = {'mbcs': sch3.Sch3}
|
||||
|
||||
var tick: int = 0
|
||||
|
||||
@@ -47,13 +48,26 @@ class SocketTCP extends TCPServer:
|
||||
peer.put_data(data)
|
||||
|
||||
|
||||
class Modbus extends ModbusClientRtu:
|
||||
func send_to(data):
|
||||
if data['code'] == 'write':
|
||||
var addr = data['data'].pop_at(0)
|
||||
request_write(addr, data['data'])
|
||||
elif data['code'] == 'read_holding':
|
||||
request_read(data['data'][0], data['data'][1])
|
||||
elif data['code'] == 'read_input':
|
||||
request_read_input(data['data'][0], data['data'][1])
|
||||
|
||||
|
||||
var poll_sockets: Array[Socket]
|
||||
var tcp_sockets: Array
|
||||
var units: Dictionary
|
||||
var units_udp: Dictionary
|
||||
var units_tcp: Dictionary
|
||||
var units_serial: Dictionary
|
||||
var serials: Dictionary
|
||||
var units_modbus: Dictionary
|
||||
var serials: Dictionary # Последовательные порты
|
||||
var mbcs: Dictionary # Клиенты modbus.
|
||||
var dst_ports: Dictionary
|
||||
var unit_keys: Dictionary
|
||||
var sock_unicast: Socket
|
||||
@@ -97,11 +111,23 @@ func create_serial(nm) -> Serial:
|
||||
return sp
|
||||
|
||||
|
||||
func create_modbus(nm, mbc_unit) -> Modbus:
|
||||
var port = settings.UnitProfiles[nm][1]
|
||||
var baud = settings.UnitProfiles[nm][2]
|
||||
var params = settings.UnitProfiles[nm][3]
|
||||
var mbc: = Modbus.new()
|
||||
mbc.connect('read', mbc_unit.on_read)
|
||||
mbc.connect('read_input', mbc_unit.on_read_input)
|
||||
mbc.connect('write', mbc_unit.on_write)
|
||||
var _rc = mbc.open(port, params[0], baud[0], params[1], params[2], params[3])
|
||||
mbc.thread_run()
|
||||
return mbc
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
poll_sockets.append(create_socket('уарэп-яу07-частный'))
|
||||
poll_sockets.append(create_socket('уарэп-яу07-общий'))
|
||||
poll_sockets.append(create_socket('уарэп-капсрпб'))
|
||||
poll_sockets.append(create_socket('уарэп-щ3'))
|
||||
sock_unicast = poll_sockets[0]
|
||||
sock_capsrpb = poll_sockets[2]
|
||||
|
||||
@@ -130,6 +156,19 @@ func _ready() -> void:
|
||||
unit_tcp.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
|
||||
unit_tcp.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
|
||||
|
||||
|
||||
if proto in MODBUS_PROTO:
|
||||
var unit_modbus = MODBUS_PROTO[proto].new(unit_name)
|
||||
var unit_key = settings.get_unit_key(unit_name)
|
||||
if logger_page:
|
||||
unit_modbus.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
|
||||
unit_modbus.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
|
||||
var mbc = create_modbus(unit_name, unit_modbus)
|
||||
units_modbus[unit_key] = unit_modbus
|
||||
units[unit_key] = unit_modbus
|
||||
mbcs[unit_key] = mbc
|
||||
|
||||
|
||||
if proto in SERIAL_PROTO:
|
||||
var unit_serial = SERIAL_PROTO[proto].new(unit_name)
|
||||
var unit_key = settings.get_unit_key(unit_name)
|
||||
@@ -226,6 +265,12 @@ func _process(_delta: float) -> void:
|
||||
match unit_serial.process(tick):
|
||||
Error.OK: serial.send_to(unit_serial.tx_data)
|
||||
Error.FAILED: emit_signal('socket_error', [unit_serial, serial])
|
||||
for key in units_modbus:
|
||||
var unit_modbus = units_modbus[key]
|
||||
var mbc = mbcs[key]
|
||||
match unit_modbus.process(tick):
|
||||
Error.OK: mbc.send_to(unit_modbus.mb_data)
|
||||
Error.FAILED: emit_signal('socket_error', [unit_modbus, mbc])
|
||||
for sock_unit in tcp_sockets:
|
||||
var sock = sock_unit[0]
|
||||
var unit_tcp = sock_unit[1]
|
||||
|
||||
140
scripts/sch3.gd
140
scripts/sch3.gd
@@ -9,10 +9,11 @@ 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 ## Время отправки крайнего сообщения.
|
||||
var mb_addr: = 0 ## Адрес устройства Modbus.
|
||||
var cmd_state: = CmdState.DONE ## Состояние выполнения текущей команды.
|
||||
var tick_rx: = 0 ## Время приёма крайнего сообщения.
|
||||
var tick_tx: = 0 ## Время отправки крайнего сообщения.
|
||||
var mb_data: Dictionary = {} ## Буфер для записи в регистры модбас
|
||||
|
||||
static var json_conv: = JSON.new()
|
||||
signal resp_input(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
|
||||
@@ -48,50 +49,43 @@ class Sch3 extends unit.Unit:
|
||||
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
|
||||
## [param data] - Данные принятые на сокете.[br]
|
||||
## [param tick] - Текущщее время в мс.[br]
|
||||
func parse(data: PackedByteArray, tick: int) -> bool:
|
||||
func parse(message: Dictionary, 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):
|
||||
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('command_fail', self)
|
||||
else:
|
||||
var message = json_conv.get_error_message()
|
||||
emit_signal('parse_failed', message)
|
||||
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)
|
||||
return true
|
||||
|
||||
## Отправляет команду "записать в регистры".[br]
|
||||
@@ -99,9 +93,7 @@ class Sch3 extends unit.Unit:
|
||||
## [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)
|
||||
mb_data = {'code': 'write', 'data': [addr] + data, 'unit': mb_addr}
|
||||
cmd_state = CmdState.SEND
|
||||
return true
|
||||
|
||||
@@ -110,9 +102,7 @@ class Sch3 extends unit.Unit:
|
||||
## [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)
|
||||
mb_data = {'code': 'read_holding', 'data': [addr, count], 'unit': mb_addr}
|
||||
cmd_state = CmdState.SEND
|
||||
return true
|
||||
|
||||
@@ -121,8 +111,54 @@ class Sch3 extends unit.Unit:
|
||||
## [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)
|
||||
mb_data = {'code': 'read_input', 'data': [addr, count], 'unit': mb_addr}
|
||||
cmd_state = CmdState.SEND
|
||||
return true
|
||||
|
||||
|
||||
## Принимает результат команды "читать регистры хранения".[br]
|
||||
## [param return_code] - Код выполнения команды.[br]
|
||||
## [param base_addr] - Начальный адрес регистров.[br]
|
||||
## [param data] - Данные прочитанные из регистров.[br]
|
||||
## [param tick] - Время приёма пакета.[br]
|
||||
func on_read(return_code, base_addr, data):
|
||||
var tick = Time.get_ticks_msec()
|
||||
var msg: Dictionary
|
||||
if return_code == 0:
|
||||
msg['code'] = 'resp_holding'
|
||||
msg['data'] = [base_addr] + data
|
||||
else:
|
||||
msg['code'] = 'exception'
|
||||
parse(msg, tick)
|
||||
|
||||
|
||||
## Принимает результат команды "читать регистры входов".[br]
|
||||
## [param return_code] - Код выполнения команды.[br]
|
||||
## [param base_addr] - Начальный адрес регистров.[br]
|
||||
## [param data] - Данные прочитанные из регистров.[br]
|
||||
## [param tick] - Время приёма пакета.[br]
|
||||
func on_read_input(return_code, base_addr, data):
|
||||
var tick = Time.get_ticks_msec()
|
||||
var msg: Dictionary
|
||||
if return_code == 0:
|
||||
msg['code'] = 'resp_input'
|
||||
msg['data'] = [base_addr] + data
|
||||
else:
|
||||
msg['code'] = 'exception'
|
||||
parse(msg, tick)
|
||||
|
||||
|
||||
## Принимает результат команды "записать в регистры".[br]
|
||||
## [param return_code] - Код выполнения команды.[br]
|
||||
## [param base_addr] - Начальный адрес регистров.[br]
|
||||
## [param data] - Данные прочитанные из регистров.[br]
|
||||
## [param tick] - Время приёма пакета.[br]
|
||||
func on_write(return_code, _base_addr, data):
|
||||
var tick = Time.get_ticks_msec()
|
||||
var msg: Dictionary
|
||||
msg['data'] = 'resp_write'
|
||||
if return_code == 0:
|
||||
msg['code'] = 'resp_write'
|
||||
else:
|
||||
msg['code'] = 'exception'
|
||||
parse(msg, tick)
|
||||
|
||||
@@ -9,7 +9,7 @@ var settings_program: Dictionary
|
||||
|
||||
@export var UnitProfiles: = { \
|
||||
# Название | Протокол | Адрес | Порт | Широковещательное | Привязывать к адресу | Комментарий
|
||||
'уарэп-яу07-частный': ['yau07rx', '10.1.1.14', [50014], false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
|
||||
'уарэп-яу07-частный': ['yau07rx', '10.1.1.2', [50002], false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
|
||||
'уарэп-яу07-общий': ['yau07rx', '*', [50000], true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
|
||||
'уарэп-капсрпб': ['json-capsrpb', '127.0.0.1', [42023, 42022], false, true, 'IP-адрес на котором принимают сообщения от КАПС РПБ'],
|
||||
'уарэп-эмс': ['yau07tx', '10.1.1.52', [50052], false, false, 'IP-адрес ЯУ-07 прибора УФ'],
|
||||
@@ -29,8 +29,8 @@ var settings_program: Dictionary
|
||||
# Название: [ Протокол, Адрес, Порт получения, Комментарий ]
|
||||
'уарэп-5п28': [ '5p28', '192.168.3.109', [50000], 'IP-адрес комплекса 5П-28'],
|
||||
|
||||
# Название: [ Протокол, Адрес, [ Порт получения, Порт отправки], ??, ??, Комментарий
|
||||
'уарэп-щ3': ['udp-json-mbcs', '127.0.0.1', [48000, 44100], false, true, 'IP-адрес и порты через которые производят обмен сообщения с драйвером клиента Modbus Serial'],
|
||||
# Название: [ Протокол, Адрес, Скорость, ??, ??, Комментарий
|
||||
'уарэп-щ3': ['mbcs', '/home/sasha/dev/tty1', [19200], [3, 'N', 8, 1], 'Параметры клиента Modbus Serial'],
|
||||
|
||||
# Название: [ Протокол, Имя порта, Скорость, Чётность, ??, Комментарий
|
||||
'уарэп-спт25-1': ['uart', '/home/sasha/dev/tty0', [19200, false, false], 'Адрес прибора СПТ-25 (G1)'],
|
||||
|
||||
Reference in New Issue
Block a user