class_name TestPRD extends Node #region CONSTANTS ## Константы прогресса для визуализации выполнения контроля 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 COUNT_PACK_POWER_RECIEVE = 10 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°'}, 1: { 'state': 'UG_SET_RAY_1', 'name': '5°'}, 2: { 'state': 'UG_SET_RAY_2', 'name': '15°'}, 3: { 'state': 'UG_SET_RAY_3', 'name': '25°'}, 4: { 'state': 'UG_SET_RAY_4', 'name': '35°'}, 5: { 'state': 'UG_SET_RAY_5', 'name': '45°'}, 6: { 'state': 'UG_SET_RAY_0', 'name': 'Контроль'} # ДКМ } const ATT_MAPPING = { 1: 'ATT_UM_3', 2: 'ATT_UM_1', 4: 'ATT_UM_1', 6: 'ATT_UM_1', 3: 'ATT_UM_2', 5: 'ATT_UM_2', 7: 'ATT_UM_2' } # Таблица соответствий: device_name -> (current_lit -> nmfs в ecms) const LITER_TO_NMFS: Dictionary = { '1к': {1: 11, 6: 16, 7: 17}, '2к': {1: 21, 6: 26, 7: 27}, '3к': {1: 31, 6: 36, 7: 37}, '4к': {1: 41, 6: 46, 7: 47}, '1н': {2: 12, 3: 13}, '2н': {2: 22, 3: 23}, '3н': {2: 32, 3: 33}, '4н': {2: 42, 3: 43}, '1в': {4: 14, 5: 15}, '2в': {4: 24, 5: 25}, '3в': {4: 34, 5: 35}, '4в': {4: 44, 5: 45} } const RAY_TYPES := [RAY_m5, RAY_5, RAY_15, RAY_25, RAY_35, RAY_45] const DATA_EXIT_CONTOL_ISA: int = 0 ## Перечисление состояний машины контроля ПРД enum STATE_MACHINE { INIT, FS_TURN_ON, FS_WORK, READ_ISA, CHEK_KASSETA_Y5, CHEK_BLOCK_IP, 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, UG_SET_RAY_CTRL, IN_EMS_RUN, IN_EMS_STOP, FS_TURN_OFF, STOP_CONTROL, AWAIT } #endregion #region VARIABLES ## Словарь состояния сокетов ЭМС-Г 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 _default_states: Dictionary = {} ## Сохраняет состояния по умолчанию для сброса var _fs_rules: Array ## Основные переменные класса var config_manager: PRDConfigManager var unit_prd: Object var control_results: Dictionary var power_result: Dictionary 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 ecms: Dictionary var power_for_litera: Dictionary var self_name: String var state: int = STATE_MACHINE.INIT var current_litera: int var count_packets_power: int = 0 var current_ecm_key: int ## Флаги состояния системы var flags: Dictionary = { 'write_isa': false, 'fs_status_ok': false, 'si_fs_input': false, 'si_fs_output': false, 'in_control': false, 'control_is_over': false, 'no_trust_yau07': false, 'only_fs': false, 'ecm_is_comming': false, 'temperature_ok': true, } ## Таймеры контроля 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 prog_back: float = 0.0 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(device_name: String) # Когда контроль завершен signal status_updated(status_text: String) # Сигнал для обновления статуса signal control_results_updated(control_results: Dictionary) # Обновление результатов контроля signal update_progress(progress_value: float) # Обновление статуса выполнения контроля signal update_max_value_progress(max_progress_value: int) # Установка максимального значения для прогресс бара ## Свойство прогресса с автоматическим emit сигнала var progress_value: float: set(v): if progress_value != v: progress_value = v call_deferred('emit_signal', 'update_progress', v) #endregion #region INITIALIZATION ## Инициализация объекта контроля ПРД 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_default_states() -> void: _default_states = { # Флаги состояния системы 'flags': flags.duplicate(true), # Состояние машины и литеры 'state': state, 'current_litera': current_litera, # Переменные прогресса 'progress_value': progress_value, 'current_status': current_status, 'total_fs_to_check': total_fs_to_check, 'completed_fs_count': completed_fs_count, 'current_fs_progress': current_fs_progress, # Счетчики 'cc': cc, # Сокеты ЭМС-Г 'ems_g_sock_dic': ems_g_sock_dic.duplicate(true), # Структуры данных (глубокое копирование) 'power_for_litera': _deep_copy_power_structure(), 'control_results': control_results.duplicate(true), 'power_result': power_result.duplicate(true), 'temperature_um': temperature_um.duplicate(true), # Конфигурации блоков 'block_ip_config': block_ip_config.duplicate(true), 'block_kasseta_y5_config': block_kasseta_y5_config.duplicate(true), # Конфигурация устройства 'self_name': self_name, 'constants': constants.duplicate(true), 'pribor_config': pribor_config.duplicate(true), 'fs_parameters': fs_parameters.duplicate(true) } ## Инициализация конфигурации из менеджера 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_default_states() # Инициализация состояний по умолчанию initialize_connections() # Инициализация соединений и сигналов setup_timer() # Настройка таймеров контроля _initialize_ray_state_enums() # Инициализация перечислений значений для состояний лучей ## Инициализация маппинга состояний лучей 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', STATE_MACHINE.UG_SET_RAY_CTRL: 'RAY_CTRL', } ## Инициализация 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) #endregion #region PROCESS_METHODS ## Основной процесс (не используется, но оставлен для совместимости) func _process(_delta: float) -> void: pass ## Обработка данных от ЯУ-07 func on_data_received(unit_pribor: Object) -> void: var status: PackedByteArray = unit_pribor.status if status.size() < 100: push_error('Принимаемые значения от ЯУ-07б:%s не коррентны. (размер пакета: %d)' % [self_name, status.size()]); return temperature_um = check_temperature_um(status) flags.temperature_ok = check_overheating(temperature_um) block_ip_config = check_block_ip(status, block_ip_config) block_kasseta_y5_config = check_block_kasseta_y5(status, block_kasseta_y5_config, flags.no_trust_yau07) _set_control_result('block_kasseta', on_y5_control_result(block_kasseta_y5_config)) _set_control_result('temperature', flags.temperature_ok) _set_control_result('block_ip', on_dry_control_result(block_ip_config)) if not flags.in_control: return if machine_timer.is_stopped(): return if flags.no_trust_yau07: return socket_status_ems_g(status) _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 == 'RAY_CTRL': count_packets_power += 1 elif interes != '': tek_litera[_get_ray_key(state)] = power_um_ukp(status, current_litera, tek_litera[_get_ray_key(state)], false) power_for_litera[current_litera] = tek_litera count_packets_power += 1 ## Получение ключа луча по состоянию машины func _get_ray_key(machine_state: int) -> String: return _ray_state_mapping.get(machine_state, '') #endregion #region EMS_SOCKET_HANDLING ## Обработка статуса сокетов ЭМС-Г из пакета ЯУ-07 func socket_status_ems_g(packet_form_yau_07: PackedByteArray) -> void: # Обработка для разных типов приборов if self_name in ['1н', '2н', '3н', '4н']: 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 ['1в', '2в', '3в', '4в']: 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 ['1к', '2к', '3к', '4к']: 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_lit_1 = (packet_form_yau_07.decode_u16(config_manager.get_data_index('OUT_BLANK_PRD')) & (1 << 3)) != 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 # Определение флагов СИ ФС входа 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')) flags.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')) flags.si_fs_output = (out_blank & (1 << number_socket_output)) != 0 #endregion #region STATE_MACHINE ## Основная машина состояний контроля ПРД func state_control_machine() -> void: match state: STATE_MACHINE.INIT: _handle_init_state() STATE_MACHINE.CHEK_KASSETA_Y5: _handle_check_kasseta_state() # Проверка Кассеты У5 STATE_MACHINE.CHEK_BLOCK_IP: _handle_check_block_ip_state() # Проверка ИП STATE_MACHINE.FS_TURN_ON: _handle_fs_turn_on_state() STATE_MACHINE.FS_WORK: _handle_fs_work_state() STATE_MACHINE.READ_ISA: _handle_read_isa_state() STATE_MACHINE.UG_SET_RAY_CTRL: _handle_ray_operation(6) 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: _handle_ems_stop_state() STATE_MACHINE.FS_TURN_OFF: _handle_fs_turn_off_state() STATE_MACHINE.STOP_CONTROL: _handle_stop_control_state() # Обновление прогресс-бара после обработки состояния if block_kasseta_y5_config['yau07'] or flags.no_trust_yau07: progressbar_status() ## Обработка состояния INIT - инициализация ФС func _handle_init_state() -> void: if current_litera in [1, 2, 3, 4, 5, 6, 7]: _set_status('Инициализация ФС-%s' % current_litera) if _get_current_ecm(): return state = STATE_MACHINE.CHEK_KASSETA_Y5 else: # Завершение контроля если литеры закончились flags.control_is_over = true power_result = prep_power(power_for_litera, self_name) machine_timer.stop() _set_control_result('is_over_control', flags.control_is_over) 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', self_name) ## Обработка состояния FS_TURN_ON - включение ФС func _handle_fs_turn_on_state() -> void: _set_status('Включение ФС-%s' % current_litera) manage_fs(self_name, pribor_config, fs_parameters, current_litera, constants.POWER_UM) current_ecm_key = take_ecm_id(ecms, self_name, current_litera) flags.ecm_is_comming = current_ecm_key != -1 control_timer.wait_time = constants.TIMER_DELAY control_timer.start() state = STATE_MACHINE.FS_WORK static func take_ecm_id(ecm_dic: Dictionary, device_name: String, current_lit: int) -> int: # Получаем целевой nmfs из таблицы var target_nmfs: int = LITER_TO_NMFS.get(device_name, {}).get(current_lit, -1) if target_nmfs == -1: return 0 # Ищем ECM с соответствующим nmfs for ecm_id in ecm_dic: if ecm_dic[ecm_id].nmfs == target_nmfs: return ecm_id return 0 ## Обработка состояния FS_WORK - проверка работы ФС func _handle_fs_work_state() -> void: _set_status('Проверка связи сервиса КАПС РПБ') if not ecms.has(current_ecm_key): push_error('Нет текущей ecm: %s' % current_ecm_key); return _set_status('Ожидание выполнения помехи состояние %s литеры %s' % [ecms[current_ecm_key].svk, current_litera]) if current_ecm_key > 0 and ecms[current_ecm_key].svk == 1: if not flags.si_fs_input: _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): if flags.only_fs: state = STATE_MACHINE.IN_EMS_STOP elif not block_kasseta_y5_config['yau07']: _set_status('Ожидание данных от МП550 сервиса...') return else: state = STATE_MACHINE.UG_SET_RAY_5 if current_litera == 1 else STATE_MACHINE.UG_SET_RAY_CTRL ## Обработка состояния CHECK_KASSETA - проверка кассеты Y5 func _handle_check_kasseta_state() -> void: _set_status('Проверка кассеты У5') var block_kasseta_y5 = true for case in block_kasseta_y5_config: if not block_kasseta_y5_config[case]: block_kasseta_y5 = false if block_kasseta_y5: if flags.temperature_ok: ems_6666_timer.start() state = STATE_MACHINE.CHEK_BLOCK_IP else: _set_status('Перегрев УМ') state = STATE_MACHINE.IN_EMS_STOP else: flags.only_fs = true _set_status('Касета У5: ERROR, Проверка ФС.') state = STATE_MACHINE.FS_TURN_ON ## Обработка состояния CHECK_BLOCK_IP - проверка кассеты Y5 func _handle_check_block_ip_state() -> void: _set_status('Проверка источников питания') var block_ip = true for ip in block_ip_config: if not block_ip_config[ip][1]: block_ip = false state = STATE_MACHINE.FS_TURN_ON if block_ip else STATE_MACHINE.IN_EMS_STOP ## Обработка состояния READ_ISA - чтение из УГ func _handle_read_isa_state() -> void: 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) flags.write_isa = false state = STATE_MACHINE.UG_SET_RAY ## Обработка состояния EMS_STOP - остановка ЭМС func _handle_ems_stop_state() -> void: ems_6666_timer.stop() state = STATE_MACHINE.FS_TURN_OFF ## Обработка состояния FS_TURN_OFF - выключение ФС func _handle_fs_turn_off_state() -> void: state = STATE_MACHINE.STOP_CONTROL if not _get_current_ecm(): return _set_status('Отключение ФС-%s' % current_litera) flags.fs_status_ok = false signaller.emit_signal('interfer_off', ecms[current_ecm_key]) ## Обработка состояния STOP_CONTROL - завершение контроля func _handle_stop_control_state() -> void: _set_status('Завершение контроля ФС-%s' % current_litera) completed_fs_count += 1 _advance_to_next_fs() flags.ecm_is_comming = false state = STATE_MACHINE.INIT ## Переход к следующей литере контроля 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 #endregion #region RAY_OPERATIONS ## Универсальный обработчик операций с лучами 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 _handle_ray_write_mode(ray_num: int) -> void: if not _can_write_ray(): return if (ray_num == 6 or ray_num == 5) and not control_timer.is_stopped(): control_timer.stop() # Установка луча if not flags.write_isa: _handle_ug_set_state(ray_num) flags.write_isa = true # Ожидание COUNT_PACK_POWER_RECIEVE пакетов от ЯУ-07 if count_packets_power < COUNT_PACK_POWER_RECIEVE: return state = STATE_MACHINE.READ_ISA ## Обработка значения луча из 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: if count_packets_power < COUNT_PACK_POWER_RECIEVE: return state = STATE_MACHINE.UG_SET_RAY_0 ## Проверка возможности обработки состояния луча 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 _can_write_ray() -> bool: if not flags.si_fs_input: _set_status('Ожидание сигнала излучения от ФС-%s' % current_litera) return false else: return true ## Получение адреса UG для текущей литеры func _get_ug_address() -> int: return constants.ADDR_UG_LITERA_2 if current_litera in SPECIAL_LITERAS else constants.ADDR_UG_LITERA_1 #endregion #region UG_OPERATIONS ## Подготовка к настройке и записи в УГ func _handle_ug_set_state(RAY_DOU_NUM: int) -> void: var def_att: int = 0x00 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': def_att, 'BASE_EMS_G': constants.BASE_ADDR_EMS_G } # Конфигурация аттенюаторов для разных типов приборов if self_name == '1к' or self_name == '2к' or self_name == '3к' or self_name == '4к': 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 == '1в' or self_name == '2в' or self_name == '3в' or self_name == '4в': dic_att['ATT_UM_1'] = constants.ATT_UM_4 dic_att['ATT_UM_2'] = constants.ATT_UM_5 elif self_name == '1н' or self_name == '2н' or self_name == '3н' or self_name == '4н': dic_att['ATT_UM_1'] = constants.ATT_UM_2 dic_att['ATT_UM_2'] = constants.ATT_UM_3 var att_key = ATT_MAPPING[current_litera] _set_status('Литера-%s: Настройка угла %s, АТТ %s' % [current_litera, _get_ray_name(RAY_DOU_NUM), dic_att[att_key]]) flags.write_isa = on_ug_setting(unit_prd, dic_att, cmd_array, current_litera) count_packets_power = 0 ## Получение имени луча по номеру func _get_ray_name(ray_num: int) -> String: return RAY_CONFIG.get(ray_num, {}).get('name', 'неизвестный угол') #endregion #region PROGRESS_MANAGEMENT ## Обновление статуса прогресс-бара 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.UG_SET_RAY_0: base_progress = PROGRESS_RAY_STATES STATE_MACHINE.UG_SET_RAY_1: base_progress = PROGRESS_RAY_STATES + 5 STATE_MACHINE.UG_SET_RAY_2: base_progress = PROGRESS_RAY_STATES + 10 STATE_MACHINE.UG_SET_RAY_3: base_progress = PROGRESS_RAY_STATES + 15 STATE_MACHINE.UG_SET_RAY_4: base_progress = PROGRESS_RAY_STATES + 20 STATE_MACHINE.UG_SET_RAY_5: base_progress = PROGRESS_RAY_STATES + 25 STATE_MACHINE.IN_EMS_STOP: base_progress = PROGRESS_COMPLETE STATE_MACHINE.FS_TURN_OFF: base_progress = PROGRESS_COMPLETE + 5 STATE_MACHINE.STOP_CONTROL: base_progress = PROGRESS_COMPLETE + 10 # Плавное заполнение во время ожидания таймера 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 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 prog_back = fs_base_progress + (base_progress * progress_per_fs / PROGRESS_COMPLETE) else: prog_back = base_progress if control_timer.time_left > 0 and not control_timer.is_stopped(): prog_back += (control_timer.wait_time - control_timer.time_left) + 10 prog_back = progress_value if progress_value > prog_back else prog_back progress_value = clamp(progress_value, prog_back, PROGRESS_COMPLETE) ## Установка нового статуса с emit сигнала func _set_status(new_status: String) -> void: if current_status != new_status: current_status = new_status call_deferred('emit_signal', 'status_updated', new_status) #endregion #region TIMER_MANAGEMENT ## Настройка таймеров контроля 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: if state == STATE_MACHINE.UG_SET_RAY: flags.no_trust_yau07 = true push_error('no_trust_yau07: ', self_name) state = STATE_MACHINE.IN_EMS_STOP #endregion #region DEVICE_CONFIGURATION ## Определение имени и конфигурации устройства func _determine_self_name() -> void: flags.no_trust_yau07 = false flags.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: '1к', '2к', '3к', '4к': total_fs_to_check = 3 # Литеры 1, 6, 7 '1н', '2н', '3н', '4н': total_fs_to_check = 2 # Литеры 2, 3 '1в', '2в', '3в', '4в': total_fs_to_check = 2 # Литеры 4, 5 progress_value = 0 completed_fs_count = 0 current_fs_progress = 0.0 prog_back = 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 '' #endregion #region CONNECTIONS_MANAGEMENT ## Инициализация соединений и сигналов 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')) unit_prd.connect('line_changed', Callable(self, 'on_line_changed_yau07')) # Подключение сигналов режимов работы 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)) ## Обработка обновления состояния ФС от 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) flags.fs_status_ok = true if fs_result[fs_key] == 1 else false if not flags.si_fs_input: return control_results[fs_key] = fs_result[fs_key] ## Обработка изменения размера интерферометра func on_interfer_resized(ecms_dic: Dictionary) -> void: ecms = ecms_dic ## Обработка запуска контроля устройства func _on_start_contol_device()-> void: _set_status('Подготовка к контролю') restore_default_states() signaller.emit_signal('interfer_off_all') flags.in_control = true machine_timer.wait_time = constants.STATE_MASHINE_TIMER machine_timer.start() ## Обработка изменения режима работы func on_mode_changed(in_tree: bool) -> void: if not in_tree and flags.in_control: ## При нажатии выхода из режима контроль state = STATE_MACHINE.INIT cmd_array.append([unit_prd.CmdCode.WRITE_ISA,[ constants.ADDR_UG_LITERA_1, DATA_EXIT_CONTOL_ISA, constants.ADDR_UG_LITERA_2, DATA_EXIT_CONTOL_ISA, constants.ADDR_UG_LITERA_3, DATA_EXIT_CONTOL_ISA]]) flags.no_trust_yau07 = false flags.only_fs = false flags.ecm_is_comming = false flags.in_control = false progress_value = 0 _handle_fs_turn_off_state() if not machine_timer.is_stopped(): flags.control_is_over = false restore_default_states() machine_timer.stop() else: ## При нажатии на режим контроль _set_status('Ожидание запуска контроля') # Вызывается при смене связи я ячейков ЯУ-07Б func on_line_changed_yau07(_status: Object)->void: flags.control_is_over = false flags.no_trust_yau07 = false flags.only_fs = false restore_default_states() block_kasseta_y5_config.yau07 = _status.online if _status.online: _set_status('Ожидание запуска контроля') else: _set_status('Ячейка ЯУ-07Б: Нет связи') #endregion #region ECMS ## Универсальная проверка доступа к ecms: func _get_current_ecm() -> Variant: if current_ecm_key != 0 and ecms.has(current_ecm_key): return ecms[current_ecm_key] return null #endregion #region DKM_PROCESSING ## Обработка статуса ДКМ из пакета ЯУ-07 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 #endregion #region PUBLIC_API ## Геттер для текущего статуса func get_current_status() -> String: return current_status ## Геттер для результатов контроля func get_control_results() -> Dictionary: return { 'control_is_over': flags.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 } #endregion #region STATIC_UTILITY_METHODS ## Итоговое заключение по результатам контроля всех ИП static func on_dry_control_result(ip_config: Dictionary) -> bool: var all_blocks_ip_ok = true for block in ip_config: if not ip_config[block][1]: all_blocks_ip_ok = false return all_blocks_ip_ok ## Итоговое заключение по результатам контроля кассеты у5 static func on_y5_control_result(block_kasseta: Dictionary) -> bool: var all_blocks_y5_ok = true for block in block_kasseta: if not block_kasseta[block]: all_blocks_y5_ok = false return all_blocks_y5_ok ## Установка угла и аттенюации для УМ static func on_ug_setting(prd_unit: Object, settings_ug: Dictionary, prd_cmd_array: Array, cur_litera: int) -> bool: var result_1: int if cur_litera == 1: result_1 = ((settings_ug.ATT_UM_1 & 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]]) prd_cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [settings_ug.ADDR_UG_LITERA_3, settings_ug.ATT_UM_3]]) else: if cur_litera in [2, 4, 6]: result_1 = ((settings_ug.ATT_UM_1 & 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]]) elif cur_litera in [3, 5, 7]: result_1 = ((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_2, result_1]]) return true ## Обработка чтения ISA портов 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(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' 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('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 != 0 y5_config.ukp1 = (status_prd[0] >> 2) & 1 != 0 y5_config.ukp2 = (status_prd[0] >> 3) & 1 != 0 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 else: for i_temp in 8: return_dic_temp[arr_um[i_temp]] = -999 # Заполняем нулями если УКП нет на связи 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 else: for i_temp in 8: return_dic_temp[arr_um[i_temp+8]] = -999 # Заполняем -999 если УКП нет на связи return return_dic_temp static func check_overheating(temperature_data: Dictionary) -> bool: const MAX_TEMP: int = 55 const MIN_VALID_TEMP: int = -1500 const MAX_VALID_TEMP: int = 130 for key in temperature_data: var temp = temperature_data[key] # Пропускаем невалидные значения if temp < MIN_VALID_TEMP or temp > MAX_VALID_TEMP: continue # Проверяем превышение температуры if temp > MAX_TEMP: return false return true ## Проверка ДКМ 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к', 1: '4к', 2: '3к', 3: '2к', 4: '1н', 5: '4н', 6: '3н', 7: '2н', 8: '1н', 9: '4н', 10: '3н', 11: '2н', 12: '1в', 13: '4в', 14: '3в', 15: '2в', 16: '1в', 17: '4в', 18: '3в', 19: '2в', 20: '1к', 21: '4к', 22: '3к', 23: '2к', 24: '1к', 25: '4к', 26: '3к', 27: '2к', } 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, mode_work: bool) -> Array: const Constants: Dictionary = {'POWER_UKP_1' : 31, 'POWER_UKP_2': 63} var power_values: Array = [] var base_offset = 0 var iteration: int = 6 if not len(status): return power_values var ukp1_valid: bool = (status[0] >> 2) & 1 var ukp2_valid: bool = (status[0] >> 3) & 1 match litera: 1: var value = status.decode_u16(Constants.POWER_UKP_1 + 2 * 7) if ukp1_valid: power_values = [value] 2: base_offset = Constants.POWER_UKP_1 if ukp1_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) 3: base_offset = Constants.POWER_UKP_2 if ukp2_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) 4: base_offset = Constants.POWER_UKP_1 if ukp1_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) 5: base_offset = Constants.POWER_UKP_2 if ukp2_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) 6: base_offset = Constants.POWER_UKP_1 if ukp1_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) 7: base_offset = Constants.POWER_UKP_2 if ukp2_valid: for i in iteration: power_values.append(status.decode_u16(base_offset + 2 * i)) if not mode_work: 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: '1н', '2н', '3н', '4н': arr_litera = [2, 3] '1в', '2в', '3в', '4в': arr_litera = [4, 5] '1к', '2к', '3к', '4к': 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 dou: String = 'dou_2' if litera == 2 else 'dou_3' if pribor == '1к' or pribor == '2к' or pribor == '3к' or pribor == '4к': dou = 'dou_6' if litera == 6 else 'dou_7' elif pribor == '1в' or pribor == '2в' or pribor == '3в' or pribor == '4в': 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 # Подсчет значений ниже порога по позициям var low_power_by_position: Array = [0, 0, 0, 0, 0, 0] # Счетчики для 6 позиций for ray_key in [RAY_m5, RAY_5, RAY_15, RAY_25, RAY_35, RAY_45]: var power_array: Array = ray_dic[ray_key] for i in power_array.size(): if power_array[i] < cnst.POWER_THRESHOLD: low_power_by_position[i] += 1 # Проверяем, нет ли позиции где много низких значений var limit_power_um: int = 2 var good_positions: int = 0 for count in low_power_by_position: if count <= limit_power_um: good_positions += 1 control_dic[dou] = good_positions >= 4 return control_dic #endregion #region DEFAULT_STATES ## Глубокое копирование структуры мощностей func _deep_copy_power_structure() -> Dictionary: var copy = {} for litera in power_for_litera: copy[litera] = {} for ray_type in power_for_litera[litera]: copy[litera][ray_type] = power_for_litera[litera][ray_type].duplicate() return copy ## Восстановление состояний по умолчанию func restore_default_states() -> void: if _default_states.is_empty(): _initialize_default_states() # Восстановление простых переменных flags = _default_states['flags'].duplicate(true) state = _default_states['state'] current_litera = _default_states['current_litera'] progress_value = _default_states['progress_value'] current_status = _default_states['current_status'] total_fs_to_check = _default_states['total_fs_to_check'] completed_fs_count = _default_states['completed_fs_count'] current_fs_progress = _default_states['current_fs_progress'] cc = _default_states['cc'] # Восстановление словарей (глубокое копирование) ems_g_sock_dic = _default_states['ems_g_sock_dic'].duplicate(true) power_for_litera = _default_states['power_for_litera'].duplicate(true) control_results = _default_states['control_results'].duplicate(true) power_result = _default_states['power_result'].duplicate(true) temperature_um = _default_states['temperature_um'].duplicate(true) block_ip_config = _default_states['block_ip_config'].duplicate(true) # Остановка таймеров control_timer.stop() ems_6666_timer.stop() machine_timer.stop() #'Состояния сброшены к значениям по умолчанию' ## Получение текущих состояний для отладки func get_current_states() -> Dictionary: return { 'flags': flags.duplicate(true), 'state_machine': { 'state': state, 'current_litera': current_litera }, 'progress': { 'value': progress_value, 'status': current_status, 'total_fs': total_fs_to_check, 'completed_fs': completed_fs_count, 'current_fs_progress': current_fs_progress }, 'counters': { 'cc': cc, 'cmd_array_size': cmd_array.size() }, 'results': { 'power_for_litera': power_for_litera, 'power_results': power_result, 'control_results': control_results, } } #endregion #region setters func _set_control_result(key: String, status: bool)-> void: var old_value = control_results.get(key) if key == 'is_over_control' or old_value != status: control_results[key] = status emit_signal('control_results_updated', control_results) func _get_control_result(key: String) -> bool: return control_results[key] #endregion