Files
imi_sky/threats.gd

607 lines
24 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

extends Node
const TableCellType1 = preload('res://ячейка-1.tscn')
const TableCellType2 = preload('res://кнопка-3.tscn')
const TableCellType3 = preload('res://кнопка-4.tscn')
const TableCellType4 = preload('res://заголовок.tscn')
const TableCellType5 = preload('res://ячейка-2.tscn')
const TableCellType6 = preload('res://кнопка-5.tscn')
const TableHeader = preload('res://table/header.tscn')
# Индекс колонки: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
const TABLE_HEADERS = ['ID', 'Курc, гр.', 'Частота', 'Ш. диап.', 'Ампл.', 'T обновл.', 'Мод.', 'Реж. см. F', 'Ск. пер.', 'Протокол', 'Ст. дол.', 'Ст. шир.', 'Cт. выс.', 'Тек. дол.', 'Тек. шир.', 'Тек. выс.', 'Рек. помеха', 'Мерцание']
const TABLE_HEADER_TYPES = [ TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader, TableHeader]
const TABLE_HEADER_ALIGNMENTS = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER]
const TABLE_ROW_TYPES = [ TableCellType1, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType6, TableCellType6, TableCellType5, TableCellType6, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType6, TableCellType5]
const TABLE_ROW_ALIGNMENTS = [ HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_LEFT, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER]
const TABLE_COLUMN_SIZES = [ 40, 70, 82, 82, 82, 90, 110, 150, 80, 130, 82, 82, 82, 82, 82, 82, 140, 82]
const COLUMN_ID = 0 # Идентификатор цели
const COLUMN_AOA = 1 # Курсовой угол на источник сигнала, градусы
const COLUMN_FREQ = 2 # Частота несущей или центральная частота, МГц
const COLUMN_WIDTH = 3 # Ширина занимаемого диапазона частот, МГц
const COLUMN_POW = 4 # Уровень принимаемого сигнала, дБ
const COLUMN_TICK = 5 # Относительное время обнаружения сигнала, мс.
const COLUMN_TMOD = 6 # Вид модуляции
const COLUMN_FREQM = 7 # Режим смены частоты.
const COLUMN_BAUD = 8 # Скорость передачи данных, бит/с
const COLUMN_PROTO = 9 # Тип протокола источника сигнала.
const COLUMN_SLON = 10 # Координаты старта, долгота в градусах
const COLUMN_SLAT = 11 # Координаты старта, широта в градусах
const COLUMN_SALT = 12 # Координаты старта, высота от уровня моря, метры
const COLUMN_LAT = 13 # Текущие координаты, долгота в градусах
const COLUMN_LON = 14 # Текущие координаты, широта в градусах
const COLUMN_ALT = 15 # Текущая высота, метры
const COLUMN_REC = 16 # Текущая высота, метры
const COLUMN_FLIC = 17 # Время мерцания
# Индексы колонок, которым можно задавать выравнивание текста
const TABLE_ALLIGNED_COLUMNS = [
COLUMN_ID,
COLUMN_AOA,
COLUMN_FREQ,
COLUMN_WIDTH,
COLUMN_POW,
COLUMN_TICK,
COLUMN_BAUD,
COLUMN_SLON,
COLUMN_SLAT,
COLUMN_SALT,
COLUMN_LAT,
COLUMN_LON,
COLUMN_ALT,
COLUMN_FLIC ]
# Индексы колонок, в которых можно вводит текст
const TABLE_ENTRY_COLUMNS = [
COLUMN_AOA,
COLUMN_FREQ,
COLUMN_WIDTH,
COLUMN_POW,
COLUMN_TICK,
COLUMN_BAUD,
COLUMN_SLON,
COLUMN_SLAT,
COLUMN_SALT,
COLUMN_LAT,
COLUMN_LON,
COLUMN_ALT,
COLUMN_FLIC ]
# Типы модуляции
const MODE_TYPES = ['<неопр.>', 'am', 'ook', 'ask', 'fm', 'qpsk', 'oqpsk', 'pi4qpsk', 'qam16',
'qam32', 'qam64', 'qam128', 'qam256', 'qam512', 'fsk', 'cpfsk', 'psk','ofdm']
# Режим смены частоты
const FREQM = ['<неопр.>', 'fhss', 'lfm', 'const']
# Протоколы радиомодема
const M_PROTO = ['<неопр.>', '3dlink', 'skyhopperpro', 'picardiooem', 'solo7', 'j11',
'mavlink', 'ltm', 'hc12', 'df1', ]
const COLUMN_OPT_BTN = [COLUMN_TMOD, COLUMN_FREQM, COLUMN_PROTO, COLUMN_REC]
const ID_ARRAY_LEN = 150 # Размер пула номеров целей
const MIN_FLIC_TIME = 1.0 # минимальное время мерцания цели
var id_array: Array # Массив id целей
var threats : Dictionary # Словарь целей
var msg_counter : int = 0 # Счётчик отправленных пакетов
var g_table: GridContainer
var send_flag = true
var rkrp = []
var now = 0.0 # Время с момента запуска приложения
var bpo_mode: int = 1 # Режим работы блока БПО
# Номера колонок
var COLUMN_OPT = [[COLUMN_TMOD, MODE_TYPES], [COLUMN_FREQM, FREQM], [COLUMN_PROTO, M_PROTO], [COLUMN_REC, rkrp]]
# Цель
class Threat:
# параметры цели, второе значение, разрешение отправки.
var row: Dictionary = {
'id': [0, true],
'aoa': [10.0, true],
'freq': [2480.0, true],
'width': [20.0, true],
'power': [20.0, true],
'tick': [10, true],
'tmod': ['<неопр.>', false],
'freqm': ['<неопр.>', false],
'baud': [0.0, false],
'rparams': [{}, false],
'rkrp': ['<неопр.>', false],
'proto': ['<неопр.>', false],
'slon': [0.0, false],
'slat': [0.0, false],
'salt': [0.0, false],
'lat': [0.0, false],
'lon': [0.0, false],
'alt': [0.0, false],
}
var row_id: int
var flic: Array = [0.0, false]
var flic_ena: bool = true
var flic_tick: = 0.0 ## Время изменения состояния flic
func _init(th_id : int, row_i: int):
row.id[0] = th_id
row_id = row_i
func get_data():
var data_to_send : Dictionary
for key in row.keys():
var value = row[key]
var data = value[0]
var need_send = value[1]
if need_send:
data_to_send[key] = data
return data_to_send
func update_rows():
var new_rows: Array = []
new_rows.append(_check_value(row.id))
new_rows.append(_check_value(row.aoa))
new_rows.append(_check_value(row.freq))
new_rows.append(_check_value(row.width))
new_rows.append(_check_value(row.power))
new_rows.append(_check_value(row.tick))
new_rows.append(_check_value(row.tmod))
new_rows.append(_check_value(row.freqm))
new_rows.append(_check_value(row.baud))
new_rows.append(_check_value(row.proto))
new_rows.append(_check_value(row.slon))
new_rows.append(_check_value(row.slat))
new_rows.append(_check_value(row.salt))
new_rows.append(_check_value(row.lat))
new_rows.append(_check_value(row.lon))
new_rows.append(_check_value(row.alt))
new_rows.append(_check_value(row.rkrp))
new_rows.append(_check_value(flic))
return new_rows
func _check_value(val):
if val[1]:
return '%s' % val[0]
else:
return ''
func set_aoa(val):
var value = float(val)
value = Tools.check_low_high(value, 0, 360)
value = Tools.check_len(val, value)
row.aoa[0] = value
row.aoa[1] = Tools.check_empty(value)
return value
func set_freq(val):
var value = float(val)
value = Tools.check_negative(value)
value = Tools.check_len(val, value)
row.freq[0] = value
row.freq[1] = Tools.check_empty(value)
if row.rparams[0].has('freq'):
row.rparams[0]['freq'] = row.freq[0]
return value
func set_width(val):
var value = float(val)
value = Tools.check_negative(value)
value = Tools.check_len(val, value)
row.width[0] = value
row.width[1] = Tools.check_empty(value)
return value
func set_flic(val):
var value = float(val)
value = Tools.check_negative(value)
value = Tools.check_len(val, value)
flic[0] = value
flic[1] = Tools.check_empty(value)
return value
func set_power(val):
var value = float(val)
value = Tools.check_negative(value)
value = Tools.check_len(val, value)
row.power[0] = value
row.power[1] = Tools.check_empty(value)
return value
func set_tick(val):
var value = int(val)
value = Tools.check_low_high(value, 0, 60000)
value = Tools.check_len(val, value)
row.tick[0] = value
row.tick[1] = Tools.check_empty(value)
return value
func set_baud(val):
var value = float(val)
value = Tools.check_negative(value)
value = Tools.check_len(val, value)
row.baud[0] = value
row.baud[1] = Tools.check_empty(value)
return value
func set_slon(val):
var value = float(val)
value = Tools.check_low_high(value, -90, 90)
value = Tools.check_len(val, value)
row.slon[0] = value
row.slon[1] = Tools.check_empty(value)
return value
func set_slat(val):
var value = float(val)
value = Tools.check_low_high(value, -180, 180)
value = Tools.check_len(val, value)
row.slat[0] = value
row.slat[1] = Tools.check_empty(value)
return value
func set_salt(val):
var value = float(val)
value = Tools.check_len(val, value)
row.salt[0] = value
row.salt[1] = Tools.check_empty(value)
return value
func set_lon(val):
var value = float(val)
value = Tools.check_low_high(value, -90, 90)
value = Tools.check_len(val, value)
row.lon[0] = value
row.lon[1] = Tools.check_empty(value)
return value
func set_lat(val):
var value = float(val)
value = Tools.check_low_high(value, -180, 180)
value = Tools.check_len(val, value)
row.lat[0] = value
row.lat[1] = Tools.check_empty(value)
return value
func set_alt_pressed(val):
var value = float(val)
value = Tools.check_len(val, value)
row.alt[0] = value
row.alt[1] = Tools.check_empty(value)
return value
func set_tmod(val):
var value = str(val)
row.tmod[0] = value
row.tmod[1] = false if value == '<неопр.>' else true
return value
func set_freqm(val):
var value = str(val)
row.freqm[0] = value
row.freqm[1] = false if value == '<неопр.>' else true
return value
func set_proto(val):
var value = str(val)
row.proto[0] = value
row.proto[1] = false if value == '<неопр.>' else true
return value
func set_rname(val):
var value = str(val)
row.rkrp[0] = value
row.rkrp[1] = false if value == '<неопр.>' else true
row.rparams[1] = row.rkrp[1]
row.rparams[0] = {}
if row.freq[1]:
row.rparams[0]['freq'] = row.freq[0]
if row.width[1]:
row.rparams[0]['width'] = row.width[0]
if row.rkrp[0] == Interfers.LCHM:
row.rparams[0]['period'] = 1.0
elif row.rkrp[0] == Interfers.IQ_FL_NAME:
row.rparams[0]['filename'] = Interfers.INTERFER_NAMES[Interfers.IQ_FL_NAME][0]
return value
func init_threats(table, nodes): # Инициализация вкладки с целями
set_rkrp()
for i in range(ID_ARRAY_LEN): # Заполняет массив ID целей
id_array.append(i+1)
table.set_header(TABLE_HEADER_TYPES)
table.set_header_text(TABLE_HEADERS)
load_treats(table)
init_table(table, TABLE_COLUMN_SIZES)
g_table = table
table.set_columns_min_size(TABLE_COLUMN_SIZES)
table.connect('row_pressed', Callable(self, 'on_row_pressed').bind(table))
table.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [])
table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [])
table.pin_header(nodes.scroll_thr, nodes.panel)
nodes.btn_add.connect('button_up', Callable(self, 'on_btn_add').bind(table))
nodes.btn_del.connect('button_up', Callable(self, 'on_btn_del').bind(table))
nodes.btn_save.connect('button_up', Callable(self, 'on_btn_save'))
nodes.thr_gen.connect('button_up', Callable(self, 'on_thr_gen').bind(table))
nodes.btn_load.connect('pressed', Callable(self, 'on_btn_load').bind(table))
nodes.btn_rt.connect('pressed', Callable(self, 'on_rotate_th').bind(nodes.entry_rt, table))
var timer = Timer.new()
timer.connect('timeout', Callable(self, 'on_timeout').bind(nodes.entry_rt, table, nodes.chkbx_rt))
add_child(timer) #to process
timer.start(1) #to start
func load_treats(table):
var file = FileAccess.open('user://save.json', FileAccess.READ)
if file == null:
return
var read = file.get_as_text()
file.close()
var json_conv: = JSON.new()
if Error.OK == json_conv.parse(read):
var json_data = json_conv.get_data()
for item in json_data:
if item.has('id'):
var id = int(item['id'])
id_array.erase(int(id))
var threat : = Threat.new(id, table.get_rows_count())
threats['%d' % id] = threat
for key in item:
if key == 'id': threat.row[key] = [int(item[key]), true]
elif key == 'tick': threat.row[key] = [int(item[key]), true]
elif key == 'flic': threat.flic = [float(item[key]), true]
else: threat.row[key] = [item[key], true]
var row = threat.update_rows()
table.add_row(TABLE_ROW_TYPES)
table.set_row_text(table.get_rows_count()-1, row)
table.set_node_user_data(0, table.get_rows_count()-1, threat)
init_opt_btns(table.get_rows_count()-1, table, threat)
table.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [])
table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [])
func on_btn_save():
var file = FileAccess.open('user://save.json', FileAccess.WRITE)
var data_to_json : Array
for key in threats:
var treat = threats[key]
var data = treat.get_data()
data['flic'] = threats[key].flic[0]
data_to_json.append(data)
var json = JSON.new().stringify(data_to_json)
file.store_string(json)
file.close()
func init_table(table: Table, sizes: Array):
for i_row in table.get_rows_count():
pass
func init_opt_btns(row : int, table, threat):
for item in COLUMN_OPT:
var i: int = 0
var i_col = item[0]
var opt_arr = item[1]
var cell = table.get_node2(i_col, row)
for opt in opt_arr:
cell.add_item(opt)
if i_col == COLUMN_TMOD:
var mode = threat.row['tmod'][0]
i = MODE_TYPES.find(mode)
if i_col == COLUMN_FREQM:
var freqm = threat.row['freqm'][0]
i = FREQM.find(freqm)
if i_col == COLUMN_PROTO:
var proto = threat.row['proto'][0]
i = M_PROTO.find(proto)
cell.select(i)
func on_item_selected(item_num, node):
var optbtn_text = node[0].text
var indexis = g_table.get_key_indexes(node[0].name)
var row_i = indexis[1]
var col_i = indexis[0]
var cell = g_table.get_node2(0,row_i)
var value = set_value(optbtn_text, cell.text, col_i)
func on_edit_entry(text : String, entry):
var indexis = g_table.get_key_indexes(entry[0].name)
var row_i = indexis[1]
var col_i = indexis[0]
var cell = g_table.get_node2(0,row_i)
var value = set_value(text, cell.text, col_i)
entry[0].text = str(value)
func set_value(val : String, treat_id : String, column : int):
var treat = threats[treat_id]
match column:
COLUMN_AOA:
return treat.set_aoa(val)
COLUMN_FREQ:
return treat.set_freq(val)
COLUMN_WIDTH:
return treat.set_width(val)
COLUMN_POW:
return treat.set_power(val)
COLUMN_TICK:
return treat.set_tick(val)
COLUMN_TMOD:
return treat.set_tmod(val)
COLUMN_FREQM:
return treat.set_freqm(val)
COLUMN_BAUD:
return treat.set_baud(val)
COLUMN_PROTO:
return treat.set_proto(val)
COLUMN_SLON:
return treat.set_slon(val)
COLUMN_SLAT:
return treat.set_slat(val)
COLUMN_SALT:
return treat.set_salt(val)
COLUMN_LAT:
return treat.set_lon(val)
COLUMN_LON:
return treat.set_lat(val)
COLUMN_ALT:
return treat.set_alt_pressed(val)
COLUMN_REC:
return treat.set_rname(val)
COLUMN_FLIC:
return treat.set_flic(val)
func on_row_pressed(i_row: int, table):
table.clear_rows_selected()
table.set_row_selected(i_row, true)
func on_btn_add(table):
var id = pop_id()
var threat : = Threat.new(id, table.get_rows_count())
threats['%d' % id] = threat
var row = threat.update_rows()
table.add_row(TABLE_ROW_TYPES)
table.set_row_text(table.get_rows_count()-1, row)
table.set_node_user_data(0, table.get_rows_count()-1, threat)
init_opt_btns(table.get_rows_count()-1, table, threat)
table.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [])
table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [])
func on_btn_del(table):
var row_i = []
table.get_selected_rows(row_i)
if len(row_i) > 0:
var cell = table.get_node2(0, row_i[0])
threats.erase(cell.text)
table.remove_row(row_i[0])
for i in table.get_rows_count():
var treat = table.get_node_user_data(0, i)
treat.row_id = i
func pop_id():
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)
func get_threats_data():
var data_to_json : Dictionary
data_to_json['ts'] = 5
msg_counter += 1
data_to_json['ss'] = msg_counter
data_to_json['msvk'] = []
data_to_json['sa'] = bpo_mode
for item in Interfers.interfers.values():
var msvk = {}
msvk['ispp'] = item.options['ispp']
msvk['svk'] = item.svk
data_to_json['msvk'].append(msvk)
data_to_json['mis'] = []
for key in threats:
var threat = threats[key]
var flag = int(key) % 2
if (int(send_flag) ^ flag) or (not threat.flic_ena):
continue
set_ticks(threat)
var data = threat.get_data()
data_to_json['mis'].append(data)
var json = JSON.new().stringify(data_to_json)
var pac = json.to_utf8_buffer()
send_flag = not send_flag
return pac
func set_ticks(treat):
var tick = Time.get_ticks_msec()
var cell = g_table.get_node2(COLUMN_TICK, treat.row_id)
cell.text = str(treat.set_tick(str(tick%60000)))
func on_rotate_th(entry, table):
if entry.text.is_valid_float():
for th in threats.values():
var aoa = th.row.aoa[0]
aoa += float(entry.text)
if aoa > 360.0:
aoa -= 360.0
elif aoa < 0:
aoa += 360.0
th.set_aoa(str(aoa))
var node_aoa = table.get_node2(1, th.row_id)
if th.row.aoa[1]:
node_aoa.text = str(th.row.aoa[0])
else:
print_debug('Угол поворота целей задан не верно')
func on_timeout(entry, table, chkbx_rt):
if chkbx_rt.button_pressed:
on_rotate_th(entry, table)
func on_btn_load(table):
for i in table.get_rows_count():
var cell = table.get_node2(0, 0)
threats.erase(cell.text)
table.remove_row(0)
load_treats(table)
func on_thr_gen(table):
for i in range(100):
var id = pop_id()
if id == 0: return
var threat : = Threat.new(id, table.get_rows_count())
threats['%d' % id] = threat
threat.row.aoa[0] = 0 + 30 * i
while (threat.row.aoa[0] > 360):
threat.row.aoa[0] -= 360
threat.row.freq[0] = 400 + 350 * i
while (threat.row.freq[0] > 6000):
threat.row.freq[0] -= 5600
var row = threat.update_rows()
table.add_row(TABLE_ROW_TYPES)
table.set_row_text(table.get_rows_count()-1, row)
table.set_node_user_data(0, table.get_rows_count()-1, threat)
init_opt_btns(table.get_rows_count()-1, table, threat)
table.connect_columns(self, 'text_submitted', 'on_edit_entry', TABLE_ENTRY_COLUMNS, [])
table.connect_columns(self, 'item_selected', 'on_item_selected', COLUMN_OPT_BTN, [])
func set_rkrp():
rkrp.append('<неопр.>')
for key in Interfers.INTERFER_NAMES.keys():
rkrp.append(key)
func _process(delta):
now += delta
for th in threats.values():
if th.flic[0] > MIN_FLIC_TIME:
if (now - th.flic_tick) >= th.flic[0]:
th.flic_ena = not th.flic_ena
th.flic_tick = now
else:
th.flic_ena = true
func on_receive_msg9(json_data):
if not json_data.has('sa'): return
bpo_mode = int(json_data['sa'])