Files
uarep-ctl/scripts/tcp5p28.gd

194 lines
9.0 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.

class_name tcp5_p28 extends Node
## Реализация "Протокол информационного сопряжения.
## СПО АСУ изделия «МП550» с СПО 5П-28".
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от 5П-28, мс.
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
## Тип модуляции для запаковки в пакет для 5П-28.
const MOD_TYPES: Array = ['',
'am',
'ook',
'ask',
'fm',
'qpsk',
'oqpsk',
'pi4qpsk',
'qam16',
'qam32',
'qam64',
'qam128',
'qam256',
'qam512',
'cpfsk',
'psk',
'ofdm',]
const CU_STATE: Dictionary = {
0:2, # Подготовка к выполнению
1:1, # Выполняется
2:9, # Ошибка в команде
3:7, # Занят выполнением другого ЦУ
4:9, # Неисправность
}
class TCP5P28:
const PACK_TYPE_CMD: int = 1
const PACK_TYPE_RES: int = 2
const CMD_TYPE_STATE: int = 1
const CMD_TYPE_TH: int = 2
const CMD_TYPE_IN: int = 3
signal line_changed(unit: TCP5P28) ## Сигнал состояние связи изменилось.
signal data_received(unit: TCP5P28) ## Сигнал данные приняты.
signal command_fail(unit: TCP5P28) ## Сигнал при не выполнении команды.
signal parse_error(unit: TCP5P28, msg: String) ## Сигнал ошибки разбора сообщения.
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей.
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания.
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var rx_tick: = 0 ## Тик время последнего приёма, мс.
var tx_data: = PackedByteArray() ## Пакет для отправки.
var tx_stack: Array ## Массив пакетов для отправки.
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm): self.name = nm
func parse(data: PackedByteArray, now_tick: int):
rx_tick = now_tick
if not online:
online = true
emit_signal('line_changed', self)
var pack_type = data.decode_u8(2)
if pack_type == PACK_TYPE_CMD:
var cmd_type = data.decode_u8(8)
if cmd_type == CMD_TYPE_TH:
emit_signal('get_threats')
if cmd_type == CMD_TYPE_STATE:
emit_signal('get_interfers')
var external_cu = ProjectSettings.get_setting('application/config/external_cu', false)
if cmd_type == CMD_TYPE_IN and external_cu:
set_interfer(data)
func process(now_tick: int):
if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if len(tx_stack):
tx_data = tx_stack[0]
tx_stack.remove_at(0)
return Error.OK
else:
return Error.ERR_UNAVAILABLE
func pack_threats(ths):
var data = PackedByteArray()
var data_len = 4 + len(ths) * 80 # длинна блока данных в байтах
var tick = Time.get_ticks_msec()
data.resize(4)
data.encode_u16(0, 0) # Код ошибки
data.encode_u16(2, len(ths)) # Количество целей
for th in ths.values():
data.append_array(get_threats_data(th, int(tick)))
var data_to_send: PackedByteArray = create_header(data_len)
data_to_send.append_array(data)
tx_stack.append(data_to_send)
func pack_interfers(interfers, ecms):
var data = PackedByteArray()
var data_len = 12 # длинна блока данных в байтах
data.resize(data_len)
data.encode_u16(0, 0) # Код ошибки
data.encode_u16(2, len(interfers)) # Количество целей
data.encode_u32(4, 0) # Состояние УА-РЕП
data.encode_u32(8, 0) # Состояние линий связи
for id in interfers.values():
var cu_data: PackedByteArray = []
cu_data.resize(4)
var cu = ecms[id]
cu_data.encode_u16(0, cu.ispp)
var state: int
if CU_STATE.has(cu.svk):
state = CU_STATE[cu.svk]
else:
state = 9
cu_data.encode_u8(2, state) # Состояние выполнения команды
cu_data.encode_u8(3, 0xFF) # Эффективность работы помехи
data.append_array(cu_data)
var data_to_send: PackedByteArray = create_header(data_len + 4 * len(interfers))
data_to_send.append_array(data)
tx_stack.append(data_to_send)
func create_header(data_len):
var head_data = PackedByteArray()
head_data.resize(8) # Размер заголовка
head_data.encode_u16(0, 0) # Код ошибки
head_data.encode_u8(2, 2) # Тип пакета, ответ на запрос
head_data.encode_u8(3, 5) # Версия протокола, всегда 5
head_data.encode_u32(4, data_len) # Длинна пакета данных
return head_data
func get_threats_data(th, tick):
var th_data = PackedByteArray()
th_data.resize(80) # Количество байт в массиве
th_data.encode_u64(0, tick)
var flags: int = 0 # с 0 по 7 бит рекомендованная помеха
flags |= 0 << 8 # Флаг рекомендуемой помехи
flags |= int(th.fflags['aoa']) << 9 # Флаг доставерности пеленга
flags |= int(th.fflags['alt']) << 10 # Флаг доставерности высоты
flags |= int(th.fflags['power']) << 11 # Флаг доставерности мощности
flags |= int(th.fflags['baud']) << 12 # Флаг доставерности ск. мод.
flags |= int(th.fflags['slon']) << 13 # Флаг доставерности долготы ст. позиции
flags |= int(th.fflags['slat']) << 14 # Флаг доставерности широты ст. позиции
flags |= int(th.fflags['lon']) << 15 # Флаг доставерности долготы
flags |= int(th.fflags['lat']) << 16 # Флаг доставерности широты
flags |= int(0) << 30 # Флаг признак назначения помехи на цель
flags |= int(0) << 31 # Флаг признак назначения опасной цель
th_data.encode_u32(8, flags) # Флаги
th_data.encode_u16(12, th.id) # Идентификатор объекта
th_data.encode_u16(14, int(round(th.aoa/0.1))) # Пеленг объекта
th_data.encode_u16(16, int(th.alt)) # Высота объекта
th_data.encode_u16(18, int(th.freq)) # Частота объекта
th_data.encode_u16(20, int(th.width)) # Ширина частотной полосы объекта
th_data.encode_u8(22, int(th.power)) # Мощность излучения объекта
var mod = MOD_TYPES.find(th.tmod)
if mod == -1: mod = 0
th_data.encode_u8(23, int(mod)) # Тип модуляции
th_data.encode_u32(24, int(th.baud)) # Скорость модуляции, бод
to_cp866(th.proto, th_data)
var c1 = pow(2, 30) / 180.0
th_data.encode_s32(64, int(th.slon * c1))
th_data.encode_s32(68, int(th.slat * c1))
th_data.encode_s32(72, int(th.lon * c1))
th_data.encode_s32(76, int(th.lat * c1))
return th_data
func to_cp866(proto: String, th_data):
var cp866_proto: PackedByteArray = proto.to_ascii_buffer()
cp866_proto.resize(36)
for i in len(cp866_proto):
th_data[28 + i] = cp866_proto[i]
func set_interfer(data):
var mode = data.decode_u8(9)
var id = data.decode_u16(10)
var aoa = float(data.decode_u16(12)) / 10
var ela = float(data.decode_u16(14)) / 10
var freq = data.decode_u16(16)
var width = data.decode_u16(18)
var interfer_params: Array = [mode, id, aoa, ela, freq, width]
signaller.emit_signal('interfer_rcv', interfer_params)
func on_interfer_accept(err: bool):
var data_tx = PackedByteArray()
var data_len = 2 # длинна блока данных в байтах
data_tx.resize(data_len)
data_tx.encode_u16(0, err) # Код ошибки
var data_to_send: PackedByteArray = create_header(data_len)
data_to_send.append_array(data_tx)
tx_stack.append(data_to_send)