328 lines
14 KiB
GDScript
328 lines
14 KiB
GDScript
class_name Iterfer extends Node
|
||
|
||
## Представление помехи.
|
||
|
||
## Режимы помехи.
|
||
const ITERFER_MODE = {
|
||
'off': ['Откл', ['freq', 'width'], 0],
|
||
'auto': ['АВТО', ['freq', 'width'], 1000],
|
||
'srni1': ['СРН-И1', ['freq', 'width'], 1],
|
||
'srnm2': ['СРН-М2', ['freq', 'width'], 2],
|
||
'srngps': ['СРН-GPS', ['freq', 'width'], 3],
|
||
'lchm1': ['ЛЧМ-1', ['freq', 'width'], 10],
|
||
'lchm2': ['ЛЧМ-2', ['freq', 'width'], 16],
|
||
'mchm1': ['МЧМ-1', ['freq', 'width'], 11],
|
||
'pdm2': ['ПД-М2', ['freq', 'width'], 12],
|
||
'pdm4': ['ПД-М4', ['freq', 'width'], 13],
|
||
'pdm4s': ['ПД-М4С', ['freq', 'width'], 14],
|
||
'pdchm': ['ПД-ЧМ', ['freq', 'width'], 15],
|
||
'svi1': ['СВ-И1', ['freq', 'width'], 20],
|
||
'svm2': ['СВ-М2', ['freq', 'width'], 21],
|
||
'k1': ['K1', ['freq', 'width', 'dur', 'period'], 50],
|
||
'ozp1': ['ОЗП-1', ['freq', 'width'], 51] }
|
||
|
||
|
||
const SOURCE_INTERFER = ['th','fs','cu']
|
||
const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей.
|
||
const INTERFER_OFF = 'off'
|
||
const STATE_TSMT = 5 ## Значение svk для цели, когда ответ ещё не получен.
|
||
var msg_ss: int = 0 ## Счётчик сообщений.
|
||
var id_array: Array ## Массив id воздействий.
|
||
var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия.
|
||
var fs: Dictionary ## Словарь воздействий для секторов, ключ - id воздействия.
|
||
var cu: Dictionary ## Словарь воздействий для 5П-28, ключ - id воздействия.
|
||
var auto_status: int = 0 ## Статус скролла автомата
|
||
var emit_enable: bool = true ## Разрешить излучение
|
||
|
||
## Сеанс помехи.
|
||
class Interfer:
|
||
var ss: int = 0 ## Счётчик сообщений.
|
||
var ispp: int = 0 ## Индекс сеанса.
|
||
var svk: = 0 ## Состояние сеанса. Ответ КАПСРПБ. Возможные значения в [param ITERFER_STATE].
|
||
var krp: String = '' ## Тип помехи. Возможные значения в [param INTERFER_MODE].
|
||
var powp: float = 100.0 ## Мощность излучения выраженная в процентах.
|
||
var kni: = 0.0 ## Курсовой угол направления излучения.
|
||
var params: = {} ## Параметры помехи.
|
||
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
|
||
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
|
||
var tick_tx: int ## Тик время обновления цели, мс.
|
||
var source_interfer: String = '' ## Тип объекта по которой поставлена помеха.
|
||
var modulation: bool ## Модуляция для включения усилителей
|
||
var um: float ## Угол места для помехи.
|
||
|
||
func _to_string() -> String:
|
||
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
|
||
|
||
func get_msg6_data() -> PackedByteArray:
|
||
var data_to_json : Dictionary = {}
|
||
data_to_json['ts'] = 6
|
||
data_to_json['ss'] = ss
|
||
data_to_json['ispp'] = ispp
|
||
data_to_json['krp'] = krp
|
||
if krp != INTERFER_OFF:
|
||
data_to_json['kni'] = kni
|
||
data_to_json['powp'] = powp # TODO: Необходимо добавить управление мощностью
|
||
data_to_json['get'] = []
|
||
data_to_json['params'] = params
|
||
var pac = JSON.stringify(data_to_json).to_utf8_buffer()
|
||
return pac
|
||
|
||
func set_from_dic(dic: Dictionary):
|
||
var names: = tools.get_members_names(self)
|
||
names.any(func(vn): if dic.has(vn): set(vn, dic[vn]); return false)
|
||
|
||
func get_value(value_key):
|
||
var param = self.get(value_key)
|
||
if param == null:
|
||
if params.has(value_key): param = params[value_key]
|
||
return param
|
||
|
||
func set_value(value, value_key):
|
||
var param = self.get(value_key)
|
||
if param == null:
|
||
params[value_key] = value
|
||
else:
|
||
self.set(value_key, value)
|
||
|
||
signal interfer_preparing(ecm: Interfer) ## Вызывается в момент запуска помехи.
|
||
signal interfer_run(ecm: Interfer) ## Вызывается в момент начала работы помехи.
|
||
signal interfer_error(ecm: Interfer, msg: String) ## Вызывается при ошибке.
|
||
signal interfer_update(ecm: Interfer) ## Вызывается при обновлении помехи.
|
||
signal interfer_resized(ecms: Dictionary) ## Вызывается при изменении количества сеансов помех.
|
||
|
||
|
||
func _ready():
|
||
var ecms: Dictionary = {} ## Словарь помех.
|
||
for i in ID_INTERFERS_LEN: # Заполняет массив ID целей
|
||
id_array.append(i + 1)
|
||
var unit_key = settings.get_unit_key('уарэп-капсрпб')
|
||
var unit = network.units[unit_key]
|
||
var unit_5p28_key = settings.get_unit_key('уарэп-5п28')
|
||
var unit_5p28 = network.units_tcp[unit_5p28_key]
|
||
var timer_check_state: = Timer.new()
|
||
add_child(timer_check_state)
|
||
var resend_timeout = ProjectSettings.get_setting('application/interfer/resend_timeout', 1000.0)
|
||
timer_check_state.connect('timeout', Callable(self, 'on_timer_check_state').bind(unit, ecms, resend_timeout))
|
||
timer_check_state.start(resend_timeout / 1000.0)
|
||
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms))
|
||
unit_5p28.connect('get_interfers', Callable(self, 'on_get_interfers').bind(unit_5p28, ecms))
|
||
signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms))
|
||
signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms))
|
||
signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit))
|
||
signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit, ecms))
|
||
signaller.connect('th_aoa_update', Callable(self, 'on_th_aoa_update').bind(ecms, unit))
|
||
signaller.connect('interfer_off', Callable(self, 'on_interfer_off'))
|
||
signaller.connect('manual_control', Callable(self, 'on_manual_control'))
|
||
signaller.connect('full_auto', Callable(self, 'on_full_auto'))
|
||
signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno'))
|
||
signaller.connect('emit_changed', Callable(self, 'on_emit_changed').bind(ecms))
|
||
threats.connect('threat_lost', Callable(self, 'on_threats_lost').bind(ecms, unit))
|
||
|
||
|
||
## Проверяет состояние отправки пакета и если не доставлен, повторяет отправку.
|
||
func on_timer_check_state(unit, ecms, resend_timeout):
|
||
var tick = Time.get_ticks_msec()
|
||
for ecm in ecms.values():
|
||
if ecm.svk == STATE_TSMT:
|
||
if (tick - ecm.tick_tx) >= resend_timeout:
|
||
send_ecm(ecm, unit)
|
||
ecm.tick_tx = tick
|
||
|
||
|
||
func on_manual_control():
|
||
auto_status = 0
|
||
|
||
|
||
func on_full_auto():
|
||
auto_status = 3
|
||
|
||
|
||
func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit):
|
||
for thr in threats.values():
|
||
var th_id = thr.id
|
||
for ecm_i in thrs.keys():
|
||
if thrs[ecm_i] == th_id:
|
||
var ecm = ecms[ecm_i]
|
||
ecm.params['freq'] = thr.freq
|
||
ecm.kni = thr.aoa
|
||
send_ecm(ecm, unit)
|
||
signaller.emit_signal('fs_update_color', ecms)
|
||
prd.update_fs_state(ecms)
|
||
|
||
if auto_status == 0:
|
||
return
|
||
|
||
if auto_status == 3:
|
||
for thr in threats.values():
|
||
thr.auto_selected = true
|
||
signaller.emit_signal('interfer_init', 'lchm1', [])
|
||
thr.auto_selected = false
|
||
|
||
|
||
## Производит приём состояния помех. [param unit] -> [param ecms].
|
||
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
|
||
if not unit.json_dic.has('ts'): return
|
||
if not (unit.json_dic['ts'] is float): return
|
||
if unit.json_dic['ts'] != 5: return
|
||
if not unit.json_dic.has('msvk'): return
|
||
if not (unit.json_dic['msvk'] is Array): return
|
||
var msvk = unit.json_dic['msvk']
|
||
var sz: = ecms.size()
|
||
for dic_msvk in msvk:
|
||
if not (dic_msvk is Dictionary): continue
|
||
if dic_msvk.has('ispp'):
|
||
var ispp = int(dic_msvk['ispp'])
|
||
if ecms.has(ispp):
|
||
var ecm = ecms[ispp]
|
||
ecm.set_from_dic(dic_msvk)
|
||
call_deferred('emit_signal', 'interfer_update', ecm)
|
||
else:
|
||
var ecm = Interfer.new()
|
||
ecm.set_from_dic(dic_msvk)
|
||
ecm.krp = INTERFER_OFF
|
||
send_ecm(ecm, unit)
|
||
if sz != ecms.size():
|
||
call_deferred('emit_signal', 'interfer_resized', ecms)
|
||
|
||
|
||
## Вызыватся, когда пользователь выбрал помеху и выбраны цели.
|
||
func on_interfer_create(interfer_name, sel_threats, fs_arr, _unit, ecms):
|
||
for item in sel_threats:
|
||
var param: Dictionary = {}
|
||
var kni: float = item.aoa
|
||
var id = item.id
|
||
param['freq'] = item.freq
|
||
param['width'] = item.width
|
||
if (param['width'] < settings.WIDTH_MIN):
|
||
param['width'] = settings.WIDTH_MIN
|
||
elif (param['width'] > settings.WIDTH_MAX):
|
||
param['width'] = settings.WIDTH_MAX
|
||
interfer_create(interfer_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0])
|
||
|
||
for item in fs_arr:
|
||
var param: Dictionary = {}
|
||
var kni: float = item[0]
|
||
var id = item[3]
|
||
param['freq'] = item[1]
|
||
param['width'] = item[2]
|
||
interfer_create(interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1])
|
||
|
||
|
||
func on_interfer_rcv(interfer_params: Array, unit, ecms):
|
||
var err: bool = false
|
||
var mode = interfer_params[0]
|
||
var id = interfer_params[1]
|
||
var aoa = interfer_params[2]
|
||
var um = interfer_params[3]
|
||
if (aoa < 0.0) and (aoa > 360.0):
|
||
err = true
|
||
var param: Dictionary = {}
|
||
if (um < -settings.UM_MIN) and (um > settings.UM_MAX):
|
||
err = true
|
||
param['um'] = um
|
||
param['freq'] = interfer_params[4]
|
||
if (param['freq'] < settings.FREQ_MIN) and (param['freq'] > settings.FREQ_MAX):
|
||
err = true
|
||
param['width'] = interfer_params[5]
|
||
if (param['width'] < settings.WIDTH_MIN) and (param['width'] > settings.WIDTH_MAX):
|
||
err = true
|
||
var interfer_name: String
|
||
for key in ITERFER_MODE:
|
||
if ITERFER_MODE[key][2] == mode:
|
||
interfer_name = key
|
||
break
|
||
if interfer_name == '':
|
||
err = true
|
||
if not err:
|
||
interfer_create(interfer_name, ecms, param, aoa, id, cu, SOURCE_INTERFER[2])
|
||
unit.on_interfer_accept(err)
|
||
|
||
|
||
func interfer_create(interfer_name, ecms, param, kni, id, dict, source_interfer):
|
||
var ispp: int = 0
|
||
if interfer_name == 'k1':
|
||
param['dur'] = 1.0 # Необходимо добавить параметры управления
|
||
param['period'] = 1.0 # Необходимо добавить параметры управления
|
||
var key = dict.find_key(id)
|
||
if source_interfer != SOURCE_INTERFER[2]:
|
||
if key != null:
|
||
ispp = key
|
||
else:
|
||
if interfer_name == 'off':
|
||
return
|
||
ispp = pop_id()
|
||
if ispp == 0:
|
||
return
|
||
else:
|
||
ispp = id
|
||
dict[ispp] = id
|
||
msg_ss += 1
|
||
var ecm: Interfer
|
||
if ecms.has(ispp):
|
||
ecm = ecms[ispp]
|
||
else:
|
||
ecm = Interfer.new()
|
||
ecm.ispp = ispp
|
||
ecms[ispp] = ecm
|
||
ecm.svk = STATE_TSMT # Подготовка к передаче сообщения
|
||
ecm.ss = msg_ss
|
||
ecm.kni = kni
|
||
ecm.krp = interfer_name
|
||
ecm.params = param
|
||
ecm.powp = 100.0
|
||
ecm.source_interfer = source_interfer
|
||
ecm.modulation = emit_enable
|
||
if param.has('um'):
|
||
ecm.um = param['um']
|
||
else:
|
||
ecm.um = 15.0 # Значение по умолчанию
|
||
signaller.emit_signal('interfer_new', ecm)
|
||
if interfer_name == 'off':
|
||
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
|
||
thrs.erase(ispp)
|
||
ecm.tick_tx = Time.get_ticks_msec()
|
||
|
||
|
||
func send_ecm(ecm, unit):
|
||
var json_data = ecm.get_msg6_data()
|
||
unit.tx_stack.append(json_data)
|
||
|
||
|
||
func on_interfer_off_all(unit, ecms):
|
||
for ecm in ecms.values():
|
||
ecm.krp = INTERFER_OFF
|
||
send_ecm(ecm, unit)
|
||
signaller.emit_signal('interfer_off',ecm, ecms, thrs)
|
||
|
||
|
||
func on_threats_lost(th, ecms, unit):
|
||
for key in interfer.thrs:
|
||
if interfer.thrs[key] == th.id:
|
||
var ecm_id = key
|
||
var ecm = ecms[ecm_id]
|
||
ecm.krp = INTERFER_OFF
|
||
send_ecm(ecm, unit)
|
||
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
|
||
|
||
|
||
func pop_id() -> int:
|
||
var id = 0
|
||
if len(id_array):
|
||
id = id_array[0]
|
||
id_array.remove_at(0)
|
||
return id
|
||
|
||
|
||
func push_id(id : int):
|
||
id_array.append(id)
|
||
id_array.sort()
|
||
|
||
|
||
## Отправляет словарь помех в юнит, для запаковки и отправки в 5П28.
|
||
func on_get_interfers(unit, ecms): unit.pack_interfers(cu, ecms)
|
||
|
||
func on_emit_changed(state, ecms):
|
||
emit_enable = state
|
||
for ecm in ecms.values():
|
||
ecm.modulation = state
|