Регрессия. Неверный символ отступа, должен быть "пробел".

This commit is contained in:
sasha80
2024-07-29 10:06:46 +03:00
parent 596127b371
commit af3ceeb2b3
34 changed files with 2918 additions and 2920 deletions

View File

@@ -9,42 +9,42 @@ const BUFFER_SIZE = 2048 ## Размер приёмного буфера д
class CapsRpb:
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось.
signal data_received(unit: CapsRpb) ## Сигнал данные приняты.
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды.
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения.
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось.
signal data_received(unit: CapsRpb) ## Сигнал данные приняты.
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды.
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения.
static var json_conv: = JSON.new()
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var json_dic: Dictionary ## Аппарат для разбора сообщений.
var tick: = 0 ## Тик время последнего обновления, мс.
var tx_data: = PackedByteArray() ## Пакет для отправки.
var tx_stack: Array ## Массив пакетов для отправки.
static var json_conv: = JSON.new()
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var json_dic: Dictionary ## Аппарат для разбора сообщений.
var 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 _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm): self.name = nm
func parse(data: PackedByteArray, now_tick: int):
tick = now_tick
if not online:
online = true
emit_signal('line_changed', self)
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
json_dic.merge(json_conv.get_data(), true)
emit_signal('data_received', self)
else:
var msg = json_conv.get_error_message()
emit_signal('parse_error', self, msg)
func parse(data: PackedByteArray, now_tick: int):
tick = now_tick
if not online:
online = true
emit_signal('line_changed', self)
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
json_dic.merge(json_conv.get_data(), true)
emit_signal('data_received', self)
else:
var msg = json_conv.get_error_message()
emit_signal('parse_error', self, msg)
func process(now_tick: int):
if online and ((now_tick - 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 process(now_tick: int):
if online and ((now_tick - 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

View File

@@ -4,22 +4,22 @@ class_name Iterfer extends Node
## Режимы помехи.
const ITERFER_MODE = {
'off': ['Откл', ['freq', 'width'], 0],
'auto': ['АВТО', ['freq', 'width'], 1000],
'srni1': ['СРН-И1', ['freq', 'width'], 1],
'srnm2': ['СРН-М2', ['freq', 'width'], 2],
'srngps': ['СРН-GPS', ['freq', 'width'], 3],
'lchm1': ['ЛЧМ-1', ['freq', 'width'], 10],
'lchm2': ['ЛЧМ-2', ['freq', 'width'], 4],
'mchm1': ['МЧМ-1', ['freq', 'width'], 11],
'pdm2': ['ПД-М2', ['freq', 'width'], 12],
'pdm4': ['ПД-М4', ['freq', 'width'], 13],
'pdm4s': ['ПД-М4С', ['freq', 'width'], 14],
'pdchm': ['ПД-ЧМ', ['freq', 'width'], 15],
'svi1': ['СВ-И1', ['freq', 'width'], 20],
'svm2': ['СВ-М2', ['freq', 'width'], 21],
'k1': ['K1', ['freq', 'width', 'dur', 'period'], 50],
'ozp1': ['ОЗП-1', ['freq', 'width'], 51] }
'off': ['Откл', ['freq', 'width'], 0],
'auto': ['АВТО', ['freq', 'width'], 1000],
'srni1': ['СРН-И1', ['freq', 'width'], 1],
'srnm2': ['СРН-М2', ['freq', 'width'], 2],
'srngps': ['СРН-GPS', ['freq', 'width'], 3],
'lchm1': ['ЛЧМ-1', ['freq', 'width'], 10],
'lchm2': ['ЛЧМ-2', ['freq', 'width'], 4],
'mchm1': ['МЧМ-1', ['freq', 'width'], 11],
'pdm2': ['ПД-М2', ['freq', 'width'], 12],
'pdm4': ['ПД-М4', ['freq', 'width'], 13],
'pdm4s': ['ПД-М4С', ['freq', 'width'], 14],
'pdchm': ['ПД-ЧМ', ['freq', 'width'], 15],
'svi1': ['СВ-И1', ['freq', 'width'], 20],
'svm2': ['СВ-М2', ['freq', 'width'], 21],
'k1': ['K1', ['freq', 'width', 'dur', 'period'], 50],
'ozp1': ['ОЗП-1', ['freq', 'width'], 51] }
const FREQ_MAX = 6000
const FREQ_MIN = 400
@@ -38,52 +38,52 @@ var cu: Dictionary ## Словарь воздействий для 5
## Сеанс помехи.
class Interfer:
var ss: int = 0 ## Счётчик сообщений.
var ispp: int = 0 ## Индекс сеанса.
var svk: = 0 ## Состояние сеанса. Ответ КАПСРПБ. Возможные значения в [param ITERFER_STATE].
var krp: String = '' ## Тип помехи. Возможные значения в [param INTERFER_MODE].
var powp: float = 0.0 ## Мощность излучения выраженная в процентах.
var kni: = 0.0 ## Курсовой угол направления излучения.
var params: = {} ## Параметры помехи.
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
var tick_tx: int ## Тик время обновления цели, мс.
var source_interfer: String = '' ## Тип объекта по которой поставлена помеха.
var ss: int = 0 ## Счётчик сообщений.
var ispp: int = 0 ## Индекс сеанса.
var svk: = 0 ## Состояние сеанса. Ответ КАПСРПБ. Возможные значения в [param ITERFER_STATE].
var krp: String = '' ## Тип помехи. Возможные значения в [param INTERFER_MODE].
var powp: float = 0.0 ## Мощность излучения выраженная в процентах.
var kni: = 0.0 ## Курсовой угол направления излучения.
var params: = {} ## Параметры помехи.
var get_params: Array[String] ## Запрос массива параметров (список запрошенных параметров).
var retss: int ## Значение счётчика сообщения в котором был произведён запрос массива параметров.
var tick_tx: int ## Тик время обновления цели, мс.
var source_interfer: String = '' ## Тип объекта по которой поставлена помеха.
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
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
data_to_json['ss'] = ss
data_to_json['ispp'] = ispp
data_to_json['krp'] = krp
if krp != INTERFER_OFF:
data_to_json['kni'] = kni
data_to_json['powp'] = powp # Необходимо добавить управление мощностью
data_to_json['get'] = []
data_to_json['params'] = params
var json = JSON.stringify(data_to_json)
var pac = json.to_utf8_buffer()
return pac
func get_msg6_data():
var data_to_json : Dictionary = {}
data_to_json['ts'] = 6
data_to_json['ss'] = ss
data_to_json['ispp'] = ispp
data_to_json['krp'] = krp
if krp != INTERFER_OFF:
data_to_json['kni'] = kni
data_to_json['powp'] = powp # Необходимо добавить управление мощностью
data_to_json['get'] = []
data_to_json['params'] = params
var json = JSON.stringify(data_to_json)
var pac = json.to_utf8_buffer()
return pac
func set_from_dic(dic: Dictionary):
var names: = tools.get_members_names(self)
names.any(func(vn): if dic.has(vn): set(vn, dic[vn]); return false)
func set_from_dic(dic: Dictionary):
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 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)
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) ## Вызывается в момент запуска помехи.
@@ -94,172 +94,172 @@ signal interfer_resized(ecms: Dictionary) ## Вызывается пр
func _ready():
var ecms: Dictionary = {} ## Словарь помех.
for i in range(ID_INTERFERS_LEN): # Заполняет массив ID целей
id_array.append(i + 1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_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))
unit_5p28.connect('get_interfers', Callable(self, 'on_get_interfers').bind(unit_5p28, ecms))
signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms))
signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms))
signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit))
signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit, ecms))
var ecms: Dictionary = {} ## Словарь помех.
for i in range(ID_INTERFERS_LEN): # Заполняет массив ID целей
id_array.append(i + 1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_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))
unit_5p28.connect('get_interfers', Callable(self, 'on_get_interfers').bind(unit_5p28, ecms))
signaller.connect('interfer_create', Callable(self, 'on_interfer_create').bind(unit, ecms))
signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms))
signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit))
signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit, ecms))
## Проверяет состояние отправки пакета и если не доставлен, повторяет отправку.
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
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):
if not unit.json_dic.has('ts'): return
if not (unit.json_dic['ts'] is float): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('msvk'): return
if not (unit.json_dic['msvk'] is Array): return
var msvk = unit.json_dic['msvk']
var sz: = ecms.size()
for dic_msvk in msvk:
if not (dic_msvk is Dictionary): continue
if dic_msvk.has('ispp'):
var ispp = int(dic_msvk['ispp'])
if ecms.has(ispp):
var ecm = ecms[ispp]
ecm.set_from_dic(dic_msvk)
call_deferred('emit_signal', 'interfer_update', ecm)
else:
var ecm = Interfer.new()
ecm.set_from_dic(dic_msvk)
ecm.krp = INTERFER_OFF
send_ecm(ecm, unit)
if sz != ecms.size():
call_deferred('emit_signal', 'interfer_resized', ecms)
if not unit.json_dic.has('ts'): return
if not (unit.json_dic['ts'] is float): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('msvk'): return
if not (unit.json_dic['msvk'] is Array): return
var msvk = unit.json_dic['msvk']
var sz: = ecms.size()
for dic_msvk in msvk:
if not (dic_msvk is Dictionary): continue
if dic_msvk.has('ispp'):
var ispp = int(dic_msvk['ispp'])
if ecms.has(ispp):
var ecm = ecms[ispp]
ecm.set_from_dic(dic_msvk)
call_deferred('emit_signal', 'interfer_update', ecm)
else:
var ecm = Interfer.new()
ecm.set_from_dic(dic_msvk)
ecm.krp = INTERFER_OFF
send_ecm(ecm, unit)
if sz != ecms.size():
call_deferred('emit_signal', 'interfer_resized', ecms)
## Вызыватся, когда пользователь выбрал помеху и выбраны цели.
func on_interfer_create(btn, sel_threats, fs_arr, _unit, ecms):
for item in sel_threats:
var param: Dictionary = {}
var kni: float = item.aoa
var id = item.id
var interfer_name: String = btn.get_meta('rfi_name')
param['freq'] = item.freq
param['width'] = item.width
interfer_create(interfer_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0])
for item in sel_threats:
var param: Dictionary = {}
var kni: float = item.aoa
var id = item.id
var interfer_name: String = btn.get_meta('rfi_name')
param['freq'] = item.freq
param['width'] = item.width
interfer_create(interfer_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0])
for item in fs_arr:
var param: Dictionary = {}
var kni: float = item[0]
var id = item[3]
var interfer_name: String = btn.get_meta('rfi_name')
param['freq'] = item[1]
param['width'] = item[2]
interfer_create(interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1])
for item in fs_arr:
var param: Dictionary = {}
var kni: float = item[0]
var id = item[3]
var interfer_name: String = btn.get_meta('rfi_name')
param['freq'] = item[1]
param['width'] = item[2]
interfer_create(interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1])
func on_interfer_rcv(interfer_params: Array, unit, ecms):
var err: bool = false
var mode = interfer_params[0]
var id = interfer_params[1]
var aoa = interfer_params[2]
if (aoa < 0) and (aoa > 360):
err = true
var param: Dictionary = {}
param['freq'] = interfer_params[4]
if (param['freq'] < FREQ_MIN) and (param['freq'] > FREQ_MAX):
err = true
param['width'] = interfer_params[5]
if (param['width'] < WIDTH_MIN) and (param['width'] > WIDTH_MAX):
err = true
var interfer_name: String
for key in ITERFER_MODE:
if ITERFER_MODE[key][2] == mode:
interfer_name = key
break
if interfer_name == '':
err = true
if not err:
interfer_create(interfer_name, ecms, param, aoa, id, cu, SOURCE_INTERFER[2])
unit.on_interfer_accept(err)
var err: bool = false
var mode = interfer_params[0]
var id = interfer_params[1]
var aoa = interfer_params[2]
if (aoa < 0) and (aoa > 360):
err = true
var param: Dictionary = {}
param['freq'] = interfer_params[4]
if (param['freq'] < FREQ_MIN) and (param['freq'] > FREQ_MAX):
err = true
param['width'] = interfer_params[5]
if (param['width'] < WIDTH_MIN) and (param['width'] > WIDTH_MAX):
err = true
var interfer_name: String
for key in ITERFER_MODE:
if ITERFER_MODE[key][2] == mode:
interfer_name = key
break
if interfer_name == '':
err = true
if not err:
interfer_create(interfer_name, ecms, param, aoa, id, cu, SOURCE_INTERFER[2])
unit.on_interfer_accept(err)
func interfer_create(interfer_name, ecms, param, kni, id, dict, source_interfer):
var ispp: int = 0
if interfer_name == 'k1':
param['dur'] = 1.0 # Необходимо добавить параметры управления
param['period'] = 1.0 # Необходимо добавить параметры управления
var key = dict.find_key(id)
if source_interfer != SOURCE_INTERFER[2]:
if key != null:
ispp = key
else:
if interfer_name == 'off':
return
ispp = pop_id()
if ispp == 0: return
else: ispp = id
dict[ispp] = id
msg_ss += 1
var ecm: Interfer
if ecms.has(ispp):
ecm = ecms[ispp]
else:
ecm = Interfer.new()
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 # Необходимо добавить управление мощностью
ecm.source_interfer = source_interfer
signaller.emit_signal('interfer_new', ecm)
if interfer_name == 'off':
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
push_id(ecm.ispp)
thrs.erase(ispp)
ecm.tick_tx = Time.get_ticks_msec()
var ispp: int = 0
if interfer_name == 'k1':
param['dur'] = 1.0 # Необходимо добавить параметры управления
param['period'] = 1.0 # Необходимо добавить параметры управления
var key = dict.find_key(id)
if source_interfer != SOURCE_INTERFER[2]:
if key != null:
ispp = key
else:
if interfer_name == 'off':
return
ispp = pop_id()
if ispp == 0: return
else: ispp = id
dict[ispp] = id
msg_ss += 1
var ecm: Interfer
if ecms.has(ispp):
ecm = ecms[ispp]
else:
ecm = Interfer.new()
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 # Необходимо добавить управление мощностью
ecm.source_interfer = source_interfer
signaller.emit_signal('interfer_new', ecm)
if interfer_name == 'off':
signaller.emit_signal('interfer_off', ecm, ecms, thrs)
push_id(ecm.ispp)
thrs.erase(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)
var json_data = ecm.get_msg6_data()
unit.tx_stack.append(json_data)
func on_interfer_off_all(unit, ecms):
for ecm in ecms.values():
ecm.krp = INTERFER_OFF
push_id(ecm.ispp)
send_ecm(ecm, unit)
signaller.emit_signal('interfer_off',ecm, ecms, thrs)
for ecm in ecms.values():
ecm.krp = INTERFER_OFF
push_id(ecm.ispp)
send_ecm(ecm, unit)
signaller.emit_signal('interfer_off',ecm, ecms, thrs)
func pop_id():
var id = 0
if len(id_array):
id = id_array[0]
id_array.remove_at(0)
return 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)
id_array.sort()
id_array.append(id)
id_array.sort()
## Отправляет словарь помех в юнит, для запаковки и отправки в 5П28.

File diff suppressed because it is too large Load Diff

View File

@@ -4,128 +4,128 @@ const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от я
class ModbusClient:
## Состояние автомата выполнения команды.
enum CmdState {
DONE, ## Команда выполнена.
FAIL, ## Команда не выполнена.
SEND, ## Буфер готов для отправки.
WAIT ## Ожидание выполнения.
}
## Состояние автомата выполнения команды.
enum CmdState {
DONE, ## Команда выполнена.
FAIL, ## Команда не выполнена.
SEND, ## Буфер готов для отправки.
WAIT ## Ожидание выполнения.
}
var name: String
var unit: = 1 ## Адрес устройства Modbus.
var cmd_state: = CmdState.DONE ## Код текущей команды.
var tx_data: PackedByteArray ## Данные для отправки.
var online: = false ## Флаг. Если установлен, устройство на связи. Активный уровень - [b]true[/b].
var tick_rx: = 0 ## Время приёма крайнего сообщения.
var tick_tx: = 0 ## Время отправки крайнего сообщения.
var name: String
var unit: = 1 ## Адрес устройства Modbus.
var cmd_state: = CmdState.DONE ## Код текущей команды.
var tx_data: PackedByteArray ## Данные для отправки.
var online: = false ## Флаг. Если установлен, устройство на связи. Активный уровень - [b]true[/b].
var tick_rx: = 0 ## Время приёма крайнего сообщения.
var tick_tx: = 0 ## Время отправки крайнего сообщения.
static var json_conv: = JSON.new()
static var json_conv: = JSON.new()
signal command_done() ## Вызывается при успешном выполнении команды.
signal command_fail() ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed() ## Вызывается при смене состояния связи с ячейкой.
signal data_received() ## Вызывается при приёме сообщения, до его разбора.
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке.
signal command_done() ## Вызывается при успешном выполнении команды.
signal command_fail() ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed() ## Вызывается при смене состояния связи с ячейкой.
signal data_received() ## Вызывается при приёме сообщения, до его разбора.
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке.
signal holding_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal input_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
signal holding_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal input_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
func _init(nm: String, u: int = 1):
unit = u
name = nm
func _init(nm: String, u: int = 1):
unit = u
name = nm
## Изменяет состояние. Вызывать периодически.[br]
## [param tick] - Текущщее время в мс.[br]
func process(tick: int):
if online and ((tick - tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed')
if (cmd_state == CmdState.WAIT) or (cmd_state == CmdState.SEND):
cmd_state = CmdState.FAIL
emit_signal('command_fail')
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
tick_tx = tick
cmd_state = CmdState.WAIT
return rc
## Изменяет состояние. Вызывать периодически.[br]
## [param tick] - Текущщее время в мс.[br]
func process(tick: int):
if online and ((tick - tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed')
if (cmd_state == CmdState.WAIT) or (cmd_state == CmdState.SEND):
cmd_state = CmdState.FAIL
emit_signal('command_fail')
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
tick_tx = tick
cmd_state = CmdState.WAIT
return rc
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
## [param data] - Данные принятые на сокете.[br]
## [param tick] - Текущщее время в мс.[br]
func parse(data: PackedByteArray, tick: int) -> bool:
tick_rx = tick
if not online:
online = true
emit_signal('line_changed')
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
emit_signal('data_received')
var message: Dictionary = json_conv.get_data()
if message.has('code') and message.has('data'):
var rc: = true
var message_code = message['code']
var message_data = message['data']
match message_code:
'read_input':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('input_received', addr, regs)
'read_holding':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('holding_received', addr, regs)
'info':
var msg = message['data']
emit_signal('info_received', msg)
'exception':
var msg = message['data']
emit_signal('except_received', msg)
rc = false
_:
var msg: String = 'код команды \"%s\" - не распознан' % message_code
emit_signal('parse_failed', msg)
rc = false
if (cmd_state == CmdState.WAIT) and rc:
cmd_state = CmdState.DONE
emit_signal('command_done')
elif (cmd_state == CmdState.WAIT) and (not rc):
cmd_state = CmdState.FAIL
emit_signal('command_fail')
else:
var message = json_conv.get_error_message()
emit_signal('parse_failed', message)
return true
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
## [param data] - Данные принятые на сокете.[br]
## [param tick] - Текущщее время в мс.[br]
func parse(data: PackedByteArray, tick: int) -> bool:
tick_rx = tick
if not online:
online = true
emit_signal('line_changed')
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
emit_signal('data_received')
var message: Dictionary = json_conv.get_data()
if message.has('code') and message.has('data'):
var rc: = true
var message_code = message['code']
var message_data = message['data']
match message_code:
'read_input':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('input_received', addr, regs)
'read_holding':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('holding_received', addr, regs)
'info':
var msg = message['data']
emit_signal('info_received', msg)
'exception':
var msg = message['data']
emit_signal('except_received', msg)
rc = false
_:
var msg: String = 'код команды \"%s\" - не распознан' % message_code
emit_signal('parse_failed', msg)
rc = false
if (cmd_state == CmdState.WAIT) and rc:
cmd_state = CmdState.DONE
emit_signal('command_done')
elif (cmd_state == CmdState.WAIT) and (not rc):
cmd_state = CmdState.FAIL
emit_signal('command_fail')
else:
var message = json_conv.get_error_message()
emit_signal('parse_failed', message)
return true
## Отправляет команду "записать в регистры".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Данные для записи в регистры от начального адреса.[br]
func write(addr: int, data: Array) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'write', 'data': [addr] + data}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "записать в регистры".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Данные для записи в регистры от начального адреса.[br]
func write(addr: int, data: Array) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'write', 'data': [addr] + data}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры хранения".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_holdind(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_holding', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры хранения".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_holdind(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_holding', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры входов".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_input(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_input', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры входов".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_input(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_input', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true

View File

@@ -5,27 +5,27 @@ const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'jsontx': capsrpb.CapsRpb, 'udp
const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28}
class Socket extends PacketPeerUDP:
func send_to(addr, data):
self.set_dest_address(addr[0], addr[1])
self.put_packet(data)
func send_to(addr, data):
self.set_dest_address(addr[0], addr[1])
self.put_packet(data)
class SocketTCP extends TCPServer:
const RX_TIMEOUT: int = 1000 ## Время сброса счётчика принятия части пакета.
var peerstream: = PacketPeerStream.new()
var unit_key: Array ## Клюс юнита.
var head_len: int = 8 ## Длинна заголовка команды.
var len_place: int = 4 ## Номер начального байта с длинной блока данных.
var type_len: int = 4 ## Количество байт в размере длинны.
var rx_tick: int ## Время приёма последнего пакета.
var rx_all: bool = true ## Флаг, что пакет принят полностью.
var rx_len: int ## Количество принятых байт.
var rx_data: PackedByteArray ## Принятые данные.
var data_len: int ## Размер ожидаемых данных.
const RX_TIMEOUT: int = 1000 ## Время сброса счётчика принятия части пакета.
var peerstream: = PacketPeerStream.new()
var unit_key: Array ## Клюс юнита.
var head_len: int = 8 ## Длинна заголовка команды.
var len_place: int = 4 ## Номер начального байта с длинной блока данных.
var type_len: int = 4 ## Количество байт в размере длинны.
var rx_tick: int ## Время приёма последнего пакета.
var rx_all: bool = true ## Флаг, что пакет принят полностью.
var rx_len: int ## Количество принятых байт.
var rx_data: PackedByteArray ## Принятые данные.
var data_len: int ## Размер ожидаемых данных.
func send_to(data):
var peer = peerstream.get_stream_peer()
peer.put_data(data)
func send_to(data):
var peer = peerstream.get_stream_peer()
peer.put_data(data)
var poll_sockets: Array[Socket]
@@ -38,129 +38,129 @@ var logger_page: Node
func create_socket(nm) -> Socket:
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2]
var broad = repsettings.UnitProfiles[nm][3]
var bind = repsettings.UnitProfiles[nm][4]
var sock: = Socket.new()
sock.set_broadcast_enabled(broad)
var rc = Error.OK if not bind else sock.bind(port, addr)
var errlevel = log.INFO if rc == Error.OK else log.ERROR
log.message(errlevel, '%s: сокет:%s:%d привязанный:%s %s' % [nm, addr, port, ['нет', 'да'][int(bind)], error_string(rc)])
return sock
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2]
var broad = repsettings.UnitProfiles[nm][3]
var bind = repsettings.UnitProfiles[nm][4]
var sock: = Socket.new()
sock.set_broadcast_enabled(broad)
var rc = Error.OK if not bind else sock.bind(port, addr)
var errlevel = log.INFO if rc == Error.OK else log.ERROR
log.message(errlevel, '%s: сокет:%s:%d привязанный:%s %s' % [nm, addr, port, ['нет', 'да'][int(bind)], error_string(rc)])
return sock
func create_tcpsocket(nm) -> SocketTCP:
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2]
var sock = SocketTCP.new()
sock.unit_key = repsettings.get_unit_key(nm)
sock.listen(port, addr)
log.message(log.INFO, '%s: сокет:%s:%d привязанный:' % [nm, addr, port])
return sock
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2]
var sock = SocketTCP.new()
sock.unit_key = repsettings.get_unit_key(nm)
sock.listen(port, addr)
log.message(log.INFO, '%s: сокет:%s:%d привязанный:' % [nm, addr, port])
return sock
func _ready() -> void:
log.info('Модуль работы с сетью готов')
poll_sockets.append(create_socket('уарэп-яу07-частный'))
poll_sockets.append(create_socket('уарэп-яу07-общий'))
poll_sockets.append(create_socket('уарэп-капсрпб-пол'))
sock_unicast = poll_sockets[0]
sock_capsrpb = poll_sockets[2]
log.info('Модуль работы с сетью готов')
poll_sockets.append(create_socket('уарэп-яу07-частный'))
poll_sockets.append(create_socket('уарэп-яу07-общий'))
poll_sockets.append(create_socket('уарэп-капсрпб-пол'))
sock_unicast = poll_sockets[0]
sock_capsrpb = poll_sockets[2]
for unit_name in repsettings.UnitProfiles:
var setting = repsettings.UnitProfiles[unit_name]
var proto = setting[0]
if proto in PROTOCOL_TYPES:
var unit = PROTOCOL_TYPES[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
units[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
for unit_name in repsettings.UnitProfiles:
var settings = repsettings.UnitProfiles[unit_name]
var proto = settings[0]
if proto in PROTOCOL_TYPES:
var unit = PROTOCOL_TYPES[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
units[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
if proto in TCP_PROTO:
var unit = TCP_PROTO[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
units_tcp[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
if proto in TCP_PROTO:
var unit = TCP_PROTO[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
units_tcp[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
tcp_sockets.append([create_tcpsocket('уарэп-5п28'), units_tcp[repsettings.get_unit_key('уарэп-5п28')]])
tcp_sockets.append([create_tcpsocket('уарэп-5п28'), units_tcp[repsettings.get_unit_key('уарэп-5п28')]])
for key in units: log.info('%s %s:%d' % [units[key].name, key[0], key[1]])
for key in units_tcp: log.info('%s %s:%d' % [units_tcp[key].name, key[0], key[1]])
for key in units: log.info('%s %s:%d' % [units[key].name, key[0], key[1]])
for key in units_tcp: log.info('%s %s:%d' % [units_tcp[key].name, key[0], key[1]])
func poll_receive(sock: Socket, tick: int) -> bool:
while sock.get_available_packet_count() > 0:
var data: = sock.get_packet()
var addr: = sock.get_packet_ip()
var port: = sock.get_packet_port()
var addr_port: = [addr, port]
if addr_port in units: units[addr_port].parse(data, tick)
return false
while sock.get_available_packet_count() > 0:
var data: = sock.get_packet()
var addr: = sock.get_packet_ip()
var port: = sock.get_packet_port()
var addr_port: = [addr, port]
if addr_port in units: units[addr_port].parse(data, tick)
return false
func poll_receive_tcp(sock: SocketTCP, tick: int) -> bool:
if sock.is_connection_available(): # check if someone's trying to connect
var client = sock.take_connection() # accept connection
sock.peerstream.set_stream_peer(client) # bind peerstream to new client
print_debug('client_is_connected')
var peer = sock.peerstream.get_stream_peer()
if peer:
var peer_len_data = peer.get_available_bytes()
if peer_len_data > 0:
get_client_data(sock, peer_len_data, peer, tick)
if sock.unit_key in units_tcp and sock.rx_all: units_tcp[sock.unit_key].parse(sock.rx_data, tick)
return false
if sock.is_connection_available(): # check if someone's trying to connect
var client = sock.take_connection() # accept connection
sock.peerstream.set_stream_peer(client) # bind peerstream to new client
print_debug('client_is_connected')
var peer = sock.peerstream.get_stream_peer()
if peer:
var peer_len_data = peer.get_available_bytes()
if peer_len_data > 0:
get_client_data(sock, peer_len_data, peer, tick)
if sock.unit_key in units_tcp and sock.rx_all: units_tcp[sock.unit_key].parse(sock.rx_data, tick)
return false
func get_client_data(sock: SocketTCP, peer_len_data, peer, tick):
if tick - sock.rx_tick > sock.RX_TIMEOUT:
sock.rx_all = true
sock.rx_tick = tick
if sock.rx_all:
if peer_len_data >= sock.head_len:
sock.rx_all = false
sock.rx_len = sock.head_len
var head = peer.get_data(sock.head_len)
sock.data_len = head[1].decode_u32(sock.len_place)
var len_data_in_buf = peer.get_available_bytes()
if len_data_in_buf > 0:
sock.rx_data = head[1]
var len_rx = len_data_in_buf
if len_data_in_buf >= sock.data_len:
len_rx = sock.data_len
get_tcp_data(sock, peer, len_rx)
else:
var len_rx = (sock.head_len + sock.data_len) - sock.rx_len
if peer_len_data < len_rx:
len_rx = peer_len_data
get_tcp_data(sock, peer, len_rx)
if tick - sock.rx_tick > sock.RX_TIMEOUT:
sock.rx_all = true
sock.rx_tick = tick
if sock.rx_all:
if peer_len_data >= sock.head_len:
sock.rx_all = false
sock.rx_len = sock.head_len
var head = peer.get_data(sock.head_len)
sock.data_len = head[1].decode_u32(sock.len_place)
var len_data_in_buf = peer.get_available_bytes()
if len_data_in_buf > 0:
sock.rx_data = head[1]
var len_rx = len_data_in_buf
if len_data_in_buf >= sock.data_len:
len_rx = sock.data_len
get_tcp_data(sock, peer, len_rx)
else:
var len_rx = (sock.head_len + sock.data_len) - sock.rx_len
if peer_len_data < len_rx:
len_rx = peer_len_data
get_tcp_data(sock, peer, len_rx)
func get_tcp_data(sock: SocketTCP, peer, len_rx):
var temp_data = peer.get_data(len_rx)[1]
sock.rx_data.append_array(temp_data)
sock.rx_len += len_rx
if sock.rx_len >= sock.head_len + sock.data_len:
sock.rx_all = true
var temp_data = peer.get_data(len_rx)[1]
sock.rx_data.append_array(temp_data)
sock.rx_len += len_rx
if sock.rx_len >= sock.head_len + sock.data_len:
sock.rx_all = true
func _process(_delta: float) -> void:
var tick = Time.get_ticks_msec()
for addr in units:
var unit = units[addr]
match unit.process(tick):
Error.OK: sock_unicast.send_to(addr, unit.tx_data)
Error.FAILED: emit_signal('socket_error', 'ошибка: %s %s:%d' % [unit, addr[0], addr[1]])
for sock_unit in tcp_sockets:
var sock = sock_unit[0]
var unit = sock_unit[1]
match unit.process(tick):
Error.OK: sock.send_to(unit.tx_data)
Error.FAILED: emit_signal('socket_error', 'ошибка: %s' %unit)
poll_receive_tcp(sock, tick)
poll_sockets.any(func(sock): poll_receive(sock, tick))
var tick = Time.get_ticks_msec()
for addr in units:
var unit = units[addr]
match unit.process(tick):
Error.OK: sock_unicast.send_to(addr, unit.tx_data)
Error.FAILED: emit_signal('socket_error', 'ошибка: %s %s:%d' % [unit, addr[0], addr[1]])
for sock_unit in tcp_sockets:
var sock = sock_unit[0]
var unit = sock_unit[1]
match unit.process(tick):
Error.OK: sock.send_to(unit.tx_data)
Error.FAILED: emit_signal('socket_error', 'ошибка: %s' %unit)
poll_receive_tcp(sock, tick)
poll_sockets.any(func(sock): poll_receive(sock, tick))

View File

@@ -3,40 +3,40 @@ class_name rep_settings extends Node
## Параметры.
@export var UnitProfiles: = { \
# Название | Протокол | Адрес | Порт | Широковещательное | Привязывать к адресу | Комментарий
'уарэп-яу07-частный': ['yau07rx', '10.1.1.2', 50002, false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
'уарэп-яу07-общий': ['yau07rx', '10.1.1.255', 50000, true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
'уарэп-капсрпб-пол': ['jsonrx', '127.0.0.1', 42023, false, true, 'IP-адрес на котором принимают сообщения от КАПС РПБ'],
'уарэп-капсрпб-отп': ['jsontx', '127.0.0.1', 42022, false, false, 'IP-адрес на который отправляют сообщения для КАПС РПБ'],
'уарэп-эмс': ['yau07tx', '10.1.1.27', 50027, false, false, 'IP-адрес ЯУ-07 прибора УФ'],
'уарэп-яу07-2в': ['yau07tx', '10.1.1.34', 50034, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-2н': ['yau07tx', '10.1.1.33', 50033, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-2к': ['yau07tx', '10.1.1.35', 50035, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-4в': ['yau07tx', '10.1.1.66', 50066, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-4н': ['yau07tx', '10.1.1.65', 50065, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-4к': ['yau07tx', '10.1.1.67', 50067, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-1в': ['yau07tx', '10.1.1.18', 50018, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-1н': ['yau07tx', '10.1.1.17', 50017, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-1к': ['yau07tx', '10.1.1.19', 50019, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-3в': ['yau07tx', '10.1.1.50', 50050, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-3н': ['yau07tx', '10.1.1.49', 50049, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-3к': ['yau07tx', '10.1.1.51', 50051, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
# Название | Протокол | Адрес | Порт | Широковещательное | Привязывать к адресу | Комментарий
'уарэп-яу07-частный': ['yau07rx', '10.1.1.2', 50002, false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
'уарэп-яу07-общий': ['yau07rx', '10.1.1.255', 50000, true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
'уарэп-капсрпб-пол': ['jsonrx', '127.0.0.1', 42023, false, true, 'IP-адрес на котором принимают сообщения от КАПС РПБ'],
'уарэп-капсрпб-отп': ['jsontx', '127.0.0.1', 42022, false, false, 'IP-адрес на который отправляют сообщения для КАПС РПБ'],
'уарэп-эмс': ['yau07tx', '10.1.1.27', 50027, false, false, 'IP-адрес ЯУ-07 прибора УФ'],
'уарэп-яу07-2в': ['yau07tx', '10.1.1.34', 50034, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-2н': ['yau07tx', '10.1.1.33', 50033, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-2к': ['yau07tx', '10.1.1.35', 50035, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-4в': ['yau07tx', '10.1.1.66', 50066, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-4н': ['yau07tx', '10.1.1.65', 50065, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-4к': ['yau07tx', '10.1.1.67', 50067, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-1в': ['yau07tx', '10.1.1.18', 50018, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-1н': ['yau07tx', '10.1.1.17', 50017, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-1к': ['yau07tx', '10.1.1.19', 50019, false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
'уарэп-яу07-3в': ['yau07tx', '10.1.1.50', 50050, false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-3н': ['yau07tx', '10.1.1.49', 50049, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-3к': ['yau07tx', '10.1.1.51', 50051, false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
# Название | Протокол | Адрес | Порт получения | Комментарий
'уарэп-5п28': ['5p28', '127.0.0.1', 50000, 'IP-адрес комплекса 5П-28'],
# Название | Протокол | Адрес | Порт получения | Комментарий
'уарэп-5п28': ['5p28', '127.0.0.1', 50000, 'IP-адрес комплекса 5П-28'],
# Название | Протокол | Адрес | Порт получения | Порт отправки | Комментарий
'уарэп-щ3': ['udp-json-mbcs', 'localhost', 48000, 44100, 'IP-адрес и порты через которые производят обмен сообщения с драйвером клиента Modbus Serial'],
# Название | Протокол | Адрес | Порт получения | Порт отправки | Комментарий
'уарэп-щ3': ['udp-json-mbcs', 'localhost', 48000, 44100, 'IP-адрес и порты через которые производят обмен сообщения с драйвером клиента Modbus Serial'],
# Название | Протокол | Имя порта | Скорость, бод | Чётность | Комментарий
'уарэп-спт25-1': ['uart', '/dev/tty2', 115200, false, 'Адрес прибора СПТ-25 (G1)'],
'уарэп-спт25-2': ['uart', '/dev/tty3', 115200, false, 'Адрес прибора СПТ-25 (G2)'],
# Название | Протокол | Имя порта | Скорость, бод | Чётность | Комментарий
'уарэп-спт25-1': ['uart', '/dev/tty2', 115200, false, 'Адрес прибора СПТ-25 (G1)'],
'уарэп-спт25-2': ['uart', '/dev/tty3', 115200, false, 'Адрес прибора СПТ-25 (G2)'],
}
## Параметры цели.
@export var ThreatParams = {
'time_lost': 5000 ## Время после последнего обновления в мс, через которое цель считается потерянной.
}
'time_lost': 5000 ## Время после последнего обновления в мс, через которое цель считается потерянной.
}
func _ready() -> void: log.info('Модуль настроек готов')
@@ -44,6 +44,6 @@ func _ready() -> void: log.info('Модуль настроек готов')
## Возвращает ключ устройства.
func get_unit_key(unit_name: String) -> Array:
assert(UnitProfiles.has(unit_name), 'ошибка: нет такого устройства \"%s\"' % unit_name)
var item = UnitProfiles[unit_name]
return [item[1], item[2]]
assert(UnitProfiles.has(unit_name), 'ошибка: нет такого устройства \"%s\"' % unit_name)
var item = UnitProfiles[unit_name]
return [item[1], item[2]]

View File

@@ -9,185 +9,185 @@ 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',]
'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, # Неисправность
}
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
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) ## Запрос состояния выполнения целеуказания.
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 ## Массив пакетов для отправки.
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 _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 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 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_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 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 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 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 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 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)
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)

View File

@@ -5,36 +5,36 @@ extends Node
## Цель
class Threat:
var alt: float ## Текущая высота, метры.
var aoa: float ## Курсовой угол на источник сигнала, градусы.
var atick: float ## Тик обнаружения.
var baud: float ## Модуляционная скорость.
var fflags: Dictionary ## Флаги достоверности полей.
var freq: float ## Частота несущей или центральная частота, МГц.
var freqm: String ## Режим смены частоты.
var id: int ## Идентификатор цели.
var lat: float ## Текущие координаты, широта в градусах.
var lon: float ## Текущие координаты, долгота в градусах.
var power: float ## Уровень принимаемого сигнала, дБм.
var proto: String ## Тип протокола источника сигнала.
var rkrp: String ## Рекомендуемый режим помехи.
var rparams: String ## Рекомендуемые параметры помехи.
var salt: float ## Координаты старта, высота от уровня моря, м.
var slat: float ## Координаты старта, широта в градусах.
var slon: float ## Координаты старта, долгота в градусах.
var tick: int ## Тик время приёма сигнала, мс.
var tick_rx: int ## Тик время обновления цели, мс.
var tmod: String ## Тип модуляции.
var width: float ## Ширина занимаемого диапазона частот, МГц.
var selected: bool ## Флаг, что цель выбрана.
var alt: float ## Текущая высота, метры.
var aoa: float ## Курсовой угол на источник сигнала, градусы.
var atick: float ## Тик обнаружения.
var baud: float ## Модуляционная скорость.
var fflags: Dictionary ## Флаги достоверности полей.
var freq: float ## Частота несущей или центральная частота, МГц.
var freqm: String ## Режим смены частоты.
var id: int ## Идентификатор цели.
var lat: float ## Текущие координаты, широта в градусах.
var lon: float ## Текущие координаты, долгота в градусах.
var power: float ## Уровень принимаемого сигнала, дБм.
var proto: String ## Тип протокола источника сигнала.
var rkrp: String ## Рекомендуемый режим помехи.
var rparams: String ## Рекомендуемые параметры помехи.
var salt: float ## Координаты старта, высота от уровня моря, м.
var slat: float ## Координаты старта, широта в градусах.
var slon: float ## Координаты старта, долгота в градусах.
var tick: int ## Тик время приёма сигнала, мс.
var tick_rx: int ## Тик время обновления цели, мс.
var tmod: String ## Тип модуляции.
var width: float ## Ширина занимаемого диапазона частот, МГц.
var selected: bool ## Флаг, что цель выбрана.
func _init(): clear_fflags()
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 _init(): clear_fflags()
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):
var items: = fflags.keys().filter(func(vn): return dic.has(vn))
items.any(func(vn): set(vn, dic[vn]); fflags[vn] = true; return false)
func set_from_dic(dic: Dictionary):
var items: = fflags.keys().filter(func(vn): return dic.has(vn))
items.any(func(vn): set(vn, dic[vn]); fflags[vn] = true; return false)
signal threat_new(th: Threat)
@@ -44,34 +44,34 @@ signal threats_resized(th: Dictionary)
func _ready() -> void:
log.info('Модуль обработки целей готов')
var threats = {} ## Список целей. Индекс - <номер цели>
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_key]
var timer_check_lost: = Timer.new()
add_child(timer_check_lost)
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(threats))
unit_5p28.connect('get_threats', Callable(self, 'on_get_threats').bind(unit_5p28, threats))
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('rto_threat_unsel_all', Callable(self, 'on_rto_threat_unsel_all').bind(threats))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats))
signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats))
log.info('Модуль обработки целей готов')
var threats = {} ## Список целей. Индекс - <номер цели>
var unit_key = repsettings.get_unit_key('уарэп-капсрпб-отп')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_key]
var timer_check_lost: = Timer.new()
add_child(timer_check_lost)
unit.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(threats))
unit_5p28.connect('get_threats', Callable(self, 'on_get_threats').bind(unit_5p28, threats))
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('rto_threat_unsel_all', Callable(self, 'on_rto_threat_unsel_all').bind(threats))
signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(threats))
signaller.connect('interfer_init', Callable(self, 'on_interfer_init').bind(threats))
## Периодически удаляет устаревшие цели.
func on_timer_check_lost(time_lost: int, threats: Dictionary):
var tick = Time.get_ticks_msec()
var sz: = threats.size()
for th in threats.values():
if (tick - th.tick_rx) >= time_lost:
threats.erase(th.id)
call_deferred('emit_signal', 'threat_lost', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)
var tick = Time.get_ticks_msec()
var sz: = threats.size()
for th in threats.values():
if (tick - th.tick_rx) >= time_lost:
threats.erase(th.id)
call_deferred('emit_signal', 'threat_lost', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)
## отправляет словарь целей в юнит, для запаковки и отправки в 5П28.
@@ -84,8 +84,8 @@ func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false
## Снимает выделение со всех целей.
func on_rto_threat_unsel_all(threats):
for th in threats.values():
signaller.emit_signal('rto_threat_unsel', th.id)
for th in threats.values():
signaller.emit_signal('rto_threat_unsel', th.id)
## Выбирает цель, если нажать по отметке цели.
@@ -94,44 +94,44 @@ func on_rto_threat_sel(th_id, threats): on_threat_selected(threats[th_id], threa
## Выбирает цель, если выбрать в таблице.
func on_threat_selected(th, threats):
for threat in threats.values():
threat.selected = false
th.selected = true
for threat in threats.values():
threat.selected = false
th.selected = true
## Формирует список выбранных целей для включения помехи.
func on_interfer_init(btn, fs_arr, threats):
var sel_threats: Array = []
for threat in threats.values():
if threat.selected:
sel_threats.append(threat)
if len(sel_threats) or (len(fs_arr)):
signaller.emit_signal('interfer_create', btn, sel_threats, fs_arr)
var sel_threats: Array = []
for threat in threats.values():
if threat.selected:
sel_threats.append(threat)
if len(sel_threats) or (len(fs_arr)):
signaller.emit_signal('interfer_create', btn, sel_threats, fs_arr)
## Производит приём целей.
func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary):
if not unit.json_dic.has('ts'): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('mis'): return
if not unit.json_dic.has('ts'): return
if unit.json_dic['ts'] != 5: return
if not unit.json_dic.has('mis'): return
var mis = unit.json_dic['mis']
var sz: = threats.size()
for dic_th in mis:
if dic_th is Dictionary:
if dic_th.has('id'):
var id = int(dic_th['id'])
if threats.has(id):
var th = threats[id]
th.clear_fflags()
th.set_from_dic(dic_th)
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_update', th)
else:
var th = Threat.new()
th.set_from_dic(dic_th)
threats[id] = th
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_new', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)
var mis = unit.json_dic['mis']
var sz: = threats.size()
for dic_th in mis:
if dic_th is Dictionary:
if dic_th.has('id'):
var id = int(dic_th['id'])
if threats.has(id):
var th = threats[id]
th.clear_fflags()
th.set_from_dic(dic_th)
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_update', th)
else:
var th = Threat.new()
th.set_from_dic(dic_th)
threats[id] = th
th.tick_rx = unit.tick
call_deferred('emit_signal', 'threat_new', th)
if sz != threats.size():
call_deferred('emit_signal', 'threats_resized', threats)

View File

@@ -30,14 +30,14 @@ func is_overlap(x1, x2, y1, y2) -> bool: return max(x1, y1) <= min(x2, y2)
func _check_index(obj, index) -> bool:
if obj is Dictionary:
if obj.has(index):
return true
elif obj is Array:
if index is int:
if (index >= 0) and (index < obj.size()):
return true
return false
if obj is Dictionary:
if obj.has(index):
return true
elif obj is Array:
if index is int:
if (index >= 0) and (index < obj.size()):
return true
return false
## Возвращает значение поля хранящегося по указанному пути внутри объекта.[br]
@@ -48,15 +48,15 @@ func _check_index(obj, index) -> bool:
## [param ret_val[1]] - устанвлено в [b]true[/b], если поле найдено, и установлено в [b]false[/b],
## если искомое поле не найдено.
func get_value_by_path(obj, paths: Array, ret_val: Array):
var index = paths.pop_at(0)
ret_val[1] = false
if paths.size():
if _check_index(obj, index):
get_value_by_path(obj[index], paths, ret_val)
else:
if _check_index(obj, index):
ret_val[0] = obj[index]
ret_val[1] = true
var index = paths.pop_at(0)
ret_val[1] = false
if paths.size():
if _check_index(obj, index):
get_value_by_path(obj[index], paths, ret_val)
else:
if _check_index(obj, index):
ret_val[0] = obj[index]
ret_val[1] = true
## Возвращает часть от входной строки ограниченную индексами символов.[br]
@@ -65,75 +65,75 @@ func get_value_by_path(obj, paths: Array, ret_val: Array):
## [param i0] - Индекс начала части строки.[br]
## [param i1] - Индекс конца части строки. Возвращает все символы до этого индекса.
func get_string_slice(s_in: String, s_out: Array, i0: int, i1: int):
for i in range(i0, i1):
if s_in[i] != '\'':
s_out[0] += s_in[i]
for i in range(i0, i1):
if s_in[i] != '\'':
s_out[0] += s_in[i]
## Производит преобразование из декартовой в полярную систему координат.
func pos_calc(freq: float, aoa: float, pos0: Vector2, r0: float, r1: float, f0: float, f1: float):
var r = ((freq - f0) / (f1 - f0)) * r1 + r0
var aoa_rad = radians(aoa) - PI / 2.0
return Vector2(cos(aoa_rad), sin(aoa_rad)) * r + pos0
var r = ((freq - f0) / (f1 - f0)) * r1 + r0
var aoa_rad = radians(aoa) - PI / 2.0
return Vector2(cos(aoa_rad), sin(aoa_rad)) * r + pos0
## Отсекает значение до заданного диапазона.
func clip_value(val, val_min, val_max):
if val < val_min: val = val_min
if val > val_max: val = val_max
return val
if val < val_min: val = val_min
if val > val_max: val = val_max
return val
## Возвращает массив с именами членов [param obj].
func get_members_names(obj: Object) -> Array:
var pl = obj.get_property_list()
var names: = Array()
for item in pl: names.append(item.name)
return names
var pl = obj.get_property_list()
var names: = Array()
for item in pl: names.append(item.name)
return names
## Проверяет, что заданный массив [param val] похож на ip-адрес.
func is_array_ipaddr(val: Array):
return (val.size() == 2) \
and (val[0] is String) \
and (val[1] is int) \
and (0 < val[1]) \
and (val[1] < 65536)
return (val.size() == 2) \
and (val[0] is String) \
and (val[1] is int) \
and (0 < val[1]) \
and (val[1] < 65536)
## Преобразует декартовые координаты в полярные.[br]
## [param pos0] - координаты центра.[br]
## [param pos] - координаты точки.[br]
func map_dec_to_rad(pos0: Vector2, pos: Vector2) -> Vector2:
var x1: float = pos.x - pos0.x
var y1: float = pos.y - pos0.y
var ang: float = (atan2(y1, x1) * 180.0) / PI
return Vector2(ang + 360.0 * float(ang < 0.0), hypot(x1, y1))
var x1: float = pos.x - pos0.x
var y1: float = pos.y - pos0.y
var ang: float = (atan2(y1, x1) * 180.0) / PI
return Vector2(ang + 360.0 * float(ang < 0.0), hypot(x1, y1))
## Переводит значение val из диапазона a0...a1 в диапазон b0...b1.
func map_range(val: float, a0: float, a1: float, b0: float, b1: float) -> float:
return (((val - a0) * (b1 - b0)) / (a1 - a0)) + b0
return (((val - a0) * (b1 - b0)) / (a1 - a0)) + b0
## Возвращает [b]true[/b], если точка внутри заданного полигона.[br]
## [param pos] - Проверяемая точка.[br]
## [param p] - Координаты вершин полигона.[br]
func is_point_in_polygon(pos: Vector2, p: PackedVector2Array) -> bool:
var sz: = p.size()
assert(sz)
var j: int = sz - 1
var odd_nodes: int = 0
for i in sz:
if ((p[i].y < pos.y and p[j].y >= pos.y or p[j].y < pos.y and p[i].y >= pos.y) and (p[i].x <= pos.x or p[j].x <= pos.x)):
odd_nodes ^= int((p[i].x + (pos.y - p[i].y) / (p[j].y - p[i].y) * (p[j].x - p[i].x) < pos.x))
j = i
return odd_nodes > 0
var sz: = p.size()
assert(sz)
var j: int = sz - 1
var odd_nodes: int = 0
for i in sz:
if ((p[i].y < pos.y and p[j].y >= pos.y or p[j].y < pos.y and p[i].y >= pos.y) and (p[i].x <= pos.x or p[j].x <= pos.x)):
odd_nodes ^= int((p[i].x + (pos.y - p[i].y) / (p[j].y - p[i].y) * (p[j].x - p[i].x) < pos.x))
j = i
return odd_nodes > 0
## Записывает слово [param val] в элемент байтовго массива [param buf].
## расположенный по индексу [param index] (младшее слово).[br]
## [i]Следует использовать встроенные в[/i] [b]PackedByteArray[/b] [i]методы вместо этой функции.[/i]
func set_wordi(buf: PackedByteArray, index: int, val: int) -> void:
buf[index] = val & 0xff
buf[index + 1] = (val >> 8) & 0xff
buf[index] = val & 0xff
buf[index + 1] = (val >> 8) & 0xff

View File

@@ -11,239 +11,239 @@ const BUFFER_SIZE = 2048 ## Размер буфера для приёма д
## Ячейка ЯУ-07.
class YaU07:
## Коды выполняемых команд.
enum CmdCode {
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07.
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07.
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07.
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07.
}
## Коды выполняемых команд.
enum CmdCode {
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07.
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07.
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07.
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07.
}
## Состояние автомата выполнения команды.
enum CmdState {
UNCK, ## Номер команды не ининциирован.
SEND, ## Буфер готов для отправки.
WAIT, ## Ожидание выполнения.
DONE, ## Команда выполнена.
FAIL ## Команда не выполнена.
}
## Состояние автомата выполнения команды.
enum CmdState {
UNCK, ## Номер команды не ининциирован.
SEND, ## Буфер готов для отправки.
WAIT, ## Ожидание выполнения.
DONE, ## Команда выполнена.
FAIL ## Команда не выполнена.
}
signal line_changed(unit: YaU07) ## Вызывается когда меняется состояние связи с ячейкой.
signal command_done(unit: YaU07) ## Вызывается после выполнения команды.
signal command_fail(unit: YaU07) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
signal parse_failed(unit: YaU07)
signal line_changed(unit: YaU07) ## Вызывается когда меняется состояние связи с ячейкой.
signal command_done(unit: YaU07) ## Вызывается после выполнения команды.
signal command_fail(unit: YaU07) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
signal parse_failed(unit: YaU07)
var name: = String()
var cmd_num_rx: = 0 ## Номер команды принятый.
var cmd_num_tx: = 0 ## Номер команды переданный.
var cmd_state = CmdState.UNCK ## Состояние выполнения команды.
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07.
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07.
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду.
var tick = 0.0 ## Текущее тик-время в мс.
var cmd_tick_tx = 0.0 ## Время последней отправки команды.
var cmd_tick_rx = 0.0 ## Время последнего приёма команды.
var status: = PackedByteArray() ## Поле "состояние прибора".
var tx_data: = PackedByteArray() ## Буфер отправленный.
var tx_len = 0 ## Длина последнего отправленного пакета.
var isa_ports = {} ## Результат выполнения команды "читать порт".
var isa_block = {} ## Результат выполнения команды "читать массив из порта".
var online = false ## Состояние связи с ячейкой.
var name: = String()
var cmd_num_rx: = 0 ## Номер команды принятый.
var cmd_num_tx: = 0 ## Номер команды переданный.
var cmd_state = CmdState.UNCK ## Состояние выполнения команды.
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07.
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07.
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду.
var tick = 0.0 ## Текущее тик-время в мс.
var cmd_tick_tx = 0.0 ## Время последней отправки команды.
var cmd_tick_rx = 0.0 ## Время последнего приёма команды.
var status: = PackedByteArray() ## Поле "состояние прибора".
var tx_data: = PackedByteArray() ## Буфер отправленный.
var tx_len = 0 ## Длина последнего отправленного пакета.
var isa_ports = {} ## Результат выполнения команды "читать порт".
var isa_block = {} ## Результат выполнения команды "читать массив из порта".
var online = false ## Состояние связи с ячейкой.
func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm):
self.name = nm
tx_data.resize(BUFFER_SIZE)
tx_data.fill(0)
tick = 0.0
func _init(nm):
self.name = nm
tx_data.resize(BUFFER_SIZE)
tx_data.fill(0)
tick = 0.0
func process(delta: float):
tick += delta
if online and ((tick - cmd_tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
func process(delta: float):
tick += delta
if online and ((tick - cmd_tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
cmd_tick_tx = tick
cmd_state = CmdState.WAIT
cmd_retry = RETRY_COUNT
elif cmd_state == CmdState.WAIT:
if cmd_retry:
if (tick - cmd_tick_tx) > RESEND_TIMEOUT:
rc = Error.OK
cmd_tick_tx = tick
cmd_retry -= 1
else:
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
rc = Error.FAILED
return rc
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
cmd_tick_tx = tick
cmd_state = CmdState.WAIT
cmd_retry = RETRY_COUNT
elif cmd_state == CmdState.WAIT:
if cmd_retry:
if (tick - cmd_tick_tx) > RESEND_TIMEOUT:
rc = Error.OK
cmd_tick_tx = tick
cmd_retry -= 1
else:
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
rc = Error.FAILED
return rc
func send_isa(cmd_code: int, ports_data: Array) -> bool:
if (cmd_state == CmdState.WAIT) \
or (cmd_state == CmdState.SEND) \
or (cmd_state == CmdState.UNCK):
return false
if not ((cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA)):
return false
func send_isa(cmd_code: int, ports_data: Array) -> bool:
if (cmd_state == CmdState.WAIT) \
or (cmd_state == CmdState.SEND) \
or (cmd_state == CmdState.UNCK):
return false
if not ((cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA)):
return false
cmd_num_tx = (cmd_num_rx + 1) % 0xffff
cmd_num_tx = (cmd_num_rx + 1) % 0xffff
var ports_count = ports_data.size()
tx_len = ports_count * 2 + 8
tx_data.encode_u16(0, cmd_retry) # Исправление для сетевого стека "nm-callback" процессоров STM
tx_data.encode_u16(2, cmd_num_tx)
var ports_count = ports_data.size()
tx_len = ports_count * 2 + 8
tx_data.encode_u16(0, cmd_retry) # Исправление для сетевого стека "nm-callback" процессоров STM
tx_data.encode_u16(2, cmd_num_tx)
if cmd_code == CmdCode.WRITE_ISA:
ports_count /= 2
tx_data[6] = cmd_code
tx_data[7] = ports_count
if cmd_code == CmdCode.WRITE_ISA:
ports_count /= 2
tx_data[6] = cmd_code
tx_data[7] = ports_count
var i: = 0
for word in ports_data:
tx_data.encode_u16(8 + i, word)
i += 2
cmd_state = CmdState.SEND
return true
var i: = 0
for word in ports_data:
tx_data.encode_u16(8 + i, word)
i += 2
cmd_state = CmdState.SEND
return true
func send_block(cmd_code: int, block_len: int, port: Array) -> bool:
if (cmd_state == CmdState.WAIT) \
or (cmd_state == CmdState.SEND) \
or (cmd_state == CmdState.UNCK):
return false
if not ((cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK)):
return false
func send_block(cmd_code: int, block_len: int, port: Array) -> bool:
if (cmd_state == CmdState.WAIT) \
or (cmd_state == CmdState.SEND) \
or (cmd_state == CmdState.UNCK):
return false
if not ((cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK)):
return false
cmd_num_tx = (cmd_num_rx + 1) % 0xffff
cmd_num_tx = (cmd_num_rx + 1) % 0xffff
tx_len = 11
tx_data.encode_u16(0, cmd_retry) # Исправление для сетевого стека "nm-callback" процессоров STM
tx_data.encode_u16(2, cmd_num_tx)
tx_len = 11
tx_data.encode_u16(0, cmd_retry) # Исправление для сетевого стека "nm-callback" процессоров STM
tx_data.encode_u16(2, cmd_num_tx)
if cmd_code == CmdCode.WRITE_BLOCK:
block_len /= 2
tx_data[6] = cmd_code
tx_data.encode_u16(7, block_len)
if cmd_code == CmdCode.WRITE_BLOCK:
block_len /= 2
tx_data[6] = cmd_code
tx_data.encode_u16(7, block_len)
tx_data.encode_u16(9, int(port[0]))
cmd_state = CmdState.SEND
return true
## Возвращает код команды ЯУ-07.
## rx_data - Принятые данные.
## Возвращает - Код команды не найден, 0...255 - код команды.
func get_cmd_code(rx_data: PackedByteArray):
tx_data.encode_u16(9, int(port[0]))
cmd_state = CmdState.SEND
return true
## Возвращает код команды ЯУ-07.
## rx_data - Принятые данные.
## Возвращает - Код команды не найден, 0...255 - код команды.
func get_cmd_code(rx_data: PackedByteArray):
var rx_data_len = rx_data.size()
if rx_data_len < 7:
return null
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len <= (status_len + 6): # Нет поля "ответ на команду", разбор пакета завершить
return null
var cmd_code_pos = status_len + 8 # Положение в приёмном буфере "кода команды"
if rx_data_len <= cmd_code_pos:
return null
return rx_data[cmd_code_pos] # "код команды"
var rx_data_len = rx_data.size()
if rx_data_len < 7:
return null
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len <= (status_len + 6): # Нет поля "ответ на команду", разбор пакета завершить
return null
var cmd_code_pos = status_len + 8 # Положение в приёмном буфере "кода команды"
if rx_data_len <= cmd_code_pos:
return null
return rx_data[cmd_code_pos] # "код команды"
func parse_isa(rx_data: PackedByteArray, status_len) -> bool:
var ports_count_pos = status_len + 10 # Положение в приёмном буфере количества портов
if rx_data.size() < ports_count_pos:
return false
var ports_count = rx_data[ports_count_pos] # Количество портов
var counted_len = status_len + (ports_count * 4) + 11 # Вычисленная длина пакета
if rx_data.size() < counted_len:
return false
var addr_pos = status_len + 11 # Смещение положения адреса в приёмном буфере
var data_pos = status_len + 13 # Смещение положения данных в приёмном буфере
var i: = 0
while i < ports_count:
var shift: = i * 4
var isa_addr = rx_data.decode_u16(addr_pos + shift) # Адрес порта ISA яу-07
var isa_data = rx_data.decode_u16(data_pos + shift) # Данные порта ISA яу-07
isa_ports[isa_addr] = isa_data
i += 1
cmd_data = rx_data.slice(addr_pos, (addr_pos + ports_count * 4) - 1)
return i > 0
func parse_isa(rx_data: PackedByteArray, status_len) -> bool:
var ports_count_pos = status_len + 10 # Положение в приёмном буфере количества портов
if rx_data.size() < ports_count_pos:
return false
var ports_count = rx_data[ports_count_pos] # Количество портов
var counted_len = status_len + (ports_count * 4) + 11 # Вычисленная длина пакета
if rx_data.size() < counted_len:
return false
var addr_pos = status_len + 11 # Смещение положения адреса в приёмном буфере
var data_pos = status_len + 13 # Смещение положения данных в приёмном буфере
var i: = 0
while i < ports_count:
var shift: = i * 4
var isa_addr = rx_data.decode_u16(addr_pos + shift) # Адрес порта ISA яу-07
var isa_data = rx_data.decode_u16(data_pos + shift) # Данные порта ISA яу-07
isa_ports[isa_addr] = isa_data
i += 1
cmd_data = rx_data.slice(addr_pos, (addr_pos + ports_count * 4) - 1)
return i > 0
func parse_block(rx_data: PackedByteArray, status_len) -> bool:
var ports_count_pos = status_len + 7 # Положение в приёмном буфере количества портов
if rx_data.size() < ports_count_pos:
return false
var block_len = rx_data.decode_u16(ports_count_pos + 3)
var block_adr = rx_data.decode_u16(ports_count_pos + 5)
var block_data = []
for i in block_len:
var shift: int = i * 2
block_data.append(rx_data.decode_u16(ports_count_pos + 7 + shift))
isa_block[block_adr] = block_data
return true
func parse_block(rx_data: PackedByteArray, status_len) -> bool:
var ports_count_pos = status_len + 7 # Положение в приёмном буфере количества портов
if rx_data.size() < ports_count_pos:
return false
var block_len = rx_data.decode_u16(ports_count_pos + 3)
var block_adr = rx_data.decode_u16(ports_count_pos + 5)
var block_data = []
for i in block_len:
var shift: int = i * 2
block_data.append(rx_data.decode_u16(ports_count_pos + 7 + shift))
isa_block[block_adr] = block_data
return true
## Заполняет состояние прибора данными прочитанными из портов ЯУ-07.
## для команд "читать порты" или "записать порты".[br]
## [param rx_data] - Принятые данные.[br]
## Возвращает [b]true[/b] - Данные обработаны успешно.[br]
## Возвращает [b]false[/b] - Данные не обработаны из за ошибки.[br]
func parse(rx_data: PackedByteArray) -> bool:
## Заполняет состояние прибора данными прочитанными из портов ЯУ-07.
## для команд "читать порты" или "записать порты".[br]
## [param rx_data] - Принятые данные.[br]
## Возвращает [b]true[/b] - Данные обработаны успешно.[br]
## Возвращает [b]false[/b] - Данные не обработаны из за ошибки.[br]
func parse(rx_data: PackedByteArray) -> bool:
cmd_tick_rx = tick
cmd_tick_rx = tick
if not online:
online = true
emit_signal('line_changed', self)
if not online:
online = true
emit_signal('line_changed', self)
var rx_data_len = rx_data.size()
if rx_data_len < 10:
return false
var rx_data_len = rx_data.size()
if rx_data_len < 10:
return false
cmd_num_rx = rx_data.decode_u16(2)
if cmd_state == CmdState.UNCK:
cmd_state = CmdState.DONE
cmd_num_rx = rx_data.decode_u16(2)
if cmd_state == CmdState.UNCK:
cmd_state = CmdState.DONE
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len < (status_len + 6):
return false
var i: = 0
var len_rx_data: = rx_data.size()
status.resize(status_len)
while i < status_len:
var byte_i = i + 8
if byte_i < len_rx_data:
status[i] = rx_data[byte_i] # Массив байтовый "состояние прибора"
i += 1
var status_len = rx_data.decode_u16(6) # Длина массива байтового "состояние прибора"
if rx_data_len < (status_len + 6):
return false
var i: = 0
var len_rx_data: = rx_data.size()
status.resize(status_len)
while i < status_len:
var byte_i = i + 8
if byte_i < len_rx_data:
status[i] = rx_data[byte_i] # Массив байтовый "состояние прибора"
i += 1
if rx_data_len == (status_len + 6):
return true # Нет поля "ответ на команду", разбор пакета завершить
if rx_data_len == (status_len + 6):
return true # Нет поля "ответ на команду", разбор пакета завершить
var cmd_code_pos = status_len + 8 # Положение в приёмном буфере "код команды"
if rx_data_len <= cmd_code_pos:
return false
var cmd_code_pos = status_len + 8 # Положение в приёмном буфере "код команды"
if rx_data_len <= cmd_code_pos:
return false
var cmd_status_pos = status_len + 9 # Положение в приёмном буфере "состояния выполнения команды"
if rx_data_len <= cmd_status_pos:
return false
cmd_result = rx_data[cmd_status_pos]
if cmd_result != 1: # Команда не выполнена
return false
var cmd_status_pos = status_len + 9 # Положение в приёмном буфере "состояния выполнения команды"
if rx_data_len <= cmd_status_pos:
return false
cmd_result = rx_data[cmd_status_pos]
if cmd_result != 1: # Команда не выполнена
return false
var cmd_code: CmdCode = rx_data[cmd_code_pos] as CmdCode # "код команды"
var rc = true
if (cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA):
rc = parse_isa(rx_data, status_len)
var cmd_code: CmdCode = rx_data[cmd_code_pos] as CmdCode # "код команды"
var rc = true
if (cmd_code == CmdCode.READ_ISA) or (cmd_code == CmdCode.WRITE_ISA):
rc = parse_isa(rx_data, status_len)
elif (cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK):
rc = parse_block(rx_data, status_len)
elif (cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK):
rc = parse_block(rx_data, status_len)
if rc:
if (cmd_state == CmdState.WAIT) and (cmd_num_rx == cmd_num_tx):
cmd_state = CmdState.DONE
emit_signal('command_done', self)
else:
emit_signal('parse_failed', self)
return true
if rc:
if (cmd_state == CmdState.WAIT) and (cmd_num_rx == cmd_num_tx):
cmd_state = CmdState.DONE
emit_signal('command_done', self)
else:
emit_signal('parse_failed', self)
return true

View File

@@ -2,36 +2,36 @@ class_name yems_dev extends Node
class InDev:
var id: int ## Идентификатор индекс устройства.
var dev_name: String ## Имя подключаемого комплекса.
var connector: String ## Номер разъёма в приборе.
var delay: float ## Задержка фронта импульса.
var offset: float ## Смещение фронта импульса.
var state: int ## Состояние входа.
var freq: int ## Предполагаемая частота на которой работает комплекс.
var ports_data: Dictionary ## Словарь состояния портов устройства.
var tbl_row_id: int ## Индекс устройства в таблице выходов.
var out_dots: Array ## Список выходных устройств в порядке, как в таблице и точки матрицы.
var connect_devs: Dictionary ## Список присоединённых устройств.
var board: String ## Плата в которой находится устройство.
var id: int ## Идентификатор индекс устройства.
var dev_name: String ## Имя подключаемого комплекса.
var connector: String ## Номер разъёма в приборе.
var delay: float ## Задержка фронта импульса.
var offset: float ## Смещение фронта импульса.
var state: int ## Состояние входа.
var freq: int ## Предполагаемая частота на которой работает комплекс.
var ports_data: Dictionary ## Словарь состояния портов устройства.
var tbl_row_id: int ## Индекс устройства в таблице выходов.
var out_dots: Array ## Список выходных устройств в порядке, как в таблице и точки матрицы.
var connect_devs: Dictionary ## Список присоединённых устройств.
var board: String ## Плата в которой находится устройство.
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
class OutDev extends InDev:
var mode: String ## Режим работы выхода.
var mode: String ## Режим работы выхода.
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
mode = 'Работа'
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
mode = 'Работа'