Доработка. Добавлен тип соединения TCP/IP для 5П28
This commit is contained in:
@@ -2,7 +2,7 @@ extends Node
|
||||
|
||||
|
||||
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb}
|
||||
|
||||
const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28}
|
||||
|
||||
class Socket extends PacketPeerUDP:
|
||||
func send_to(addr, data):
|
||||
@@ -10,8 +10,24 @@ class Socket extends PacketPeerUDP:
|
||||
self.put_packet(data)
|
||||
|
||||
|
||||
class SocketTCP extends TCPServer:
|
||||
const RX_TIMEOUT: int = 1000 # Время сброса счётчика принятия части пакета
|
||||
var peerstream: = PacketPeerStream.new()
|
||||
var unit_key: Array # Клюс юнита
|
||||
var head_len: int # Длинна заголовка команды
|
||||
var len_place: int # Номер начального байта с длинной блока данных
|
||||
var type_len: int # Количество байт в размере длинны
|
||||
var rx_tick: int # Время приёма последнего пакета
|
||||
var rx_all: bool = true # Флаг, что пакет принят полностью
|
||||
var rx_len: int # Количество принятых байт
|
||||
var rx_data: PackedByteArray # Принятые данные
|
||||
var data_len: int # Размер ожидаемых данных
|
||||
|
||||
|
||||
var poll_sockets: Array[Socket]
|
||||
var tcp_sockets: Array[SocketTCP]
|
||||
var units: Dictionary
|
||||
var units_tcp: Dictionary
|
||||
var sock_unicast: Socket
|
||||
var sock_capsrpb: Socket
|
||||
var logger_page: Node
|
||||
@@ -30,12 +46,27 @@ func create_socket(nm) -> Socket:
|
||||
return sock
|
||||
|
||||
|
||||
func create_tcpsocket(nm) -> SocketTCP:
|
||||
var addr = repsettings.UnitProfiles[nm][1]
|
||||
var port = repsettings.UnitProfiles[nm][2]
|
||||
var sock = SocketTCP.new()
|
||||
sock.unit_key = repsettings.get_unit_key(nm)
|
||||
sock.head_len = repsettings.UnitProfiles[nm][3]
|
||||
sock.len_place = repsettings.UnitProfiles[nm][4]
|
||||
sock.type_len = repsettings.UnitProfiles[nm][5]
|
||||
sock.listen(port, addr)
|
||||
log.message(log.INFO, '%s: сокет:%s:%d привязанный:' % [nm, addr, port])
|
||||
return sock
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
log.info('Модуль работы с сетью готов')
|
||||
poll_sockets.append(create_socket('уарэп-яу07-частный'))
|
||||
poll_sockets.append(create_socket('уарэп-яу07-общий'))
|
||||
poll_sockets.append(create_socket('уарэп-капсрпб-пол'))
|
||||
|
||||
|
||||
tcp_sockets.append(create_tcpsocket('уарэп-5п28'))
|
||||
|
||||
sock_unicast = poll_sockets[0]
|
||||
sock_capsrpb = poll_sockets[2]
|
||||
|
||||
@@ -49,9 +80,17 @@ func _ready() -> void:
|
||||
if logger_page:
|
||||
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
|
||||
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
|
||||
|
||||
|
||||
if proto in TCP_PROTO:
|
||||
var unit = TCP_PROTO[proto].new(unit_name)
|
||||
var unit_key = repsettings.get_unit_key(unit_name)
|
||||
units_tcp[unit_key] = unit
|
||||
if logger_page:
|
||||
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
|
||||
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
|
||||
|
||||
for key in units: log.info('%s %s:%d' % [units[key].name, key[0], key[1]])
|
||||
|
||||
for key in units_tcp: log.info('%s %s:%d' % [units_tcp[key].name, key[0], key[1]])
|
||||
|
||||
func poll_receive(sock: Socket, tick: int) -> bool:
|
||||
while sock.get_available_packet_count() > 0:
|
||||
@@ -63,6 +102,51 @@ func poll_receive(sock: Socket, tick: int) -> bool:
|
||||
return false
|
||||
|
||||
|
||||
func poll_receive_tcp(sock: SocketTCP, tick: int) -> bool:
|
||||
if sock.is_connection_available(): # check if someone's trying to connect
|
||||
var client = sock.take_connection() # accept connection
|
||||
sock.peerstream.set_stream_peer(client) # bind peerstream to new client
|
||||
var peer = sock.peerstream.get_stream_peer()
|
||||
if peer:
|
||||
var peer_len_data = peer.get_available_bytes()
|
||||
if peer_len_data > 0:
|
||||
get_client_data(sock, peer_len_data, peer, tick)
|
||||
if sock.unit_key in units and sock.rx_all: units[sock.unit_key].parse(sock.rx_data, tick)
|
||||
return false
|
||||
|
||||
|
||||
func get_client_data(sock: SocketTCP, peer_len_data, peer, tick):
|
||||
if tick - sock.rx_tick > sock.RX_TIMEOUT:
|
||||
sock.rx_all = true
|
||||
sock.rx_tick = tick
|
||||
if sock.rx_all:
|
||||
if peer_len_data >= sock.head_len:
|
||||
sock.rx_all = false
|
||||
sock.rx_len = sock.head_len
|
||||
var head = peer.get_data(sock.head_len)
|
||||
sock.data_len = head[1].decode_u32(sock.len_place)
|
||||
var len_data_in_buf = peer.get_available_bytes()
|
||||
if len_data_in_buf > 0:
|
||||
sock.rx_data = head[1]
|
||||
var len_rx = len_data_in_buf
|
||||
if len_data_in_buf >= sock.data_len:
|
||||
len_rx = sock.data_len
|
||||
get_tcp_data(sock, peer, len_rx)
|
||||
else:
|
||||
var len_rx = (sock.head_len + sock.data_len) - sock.rx_len
|
||||
if peer_len_data < len_rx:
|
||||
len_rx = peer_len_data
|
||||
get_tcp_data(sock, peer, len_rx)
|
||||
|
||||
|
||||
func get_tcp_data(sock: SocketTCP, peer, len_rx):
|
||||
var temp_data = peer.get_data(len_rx)[1]
|
||||
sock.rx_data.append_array(temp_data)
|
||||
sock.rx_len += len_rx
|
||||
if sock.rx_len >= sock.head_len + sock.data_len:
|
||||
sock.rx_all = true
|
||||
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
var tick = Time.get_ticks_msec()
|
||||
for addr in units:
|
||||
@@ -71,3 +155,4 @@ func _process(_delta: float) -> void:
|
||||
Error.OK: sock_unicast.send_to(addr, unit.tx_data)
|
||||
Error.FAILED: emit_signal('socket_error', 'ошибка: %s %s:%d' % [unit, addr[0], addr[1]])
|
||||
poll_sockets.any(func(sock): poll_receive(sock, tick))
|
||||
tcp_sockets.any(func(sock): poll_receive_tcp(sock, tick))
|
||||
|
||||
@@ -28,7 +28,8 @@ extends Node
|
||||
'уарэп-яу07-3в': ['yau07tx', '10.1.1.50', 50050, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
|
||||
'уарэп-яу07-3н': ['yau07tx', '10.1.1.49', 50049, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
|
||||
'уарэп-яу07-3к': ['yau07tx', '10.1.1.51', 50051, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
|
||||
'уарэп-щ3': ['uart', '/dev/stty0', 115200, 1, 1, false, 1000, 'Прибор Щ3'] } # скорость, стартовых, стоповых, чётность, таймаут в мкс
|
||||
'уарэп-5п28': ['5p28', '127.0.0.1', 50000, 8, 4, 4, 'IP-адрес комплекса 5П-28'], # IP Адресс, порт, мин. длинна пакета, длинна место, длинна длинны
|
||||
'уарэп-щ3': ['uart', '/dev/stty0', 115200, 1, 1, false, 1000, 'Прибор Щ3'] } # скорость, стартовых, стоповых, чётность, таймаут в мкс
|
||||
|
||||
|
||||
## Параметры цели
|
||||
|
||||
43
scripts/tcp5p28.gd
Normal file
43
scripts/tcp5p28.gd
Normal file
@@ -0,0 +1,43 @@
|
||||
extends Node
|
||||
|
||||
## Реализация "Протокол информационного сопряжения
|
||||
## СПО АСУ изделия «МП‑550» с СПО 5П28"
|
||||
|
||||
|
||||
const ONLINE_TIMEOUT = 3000 ## Время ожидания пакета от КАПС РПБ, мс
|
||||
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм
|
||||
|
||||
class TCP5P28:
|
||||
signal line_changed(unit: TCP5P28) ## Сигнал состояние связи изменилось
|
||||
signal data_received(unit: TCP5P28) ## Сигнал данные приняты
|
||||
signal command_fail(unit: TCP5P28) ## Сигнал при не выполнении команды
|
||||
signal parse_error(unit: TCP5P28, msg: String) ## Сигнал ошибки разбора сообщения
|
||||
|
||||
static var json_conv: = JSON.new()
|
||||
var online: = false ## Состояние связи с источником сообщений
|
||||
var name: String ## Имя экземпляра
|
||||
var json_dic: Dictionary ## Аппарат для разбора сообщений
|
||||
var tick: = 0 ## Тик время последнего обновления, мс
|
||||
var tx_data: = PackedByteArray() ## Пакет для отправки
|
||||
var tx_stack: Array ## Массив пакетов для отправки
|
||||
|
||||
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
|
||||
func _init(nm): self.name = nm
|
||||
|
||||
func parse(data: PackedByteArray, now_tick: int):
|
||||
tick = now_tick
|
||||
if not online:
|
||||
online = true
|
||||
emit_signal('line_changed', self)
|
||||
|
||||
|
||||
func process(now_tick: int):
|
||||
if online and ((now_tick - tick) > ONLINE_TIMEOUT):
|
||||
online = false
|
||||
emit_signal('line_changed', self)
|
||||
if len(tx_stack):
|
||||
tx_data = tx_stack[0]
|
||||
tx_stack.remove_at(0)
|
||||
return Error.OK
|
||||
else:
|
||||
return Error.ERR_UNAVAILABLE
|
||||
Reference in New Issue
Block a user