Рефактор и доработка read_isa, write_isa

This commit is contained in:
TotMaxim
2025-11-20 12:36:08 +03:00
parent e1aaa0b39f
commit 667f6d997e
3 changed files with 564 additions and 109 deletions

53
main.gd
View File

@@ -36,35 +36,42 @@ func _exit_tree():
func on_modify_device(toggled: bool, name_device: String) -> void:
if toggled:
udp_broadcast = UDPBroadcast.new(name_device)
udp_broadcast.add_timer_to_scene(self)
udp_broadcast.add_timers_to_scene(self) # Исправлено имя метода
udp_broadcast.start_broadcast()
dictionary_yau07[name_device] = udp_broadcast
print("Устройство %s активировано" % name_device)
else:
dictionary_yau07[name_device].close_udp_unit()
if dictionary_yau07.has(name_device) and dictionary_yau07[name_device]:
dictionary_yau07[name_device].close_udp_unit()
dictionary_yau07.erase(name_device)
print("Устройство %s деактивировано" % name_device)
## Функция для установки статусов ячеек на связи (УГ, ЭМС-Г, УКП)
func _on_modify_sockets(toggled: bool, bit: int, device: String)->void:
if dictionary_yau07.has(device):
var udp_unit = dictionary_yau07[device]
udp_unit.sockets_status_bit = _set_bit(udp_unit.sockets_status_bit, bit, toggled)
var current_status = udp_unit.get_sockets_status() # Используем геттер
var new_status = _set_bit(current_status, bit, toggled)
udp_unit.set_sockets_status(new_status) # Используем сеттер
print("Статус сокетов устройства %s обновлен: 0x%04X" % [device, new_status])
## Функция для установки статусов ДКМ в ПРД
func _on_modify_dkm(toggled: bool, bit: int, device: String)->void:
if dictionary_yau07.has(device):
var udp_unit = dictionary_yau07[device]
udp_unit.dkm_status_bit = _set_bit(udp_unit.dkm_status_bit, bit, toggled)
func _process(_delta: float) -> void:
for device in dictionary_yau07.keys():
if dictionary_yau07[device]:
dictionary_yau07[device].poll_receive()
var current_status = udp_unit.get_dkm_status() # Используем геттер
var new_status = _set_bit(current_status, bit, toggled)
udp_unit.set_dkm_status(new_status) # Используем сеттер
print("Статус DKM устройства %s обновлен: 0x%04X" % [device, new_status])
## Функция для установки значений в ячейках УКП
func _on_ukp_submitted(_new_text: String, device: String) -> void:
if not dictionary_yau07.has(device):
return
var prep_temperature_ukp1_array: Array = _on_text_temperature_changed(device, 1)
var prep_temperature_ukp2_array: Array = _on_text_temperature_changed(device, 2)
@@ -74,8 +81,8 @@ func _on_ukp_submitted(_new_text: String, device: String) -> void:
var combine_data_ukp1: Array = _combine_arrays(prep_temperature_ukp1_array, prep_power_ukp1_array)
var combine_data_ukp2: Array = _combine_arrays(prep_temperature_ukp2_array, prep_power_ukp2_array)
_form_buffers(device,combine_data_ukp1, 1, dictionary_yau07)
_form_buffers(device,combine_data_ukp2, 2, dictionary_yau07)
_form_buffers(device, combine_data_ukp1, 1, dictionary_yau07)
_form_buffers(device, combine_data_ukp2, 2, dictionary_yau07)
func _on_text_temperature_changed(device: String, number_device: int) -> Array:
@@ -167,9 +174,31 @@ static func _form_buffers(device: String, ukp_data: Array, number_device: int, d
var udp_unit = dic_yau07[device]
if number_device == 1:
udp_unit.ukp0_data = buffer
print("Данные UKP0 устройства %s обновлены" % device)
elif number_device == 2:
udp_unit.ukp1_data = buffer
print("Данные UKP1 устройства %s обновлены" % device)
static func _set_bit(bits: int, index: int, val: bool) -> int:
return bits | (1 << index) if val else bits & ~(1 << index)
## Новый метод для работы с ISA портами (если потребуется)
func read_isa_ports(device: String, port_addresses: Array) -> Dictionary:
"""Чтение ISA портов указанного устройства"""
if dictionary_yau07.has(device):
return dictionary_yau07[device].read_isa_ports(port_addresses)
else:
push_error("Устройство %s не найдено" % device)
return {}
## Новый метод для записи ISA портов (если потребуется)
func write_isa_port(device: String, port_address: int, value: int) -> bool:
"""Запись значения в ISA порт указанного устройства"""
if dictionary_yau07.has(device):
return dictionary_yau07[device].set_isa_port(port_address, value)
else:
push_error("Устройство %s не найдено" % device)
return false

View File

@@ -581,6 +581,7 @@ metadata/place = 13
metadata/device = "ПРД-В1"
[node name="dkm" type="GridContainer" parent="TabContainer/ПРД-В1"]
layout_mode = 0
offset_left = 10.0
offset_top = 201.0
offset_right = 50.0
@@ -639,6 +640,7 @@ metadata/bit = 4
metadata/device = "ПРД-К1"
[node name="ukp_1" type="GridContainer" parent="TabContainer/ПРД-К1"]
layout_mode = 0
offset_left = 205.0
offset_top = 7.0
offset_right = 939.0
@@ -732,6 +734,7 @@ metadata/place = 5
metadata/device = "ПРД-К1"
[node name="ukp_1_lit_1" type="GridContainer" parent="TabContainer/ПРД-К1"]
layout_mode = 0
offset_left = 205.0
offset_top = 195.0
offset_right = 939.0
@@ -765,6 +768,7 @@ metadata/place = 0
metadata/device = "ПРД-К1"
[node name="ukp_2" type="GridContainer" parent="TabContainer/ПРД-К1"]
layout_mode = 0
offset_left = 205.0
offset_top = 103.0
offset_right = 939.0
@@ -858,6 +862,7 @@ metadata/place = 13
metadata/device = "ПРД-К1"
[node name="dkm" type="GridContainer" parent="TabContainer/ПРД-К1"]
layout_mode = 0
offset_left = 10.0
offset_top = 201.0
offset_right = 50.0

View File

@@ -1,6 +1,24 @@
class_name UDPBroadcast
const addres_list: Dictionary = {
# Константы для размеров данных и смещений
const STATUS_PACKET_SIZE: int = 103
const HEADER_SIZE: int = 8
const EMS_G_DATA_OFFSET: int = 9
const EMS_G_DATA_SIZE: int = 26 # 13 * 2 байта
const UG_DATA_OFFSET: int = 35
const UKP0_DATA_OFFSET: int = 39
const UKP1_DATA_OFFSET: int = 71
const UKP_DATA_SIZE: int = 32
# Константы команд ISA
const CMD_READ_ISA: int = 0
const CMD_WRITE_ISA: int = 1
# Минимальный размер пакета для валидации
const MIN_PACKET_SIZE: int = 7
# Словарь адресов устройств
const ADDRESS_LIST: Dictionary = {
'ПРД-Н1': [50011, "10.1.1.11"],
'ПРД-В1': [50012, "10.1.1.12"],
'ПРД-К1': [50013, "10.1.1.13"],
@@ -14,133 +32,536 @@ const addres_list: Dictionary = {
'ПРД-В4': [50042, "10.1.1.42"],
'ПРД-К4': [50043, "10.1.1.43"],
}
const broadcast_addr: Array = [50000, "10.1.1.255"]
#const bind_addr: Array = [50_000, "10.1.1.70"] TODO: Порт по умолчанию
var _socket: SocketUDP
var self_name: String
var _timer: Timer
var sockets_status_bit: int = 0
var dkm_status_bit: int = 0
# Широковещательный адрес
const BROADCAST_ADDR: Array = [50000, "10.1.1.255"]
# Приватные свойства
var _socket: SocketUDP
var _self_name: String
var _timer: Timer
var _poll_timer: Timer
var _sockets_status_bit: int = 0
var _dkm_status_bit: int = 0
var _isa_ports: Dictionary = {}
var _cmd_number_count: int = 0
var _written_isa_ports: Array = []
var _last_received_command: int = -1
# Публичные свойства с контролем доступа
var ukp0_data: PackedByteArray:
set(v):
ukp0_data = v
print('Произошло Обновление данных ukp0_data')
set(value):
if value.size() == UKP_DATA_SIZE:
ukp0_data = value
print('Данные UKP0 обновлены')
var ukp1_data: PackedByteArray:
set(v):
ukp1_data = v
print('Произошло Обновление данных ukp1_data')
set(value):
if value.size() == UKP_DATA_SIZE:
ukp1_data = value
print('Данные UKP1 обновлены')
func _init(name: String):
self_name = name
"""Инициализация UDP broadcast клиента"""
_self_name = name
_initialize_socket()
_initialize_ukp_data()
_initialize_timers()
if not _bind_to_device_address(name):
push_error("Не удалось инициализировать устройство: %s" % name)
func _initialize_socket() -> void:
"""Инициализация UDP сокета"""
_socket = SocketUDP.new()
func _initialize_timers() -> void:
"""Инициализация таймеров"""
# Таймер для широковещательной рассылки (3 раза в секунду)
_timer = Timer.new()
_timer.wait_time = 1.0 / 3.0
_timer.timeout.connect(_on_timer_timeout)
ukp0_data.resize(32)
_timer.timeout.connect(_on_broadcast_timeout)
# Таймер для частого опроса сокета (100 раз в секунду)
_poll_timer = Timer.new()
_poll_timer.wait_time = 0.01
_poll_timer.timeout.connect(_on_poll_timeout)
func _initialize_ukp_data() -> void:
"""Инициализация данных UKP нулевыми значениями"""
ukp0_data = PackedByteArray()
ukp0_data.resize(UKP_DATA_SIZE)
ukp0_data.fill(0)
ukp1_data.resize(32)
ukp1_data = PackedByteArray()
ukp1_data.resize(UKP_DATA_SIZE)
ukp1_data.fill(0)
if addres_list.has(name):
var port: int = addres_list[name][0]
var addr: String = addres_list[name][1]
bind_unit_addres(port, addr)
else:
push_error("Неизвестное устройство: %s" % name)
func _bind_to_device_address(device_name: String) -> bool:
"""Привязка к адресу устройства по его имени"""
if not ADDRESS_LIST.has(device_name):
push_error("Неизвестное устройство: %s" % device_name)
return false
var port: int = ADDRESS_LIST[device_name][0]
var address: String = ADDRESS_LIST[device_name][1]
return bind_unit_address(port, address)
func bind_unit_addres(port_for_bind: int, addr_for_bind: String) -> void:
var bind_result = _socket.bind(port_for_bind, addr_for_bind)
func bind_unit_address(port: int, address: String) -> bool:
"""Привязка сокета к указанному порту и адресу"""
if port <= 0 or port > 65535:
push_error("Некорректный номер порта: %d" % port)
return false
var bind_result = _socket.bind(port, address)
if bind_result != OK:
push_error("Не удалось привязаться к %s: %s" % [addr_for_bind, error_string(bind_result)])
push_error("Не удалось привязаться к %s:%d - %s" % [address, port, error_string(bind_result)])
return false
func start_broadcast() -> void:
_timer.start()
func stop_broadcast() -> void:
_timer.stop()
func send_broadcast() -> bool:
_socket.set_broadcast_enabled(true)
var data: PackedByteArray = _form_status_packet()
# добавление 11 байтов вперед вохоже
_socket.send_to(broadcast_addr[1], broadcast_addr[0], data)
print("Успешно привязано к %s:%d" % [address, port])
return true
func close_udp_unit() -> void:
func add_timers_to_scene(parent: Node) -> void:
"""Добавление таймеров в дерево сцены"""
# Проверяем что таймеры еще не имеют родителя
if not _timer.get_parent():
parent.add_child(_timer)
elif _timer.get_parent() != parent:
push_warning("Таймер broadcast уже добавлен в другую сцену")
if not _poll_timer.get_parent():
parent.add_child(_poll_timer)
elif _poll_timer.get_parent() != parent:
push_warning("Таймер poll уже добавлен в другую сцену")
func start_broadcast() -> void:
"""Запуск широковещательной рассылки и опроса сокета"""
_timer.start()
_poll_timer.start()
print("Широковещательная рассылка запущена")
func stop_broadcast() -> void:
"""Остановка широковещательной рассылки"""
_timer.stop()
_poll_timer.stop()
print("Широковещательная рассылка остановлена")
func close_udp_unit() -> void:
"""Закрытие UDP соединения"""
stop_broadcast()
_socket.close()
print("UDP соединение закрыто")
func add_timer_to_scene(parent: Node) -> void:
parent.add_child(_timer)
#region Публичные методы для управления состоянием
func set_sockets_status(status: int) -> void:
"""Установка статуса сокетов"""
_sockets_status_bit = status
func poll_receive() -> void:
while _socket.get_available_packet_count() > 0:
var broadcast_packet = _socket.get_packet()
var addr_receive = _socket.get_packet_ip()
#var port_receive = _socket.get_packet_port()
#var parsed_data = _parse_packet(broadcast_packet)
_handle_received_data(broadcast_packet, addr_receive)
func get_sockets_status() -> int:
"""Получение статуса сокетов"""
return _sockets_status_bit
func _handle_received_data(data: PackedByteArray, addr: String) -> void:
print("данные от %s: %s" % [addr, data])
# Здесь можно эмитировать сигналы или обрабатывать данные
func set_dkm_status(status: int) -> void:
"""Установка статуса DKM"""
_dkm_status_bit = status
func _on_timer_timeout() -> void:
func get_dkm_status() -> int:
"""Получение статуса DKM"""
return _dkm_status_bit
func set_isa_port(port_addr: int, value: int) -> bool:
"""Установка значения ISA порта"""
if port_addr < 0 or port_addr > 0xFFFF:
push_error("Некорректный адрес порта: 0x%04X" % port_addr)
return false
_isa_ports[port_addr] = value
return true
func get_isa_port(port_addr: int) -> int:
"""Получение значения ISA порта"""
return _isa_ports.get(port_addr, 0xFFFF)
func read_isa_ports(port_addresses: Array) -> Dictionary:
"""Чтение значений нескольких ISA портов"""
var result = {}
for port_addr in port_addresses:
if port_addr is int and port_addr >= 0 and port_addr <= 0xFFFF:
result[port_addr] = get_isa_port(port_addr)
else:
push_error("UDPBroadcast: Некорректный адрес порта: " + str(port_addr))
return result
#endregion
#region Обработчики таймеров
func _on_broadcast_timeout() -> void:
"""Обработчик таймера широковещательной рассылки"""
send_broadcast()
func _form_status_packet() -> PackedByteArray:
var buf = PackedByteArray()
buf.resize(126) # Увеличиваем размер до 126 байт
func _on_poll_timeout() -> void:
"""Обработчик таймера опроса сокета"""
_poll_socket()
# Заголовок (0-5 байты)
buf.encode_u16(0, 0) # 00 00
buf.encode_u16(2, 0x0cff) # ff 0c
buf.encode_u16(4, 0) # 00 00
#endregion
# Идентификатор пакета
buf[6] = 103 # 67
#region Работа с сокетом
# Статус устройств
buf[7] = 0
buf[8] = sockets_status_bit
func send_broadcast() -> bool:
"""Отправка широковещательного пакета"""
_socket.set_broadcast_enabled(true)
var data: PackedByteArray = _form_status_device_packet()
var send_result = _socket.send_to(BROADCAST_ADDR[1], BROADCAST_ADDR[0], data)
# Данные EMS-G (байты 9-34)
var ems_g_data = [0x9e00, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x0000,
0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff]
for i in range(13):
buf.encode_u16(9 + i * 2, ems_g_data[i])
# Данные UG (байты 35-38)
buf.encode_u8(35, 0x00)
buf.encode_u8(36, dkm_status_bit)
buf.encode_u16(37, 0x059e) # 9e 05
# Данные UKP0 (байты 39-70)
for i in ukp0_data.size():
buf[39 + i] = ukp0_data[i]
# Данные UKP1 (байты 71-102)
for i in ukp1_data.size():
buf[71 + i] = ukp1_data[i]
return buf
if send_result == OK:
return true
else:
push_error("Ошибка отправки широковещательного пакета")
return false
####
func _poll_socket() -> void:
"""Опрос сокета для получения входящих пакетов"""
while _socket.get_available_packet_count() > 0:
var packet = _socket.get_packet()
var address = _socket.get_packet_ip()
var port = _socket.get_packet_port()
_handle_received_data(packet, address, port)
#endregion
#region Формирование пакета статуса устройства
func _form_status_device_packet() -> PackedByteArray:
var buffer = PackedByteArray()
# Базовый размер пакета + дополнительные байты для записанных портов
# + 2 байта для полей команды (код + результат)
var header_size = 8
var ports_count_size = 1
var cmd_fields_size = 0
var isa_ports_size = 0
if _written_isa_ports.size() > 0:
isa_ports_size = _written_isa_ports.size() * 4
cmd_fields_size = 4
var total_size = header_size + STATUS_PACKET_SIZE + ports_count_size + cmd_fields_size + isa_ports_size
buffer.resize(total_size)
buffer.fill(0)
_encode_packet_header(buffer)
_encode_device_data(buffer)
print('_written_isa_ports.size(): ', _written_isa_ports.size())
# Добавляем поле команды после статуса
if _written_isa_ports.size() > 0:
var cmd_offset = header_size + STATUS_PACKET_SIZE
if cmd_offset < buffer.size():
buffer.encode_u16(cmd_offset, _last_received_command) # код команды (0 для статуса)
if (cmd_offset + 1) < buffer.size():
buffer.encode_u16(cmd_offset+1, 1) # результат выполнения
var ports_count_offset = cmd_offset + 2
# Затем ISA порты
buffer.encode_u8(ports_count_offset, _written_isa_ports.size())
_encode_written_isa_ports(buffer, ports_count_offset+1)
return buffer
func _encode_packet_header(buffer: PackedByteArray) -> void:
"""Кодирование заголовка пакета"""
# 0-1: Reserved (0x0000)
buffer.encode_u16(0, 0)
# 2-3: Номер команды
buffer.encode_u16(2, _cmd_number_count)
# 4-5: Reserved (0x0000)
buffer.encode_u16(4, 0)
# 6-7: Длина статуса
buffer.encode_u16(6, STATUS_PACKET_SIZE)
func _encode_written_isa_ports(buffer: PackedByteArray, offset: int) -> void:
"""Добавление данных о записанных ISA портах в конец пакета"""
for i in range(_written_isa_ports.size()):
var port_data = _written_isa_ports[i]
# Добавляем порт и значение (по 2 байта каждый)
buffer.encode_u16(offset, port_data[0])
buffer.encode_u16(offset + 2, port_data[1])
offset += 4
func _encode_device_data(buffer: PackedByteArray) -> void:
"""Кодирование данных устройств в пакет"""
# 8-9: Статус сокетов
buffer.encode_u16(8, _sockets_status_bit)
# 9-34: Данные EMS-G
_encode_ems_g_data(buffer)
# 35-38: Данные UG
_encode_ug_data(buffer)
# 39-70: Данные UKP0
# 71-102: Данные UKP1
_encode_ukp_data(buffer)
func _encode_ems_g_data(buffer: PackedByteArray) -> void:
"""Кодирование данных EMS-G"""
var ems_g_data = [
0x9e00, 0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0x0000,
0xffff, 0xffff, 0x0000, 0xffff, 0xffff, 0xffff
]
for i in range(ems_g_data.size()):
buffer.encode_u16(EMS_G_DATA_OFFSET + i * 2, ems_g_data[i])
func _encode_ug_data(buffer: PackedByteArray) -> void:
"""Кодирование данных UG"""
buffer.encode_u16(UG_DATA_OFFSET, _dkm_status_bit) # Статус DKM
buffer.encode_u16(UG_DATA_OFFSET + 2, 0x059e) # DRY CONTACT
func _encode_ukp_data(buffer: PackedByteArray) -> void:
"""Кодирование данных UKP"""
for i in range(UKP_DATA_SIZE):
if i < ukp0_data.size():
buffer[UKP0_DATA_OFFSET + i] = ukp0_data[i]
if i < ukp1_data.size():
buffer[UKP1_DATA_OFFSET + i] = ukp1_data[i]
#endregion
#region Прямая отправка ответа
func _send_immediate_response(address: String, port: int) -> void:
"""Немедленная отправка пакета на указанный адрес и порт"""
var data: PackedByteArray = _form_status_device_packet()
_socket.set_broadcast_enabled(false) # Отключаем broadcast для точечной отправки
var send_result = _socket.send_to(address, port, data)
_socket.set_broadcast_enabled(true) # Включаем обратно для broadcast
if send_result == OK:
print("Отправлен немедленный ответ на %s:%d" % [address, port])
else:
push_error("Ошибка отправки ответа на %s:%d" % [address, port])
#endregion
#region Обработка входящих данных
func _handle_received_data(data: PackedByteArray, address: String, port: int) -> void:
"""Обработка входящих данных"""
if not _validate_received_packet(data):
return
var command_type = _get_command_type(data)
if command_type == -1: # Проверяем на -1 вместо null
return
_cmd_number_count = (_cmd_number_count + 1) & 0xFFFF
_handle_isa_command(command_type, data, address, port)
func _validate_received_packet(data: PackedByteArray) -> bool:
"""Валидация входящего пакета"""
if data.size() < MIN_PACKET_SIZE:
push_warning("Получен слишком короткий пакет: %d байт" % data.size())
return false
return true
func _get_command_type(data: PackedByteArray) -> int:
"""Получение типа команды из данных пакета"""
if data.size() < 7:
return -1 # Используем -1 для обозначения ошибки
# Определяем длину статуса из заголовка
var status_length = data.decode_u8(7)
if data.size() <= (status_length + 8):
return -1 # Используем -1 для обозначения ошибки
return data.decode_u8(6)
func _handle_isa_command(command_code: int, data: PackedByteArray, address: String, port: int) -> void:
"""Обработка команд ISA"""
_last_received_command = command_code # Запоминаем последнюю команду
match command_code:
CMD_READ_ISA:
_handle_read_isa_command(data, address, port)
CMD_WRITE_ISA:
_handle_write_isa_command(data, address, port)
_:
push_warning("Неизвестная команда ISA: %d от %s:%d" % [command_code, address, port])
func _handle_read_isa_command(data: PackedByteArray, address: String, port: int) -> void:
"""Обработка команды чтения ISA портов"""
var ports = _parse_command_ports(data)
if ports.is_empty():
return
var port_data = _get_isa_ports_data(ports)
print('Принята команда на чтение ISA портов от %s:%d: %s' % [address, port, port_data])
func _handle_write_isa_command(data: PackedByteArray, address: String, port: int) -> void:
"""Обработка команды записи ISA портов"""
var ports = _parse_command_ports(data)
var data_to_write = _parse_command_ports_data(data)
if ports.size() != data_to_write.size():
push_warning("Несоответствие размеров портов и данных от %s:%d" % [address, port])
return
var added_ports = 0
var updated_ports = 0
# Обновляем или добавляем записанные порты
for i in range(ports.size()):
var port_addr = ports[i]
var value = data_to_write[i]
set_isa_port(port_addr, value)
# Ищем порт в массиве, если есть - обновляем, если нет - добавляем
var found = false
for j in range(_written_isa_ports.size()):
if _written_isa_ports[j][0] == port_addr:
_written_isa_ports[j][1] = value # Обновляем значение
found = true
updated_ports += 1
break
if not found:
_written_isa_ports.append([port_addr, value]) # Добавляем новый порт
added_ports += 1
# Выводим суммарное сообщение вместо спама для каждого порта
if added_ports > 0 or updated_ports > 0:
print("Обработана команда записи от %s:%d - добавлено: %d, обновлено: %d портов" % [address, port, added_ports, updated_ports])
print('Принята команда на запись в ISA порты от %s:%d: %s' % [address, port, _isa_ports])
# Немедленная отправка ответа отправителю
_send_immediate_response(address, port)
#endregion
#region Парсинг команд ISA
func _parse_command_ports(data: PackedByteArray) -> Array:
"""Парсинг адресов портов из команды"""
if data.size() < 7:
return []
var ports_count = data.decode_u8(7)
if data.size() <= (ports_count + 8):
return []
var ports = []
for i in range(ports_count):
var port_address = data.decode_u16(8 + i * 2)
ports.append(port_address)
print("Порт %d: 0x%04X" % [i, port_address])
return ports
func _parse_command_ports_data(data: PackedByteArray) -> Array:
"""Парсинг данных портов из команды записи"""
if data.size() < 8:
return []
var ports_count = data.decode_u8(7)
if data.size() <= (ports_count + 10):
return []
var ports_data = []
var data_offset = 10 # Смещение для данных портов
for i in range(ports_count):
if data_offset + i * 2 < data.size():
var port_data = data.decode_u16(data_offset + i * 2)
ports_data.append(port_data)
print("Данные порта %d: 0x%04X" % [i, port_data])
return ports_data
func _get_isa_ports_data(ports: Array) -> Array:
"""Получение данных указанных ISA портов"""
var result = []
for port_address in ports:
result.append(get_isa_port(port_address))
return result
func _set_isa_ports_data(ports: Array, data: Array) -> void:
"""Установка данных для указанных ISA портов"""
for i in range(ports.size()):
if i < data.size():
set_isa_port(ports[i], data[i])
#endregion
#region Вложенный класс SocketUDP
class SocketUDP extends PacketPeerUDP:
func send_to(addr: String, port: int, data: PackedByteArray):
set_dest_address(addr, port)
var rc: = put_packet(data)
if rc != OK:
push_error('%s: %s:%s' % [error_string(rc), addr, port])
"""Расширенный класс UDP сокета с улучшенной обработкой ошибок"""
func send_to(address: String, port: int, data: PackedByteArray) -> int:
"""Отправка данных на указанный адрес и порт"""
set_dest_address(address, port)
var result = put_packet(data)
if result != OK:
push_error('Ошибка отправки: %s - %s:%d' % [error_string(result), address, port])
return result
#endregion
#region Методы управления записанными портами
func clear_written_ports() -> void:
"""Очистка списка записанных портов (ручное управление)"""
_written_isa_ports.clear()
print("Список записанных портов очищен")
func get_written_ports_count() -> int:
"""Получение количества записанных портов"""
return _written_isa_ports.size()
func remove_written_port(port_addr: int) -> bool:
"""Удаление конкретного порта из списка записанных"""
for i in range(_written_isa_ports.size()):
if _written_isa_ports[i][0] == port_addr:
_written_isa_ports.remove_at(i)
print("Порт 0x%04X удален из списка записанных" % port_addr)
return true
return false
#endregion