extends Label enum DEVICE_STATE { NONE, # Нет связи GOOD, # Исправно ERR # Отказ } enum DEVICE_STATUS { ONLINE, # Связь есть STATUS, # Статус исправности CONTROL # Контроль завершен } # Состояния сервиса для RTR устройств enum RTR_SERVICEABILITY { NO_CONNECTION = 0, # Нет связи PASSED = 1, # Все тесты пройдены ERROR = 2 # Есть ошибки } const STATUS_CONFIG := { DEVICE_STATE.NONE: {'text': 'Нет связи', 'color': Color.WHITE, 'font_color': Color.BLACK}, DEVICE_STATE.GOOD: {'text': 'Исправно', 'color': Color.GREEN, 'font_color': Color.BLACK}, DEVICE_STATE.ERR: {'text': 'Отказ', 'color': Color.RED, 'font_color': Color.WHITE} } class DeviceObserver: var device_name: String var status: Array = [false, false, false] # [online, operational, control_complete] var last_results: Dictionary = {} # Для RTR устройств var rtr_serviceability: int = RTR_SERVICEABILITY.NO_CONNECTION func update_online_state(online: bool) -> bool: if status[DEVICE_STATUS.ONLINE] != online: status[DEVICE_STATUS.ONLINE] = online return true return false func update_control_results(results: Dictionary) -> bool: var changed := false if results.get('is_over_control', false): # Контроль завершен - проверяем все результаты var all_ok := true for key in results: if key != 'is_over_control' and not results[key]: all_ok = false break if status[DEVICE_STATUS.STATUS] != all_ok or status[DEVICE_STATUS.CONTROL] != true: status[DEVICE_STATUS.STATUS] = all_ok status[DEVICE_STATUS.CONTROL] = true changed = true else: # Контроль в процессе - проверяем базовые параметры var basic_ok: bool = results.get('block_kasseta', false) and \ results.get('block_ip', false) and \ results.get('temperature', true) if status[DEVICE_STATUS.STATUS] != basic_ok or status[DEVICE_STATUS.CONTROL] != false: status[DEVICE_STATUS.STATUS] = basic_ok status[DEVICE_STATUS.CONTROL] = false changed = true return changed func update_rtr_serviceability(state: int) -> bool: if rtr_serviceability != state: rtr_serviceability = state # Обновляем operational статус на основе RTR var new_operational = (state == RTR_SERVICEABILITY.PASSED) if status[DEVICE_STATUS.STATUS] != new_operational: status[DEVICE_STATUS.STATUS] = new_operational return true return false var device_observers: Dictionary = {} var overall_prd_state: DEVICE_STATE = DEVICE_STATE.NONE var status_uf: int = DEVICE_STATE.NONE # Статус УФ (УАРЭП-ЭМС) # Добавляем наблюдателей для RTR устройств var rtr_device_names := [ 'rtr_afsp_left', 'rtr_afsp_right', 'rtr_bpo' # Общий для левого и правого БПО ] func _ready() -> void: tooltip_text = 'Нет связи с приборами комплекса' add_theme_color_override('font_color', Color.BLACK) # Инициализация наблюдателей _initialize_observers() # Подписка на сигналы ПРД модулей for prd_module in prd.prd_dict.values(): # Подключаемся к контролю ПРД if prd_module.unit_control: prd_module.unit_control.connect('control_results_updated', Callable(self, '_on_prd_control_results').bind(prd_module)) # Подключаемся к онлайн-статусу ЯУ-07 if prd_module.unit_yau07: prd_module.unit_yau07.connect('line_changed', Callable(self, '_on_prd_online_changed').bind(prd_module)) # Подписка на УФ signaller.connect('update_uf_serviceability', _on_uf_status_receive) # Подписка на сигналы RTR (через signaller или напрямую) _connect_rtr_signals() # Инициализация начального состояния _recalculate_overall_state() func _connect_rtr_signals() -> void: scouting.connect('serviceability_rtr_afsp_left', Callable(self, '_on_rtr_afsp_left_serviceability')) scouting.connect('serviceability_rtr_afsp_right', Callable(self, '_on_rtr_afsp_right_serviceability')) scouting.connect('serviceability_rtr_bpo', Callable(self, '_on_rtr_bpo_serviceability')) func _initialize_observers() -> void: var device_names := [ 'уарэп-яу07-1н', 'уарэп-яу07-1в', 'уарэп-яу07-1к', 'уарэп-яу07-2н', 'уарэп-яу07-2в', 'уарэп-яу07-2к', 'уарэп-яу07-3н', 'уарэп-яу07-3в', 'уарэп-яу07-3к', 'уарэп-яу07-4н', 'уарэп-яу07-4в', 'уарэп-яу07-4к' ] for device_name in device_names: device_observers[device_name] = DeviceObserver.new() device_observers[device_name].device_name = device_name # Инициализируем наблюдателей для RTR устройств for rtr_name in rtr_device_names: device_observers[rtr_name] = DeviceObserver.new() device_observers[rtr_name].device_name = rtr_name # Обработчики сигналов RTR func _on_rtr_afsp_left_serviceability(state: int) -> void: var observer: DeviceObserver = device_observers.get('rtr_afsp_left') if not observer: return var changed = false if observer.update_rtr_serviceability(state): changed = true var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION) if observer.update_online_state(is_online): changed = true if changed: _recalculate_overall_state() else: _update_display() func _on_rtr_afsp_right_serviceability(state: int) -> void: var observer: DeviceObserver = device_observers.get('rtr_afsp_right') if not observer: return var changed = false if observer.update_rtr_serviceability(state): changed = true var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION) if observer.update_online_state(is_online): changed = true if changed: _recalculate_overall_state() else: _update_display() func _on_rtr_bpo_serviceability(state: int) -> void: var observer: DeviceObserver = device_observers.get('rtr_bpo') if not observer: return var changed = false if observer.update_rtr_serviceability(state): changed = true var is_online = (state != RTR_SERVICEABILITY.NO_CONNECTION) if observer.update_online_state(is_online): changed = true if changed: _recalculate_overall_state() else: _update_display() func _on_prd_online_changed(line_status: Object, prd_module: Object) -> void: var online: bool = line_status.online var observer: DeviceObserver = device_observers.get(prd_module.prd_name) if observer and observer.update_online_state(online): _recalculate_overall_state() func _on_prd_control_results(results: Dictionary, prd_module: Object) -> void: var observer: DeviceObserver = device_observers.get(prd_module.prd_name) if observer and observer.update_control_results(results): _recalculate_overall_state() func _on_uf_status_receive(unit_uf_status: int) -> void: if status_uf != unit_uf_status: status_uf = unit_uf_status _recalculate_overall_state() func _recalculate_overall_state() -> void: var new_state := DEVICE_STATE.NONE # Проверяем статус ПРД var prd_state := DEVICE_STATE.NONE var has_online_prd := false var all_prd_operational := true for observer_key in device_observers.keys(): # Пропускаем RTR устройства при подсчете ПРД if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE]: has_online_prd = true if observer.status[DEVICE_STATUS.CONTROL]: if not observer.status[DEVICE_STATUS.STATUS]: all_prd_operational = false break else: if not observer.status[DEVICE_STATUS.STATUS]: all_prd_operational = false if has_online_prd: if all_prd_operational: prd_state = DEVICE_STATE.GOOD else: prd_state = DEVICE_STATE.ERR else: prd_state = DEVICE_STATE.NONE # Проверяем статус RTR устройств var rtr_state := DEVICE_STATE.NONE var has_online_rtr := false var all_rtr_operational := true for rtr_name in rtr_device_names: var observer = device_observers.get(rtr_name) if observer and observer.status[DEVICE_STATUS.ONLINE]: has_online_rtr = true if not observer.status[DEVICE_STATUS.STATUS]: all_rtr_operational = false if has_online_rtr: if all_rtr_operational: rtr_state = DEVICE_STATE.GOOD else: rtr_state = DEVICE_STATE.ERR else: rtr_state = DEVICE_STATE.NONE # Комбинируем статусы по правилу: # 1. Если хоть один ERROR → ERROR # 2. Если нет ERROR и хоть один GOOD → GOOD # 3. Иначе → NONE if prd_state == DEVICE_STATE.ERR or status_uf == DEVICE_STATE.ERR or rtr_state == DEVICE_STATE.ERR: new_state = DEVICE_STATE.ERR elif prd_state == DEVICE_STATE.GOOD or status_uf == DEVICE_STATE.GOOD or rtr_state == DEVICE_STATE.GOOD: new_state = DEVICE_STATE.GOOD else: new_state = DEVICE_STATE.NONE if overall_prd_state != new_state: overall_prd_state = new_state _update_display() func _update_display() -> void: var config: Dictionary = STATUS_CONFIG[overall_prd_state].duplicate() text = config.text modulate = config.color add_theme_color_override('font_color', config.font_color) tooltip_text = _get_tooltip_text() func _get_tooltip_text() -> String: var tooltip := '' # Получаем статистику по ПРД var prd_summary = _get_prd_summary() var uf_status_str = _get_uf_status_text() var rtr_summary = _get_rtr_summary() match overall_prd_state: DEVICE_STATE.NONE: tooltip = 'Нет исправных систем в комплексе' DEVICE_STATE.GOOD: tooltip = 'Комплекс исправен' DEVICE_STATE.ERR: tooltip = 'Обнаружены неисправности в комплексе' tooltip += '\n\nСтатус ПРД систем: ' + prd_summary tooltip += '\nСтатус УФ: ' + uf_status_str tooltip += '\nСтатус RTR: ' + rtr_summary # Детализация по источникам статуса tooltip += '\n\nСостояние систем:' # ПРД системы var prd_ok_count = 0 var prd_total = 0 for observer_key in device_observers.keys(): if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE]: prd_total += 1 if observer.status[DEVICE_STATUS.STATUS]: prd_ok_count += 1 tooltip += '\nПРД: %d/%d исправно' % [prd_ok_count, prd_total] # УФ система tooltip += '\nУФ: ' + _get_uf_status_text() # RTR системы tooltip += '\nRTR:' for rtr_name in rtr_device_names: var observer = device_observers.get(rtr_name) if observer: var status_text = _get_rtr_status_text(observer.rtr_serviceability) var display_name = _get_rtr_display_name(rtr_name) tooltip += '\n - %s: %s' % [display_name, status_text] return tooltip func _get_rtr_summary() -> String: var online_count := 0 var operational_count := 0 for rtr_name in rtr_device_names: var observer = device_observers.get(rtr_name) if observer and observer.status[DEVICE_STATUS.ONLINE]: online_count += 1 if observer.status[DEVICE_STATUS.STATUS]: operational_count += 1 if online_count == 0: return 'Нет связи' else: return '%d/%d исправно' % [operational_count, online_count] func _get_rtr_status_text(state: int) -> String: match state: RTR_SERVICEABILITY.NO_CONNECTION: return 'Нет связи' RTR_SERVICEABILITY.PASSED: return 'Исправен' RTR_SERVICEABILITY.ERROR: return 'Ошибка' _: return 'Неизвестно' func _get_rtr_display_name(rtr_key: String) -> String: match rtr_key: 'rtr_afsp_left': return 'АФСП Л' 'rtr_afsp_right': return 'АФСП П' 'rtr_bpo': return 'РТР' _: return rtr_key.replace('rtr_', '') func _get_prd_summary() -> String: var online_count := 0 var operational_count := 0 for observer_key in device_observers.keys(): if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE]: online_count += 1 if observer.status[DEVICE_STATUS.STATUS]: operational_count += 1 if online_count == 0: return 'Нет связи' else: return '%d/%d исправно' % [operational_count, online_count] func _get_uf_status_text() -> String: match status_uf: DEVICE_STATE.NONE: return 'Нет данных' DEVICE_STATE.GOOD: return 'Исправен' DEVICE_STATE.ERR: return 'Неисправен' _: return 'Неизвестно' func _has_prd_errors() -> bool: for observer_key in device_observers.keys(): if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE] and not observer.status[DEVICE_STATUS.STATUS]: return true return false func _has_operational_prd() -> bool: for observer_key in device_observers.keys(): if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE] and observer.status[DEVICE_STATUS.STATUS]: return true return false # Публичные методы для получения информации func get_device_status(device_name: String) -> Dictionary: var observer: DeviceObserver = device_observers.get(device_name) if observer: return { 'online': observer.status[DEVICE_STATUS.ONLINE], 'operational': observer.status[DEVICE_STATUS.STATUS], 'control_complete': observer.status[DEVICE_STATUS.CONTROL], 'last_results': observer.last_results.duplicate(), 'status_uf': status_uf, 'rtr_serviceability': observer.rtr_serviceability if device_name.begins_with('rtr_') else -1 } return {} func get_overall_status() -> Dictionary: var online_count := 0 var operational_count := 0 var control_complete_count := 0 for observer_key in device_observers.keys(): if observer_key.begins_with('rtr_'): continue var observer = device_observers[observer_key] if observer.status[DEVICE_STATUS.ONLINE]: online_count += 1 if observer.status[DEVICE_STATUS.STATUS]: operational_count += 1 if observer.status[DEVICE_STATUS.CONTROL]: control_complete_count += 1 return { 'overall_state': overall_prd_state, 'online_devices': online_count, 'operational_devices': operational_count, 'total_devices': device_observers.size() - len(rtr_device_names), # Исключаем RTR 'control_complete_devices': control_complete_count, 'uf_status': status_uf, 'rtr_status': _get_rtr_summary() }