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

1405 lines
57 KiB
GDScript
Raw Permalink 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
#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': ''},
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: 11, 6: 16, 7: 17},
'': {1: 21, 6: 26, 7: 27},
'': {1: 31, 6: 36, 7: 37},
'': {1: 41, 6: 46, 7: 47},
'': {2: 12, 3: 13},
'': {2: 22, 3: 23},
'': {2: 32, 3: 33},
'': {2: 42, 3: 43},
'': {4: 14, 5: 15},
'': {4: 24, 5: 25},
'': {4: 34, 5: 35},
'': {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 ['', '', '', '']:
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_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 == '' 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
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:
'', '', '', '':
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
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: '', 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, 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:
'', '', '', '':
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 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
# Подсчет значений ниже порога по позициям
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