395 lines
17 KiB
GDScript
395 lines
17 KiB
GDScript
extends Control
|
||
|
||
const CONFIG_PATH = "res://config/default_data.json"
|
||
const BUFFER_SIZE = 32
|
||
var udp_broadcast: UDPBroadcast
|
||
var default_data: Dictionary = {}
|
||
var dictionary_yau07: Dictionary
|
||
var dictionary_sockets_bit: Dictionary ## Байт 8 для отправки о состоянии ячеек
|
||
|
||
func _load_default_data():
|
||
var file = FileAccess.open(CONFIG_PATH, FileAccess.READ)
|
||
if file:
|
||
var json = JSON.new()
|
||
var error = json.parse(file.get_as_text())
|
||
if error == OK:
|
||
default_data = json.data["default_data"]
|
||
else:
|
||
push_error("JSON Parse Error: ", json.get_error_message())
|
||
file.close()
|
||
else:
|
||
push_error("Failed to load config file: ", CONFIG_PATH)
|
||
|
||
|
||
func _apply_default_data():
|
||
var prd_nodes = get_tree().get_nodes_in_group('prd')
|
||
|
||
for prd in prd_nodes:
|
||
var device_name = prd.get_meta('yau07')
|
||
if default_data.has(device_name):
|
||
var device_data = default_data[device_name]
|
||
_fill_ukp_fields(prd, device_data)
|
||
|
||
|
||
# Заполняем поля температур
|
||
func _fill_ukp_fields(prd_node: Control, device_data: Dictionary):
|
||
var device_name = prd_node.get_meta('yau07')
|
||
|
||
# Заполняем поля температур
|
||
var temp_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "temperature_ukp")
|
||
if device_data.has("temperature_ukp"):
|
||
for i in range(min(temp_fields.size(), device_data["temperature_ukp"].size())):
|
||
temp_fields[i].text = str(device_data["temperature_ukp"][i])
|
||
|
||
# Заполняем поля мощности
|
||
var power_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "power_ukp")
|
||
if device_data.has("power_ukp"):
|
||
for i in range(min(power_fields.size(), device_data["power_ukp"].size())):
|
||
power_fields[i].text = str(device_data["power_ukp"][i])
|
||
|
||
# Устанавливаем состояния сокетов
|
||
if device_data.has("sockets"):
|
||
var socket_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "socket")
|
||
for i in range(min(socket_fields.size(), device_data["sockets"].size())):
|
||
socket_fields[i].set_pressed_no_signal(device_data["sockets"][i])
|
||
|
||
# Устанавливаем состояния ДКМ
|
||
if device_data.has("dkm"):
|
||
var dkm_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "dkm")
|
||
for i in range(min(dkm_fields.size(), device_data["dkm"].size())):
|
||
dkm_fields[i].set_pressed_no_signal(device_data["dkm"][i])
|
||
|
||
# Устанавливаем состояния ДОУ2
|
||
if device_data.has("dou2"):
|
||
var dou2_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "dou2")
|
||
for i in range(min(dou2_fields.size(), device_data["dou2"].size())):
|
||
dou2_fields[i].set_pressed_no_signal(device_data["dou2"][i])
|
||
|
||
# Устанавливаем состояния ДОУ3
|
||
if device_data.has("dou3"):
|
||
var dou3_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "dou3")
|
||
for i in range(min(dou3_fields.size(), device_data["dou3"].size())):
|
||
dou3_fields[i].set_pressed_no_signal(device_data["dou3"][i])
|
||
|
||
# Устанавливаем состояния аттенюаторов 2
|
||
if device_data.has("att2"):
|
||
var att2_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "att2")
|
||
for i in range(min(att2_fields.size(), device_data["att2"].size())):
|
||
att2_fields[i].set_pressed_no_signal(device_data["att2"][i])
|
||
|
||
# Устанавливаем состояния аттенюаторов 3
|
||
if device_data.has("att3"):
|
||
var att3_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "att3")
|
||
for i in range(min(att3_fields.size(), device_data["att3"].size())):
|
||
att3_fields[i].set_pressed_no_signal(device_data["att3"][i])
|
||
|
||
# Устанавливаем состояния источников питания (с инверсией)
|
||
if device_data.has("ip"):
|
||
var ip_fields = _get_ukp_nodes_for_device(device_name, [prd_node], "ip")
|
||
for i in range(min(ip_fields.size(), device_data["ip"].size())):
|
||
# Для IP используется инверсия: true в JSON = нажато = бит 0
|
||
ip_fields[i].set_pressed_no_signal(device_data["ip"][i])
|
||
|
||
|
||
func _ready() -> void:
|
||
var device_yau07: Array = get_tree().get_nodes_in_group('device-addr')
|
||
for device in device_yau07:
|
||
device.connect('toggled', on_modify_device.bind(device.get_meta('device')))
|
||
|
||
var sockets: Array = get_tree().get_nodes_in_group('socket')
|
||
for soc in sockets:
|
||
soc.connect('toggled', _on_modify_sockets.bind(soc.get_meta('bit'), soc.get_meta('device'))) ## Мета bit от 0 до 3, мета ПРД
|
||
|
||
var power_ukp_arr_node: Array = get_tree().get_nodes_in_group('power_ukp')
|
||
for socket_power in power_ukp_arr_node:
|
||
socket_power.connect('text_submitted', _on_ukp_submitted.bind(socket_power.get_meta('device')))
|
||
|
||
var temperature_ukp_arr_node: Array = get_tree().get_nodes_in_group('temperature_ukp')
|
||
for socket_temp in temperature_ukp_arr_node:
|
||
socket_temp.connect('text_submitted', _on_ukp_submitted.bind(socket_temp.get_meta('device')))
|
||
|
||
var dkm_arr_node: Array = get_tree().get_nodes_in_group('dkm')
|
||
for dkm in dkm_arr_node:
|
||
dkm.connect('toggled', _on_modify_dkm.bind(dkm.get_meta('bit'), dkm.get_meta('device')))
|
||
|
||
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')))
|
||
|
||
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')))
|
||
|
||
var ip_arr_node: Array = get_tree().get_nodes_in_group('ip')
|
||
for ip in ip_arr_node:
|
||
ip.connect('toggled', _on_modify_ip.bind(ip.get_meta('bit'), ip.get_meta('device')))
|
||
_update_tab_container()
|
||
_load_default_data()
|
||
_apply_default_data()
|
||
|
||
|
||
func _process(_delta: float) -> void:
|
||
for device in dictionary_yau07:
|
||
dictionary_yau07[device]._on_poll_timeout()
|
||
|
||
|
||
func _exit_tree():
|
||
for device in dictionary_yau07:
|
||
if dictionary_yau07[device]:
|
||
dictionary_yau07[device].close_udp_unit()
|
||
|
||
|
||
func on_modify_device(toggled: bool, name_device: String) -> void:
|
||
if toggled:
|
||
udp_broadcast = UDPBroadcast.new(name_device)
|
||
udp_broadcast.add_timers_to_scene(self) # Исправлено имя метода
|
||
udp_broadcast.start_broadcast()
|
||
dictionary_yau07[name_device] = udp_broadcast
|
||
print("Устройство %s активировано" % name_device)
|
||
else:
|
||
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)
|
||
_update_tab_container()
|
||
|
||
|
||
func _update_tab_container():
|
||
var tab_container = $TabContainer
|
||
var device_nodes = get_tree().get_nodes_in_group('device-addr')
|
||
var has_visible_tabs = false
|
||
# Проходим по всем вкладкам и обновляем их состояние
|
||
for i in range(tab_container.get_tab_count()):
|
||
var tab_control = tab_container.get_tab_control(i)
|
||
var device_name = tab_control.get_meta('yau07', '')
|
||
|
||
# Ищем соответствующую кнопку устройства
|
||
var device_button = null
|
||
for device in device_nodes:
|
||
if device.get_meta('device') == device_name:
|
||
device_button = device
|
||
break
|
||
|
||
# Если нашли кнопку, устанавливаем состояние вкладки
|
||
if device_button:
|
||
var is_enabled = device_button.button_pressed
|
||
tab_container.set_tab_disabled(i, !is_enabled)
|
||
|
||
if is_enabled:
|
||
has_visible_tabs = true
|
||
|
||
# Если все вкладки заблокированы, скрываем TabContainer
|
||
tab_container.visible = has_visible_tabs
|
||
|
||
|
||
## Функция для установки статусов ячеек на связи (УГ, ЭМС-Г, УКП)
|
||
func _on_modify_sockets(toggled: bool, bit: int, device: String)->void:
|
||
if dictionary_yau07.has(device):
|
||
var udp_unit = dictionary_yau07[device]
|
||
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]
|
||
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])
|
||
|
||
|
||
## Функция для установки статусов ДОУ2 в ПРД
|
||
func _on_modify_dou2(toggled: bool, bit: int, device: String)->void:
|
||
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)
|
||
|
||
# Всегда устанавливаем статус, если кнопка нажата
|
||
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)
|
||
|
||
|
||
func _on_modify_ip(toggled: bool, bit: int, device: String):
|
||
if dictionary_yau07.has(device):
|
||
var udp_unit = dictionary_yau07[device]
|
||
var current_status = udp_unit.get_ip_status()
|
||
# Инверсия: нажата = 0, отжата = 1
|
||
var bit_value = 0 if toggled else 1
|
||
var new_status
|
||
if bit_value == 0:
|
||
new_status = current_status & ~(1 << bit) # Устанавливаем бит в 0
|
||
else:
|
||
new_status = current_status | (1 << bit) # Устанавливаем бит в 1
|
||
|
||
udp_unit.set_ip_status(new_status)
|
||
print("Статус ИП устройства %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)
|
||
|
||
var prep_power_ukp1_array: Array = _on_text_power_changed(device, 1)
|
||
var prep_power_ukp2_array: Array = _on_text_power_changed(device, 2)
|
||
|
||
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)
|
||
|
||
|
||
func _on_text_temperature_changed(device: String, number_device: int) -> Array:
|
||
return _process_ukp_data(device, number_device, "temperature_ukp", _convert_temperature)
|
||
|
||
func _on_text_power_changed(device: String, number_device: int) -> Array:
|
||
return _process_ukp_data(device, number_device, "power_ukp", _convert_power)
|
||
|
||
|
||
func _process_ukp_data(device: String, number_device: int, group_name: String, converter: Callable) -> Array:
|
||
var prd_module_arr = get_tree().get_nodes_in_group('prd')
|
||
var current_change: Array = _get_ukp_nodes_for_device(device, prd_module_arr, group_name)
|
||
var result_arr: Array = [0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff]
|
||
var config: Dictionary = _get_ukp_config(device, number_device)
|
||
|
||
for i in range(config.start_index, config.end_index):
|
||
if i < current_change.size() and not current_change[i].text.is_empty():
|
||
var value = _safe_convert_to_int(current_change[i].text)
|
||
var offset: int = config.offset if i == config.end_index-1 else 0
|
||
var result_index = i - config.start_index + offset
|
||
if result_index < result_arr.size():
|
||
result_arr[result_index] = converter.call(value)
|
||
return result_arr
|
||
|
||
|
||
static func _get_ukp_nodes_for_device(device: String, prd_module_arr: Array, group_name: String) -> Array:
|
||
for prd in prd_module_arr:
|
||
if device == prd.get_meta('yau07'):
|
||
var nodes = []
|
||
for node in prd.get_tree().get_nodes_in_group(group_name):
|
||
if prd.is_ancestor_of(node):
|
||
nodes.append(node)
|
||
return nodes
|
||
return []
|
||
|
||
|
||
static func _get_ukp_config(device: String, number_device: int) -> Dictionary:
|
||
var is_k_device = device in ['ПРД-К1', 'ПРД-К2', 'ПРД-К3', 'ПРД-К4']
|
||
if number_device == 1:
|
||
return {
|
||
"start_index": 0,
|
||
"end_index": 7 if is_k_device else 6,
|
||
"offset": 1 if is_k_device else 0
|
||
}
|
||
else:
|
||
return {
|
||
"start_index": 7 if is_k_device else 6,
|
||
"end_index": 13 if is_k_device else 12,
|
||
"offset": 0
|
||
}
|
||
|
||
|
||
static func _convert_temperature(value: int) -> int:
|
||
const CONST_MIN_TEMP: int = -25
|
||
const MAXIMUM_CODE_ADC: int = 3796
|
||
const MINIMUM_CODE_AD: int = 2660
|
||
const TEMP: float = 115.0 / (MAXIMUM_CODE_ADC - MINIMUM_CODE_AD)
|
||
|
||
var result: float = MAXIMUM_CODE_ADC - (value - CONST_MIN_TEMP - 3) / TEMP
|
||
return int(result)
|
||
|
||
|
||
static func _convert_power(value: int) -> int:
|
||
return value
|
||
|
||
|
||
static func _safe_convert_to_int(text: String) -> int:
|
||
text = text.strip_edges().to_lower()
|
||
if text.is_valid_int():
|
||
return int(text)
|
||
elif text.is_valid_float():
|
||
return roundi(float(text))
|
||
elif text.begins_with("0x") and text.substr(2).is_valid_hex_number():
|
||
return text.hex_to_int()
|
||
else:
|
||
return 0
|
||
|
||
|
||
static func _combine_arrays(power_arr: Array, temp_arr: Array)-> Array:
|
||
return temp_arr + power_arr
|
||
|
||
|
||
static func _form_buffers(device: String, ukp_data: Array, number_device: int, dic_yau07: Dictionary):
|
||
var buffer: PackedByteArray = PackedByteArray()
|
||
buffer.resize(BUFFER_SIZE)
|
||
for i in ukp_data.size():
|
||
buffer.encode_u16(2 * i, ukp_data[i])
|
||
if dic_yau07.has(device):
|
||
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
|