Merge remote-tracking branch 'origin/MAD_CAT' into prd-control

# Conflicts:
#	scenes/tabs-switch/tab-switch.tscn
#	scenes/эмс2/эмс_тг.gd
#	scripts/signaller.gd
This commit is contained in:
TotMaxim
2025-11-11 16:37:37 +03:00
13 changed files with 154 additions and 94 deletions

2
generate-sertificate.sh Normal file
View File

@@ -0,0 +1,2 @@
#openssl req -x509 -newkey rsa:4096 -keyout key.pem -nodes -out cert.pem -sha256 -days 365 -subj "/C=RU/ST=NTC/L=TNIIS/O=Company Name/OU=Org/CN=www.example.com"
openssl req -new -x509 -keyout "html/server.pem" -out "html/server.pem" -days 365 -nodes

17
https-server.py Normal file
View File

@@ -0,0 +1,17 @@
#!/usr/bin/env python3
from http import server # Python 3
import ssl
import os
class MyHTTPRequestHandler(server.SimpleHTTPRequestHandler):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if __name__ == '__main__':
html_dir = os.path.join(os.path.dirname(__file__), 'html')
os.chdir(html_dir)
srv = server.HTTPServer(('', 8000), MyHTTPRequestHandler)
sdc = ssl.create_default_context()
srv.serve_forever()

View File

@@ -28,7 +28,7 @@ interfer/center_offset=Vector2(200, 225)
interfer/default_color0=Color(0.38, 0.47, 0.51, 1)
interfer/default_color1=Color(0.39, 0.44, 0.5, 1)
interfer/select_color=Color(1, 1, 1, 1)
interfer/interfer_color=Color(0.58, 0.47, 0.51, 1)
interfer/interfer_color=Color(0.92379, 0.0965192, 0.249261, 1)
interfer/resend_timeout=1000.0
config/external_cu=false
config/unit_rr_request_period=20.0
@@ -36,7 +36,7 @@ config/kems_files_path="user://kems/"
config/emsg_files_path="user://emsg/"
config/settings_path="user://settings.json"
config/unit_bpo_request_period=20.0
interfer/emit_color=Color(0.58, 0.471, 0.51, 0.2)
interfer/emit_color=Color(0.92549, 0.0980392, 0.25098, 0.509804)
interfer/closed_sectors=Color(0, 0, 0, 1)
[autoload]

View File

@@ -6,6 +6,10 @@ var selected: bool
func set_track_visible(value: bool): $track.visible = value
## Задаёт цвет точки
func set_bip_color(val: Color): $bip.set_instance_shader_parameter('color', val)
## Присваивает заданное значение видимости индикатору выполнения.
func set_ecm_visible(value: bool): $ecm_done.visible = value

View File

@@ -7,8 +7,8 @@ const TableHeader = preload('res://table/header.tscn') ## Ячейка за
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['Номер', 'Название', 'Пеленг', 'Состояние' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 75, 100, 90, 170 ] ## Ширины колонок.
const TABLE_HEADERS_TEXT = ['', 'Название', 'Пеленг', 'Состояние' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 100, 90, 170 ] ## Ширины колонок.
## Состояние выполнения сеанса помехи
const INTERFER_STATE = {

View File

@@ -0,0 +1,23 @@
[gd_scene load_steps=2 format=3 uid="uid://d012h4hxf2anf"]
[ext_resource type="Texture2D" uid="uid://b3woliae871je" path="res://data/отметка-неопред.png" id="1_0a4l0"]
[node name="emit-led" type="Control"]
layout_mode = 3
anchors_preset = 0
offset_right = 40.0
offset_bottom = 40.0
[node name="texture-led" type="TextureButton" parent="."]
visible = false
layout_mode = 1
anchors_preset = 15
anchor_right = 1.0
anchor_bottom = 1.0
offset_left = 26.0
offset_top = 11.0
offset_right = 3.0
offset_bottom = -12.0
grow_horizontal = 2
grow_vertical = 2
texture_normal = ExtResource("1_0a4l0")

View File

@@ -35,5 +35,5 @@ script = ExtResource("2_empn3")
[node name="table" type="GridContainer" parent="scroll"]
layout_mode = 2
columns = 4
columns = 5
script = ExtResource("3_4bupu")

View File

@@ -5,14 +5,16 @@ class_name scroll_threats extends ScrollContainer
const CellLineEdit = preload('res://table/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const EmitLed = preload('res://scenes/frame-threats/emit-led.tscn') ## Ячейка заголовок таблицы.
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit, EmitLed ] ## Описание ряда.
const TABLE_COLUMN_PARAM = ['id', 'aoa', 'freq', 'proto', 'emit' ] ## Параметры цели отображаемые в таблице.
const TABLE_HEADERS_TEXT = ['', 'Пеленг', 'Частота, МГц', 'Протокол', 'Помеха' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 70, 110, 140, 65] ## Ширины колонок.
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit ] ## Описание ряда.
const TABLE_COLUMN_PARAM = ['id', 'aoa', 'freq', 'proto' ] ## Параметры цели отображаемые в таблице.
const TABLE_HEADERS_TEXT = ['Номер', 'Пеленг', 'Частота, МГц', 'Протокол' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 145, 145, 90 ] ## Ширины колонок.
const TABLE_TEXT_ROWS = 4
const EMIT_STATE_COL = 4
## Снимает выделение цели.
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()
@@ -63,6 +65,17 @@ func on_threat_update(th, table_index: Dictionary):
var row = map_th_to_row(th)
var i_row = table_index[th.id]
$table.set_row_text(i_row, row)
var emit_node = $table.get_node2(EMIT_STATE_COL, i_row)
var emit_txr = emit_node.get_node('texture-led')
if th.emit_state == 0:
emit_txr.visible = false
elif th.emit_state == 1:
emit_txr.visible = true
emit_txr.self_modulate = Color.ORANGE
elif th.emit_state == 2:
emit_txr.visible = true
emit_txr.self_modulate = Color.RED
## Обрабатывает сигнал [b]threat_lost[/b].
@@ -78,7 +91,7 @@ func on_threat_new(th, table_index):
$table.add_row(TABLE_ROW)
var row = map_th_to_row(th)
$table.set_row_text(i_row, row)
$table.set_row_editable(i_row, false)
disable_edit($table, TABLE_TEXT_ROWS, i_row)
$table.set_node_user_data(0, i_row, th)
table_index[th.id] = i_row
@@ -86,10 +99,11 @@ func on_threat_new(th, table_index):
## Преобразует цель в строку таблицы.
func map_th_to_row(th) -> Array:
var row: = Array()
row.resize(TABLE_COLUMN_PARAM.size())
row.resize(TABLE_TEXT_ROWS)
var i_col: int = 0
for param_name in TABLE_COLUMN_PARAM:
var val = th.get(param_name)
if val == null: continue
row[i_col] = '%0.1f' % val if val is float else '%s' % val
if not th.fflags[param_name]:
row[i_col] = ''
@@ -104,3 +118,13 @@ func on_rto_threat_sel(th_id, tbl):
if node.text.to_int() == th_id:
row_pressed(i)
break
## Отключает возможность редактирования LineEdit в таблице.[br]
## [param tbl] - таблица,[br]
## [param num_col] - номер колонки,[br]
## [param i_row] - номер столбца.[br]
func disable_edit(tbl, num_col: int, i_row: int):
for col in num_col:
var node: LineEdit = tbl.get_node2(col, i_row)
node.editable = false

View File

@@ -98,7 +98,7 @@ func on_settings_changed():
color_closed = ProjectSettings.get_setting('application/interfer/closed_sectors', Color(0.0, 0.0, 0.0, 1.0))
color_emit_sel = color_select
color_closed_emit = color_closed
color_select *= Color(1.0, 1.0, 1.0, 0.0)
color_ecm *= Color(1.0, 1.0, 1.0, 0.0)
color_emit_sel *= Color(1.0, 1.0, 1.0, 0.2)
@@ -167,6 +167,7 @@ func _ready():
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(nodes))
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected').bind(nodes))
signaller.connect('interfer_new', Callable(self, 'on_interfer_new'))
signaller.connect('on_prog_ecm_off', Callable(self, 'on_interfer_new'))
signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all'))
signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno').bind(nodes))
signaller.connect('fs_selected', Callable(self, 'on_fs_selected'))
@@ -253,9 +254,10 @@ func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool:
## Обработчик сигнала обновления цели.
func on_threat_update(th):
func on_threat_update(th: threats.Threat):
var bip = get_node('%d' % th.id)
bip.update(th.tick_rx)
bip.set_bip_color(Color.CORAL if th.proto else Color.WHITE)
bip.visible = map_threat_to_bip(th, bip)
@@ -520,6 +522,14 @@ func update_fs_colors():
else:
fs_colors[key] = color_select
$canvas.set_band_colors(fs_colors)
if fs_emit.size():
if $btn_activate.pressed:
$btn_activate.self_modulate = Color.RED
else:
$btn_activate.self_modulate = Color.WHITE
else:
$btn_activate.self_modulate = Color.WHITE
func unsel_fs_all(need_btns_off: bool):
@@ -580,6 +590,8 @@ func on_btn_center_toggled(toggled_on: bool) -> void:
func on_btn_activate_toggled(toggled_on: bool) -> void:
$btn_activate.tooltip_text = 'Включает подавление (%s)' % ('включено' if toggled_on else 'отключено')
signaller.emit_signal('emit_changed', toggled_on)
if not toggled_on:
$btn_activate.self_modulate = Color.WHITE
func on_update_coordinates_label(coordinates_label) -> void:

View File

@@ -379,12 +379,12 @@ texture_normal = ExtResource("14_ggrwd")
[connection signal="drag_continue" from="." to="." method="_on_drag_continue"]
[connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"]
[connection signal="toggled" from="chk_auto" to="." method="on_value_changed"]
[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"]
[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"]
[connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"]
[connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"]
[connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"]
[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"]
[connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"]
[connection signal="pressed" from="btn_all_work" to="." method="_on_btn_all_work_pressed"]

View File

@@ -257,22 +257,34 @@ func on_timer_check_state(unit_instance, ecms, resend_timeout) -> void:
func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> void:
gos_nmfs.clear()
for thr in threats.values():
if not gos_flag: # Составляется список запретных секторов работы
if (thr.proto in gos_protocols) and thr.fflags.proto:
var fs_arr: Array = []
prd.find_fs_index(thr.aoa, thr.freq, fs_arr)
if fs_arr.size():
for item in fs_arr:
var nmfs = prd.FS_PRD[item][1]
gos_nmfs.append(nmfs)
var fs_arr: Array = []
var th_aoa = fposmod(thr.aoa - course, 360)
prd.find_fs_index(th_aoa, thr.freq, fs_arr)
if fs_arr.size():
for item in fs_arr:
var nmfs = prd.FS_PRD[item][1]
thr.nmfs = nmfs
if (thr.proto in gos_protocols) and thr.fflags.proto and (not gos_flag):
gos_nmfs.append(nmfs)
thr.emit_state = 0
for ecm in ecms.values():
if thr.nmfs == ecm.nmfs:
set_th_emit(thr, ecm)
var ecm_active = true
if not gos_flag:
if ecm.nmfs in gos_nmfs:
interfer_off(ecm, unit_instance)
ecm_active = false
if ecm_active and (prd.fs_caps_id[ecm.nmfs] in fs_closed):
interfer_off(ecm, unit_instance)
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 - course
if ecm.kni < 0:
ecm.kni += 360
ecm.kni = fposmod(thr.aoa - course, 360)
call_ecm_proc(ecm)
if ecm.nmfs in gos_nmfs:
interfer_off(ecm, unit_instance)
@@ -283,23 +295,11 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> v
signaller.emit_signal('fs_update_color', ecms)
prd.update_fs_state(ecms, trenazh_mode)
for ecm in ecms.values():
var ecm_active = true
if not gos_flag:
if ecm.nmfs in gos_nmfs:
interfer_off(ecm, unit_instance)
ecm_active = false
if ecm_active and (prd.fs_caps_id[ecm.nmfs] in fs_closed):
interfer_off(ecm, unit_instance)
if not auto_enabled:
return
if auto_enabled:
for thr in threats.values():
var fs_arr: Array = []
prd.find_fs_index(thr.aoa, thr.freq, fs_arr)
var th_aoa = fposmod(thr.aoa - course, 360)
prd.find_fs_index(th_aoa, thr.freq, fs_arr)
if fs_arr.size():
var need_continue = false
for item in fs_arr:
@@ -576,58 +576,8 @@ func on_threats_update(threat, ecms, unit_caps):
if ecm.kni < 0:
ecm.kni += 360
set_nmfs(ecm)
if threat.tmod != 'fm':
if ecm != null:
send_ecm(ecm, unit_caps)
return
var th_fm_dict: Dictionary
var fs_index_arr: Array
prd.find_fs_index(threat.aoa, threat.freq, fs_index_arr)
if fs_index_arr.size() == 0:
if ecm != null:
send_ecm(ecm, unit_caps)
return
var fs_index = fs_index_arr[0]
var nmfs = prd.FS_PRD[fs_index][1]
if ecm == null:
for ecm_i in ecms.values():
if nmfs != ecm_i.nmfs: continue
if ecm_i.svk != 1: continue
ecm = ecm_i
if ecm == null: return
for th_index in thrs_dict:
if thrs_dict[th_index].tmod != 'fm': continue
fs_index_arr = []
prd.find_fs_index(thrs_dict[th_index].aoa, thrs_dict[th_index].freq, fs_index_arr)
if fs_index_arr.size() == 0: continue
if fs_index_arr[0] != fs_index: continue
th_fm_dict[th_index] = thrs_dict[th_index]
if len(th_fm_dict) > 1:
pass
send_ecm(ecm, unit_caps)
func get_freq_range(freq_range_dict: Dictionary, th_dict: Dictionary):
for key_i in th_dict:
var min_range: int = 6000
var key_min = null
for key_j in th_dict:
if key_i == key_j: continue
var width = (th_dict[key_i].width / 2) + (th_dict[key_j].width / 2)
var freq_range = abs(th_dict[key_i].freq - th_dict[key_j].freq) + width
if freq_range < min_range:
key_min = key_j
min_range = freq_range
var max_width = 0
for key in PDCHM_PARAMS['files'].keys():
if max_width < key: max_width = key
if min_range > max_width:
th_dict.erase(key_i)
continue
else:
if key_min == null: continue
freq_range_dict[key_i] = [th_dict[key_i], th_dict[key_min], min_range]
if ecm != null:
send_ecm(ecm, unit_caps)
func find_threat(freq: int, aoa: float):
@@ -677,6 +627,7 @@ func get_krp(threat: threats.Threat):
func on_interfer_off(ecm: Interfer, ecms):
var sz = ecms.size()
signaller.emit_signal('on_prog_ecm_off', ecm)
ecms.erase(ecm.ispp)
thrs.erase(ecm.ispp)
interfer.cu.erase(ecm.ispp)
@@ -712,3 +663,16 @@ func call_ecm_proc(ecm):
func on_update_fs_closed(fs_dict):
fs_closed = fs_dict
func set_th_emit(th: threats.Threat, ecm: Interfer):
var freq_min = ecm.params['freq'] - ecm.params.get('width', settings.WIDTH_MAX)/2
var freq_max = ecm.params['freq'] + ecm.params.get('width', settings.WIDTH_MAX)/2
if (th.freq >= freq_min) and (th.freq <= freq_max):
if ecm.svk == 1:
th.emit_state = 2
elif th.emit_state == 2:
return
else:
th.emit_state = 1

View File

@@ -28,6 +28,8 @@ class Threat:
var width: float ## Ширина занимаемого диапазона частот, МГц.
var selected: bool ## Флаг, что цель выбрана.
var auto_selected: bool = false ## Флаг автомата для целей
var emit_state: int = 0 ## 0 - подавление не назначено, 1 - назначено, 2 - выполняется
var nmfs:int ## Индекс модуля ФС, в зону действия которого попала цель
func _init(): clear_fflags()
func _to_string() -> String: return 'номер: %d пеленг: %0.1f частота: %0.1f МГц' % [id, aoa, freq]

12
uarep-ctl.linux.x86_64 Normal file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
DATE_TIME=$(date "+%F %H-%M-%S")
LOG_PATH="/home/${USER}/$(basename "$0")-${DATE_TIME}.log" # Путь к файлу журнала.
# { Вывод этого скрипта в файл журнала и консоль одновременно
# shellcheck disable=SC2015,SC2086
test $1 = x$'\x00' && shift || { set -o pipefail ; ( exec 2>&1 ; $0 $'\x00' "$@" ) | tee "${LOG_PATH}" ; exit $? ; }
# }
/opt/uarep-ctl/bin/uarep-ctl.linux.x86_64 -f -t --screen 1