From 38529ac0ccda2c2f751337024671fa799bfc25c6 Mon Sep 17 00:00:00 2001
From: TotMaxim
Date: Sun, 5 Apr 2026 15:52:50 +0300
Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?=
=?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB?=
=?UTF-8?q?=D1=8F=20=D0=90=D0=A4=D0=A1=D0=9F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
project.godot | 1 +
scenes/pribor-afsp/pribor-afsp-1.tscn | 13 +-
scenes/pribor-afsp/pribor-afsp-2.tscn | 13 +-
scenes/pribor-afsp/pribor-afsp.gd | 174 ++++++++++++------
scenes/контроль/request.gd | 1 +
scenes/контроль/контроль.tscn | 15 +-
scripts/rtr.gd | 252 ++++++++++++++++++++++++++
scripts/rtr.gd.uid | 1 +
8 files changed, 382 insertions(+), 88 deletions(-)
create mode 100644 scripts/rtr.gd
create mode 100644 scripts/rtr.gd.uid
diff --git a/project.godot b/project.godot
index 797f901a..a72ef926 100644
--- a/project.godot
+++ b/project.godot
@@ -123,6 +123,7 @@ prd="*res://scripts/prd.gd"
navi="*res://scripts/navigation.gd"
trassa="*res://scripts/trassa.gd"
yemstg="*res://scripts/yemstg.gd"
+scouting="*res://scripts/rtr.gd"
[debug]
diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn
index e99f25c5..f4d16c85 100644
--- a/scenes/pribor-afsp/pribor-afsp-1.tscn
+++ b/scenes/pribor-afsp/pribor-afsp-1.tscn
@@ -1,7 +1,6 @@
-[gd_scene load_steps=4 format=3 uid="uid://8ll27id5ajq1"]
+[gd_scene load_steps=3 format=3 uid="uid://8ll27id5ajq1"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_151rh"]
-[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_4vyhj"]
[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_d7iti"]
[node name="pribor_afsp" type="Control"]
@@ -20,13 +19,6 @@ settings_path_to_url = "Адрес АФСП левого борта"
settings_path_to_wait_time = "Период опроса состояния АФСП, секунды"
metadata/DeviceName = &"Устройство РР левого борта"
-[node name="request" type="HTTPRequest" parent="."]
-use_threads = true
-script = ExtResource("2_4vyhj")
-
-[node name="timer" type="Timer" parent="request"]
-autostart = true
-
[node name="bort" parent="." instance=ExtResource("3_d7iti")]
layout_mode = 0
offset_left = 24.0
@@ -35,7 +27,4 @@ offset_right = 604.0
offset_bottom = 1216.78
metadata/DeviceName = &"Устройство РР левого борта"
-[connection signal="child_entered_tree" from="request" to="request" method="_on_child_entered_tree"]
-[connection signal="request_completed" from="request" to="." method="_on_request_completed"]
-[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"]
[connection signal="pressed" from="bort" to="." method="_on_item_pressed"]
diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn
index 1eae9366..64beffa7 100644
--- a/scenes/pribor-afsp/pribor-afsp-2.tscn
+++ b/scenes/pribor-afsp/pribor-afsp-2.tscn
@@ -1,7 +1,6 @@
-[gd_scene load_steps=4 format=3 uid="uid://5uv1idl3lqet"]
+[gd_scene load_steps=3 format=3 uid="uid://5uv1idl3lqet"]
[ext_resource type="Script" uid="uid://d0jwv5opi3mrl" path="res://scenes/pribor-afsp/pribor-afsp.gd" id="1_tfses"]
-[ext_resource type="Script" uid="uid://bux47vkw71w1t" path="res://scenes/контроль/request.gd" id="2_miwrd"]
[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_xpxb5"]
[node name="pribor_afsp" type="Control"]
@@ -20,13 +19,6 @@ settings_path_to_url = "Адрес АФСП правого борта"
settings_path_to_wait_time = "Период опроса состояния АФСП, секунды"
metadata/DeviceName = &"Устройство РР правого борта"
-[node name="request" type="HTTPRequest" parent="."]
-use_threads = true
-script = ExtResource("2_miwrd")
-
-[node name="timer" type="Timer" parent="request"]
-autostart = true
-
[node name="bort" parent="." instance=ExtResource("3_xpxb5")]
layout_mode = 0
offset_left = 12.0
@@ -35,7 +27,4 @@ offset_right = 592.0
offset_bottom = 1130.0
metadata/DeviceName = &"Устройство РР правого борта"
-[connection signal="child_entered_tree" from="request" to="request" method="_on_child_entered_tree"]
-[connection signal="request_completed" from="request" to="." method="_on_request_completed"]
-[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"]
[connection signal="pressed" from="bort" to="." method="_on_item_pressed"]
diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd
index 04ef8611..fde8c96b 100644
--- a/scenes/pribor-afsp/pribor-afsp.gd
+++ b/scenes/pribor-afsp/pribor-afsp.gd
@@ -7,98 +7,164 @@ class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd'
@export var settings_path_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: Node
-static var node_request_timer: Node
var ctrl_pos = 0
# SystemName: "gen" DevList - там состояние связи с генератором по кан шине
func _ready() -> void:
- ProjectSettings.connect('settings_changed', on_settings_chaged)
- node_request = $request
- node_request_timer = $request/timer
- on_settings_chaged()
+ # Подключаемся к сигналам в зависимости от борта
+ if this_afsp_name == 'Устройство РР левого борта':
+ scouting.response_received_left.connect(_on_response_received)
+ else:
+ scouting.response_received_right.connect(_on_response_received)
+
+ # При старте отрисовываем последние данные (если есть)
+ _on_press_device()
-func on_settings_chaged():
- node_request.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path_to_url)
- node_request_timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time))
- tools.allways(node_request.request_url != null)
-
-
-func _on_request_completed(result, _response_code, headers, body: PackedByteArray):
-
- var unit_instance: = network.get_unit_instance(unit_name)
-
- if result != 0:
- var rs = node_request.get_result_string(result)
- log.error('\"%s\"' % rs)
+# Обработка полученного ответа от rtr
+func _on_response_received(response: String, success: bool) -> void:
+ var unit_instance = network.get_unit_instance(unit_name)
+
+ if not success:
+ log.error('Ошибка запроса: %s' % response)
if unit_instance.online:
unit_instance.online = false
unit_instance.emit_signal('line_changed', unit_instance)
+ # При ошибке сбрасываем UI в 0
+ _reset_ui_to_zero()
return
-
- var json_str: String = body.get_string_from_utf8()
- if not json_str:
- push_error('не удаётся получить строку utf8 из данных (%s)' % headers)
+
+ # Парсим JSON строку
+ var parse_result = json_conv.parse(response)
+ if parse_result != OK:
+ var err = json_conv.get_error_message()
+ push_error('разбор json прерван - "%s"' % err)
if unit_instance.online:
unit_instance.online = false
unit_instance.emit_signal('line_changed', unit_instance)
+ # При ошибке парсинга сбрасываем UI в 0
+ _reset_ui_to_zero()
return
-
- 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])
- if unit_instance.online:
- unit_instance.online = false
- unit_instance.emit_signal('line_changed', unit_instance)
- return
-
+
+ # Ищем имя прибора в JSON
var pp = []
tools.map_solid_to_array(prefix_path, pp)
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]])
+ # Если путь не найден, сбрасываем UI в 0
+ _reset_ui_to_zero()
return
-
+
var received_afsp_name: StringName = ret_val[0]
-
+
+ # Проверяем, что ответ от нужного прибора
if this_afsp_name != received_afsp_name:
- # TODO: Сюда попадаем, когда приходит от другого борта
- #push_error('не известное устройство: \"%s\", ожидадось: \"%s\"' % [received_afsp_name, this_afsp_name])
+ # Ответ от другого борта - игнорируем
return
-
+
+ # Обновляем статус online
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 элементы из JSON
+ _update_ui(json_conv.data)
+
+# Обновление интерфейса из JSON данных
+func _update_ui(json_data: Dictionary) -> void:
+ # Конвертер
for child in $bort.get_node('konverter/grid').get_children():
- node_maper.map_value_to_item(json_conv.data, child, 'value0')
- node_maper.map_value_to_item(json_conv.data, child, 'value1')
- node_maper.map_value_to_item(json_conv.data, child, 'value2')
- node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
+ node_maper.map_value_to_item(json_data, child, 'value0')
+ node_maper.map_value_to_item(json_data, child, 'value1')
+ node_maper.map_value_to_item(json_data, child, 'value2')
+ node_maper.map_error_codes_to_item(json_data, child, 'state', 0)
+
+ # Антенна 1
for child in $bort.get_node('antenna1/grid').get_children():
- node_maper.map_value_to_item(json_conv.data, child, 'value0')
- node_maper.map_value_to_item(json_conv.data, child, 'value1')
- node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
+ node_maper.map_value_to_item(json_data, child, 'value0')
+ node_maper.map_value_to_item(json_data, child, 'value1')
+ node_maper.map_error_codes_to_item(json_data, child, 'state', 0)
+
+ # Антенна 2
for child in $bort.get_node('antenna2/grid').get_children():
- node_maper.map_value_to_item(json_conv.data, child, 'value0')
- node_maper.map_value_to_item(json_conv.data, child, 'value1')
- node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
+ node_maper.map_value_to_item(json_data, child, 'value0')
+ node_maper.map_value_to_item(json_data, child, 'value1')
+ node_maper.map_error_codes_to_item(json_data, child, 'state', 0)
+
+ # Остальные элементы
for child in $bort.get_children():
- node_maper.map_value_to_item(json_conv.data, child, 'value0')
- node_maper.map_value_to_item(json_conv.data, child, 'value1')
- node_maper.map_error_codes_to_item(json_conv.data, child, 'state', 0)
+ node_maper.map_value_to_item(json_data, child, 'value0')
+ node_maper.map_value_to_item(json_data, child, 'value1')
+ node_maper.map_error_codes_to_item(json_data, child, 'state', 0)
- emit_signal('receive_response_afp_bpo')
+
+# Сброс всех UI элементов в 0 (при отсутствии данных)
+func _reset_ui_to_zero() -> void:
+ # Конвертер
+ for child in $bort.get_node('konverter/grid').get_children():
+ _reset_item_value(child)
+
+ # Антенна 1
+ for child in $bort.get_node('antenna1/grid').get_children():
+ _reset_item_value(child)
+
+ # Антенна 2
+ for child in $bort.get_node('antenna2/grid').get_children():
+ _reset_item_value(child)
+
+ # Остальные элементы
+ for child in $bort.get_children():
+ _reset_item_value(child)
+
+
+# Сброс конкретного элемента в 0
+func _reset_item_value(item) -> void:
+ item.set('value0', 0)
+ item.set('value1', 0)
+ item.set('value2', 0)
+ item.set('state', 0)
+
+
+# Отрисовывание при нажатии на прибор
+func _on_press_device() -> void:
+ # Проверяем, есть ли сохраненные данные в rtr
+ var has_data = false
+ var last_response = ""
+
+ if this_afsp_name == 'Устройство РР левого борта':
+ has_data = scouting.has_left_success()
+ if has_data:
+ last_response = scouting.get_left_response()
+ else:
+ has_data = scouting.has_right_success()
+ if has_data:
+ last_response = scouting.get_right_response()
+
+ # Если есть данные - парсим и отображаем
+ if has_data and not last_response.is_empty():
+ var parse_result = json_conv.parse(last_response)
+ if parse_result == OK:
+ # Проверяем, что это данные именно от этого прибора
+ var pp = []
+ tools.map_solid_to_array(prefix_path, pp)
+ var ret_val = [null, false, 0]
+ tools.get_value_by_path(json_conv.data, pp, ret_val)
+
+ if ret_val[1] and ret_val[0] == this_afsp_name:
+ _update_ui(json_conv.data)
+ return
+
+ # Если данных нет или они не подходят - сбрасываем в 0
+ _reset_ui_to_zero()
## Вызывается при клике мыши на элементе.
diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd
index fda7abda..cd860e14 100644
--- a/scenes/контроль/request.gd
+++ b/scenes/контроль/request.gd
@@ -29,6 +29,7 @@ func get_result_string(result: Result):
func _on_request_timer():
+ print('_on_request_timer: ', Time.get_ticks_msec())
if HTTPClient.Status.STATUS_DISCONNECTED != get_http_client_status():
return
var rc: = request(request_url)
diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn
index e3d87b6b..bb39fe2c 100644
--- a/scenes/контроль/контроль.tscn
+++ b/scenes/контроль/контроль.tscn
@@ -123,6 +123,8 @@ 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))
func online_change_arr(_u, conn_node, pribor_meta):
@@ -166,24 +168,17 @@ func on_pribor_press(pribor_path, header_text, pribor_node):
pribor.add_to_group('pribor_items')
add_child(pribor)
update_pribor_items_visibility()
- if pribor_node.get_meta('unit_name')[0] == 'уарэп-афсп-левый' or pribor_node.get_meta('unit_name')[0] == 'уарэп-афсп-правый':
- pribor.node_request.connect('send_http_request', Callable(self, 'on_send_http_request').bind(pribor_node, pribor.node_request_timer.wait_time))
- pribor.connect('receive_response_afp_bpo', Callable(self, 'on_receive_response_afp_bpo').bind(pribor_node))
- if pribor_node.get_meta('unit_name')[0] == 'уарэп-бпо-1' or pribor_node.get_meta('unit_name')[0] == 'уарэп-бпо-2':
- pribor.node_request_1.connect('send_http_request', Callable(self, 'on_send_http_request').bind(pribor_node, pribor.node_request_timer_1.wait_time))
- pribor.connect('receive_response_afp_bpo', Callable(self, 'on_receive_response_afp_bpo').bind(pribor_node))
- #signal receive_response_afp_bpo
# Вызов при отправке запроса на селфтест АФСП
-func on_send_http_request(node: Node, time_req: float) -> void:
+func _on_request_sent_left(_url: String, node: Node) -> void:
node.progress_max_value = 100
node.progress_value = 0
node.progress_visible = true
- node.timeout_tween = time_req
+ node.timeout_tween = float(ProjectSettings.get_setting('application/config/%s' % 'Период опроса состояния АФСП, секунды'))
-func on_receive_response_afp_bpo(node: Node) -> void:
+func _on_response_received(_response: String, _success: bool, node: Node):
node.progress_value = 100
node.progress_visible = false
diff --git a/scripts/rtr.gd b/scripts/rtr.gd
new file mode 100644
index 00000000..a66be793
--- /dev/null
+++ b/scripts/rtr.gd
@@ -0,0 +1,252 @@
+class_name rtr
+extends Node
+
+#region Перечисления
+enum State { IDLE, REQUESTING_LEFT, REQUESTING_RIGHT, WAITING_TIMEOUT }
+#endregion
+
+#region Сигналы
+# Сигналы отправки запроса
+signal request_sent_left(url: String) # Отправлен запрос к левому борту
+signal request_sent_right(url: String) # Отправлен запрос к правому борту
+
+# Сигналы получения ответа
+signal response_received_left(response: String, success: bool) # Получен ответ от левого борта
+signal response_received_right(response: String, success: bool) # Получен ответ от правого борта
+#endregion
+
+#region Константы
+# Словарь с текстовым описанием кодов результатов HTTP запросов
+const RESULT_STRINGS = {
+ HTTPRequest.Result.RESULT_SUCCESS: 'Запрос успешен',
+ HTTPRequest.Result.RESULT_CHUNKED_BODY_SIZE_MISMATCH: 'Несоответствие размеров частей сообщения',
+ HTTPRequest.Result.RESULT_CANT_CONNECT: 'Запрос не выполнен при подключении',
+ HTTPRequest.Result.RESULT_CANT_RESOLVE: 'Запрос не выполнен при разрешении',
+ HTTPRequest.Result.RESULT_CONNECTION_ERROR: 'Запрос не выполнен из-за ошибки соединения',
+ HTTPRequest.Result.RESULT_TLS_HANDSHAKE_ERROR: 'Запрос не выполнен на TLS рукопожатии',
+ HTTPRequest.Result.RESULT_NO_RESPONSE: 'Запрос не имеет ответа (пока)',
+ HTTPRequest.Result.RESULT_BODY_SIZE_LIMIT_EXCEEDED: 'Запрос превысил максимальный размер',
+ HTTPRequest.Result.RESULT_BODY_DECOMPRESS_FAILED: 'Не удалось распаковать сообщение',
+ HTTPRequest.Result.RESULT_REQUEST_FAILED: 'Запрос не удался',
+ HTTPRequest.Result.RESULT_DOWNLOAD_FILE_CANT_OPEN: 'Невозможно открыть файл загрузки',
+ HTTPRequest.Result.RESULT_DOWNLOAD_FILE_WRITE_ERROR: 'Невозможно записать в файл загрузки',
+ HTTPRequest.Result.RESULT_REDIRECT_LIMIT_REACHED: 'Достигнут лимит перенаправлений',
+ HTTPRequest.Result.RESULT_TIMEOUT: 'Время истекло'
+}
+#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 last_response_left: String = '' # Последний успешный ответ левого борта
+var last_response_right: String = '' # Последний успешный ответ правого борта
+var last_error_left: String = '' # Последняя ошибка левого борта
+var last_error_right: String = '' # Последняя ошибка правого борта
+
+var timeout: float
+#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_right_response() -> String:
+ return last_response_right
+
+func get_left_error() -> String:
+ return last_error_left
+
+func get_right_error() -> String:
+ return last_error_right
+
+# Проверка успешности запросов
+func has_left_success() -> bool:
+ return not last_response_left.is_empty()
+
+func has_right_success() -> bool:
+ return not last_response_right.is_empty()
+#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 = ''
+
+ # Загружаем URL адреса из ProjectSettings
+ 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)
+
+# Сигнал от 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()
+
+ # Проверяем успешность ответа
+ if response_code == 200:
+ var response_text = body.get_string_from_utf8()
+ _save_response(response_text)
+
+ # Испускаем сигнал успешного получения ответа
+ match current_state:
+ State.REQUESTING_LEFT:
+ emit_signal('response_received_left', response_text, true)
+ State.REQUESTING_RIGHT:
+ emit_signal('response_received_right', response_text, true)
+
+ _on_request_finished()
+ else:
+ var error_msg = 'HTTP ошибка %d: %s' % [response_code, get_result_string(result)]
+ _save_error(error_msg)
+
+ # Испускаем сигнал с ошибкой
+ match current_state:
+ State.REQUESTING_LEFT:
+ emit_signal('response_received_left', error_msg, false)
+ State.REQUESTING_RIGHT:
+ emit_signal('response_received_right', error_msg, false)
+
+ _on_request_finished()
+
+# Сигнал от таймера - истекло время ожидания ответа
+func _on_timeout() -> void:
+ current_state = State.WAITING_TIMEOUT
+ http_request.cancel_request() # Отменяем текущий запрос
+ var timeout_msg = 'Таймаут %.1f секунд - %s' % [timeout, get_result_string(HTTPRequest.Result.RESULT_TIMEOUT)]
+ _save_error(timeout_msg)
+
+ # Испускаем сигнал с ошибкой таймаута
+ match current_state:
+ State.REQUESTING_LEFT:
+ emit_signal('response_received_left', timeout_msg, false)
+ State.REQUESTING_RIGHT:
+ emit_signal('response_received_right', timeout_msg, false)
+
+ _on_request_finished()
+#endregion
+
+#region Управление запросами
+# Переход к следующему запросу в очереди
+func _request_next(next_state: State) -> void:
+ current_state = next_state
+
+ # Определяем URL для текущего состояния
+ match current_state:
+ State.REQUESTING_LEFT:
+ current_url = addresses.get('Адрес АФСП левого борта', '')
+ State.REQUESTING_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)
+
+ # Испускаем сигнал с ошибкой
+ match current_state:
+ State.REQUESTING_LEFT:
+ emit_signal('response_received_left', error_msg, false)
+ State.REQUESTING_RIGHT:
+ emit_signal('response_received_right', error_msg, false)
+
+ _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)
+
+ # Запускаем таймер и отправляем запрос
+ timeout_timer.start(timeout)
+ var error = http_request.request(current_url)
+ if error != OK:
+ print('Ошибка запроса: ', error_string(error))
+ var error_msg = 'Ошибка запроса: ' + error_string(error)
+ _save_error(error_msg)
+
+ # Испускаем сигнал с ошибкой
+ match current_state:
+ State.REQUESTING_LEFT:
+ emit_signal('response_received_left', error_msg, false)
+ State.REQUESTING_RIGHT:
+ emit_signal('response_received_right', error_msg, false)
+
+ _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
+ current_state = State.IDLE
+ print('Цикл запросов завершен')
+#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
+
+# Сохраняет ошибку от устройства
+func _save_error(error: String) -> void:
+ match current_state:
+ State.REQUESTING_LEFT:
+ last_error_left = error
+ State.REQUESTING_RIGHT:
+ last_error_right = error
+#endregion
diff --git a/scripts/rtr.gd.uid b/scripts/rtr.gd.uid
new file mode 100644
index 00000000..b19ac1eb
--- /dev/null
+++ b/scripts/rtr.gd.uid
@@ -0,0 +1 @@
+uid://ctqcvjqjb1av3