478 lines
17 KiB
GDScript
478 lines
17 KiB
GDScript
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()
|
||
}
|