diff --git a/data/main-font.tres b/data/main-font.tres index 24d67ef9..92f7276c 100644 --- a/data/main-font.tres +++ b/data/main-font.tres @@ -10,3 +10,11 @@ cache/0/16/0/underline_position = 0.0 cache/0/16/0/underline_thickness = 0.0 cache/0/16/0/scale = 1.0 cache/0/16/0/kerning_overrides/16/0 = Vector2(0, 0) +cache/0/16/0/kerning_overrides/14/0 = Vector2(0, 0) +cache/0/14/0/ascent = 0.0 +cache/0/14/0/descent = 0.0 +cache/0/14/0/underline_position = 0.0 +cache/0/14/0/underline_thickness = 0.0 +cache/0/14/0/scale = 1.0 +cache/0/14/0/kerning_overrides/16/0 = Vector2(0, 0) +cache/0/14/0/kerning_overrides/14/0 = Vector2(0, 0) diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index f4737732..00bca853 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -26,9 +26,11 @@ const INTERFER_NAMES = { 'mchm1': 'МЧМ-1', 'srni1': 'СРН-И1', 'srnm2': 'СРН-М2', + 'srngps': 'СРН-GPS', 'pdm4': 'ПД-М4', 'pdm2': 'ПД-М2', 'lchm1': 'ЛЧМ-1', + 'lchm2': 'ЛЧМ-2', 'pdm4s': 'ПД-М4С', 'pdchm': 'ПД-ЧМ', 'svi1': 'СВ-И1', diff --git a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn index ca32b73f..880bd60f 100644 --- a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn +++ b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn @@ -5,7 +5,7 @@ [node name="grd_btns" type="GridContainer"] offset_right = 1096.0 offset_bottom = 54.0 -columns = 14 +columns = 16 [node name="btn_off" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] layout_mode = 2 @@ -57,6 +57,16 @@ disabled = true toggle_mode = true metadata/rfi_name = "srnm2" +[node name="btn_p18" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +strips_rotation = 30.0 +text = "СРН-GPS" +disabled = true +toggle_mode = true +metadata/rfi_name = "srngps" + [node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] layout_mode = 2 size_flags_horizontal = 3 @@ -87,6 +97,16 @@ disabled = true toggle_mode = true metadata/rfi_name = "lchm1" +[node name="btn_p17" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] +layout_mode = 2 +size_flags_horizontal = 3 +size_flags_vertical = 3 +strips_rotation = 30.0 +text = "ЛЧМ-2" +disabled = true +toggle_mode = true +metadata/rfi_name = "lchm2" + [node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] layout_mode = 2 size_flags_horizontal = 3 diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 86d21643..6e04b6c3 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -233,7 +233,7 @@ func on_rto_threat_sel(th_id, ecm_btns): else: item.set_sel_visible(false) for btn in ecm_btns: - btn.set_disabled(false) + set_btns_disabled(false, btn) ## Обработчик снятия выбора РТО цели @@ -279,7 +279,7 @@ func on_interfer_selected(ecm, btns) -> void: else: ecm_name = interfer.INTERFER_OFF for btn in btns: - btn.set_disabled(false) + set_btns_disabled(false, btn) btn.get_meta('rfi_name') if ecm_name == btn.get_meta('rfi_name'): btn.set_pressed(true) @@ -432,7 +432,7 @@ func set_ecm_btns_state(value: bool): var btns: Array = get_tree().get_nodes_in_group('группа-режим-помехи') for btn in btns: btn.set_pressed(false) - btn.set_disabled(value) + set_btns_disabled(value, btn) func get_fs_param(index: int) -> Array: @@ -466,3 +466,12 @@ func get_fs_index(ecm): band = fs_freq.find_key(diap) var fs_index = band * 4 + sector return fs_index + + +func set_btns_disabled(value: bool, btn): + var external_cu = ProjectSettings.get_setting('application/config/external_cu', false) + if external_cu: + btn.set_pressed(false) + btn.set_disabled(true) + else: + btn.set_disabled(value) diff --git a/scripts/interfer.gd b/scripts/interfer.gd index ba54b2f3..55b1c869 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -4,22 +4,29 @@ extends Node ## Режимы помехи const ITERFER_MODE = { - 'off': ['Откл', ['freq', 'width']], - 'auto': ['АВТО', ['freq', 'width']], - 'srni1': ['СРН-И1', ['freq', 'width']], - 'srnm2': ['СРН-М2', ['freq', 'width']], - 'lchm1': ['ЛЧМ-1', ['freq', 'width']], - 'mchm1': ['МЧМ-1', ['freq', 'width']], - 'pdm2': ['ПД-М2', ['freq', 'width']], - 'pdm4': ['ПД-М4', ['freq', 'width']], - 'pdm4s': ['ПД-М4С', ['freq', 'width']], - 'pdchm': ['ПД-ЧМ', ['freq', 'width']], - 'svi1': ['СВ-И1', ['freq', 'width']], - 'svm2': ['СВ-М2', ['freq', 'width']], - 'k1': ['K1', ['freq', 'width', 'dur', 'period']], - 'ozp1': ['ОЗП-1', ['freq', 'width']] } + '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'], 4], + '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 TYPE_TH = ['th','fs'] +const FREQ_MAX = 6000 +const FREQ_MIN = 400 +const WIDTH_MAX = 120 +const WIDTH_MIN = 0 + +const SOURCE_INTERFER = ['th','fs','cu'] const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей const INTERFER_OFF = 'off' const STATE_TSMT = 5 ## Значение svk для цели, когда ответ ещё не получен @@ -27,21 +34,21 @@ var msg_ss: int = 0 ## счётчик сообщений var id_array: Array ## Массив id воздействий var thrs: Dictionary ## Словарь воздействия для целей, ключ - id воздействия var fs: Dictionary ## Словарь воздействий для секторов, ключ - id воздействия - +var cu: Dictionary ## Словарь воздействий для 5П-28, ключ - id воздействия ## Сеанс помехи 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 = 0.0 ## Мощность излучения выраженная в процентах. - var kni: = 0.0 ## Курсовой угол направления излучения. - var params: = {} ## Параметры помехи. - var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров). - var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров. - var tick_tx: int ## Тик время обновления цели, мс. - var type_th: String = '' ## Тип объекта по которой поставлена помеха + var ss: int = 0 ## Счётчик сообщений. + var ispp: int = 0 ## Индекс сеанса. + var svk: = 0 ## Состояние сеанса. Ответ КАПСРПБ. Возможные значения в [param ITERFER_STATE]. + var krp: String = '' ## Тип помехи. Возможные значения в [param INTERFER_MODE]. + var powp: float = 0.0 ## Мощность излучения выраженная в процентах. + var kni: = 0.0 ## Курсовой угол направления излучения. + var params: = {} ## Параметры помехи. + var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров). + var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров. + var tick_tx: int ## Тик время обновления цели, мс. + var source_interfer: String = '' ## Тип объекта по которой поставлена помеха func _to_string() -> String: return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni] @@ -92,13 +99,17 @@ func _ready(): id_array.append(i + 1) var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп') var unit = repnetwork.units[unit_key] + var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28') + var unit_5p28 = repnetwork.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)) @@ -145,33 +156,62 @@ func on_interfer_create(btn, sel_threats, fs_arr, _unit, ecms): var param: Dictionary = {} var kni: float = item.aoa var id = item.id + var interfer_name: String = btn.get_meta('rfi_name') param['freq'] = item.freq param['width'] = item.width - interfer_create(btn, ecms, param, kni, id, thrs, item, TYPE_TH[0]) + 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] + var interfer_name: String = btn.get_meta('rfi_name') param['freq'] = item[1] param['width'] = item[2] - interfer_create(btn, ecms, param, kni, id, fs, item, TYPE_TH[1]) + interfer_create(interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1]) -func interfer_create(btn, ecms, param, kni, id, dict, item, type_th): +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] + if (aoa < 0) and (aoa > 360): + err = true + var param: Dictionary = {} + param['freq'] = interfer_params[4] + if (param['freq'] < FREQ_MIN) and (param['freq'] > FREQ_MAX): + err = true + param['width'] = interfer_params[5] + if (param['width'] < WIDTH_MIN) and (param['width'] > 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 - var interfer_name: String = btn.get_meta('rfi_name') if interfer_name == 'k1': param['dur'] = 1.0 # Необходимо добавить параметры управления param['period'] = 1.0 # Необходимо добавить параметры управления var key = dict.find_key(id) - if key != null: - ispp = key - else: - if interfer_name == 'off': - return - ispp = pop_id() - if ispp == 0: return + 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 @@ -187,7 +227,7 @@ func interfer_create(btn, ecms, param, kni, id, dict, item, type_th): ecm.krp = interfer_name ecm.params = param ecm.powp = 100.0 # Необходимо добавить управление мощностью - ecm.type_th = type_th + ecm.source_interfer = source_interfer signaller.emit_signal('interfer_new', ecm) if interfer_name == 'off': signaller.emit_signal('interfer_off', ecm, ecms, thrs) @@ -220,3 +260,7 @@ func pop_id(): func push_id(id : int): id_array.append(id) id_array.sort() + + +## отправляет словаhь помех в юнит, для запаковки и отправки в 5П28 +func on_get_interfers(unit, ecms): unit.pack_interfers(cu, ecms) diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 4e14e72e..77718839 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -104,6 +104,11 @@ signal interfer_off (ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary) signal interfer_off_all () +## Вызывается при получении внешнего целеуказания +## [param interfer_params] - Параметры полученной помехи от 5П-28.[br] +signal interfer_rcv(interfer_params: Array) + + ## Вызывается, когда отключается действующая помеха.[br] ## [param ecm] - Выбранная помеха signal interfer_selected (ecm: interfer.Interfer) diff --git a/scripts/tcp5p28.gd b/scripts/tcp5p28.gd index 3d889bb4..d564213c 100644 --- a/scripts/tcp5p28.gd +++ b/scripts/tcp5p28.gd @@ -26,6 +26,14 @@ const MOD_TYPES: Array = ['', 'psk', 'ofdm',] +const CU_STATE: Dictionary = { + 0:2, # Подготовка к выполнению + 1:1, # Выполняется + 2:9, # Ошибка в команде + 3:7, # Занят выполнением другого ЦУ + 4:9, # Неисправность + } + class TCP5P28: const PACK_TYPE_CMD: int = 1 const PACK_TYPE_RES: int = 2 @@ -38,6 +46,7 @@ class TCP5P28: signal command_fail(unit: TCP5P28) ## Сигнал при не выполнении команды signal parse_error(unit: TCP5P28, msg: String) ## Сигнал ошибки разбора сообщения signal get_threats(unit: TCP5P28) ## Сигнал запрос целей + signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания var online: = false ## Состояние связи с источником сообщений var name: String ## Имя экземпляра @@ -58,6 +67,11 @@ class TCP5P28: var cmd_type = data.decode_u8(8) if cmd_type == CMD_TYPE_TH: emit_signal('get_threats') + if cmd_type == CMD_TYPE_STATE: + emit_signal('get_interfers') + var external_cu = ProjectSettings.get_setting('application/config/external_cu', false) + if cmd_type == CMD_TYPE_IN and external_cu: + set_interfer(data) func process(now_tick: int): if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT): @@ -70,19 +84,44 @@ class TCP5P28: else: return Error.ERR_UNAVAILABLE - func pack_threats(threats): + func pack_threats(ths): var data = PackedByteArray() - var data_len = 4 + len(threats) * 80 # длинна блока данных в байтах + var data_len = 4 + len(ths) * 80 # длинна блока данных в байтах var tick = Time.get_ticks_msec() data.resize(4) data.encode_u16(0, 0) # Код ошибки - data.encode_u16(2, len(threats)) # Количество целей - for th in threats.values(): + data.encode_u16(2, len(ths)) # Количество целей + for th in ths.values(): data.append_array(get_threats_data(th, int(tick))) var data_to_send: PackedByteArray = create_header(data_len) data_to_send.append_array(data) tx_stack.append(data_to_send) - + + func pack_interfers(interfers, ecms): + var data = PackedByteArray() + var data_len = 12 # длинна блока данных в байтах + data.resize(data_len) + data.encode_u16(0, 0) # Код ошибки + data.encode_u16(2, len(interfers)) # Количество целей + data.encode_u32(4, 0) # Состояние УА-РЕП + data.encode_u32(8, 0) # Состояние линий связи + for id in interfers.values(): + var cu_data: PackedByteArray = [] + cu_data.resize(4) + var cu = ecms[id] + cu_data.encode_u16(0, cu.ispp) + var state: int + if CU_STATE.has(cu.svk): + state = CU_STATE[cu.svk] + else: + state = 9 + cu_data.encode_u8(2, state) # Состояние выполнения команды + cu_data.encode_u8(3, 0xFF) # Эффективность работы помехи + data.append_array(cu_data) + var data_to_send: PackedByteArray = create_header(data_len + 4 * len(interfers)) + data_to_send.append_array(data) + tx_stack.append(data_to_send) + func create_header(data_len): var head_data = PackedByteArray() head_data.resize(8) # Размер заголовка @@ -127,10 +166,29 @@ class TCP5P28: th_data.encode_s32(76, int(th.lat * c1)) return th_data - func to_cp866(proto: String, th_data): + func to_cp866(proto: String, th_data): var cp866_proto: PackedByteArray = proto.to_ascii_buffer() cp866_proto.resize(36) for i in len(cp866_proto): th_data[28 + i] = cp866_proto[i] - + func set_interfer(data): + var mode = data.decode_u8(9) + var id = data.decode_u16(10) + var aoa = float(data.decode_u16(12)) / 10 + var ela = float(data.decode_u16(14)) / 10 + var freq = data.decode_u16(16) + var width = data.decode_u16(18) + var interfer_params: Array = [mode, id, aoa, ela, freq, width] + signaller.emit_signal('interfer_rcv', interfer_params) + + func on_interfer_accept(err: bool): + var data_tx = PackedByteArray() + var data_len = 2 # длинна блока данных в байтах + var tick = Time.get_ticks_msec() + data_tx.resize(data_len) + data_tx.encode_u16(0, err) # Код ошибки + var data_to_send: PackedByteArray = create_header(data_len) + data_to_send.append_array(data_tx) + tx_stack.append(data_to_send) + diff --git a/scripts/threats.gd b/scripts/threats.gd index 653a8365..b26ae779 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -74,7 +74,7 @@ func on_timer_check_lost(time_lost: int, threats: Dictionary): call_deferred('emit_signal', 'threats_resized', threats) -## отправляет словапь целей в юнит, для запаковки и отправки в 5П28 +## отправляет словарь целей в юнит, для запаковки и отправки в 5П28 func on_get_threats(unit, threats): unit.pack_threats(threats)