From 39bef3a351a3220df3d091e6ce9516e945cd6e91 Mon Sep 17 00:00:00 2001
From: TotMaxim
Date: Fri, 21 Nov 2025 13:02:32 +0300
Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D1=82=D0=BE?=
=?UTF-8?q?=D0=BA=D0=B0=20=D0=B0=D1=82=D1=82=20=D0=B8=20=D1=81=D1=82=D0=B0?=
=?UTF-8?q?=D1=82=D1=83=D1=81=20=D0=BC=D0=B5=D0=BD=D0=B5=D0=B4=D0=B6=D0=B5?=
=?UTF-8?q?=D1=80=D0=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
StatusManager.gd | 55 +++++++++++++++++++++
StatusManager.gd.uid | 1 +
main.gd | 113 ++++++++++++++++++++++++++++---------------
main.tscn | 2 +-
udp_broadcast.gd | 46 +++---------------
5 files changed, 137 insertions(+), 80 deletions(-)
create mode 100644 StatusManager.gd
create mode 100644 StatusManager.gd.uid
diff --git a/StatusManager.gd b/StatusManager.gd
new file mode 100644
index 0000000..1b73c91
--- /dev/null
+++ b/StatusManager.gd
@@ -0,0 +1,55 @@
+class_name StatusManager
+extends RefCounted
+
+var _device
+
+func _init(device):
+ _device = device
+ Callable(_emit_initial_ports).call_deferred()
+
+
+func _emit_initial_ports() -> void:
+ """Вывод начального состояния через существующий сигнал UDPBroadcast"""
+ # Просто устанавливаем текущие значения (это вызовет update_isa_ports)
+ var current_106 = _device.get_isa_port(0x106)
+ var current_108 = _device.get_isa_port(0x108)
+
+ # Триггерим обновление через установку тех же значений
+ _device.set_isa_port(0x106, current_106)
+ _device.set_isa_port(0x108, current_108)
+
+# Универсальные методы для работы с битовыми полями
+func set_status_field(port: int, value: int, bit_mask: int, shift: int = 0) -> void:
+ var current_value = _device.get_isa_port(port)
+ var masked_value = (value & bit_mask) << shift
+ var clear_mask = ~(bit_mask << shift) & 0xFF
+ var new_value = (current_value & clear_mask) | masked_value
+ _device.set_isa_port(port, new_value)
+
+func get_status_field(port: int, bit_mask: int, shift: int = 0) -> int:
+ return (_device.get_isa_port(port) >> shift) & bit_mask
+
+# Специфичные методы для каждого статуса
+func set_dou2_status(status: int) -> void:
+ set_status_field(0x106, status, 0b111, 0)
+
+func get_dou2_status() -> int:
+ return get_status_field(0x106, 0b111, 0)
+
+func set_att2_status(status: int) -> void:
+ set_status_field(0x106, status, 0b111, 3)
+
+func get_att2_status() -> int:
+ return get_status_field(0x106, 0b111, 3)
+
+func set_dou3_status(status: int) -> void:
+ set_status_field(0x108, status, 0b111, 0)
+
+func get_dou3_status() -> int:
+ return get_status_field(0x108, 0b111, 0)
+
+func set_att3_status(status: int) -> void:
+ set_status_field(0x108, status, 0b111, 3)
+
+func get_att3_status() -> int:
+ return get_status_field(0x108, 0b111, 3)
diff --git a/StatusManager.gd.uid b/StatusManager.gd.uid
new file mode 100644
index 0000000..7088d0c
--- /dev/null
+++ b/StatusManager.gd.uid
@@ -0,0 +1 @@
+uid://ddgp4l3kdjwg2
diff --git a/main.gd b/main.gd
index 9d47c5c..af8aa76 100644
--- a/main.gd
+++ b/main.gd
@@ -114,11 +114,19 @@ func _ready() -> void:
var dou2_arr_node: Array = get_tree().get_nodes_in_group('dou2')
for dou2 in dou2_arr_node:
- dou2.connect('toggled', _on_modify_dou2.bind(dou2.get_meta('bit'), dou2.get_meta('device')))
-
+ dou2.toggled.connect(_on_modify_status.bind(dou2.get_meta('bit'), dou2.get_meta('device'), "dou2"))
+
var dou3_arr_node: Array = get_tree().get_nodes_in_group('dou3')
for dou3 in dou3_arr_node:
- dou3.connect('toggled', _on_modify_dou3.bind(dou3.get_meta('bit'), dou3.get_meta('device')))
+ dou3.toggled.connect(_on_modify_status.bind(dou3.get_meta('bit'), dou3.get_meta('device'), "dou3"))
+
+ var att2_arr_node: Array = get_tree().get_nodes_in_group('att2')
+ for att2 in att2_arr_node:
+ att2.toggled.connect(_on_modify_status.bind(att2.get_meta('bit'), att2.get_meta('device'), "att2"))
+
+ var att3_arr_node: Array = get_tree().get_nodes_in_group('att3')
+ for att3 in att3_arr_node:
+ att3.toggled.connect(_on_modify_status.bind(att3.get_meta('bit'), att3.get_meta('device'), "att3"))
var ip_arr_node: Array = get_tree().get_nodes_in_group('ip')
for ip in ip_arr_node:
@@ -146,6 +154,7 @@ func on_modify_device(toggled: bool, name_device: String) -> void:
udp_broadcast.start_broadcast()
dictionary_yau07[name_device] = udp_broadcast
print("Устройство %s активировано" % name_device)
+ dictionary_yau07[name_device].connect('update_isa_ports', _on_update_isa_ports)
else:
if dictionary_yau07.has(name_device) and dictionary_yau07[name_device]:
dictionary_yau07[name_device].close_udp_unit()
@@ -182,6 +191,38 @@ func _update_tab_container():
tab_container.visible = has_visible_tabs
+func _on_update_isa_ports(isa_ports: Dictionary)->void:
+ for port_addr in isa_ports:
+ var value = isa_ports[port_addr]
+
+ # Группы кнопок обновлять для каждого порта
+ var port_configs = {
+ 0x106: [ # Порт 0x106
+ {'group': 'dou2', 'mask': 0b111, 'shift': 0},
+ {'group': 'att2', 'mask': 0b111, 'shift': 3}
+ ],
+ 0x108: [ # Порт 0x108
+ {'group': 'dou3', 'mask': 0b111, 'shift': 0},
+ {'group': 'att3', 'mask': 0b111, 'shift': 3}
+ ]
+ }
+
+ if port_configs.has(port_addr):
+ for config in port_configs[port_addr]:
+ var status = (value >> config.shift) & config.mask
+ _update_button_group(config.group, status)
+
+
+func _update_button_group(group_name: String, status: int) -> void:
+ """Обновление всех кнопок в группе на основе статуса"""
+ var buttons = get_tree().get_nodes_in_group(group_name)
+ for button in buttons:
+ if button.has_meta('bit'):
+ var bit_value = button.get_meta('bit')
+ var should_be_pressed = (status == bit_value)
+ button.set_pressed_no_signal(should_be_pressed)
+
+
## Функция для установки статусов ячеек на связи (УГ, ЭМС-Г, УКП)
func _on_modify_sockets(toggled: bool, bit: int, device: String)->void:
if dictionary_yau07.has(device):
@@ -202,43 +243,35 @@ func _on_modify_dkm(toggled: bool, bit: int, device: String)->void:
print("Статус DKM устройства %s обновлен: 0x%04X" % [device, new_status])
-## Функция для установки статусов ДОУ2 в ПРД
-func _on_modify_dou2(toggled: bool, bit: int, device: String)->void:
+func _on_modify_status(toggled: bool, bit: int, device: String, status_type: String) -> void:
+ if not dictionary_yau07.has(device):
+ return
+
+ var udp_unit = dictionary_yau07[device]
+ var button_group = get_tree().get_nodes_in_group(status_type)
+
if not toggled:
- var dou2_arr_node = get_tree().get_nodes_in_group('dou2')
- for dou2 in dou2_arr_node:
- if dou2.has_meta('bit') and dou2.get_meta('bit') == bit:
- dou2.set_pressed(true)
- if toggled:
- var dou2_arr_node = get_tree().get_nodes_in_group('dou2')
- for dou2 in dou2_arr_node:
- if dou2.has_meta('bit') and dou2.get_meta('bit') != bit and dou2.button_pressed:
- dou2.set_pressed_no_signal(false)
+ # Восстанавливаем предыдущее состояние
+ for button in button_group:
+ if button.has_meta('bit') and button.get_meta('bit') == bit:
+ button.set_pressed(true)
+ return
- # Всегда устанавливаем статус, если кнопка нажата
- if toggled and dictionary_yau07.has(device):
- var udp_unit = dictionary_yau07[device]
- udp_unit.set_dou2_status(bit)
-
-
-## Функция для установки статусов ДОУ3 в ПРД
-func _on_modify_dou3(toggled: bool, bit: int, device: String)->void:
- if not toggled:
- var dou3_arr_node = get_tree().get_nodes_in_group('dou3')
- for dou3 in dou3_arr_node:
- if dou3.has_meta('bit') and dou3.get_meta('bit') == bit:
- dou3.set_pressed(true)
-
- if toggled:
- var dou3_arr_node = get_tree().get_nodes_in_group('dou3')
- for dou3 in dou3_arr_node:
- if dou3.has_meta('bit') and dou3.get_meta('bit') != bit and dou3.button_pressed:
- dou3.set_pressed_no_signal(false)
-
- # Всегда устанавливаем статус, если кнопка нажата
- if toggled and dictionary_yau07.has(device):
- var udp_unit = dictionary_yau07[device]
- udp_unit.set_dou3_status(bit)
+ # Выключаем другие кнопки в группе
+ for button in button_group:
+ if button.has_meta('bit') and button.get_meta('bit') != bit and button.button_pressed:
+ button.set_pressed_no_signal(false)
+ print('button_press_bit: ', bit)
+ # Устанавливаем статус через менеджер
+ match status_type:
+ "dou2":
+ udp_unit.status_manager.set_dou2_status(bit)
+ "att2":
+ udp_unit.status_manager.set_att2_status(bit)
+ "dou3":
+ udp_unit.status_manager.set_dou3_status(bit)
+ "att3":
+ udp_unit.status_manager.set_att3_status(bit)
func _on_modify_ip(toggled: bool, bit: int, device: String):
@@ -374,7 +407,7 @@ static func _set_bit(bits: int, index: int, val: bool) -> int:
return bits | (1 << index) if val else bits & ~(1 << index)
-## Новый метод для работы с ISA портами (если потребуется)
+## Новый метод для работы с ISA портами
func read_isa_ports(device: String, port_addresses: Array) -> Dictionary:
"""Чтение ISA портов указанного устройства"""
if dictionary_yau07.has(device):
@@ -384,7 +417,7 @@ func read_isa_ports(device: String, port_addresses: Array) -> Dictionary:
return {}
-## Новый метод для записи ISA портов (если потребуется)
+## Новый метод для записи ISA портов
func write_isa_port(device: String, port_address: int, value: int) -> bool:
"""Запись значения в ISA порт указанного устройства"""
if dictionary_yau07.has(device):
diff --git a/main.tscn b/main.tscn
index 63d3f88..25a4541 100644
--- a/main.tscn
+++ b/main.tscn
@@ -440,8 +440,8 @@ layout_mode = 2
[node name="CheckBox" type="CheckBox" parent="TabContainer/ПРД-Н1/TabBar/ug/GridContainer2" groups=["att2"]]
layout_mode = 2
text = "АТТ 0 dB"
-metadata/att = 0
metadata/device = "ПРД-Н1"
+metadata/bit = 0
[node name="CheckBox2" type="CheckBox" parent="TabContainer/ПРД-Н1/TabBar/ug/GridContainer2" groups=["att2"]]
layout_mode = 2
diff --git a/udp_broadcast.gd b/udp_broadcast.gd
index ac96470..83e5cd7 100644
--- a/udp_broadcast.gd
+++ b/udp_broadcast.gd
@@ -37,6 +37,7 @@ const ADDRESS_LIST: Dictionary = {
const BROADCAST_ADDR: Array = [50000, "10.1.1.255"]
# Приватные свойства
+var status_manager: StatusManager
var _socket: SocketUDP
var _self_name: String
var _isa_ports: Dictionary = {}
@@ -47,27 +48,15 @@ var _dkm_status_bit: int = 0
var _dry_contact_status_bit: int = 0xFF
var _cmd_number_count: int = 0
var _last_received_command: int = -1
+var ukp0_data: PackedByteArray
+var ukp1_data: PackedByteArray
-
-# Публичные свойства с контролем доступа
-var ukp0_data: PackedByteArray:
- set(value):
- if value.size() == UKP_DATA_SIZE:
- ukp0_data = value
- print('Данные UKP0 обновлены')
-
-
-var ukp1_data: PackedByteArray:
- set(value):
- if value.size() == UKP_DATA_SIZE:
- ukp1_data = value
- print('Данные UKP1 обновлены')
-
-
+signal update_isa_ports(_isa_ports: Dictionary)
func _init(name: String):
"""Инициализация UDP broadcast клиента"""
+ status_manager = StatusManager.new(self)
_self_name = name
_initialize_socket()
_initialize_ukp_data()
@@ -199,28 +188,6 @@ func get_dkm_status() -> int:
return _dkm_status_bit
-func set_dou2_status(status: int) -> void:
- """Установка статуса DOU"""
- var masked_status = status & 0b111 # Маска для первых 3 битов
- set_isa_port(0x106, masked_status)
-
-
-func get_dou2_status() -> int:
- """Получение статуса DOU"""
- return get_isa_port(0x106) & 0b111
-
-
-func set_dou3_status(status: int) -> void:
- """Установка статуса DOU"""
- var masked_status = status & 0b111 # Маска для первых 3 битов
- set_isa_port(0x108, masked_status)
-
-
-func get_dou3_status() -> int:
- """Получение статуса DOU"""
- return get_isa_port(0x108) & 0b111
-
-
func set_ip_status(status: int)->void:
"""Установка статуса ИП"""
_dry_contact_status_bit = status
@@ -234,10 +201,11 @@ func get_ip_status()->int:
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)
+ push_error("Некорректный адрес порта: 0x%03X" % port_addr)
return false
_isa_ports[port_addr] = value
+ emit_signal('update_isa_ports', _isa_ports)
return true