Compare commits

...

6 Commits

Author SHA1 Message Date
TotMaxim
1633a45c9b Доработка статуса контроля РТР
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 14:24:05 +03:00
TotMaxim
65a0164ec0 Доработка контроля РТР БПО 2026-04-09 13:14:07 +03:00
TotMaxim
0c30572f1e Доработка АФСП провекри 2026-04-09 11:25:18 +03:00
TotMaxim
08597ff7ce Merge remote-tracking branch 'origin/master' 2026-04-09 09:59:08 +03:00
TotMaxim
8abdc957ed Merge remote-tracking branch 'origin/master'
Some checks failed
Локальный тест / test (push) Has been cancelled
2026-04-09 09:58:04 +03:00
TotMaxim
85b2f4eadd Доработка адресов ЭМС ТГ и флага изменнена пользователем частоты 2026-04-09 09:55:57 +03:00
9 changed files with 488 additions and 246 deletions

View File

@@ -20,8 +20,8 @@ script_export_mode=0
[preset.0.options]
custom_template/debug=""
custom_template/release=""
custom_template/debug="/home/user/temp/godot.linuxbsd.template_release.x86_64"
custom_template/release="/home/user/temp/godot.linuxbsd.template_release.x86_64"
debug/export_console_wrapper=0
binary_format/embed_pck=true
texture_format/s3tc_bptc=true

View File

@@ -97,8 +97,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 2"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[1].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[1]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[1]['TestPassed']"]
@@ -122,8 +122,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 3"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[2].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[2]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[2]['TestPassed']"]
@@ -147,8 +147,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 4"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[3].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[3]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[3]['TestPassed']"]
@@ -172,8 +172,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 5"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[4].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[4]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[4]['TestPassed']"]
@@ -197,8 +197,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 6"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[5].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[5]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[5]['TestPassed']"]
@@ -222,8 +222,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 7"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[6].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[6]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[6]['TestPassed']"]
@@ -247,8 +247,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Канал 8"
metadata/value0 = "SelfTest[1].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[1].DevList[7].TestedParamList[0]['CurrentValue']"
metadata/value2 = "SelfTest[0].SystemList[1].DevList[7]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[1].DevList[7]['TestPassed']"]
@@ -800,7 +800,7 @@ offset_right = 580.0
offset_bottom = 115.0
tooltip_text = "Плата АЦП ADCS500"
fname = "АЦП"
metadata/state = ["SelfTest[4].SystemList[0].DevList[1]['TestPassed']"]
metadata/state = ["SelfTest[0].SystemList[0].DevList[1]['TestPassed']"]
[node name="dsp" parent="." instance=ExtResource("4_mtf2n")]
layout_mode = 0
@@ -809,7 +809,7 @@ offset_right = 580.0
offset_bottom = 60.0
tooltip_text = "Плата цифровой обработки сигналов BPL"
fname = "Сигн. проц."
metadata/state = ["SelfTest[4].SystemList[0].DevList[0]['TestPassed']"]
metadata/state = ["SelfTest[0].SystemList[0].DevList[0]['TestPassed']"]
[node name="gen" parent="." instance=ExtResource("2_dmhrm")]
layout_mode = 2
@@ -827,8 +827,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Генератор"
metadata/value0 = "SelfTest[1].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[2].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value0 = "SelfTest[0].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/value1 = "SelfTest[0].SystemList[2].DevList[0].TestedParamList[0]['CurrentValue']"
metadata/state = ["SelfTest[0].SystemList[2].DevList[0]['TestPassed']"]
[node name="rpu" parent="." instance=ExtResource("2_dmhrm")]
@@ -848,8 +848,8 @@ name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
name_min_size2 = Vector2i(35, 20)
fname = "Приёмник 20...1000 МГц"
metadata/value0 = "SelfTest[1].SystemList[0].DevList[0]['TestPassed']"
metadata/value1 = "SelfTest[2].SystemList[0].DevList[0]['TestPassed']"
metadata/value0 = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']"
metadata/value1 = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']"
metadata/state = ["SelfTest[0].SystemList[0].DevList[3]['TestPassed']"]
[connection signal="pressed" from="konverter/grid/kanal1" to="." method="_on_item_pressed"]

View File

@@ -16,9 +16,9 @@ var ctrl_pos = 0
func _ready() -> void:
# Подключаемся к сигналам в зависимости от борта
if this_afsp_name == 'Устройство РР левого борта':
scouting.response_received_left.connect(_on_response_received)
scouting.response_received_afsp_left.connect(_on_response_received)
else:
scouting.response_received_right.connect(_on_response_received)
scouting.response_received_afsp_right.connect(_on_response_received)
# При старте отрисовываем последние данные (если есть)
_on_press_device()
@@ -124,13 +124,11 @@ func _on_press_device() -> void:
var last_response = ""
if this_afsp_name == 'Устройство РР левого борта':
has_data = scouting.has_left_success()
if has_data:
last_response = scouting.get_left_response()
has_data = scouting.has_afsp_left_success()
if has_data: last_response = scouting.get_afsp_left_response()
else:
has_data = scouting.has_right_success()
if has_data:
last_response = scouting.get_right_response()
has_data = scouting.has_afsp_right_success()
if has_data: last_response = scouting.get_afsp_right_response()
# Если есть данные - парсим и отображаем
if has_data and not last_response.is_empty():

View File

@@ -4,64 +4,53 @@ class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd'
@export var prefix_path: String = '' ## Должно быть в JSON
@export var this_bpo1_name: String = '' ## Должно быть в JSON
@export var this_bpo2_name: String = '' ## Должно быть в JSON
@export var unit_name1: StringName= '' ## Должно быть в settings.gd
@export var unit_name2: StringName= '' ## Должно быть в settings.gd
@export var unit_name1: StringName = '' ## Должно быть в settings.gd
@export var unit_name2: StringName = '' ## Должно быть в settings.gd
@export var settings_path1_to_url: String = '' ## Должно быть в ProjectSettings
@export var settings_path2_to_url: String = '' ## Должно быть в ProjectSettings
@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings
signal receive_response_afp_bpo()
static var json_conv: JSON = JSON.new()
static var node_maper = load('res://scenes/контроль/node-maper.gd')
static var node_request_1: Node
static var node_request_timer_1: Node
static var node_request_2: Node
static var node_request_timer_2: Node
var ctrl_pos = 110
var bort_to_node_name = {}
var bort_to_unit_name = {}
func _ready() -> void:
ProjectSettings.connect('settings_changed', on_settings_changed)
node_request_1 = $request1
node_request_timer_1 = $request1/timer
node_request_2 = $request2
node_request_timer_2 = $request2/timer
scouting.response_received_bpo_left.connect(_on_response_received_left)
scouting.response_received_bpo_right.connect(_on_response_received_right)
on_settings_changed()
find_labels(self)
_on_press_device()
func on_settings_changed():
bort_to_node_name.merge({this_bpo1_name: 'grid_bpo_a1', this_bpo2_name: 'grid_bpo_a2'}, true)
bort_to_unit_name.merge({this_bpo1_name: unit_name1, this_bpo2_name: unit_name2})
node_request_1.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path1_to_url)
node_request_timer_1.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
node_request_2.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path2_to_url)
node_request_timer_2.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
assert(node_request_1.request_url != null)
assert(node_request_2.request_url != null)
bort_to_unit_name.merge({this_bpo1_name: unit_name1, this_bpo2_name: unit_name2}, true)
func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
if result != 0:
var rs = node_request_1.get_result_string(result)
push_error('\"%s\"' % rs)
# Обработка ответа от первого бпо
func _on_response_received_left(response: String, success: bool) -> void:
if not success:
log.error('Ошибка запроса или нет связи (левый): %s' % response)
_reset_grid('grid_bpo_a1')
return
_parse_and_update_ui(response)
var json_str: = body.get_string_from_utf8()
if not json_str:
push_error('не удаётся получить строку из utf8-данных (%s)' % headers)
# Обработка ответа от второго бпо
func _on_response_received_right(response: String, success: bool) -> void:
if not success:
log.error('Ошибка запроса или нет связи (правый): %s' % response)
_reset_grid('grid_bpo_a2')
return
_parse_and_update_ui(response)
# Оригинальный парсинг из _on_request_completed
func _parse_and_update_ui(json_str: String) -> void:
var rc: = json_conv.parse(json_str)
if rc != Error.OK:
var err = json_conv.get_error_message()
push_error('разбор json прерван - \"%s\" (%s)' % [err, headers])
push_error('разбор json прерван - %s' % err)
return
var pp: = []
@@ -69,45 +58,96 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra
var ret_val = [null, false, 0]
var pp_copy = pp.duplicate(true)
tools.get_value_by_path(json_conv.data, pp, ret_val)
if not ret_val[1]:
push_error('путь %s не найден (%s)' % [pp_copy, ret_val[2]])
return
if not bort_to_node_name.has(ret_val[0]):
push_error('не известное устройство: \"%s\"' % ret_val[0])
var device_name: String = ret_val[0]
if not bort_to_node_name.has(device_name):
push_error('не известное устройство: %s' % device_name)
return
var node_name = bort_to_node_name[ret_val[0]]
var node_name = bort_to_node_name[device_name]
var bort_node = get_node(node_name)
var unit_name = bort_to_unit_name[ret_val[0]]
var unit_instance = network.get_unit_instance(unit_name)
unit_instance.rx_tick = Time.get_ticks_msec()
if not unit_instance.online:
unit_instance.online = true
unit_instance.emit_signal('line_changed', unit_instance)
# Обновляем UI только для конкретного грида
for item in bort_node.get_children():
node_maper.map_value_to_item(json_conv.data, item, 'state')
# Обновляем групповые индикаторы
_update_group_indicators_original()
# Оригинальное обновление групповых индикаторов
func _update_group_indicators_original() -> void:
# Сначала сбрасываем все
if has_node('yas_bpo_a1'):
$yas_bpo_a1.state = 0
if has_node('yas_bpo_a2'):
$yas_bpo_a2.state = 0
if has_node('mod_pit_g1'):
$mod_pit_g1.state = 0
# Проверяем обе группы и устанавливаем если есть активные
var items = get_tree().get_nodes_in_group('управляется-по-шине-1')
for node in items:
if node.state == 1:
$yas_bpo_a1.state = 1
if node.has_method('get') and node.get('state') == 1:
if has_node('yas_bpo_a1'):
$yas_bpo_a1.state = 1
break
items = get_tree().get_nodes_in_group('управляется-по-шине-2')
for node in items:
if node.state == 1:
$yas_bpo_a2.state = 1
if node.has_method('get') and node.get('state') == 1:
if has_node('yas_bpo_a2'):
$yas_bpo_a2.state = 1
break
items = get_tree().get_nodes_in_group('потребитель-питания')
for node in items:
if node.state == 1:
$mod_pit_g1.state = 1
if node.has_method('get') and node.get('state') == 1:
if has_node('mod_pit_g1'):
$mod_pit_g1.state = 1
break
emit_signal('receive_response_afp_bpo')
# Сброс конкретного грида
func _reset_grid(grid_name: String) -> void:
if has_node(grid_name):
for item in get_node(grid_name).get_children():
_reset_item_value(item)
_update_group_indicators_original()
# Сброс всех UI элементов в 0 (при отсутствии данных)
func _reset_ui_to_zero() -> void:
_reset_grid('grid_bpo_a1')
_reset_grid('grid_bpo_a2')
# Сброс конкретного элемента в 0
func _reset_item_value(item) -> void:
if item.has_method('set'):
item.set('value0', 0)
item.set('value1', 0)
item.set('value2', 0)
item.set('state', 0)
# Отрисовывание при нажатии на прибор
func _on_press_device() -> void:
# Проверяем левый борт
if scouting.has_bpo_left_success():
var response = scouting.get_bpo_left_response()
if not response.is_empty():
_parse_and_update_ui(response)
else:
_reset_grid('grid_bpo_a1')
# Проверяем правый борт
if scouting.has_bpo_right_success():
var response = scouting.get_bpo_right_response()
if not response.is_empty():
_parse_and_update_ui(response)
else:
_reset_grid('grid_bpo_a2')
func find_labels(node1: Node):
if node1 is Label:
@@ -123,3 +163,9 @@ func find_labels(node1: Node):
node1.set_meta('tooltip_set', true)
for child in node1.get_children():
find_labels(child)
## Вызывается при клике мыши на элементе.
func _on_item_pressed(block_a: Control):
var metas = block_a.get_meta_list()
for n in metas:
var _v = block_a.get_meta(n)

View File

@@ -1,9 +1,8 @@
[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqea"]
[gd_scene load_steps=4 format=3 uid="uid://5uv1idl3lqea"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrk" path="res://scenes/pribor-afsp/pribor-bpo.gd" id="1_bhc4e"]
[ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_jp6m0"]
[ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_jcpjs"]
[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="4_crej3"]
[node name="pribor_bpo" type="Control"]
layout_mode = 3
@@ -198,22 +197,3 @@ offset_bottom = 362.0
show_rname = false
self_size = Vector2i(50, 145)
fname = "Яч. связи"
[node name="request1" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("4_crej3")
[node name="timer" type="Timer" parent="request1"]
autostart = true
[node name="request2" type="HTTPRequest" parent="."]
use_threads = true
script = ExtResource("4_crej3")
[node name="timer" type="Timer" parent="request2"]
autostart = true
[connection signal="request_completed" from="request1" to="." method="_on_request_completed"]
[connection signal="timeout" from="request1/timer" to="request1" method="_on_request_timer"]
[connection signal="request_completed" from="request2" to="." method="_on_request_completed"]
[connection signal="timeout" from="request2/timer" to="request2" method="_on_request_timer"]

View File

@@ -40,8 +40,7 @@ static func map_error_codes_to_item(data, item, value_name: StringName, value_in
# Плавное обновление с анимацией
static func map_value_to_item_animated(data, item, value_name: StringName):
var meta = item.get_meta(value_name, '')
if meta == '' or not (meta is String):
return
if meta == '' or not (meta is String): return
var paths: = Array()
tools.map_solid_to_array(meta, paths)
@@ -55,8 +54,7 @@ static func map_value_to_item_animated(data, item, value_name: StringName):
static func map_error_codes_to_item_animated(data, item, value_name: StringName, value_init: int):
var metas = item.get_meta(value_name, '')
if not (metas is Array):
return
if not (metas is Array): return
var paths: = Array()
var values: = Array()
@@ -79,8 +77,8 @@ static func map_error_codes_to_item_animated(data, item, value_name: StringName,
static func _animate_property(item, property: StringName, target_value):
var current = item.get(property)
if current == target_value:
return
if typeof(current) != typeof(target_value): return
if current == target_value: return
# Исправление: преобразуем StringName в String для NodePath
var tween = item.create_tween()

View File

@@ -123,8 +123,15 @@ func _ready():
signaller.conn(signaller.режим_настройки, on_mode_changed)
signaller.conn(signaller.режим_эмс, on_mode_changed)
signaller.connect('debag_control_pressed', Callable(self, 'on_debag_button_pressed'))
scouting.request_sent_left.connect(_on_request_sent_left.bind($pribor_afsp_1))
scouting.response_received_left.connect(_on_response_received.bind($pribor_afsp_1))
scouting.request_sent_afsp_left.connect(_on_request_sent_left.bind($pribor_afsp_1))
scouting.response_received_afsp_left.connect(_on_response_received.bind($pribor_afsp_1))
scouting.request_sent_afsp_right.connect(_on_request_sent_left.bind($pribor_afsp_2))
scouting.response_received_afsp_right.connect(_on_response_received.bind($pribor_afsp_2))
scouting.request_sent_bpo_left.connect(_on_request_sent_left.bind($pribor_rtr))
scouting.response_received_bpo_left.connect(_on_response_received.bind($pribor_rtr))
scouting.serviceability_rtr_afsp_left.connect(on_serviceability_rtr.bind($pribor_afsp_1))
scouting.serviceability_rtr_afsp_right.connect(on_serviceability_rtr.bind($pribor_afsp_2))
scouting.serviceability_rtr_bpo.connect(on_serviceability_rtr.bind($pribor_rtr))
func online_change_arr(_u, conn_node, pribor_meta):
@@ -170,7 +177,7 @@ func on_pribor_press(pribor_path, header_text, pribor_node):
update_pribor_items_visibility()
# Вызов при отправке запроса на селфтест АФСП
# Вызов при отправке запроса на селфтест АФСП и РТР
func _on_request_sent_left(_url: String, node: Node) -> void:
node.progress_max_value = 100
node.progress_value = 0
@@ -192,6 +199,10 @@ func on_update_uf_serviceability(uf_serviceaability: int, uf_pribor: Node) -> vo
uf_pribor.state = uf_serviceaability
func on_serviceability_rtr(state: int, node_rtr: Node)-> void:
node_rtr.state = state
func _on_chk_show_functional_toggled(toggled_on: bool) -> void:
if cur_pribor_node:
cur_pribor_node.show_functional = toggled_on

View File

@@ -136,6 +136,7 @@ class Interfer:
var nmfs: int = 0 ## Номер модуля ФС в нумерации СТЦ
var priority: int = 0 ## Приоритет помехи
var active: bool = false ## Флаг, что фиксируется мощность на выходном усилителе
var freq_change = false ## Флаг, что частота изменнена пользователем
func _to_string() -> String:
return 'номер: %d название: %s частота: %0.1f МГц пеленг: %0.1f гр.' % [ispp, ITERFER_MODE[krp][0], params['freq'], kni]
@@ -174,6 +175,8 @@ class Interfer:
params[value_key] = value
else:
self.set(value_key, value)
if value_key == 'freq':
freq_change = true
signal interfer_preparing(ecm: Interfer) ## Вызывается в момент запуска помехи.
signal interfer_run(ecm: Interfer) ## Вызывается в момент начала работы помехи.
@@ -541,7 +544,8 @@ func call_diap(ecm, ecm_params: Dictionary):
var band = fs_index_arr[0] / 4
if ecm_params['files'].has(band):
ecm.params['filename'] = ecm_params['files'][band][0]
ecm.params['freq'] = ecm_params['files'][band][1]
if not ecm.freq_change:
ecm.params['freq'] = ecm_params['files'][band][1]
func call_pdchm(ecm, ecm_params: Dictionary):

View File

@@ -2,22 +2,36 @@ class_name rtr
extends Node
#region Перечисления
enum State { IDLE, REQUESTING_LEFT, REQUESTING_RIGHT, WAITING_TIMEOUT }
enum State {
IDLE,
REQUESTING_AFSP_LEFT,
REQUESTING_AFSP_RIGHT,
REQUESTING_BPO_LEFT,
REQUESTING_BPO_RIGHT,
WAITING_TIMEOUT
}
#endregion
#region Сигналы
# Сигналы отправки запроса
signal request_sent_left(url: String) # Отправлен запрос к левому борту
signal request_sent_right(url: String) # Отправлен запрос к правому борту
signal request_sent_afsp_left(url: String)
signal request_sent_afsp_right(url: String)
signal request_sent_bpo_left(url: String)
signal request_sent_bpo_right(url: String)
# Сигналы получения ответа
signal response_received_left(response: String, success: bool) # Получен ответ от левого борта
signal response_received_right(response: String, success: bool) # Получен ответ от правого борта
signal response_received_afsp_left(response: String, success: bool)
signal response_received_afsp_right(response: String, success: bool)
signal response_received_bpo_left(response: String, success: bool)
signal response_received_bpo_right(response: String, success: bool)
# Сигналы исправности (0 - нет связи, 1 - всё пройдено, 2 - есть ошибки)
signal serviceability_rtr_afsp_left(state: int)
signal serviceability_rtr_afsp_right(state: int)
signal serviceability_rtr_bpo(state: int) # Общий для левого и правого БПО
#endregion
#region Константы
# Словарь с текстовым описанием кодов результатов HTTP запросов
const RESULT_STRINGS = {
HTTPRequest.Result.RESULT_SUCCESS: 'Запрос успешен',
HTTPRequest.Result.RESULT_CHUNKED_BODY_SIZE_MISMATCH: 'Несоответствие размеров частей сообщения',
@@ -37,140 +51,184 @@ const RESULT_STRINGS = {
#endregion
#region Переменные
var http_request: HTTPRequest # HTTP клиент для выполнения запросов
var addresses: Dictionary # Словарь с URL адресами устройств
var current_state: State = State.IDLE # Текущее состояние машины состояний
var current_url: String = '' # Текущий URL для запроса
var timeout_timer: Timer # Таймер ожидания ответа (30 секунд)
var http_request: HTTPRequest
var addresses: Dictionary
var current_state: State = State.IDLE
var current_url: String = ''
var timeout_timer: Timer
# Результаты запросов
var last_response_left: String = '' # Последний успешный ответ левого борта
var last_response_right: String = '' # Последний успешный ответ правого борта
var last_error_left: String = '' # Последняя ошибка левого борта
var last_error_right: String = '' # Последняя ошибка правого борта
# Результаты запросов АФСП
var last_response_afsp_left: String = ''
var last_response_afsp_right: String = ''
var last_error_afsp_left: String = ''
var last_error_afsp_right: String = ''
# Результаты запросов БПО
var last_response_bpo_left: String = ''
var last_response_bpo_right: String = ''
var last_error_bpo_left: String = ''
var last_error_bpo_right: String = ''
# Статус online для каждого борта
var online_left: bool = false
var online_right: bool = false
var online_afsp_left: bool = false
var online_afsp_right: bool = false
var online_bpo_left: bool = false
var online_bpo_right: bool = false
# Время последнего успешного ответа
var last_success_time_left: int = 0
var last_success_time_right: int = 0
# Состояния исправности для БПО
var bpo_left_state: int = 0 # 0 - нет связи, 1 - успешно, 2 - ошибка
var bpo_right_state: int = 0
var last_success_time_afsp_left: int = 0
var last_success_time_afsp_right: int = 0
var last_success_time_bpo_left: int = 0
var last_success_time_bpo_right: int = 0
var timeout: float
var current_device_type: String = ''
#endregion
#region Инициализация
func _ready() -> void:
# Создаем и настраиваем HTTP клиент
http_request = HTTPRequest.new()
add_child(http_request)
http_request.request_completed.connect(_on_request_completed)
# Создаем и настраиваем таймер для обработки таймаутов
timeout_timer = Timer.new()
add_child(timeout_timer)
timeout_timer.timeout.connect(_on_timeout)
timeout_timer.one_shot = true
# Подписываемся на сигнал запуска управления устройством
signaller.conn(signaller.start_contol_device, Callable(self, '_on_start_contol_device'))
#endregion
#region Публичные методы
# Возвращает текстовое описание кода результата HTTP запроса
func get_result_string(result: int) -> String:
return RESULT_STRINGS.get(result, '<неизвестный код результата HTTPRequest - %d>' % result)
# Геттеры для получения результатов запросов
func get_left_response() -> String:
return last_response_left
# Геттеры АФСП
func get_afsp_left_response() -> String:
return last_response_afsp_left
func get_right_response() -> String:
return last_response_right
func get_afsp_right_response() -> String:
return last_response_afsp_right
func get_left_error() -> String:
return last_error_left
func get_afsp_left_error() -> String:
return last_error_afsp_left
func get_right_error() -> String:
return last_error_right
func get_afsp_right_error() -> String:
return last_error_afsp_right
# Проверка успешности запросов
func has_left_success() -> bool:
return not last_response_left.is_empty()
func has_afsp_left_success() -> bool:
return not last_response_afsp_left.is_empty()
func has_right_success() -> bool:
return not last_response_right.is_empty()
func has_afsp_right_success() -> bool:
return not last_response_afsp_right.is_empty()
# Геттеры для статуса online
func is_left_online() -> bool:
return online_left
func is_afsp_left_online() -> bool:
return online_afsp_left
func is_right_online() -> bool:
return online_right
func is_afsp_right_online() -> bool:
return online_afsp_right
# Геттеры БПО
func get_bpo_left_response() -> String:
return last_response_bpo_left
func get_bpo_right_response() -> String:
return last_response_bpo_right
func get_bpo_left_error() -> String:
return last_error_bpo_left
func get_bpo_right_error() -> String:
return last_error_bpo_right
func has_bpo_left_success() -> bool:
return not last_response_bpo_left.is_empty()
func has_bpo_right_success() -> bool:
return not last_response_bpo_right.is_empty()
func is_bpo_left_online() -> bool:
return online_bpo_left
func is_bpo_right_online() -> bool:
return online_bpo_right
# Обновление статуса online
func _update_online_status(side: String, is_online: bool) -> void:
var unit_instance
func _update_online_status(device: String, side: String, is_online: bool) -> void:
var unit_name = ''
if device == 'afsp':
unit_name = 'уарэп-афсп-' + ('левый' if side == 'left' else 'правый')
else:
unit_name = 'уарэп-бпо-' + ('1' if side == 'left' else '2')
# Выбираем нужный экземпляр в зависимости от борта
if side == "left":
unit_instance = network.get_unit_instance('уарэп-афсп-левый')
else: # side == "right"
unit_instance = network.get_unit_instance('уарэп-афсп-правый')
# Обновляем статус если изменился
if unit_instance and unit_instance.online != is_online:
unit_instance.online = is_online
unit_instance.emit_signal('line_changed', unit_instance)
var unit_instance = network.get_unit_instance(unit_name)
if unit_instance:
unit_instance.rx_tick = Time.get_ticks_msec()
if unit_instance.online != is_online:
unit_instance.online = is_online
unit_instance.emit_signal('line_changed', unit_instance)
#endregion
#region Обработчики сигналов
# Сигнал от signaller - начало управления устройством
func _on_start_contol_device() -> void:
# Если уже выполняется запрос - игнорируем
if current_state != State.IDLE:
return
# Сбрасываем предыдущие результаты
last_response_left = ''
last_response_right = ''
last_error_left = ''
last_error_right = ''
last_response_afsp_left = ''
last_response_afsp_right = ''
last_error_afsp_left = ''
last_error_afsp_right = ''
last_response_bpo_left = ''
last_response_bpo_right = ''
last_error_bpo_left = ''
last_error_bpo_right = ''
bpo_left_state = 0
bpo_right_state = 0
# Загружаем URL адреса из ProjectSettings
addresses['Адрес АФСП левого борта'] = ProjectSettings.get_setting('application/config/%s' % 'Адрес АФСП левого борта')
addresses['Адрес АФСП правого борта'] = ProjectSettings.get_setting('application/config/%s' % 'Адрес АФСП правого борта')
addresses['Адрес БПО левого борта'] = ProjectSettings.get_setting('application/config/%s' % 'Адрес БПО левого борта')
addresses['Адрес БПО правого борта'] = ProjectSettings.get_setting('application/config/%s' % 'Адрес БПО правого борта')
timeout = float(ProjectSettings.get_setting('application/config/%s' % 'Период опроса состояния АФСП, секунды'))
# Начинаем с запроса к левому борту
_request_next(State.REQUESTING_LEFT)
# Начинаем с запроса к АФСП левого борта
_request_next(State.REQUESTING_AFSP_LEFT)
# Сигнал от HTTPRequest - получен ответ на запрос
func _on_request_completed(result: int, response_code: int, _headers: PackedStringArray, body: PackedByteArray) -> void:
# Если таймаут уже сработал - игнорируем ответ
if current_state == State.WAITING_TIMEOUT:
return
# Останавливаем таймер ожидания
timeout_timer.stop()
var is_left = (current_state == State.REQUESTING_LEFT)
var current_time = Time.get_ticks_msec()
var is_afsp = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_AFSP_RIGHT)
var is_left = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_BPO_LEFT)
var side_str = 'left' if is_left else 'right'
var device_str = 'afsp' if is_afsp else 'bpo'
# Проверяем успешность ответа
if response_code == 200:
var response_text = body.get_string_from_utf8()
_save_response(response_text)
# Обновляем статус online
if is_left:
last_success_time_left = current_time
_update_online_status("left", true)
emit_signal('response_received_left', response_text, true)
var test_passed_all = _check_all_tests_passed(response_text)
_update_success_time(device_str, side_str, current_time)
_update_online_status(device_str, side_str, true)
_emit_response_signal(device_str, side_str, response_text, true)
var serviceability_state = 1 if test_passed_all else 2
if is_afsp:
_emit_afsp_serviceability_signal(side_str, serviceability_state)
else:
last_success_time_right = current_time
_update_online_status("right", true)
emit_signal('response_received_right', response_text, true)
_update_bpo_state(side_str, serviceability_state)
_emit_bpo_serviceability_signal()
_on_request_finished()
else:
@@ -178,77 +236,189 @@ func _on_request_completed(result: int, response_code: int, _headers: PackedStri
print_debug(error_msg)
_save_error(error_msg)
# Обновляем статус online (ошибка)
if is_left:
_update_online_status("left", false)
emit_signal('response_received_left', error_msg, false)
_update_online_status(device_str, side_str, false)
_emit_response_signal(device_str, side_str, error_msg, false)
if is_afsp:
_emit_afsp_serviceability_signal(side_str, 0)
else:
_update_online_status("right", false)
emit_signal('response_received_right', error_msg, false)
_update_bpo_state(side_str, 0)
_emit_bpo_serviceability_signal()
_on_request_finished()
# Сигнал от таймера - истекло время ожидания ответа
func _update_bpo_state(side: String, state: int) -> void:
if side == 'left':
bpo_left_state = state
else:
bpo_right_state = state
func _calculate_bpo_combined_state() -> int:
# Если оба не на связи -> 0
if bpo_left_state == 0 and bpo_right_state == 0:
return 0
# Если хоть один с ошибкой -> 2
if bpo_left_state == 2 or bpo_right_state == 2:
return 2
# Если один не на связи (0), а другой успешно (1) -> 1
if (bpo_left_state == 0 and bpo_right_state == 1) or (bpo_left_state == 1 and bpo_right_state == 0):
return 1
# Оба успешно -> 1
if bpo_left_state == 1 and bpo_right_state == 1:
return 1
# По умолчанию
return 0
func _emit_bpo_serviceability_signal() -> void:
var combined_state = _calculate_bpo_combined_state()
emit_signal('serviceability_rtr_bpo', combined_state)
func _state_to_string(state: int) -> String:
match state:
0: return 'нет связи'
1: return 'успешно'
2: return 'ошибка'
return 'неизвестно'
func _emit_afsp_serviceability_signal(side: String, state: int) -> void:
if side == 'left':
emit_signal('serviceability_rtr_afsp_left', state)
else:
emit_signal('serviceability_rtr_afsp_right', state)
func _check_all_tests_passed(response_text: String) -> bool:
var json = JSON.new()
if json.parse(response_text) != OK:
print('[rtr] Ошибка парсинга JSON')
return false
var data = json.data
var self_tests = data.get('SelfTest', [])
var all_passed = true
for test in self_tests:
var system_list = test.get('SystemList', [])
for system in system_list:
# Рекурсивно проверяем систему и её подсистемы
if not _check_system_passed(system):
all_passed = false
# Не прерываем цикл, чтобы найти все ошибки
return all_passed
# Рекурсивная функция для проверки SystemList и вывода ошибок
func _check_system_passed(system: Dictionary) -> bool:
var system_passed = true
# Проверяем устройства в текущей системе
var dev_list = system.get('DevList', [])
for dev in dev_list:
var test_passed = dev.get('TestPassed', false)
if not test_passed:
system_passed = false
# Формируем читаемое имя устройства для вывода
var dev_name = dev.get('DevName', 'Неизвестное устройство')
var dev_id = dev.get('DevId', '?')
var error_text = dev.get('ErrorText', 'Нет описания ошибки')
print('[rtr] НАЙДЕНА ОШИБКА! Устройство: %s (ID: %s). TestPassed: false. Причина: %s' % [dev_name, dev_id, error_text])
# Рекурсивно проверяем вложенные подсистемы
var sub_systems = system.get('SystemList', [])
for sub in sub_systems:
if not _check_system_passed(sub):
system_passed = false
return system_passed
# Исправленная функция подсчета (использует Dictionary для передачи по ссылке)
func _count_tests_in_system(system: Dictionary, counters: Dictionary) -> void:
var dev_list = system.get('DevList', [])
for dev in dev_list:
counters['total'] += 1
if dev.get('TestPassed', false):
counters['passed'] += 1
var sub_systems = system.get('SystemList', [])
for sub in sub_systems:
_count_tests_in_system(sub, counters)
func _on_timeout() -> void:
var was_state = current_state
current_state = State.WAITING_TIMEOUT
http_request.cancel_request()
var is_afsp = (was_state == State.REQUESTING_AFSP_LEFT or was_state == State.REQUESTING_AFSP_RIGHT)
var is_left = (was_state == State.REQUESTING_AFSP_LEFT or was_state == State.REQUESTING_BPO_LEFT)
var side_str = 'left' if is_left else 'right'
var device_str = 'afsp' if is_afsp else 'bpo'
var timeout_msg = 'Таймаут %.1f секунд - %s' % [timeout, get_result_string(HTTPRequest.Result.RESULT_TIMEOUT)]
_save_error(timeout_msg)
var is_left = (current_state == State.REQUESTING_LEFT)
_update_online_status(device_str, side_str, false)
_emit_response_signal(device_str, side_str, timeout_msg, false)
# Обновляем статус online (таймаут = offline)
if is_left:
_update_online_status("left", false)
emit_signal('response_received_left', timeout_msg, false)
if is_afsp:
_emit_afsp_serviceability_signal(side_str, 0)
else:
_update_online_status("right", false)
emit_signal('response_received_right', timeout_msg, false)
_update_bpo_state(side_str, 0)
_emit_bpo_serviceability_signal()
_on_request_finished()
#endregion
#region Управление запросами
# Переход к следующему запросу в очереди
func _request_next(next_state: State) -> void:
current_state = next_state
current_device_type = 'afsp' if (next_state == State.REQUESTING_AFSP_LEFT or next_state == State.REQUESTING_AFSP_RIGHT) else 'bpo'
# Определяем URL для текущего состояния
match current_state:
State.REQUESTING_LEFT:
State.REQUESTING_AFSP_LEFT:
current_url = addresses.get('Адрес АФСП левого борта', '')
State.REQUESTING_RIGHT:
State.REQUESTING_AFSP_RIGHT:
current_url = addresses.get('Адрес АФСП правого борта', '')
State.REQUESTING_BPO_LEFT:
current_url = addresses.get('Адрес БПО левого борта', '')
State.REQUESTING_BPO_RIGHT:
current_url = addresses.get('Адрес БПО правого борта', '')
State.IDLE:
return
# Проверяем, задан ли URL
if current_url.is_empty():
print('URL не задан для ', current_state)
var error_msg = 'URL не задан'
_save_error(error_msg)
var is_left = (current_state == State.REQUESTING_LEFT)
var is_afsp = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_AFSP_RIGHT)
var is_left = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_BPO_LEFT)
var side_str = 'left' if is_left else 'right'
var device_str = 'afsp' if is_afsp else 'bpo'
# Испускаем сигнал с ошибкой
if is_left:
_update_online_status("left", false)
emit_signal('response_received_left', error_msg, false)
_update_online_status(device_str, side_str, false)
_emit_response_signal(device_str, side_str, error_msg, false)
if is_afsp:
_emit_afsp_serviceability_signal(side_str, 0)
else:
_update_online_status("right", false)
emit_signal('response_received_right', error_msg, false)
_update_bpo_state(side_str, 0)
_emit_bpo_serviceability_signal()
_on_request_finished()
return
# Испускаем сигнал отправки запроса
match current_state:
State.REQUESTING_LEFT:
emit_signal('request_sent_left', current_url)
State.REQUESTING_RIGHT:
emit_signal('request_sent_right', current_url)
State.REQUESTING_AFSP_LEFT:
emit_signal('request_sent_afsp_left', current_url)
State.REQUESTING_AFSP_RIGHT:
emit_signal('request_sent_afsp_right', current_url)
State.REQUESTING_BPO_LEFT:
emit_signal('request_sent_bpo_left', current_url)
State.REQUESTING_BPO_RIGHT:
emit_signal('request_sent_bpo_right', current_url)
# Запускаем таймер и отправляем запрос
timeout_timer.start(timeout)
var error = http_request.request(current_url)
if error != OK:
@@ -256,43 +426,78 @@ func _request_next(next_state: State) -> void:
var error_msg = 'Ошибка запроса: ' + error_string(error)
_save_error(error_msg)
var is_left = (current_state == State.REQUESTING_LEFT)
var is_afsp = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_AFSP_RIGHT)
var is_left = (current_state == State.REQUESTING_AFSP_LEFT or current_state == State.REQUESTING_BPO_LEFT)
var side_str = 'left' if is_left else 'right'
var device_str = 'afsp' if is_afsp else 'bpo'
# Испускаем сигнал с ошибкой
if is_left:
_update_online_status("left", false)
emit_signal('response_received_left', error_msg, false)
_update_online_status(device_str, side_str, false)
_emit_response_signal(device_str, side_str, error_msg, false)
if is_afsp:
_emit_afsp_serviceability_signal(side_str, 0)
else:
_update_online_status("right", false)
emit_signal('response_received_right', error_msg, false)
_update_bpo_state(side_str, 0)
_emit_bpo_serviceability_signal()
_on_request_finished()
# Обработка завершения текущего запроса (успех/ошибка/таймаут)
func _on_request_finished() -> void:
match current_state:
State.REQUESTING_LEFT:
# После левого борта переходим к правому
_request_next(State.REQUESTING_RIGHT)
State.REQUESTING_RIGHT, State.WAITING_TIMEOUT:
# После правого борта или таймаута возвращаемся в IDLE
State.REQUESTING_AFSP_LEFT:
_request_next(State.REQUESTING_AFSP_RIGHT)
State.REQUESTING_AFSP_RIGHT:
_request_next(State.REQUESTING_BPO_LEFT)
State.REQUESTING_BPO_LEFT:
_request_next(State.REQUESTING_BPO_RIGHT)
State.REQUESTING_BPO_RIGHT, State.WAITING_TIMEOUT:
current_state = State.IDLE
#endregion
#region Сохранение результатов
# Сохраняет успешный ответ от устройства
func _save_response(response: String) -> void:
match current_state:
State.REQUESTING_LEFT:
last_response_left = response
State.REQUESTING_RIGHT:
last_response_right = response
State.REQUESTING_AFSP_LEFT:
last_response_afsp_left = response
State.REQUESTING_AFSP_RIGHT:
last_response_afsp_right = response
State.REQUESTING_BPO_LEFT:
last_response_bpo_left = response
State.REQUESTING_BPO_RIGHT:
last_response_bpo_right = response
# Сохраняет ошибку от устройства
func _save_error(error: String) -> void:
match current_state:
State.REQUESTING_LEFT:
last_error_left = error
State.REQUESTING_RIGHT:
last_error_right = error
State.REQUESTING_AFSP_LEFT:
last_error_afsp_left = error
State.REQUESTING_AFSP_RIGHT:
last_error_afsp_right = error
State.REQUESTING_BPO_LEFT:
last_error_bpo_left = error
State.REQUESTING_BPO_RIGHT:
last_error_bpo_right = error
func _update_success_time(device: String, side: String, time: int) -> void:
if device == 'afsp':
if side == 'left':
last_success_time_afsp_left = time
else:
last_success_time_afsp_right = time
else:
if side == 'left':
last_success_time_bpo_left = time
else:
last_success_time_bpo_right = time
func _emit_response_signal(device: String, side: String, response: String, success: bool) -> void:
if device == 'afsp':
if side == 'left':
emit_signal('response_received_afsp_left', response, success)
else:
emit_signal('response_received_afsp_right', response, success)
else:
if side == 'left':
emit_signal('response_received_bpo_left', response, success)
else:
emit_signal('response_received_bpo_right', response, success)
#endregion