Files
uarep-ctl/scripts/trassa.gd
2025-12-30 13:34:05 +03:00

281 lines
10 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 trassa_unit extends Node
const ONLINE_TIMEOUT: int = 5000 # Время ожидания данных
const REQUEST_PERIOD: int = 3000 # Период отправки, мс
const WORDS_TOTAL: int = 75
const NOINFO: int = 0x80000000
class Trassa extends unit.Unit:
static var json_conv: = JSON.new() ## Аппарат для разбора JSON сообщений
var source_addr: = []
var unit_caps = network.get_unit_instance('уарэп-капсрпб')
var tx_stack: Array[int] = []
var msg_counter: int = 0
var ecms: Dictionary = {} # Словарь всех активных помех
var srn = 0
var jtids = 0
var prinud_but: Array = []
var forced_buttons: Array = [] # Для хранения ссылок на кнопки
var json_dic: Dictionary = {} # Для хранения распарсенного JSON
var target: bool = false # Флаг наличия значения 21930
var data_type: String = "unknown" # Тип полученных данных: "json" или "binary"
var current_index: int = 0
var set_klaster = [
[390, 510, 224, 50],
[390, 1065, 250, 100],
[800, 1065, 274, 50],
[800, 1210, 300, 100],
[1065, 1210, 324, 50],
[1065, 1380, 350, 100],
[1150, 1380, 374, 50],
[1150, 2000, 400, 100],
[1380, 2000, 424, 50],
[1380, 3500, 450, 100],
[2000, 3500, 474, 50],
[2000, 6000, 500, 100],
[3500, 6000, 524, 50],
[390, 6000, 374, 50*7]]
var lfb = 0
var hfb = 0
var dap = 0
var daa = 0
# Инициализация
func _init(nm: StringName, buttons: Array = []) -> void:
self.name = nm
self.forced_buttons = buttons
tx_stack.resize(WORDS_TOTAL)
tx_stack.fill(NOINFO)
interfer.connect('interfer_resized', Callable(self, 'on_interfer_resized'))
# Обработка полученного пакета - определение типа
func parse(rx_data: PackedByteArray, tick: int):
rx_tick = tick
if not online:
online = true
emit_signal('line_changed', self)
data_type = detect_data(rx_data)
if data_type == 'json':
parse_json(rx_data)
elif data_type == 'binary':
parse_byte(rx_data)
else:
emit_signal('parse_failed', self)
# Определение типа данных
func detect_data(data: PackedByteArray) -> String:
if data.size() > 0:
var first_char = data[0]
if first_char == 123 or first_char == 91:
return "json"
if data.size() >= 2:
var potential_json = data.slice(0, min(100, data.size()))
var test_string = potential_json.get_string_from_ascii()
if test_string and (test_string.begins_with("{") or test_string.begins_with("[")):
return "json"
return "binary"
# Обработка JSON данных
func parse_json(rx_data: PackedByteArray) -> void:
var json_string = rx_data.get_string_from_utf8()
if json_string:
if Error.OK == json_conv.parse(json_string):
json_dic = json_conv.get_data()
target = check_target(json_dic)
sector_draw(json_dic)
emit_signal('data_received', self)
else:
emit_signal('parse_failed', self)
else:
emit_signal('parse_failed', self)
func sector_draw(data: Dictionary) -> void:
var sector_data = {
"draw": false,
"color": Color.GREEN * Color(1, 1, 1, 0.1),
"rect": Rect2(),
"index": 0 }
if data.get("clean_all", false) == true:
current_index = 0
signaller.emit_signal('clear_klaster')
return
if data.has("txe") and data.has("rxe"):
var txe = data["txe"]
var rxe = data["rxe"]
if txe == true or rxe == true:
sector_data["draw"] = true
if data.has("lfb") and data.has("hfb") and data.has("dap") and data.has("daa"):
lfb = int(data["lfb"])
hfb = int(data["hfb"])
dap = int(data["dap"])
daa = int(data["daa"])
for i in range(set_klaster.size()):
var mapping = set_klaster[i]
if lfb == mapping[0] and hfb == mapping[1]:
lfb = mapping[2]
hfb = mapping[3]
break
sector_data["rect"] = Rect2(lfb, daa, dap, hfb)
sector_data["index"] = sector_index()
signaller.emit_signal('sector_klaster', sector_data)
func sector_index() -> int:
current_index += 1
return current_index - 1
# Обработка бинарных данных
func parse_byte(rx_data: PackedByteArray):
var words: Array[int] = []
var offset: int = 0
if rx_data.size() < 40:
emit_signal('parse_failed', self)
return
while offset < rx_data.size():
if offset + 4 <= rx_data.size():
var word = rx_data.decode_u32(offset)
words.append(word)
offset += 4
else:
break
if words.size() < 10:
emit_signal('parse_failed', self)
return
tx_stack.fill(NOINFO)
tx_stack[0] = words[0] # ID
tx_stack[1] = msg_counter # Nc
tx_stack[2] = 0x01 # Nб
tx_stack[3] = 0x00 # Ск
tx_stack[4] = 0x0194 # НТС
tx_stack[5] = (0x0001 << 16) | 0x0080 # Ии
tx_stack[6] = 0x01 # РКС
srn = words[7] # SRN
jtids = words[8] # JTIDS
btn_trassa_pressed()
interfer_data()
tx_stack[74] = _calc_crc(tx_stack)
emit_signal("data_received", self)
# Проверка на нужный JSON файл
func check_target(data, current_path: String = "root") -> bool:
if data == null:
return false
if data is int or data is float:
if int(data) == 21930:
return true
return false
var found = false
if data is Dictionary:
for key in data:
var new_path = current_path + "." + str(key)
if check_target(data[key], new_path):
found = true
elif data is Array:
for i in range(data.size()):
var new_path = current_path + "[" + str(i) + "]"
if check_target(data[i], new_path):
found = true
return found
func interfer_data() -> void:
for i in range(67, 74):
tx_stack[i] = 0
for ecm in ecms.values():
if ecm.svk == 1:
var nmfs_value = ecm.nmfs
var fs_key = get_fs_key(nmfs_value)
if fs_key != NOINFO:
var string_index = fs_key / 4
var bit_position = fs_key % 4
if string_index >= 0 and string_index < 7:
var target_string = 67 + string_index
tx_stack[target_string] |= (1 << bit_position)
func get_fs_key(nmfs_value: int) -> int:
if prd.fs_caps_id.has(nmfs_value):
return prd.fs_caps_id[nmfs_value]
return NOINFO
# Отправка пакета от uarep-ctl
func process(now_tick: int) -> int:
if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if (now_tick - tx_tick) > REQUEST_PERIOD:
tx_tick = now_tick
msg_counter += 1
interfer_uarep()
interfer_data()
var data = PackedByteArray()
data.resize(WORDS_TOTAL * 4)
for i in range(WORDS_TOTAL):
data.encode_u32(i * 4, tx_stack[i])
tx_data = data
tx_len = WORDS_TOTAL * 4
return Error.OK
return Error.ERR_BUSY
# Контрольная сумма
func _calc_crc(data: Array) -> int:
var acc: int = 0
for i in range(data.size() - 1): # кроме CRC
if i in [0, 1]:
continue
acc = (acc + (data[i] & 0xFFFFFFFF)) & 0xFFFFFFFF
return acc
# Обновление всех активных помех
func on_interfer_resized(ecms_dic: Dictionary) -> void: ecms = ecms_dic
func interfer_uarep() -> void:
tx_stack[65] = 0
tx_stack[66] = 0
for ecm in ecms.values():
if ecm.krp == 'srni1' and ecm.svk == 1:
tx_stack[65] = 1
if ecm.krp == 'svi1' and ecm.svk == 1:
tx_stack[66] = 1
tx_stack[1] = msg_counter
# Выполнение указаний по кнопке Трасса
func btn_trassa_pressed() -> void:
var state = ProjectSettings.get_setting('application/config/Внешнее указание Трасса', false)
if state == true:
var tree: SceneTree = Engine.get_main_loop()
if tree is SceneTree:
var nodes: Array = tree.get_nodes_in_group('группа-принудительно')
for btn in nodes:
if btn.name == 'btn_srn':
btn.pressed = (srn == 1)
elif btn.name == 'btn_jtids':
btn.pressed = (jtids == 1)
if srn == 1:
tx_stack[65] = 1
signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.srn_sectors)
else:
tx_stack[65] = 0
for ecm in ecms.values():
if ecm.krp == "srni1" and ecm.svk == 1:
signaller.emit_signal('interfer_off', ecm)
if jtids == 1:
tx_stack[66] = 1
signaller.emit_signal('interfer_prinuditelno', frm_ecm_list.jtids_sectors)
else:
tx_stack[66] = 0
for ecm in ecms.values():
if ecm.krp == 'svi1' and ecm.svk == 1:
signaller.emit_signal('interfer_off', ecm)