extends Label enum DEVICE_STATE { NONE, # Нет связи GOOD, # Исправно ERR # Отказ } enum DEVICE_STATUS { ONLINE, # Связь есть STATUS, # Статус исправности CONTROL # Контроль завершен } 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 = {} 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 var device_observers: Dictionary = {} var overall_prd_state: DEVICE_STATE = DEVICE_STATE.NONE var status_uf: int = DEVICE_STATE.NONE # Статус УФ (УАРЭП-ЭМС) 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) # Инициализация начального состояния _recalculate_overall_state() 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 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 in device_observers.values(): 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 # Комбинируем статусы по правилу: # 1. Если хоть один ERROR → ERROR # 2. Если нет ERROR и хоть один GOOD → GOOD # 3. Иначе → NONE if prd_state == DEVICE_STATE.ERR or status_uf == DEVICE_STATE.ERR: new_state = DEVICE_STATE.ERR elif prd_state == DEVICE_STATE.GOOD or status_uf == 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() 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\nСостояние систем:' # ПРД системы var prd_ok_count = 0 var prd_total = 0 for observer in device_observers.values(): 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() return tooltip func _get_prd_summary() -> String: var online_count := 0 var operational_count := 0 for observer in device_observers.values(): 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 in device_observers.values(): if observer.status[DEVICE_STATUS.ONLINE] and not observer.status[DEVICE_STATUS.STATUS]: return true return false func _has_operational_prd() -> bool: for observer in device_observers.values(): 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 } return {} func get_overall_status() -> Dictionary: var online_count := 0 var operational_count := 0 var control_complete_count := 0 for observer in device_observers.values(): 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(), 'control_complete_devices': control_complete_count, 'uf_status': status_uf }