Files
imi_skysens/threats.gd

567 lines
22 KiB
GDScript
Raw Permalink 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
var id_array: Array # Массив id целей
var treats : Dictionary # Словарь целей
var msg_counter : int = 0 # Счётчик отправленных пакетов
var g_table: GridContainer
var send_flag = true
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
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]
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]
const TABLE_ROW_TYPES = [ TableCellType1, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType6, TableCellType6, TableCellType5, TableCellType6, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType5, TableCellType6]
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]
const TABLE_COLUMN_SIZES = [ 82, 82, 82, 82, 82, 90, 150, 150, 80, 150, 82, 82, 82, 82, 82, 82, 100]
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 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 ]
# Индексы колонок, в которых можно вводит текст
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 ]
# Типы модуляции
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', ]
var rkrp = []
# Номера колонок
var COLUMN_OPT = [[COLUMN_TMOD, MODE_TYPES], [COLUMN_FREQM, FREQM], [COLUMN_PROTO, M_PROTO], [COLUMN_REC, rkrp]]
const COLUMN_OPT_BTN = [COLUMN_TMOD, COLUMN_FREQM, COLUMN_PROTO, COLUMN_REC]
const ID_ARRAY_LEN = 150 # Размер пула номеров целей
# Цель
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
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))
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_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_treats(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())
treats['%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]
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 treats:
var treat = treats[key]
var data = treat.get_data()
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 = treats[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)
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())
treats['%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])
treats.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'] = []
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 treats:
var treat = treats[key]
var flag = int(key) % 2
if int(send_flag) ^ flag:
continue
set_ticks(treat)
var data = treat.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 treats.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)
treats.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())
treats['%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)