375 lines
14 KiB
GDScript
375 lines
14 KiB
GDScript
@tool
|
||
extends "res://scenes/контроль/прибор.gd"
|
||
|
||
const Constants = {
|
||
'IN_BLANK_PRD': 1,
|
||
'OUT_BLANK_PRD': 13,
|
||
'CI_4_OT_FS': 11,
|
||
'CI_5_OT_FS': 12,
|
||
'CI_4_B_UF': 4,
|
||
'CI_5_B_UF': 5,
|
||
'POWER_UKP_1': 31,
|
||
'POWER_UKP_2': 63,
|
||
'DKM_BIT_3': 3,
|
||
'DKM_BIT_4': 4,
|
||
'ADDR_UG_LITERA_1': 0x106,
|
||
'ADDR_UG_LITERA_2': 0x108,
|
||
'TEMP_THRESHOLD': 70,
|
||
'POWER_THRESHOLD': 40,
|
||
'TIMER_DELAY': 1.4,
|
||
'POWER_UM': 70,
|
||
}
|
||
enum STATE_VAL { NONE = 0, GOOD = 1, ERROR = 2 }
|
||
# Основные переменные
|
||
var count_packet_1:int = 0
|
||
var count_packet_2:int = 0
|
||
var power_array_1: Array = []
|
||
var power_array_2: Array = []
|
||
var currecnt_unit: String
|
||
var ug_work_1: int
|
||
var ug_work_2: int
|
||
# Флаги и таймеры
|
||
var control_timer: Timer = Timer.new()
|
||
var flag_timer_started: bool = false
|
||
# Результаты контроля
|
||
var _control_results: Dictionary = {
|
||
'block_ip': false, # Проверка касет П1 и ИП МА2000
|
||
'temperature': true, # Проверка температур УМ
|
||
'dkm_1': false, # Проверка ДКМ
|
||
'dkm_2': false, # Проверка ДКМ
|
||
'power_ukp': false, # Мощность от УКП
|
||
'fs_1': false, # Проверка ФС
|
||
'fs_2': false,
|
||
}
|
||
|
||
|
||
func _ready() -> void:
|
||
initialize_connections()
|
||
setup_timer()
|
||
set_default_state()
|
||
|
||
|
||
func initialize_connections() -> void:
|
||
signaller.conn(signaller.fs_update_state, Callable(self, 'on_fs_update_state'))
|
||
var unit_name = get_meta('unit_name')[0]
|
||
var unit_prd = network.get_unit_instance(unit_name)
|
||
currecnt_unit = unit_prd.name
|
||
unit_prd.connect('data_received', Callable(self, 'on_data_received'))
|
||
unit_prd.connect('line_changed', Callable(self, 'on_line_changed'))
|
||
|
||
|
||
func setup_timer() -> void:
|
||
add_child(control_timer)
|
||
control_timer.connect('timeout', Callable(self, 'on_stop_control'))
|
||
control_timer.one_shot = true
|
||
control_timer.wait_time = 10.0
|
||
control_timer.start()
|
||
|
||
|
||
func _enter_tree() -> void:
|
||
$control_result.text = ''
|
||
signaller.connect('режим_работа', Callable(self, 'on_mode_changed').bind(false))
|
||
signaller.emit_signal('interfer_off_all')
|
||
await get_tree().create_timer(2.0).timeout
|
||
_on_control_fs(true)
|
||
|
||
|
||
func _exit_tree() -> void:
|
||
var unit_name = get_meta('unit_name')[0]
|
||
var unit_prd = network.get_unit_instance(unit_name)
|
||
var prd_module = prd.prd_dict[unit_prd.name]
|
||
prd_module.cmd_array.append([unit_prd.CmdCode.WRITE_ISA, [Constants.ADDR_UG_LITERA_1, ug_work_1, Constants.ADDR_UG_LITERA_2, ug_work_2]])
|
||
|
||
|
||
func set_default_state() -> void:
|
||
for group in get_tree().get_nodes_in_group('default_reset'):
|
||
group.state = STATE_VAL.NONE
|
||
|
||
for group in get_tree().get_nodes_in_group('power_amplifier'):
|
||
group.state = STATE_VAL.NONE
|
||
|
||
|
||
func on_line_changed(unit_prd: Object) -> void:
|
||
if not unit_prd.online:
|
||
set_default_state()
|
||
|
||
|
||
# Основной процесс по принятию и обработки пакетов
|
||
func on_data_received(unit_prd: Object) -> void:
|
||
if not is_inside_tree():
|
||
return
|
||
|
||
var status = unit_prd.status
|
||
check_block_ip(status)
|
||
check_temperature_um(status)
|
||
# Обработка данных ЭМС
|
||
_process_ems_data(status)
|
||
|
||
if flag_timer_started:
|
||
check_dkm(status, Constants.DKM_BIT_3)
|
||
check_dkm(status, Constants.DKM_BIT_4)
|
||
# Обработка мощности от УКП
|
||
_process_ukp_power(status)
|
||
|
||
|
||
## Проверка касет П1 и ИП МА2000
|
||
func check_block_ip(status_prd: PackedByteArray) -> void:
|
||
var ug_online: bool = (status_prd[0] >> 1) & 1
|
||
if not ug_online:
|
||
for node in [$maa2000_A23, $maa2000_A22, $kasseta_P_1/ref_A19, $kasseta_P_1/ref_A20, $kasseta_P_1/ref_A21]:
|
||
node.state = STATE_VAL.NONE
|
||
return
|
||
|
||
const BYTE_DRY_CONTACT: int = 27
|
||
const BIT_MAA2000_1: int = 0
|
||
const BIT_MAA2000_2: int = 1
|
||
const BIT_IP9_50_1: int = 2
|
||
const BIT_IP9_50_2: int = 3
|
||
const BIT_IP12_50_1: int = 4
|
||
|
||
var maa2000_1 = status_prd[BYTE_DRY_CONTACT] >> BIT_MAA2000_1 & 1
|
||
var maa2000_2 = status_prd[BYTE_DRY_CONTACT] >> BIT_MAA2000_2 & 1
|
||
var ip9_50_1 = status_prd[BYTE_DRY_CONTACT] >> BIT_IP9_50_1 & 1
|
||
var ip9_50_2 = status_prd[BYTE_DRY_CONTACT] >> BIT_IP9_50_2 & 1
|
||
var ip12_50_1 = status_prd[BYTE_DRY_CONTACT] >> BIT_IP12_50_1 & 1
|
||
|
||
$maa2000_A23.state = STATE_VAL.ERROR if maa2000_1 else STATE_VAL.GOOD
|
||
$maa2000_A22.state = STATE_VAL.ERROR if maa2000_2 else STATE_VAL.GOOD
|
||
$kasseta_P_1/ref_A19.state = STATE_VAL.ERROR if ip9_50_1 else STATE_VAL.GOOD
|
||
$kasseta_P_1/ref_A20.state = STATE_VAL.ERROR if ip9_50_2 else STATE_VAL.GOOD
|
||
$kasseta_P_1/ref_A21.state = STATE_VAL.ERROR if ip12_50_1 else STATE_VAL.GOOD
|
||
|
||
_control_results['block_ip'] = (
|
||
$maa2000_A23.state == STATE_VAL.GOOD and
|
||
$maa2000_A22.state == STATE_VAL.GOOD and
|
||
$kasseta_P_1/ref_A19.state == STATE_VAL.GOOD and
|
||
$kasseta_P_1/ref_A20.state == STATE_VAL.GOOD and
|
||
$kasseta_P_1/ref_A21.state == STATE_VAL.GOOD
|
||
)
|
||
|
||
|
||
## Проверка температур УМ от УКП
|
||
func check_temperature_um(status_prd: PackedByteArray) -> void:
|
||
const TEMP_CONSTANTS = {
|
||
'min_temp': -25,
|
||
'max_code': 3796,
|
||
'min_code': 2660,
|
||
'temp_factor': 115.0 / (3796 - 2660),
|
||
'offset': 3 # Корректировка температуры
|
||
}
|
||
const TEMPERATURE_UKP_1: int = 47
|
||
const TEMPERATURE_UKP_2: int = 79
|
||
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
|
||
|
||
# Сбрас флагов перед проверкой
|
||
_control_results['temperature'] = true
|
||
|
||
var ukp1_online: int = (status_prd[0] >> 2) & 1
|
||
if ukp1_online:
|
||
for i_temp in range(6):
|
||
var temperature_ukp_1: int = status_prd.decode_u16(TEMPERATURE_UKP_1 + 2 * i_temp)
|
||
var tmp_1: int = round(TEMP_CONSTANTS['min_temp'] + (TEMP_CONSTANTS['max_code'] - temperature_ukp_1) * TEMP_CONSTANTS['temp_factor'] + TEMP_CONSTANTS['offset'])
|
||
power_amplifier[i_temp].value0 = tmp_1
|
||
if tmp_1 > Constants.TEMP_THRESHOLD:
|
||
_control_results['temperature'] = false
|
||
|
||
var ukp2_online = (status_prd[0] >> 3) & 1
|
||
if ukp2_online:
|
||
for i_temp in range(6):
|
||
var temperature_ukp_2: int = status_prd.decode_u16(TEMPERATURE_UKP_2 + 2 * i_temp)
|
||
var tmp_2: int = round(TEMP_CONSTANTS['min_temp'] + (TEMP_CONSTANTS['max_code'] - temperature_ukp_2) * TEMP_CONSTANTS['temp_factor'] + TEMP_CONSTANTS['offset'])
|
||
power_amplifier[i_temp+6].value0 = tmp_2
|
||
if tmp_2 > Constants.TEMP_THRESHOLD:
|
||
_control_results['temperature'] = false
|
||
|
||
|
||
## Проверка ДКМ
|
||
func check_dkm(status_prd: PackedByteArray, bit_dkm: int) -> void:
|
||
const DKM: int = 28
|
||
var status_dkm = status_prd[DKM] >> bit_dkm & 1
|
||
if bit_dkm == Constants.DKM_BIT_3:
|
||
$dou5_A6.state = STATE_VAL.GOOD if status_dkm else STATE_VAL.ERROR
|
||
$kasseta_FS_VD/ref_A2.state = STATE_VAL.GOOD if status_dkm else STATE_VAL.ERROR
|
||
_control_results['dkm_1'] = status_dkm
|
||
elif bit_dkm == Constants.DKM_BIT_4:
|
||
$dou4_A5.state = STATE_VAL.GOOD if status_dkm else STATE_VAL.ERROR
|
||
$kasseta_FS_VD/ref_A6.state = STATE_VAL.GOOD if status_dkm else STATE_VAL.ERROR
|
||
_control_results['dkm_2'] = status_dkm
|
||
|
||
|
||
# Обрабатывает данные ЭМС и обновляет UI панели
|
||
func _process_ems_data(status: PackedByteArray) -> void:
|
||
## Контроль ЭМС
|
||
var in_blank: int = status.decode_u16(Constants.IN_BLANK_PRD)
|
||
var out_blank: int = status.decode_u16(Constants.OUT_BLANK_PRD)
|
||
|
||
# Обновление фреймов для входных сигналов
|
||
$Monitoring_panel/in_fs_1.frame = (in_blank >> Constants.CI_4_OT_FS) & 1
|
||
$Monitoring_panel/in_fs_2.frame = (in_blank >> Constants.CI_5_OT_FS) & 1
|
||
|
||
# Обновление фреймов для выходных сигналов ЭМС
|
||
$Monitoring_panel/out_ems_1.frame = (out_blank >> Constants.CI_4_B_UF) & 1
|
||
$Monitoring_panel/out_ems_2.frame = (out_blank >> Constants.CI_5_B_UF) & 1
|
||
|
||
|
||
func _process_ukp_power(status: PackedByteArray) -> void:
|
||
## Мощность УМ от УКП 1
|
||
var arr_power_ukp_1: Array = []
|
||
|
||
if (status[0] >> 2) & 1:
|
||
for i_power in range(6):
|
||
var power_ukp_1 = status.decode_u16(Constants.POWER_UKP_1 + 2 * i_power)
|
||
arr_power_ukp_1.append(power_ukp_1)
|
||
|
||
if count_packet_1 == 0:
|
||
power_array_1 = arr_power_ukp_1
|
||
else:
|
||
for i in arr_power_ukp_1.size():
|
||
if arr_power_ukp_1[i] > power_array_1[i]:
|
||
power_array_1[i] = arr_power_ukp_1[i]
|
||
|
||
var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier')
|
||
for i in 6:
|
||
power_amplifier[i].value1 = '%d' % power_array_1[i]
|
||
power_amplifier[i].state = STATE_VAL.GOOD if power_array_1[i] > Constants.POWER_THRESHOLD else STATE_VAL.ERROR
|
||
count_packet_1 += 1
|
||
|
||
## Мощность УМ от УКП 2
|
||
var arr_power_ukp_2: Array = []
|
||
|
||
if (status[0] >> 2) & 1:
|
||
for i_power in range(6):
|
||
var power_ukp_2 = status.decode_u16(Constants.POWER_UKP_2 + 2 * i_power)
|
||
arr_power_ukp_2.append(power_ukp_2)
|
||
|
||
if count_packet_2 == 0:
|
||
power_array_2 = arr_power_ukp_2
|
||
else:
|
||
for i in arr_power_ukp_2.size():
|
||
if arr_power_ukp_2[i] > power_array_2[i]:
|
||
power_array_2[i] = arr_power_ukp_2[i]
|
||
|
||
for i in 6:
|
||
power_amplifier[i+6].value1 = '%d' % power_array_2[i]
|
||
power_amplifier[i+6].state = STATE_VAL.GOOD if power_array_2[i] > Constants.POWER_THRESHOLD else STATE_VAL.ERROR
|
||
|
||
count_packet_2 += 1
|
||
|
||
_control_results['power_ukp'] = true
|
||
for amp in power_amplifier:
|
||
if amp.state != STATE_VAL.GOOD:
|
||
_control_results['power_ukp'] = false
|
||
break
|
||
|
||
|
||
func _on_control_fs(mode: bool) -> void:
|
||
var parts = currecnt_unit.split('-')
|
||
var last_part = parts[-1]
|
||
var angle: float = 0.0 # -> ПРД-В1; 90.0 -> ПРД-В2; 180.0 -> ПРД-В3; 270.0 -> ПРД-В4
|
||
var sector_1: float = 12 # -> ПРД-В1; 15 -> ПРД-В2; 14 -> ПРД-В3; 13 -> ПРД-В4;
|
||
var sector_2: float = 16 # -> ПРД-В1; 19 -> ПРД-В2; 18 -> ПРД-В3; 17 -> ПРД-В4;
|
||
if last_part == '2в':
|
||
angle = 90.0
|
||
sector_1 = 15
|
||
sector_2 = 19
|
||
elif last_part == '3в':
|
||
angle = 180.0
|
||
sector_1 = 14
|
||
sector_2 = 18
|
||
elif last_part == '4в':
|
||
angle = 270.0
|
||
sector_1 = 13
|
||
sector_2 = 17
|
||
|
||
var interfer_name: String = 'k1' if mode else 'off'
|
||
var freq_1: float = 1227.0 # ФС_1
|
||
var freq_2: float = 1575.0 # ФС_2
|
||
var hz_1: float = 340.0 # ФС_1
|
||
var hz_2: float = 510.0 # ФС_2
|
||
|
||
var fs_arr: Array = [[angle, freq_1, hz_1, sector_1], [angle, freq_2, hz_2, sector_2]]
|
||
signaller.emit_signal('interfer_init', interfer_name, fs_arr, Constants.POWER_UM)
|
||
|
||
|
||
func on_stop_control() -> void:
|
||
print_debug('Остановка контроля ПРД')
|
||
_on_control_fs(false)
|
||
on_control_result()
|
||
|
||
|
||
func on_fs_update_state(packet_type_7: Dictionary) -> void:
|
||
var parts = currecnt_unit.split('-')
|
||
var last_part = parts[-1] # Прибор
|
||
|
||
# Словарь для маппинга: ключ - номер FS, значение - целевая нода и условие прибора
|
||
var fs_mapping = {
|
||
12: { 'node': $kasseta_FS_VD/ref_A3, 'condition': last_part == '1в' },
|
||
13: { 'node': $kasseta_FS_VD/ref_A3, 'condition': last_part == '4в' },
|
||
14: { 'node': $kasseta_FS_VD/ref_A3, 'condition': last_part == '3в' },
|
||
15: { 'node': $kasseta_FS_VD/ref_A3, 'condition': last_part == '2в' },
|
||
16: { 'node': $kasseta_FS_VD/ref_A4, 'condition': last_part == '1в' },
|
||
17: { 'node': $kasseta_FS_VD/ref_A4, 'condition': last_part == '4в' },
|
||
18: { 'node': $kasseta_FS_VD/ref_A4, 'condition': last_part == '3в' },
|
||
19: { 'node': $kasseta_FS_VD/ref_A4, 'condition': last_part == '2в' }
|
||
}
|
||
for fs in packet_type_7:
|
||
if fs in fs_mapping and fs_mapping[fs]['condition']:
|
||
var data = packet_type_7[fs]
|
||
var state = STATE_VAL.GOOD if data.isg == 1 else STATE_VAL.ERROR if data.isg == 0 else STATE_VAL.NONE
|
||
fs_mapping[fs]['node'].state = state
|
||
if fs < 16:
|
||
_control_results['fs_1'] = (data.isg == 1)
|
||
else:
|
||
_control_results['fs_2'] = (data.isg == 1)
|
||
if _control_results['fs_1'] and _control_results['fs_2'] and not flag_timer_started:
|
||
on_ug_setting()
|
||
control_timer.wait_time = Constants.TIMER_DELAY
|
||
control_timer.start()
|
||
flag_timer_started = true
|
||
|
||
|
||
func on_ug_setting() -> void:
|
||
var unit_name = get_meta('unit_name')[0]
|
||
var unit_prd = network.units[unit_name]
|
||
|
||
if unit_prd.isa_ports.has(Constants.ADDR_UG_LITERA_1):
|
||
ug_work_1 = unit_prd.isa_ports[Constants.ADDR_UG_LITERA_1]
|
||
if unit_prd.isa_ports.has(Constants.ADDR_UG_LITERA_2):
|
||
ug_work_2 = unit_prd.isa_ports[Constants.ADDR_UG_LITERA_2]
|
||
|
||
const dou = 0x3
|
||
const att = 0x7
|
||
var result = ((att & 0x07) << 3) | (dou & 0x07)
|
||
|
||
var prd_module = prd.prd_dict[unit_prd.name]
|
||
prd_module.cmd_array.append([unit_prd.CmdCode.WRITE_ISA, [Constants.ADDR_UG_LITERA_1, result, Constants.ADDR_UG_LITERA_2, result, 0x120, 6666]])
|
||
|
||
|
||
func on_mode_changed(in_tree: bool) -> void:
|
||
if not in_tree:
|
||
queue_free()
|
||
|
||
|
||
func on_control_result() -> void:
|
||
var result: bool = true
|
||
|
||
for key in _control_results:
|
||
if not _control_results[key]:
|
||
if key == 'fs_1':
|
||
$kasseta_FS_VD/ref_A3.state = STATE_VAL.ERROR
|
||
if key == 'fs_2':
|
||
$kasseta_FS_VD/ref_A4.state = STATE_VAL.ERROR
|
||
result = false
|
||
print_debug('%s false' % key)
|
||
|
||
var parts = currecnt_unit.split('-')
|
||
var last_part = parts[-1] # Прибор
|
||
if result:
|
||
$control_result.text = 'Прибор ПРД-%s исправен' % last_part
|
||
$control_result.add_theme_color_override("font_color", Color.AQUAMARINE)
|
||
else:
|
||
$control_result.text = 'Прибор ПРД-%s неисправен' % last_part
|
||
$control_result.add_theme_color_override("font_color", Color.CRIMSON)
|
||
await get_tree().create_timer(Constants.TIMER_DELAY).timeout
|
||
flag_timer_started = false
|