Доработка. Включение/Выключение помех. Табличка с параметрами помехи. Лог журнала событий по включению/отключению помех.

This commit is contained in:
MaD_CaT
2023-11-29 15:24:35 +03:00
parent c1a5c4cbbc
commit 5dcaef9ea6
16 changed files with 341 additions and 48 deletions

View File

@@ -26,6 +26,7 @@ config/map_image_width=512
config/map_minimum_zoom=5
config/map_maximum_zoom=19
config/map_server_addr="https://b.tile.openstreetmap.org"
interfer/resend_timeout=1000.0
[autoload]

View File

@@ -1,5 +1,6 @@
extends Control
var selected: bool
# Called when the node enters the scene tree for the first time.
func _ready():
@@ -8,8 +9,16 @@ func _ready():
# Функция делает присваивает заданое значение видимости селектору
func set_sel_visible(value: bool):
selected = value
$selector.visible = value
func _on_bip_pressed():
signaller.emit_signal('rto_threat_sel', self)
func _on_bip_gui_input(event):
if event is InputEventMouseButton and event.pressed:
match event.button_index:
MOUSE_BUTTON_LEFT:
signaller.emit_signal('rto_threat_sel', name.to_int())
MOUSE_BUTTON_RIGHT:
if selected:
signaller.emit_signal('rto_threat_unsel', name.to_int())

View File

@@ -141,6 +141,7 @@ layout_mode = 0
offset_right = 1.0
offset_bottom = 1.0
scale = Vector2(20, 20)
button_mask = 3
texture_normal = SubResource("PlaceholderTexture2D_w5pye")
stretch_mode = 3
@@ -165,4 +166,4 @@ position = Vector2(10, 10)
scale = Vector2(26, 26)
texture = SubResource("PlaceholderTexture2D_svd33")
[connection signal="pressed" from="bip" to="." method="_on_bip_pressed"]
[connection signal="gui_input" from="bip" to="." method="_on_bip_gui_input"]

View File

@@ -1,7 +1,8 @@
[gd_scene load_steps=3 format=3 uid="uid://b1o10yvgjpb0j"]
[gd_scene load_steps=4 format=3 uid="uid://b1o10yvgjpb0j"]
[ext_resource type="Texture2D" uid="uid://cs6i1xwx0pmdk" path="res://data/рамка-панели.png" id="1_q1ow7"]
[ext_resource type="Script" path="res://table/table.gd" id="2_82yax"]
[ext_resource type="Script" path="res://scenes/scroll-ecm-params.gd" id="2_sm6tk"]
[node name="frm_ecm_params" type="NinePatchRect"]
size_flags_horizontal = 3
@@ -27,9 +28,10 @@ vertical_alignment = 1
[node name="scroll" type="ScrollContainer" parent="."]
layout_mode = 0
offset_left = 4.0
offset_top = 51.0
offset_top = 25.0
offset_right = 476.0
offset_bottom = 282.0
offset_bottom = 256.0
script = ExtResource("2_sm6tk")
[node name="table" type="GridContainer" parent="scroll"]
layout_mode = 2

View File

@@ -12,7 +12,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "Откл."
pressed = true
disabled = true
metadata/rfi_name = "off"
[node name="btn_auto_rfi" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -20,6 +20,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "Автомат"
disabled = true
metadata/rfi_name = "auto"
[node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -27,6 +28,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "МЧМ-1"
disabled = true
metadata/rfi_name = "mchm1"
[node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -34,6 +36,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "СРН-И1"
disabled = true
metadata/rfi_name = "srni1"
[node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -41,6 +44,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "СРН-М2"
disabled = true
metadata/rfi_name = "srnm2"
[node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -48,6 +52,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ПД-М4"
disabled = true
metadata/rfi_name = "pdm4"
[node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -55,6 +60,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ПД-М2"
disabled = true
metadata/rfi_name = "pdm2"
[node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -62,6 +68,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ЛЧМ-1"
disabled = true
metadata/rfi_name = "lchm1"
[node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -69,6 +76,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ПД-М4С"
disabled = true
metadata/rfi_name = "pdm4s"
[node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -76,6 +84,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ПД-ЧМ"
disabled = true
metadata/rfi_name = "pdchm"
[node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -83,6 +92,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "СВ-И1"
disabled = true
metadata/rfi_name = "svi1"
[node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -90,6 +100,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "K1"
disabled = true
metadata/rfi_name = "k1"
[node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -97,6 +108,7 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "СВ-М2"
disabled = true
metadata/rfi_name = "svm2"
[node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_uiv1n")]
@@ -104,4 +116,5 @@ layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 3
text = "ОЗП-1"
disabled = true
metadata/rfi_name = "ozp1"

View File

@@ -18,8 +18,13 @@ extends PanelContainer
get: return $button.get_text()
@export var disabled: bool = false:
set(val): $button.set_disabled(val)
get: return $button.disabled
@export var pressed: bool = false:
set(val): $button.set_pressed(val)
set(val): $button.set_pressed(val)
get: return $button.is_pressed()
@@ -32,6 +37,7 @@ extends PanelContainer
func set_text(val: String): $button.set_text(val)
func set_pressed(val: bool): $button.set_pressed(val)
func set_disabled(val: bool): $button.set_disabled(val)
func button_connect(button_signal: String, proc: Callable): $button.connect(button_signal, proc)
func get_text(): return $button.get_text()
func is_pressed(): return $button.is_pressed()

View File

@@ -8,7 +8,7 @@ const TableHeader = preload('res://table/header.tscn') ## Ячейка за
const TABLE_HEADER = [ TableHeader, TableHeader, TableHeader, TableHeader , TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit , CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['Номер', 'Название', 'Частота, МГц', 'Пеленг', 'Состояние' ] ## Заголовки таблицы.
const TABLE_COLUMN_SIZE = [ 65, 80, 120, 80, 90 ] ## Ширины колонок.
const TABLE_COLUMN_SIZE = [ 65, 80, 120, 70, 100 ] ## Ширины колонок.
## Состояние выполнения сеанса помехи
const INTERFER_STATE = {
@@ -44,10 +44,41 @@ const COLUMN_FREQ = 2
const COLUMN_AOA = 3
const COLUMN_STATE = 4
## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int):
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
var ecm = $table.get_node_user_data(0, i_row)
if interfer.thrs.has(ecm.ispp):
signaller.emit_signal('rto_threat_sel', interfer.thrs[ecm.ispp])
else:
signaller.emit_signal('interfer_selected', ecm)
## Вызывается при выборе цели
func on_rto_threat_sel(th_id: int, table_index):
var ecm_ispp = interfer.thrs.find_key(th_id)
var ecm = null
if ecm_ispp != null:
var i_row = table_index[int(ecm_ispp)]
ecm = $table.get_node_user_data(0, i_row)
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
else:
$table.clear_rows_selected()
signaller.emit_signal('interfer_selected', ecm)
# Called when the node enters the scene tree for the first time.
func _ready():
var table_index: = Dictionary()
signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(table_index))
signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(table_index))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(table_index))
interfer.connect('interfer_update', Callable(self, 'on_interfer_update').bind(table_index))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table')
@@ -58,6 +89,13 @@ func init_table():
$table.pin_header(self, get_parent())
func on_interfer_update(ecm, table_index):
var row = map_th_to_row(ecm)
if table_index.has(ecm.ispp):
var i_row = table_index[ecm.ispp]
$table.set_row_text(i_row, row)
func on_interfer_new(ecm, table_index):
var row = map_th_to_row(ecm)
if table_index.has(ecm.ispp):
@@ -70,6 +108,25 @@ func on_interfer_new(ecm, table_index):
$table.set_row_editable(i_row, false)
$table.set_node_user_data(0, i_row, ecm)
table_index[ecm.ispp] = i_row
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
signaller.emit_signal('interfer_selected', ecm)
func on_interfer_off(ecm, ecms, thrs, table_index):
$table.remove_row(table_index[ecm.ispp])
table_index.clear()
rehash(table_index)
ecms.erase(ecm.ispp)
thrs.erase(ecm.ispp)
## Перестраивает индекс таблицы. Вызывать при удалении строки
func rehash(table_index: Dictionary):
var rows_count = $table.get_rows_count()
for i_row in rows_count:
var item = $table.get_node2(0, i_row)
table_index[int(item.text)] = i_row
## Преобразует цель в строку таблицы
@@ -79,7 +136,7 @@ func map_th_to_row(ecm) -> Array:
row[COLUMN_NUMBER] = '%s' % ecm.ispp
row[COLUMN_NAME] = ''
if INTERFER_NAMES.has(ecm.krp):
row[COLUMN_NAME] = '%s' % ecm.krp
row[COLUMN_NAME] = '%s' % INTERFER_NAMES[ecm.krp]
row[COLUMN_FREQ] = '%s' % ecm.params['freq']
row[COLUMN_AOA] = '%s' % ecm.kni
row[COLUMN_STATE] = ''
@@ -87,3 +144,5 @@ func map_th_to_row(ecm) -> Array:
row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk]
return row
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -0,0 +1,97 @@
extends ScrollContainer
## Отображает список параметров помехи в таблице.
const CellLineEdit = preload('res://scenes/ячейка-2.tscn') ## Ячейка таблицы.
const TableHeader = preload('res://table/header.tscn') ## Ячейка заголовок таблицы.
const TABLE_HEADER = [ TableHeader, TableHeader ] ## Описание ряда заголовка.
const TABLE_ROW = [ CellLineEdit, CellLineEdit ] ## Описание ряда.
const TABLE_HEADERS_TEXT = ['Параметр', 'Значение' ] ## Назания колонок.
const TABLE_COLUMN_SIZE = [ 370, 85 ] ## Ширины колонок.
const TABLE_PARAMS = {
'kni': [0, 'Курсовой улог, гр.', false, 0.0, 360.0],
'powp': [1, 'Мощность, %', true, 0.0, 100.0],
'freq': [2, 'Частота, МГц', true, 400.0, 6000.0],
'width': [3, 'Занимая полоса частот, МГц', true, 0.0, 120.0],
'dur': [4, 'Длительность импульса, мкс', true, 0.0, 1000000.0],
'period': [5, 'Период повтора, мкс', true, 0.0, 1000000.0] }
func init_table():
for i in TABLE_PARAMS.size(): $table.add_row(TABLE_ROW)
for key in TABLE_PARAMS.keys():
var p = TABLE_PARAMS[key]
$table.set_node_text(0, p[0], p[1])
$table.set_node_alligment(0, p[0], HORIZONTAL_ALIGNMENT_LEFT)
$table.set_node_editable(0, p[0], false)
$table.set_node_editable(1, p[0], false)
$table.set_node_user_data(1, p[0], key)
$table.connect_columns(self, 'text_submitted', 'on_edit_entry', [1], [])
$table.set_columns_min_size(TABLE_COLUMN_SIZE)
$table.set_meta('id', 0)
# Called when the node enters the scene tree for the first time.
func _ready():
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected'))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
call_deferred('init_table')
func on_edit_entry(text : String, entry):
var ecm = $table.get_meta('ecm')
if $table.has_meta('ecm') == false: return
var indexis = $table.get_key_indexes(entry[0].name)
var row_i = indexis[1]
var param = $table.get_node_user_data(1, row_i)
var p = TABLE_PARAMS[param]
var old_val = ecm.get_value(param)
var val = check_value(text, p[3], p[4], old_val)
ecm.set_value(val, param)
signaller.emit_signal('interfer_new', ecm)
func check_value(val, min_val, max_val, old_val):
if val.is_valid_float():
if float(val) < min_val: return min_val
if float(val) > max_val: return max_val
return float(val)
else: return old_val
func on_interfer_selected(ecm):
if ecm != null:
$table.set_meta('ecm', ecm)
else:
$table.set_meta('ecm', null)
on_ecm_update()
func on_ecm_update():
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')
$table.set_node_editable(1, item, false)
if $table.has_meta('ecm') == false: return
var ecm: interfer.Interfer = $table.get_meta('ecm')
var mnms = tools.get_members_names(ecm)
for item in ecm['params'].keys():
mnms.append(item)
for member_name in mnms:
if not TABLE_PARAMS.has(member_name): continue
var p = TABLE_PARAMS[member_name]
var val = ecm.get_value(member_name)
$table.set_node_text(1, p[0], '%s' % val)
$table.set_node_editable(1, p[0], p[2])
# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
pass
func on_rto_threat_unsel(_th_id):
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')
$table.set_node_editable(1, item, false)

View File

@@ -42,6 +42,7 @@ func init_table():
func _ready() -> void:
signaller.connect('threat_selected', Callable(self, 'on_threat_selected'))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
threats.connect('threat_update', Callable(self, 'on_threat_update'))
call_deferred('init_table')
@@ -49,6 +50,7 @@ func _ready() -> void:
## Обрабатывает сигнал [signal threats.threat_update].
## Обновляет отображение только для выбранной цели.
func on_threat_update(th):
if th.selected == false: return
if th.id != $table.get_meta('id'): return
var mnms = tools.get_members_names(th)
for member_name in mnms:
@@ -56,3 +58,8 @@ func on_threat_update(th):
var p = TABLE_PARAMS[member_name]
var val = th.get(member_name)
$table.set_node_text(1, p[0], '%s' % val)
func on_rto_threat_unsel(_th_id):
for item in range(len(TABLE_PARAMS)):
$table.set_node_text(1, item, '')

View File

@@ -16,13 +16,17 @@ const TABLE_COLUMN_SIZE = [ 65, 145, 145, 90 ]
## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int):
row_pressed(i_row)
signaller.emit_signal('rto_threat_sel', $table.get_node_user_data(0, i_row).id)
func row_pressed(i_row: int):
$table.clear_rows_selected()
$table.set_row_selected(i_row, true)
var threat = $table.get_node_user_data(0, i_row)
signaller.emit_signal('threat_selected', threat)
func init_table():
$table.set_header(TABLE_HEADER)
$table.set_header_text(TABLE_HEADERS_TEXT)
@@ -36,6 +40,7 @@ func _ready() -> void:
threats.connect('threat_lost', Callable(self, 'on_threat_lost').bind(table_index))
threats.connect('threat_update', Callable(self, 'on_threat_update').bind(table_index))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind($table))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel'))
$table.connect('row_pressed', Callable(self, 'on_row_pressed'))
call_deferred('init_table')
@@ -85,10 +90,14 @@ func map_th_to_row(th) -> Array:
## Выделяет выбранную цель в таблице
func on_rto_threat_sel(bip, tbl):
func on_rto_threat_sel(th_id, tbl):
for i in tbl.get_rows_count():
var node = tbl.get_node2(0, i)
if node.text.to_int() == bip.name.to_int():
on_row_pressed(i)
if node.text.to_int() == th_id:
row_pressed(i)
break
## Снимает выделение цели
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -5,6 +5,11 @@ func on_line_changed(unit, addr): log.message(Logger.INFO, 'Состояние
func on_command_fail(unit, addr): log.message(Logger.ERROR, 'Ошибка: команда не выполнена: %s %s' % [unit, addr])
func on_threats_changed(th: Object, msg: String): log.message(Logger.INFO, '%s: %s' % [msg, th.to_string()])
func on_parse_error(unit, msg: String): log.message(Logger.ERROR, '%s: %s' % [unit.to_string(), msg])
func on_interfer_off(ecm, _ecms, _thrs,msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()])
func on_interfer_new(ecm, msg: String):
if ecm.krp != interfer.INTERFER_OFF:
log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()])
func _enter_tree():
@@ -20,7 +25,8 @@ func _ready() -> void:
log.info('Операционная система: %s' % [OS.get_distribution_name()])
threats.connect('threat_new', Callable(self, 'on_threats_changed').bind('Цель обнаружена'))
threats.connect('threat_lost', Callable(self, 'on_threats_changed').bind('Цель потеряна'))
signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind('Создан сеанс помехи'))
signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind('Сеанс помехи отключен'))
func _on_clear_button_down() -> void:
$content.clear()

View File

@@ -75,7 +75,6 @@ func _ready():
$btn_zoom.set_meta('zoom', min_zoom - 1)
$btn_strob.button_connect('pressed', Callable(self, 'on_button_strobe_pressed'))
$btn_view.button_connect('toggled', Callable(self, 'on_button_view_toggled'))
$grd_btns/btn_off.set_pressed(true)
drag_fsm = DragFSM.OFF
var nodes: Array = get_tree().get_nodes_in_group('группа-режим-помехи')
nodes.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_pressed').bind(btn, nodes)))
@@ -84,9 +83,10 @@ func _ready():
threats.connect('threats_resized', Callable(self, 'on_threats_resized'))
threats.connect('threat_update', Callable(self, 'on_threat_update'))
signaller.connect('zoom_complete', Callable(self, '_on_zoom_complete'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel'))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected'))
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes))
signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(nodes))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(nodes))
signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected').bind(nodes))
func on_enter_tree() -> void:
call_deferred('_on_btn_scale_pressed')
@@ -128,20 +128,31 @@ func on_threat_lost(th) -> void:
## Обработчик выбора РТО цели
func on_rto_threat_sel(bip):
func on_rto_threat_sel(th_id, ecm_btns):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips:
item.set_sel_visible(false)
bip.set_sel_visible(true)
func on_threat_selected(th):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips:
if th.id == item.name.to_int():
if th_id == item.name.to_int():
item.set_sel_visible(true)
else:
item.set_sel_visible(false)
for btn in ecm_btns:
btn.set_disabled(false)
## Обработчик снятия выбора РТО цели
func on_rto_threat_unsel(th_id, ecm_btns):
var bips: Array = get_children().filter(func(item): return item.name.is_valid_int())
for item in bips:
if th_id == item.name.to_int():
item.set_sel_visible(false)
break
for btn in ecm_btns:
btn.set_pressed(false)
btn.set_disabled(true)
func on_threat_selected(th, ecm_btns):
on_rto_threat_sel(th.id, ecm_btns)
## Обработчик нажатия кнопки "Строб". Управляет отображением строба
@@ -156,6 +167,22 @@ func on_button_pressed(btn_this, btn_others) -> void:
signaller.emit_signal('interfer_init', btn_this)
## Управляет состоянием кнопок в радиогруппе при выборе помехи
func on_interfer_selected(ecm, btns) -> void:
var ecm_name: String
if ecm != null:
ecm_name = ecm.krp
else:
ecm_name = interfer.INTERFER_OFF
for btn in btns:
btn.set_disabled(false)
btn.get_meta('rfi_name')
if ecm_name == btn.get_meta('rfi_name'):
btn.set_pressed(true)
else:
btn.set_pressed(false)
## Возвращает ширину строба по направлению
func get_strob_width(pos: Vector2, prev: float) -> float:
var strob_dir_width: float = prev + (drag_pos_begin.y - pos.y) * drag_scale_width

View File

@@ -354,6 +354,3 @@ func on_row_pressed(i_row: int, tbl):
var is_row_selected = tbl.is_row_selected(i_row)
tbl.set_row_selected(i_row, not is_row_selected)
func _process(_delta):
pass

View File

@@ -5,6 +5,8 @@ extends Node
## Режимы помехи
const ITERFER_MODE = {
'off': ['Откл', ['freq', 'width']],
'auto': ['АВТО', ['freq', 'width']],
'srni1': ['СРН-И1', ['freq', 'width']],
'srnm2': ['СРН-М2', ['freq', 'width']],
'lchm1': ['ЛЧМ-1', ['freq', 'width']],
@@ -20,6 +22,7 @@ const ITERFER_MODE = {
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 воздействия
@@ -36,8 +39,11 @@ class Interfer:
var params: = {} ## Параметры помехи.
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
var tick_rx: int ## Тик время обновления цели, мс.
var tick_tx: int ## Тик время обновления цели, мс.
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
func get_msg6_data():
var data_to_json : Dictionary = {}
data_to_json['ts'] = 6
@@ -57,7 +63,20 @@ class Interfer:
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) ## Вызывается при ошибке.
@@ -71,9 +90,24 @@ func _ready():
id_array.append(i+1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_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))
signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms))
signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(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
## Производит приём состояния помех. [param unit] -> [param ecms]
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
@@ -91,15 +125,12 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, ecms: Dictionary):
if ecms.has(ispp):
var ecm = ecms[ispp]
ecm.set_from_dic(dic_msvk)
ecm.tick_rx = unit.tick
call_deferred('emit_signal', 'interfer_update', ecm)
else:
var ecm = Interfer.new()
ecm.set_from_dic(dic_msvk)
ecm.krp = INTERFER_OFF
var json_data = ecm.get_msg6_data()
unit.tx_stack.append(json_data)
ecm.tick_rx = unit.tick
send_ecm(ecm, unit)
if sz != ecms.size():
call_deferred('emit_signal', 'interfer_resized', ecms)
@@ -120,6 +151,8 @@ func on_interfer_create(btn, sel_threats, unit, ecms):
if key != null:
ispp = key
else:
if interfer_name == 'off':
return
ispp = pop_id()
if ispp == 0: return
msg_ss += 1
@@ -128,18 +161,25 @@ func on_interfer_create(btn, sel_threats, unit, ecms):
ecm = ecms[ispp]
else:
ecm = Interfer.new()
ecm.svk = 5 # Подготовка к передаче сообщения
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 # Необходимо добавить управление мощностью
thrs[ispp] = item.id
var json_data = ecm.get_msg6_data()
unit.tx_stack.append(json_data)
signaller.emit_signal('interfer_new', ecm)
if interfer_name == 'off':
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
push_id(ecm.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 pop_id():
@@ -152,3 +192,4 @@ func pop_id():
func push_id(id : int):
id_array.append(id)
id_array.sort()

View File

@@ -23,8 +23,13 @@ signal full_screen(id: int)
## Вызывается, когда пользователь выбирает цель
## [param bip] - Отметка цели на экране
signal rto_threat_sel (bip: Control)
## [param th_id] - Отметка цели на экране
signal rto_threat_sel (th_id: int)
## Вызывается, когда пользователь снимает выделение с цели
## [param th_id] - Отметка цели на экране
signal rto_threat_unsel (th_id: int)
## Вызывается, когда пользователь выбирает помеху
@@ -42,6 +47,17 @@ signal interfer_create (btn: PanelContainer, sel_threats: Array)
signal interfer_new (ecm: interfer.Interfer)
## Вызывается, когда отключается действующая помеха
## [param ecm] - Новая помеха, [param ecms] - словарь помех
## [param ecms] - словарь id помех и связанных с ними целей
signal interfer_off (ecm: interfer.Interfer, ecms: Dictionary, thrs: Dictionary)
## Вызывается, когда отключается действующая помеха
## [param ecm] - Выбранная помеха
signal interfer_selected (ecm: interfer.Interfer)
## Вызывается при запросе изменения уровня детализации карты
## [param zoom] - Вновь установленный уровень детализации
signal zoom_changed(zoom: int)

View File

@@ -29,7 +29,7 @@ class Threat:
var selected: bool ## Флаг, что цель выбрана
func _init(): clear_fflags()
func _to_string() -> String: return '<Threat>: номер:%d пеленг:%0.1f частота:%0.1f МГц' % [id, aoa, freq]
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):
@@ -54,6 +54,7 @@ func _ready() -> void:
timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(repsettings.ThreatParams.time_lost, threats))
timer_check_lost.start(repsettings.ThreatParams.time_lost / 1000.0)
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('threat_selected', Callable(self, 'on_threat_selected').bind(threats))
signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats))
@@ -69,11 +70,12 @@ func on_timer_check_lost(time_lost: int, threats: Dictionary):
call_deferred('emit_signal', 'threats_resized', threats)
## Снимает выделение с цели, если нажать по отметке цели.
func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false
## Выбирает цель, если нажать по отметке цели.
func on_rto_threat_sel(bip, threats):
for threat in threats.values():
threat.selected = false
threats[bip.name.to_int()].selected = true
func on_rto_threat_sel(th_id, threats): on_threat_selected(threats[th_id], threats)
## Выбирает цель, если выбрать в таблице