From db668d4b49621434a7010480c97f73c321d14ce2 Mon Sep 17 00:00:00 2001 From: sasha80 Date: Thu, 9 Oct 2025 13:46:35 +0300 Subject: [PATCH] =?UTF-8?q?=D0=92=20=D0=BF=D1=80=D0=BE=D1=86=D0=B5=D1=81?= =?UTF-8?q?=D1=81=D0=B5.=20Subject:=20[PATCH]=20Merge=20remote-tracking=20?= =?UTF-8?q?branch=20'lepshiy/master'=20=D0=A2=D1=80=D0=B0=D1=81=D1=81?= =?UTF-8?q?=D0=B0.=20=D0=9D=D0=B0=D0=B6=D0=B0=D1=82=D0=B8=D0=B5/=D0=BE?= =?UTF-8?q?=D1=82=D0=B6=D0=B0=D1=82=D0=B8=D0=B5=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BE=D0=BA=20=D0=B3=D1=80=D1=83=D0=BF=D0=BF=D1=8B=20=D0=BF?= =?UTF-8?q?=D1=80=D0=B8=D0=BD=D1=83=D0=B4=D0=B8=D1=82=D0=B5=D0=BB=D1=8C?= =?UTF-8?q?=D0=BD=D0=BE.=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D0=B0.=20=D0=BF?= =?UTF-8?q?=D0=B0=D1=80=D1=81=D0=B8=D0=BD=D0=B3=20=D0=BF=D0=BE=D0=BB=D1=83?= =?UTF-8?q?=D1=87=D0=B5=D0=BD=D0=BD=D0=BE=D0=B3=D0=BE=20=D0=BF=D0=B0=D0=BA?= =?UTF-8?q?=D0=B5=D1=82=D0=B0=20=D0=BE=D1=82=20=D1=82=D1=80=D0=B0=D1=81?= =?UTF-8?q?=D1=81=D1=8B,=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BA=D0=B0=20=D1=82?= =?UTF-8?q?=D1=80=D0=B0=D1=81=D1=81=D1=8B=20=D0=B2=20=D0=BD=D0=B0=D1=81?= =?UTF-8?q?=D1=82=D1=80=D0=BE=D0=B9=D0=BA=D0=B0=D1=85,=20=D0=BF=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B0/=D1=81=D0=BD?= =?UTF-8?q?=D1=8F=D1=82=D0=B8=D0=B5=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85,=20?= =?UTF-8?q?=D1=81=D0=B1=D0=BE=D1=80=D0=BA=D0=B0=20=D0=B8=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BF?= =?UTF-8?q?=D0=B0=D0=BA=D0=B5=D1=82=D0=B0=20=D0=B2=20=D1=82=D1=80=D0=B0?= =?UTF-8?q?=D1=81=D1=81=D1=83=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F.=20=D0=98=D1=81=D0=BF=D1=80=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D1=8B=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B0=20=D1=83?= =?UTF-8?q?=D0=B3=D0=BB=D0=B0=20=D0=BC=D0=B5=D1=81=D1=82=D0=B0.=20=D0=98?= =?UTF-8?q?=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D1=8F.?= =?UTF-8?q?=20=D0=9B=D0=B8=D1=88=D0=BD=D1=8F=D1=8F=20=D0=BF=D1=80=D0=BE?= =?UTF-8?q?=D0=B2=D0=B5=D1=80=D0=BA=D0=B0=20=D0=BF=D1=80=D0=B8=20=D0=BE?= =?UTF-8?q?=D1=82=D0=B6=D0=B0=D1=82=D0=BE=D0=B9=20=D0=BA=D0=BD=D0=BE=D0=BF?= =?UTF-8?q?=D0=BA=D0=B5=20=D0=9F=D0=BE=D0=B4=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D1=8F.=20Merge=20remote-tracking=20branch=20'refs/remote?= =?UTF-8?q?s/Cat/master'=20=D1=82=D1=80=D0=B0=D1=81=D1=81=D0=B0.=20=D0=BF?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=B0=D0=BD=D0=BE=D0=B2=D0=BA=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=85=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=BA=D0=B0.=20=D0=9F=D0=B5=D1=80=D0=B5=D0=B4=D0=B5?= =?UTF-8?q?=D0=BB=D0=B0=D0=BD=20=D0=BC=D0=B5=D1=85=D0=B0=D0=BD=D0=B8=D0=B7?= =?UTF-8?q?=D0=BC=20=D0=BE=D1=82=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8,=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=B5=D1=91=20=D0=BE=D1=82=D0=BA=D0=BB=D1=8E=D1=87?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D1=8F=20=D0=BD=D0=B0=D0=B4=D0=BE=20=D0=BE?= =?UTF-8?q?=D1=82=D0=BF=D1=80=D0=B0=D0=B2=D0=B8=D1=82=D1=8C=20=D1=82=D0=BE?= =?UTF-8?q?=D0=BB=D1=8C=D0=BA=D0=BE=20=D1=81=D0=B0=D0=BC=D1=83=20=D0=BF?= =?UTF-8?q?=D0=BE=D0=BC=D0=B5=D1=85=D1=83.=20=D0=94=D0=BE=D1=80=D0=B0?= =?UTF-8?q?=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20=D0=94=D0=BE=D0=B1=D0=B0?= =?UTF-8?q?=D0=B2=D0=BB=D0=B5=D0=BD=D0=B8=D0=B5=20=D0=BD=D0=BE=D0=B2=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=95=D0=9F?= =?UTF-8?q?=D0=A0=D0=9B=D0=A1=20=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=B8=D0=B5.=20=D0=9F=D1=80=D0=BE=D0=B2=D0=B5?= =?UTF-8?q?=D1=80=D0=BA=D0=B0=20=D1=84=D0=BB=D0=B0=D0=B3=D0=BE=D0=B2=20?= =?UTF-8?q?=D0=B4=D0=BE=D1=81=D1=82=D0=BE=D0=B2=D0=B5=D1=80=D0=BD=D0=BE?= =?UTF-8?q?=D1=81=D1=82=D0=B8=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D1=83=D0=B5=D0=BC=D0=BE=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5?= =?UTF-8?q?=D1=85=D0=B8=20=D0=B4=D0=BB=D1=8F=20=D1=86=D0=B5=D0=BB=D0=B8.?= =?UTF-8?q?=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0.=20?= =?UTF-8?q?=D0=9F=D0=B5=D1=80=D0=B5=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D0=B2=D1=8B=D0=B1=D1=80=D0=B0=D0=BD=D0=BD=D0=BE?= =?UTF-8?q?=D0=B9=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85=D0=B8=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B2=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD=D0=B8=D0=B8?= =?UTF-8?q?=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D0=B4=D0=BE=D0=B2?= =?UTF-8?q?=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=BE=D1=82=20=D1=86=D0=B5?= =?UTF-8?q?=D0=BB=D0=B8.=20=D0=94=D0=BE=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D0=BA=D0=B0.=20=D0=92=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=BD?= =?UTF-8?q?=D0=B8=D0=B5=20=D1=80=D0=B5=D0=BA=D0=BE=D0=BC=D0=B5=D0=BD=D0=B4?= =?UTF-8?q?=D0=BE=D0=B2=D0=B0=D0=BD=D0=BD=D0=BE=D0=B9=20=D0=B4=D0=BB=D1=8F?= =?UTF-8?q?=20=D1=86=D0=B5=D0=BB=D0=B8=20=D0=BF=D0=BE=D0=BC=D0=B5=D1=85?= =?UTF-8?q?=D0=B8.=20Merge=20remote-tracking=20branch=20'sasha/master'=20G?= =?UTF-8?q?odot4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scenes/настройки/настройки.tscn | 10 ++ scripts/signaller.gd | 2 +- scripts/trassa.gd | 160 +++++++++++++++++++++++++++++++- 3 files changed, 166 insertions(+), 6 deletions(-) diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index c21899b..87b1403 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -31,6 +31,7 @@ const SETTING_TABLE = [ ['Кнопка «JTIDS»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Кнопка «КУПД»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Внешнее управление', TableEdit, TableToggle, 'Передать управление в 5П28'], + ['Внешнее указание Трасса', TableEdit, TableToggle, 'Разрешить постановку помех от Трасса'], ['Кнопка «Подавление»', TableEdit, TableToggle, 'Разрешить отображение кнопки'], ['Виртуальная клавиатура', TableEdit, TableToggle, 'Включить отображение экранной клавиатуры'], ['Скрыть вкладку ЭМС 2', TableEdit, TableToggle, 'Отображать вкладку \\\"ЭМС-2\\\"'], @@ -68,6 +69,7 @@ const SUPPRESS = 17 ## Строка - Подавление const KEYBOARD = 18 ## Строка - Виртуальная клавиатура const HIDE_EMS2 = 19 ## Строка - Скрыть вкладку ЭМС 2 const COMMIT = 20 ## Строка - Версия УАРЭП +const TRASSA = 21 var name_to_line_index: = {} ## Для преобразования названия параметра в номер строки @@ -91,6 +93,11 @@ func on_external_cu_btn_pressed(btn) -> void: signaller.emit_signal('interfer_off_all') +func on_trassa_btn_pressed(btn) -> void: + var state = btn.button_pressed + ProjectSettings.set_setting('application/config/Внешнее указание Трасса', state) + + func on_vk_pressed(btn) -> void: var state = btn.button_pressed signaller.emit_signal('kb_pressed', state) @@ -207,6 +214,9 @@ func button_settings(): var extern_cu_node = $scroll_set/table.get_node2(1, EXTERNAL_CU).get_children()[0] extern_cu_node.connect('pressed', on_external_cu_btn_pressed.bind(extern_cu_node)) on_external_cu_btn_pressed(extern_cu_node) + var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children()[0] + trassa_node.connect('pressed', on_trassa_btn_pressed.bind(trassa_node)) + on_trassa_btn_pressed(trassa_node) var vk_node = $scroll_set/table.get_node2(1, KEYBOARD).get_children()[0] vk_node.connect('pressed', on_vk_pressed.bind(vk_node)) var ems2_hide_node = $scroll_set/table.get_node2(1, HIDE_EMS2).get_children()[0] diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 82d8cf1..561ed7d 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -110,7 +110,7 @@ signal interfer_new(ecm: interfer.Interfer) ## [param ecm] - Новая помеха.[br] ## [param ecms] - словарь помех.[br] ## [param thrs] - словарь id помех и связанных с ними целей.[br] -signal interfer_off(ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary) +signal interfer_off(ecm: interfer.Interfer) ## Вызывается при нажатии отключить. diff --git a/scripts/trassa.gd b/scripts/trassa.gd index b203716..3cb5b52 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -1,6 +1,9 @@ class_name trassa_unit extends Node -const ONLINE_TIMEOUT: = 5000 +const ONLINE_TIMEOUT: int = 5000 # Время ожидания данных +const REQUEST_PERIOD: int = 3000 # Период отправки, мс +const WORDS_TOTAL: int = 75 +const NOINFO: int = 0x80000000 class Trassa extends unit.Unit: var source_addr: = [] @@ -11,11 +14,158 @@ class Trassa extends unit.Unit: emit_signal('line_changed', self) return Error.ERR_BUSY - func _init(unit_name: StringName): - self.name = unit_name + var unit_caps = network.get_unit_instance('уарэп-капсрпб') + var source_addr: Array + var tx_stack: Array[int] = [] + var msg_counter: int = 0 + var ecms: Dictionary = {} # Словарь всех активных помех + var srn = 0 + var jtids = 0 + var prinud_but: Array = [] + var forced_buttons: Array = [] # Храним ссылки на кнопки + + # Инициализация + func _init(nm: StringName, buttons: Array = []) -> void: + self.name = nm + self.forced_buttons = buttons + tx_stack.resize(WORDS_TOTAL) + tx_stack.fill(NOINFO) + interfer.connect("interfer_resized", Callable(self, "on_interfer_resized")) - func parse(data: PackedByteArray, tick: int): + + # Обработка полученного пакета + func parse(rx_data: PackedByteArray, tick: int): rx_tick = tick if not online: online = true - emit_signal('line_changed', self) + emit_signal("line_changed", self) + var words: Array[int] = [] + var offset: int = 0 + while offset < rx_data.size(): + if offset + 4 <= rx_data.size(): + var word = rx_data.decode_u32(offset) + words.append(word) + offset += 4 + else: + break + if words.size() < 10: + emit_signal('parse_failed', self) + tx_stack.fill(NOINFO) + tx_stack[0] = words[0] # ID + tx_stack[1] = msg_counter # Nc + tx_stack[2] = 0x01 # Nб + tx_stack[3] = 0x00 # Ск + tx_stack[4] = 0x0194 # НТС + tx_stack[5] = (0x0001 << 16) | 0x0080 # Ии + tx_stack[6] = 0x01 # РКС + srn = words[7] # SRN + jtids = words[8] # JTIDS + btn_trassa_pressed() + interfer_data() + tx_stack[74] = _calc_crc(tx_stack) + emit_signal("data_received", self) + + + func interfer_data() -> void: + for i in range(67, 74): + tx_stack[i] = 0 + for ecm in ecms.values(): + if ecm.svk == 1: + var nmfs_value = ecm.nmfs + var fs_key = get_fs_key(nmfs_value) + if fs_key != NOINFO: + var string_index = fs_key / 4 + var bit_position = fs_key % 4 + if string_index >= 0 and string_index < 7: + var target_string = 67 + string_index + tx_stack[target_string] |= (1 << bit_position) + + + func get_fs_key(nmfs_value: int) -> int: + if prd.fs_caps_id.has(nmfs_value): + return prd.fs_caps_id[nmfs_value] + return NOINFO + + + # Отправка пакета от uarep-ctl + func process(now_tick: int) -> int: + if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT): + online = false + emit_signal("line_changed", self) + if (now_tick - tx_tick) > REQUEST_PERIOD: + tx_tick = now_tick + msg_counter += 1 + interfer_uarep() + interfer_data() + var data = PackedByteArray() + data.resize(WORDS_TOTAL * 4) + for i in range(WORDS_TOTAL): + data.encode_u32(i * 4, tx_stack[i]) + tx_data = data + tx_len = WORDS_TOTAL * 4 + return Error.OK + return Error.ERR_BUSY + + + # CRC вычисление + func _calc_crc(data: Array) -> int: + var acc: int = 0 + for i in range(data.size() - 1): # кроме CRC + if i in [0, 1]: + continue + acc = (acc + (data[i] & 0xFFFFFFFF)) & 0xFFFFFFFF + return acc + + + # Обновление всех активных помех + func on_interfer_resized(ecms_dic: Dictionary) -> void: ecms = ecms_dic + + + func interfer_uarep() -> void: + tx_stack[65] = 0 + tx_stack[66] = 0 + for ecm in ecms.values(): + if ecm.krp == "srni1" and ecm.svk == 1: + tx_stack[65] = 1 + if ecm.krp == "svi1" and ecm.svk == 1: + tx_stack[66] = 1 + tx_stack[1] = msg_counter + + + # Обработка указаний от Трассы по кнопке + func btn_trassa_pressed() -> void: + var state = ProjectSettings.get_setting('application/config/Внешнее указание Трасса', false) + if state == true: + var tree: SceneTree = Engine.get_main_loop() + if tree is SceneTree: + var nodes: Array = tree.get_nodes_in_group('группа-принудительно') + for btn in nodes: + if btn.name == 'btn_srn': + btn.pressed = (srn == 1) + elif btn.name == 'btn_jtids': + btn.pressed = (jtids == 1) + if srn == 1: + tx_stack[65] = 1 + signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.srn_sectors) + else: + tx_stack[65] = 0 + for ecm in ecms.values(): + if ecm.krp == "srni1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm) + if jtids == 1: + tx_stack[66] = 1 + signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.jtids_sectors) + else: + tx_stack[66] = 0 + for ecm in ecms.values(): + if ecm.krp == "svi1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm) + for ecm in ecms.values(): + if ecm.krp == "svi1" and ecm.svk == 1: + ecm.krp = interfer.INTERFER_OFF + interfer.send_ecm(ecm, unit_caps) + signaller.emit_signal('interfer_off', ecm)