extends Node ## Работа с целями. const MSG9_RESEND_TIMEOUT = 1.0 ## Время повторной отправки пакета 9 ## Режимы работы АФСП и БПО (Протокол ТНИИС-СТЦ, пункт 2.5.10) enum AFSP_BPO_MODE { run = 1, test = 2 } var msg9_num: int = 0 ## Счётчик сообщений "тип 9" var gos_flag = true ## Флаг работать по своим целям var gos_protocols: PackedStringArray ## Список протоколов своих целей var bpo_mode: = AFSP_BPO_MODE.run ## Режим работы АФСП и БПО var bpo_mode_rx: = AFSP_BPO_MODE.run ## Режим работы БПО полученный от ## Цель class Threat: var alt: float ## Текущая высота, метры. var aoa: float ## Курсовой угол на источник сигнала, градусы. var atick: float ## Тик обнаружения. var baud: float ## Модуляционная скорость. var fflags: Dictionary ## Флаги достоверности полей. var freq: float ## Частота несущей или центральная частота, МГц. var freqm: String ## Режим смены частоты. var id: int ## Идентификатор цели. var lat: float ## Текущие координаты, широта в градусах. var lon: float ## Текущие координаты, долгота в градусах. var pow: float ## Уровень принимаемого сигнала, дБм. var proto: String ## Тип протокола источника сигнала. var rkrp: String ## Рекомендуемый режим помехи. var rparams: Dictionary ## Рекомендуемые параметры помехи. var salt: float ## Координаты старта, высота от уровня моря, м. var slat: float ## Координаты старта, широта в градусах. var slon: float ## Координаты старта, долгота в градусах. var tick: int ## Тик время приёма сигнала, мс. var tick_rx: int ## Тик время обновления цели, мс. var tmod: String ## Тип модуляции. var width: float ## Ширина занимаемого диапазона частот, МГц. var selected: bool ## Флаг, что цель выбрана. var auto_selected: bool = false ## Флаг автомата для целей var emit_state: int = 0 ## 0 - подавление не назначено, 1 - назначено, 2 - выполняется var nmfs: int ## Индекс модуля ФС, в зону действия которого попала цель var priority: int ## Приоритет опасности цели var gos: bool = false ## Своя или чужая цель func _init(): clear_fflags() func _to_string() -> String: return 'номер: %d пеленг: %0.1f частота: %0.1f МГц' % [id, aoa, freq] func clear_fflags(): tools.get_members_names(self).any(func(vn): fflags[vn] = false) func set_from_dic(dic: Dictionary): var items: = fflags.keys().filter(func(vn): return dic.has(vn)) items.any(func(vn): set(vn, dic[vn]); fflags[vn] = true; return false) signal threat_new(th: Threat) signal threat_lost(th: Threat) signal threat_update(th: Threat) signal threats_resized(th: Dictionary) func _ready() -> void: var unit_caps = network.get_unit_instance('уарэп-капсрпб') var unit_5p28 = network.get_unit_instance('уарэп-5п28') var timer_check_lost: = Timer.new() var timer_msg9: = Timer.new() var timer_aoa_update: = Timer.new() add_child(timer_check_lost) add_child(timer_aoa_update) add_child(timer_msg9) var threats = {} ## Список целей. Индекс - <номер цели> unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(threats)) unit_caps.connect('line_changed', Callable(self, 'on_caps_line_changed').bind(timer_msg9)) unit_5p28.connect('get_threats', Callable(self, 'on_get_threats').bind(unit_5p28, threats)) timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(settings.ThreatParams.time_lost, threats)) timer_check_lost.start(settings.ThreatParams.time_lost / 1000.0) timer_aoa_update.connect('timeout', Callable(self, 'on_timer_aoa_update').bind(threats, timer_aoa_update)) timer_aoa_update.start(3.0) timer_aoa_update.one_shot = true timer_msg9.connect('timeout', Callable(self, 'on_timer_msg9').bind(unit_caps, timer_msg9)) signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(threats)) signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(threats)) signaller.connect('rto_threat_unsel_all', Callable(self, 'on_rto_threat_unsel_all').bind(threats)) signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats)) signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats)) signaller.connect('connect_work_signal', Callable(self, 'on_connect_work_signal').bind(threats)) signaller.connect('режим_контроль', Callable(self, 'on_mode_change').bind(unit_caps, timer_msg9, AFSP_BPO_MODE.test)) signaller.connect('режим_работа', Callable(self, 'on_mode_change').bind(unit_caps, timer_msg9, AFSP_BPO_MODE.run)) ProjectSettings.connect('settings_changed', on_settings_changed.bind(threats)) ## Периодически удаляет устаревшие цели. func on_timer_check_lost(time_lost: int, threats: Dictionary): var tick: = Time.get_ticks_msec() var sz: = threats.size() for th in threats.values(): if (tick - th.tick_rx) >= time_lost: threats.erase(th.id) call_deferred('emit_signal', 'threat_lost', th) if sz != threats.size(): call_deferred('emit_signal', 'threats_resized', threats) func on_timer_aoa_update(threats:Dictionary, tmr): signaller.emit_signal('th_aoa_update', threats) tmr.start(1.0) ## отправляет словарь целей в юнит, для запаковки и отправки в 5П28. func on_get_threats(unit_instance, threats): unit_instance.pack_threats(threats) ## Снимает выделение с цели, если нажать по отметке цели. func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false ## Снимает выделение со всех целей. func on_rto_threat_unsel_all(threats): for th in threats.values(): signaller.emit_signal('rto_threat_unsel', th.id) ## Выбирает цель, если нажать по отметке цели. func on_rto_threat_sel(th_id, threats): on_threat_selected(threats[th_id], threats) ## Выбирает цель, если выбрать в таблице. func on_threat_selected(th, threats): for threat in threats.values(): threat.selected = false th.selected = true ## Формирует список выбранных целей для включения помехи. func on_interfer_init(interfer_name, fs_arr, power, threats): var sel_threats: Array = [] for threat in threats.values(): if interfer.auto_enabled: if threat.auto_selected: sel_threats.append(threat) else: if threat.selected: sel_threats.append(threat) if len(sel_threats) or len(fs_arr): signaller.emit_signal('interfer_create', interfer_name, sel_threats, fs_arr, power) ## Производит приём целей. func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary): if not unit.json_dic.has('ts'): return if unit.json_dic['ts'] != 5: return if not unit.json_dic.has('mis'): return if not unit.json_dic.has('sa'): return var mis = unit.json_dic['mis'] bpo_mode_rx = int(unit.json_dic['sa']) as AFSP_BPO_MODE var sz: = threats.size() for dic_th in mis: if dic_th is not Dictionary: continue if not dic_th.has('id'): continue var id = int(dic_th['id']) if threats.has(id): var th = threats[id] th.clear_fflags() th.set_from_dic(dic_th) th.tick_rx = unit.tick if th.fflags.proto and th.proto != '': th.priority = 1 else: th.priority = 0 set_gos(th) call_deferred('emit_signal', 'threat_update', th) else: var th: = Threat.new() th.set_from_dic(dic_th) threats[id] = th th.tick_rx = unit.tick set_gos(th) call_deferred('emit_signal', 'threat_new', th) if sz != threats.size(): call_deferred('emit_signal', 'threats_resized', threats) func on_settings_changed(ths: Dictionary): gos_flag = ProjectSettings.get_setting('application/config/Включить работу по своим целям', true) var protocols: String = ProjectSettings.get_setting('application/config/Список своих протоколов', '') gos_protocols = protocols.split(",", true) for th in ths.values(): set_gos(th) func set_gos(th: Threat): if gos_flag: th.gos = false elif (th.proto in gos_protocols) and th.fflags.proto: th.gos = true func on_connect_work_signal(ths: Dictionary): emit_signal('threats_resized', ths) func on_mode_change(unit_caps, timer_msg9, state): bpo_mode = state send_msg9(unit_caps) timer_msg9.start(MSG9_RESEND_TIMEOUT) func send_msg9(unit_caps): msg9_num += 1 var json_data : Dictionary = {} json_data['ts'] = 9 json_data['ss'] = msg9_num json_data['sa'] = bpo_mode var pac = JSON.stringify(json_data).to_utf8_buffer() unit_caps.tx_stack.append(pac) func on_timer_msg9(unit_caps, timer_msg9): if bpo_mode != bpo_mode_rx: send_msg9(unit_caps) else: timer_msg9.stop() func on_caps_line_changed(unit_caps, timer_msg9): if unit_caps.online: send_msg9(unit_caps) timer_msg9.start(MSG9_RESEND_TIMEOUT)