Files
uarep-ctl/scripts/pribor-prd.gd

1080 lines
44 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

class_name TestPRD
extends Node
# Добавляем константы для прогресса
const PROGRESS_INIT: float = 5.0
const PROGRESS_FS_TURN_ON: float = 10.0
const PROGRESS_FS_WORK: float = 20.0
const PROGRESS_CHECK_KASSETA: float = 25.0
const PROGRESS_WRITE_ISA: float = 30.0
const PROGRESS_READ_ISA: float = 35.0
const PROGRESS_UG_SET_RAY: float = 40.0
const PROGRESS_RAY_STATES: float = 50.0
const PROGRESS_COMPLETE: float = 100.0
# Для маппинга (Возможно уберу в будущем, но это не точно)
# Константы для работы с лучами
const RAY_MASK = 0x07
const SPECIAL_LITERAS = [3, 5, 7]
const RAY_m5: String = "RAY_m5"
const RAY_5: String = "RAY_5"
const RAY_15: String = "RAY_15"
const RAY_25: String = "RAY_25"
const RAY_35: String = "RAY_35"
const RAY_45: String = "RAY_45"
# Маппинг значений лучей на состояния и названия
const RAY_CONFIG = {
0: { "state": "UG_SET_RAY_0", "name": "-5°", "delay": 0.5, "requires_si_fs": true },
1: { "state": "UG_SET_RAY_1", "name": "", "delay": 0.0, "requires_si_fs": false },
2: { "state": "UG_SET_RAY_2", "name": "15°", "delay": 0.0, "requires_si_fs": false },
3: { "state": "UG_SET_RAY_3", "name": "25°", "delay": 0.0, "requires_si_fs": false },
4: { "state": "UG_SET_RAY_4", "name": "35°", "delay": 0.0, "requires_si_fs": false },
5: { "state": "UG_SET_RAY_5", "name": "45°", "delay": 0.0, "requires_si_fs": false },
6: { "state": "UG_SET_RAY_0", "name": "сброс", "delay": 0.0, "requires_si_fs": false } # Особый случай
}
const RAY_TYPES := [RAY_m5, RAY_5, RAY_15, RAY_25, RAY_35, RAY_45]
enum STATE_MACHINE {
INIT,
FS_TURN_ON,
FS_WORK,
WRITE_ISA,
READ_ISA,
CHEK_KASSETA_Y5,
UG_SET_RAY,
UG_SET_RAY_0,
UG_SET_RAY_1,
UG_SET_RAY_2,
UG_SET_RAY_3,
UG_SET_RAY_4,
UG_SET_RAY_5,
IN_EMS_RUN,
IN_EMS_STOP,
FS_TURN_OFF,
STOP_CONTROL,
AWAIT
}
var ems_g_sock_dic: Dictionary = {
'ems_input_1': 0,
'ems_input_2': 0,
'ems_input_lit_1': 0,
'ems_output_1': 0,
'ems_output_2': 0,
'ems_output_lit_1': 0,
}
var _ray_state_mapping: Dictionary
var _ray_state_enums: Dictionary = {}
# Загруженные конфигурации (приватные)
var _device_constants: Dictionary
var _base_configs: Dictionary
var _device_configs: Dictionary
var _data_indices: Dictionary
var _fs_keys: Dictionary
var _temperature_constants: Dictionary
var _ems_input_bits_config: Dictionary
var _fs_rules: Array
# Переменные класса
var config_manager: PRDConfigManager
var unit_prd: Object
var constants: Dictionary
var pribor_config: Dictionary
var fs_parameters: Dictionary
var block_ip_config: Dictionary
var block_kasseta_y5_config: Dictionary
var temperature_um: Dictionary
var control_results: Dictionary
var power_result: Dictionary
var ecms: Dictionary
var power_for_litera: Dictionary
var self_name: String
var state: int = STATE_MACHINE.INIT
var current_litera: int
var flag_write_isa: bool = false
var flag_fs_status_ok: bool = false
var flag_si_fs_input: bool = false
var flag_si_fs_output: bool = false
var flag_in_control: bool = false
var flag_control_is_over: bool = false
var flag_no_trust_yau07: bool = false
var flag_only_fs: bool = false
var control_timer: Timer = Timer.new()
var ems_6666_timer: Timer = Timer.new()
var machine_timer: Timer = Timer.new()
var cc: int = 0
var cmd_array: Array
# Добавляем переменные для отслеживания прогресса
var total_fs_to_check: int = 0
var completed_fs_count: int = 0
var current_fs_progress: float = 0.0
# Переменная для текущего статуса
var current_status: String = "Ожидание запуска контроля"
# Сигналы Класса
signal control_is_over() # Когда контроль все!
signal status_updated(status_text: String) # Сигнал для обновления статуса
signal update_progress(progress_value: float)
signal update_max_value_progress(max_progress_value: int)
var progress_value: float:
set(v):
if progress_value != v:
progress_value = v
call_deferred('emit_signal', 'update_progress', v)
## Инициализация аргуметнов
func _init(init_data: Dictionary, cmd_array_from_prd: Array) -> void:
unit_prd = init_data['unit_prd']
cmd_array = cmd_array_from_prd
config_manager = PRDConfigManager.new()
_initialize_config_from_manager()
_initialize_ray_mapping()
_initialize_power_structure()
func _initialize_config_from_manager() -> void:
if not config_manager.is_loaded():
push_error("ConfigManager не загружен!")
return
_device_constants = config_manager.get_device_constants()
_base_configs = config_manager.get_base_configs()
_device_configs = config_manager.get_device_configs()
_data_indices = config_manager.get_data_indices()
_fs_keys = config_manager.get_fs_keys()
_temperature_constants = config_manager.get_temperature_constants()
_ems_input_bits_config = config_manager.get_ems_input_bits_config()
_fs_rules = config_manager.get_fs_rules()
func _initialize_power_structure() -> void:
power_for_litera = {}
for litera in range(1, 8):
power_for_litera[litera] = {}
for ray_type in RAY_TYPES:
power_for_litera[litera][ray_type] = []
func _ready() -> void:
_determine_self_name()
initialize_connections()
setup_timer()
_initialize_ray_state_enums()
func _get_ray_key(machine_state: int) -> String:
return _ray_state_mapping.get(machine_state, "")
func _initialize_ray_mapping() -> void:
_ray_state_mapping = {
STATE_MACHINE.UG_SET_RAY_0: "RAY_m5",
STATE_MACHINE.UG_SET_RAY_1: "RAY_5",
STATE_MACHINE.UG_SET_RAY_2: "RAY_15",
STATE_MACHINE.UG_SET_RAY_3: "RAY_25",
STATE_MACHINE.UG_SET_RAY_4: "RAY_35",
STATE_MACHINE.UG_SET_RAY_5: "RAY_45",
}
func _process(_delta: float) -> void:
pass
## Пакеты от ЯУ-07
func on_data_received(unit_pribor: Object) -> void:
if not flag_in_control: return
var status: PackedByteArray = unit_pribor.status
block_kasseta_y5_config = check_block_kasseta_y5(status, block_kasseta_y5_config, flag_no_trust_yau07)
if flag_no_trust_yau07: return
socket_status_ems_g(status)
block_ip_config = check_block_ip(status, block_ip_config)
temperature_um = check_temperature_um(status)
if machine_timer.is_stopped():
return
_process_dkm_status(status)
if current_litera != 0: # Формирование мощностей в литерах
var tek_litera: Dictionary = power_for_litera[current_litera]
var interes = _get_ray_key(state)
if interes != '':
tek_litera[_get_ray_key(state)] = power_um_ukp(status, current_litera, tek_litera[_get_ray_key(state)])
power_for_litera[current_litera] = tek_litera
func socket_status_ems_g(packet_form_yau_07: PackedByteArray) -> void:
if self_name in ['', '', '', '']:
ems_g_sock_dic.ems_input_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 9)) != 0
ems_g_sock_dic.ems_input_2 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 10)) != 0
if self_name in ['', '', '', '']:
ems_g_sock_dic.ems_input_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 11)) != 0
ems_g_sock_dic.ems_input_2 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 12)) != 0
if self_name in ['', '', '', '']:
ems_g_sock_dic.ems_input_lit_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 8)) != 0
ems_g_sock_dic.ems_input_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 13)) != 0
ems_g_sock_dic.ems_input_2 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD')) & (1 << 14)) != 0
ems_g_sock_dic.ems_output_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('OUT_BLANK_PRD')) & (1 << 4)) != 0
ems_g_sock_dic.ems_output_2 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('OUT_BLANK_PRD')) & (1 << 5)) != 0
ems_g_sock_dic.ems_output_lit_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('OUT_BLANK_PRD')) & (1 << 3)) != 0
var number_socket_input: int
if current_litera >= 1 and current_litera <= 7:
number_socket_input = current_litera + 7
var in_blank: int = packet_form_yau_07.decode_u16(config_manager.get_data_index('IN_BLANK_PRD'))
flag_si_fs_input = (in_blank & (1 << number_socket_input)) != 0 ## Флаг СИ от ФС входа в ЭМС-Г для текущей литеры
var number_socket_output: int
number_socket_output = 4 if current_litera in [2, 4, 6] else 3 if current_litera == 1 else 5
var out_blank: int = packet_form_yau_07.decode_u16(config_manager.get_data_index('OUT_BLANK_PRD'))
flag_si_fs_output = (out_blank & (1 << number_socket_output)) != 0 ## Флаг Модуляции УМ ЭМС-Г для текущей литеры
## Пакеты от MP550Service
func on_fs_update_state(packet_type_7: Dictionary, fs_mapping: Dictionary) -> void:
var fs_key: String = _fs_keys.get(str(current_litera), '')
if fs_key.is_empty():
return
var fs_result := {fs_key: 0}
fs_result = on_fs_state(packet_type_7, fs_mapping, fs_result, _fs_rules)
control_results[fs_key] = fs_result[fs_key]
flag_fs_status_ok = control_results[fs_key] == 1
# Обновленная машина состояний
func state_control_machine() -> void:
match state:
STATE_MACHINE.INIT:
_handle_init_state()
STATE_MACHINE.FS_TURN_ON:
_handle_fs_turn_on_state()
state = STATE_MACHINE.FS_WORK
STATE_MACHINE.FS_WORK:
var flag_ecm: bool = false
for key in ecms:
var params = ecms[key].params.freq
if fs_parameters[current_litera].freq == params:
var kni = ecms[key].kni
if pribor_config[self_name].angle == kni:
flag_ecm = true
if flag_ecm and flag_fs_status_ok:
ems_6666_timer.start()
_handle_fs_work_state()
STATE_MACHINE.CHEK_KASSETA_Y5:
if block_kasseta_y5_config['yau07']:
state = STATE_MACHINE.WRITE_ISA
elif flag_only_fs:
state = STATE_MACHINE.IN_EMS_STOP
STATE_MACHINE.WRITE_ISA:
if not flag_write_isa:
_handle_ug_set_state(0x6)
state = STATE_MACHINE.READ_ISA
STATE_MACHINE.READ_ISA:
if (unit_prd.cmd_state == unit_prd.CmdState.DONE) or (unit_prd.cmd_state == unit_prd.CmdState.FAIL):
_handle_read_isa(unit_prd, [constants.ADDR_UG_LITERA_1, constants.ADDR_UG_LITERA_2, constants.ADDR_UG_LITERA_3], cmd_array)
flag_write_isa = false
state = STATE_MACHINE.UG_SET_RAY
# Упрощенные состояния лучей
STATE_MACHINE.UG_SET_RAY:
_handle_ray_operation() # Режим чтения
STATE_MACHINE.UG_SET_RAY_0:
_handle_ray_operation(0)
STATE_MACHINE.UG_SET_RAY_1:
_handle_ray_operation(1)
STATE_MACHINE.UG_SET_RAY_2:
_handle_ray_operation(2)
STATE_MACHINE.UG_SET_RAY_3:
_handle_ray_operation(3)
STATE_MACHINE.UG_SET_RAY_4:
_handle_ray_operation(4)
STATE_MACHINE.UG_SET_RAY_5:
_handle_ray_operation(5)
STATE_MACHINE.IN_EMS_STOP:
ems_6666_timer.stop()
state = STATE_MACHINE.FS_TURN_OFF
STATE_MACHINE.FS_TURN_OFF:
ems_6666_timer.stop()
_handle_fs_turn_off_state()
state = STATE_MACHINE.STOP_CONTROL
STATE_MACHINE.STOP_CONTROL:
_handle_stop_control_state()
# Обновление прогресс-бара
if block_kasseta_y5_config['yau07'] or flag_no_trust_yau07:
progressbar_status()
## 'Выполняется инициализация ФС-%s' % current_litera
func _handle_init_state() -> void:
if current_litera in [1, 2, 3, 4, 5, 6, 7]:
_set_status("Инициализация ФС-%s" % current_litera)
var flag_ecm: bool = false
for key in ecms:
var params = ecms[key].params.freq
if fs_parameters[current_litera].freq == params:
var kni = ecms[key].kni
if pribor_config[self_name].angle == kni:
flag_ecm = true
if not flag_ecm:
state = STATE_MACHINE.FS_TURN_ON
else:
flag_control_is_over = true
control_results = on_control_result(block_ip_config, control_results)
power_result = prep_power(power_for_litera, self_name)
machine_timer.stop()
var result: bool = true
for device in control_results.values():
if not device:
result = false
_set_status("Прибор ПРД-%s: %s" % [self_name, ['неисправен', 'исправен'][int(result)]])
emit_signal('control_is_over')
##'Выполняется включение ФС-%s' % current_litera
func _handle_fs_turn_on_state() -> void:
_set_status("Включение ФС-%s" % current_litera)
manage_fs(true, self_name, pribor_config, fs_parameters, current_litera, constants.POWER_UM)
control_timer.wait_time = constants.TIMER_DELAY
control_timer.start()
##'Выполняется проверка ФС-%s' % current_litera
func _handle_fs_work_state() -> void:
_set_status("Проверка ФС-%s" % current_litera)
if (current_litera == 2 and control_results.fs_2) or \
(current_litera == 3 and control_results.fs_3) or \
(current_litera == 4 and control_results.fs_4) or \
(current_litera == 5 and control_results.fs_5) or \
(current_litera == 6 and control_results.fs_6) or \
(current_litera == 7 and control_results.fs_7) or \
(current_litera == 1 and control_results.fs_1):
state = STATE_MACHINE.CHEK_KASSETA_Y5
## Подготовка к настройки и записи в УГ
func _handle_ug_set_state(RAY_DOU_NUM: int) -> void:
_set_status("Настройка угла %s" % _get_ray_name(RAY_DOU_NUM))
var dic_att := {
'RAY_DOU_NUM': RAY_DOU_NUM,
'ADDR_UG_LITERA_1': constants.ADDR_UG_LITERA_1,
'ADDR_UG_LITERA_2': constants.ADDR_UG_LITERA_2,
'ADDR_UG_LITERA_3': constants.ADDR_UG_LITERA_3,
'ATT_UM_3': 0x00,
'BASE_EMS_G': constants.BASE_ADDR_EMS_G
}
if self_name == '' or self_name == '' or self_name == '' or self_name == '':
dic_att['ATT_UM_1'] = constants.ATT_UM_6
dic_att['ATT_UM_2'] = constants.ATT_UM_7
dic_att['ATT_UM_3'] = constants.ATT_UM_1
elif self_name == '' or self_name == '' or self_name == '' or self_name == '':
dic_att['ATT_UM_1'] = constants.ATT_UM_4
dic_att['ATT_UM_2'] = constants.ATT_UM_5
elif self_name == '' or self_name == '' or self_name == '' or self_name == '':
dic_att['ATT_UM_1'] = constants.ATT_UM_2
dic_att['ATT_UM_2'] = constants.ATT_UM_3
flag_write_isa = on_ug_setting(unit_prd, dic_att, cmd_array)
## Функция для продвижения статуса прогресс бара
# Обновленный прогресс-бар с учетом новой структуры
func progressbar_status() -> void:
if current_litera == 0:
progress_value = PROGRESS_COMPLETE
await get_tree().create_timer(0.5).timeout
progress_value = 0
return
var base_progress: float = 0.0
match state:
STATE_MACHINE.INIT:
base_progress = PROGRESS_INIT
STATE_MACHINE.FS_TURN_ON:
base_progress = PROGRESS_FS_TURN_ON
STATE_MACHINE.FS_WORK:
base_progress = PROGRESS_FS_WORK
STATE_MACHINE.CHEK_KASSETA_Y5:
base_progress = PROGRESS_CHECK_KASSETA
STATE_MACHINE.WRITE_ISA:
base_progress = PROGRESS_WRITE_ISA
STATE_MACHINE.READ_ISA:
base_progress = PROGRESS_READ_ISA
STATE_MACHINE.UG_SET_RAY:
base_progress = PROGRESS_UG_SET_RAY
STATE_MACHINE.UG_SET_RAY_0, STATE_MACHINE.UG_SET_RAY_1, STATE_MACHINE.UG_SET_RAY_2, \
STATE_MACHINE.UG_SET_RAY_3, STATE_MACHINE.UG_SET_RAY_4, STATE_MACHINE.UG_SET_RAY_5:
# Для всех состояний лучей используем одинаковый прогресс
base_progress = PROGRESS_RAY_STATES
STATE_MACHINE.IN_EMS_STOP, STATE_MACHINE.FS_TURN_OFF, STATE_MACHINE.STOP_CONTROL:
base_progress = PROGRESS_COMPLETE
# Плавное заполнение во время ожидания таймера
if control_timer.time_left > 0 and state != STATE_MACHINE.STOP_CONTROL:
var timer_progress = (control_timer.wait_time - control_timer.time_left) / control_timer.wait_time
base_progress = lerp(base_progress - 5.0, base_progress, timer_progress)
# Учитываем прогресс по лучам внутри UG_SET_RAY состояния
if state == STATE_MACHINE.UG_SET_RAY:
var addr: int = _get_ug_address()
if _can_process_ray_state(addr):
var ray_value = unit_prd.isa_ports[addr] & RAY_MASK
# Используем маппинг из RAY_CONFIG для более точного прогресса
var max_ray_value = 5.0 # максимальное значение луча для прогресса
var ray_progress = float(ray_value) / max_ray_value * 40.0
base_progress += ray_progress
# Распределяем прогресс по ФС
if total_fs_to_check > 0:
var progress_per_fs = (PROGRESS_COMPLETE - PROGRESS_INIT) / total_fs_to_check
var fs_base_progress = completed_fs_count * progress_per_fs
progress_value = fs_base_progress + (base_progress * progress_per_fs / PROGRESS_COMPLETE)
else:
progress_value = base_progress
progress_value = clamp(progress_value, 0.0, PROGRESS_COMPLETE)
##'Выполняется отключение ФС-%s' % current_litera
func _handle_fs_turn_off_state() -> void:
_set_status("Отключение ФС-%s" % current_litera)
flag_fs_status_ok = false
manage_fs(false, self_name, pribor_config, fs_parameters, current_litera, constants.POWER_UM)
##'Выполняется завершение проверки ФС-%s' % current_litera
func _handle_stop_control_state() -> void:
_set_status("Завершение контроля ФС-%s" % current_litera)
# Увеличиваем счетчик завершенных ФС
completed_fs_count += 1
_advance_to_next_fs()
state = STATE_MACHINE.INIT
if current_litera == 0: return
if flag_no_trust_yau07:
state = STATE_MACHINE.STOP_CONTROL
## Переходит на следующую литеру, если 0 то считай закончил выполнения контроля
func _advance_to_next_fs() -> void:
match current_litera:
1: current_litera = 6
2: current_litera = 3
3: current_litera = 0
4: current_litera = 5
5: current_litera = 0
6: current_litera = 7
7: current_litera = 0
# Сбрасываем прогресс текущей ФС при переходе к следующей
if current_litera != 0:
current_fs_progress = 0.0
######################################
func initialize_connections() -> void:
var fs_mapping = _create_fs_mapping(self_name)
signaller.conn(signaller.fs_update_state, Callable(self, 'on_fs_update_state').bind(fs_mapping))
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_contol_device'))
interfer.connect('interfer_resized', Callable(self, 'on_interfer_resized'))
unit_prd.connect('data_received', Callable(self, 'on_data_received'))
var mode_signals = ['режим_работа', 'режим_журнал', 'режим_эмс', 'режим_настройки']
for signal_name in mode_signals:
signaller.connect(signal_name, Callable(self, 'on_mode_changed').bind(false))
signaller.connect('режим_контроль', Callable(self, 'on_mode_changed').bind(true))
# Инициализация маппинга имен состояний в enum значения
func _initialize_ray_state_enums() -> void:
for ray_value in RAY_CONFIG:
var state_name = RAY_CONFIG[ray_value].state
_ray_state_enums[state_name] = STATE_MACHINE.get(state_name)
func on_interfer_resized(ecms_dic: Dictionary) -> void:
ecms = ecms_dic
func _on_start_contol_device()-> void:
_set_status("Подготовка к контролю")
_determine_self_name()
machine_timer.wait_time = constants.STATE_MASHINE_TIMER
machine_timer.start()
func _determine_self_name() -> void:
flag_no_trust_yau07 = false
flag_only_fs = false
cc = 0
state = STATE_MACHINE.get("INIT", 0)
var current_unit = unit_prd.name
var parts = current_unit.split('-')
self_name = parts[-1]
var device_type: String = _get_device_type()
if device_type.is_empty():
return
var device_config = _device_constants.get(device_type, {})
var device_data_config = _device_configs.get(device_type, {})
# Загружаем конфигурацию устройства
constants = device_config.get("constants", {})
pribor_config = device_config.get("pribor_config", {})
# Конвертируем fs_params ключи в int
var raw_fs_params = device_config.get("fs_params", {})
fs_parameters = {}
for key in raw_fs_params:
fs_parameters[int(key)] = raw_fs_params[key]
# Загружаем конфигурации блоков
block_ip_config = _load_block_config(device_data_config.get("block_ip", {}), "block_ip")
block_kasseta_y5_config = _load_block_config(device_data_config.get("block_kasseta", {}), "block_kasseta")
control_results = device_data_config.get("control_results", {})
current_litera = device_config.get("start_litera", 0)
# Определяем общее количество ФС для контроля
match self_name:
'', '', '', '':
total_fs_to_check = 3 # Литеры 1, 6, 7
'', '', '', '':
total_fs_to_check = 2 # Литеры 2, 3
'', '', '', '':
total_fs_to_check = 2 # Литеры 4, 5
progress_value = 0
completed_fs_count = 0
current_fs_progress = 0.0
call_deferred('emit_signal', 'update_max_value_progress', 100)
func _load_block_config(config, config_type: String) -> Dictionary:
if config is String and config == "base":
return _base_configs.get(config_type, {}).duplicate(true)
elif config is Dictionary:
return config.duplicate(true)
return {}
func _get_device_type() -> String:
if self_name.ends_with('н'): return 'PRD_N'
elif self_name.ends_with('в'): return 'PRD_V'
elif self_name.ends_with('к'): return 'PRD_K'
return ''
# Получение адреса UG для текущей литеры
func _get_ug_address() -> int:
return constants.ADDR_UG_LITERA_2 if current_litera in SPECIAL_LITERAS else constants.ADDR_UG_LITERA_1
## Настройка таймеров
func setup_timer() -> void:
add_child(control_timer)
control_timer.timeout.connect(on_stop_control)
control_timer.one_shot = true
control_timer.wait_time = constants.get("TIMER_DELAY", 10.0)
add_child(ems_6666_timer)
ems_6666_timer.timeout.connect(_on_ems_6666_timer)
ems_6666_timer.wait_time = 1.0
add_child(machine_timer)
machine_timer.connect('timeout', Callable(self, 'on_state_mashine'))
## Таймер отправки команды в ЭМС-Г для модуляции
func _on_ems_6666_timer() -> void:
cmd_array.append([unit_prd.CmdCode.WRITE_ISA, [constants.BASE_ADDR_EMS_G, 6666]])
## Таймер вызова машины состояний
func on_state_mashine():
state_control_machine()
## При таймауте таймера ожидания выполнения команды и перехода на следующий шаг машины состояний
func on_stop_control() -> void:
_handle_fs_turn_off_state()
if state == STATE_MACHINE.UG_SET_RAY:
flag_no_trust_yau07 = true
elif state == STATE_MACHINE.CHEK_KASSETA_Y5:
flag_only_fs = true
state = STATE_MACHINE.FS_TURN_OFF
# Обработка значения луча из UG_SET_RAY состояния
func _process_ray_value(ray_value: int) -> void:
match ray_value:
0, 1, 2, 3, 4:
var next_ray = ray_value + 1
if next_ray in RAY_CONFIG: # ← Добавить проверку
state = _ray_state_enums[RAY_CONFIG[next_ray].state]
5:
if not current_litera == 1:
control_results = check_dou_result(control_results, power_for_litera, self_name, current_litera, constants)
state = STATE_MACHINE.IN_EMS_STOP
6:
state = STATE_MACHINE.UG_SET_RAY_0
if current_litera == 1:
state = STATE_MACHINE.UG_SET_RAY_5
# Универсальный обработчик для всех операций с лучами
func _handle_ray_operation(ray_num: int = -1) -> void:
if ray_num == -1:
# Режим чтения - определение текущего луча
_handle_ray_read_mode()
else:
# Режим записи - установка конкретного луча
_handle_ray_write_mode(ray_num)
# Обработка чтения состояния луча
func _handle_ray_read_mode() -> void:
var addr: int = _get_ug_address()
if not _can_process_ray_state(addr):
return
var ray_value = unit_prd.isa_ports[addr] & RAY_MASK
_process_ray_value(ray_value)
# Проверка возможности обработки состояния луча
func _can_process_ray_state(addr: int) -> bool:
return unit_prd.isa_ports.has(addr) and (unit_prd.cmd_state == unit_prd.CmdState.DONE)
# Обработка записи состояния луча
func _handle_ray_write_mode(ray_num: int) -> void:
if not _can_write_ray(ray_num):
return
var ray_config = RAY_CONFIG[ray_num]
# Особые условия для луча 0
if ray_num == 0:
control_timer.stop()
# Задержка если требуется
if ray_config.delay > 0:
await get_tree().create_timer(ray_config.delay).timeout
# Установка луча
_handle_ug_set_state(ray_num)
flag_write_isa = true
state = STATE_MACHINE.READ_ISA
# Проверка возможности записи луча
func _can_write_ray(ray_num: int) -> bool:
if flag_write_isa:
return false
var ray_config = RAY_CONFIG[ray_num]
# Для луча 0 требуется flag_si_fs_input, для остальных - нет
if ray_num == 0:
return ray_config.requires_si_fs and flag_si_fs_input
return true
## Срабатывает при выходе или входе в режим контроль
func on_mode_changed(in_tree: bool) -> void:
flag_in_control = in_tree
if not in_tree: ## TODO: Дополнительная проверка если контроль идет, если нет, то смысла вызывать нет
_set_status("Ожидание запуска контроля")
flag_control_is_over = false
flag_no_trust_yau07 = false
flag_only_fs = false
progress_value = 0
machine_timer.stop()
state = STATE_MACHINE.INIT
_handle_fs_turn_off_state()
#prd_v_module.cmd_array.append([unit_prd_v.CmdCode.WRITE_ISA, [constants_v.ADDR_UG_LITERA_1, ug_work_1, constants_v.ADDR_UG_LITERA_2, ug_work_2]])
else:
_set_status("Ожидание запуска контроля")
func _process_dkm_status(status: PackedByteArray) -> void:
if not control_results.has(_get_current_fs_key(current_litera, _fs_keys)):
return
var dkm_bit = _get_dkm_bit_for_current_fs(current_litera, constants)
if dkm_bit == 0:
control_results['dkm_1'] = check_dkm(status, dkm_bit)
var addr: int = constants.ADDR_UG_LITERA_1
if current_litera == 3 or current_litera == 5 or current_litera == 7:
addr = constants.ADDR_UG_LITERA_2
if not unit_prd.isa_ports.has(addr) or not (unit_prd.cmd_state == unit_prd.CmdState.DONE):
return
if not unit_prd.isa_ports[addr] & 0x07 == 6: return
if dkm_bit == 1:
control_results['dkm_2'] = check_dkm(status, dkm_bit)
elif dkm_bit == 2:
control_results['dkm_3'] = check_dkm(status, dkm_bit)
elif dkm_bit == 3:
control_results['dkm_4'] = check_dkm(status, dkm_bit)
elif dkm_bit == 4:
control_results['dkm_5'] = check_dkm(status, dkm_bit)
elif dkm_bit == 5:
control_results['dkm_6'] = check_dkm(status, dkm_bit)
elif dkm_bit == 6:
control_results['dkm_7'] = check_dkm(status, dkm_bit)
static func _get_current_fs_key(litera: int, fs_keys_dic: Dictionary) -> String:
return fs_keys_dic.get(str(litera), '')
## Возвращает бит ДКМ для проверки текущей литеры
static func _get_dkm_bit_for_current_fs(litera: int, constants_dic: Dictionary) -> int:
match litera:
1: return constants_dic.DKM_BIT_1
2: return constants_dic.DKM_BIT_2
3: return constants_dic.DKM_BIT_3
4: return constants_dic.DKM_BIT_4
5: return constants_dic.DKM_BIT_5
6: return constants_dic.DKM_BIT_6
7: return constants_dic.DKM_BIT_7
_: return -1
## Итоговое заключение по результам контроля всех ИП
static func on_control_result(ip_config: Dictionary, ctrl_results: Dictionary) -> Dictionary:
var all_blocks_ip_ok = true
for block in ip_config:
if not ip_config[block][1]:
all_blocks_ip_ok = false
ctrl_results['block_ip'] = all_blocks_ip_ok
return ctrl_results
## Установка угла и аттенюации для УМ
static func on_ug_setting(prd_unit: Object, settings_ug: Dictionary, prd_cmd_array: Array) -> bool:
var result_1 = ((settings_ug.ATT_UM_1 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07)
var result_2 = ((settings_ug.ATT_UM_2 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07)
prd_cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [ settings_ug.ADDR_UG_LITERA_1, result_1,
settings_ug.ADDR_UG_LITERA_2, result_2,
settings_ug.ADDR_UG_LITERA_3, settings_ug.ATT_UM_3,
]
])
return true
static func _handle_read_isa(prd_unit: Object, read_isa_ports: Array, prd_cmd_array) -> void:
prd_cmd_array.append([prd_unit.CmdCode.READ_ISA, read_isa_ports])
## Управаление модулем фс (включить/отключить излучение)
static func manage_fs(mode: bool, pribor: String, p_conf: Dictionary, fs_params: Dictionary, litera: int, power_um: int) -> void:
# Получаем конфигурацию для текущего прибора
var config: Dictionary = p_conf[pribor]
var angle: float = config.angle
var sectors: Array = config.sectors
# Формируем выходные данные
var interfer_name: String = 'k1' if mode else 'off'
var fs_arr: Array = []
if litera in fs_params:
var params = fs_params[litera]
fs_arr.append([
angle,
params.freq,
params.width,
sectors[litera - 1] if litera == 1 else sectors[litera - 5] if litera > 5 else sectors[litera - 4] if litera > 3 else sectors[litera - 2]
])
#signaller.emit_signal('emit_changed', mode) TODO: не отключаю подавление (даже если при входе в контроль он был отключен)
signaller.emit_signal('interfer_init', interfer_name, fs_arr, power_um)
## Проверка касет П1 и ИП МА2000
static func check_block_ip(status_prd: PackedByteArray, ip_config: Dictionary) -> Dictionary:
# Конфигурация проверяемых блоков
var byte_dry: int = 27
var ug_valid: bool = (status_prd[0] >> 1) & 1
for block in ip_config:
var bit: int = ip_config[block][0]
if ug_valid:
var status = status_prd[byte_dry] >> bit & 1
ip_config[block][1] = false if status else true
return ip_config
## Проверка кассеты у-5 (ЯУ-07Б, ЭМС-Г, УГ, УКП-1, УКП-2)
static func check_block_kasseta_y5(status_prd: PackedByteArray, y5_config: Dictionary, flag_not_trust: bool) -> Dictionary:
y5_config.yau07 = not flag_not_trust
if y5_config.yau07:
y5_config.ems = (status_prd[0] & 1) and ((status_prd[0] >> 4) & 1)
y5_config.ug = (status_prd[0] >> 1) & 1
y5_config.ukp1 = (status_prd[0] >> 2) & 1
y5_config.ukp2 = (status_prd[0] >> 3) & 1
return y5_config
## Мониторинг температуры
static func check_temperature_um(status_prd: PackedByteArray) -> Dictionary:
const Constants: Dictionary = {
'CONST_MIN_TEMP': -25,
'MAXIMUM_CODE_ADC': 3796,
'MINIMUM_CODE_AD': 2660,
'TEMPERATURE_UKP_1': 47,
'TEMPERATURE_UKP_2': 79,
}
const arr_um: Array = ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6', 'um_7', 'um_8', 'um_9', 'um_10', 'um_11', 'um_12', 'um_13', 'um_14', 'um_15', 'um_16']
const TEMP: float = 115.0 / (Constants.MAXIMUM_CODE_ADC - Constants.MINIMUM_CODE_AD)
var return_dic_temp: Dictionary
var ukp1_online: int = (status_prd[0] >> 2) & 1
var ukp2_online = (status_prd[0] >> 3) & 1
if ukp1_online:
var tmp_1: int
var temperature_ukp_1: int
for i_temp in 8:
temperature_ukp_1 = status_prd.decode_u16(Constants.TEMPERATURE_UKP_1 + 2 * i_temp)
tmp_1 = round(Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_1) * TEMP + 3)
return_dic_temp[arr_um[i_temp]] = tmp_1
if ukp2_online:
for i_temp in 8:
var temperature_ukp_2: int = status_prd.decode_u16(Constants.TEMPERATURE_UKP_2 + 2 * i_temp)
var tmp_2: int = round(Constants.CONST_MIN_TEMP + (Constants.MAXIMUM_CODE_ADC - temperature_ukp_2) * TEMP + 3)
return_dic_temp[arr_um[i_temp+8]] = tmp_2
return return_dic_temp
## Проверка ДКМ
static func check_dkm(status_prd: PackedByteArray, bit_dkm: int) -> bool:
var dkm: int = 28
var status_dkm: bool = status_prd[dkm] >> bit_dkm & 1
return status_dkm
## Распределения номеров ФС по пирборам
static func _create_fs_mapping(s_name: String) -> Dictionary:
var suffixes: Dictionary = {
0: '', 1: '', 2: '', 3: '',
4: '', 5: '', 6: '', 7: '',
8: '', 9: '', 10: '', 11: '',
12: '', 13: '', 14: '', 15: '',
16: '', 17: '', 18: '', 19: '',
20: '', 21: '', 22: '', 23: '',
24: '', 25: '', 26: '', 27: '',
}
var mapping: Dictionary = {}
for fs_num in suffixes:
mapping[fs_num] = {'condition': s_name == suffixes[fs_num]}
return mapping
## Получения статуса ФС
static func on_fs_state(packet_type_7: Dictionary, fs_mapping: Dictionary, fs_results: Dictionary, fs_rules_config: Array) -> Dictionary:
var updated_results := fs_results.duplicate()
for fs_num in packet_type_7:
if not (fs_num in fs_mapping and fs_mapping[fs_num]['condition']):
continue
var fs_data = packet_type_7[fs_num]
for rule in fs_rules_config:
if _should_apply_rule(fs_num, rule, updated_results):
updated_results[rule.key] = fs_data.isg
break
return updated_results
## Вспомогательная функция для проверки применения правила
static func _should_apply_rule(fs_num: int, rule: Dictionary, results: Dictionary) -> bool:
return bool(fs_num >= rule.min and fs_num < rule.max) and results.has(rule.key)
## Получение мощности при выполнении контроля
static func power_um_ukp(status: PackedByteArray, litera: int, pwr_result: Array) -> Array:
const Constants: Dictionary = {'POWER_UKP_1' : 31, 'POWER_UKP_2': 63}
var power_values: Array = []
var base_offset = 0
var iteration: int = 6
var ug_valid: bool = (status[0] >> 2) & 1
match litera:
1:
# Обработка для current_fs = 1 (одно значение)
var value = status.decode_u16(Constants.POWER_UKP_1 + 2 * 7)
if ug_valid:
power_values = [value]
2:
# Обработка для current_fs = 2 (6 значений из УКП1)
base_offset = Constants.POWER_UKP_1
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
3:
# Обработка для current_fs = 3 (6 значений из УКП2)
base_offset = Constants.POWER_UKP_2
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
4:
# Обработка для current_fs = 4 (6 значений из УКП1)
base_offset = Constants.POWER_UKP_1
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
5:
# Обработка для current_fs = 5 (6 значений из УКП2)
base_offset = Constants.POWER_UKP_2
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
6:
# Обработка для current_fs = 6 (6 значений из УКП1)
base_offset = Constants.POWER_UKP_1
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
7:
# Обработка для current_fs = 7 (6 значений из УКП2)
base_offset = Constants.POWER_UKP_2
if ug_valid:
for i in iteration:
power_values.append(status.decode_u16(base_offset + 2 * i))
power_values = update_max_power_values(power_values, pwr_result)
return power_values
## Обновление максимальных значений
static func update_max_power_values(power_data: Array, max_power_values: Array) -> Array:
if power_data.size() != 6:
if max_power_values.is_empty():
max_power_values = power_data.duplicate()
elif power_data[0] > max_power_values[0]:
max_power_values = power_data.duplicate()
return max_power_values
if max_power_values.is_empty():
max_power_values = power_data.duplicate()
else:
for i in 6:
if power_data[i] > max_power_values[i]:
max_power_values[i] = power_data[i]
return max_power_values.duplicate()
## Подготовка принятых данных по контролю для передачи в сцену
static func prep_power(power_dic: Dictionary, prd_name: String)-> Dictionary:
const RAY_KEYS := ["RAY_m5", "RAY_5", "RAY_15", "RAY_25", "RAY_35", "RAY_45"]
var prep_pow_dic: Dictionary = {}
var arr_litera: Array[int]
match prd_name:
'', '', '', '':
arr_litera = [2, 3]
'', '', '', '':
arr_litera = [4, 5]
'', '', '', '':
arr_litera = [6, 7, 1]
if not arr_litera:
print_debug('Ошибка в prd_name')
return prep_pow_dic
var um_names: Array[Array] = []
if arr_litera.size() != 3:
um_names = [
['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'],
['um_9', 'um_10', 'um_11', 'um_12', 'um_13', 'um_14']
]
else:
um_names = [
['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'],
['um_9', 'um_10', 'um_11', 'um_12', 'um_13', 'um_14'],
['um_8']
]
for litera_index in arr_litera.size():
var litera: int = arr_litera[litera_index]
var litera_data: Dictionary = power_dic.get(litera, {})
var um_data: Array[Array] = [[], [], [], [], [], []]
for i in range(RAY_KEYS.size()):
var ray_key: String = RAY_KEYS[i]
var ray_array: Array = litera_data.get(ray_key, [])
if ray_array.size() == 1:
var single_value = ray_array[0]
for j in range(6):
um_data[j].append(single_value)
else:
for j in range(6):
um_data[j].append(ray_array[j] if j < ray_array.size() else 0)
var current_um_names: Array = um_names[litera_index]
for um_index in range(current_um_names.size()):
prep_pow_dic[current_um_names[um_index]] = um_data[um_index]
return prep_pow_dic
static func check_dou_result(control_dic: Dictionary, power_dic: Dictionary, pribor: String, litera: int, cnst: Dictionary) -> Dictionary:
var all_dou_ok = true
var dou: String = 'dou_2' if litera == 2 else 'dou_3'
if pribor == '' or pribor == '' or pribor == '' or pribor == '':
dou = 'dou_6' if litera == 6 else 'dou_7'
elif pribor == '' or pribor == '' or pribor == '' or pribor == '':
dou = 'dou_4' if litera == 4 else 'dou_5'
var ray_dic: Dictionary = power_dic[litera]
if ray_dic[RAY_m5].size() == 0 or \
ray_dic[RAY_5 ].size() == 0 or \
ray_dic[RAY_15].size() == 0 or \
ray_dic[RAY_25].size() == 0 or \
ray_dic[RAY_35].size() == 0 or \
ray_dic[RAY_45].size() == 0:
control_dic[dou] = false
return control_dic
for i_pow_arr in ray_dic.values():
for i_pow in i_pow_arr.size():
if i_pow_arr[i_pow] < cnst.POWER_THRESHOLD:
all_dou_ok = false
control_dic[dou] = all_dou_ok
return control_dic
# Сеттер для статуса
func _set_status(new_status: String) -> void:
if current_status != new_status:
current_status = new_status
call_deferred('emit_signal', 'status_updated', new_status)
# Геттер для текущего статуса (чтобы можно было забрать в любой момент)
func get_current_status() -> String:
return current_status
func _get_ray_name(ray_num: int) -> String:
return RAY_CONFIG.get(ray_num, {}).get("name", "неизвестный угол")
# Геттер для результатов контроля
func get_control_results() -> Dictionary:
return {
'control_is_over': flag_control_is_over,
'result_dic': control_results,
'power_dic': power_result,
'block_kasseta_y5_config': block_kasseta_y5_config,
'block_ip_config': block_ip_config,
'temperature_um': temperature_um,
'POWER_THRESHOLD': constants.POWER_THRESHOLD,
'name_prd': self_name
}