1405 lines
57 KiB
GDScript
1405 lines
57 KiB
GDScript
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
|