diff --git a/.gitignore b/.gitignore index 41d1abca..a3b149bc 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,8 @@ override.cfg # контроль версий scripts/commit.gd +*.bak + # python специфичное modbus/pymodbus/__pycache__ modbus/serial/__pycache__ diff --git a/README.md b/README.md index f73f4dc6..3fc369dd 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,10 @@ - [Прибор СПТ-25](http://gitea.srez.local:3000/Maxim/SPT-25) - [ПО 5П28 Пульт П16](http://gitea.srez.local:3000/MaD_CaT/imi-5p28) - [ПО 5П28 АКНГ](http://gitea.srez.local:3000/sasha80/imi-5p28-navi) +- [Трасса](http://gitea.srez.local:3000/lepshiy/imi-trassa) + +# Автоматизация тестирования + - [Запуск имитаторов](http://gitea.srez.local:3000/sasha80/uarep-ctl-test-launcher) # Сборка исполняемого файла из консоли @@ -30,3 +34,5 @@ # Разработка - После клонирования запустить скрипт `git-hooks-config.sh` +- В среде **Windows** запуск скрипта `git-hooks-config.sh` производить из оболочки `git bash` +- Нужно обновить `settings.json` diff --git a/addons/godot-logger/scripts/logger_output.gd b/addons/godot-logger/scripts/logger_output.gd index ae31ad2b..dde49396 100644 --- a/addons/godot-logger/scripts/logger_output.gd +++ b/addons/godot-logger/scripts/logger_output.gd @@ -17,11 +17,14 @@ signal handled() Logger.ERROR: Color.RED, Logger.FATAL: Color.RED, } - +@export var max_lines_count: int = 512 var _logger : Logger +func _on_check_box_scroll_toggled(toggled_on: bool) -> void: scroll_following = toggled_on + + func _enter_tree() -> void: var logger := get_node_or_null("/root/log") as Logger if is_instance_valid(logger): @@ -38,7 +41,7 @@ func get_color(level: int) -> Color: ## Установить журнал событий. func set_logger(logger: Logger) -> void: - assert(is_instance_valid(logger), "Invalid Logger.") + tools.allways(is_instance_valid(logger), 'Invalid Logger.') if not is_instance_valid(logger) or is_same(_logger, logger): return @@ -58,20 +61,25 @@ func get_logger() -> Logger: func format(message: Dictionary) -> String: return format_text.format( { - "year": "%02d" % message["year"], - "month": "%02d" % message["month"], - "day": "%02d" % message["day"], - "hour": "%02d" % message["hour"], - "minute": "%02d" % message["minute"], - "second": "%02d" % message["second"], - "level": message["level_name"], - "text": message["text"], + 'year': '%04d' % message['year'], + 'month': '%02d' % message['month'], + 'day': '%02d' % message['day'], + 'hour': '%02d' % message['hour'], + 'minute': '%02d' % message['minute'], + 'second': '%02d' % message['second'], + 'level': message['level_name'], + 'text': message['text'], } ) ## Обработать сообщение. func handle_message(message: Dictionary) -> void: - push_color(get_color(message["level"])) - append_text(format(message) + "\n") + push_color(get_color(message['level'])) + append_text(format(message) + '\n') pop() handled.emit() + var pc: = get_paragraph_count() + if pc < max_lines_count: + return + for i in pc - max_lines_count: + remove_paragraph(i) diff --git a/git-hooks-config.sh b/git-hooks-config.sh index 0b2cb93d..c3109721 100644 --- a/git-hooks-config.sh +++ b/git-hooks-config.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash -echo ./git-hook.sh> ./.git/hooks/post-checkout -echo ./git-hook.sh> ./.git/hooks/post-commit -echo ./git-hook.sh> ./.git/hooks/post-merge +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-checkout +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-commit +printf "#!/usr/bin/env bash\n./git-hook.sh"> ./.git/hooks/post-merge ./git-hook.sh \ No newline at end of file diff --git a/project.godot b/project.godot index 5a6acf44..43e88265 100644 --- a/project.godot +++ b/project.godot @@ -25,23 +25,26 @@ config/map_tile_size=256 config/map_minimum_zoom=5 config/map_maximum_zoom=19 interfer/center_offset=Vector2(200, 225) -interfer/default_color0=Vector3(0.38, 0.47, 0.51) -interfer/default_color1=Vector3(0.39, 0.44, 0.5) -interfer/select_color=Vector3(1, 1, 1) -interfer/interfer_color=Vector3(0.58, 0.47, 0.51) +interfer/default_color0=Color(0.38, 0.47, 0.51, 1) +interfer/default_color1=Color(0.39, 0.44, 0.5, 1) +interfer/select_color=Color(1, 1, 1, 1) +interfer/interfer_color=Color(0.58, 0.47, 0.51, 1) interfer/resend_timeout=1000.0 config/external_cu=false -config/unit_rr_request_period=5.0 +config/unit_rr_request_period=20.0 config/kems_files_path="user://kems/" config/emsg_files_path="user://emsg/" config/settings_path="user://settings.json" +config/unit_bpo_request_period=20.0 +interfer/emit_color=Color(0.58, 0.471, 0.51, 0.2) +interfer/emit_sel_color=Color(1, 1, 1, 1) [autoload] commit="*res://scripts/commit.gd" +tools="*res://scripts/tools.gd" log="*res://addons/godot-logger/scripts/logger.gd" unit="*res://scripts/unit.gd" -tools="*res://scripts/tools.gd" signaller="*res://scripts/signaller.gd" settings="*res://scripts/settings.gd" network="*res://scripts/network.gd" @@ -84,6 +87,7 @@ window/size/viewport_height=1200 window/size/window_width_override=1024 window/size/window_height_override=768 window/subwindows/embed_subwindows=false +window/frame_pacing/android/enable_frame_pacing=false window/stretch/mode="canvas_items" window/dpi/allow_hidpi=false @@ -142,6 +146,7 @@ folder_colors={ map_server_addr=false center_offset=Vector2(0, 0) external_cu=false +unit_bpo_request_period=0.0 [global_group] diff --git a/scenes/bip/bip.gd b/scenes/bip/bip.gd index 20affa3a..34497868 100644 --- a/scenes/bip/bip.gd +++ b/scenes/bip/bip.gd @@ -2,11 +2,11 @@ class_name bip_ extends Control var selected: bool -## Присваивает заданое значение видимости селектору. +## Присваивает заданное значение видимости селектору. func set_track_visible(value: bool): $track.visible = value -## Присваивает заданое значение видимости индикатору выполнения. +## Присваивает заданное значение видимости индикатору выполнения. func set_ecm_visible(value: bool): $ecm_done.visible = value @@ -14,7 +14,7 @@ func update(tick_rx: int): $bip.set_instance_shader_parameter('tick_update', tick_rx) -## Функция присваивает заданое значение видимости селектору. +## Присваивает заданое значение видимости селектору. func set_sel_visible(value: bool): selected = value $selector.visible = value diff --git a/scenes/bip/bip.tscn b/scenes/bip/bip.tscn index bf19a9d3..1cb79e0b 100644 --- a/scenes/bip/bip.tscn +++ b/scenes/bip/bip.tscn @@ -15,17 +15,19 @@ code = "shader_type canvas_item; uniform vec4 color: source_color = vec4(1, 1, 1, 1); uniform vec4 color_up: source_color = vec4(1, 1, 1, 1); /* Цвет вспышки при обновлении */ -const float ds = 0.00725; /* Относительное расстояние на котором выполняется сглаживание краёв */ -const float dsr = 6.125; +const float ds = 0.01; /* Относительное расстояние на котором выполняется сглаживание краёв */ +const float dsr = 10.0; const vec2 center = vec2(0.5, 0.5); /* Центр должен быть в (0.5, 0.5), но это не так */ const float radius = 0.075 - ds * 2.0; /* Радиус должен быть 0.5, но это не так */ uniform float speed: hint_range(-1024.0, 1024.0) = 0.0; /* Время вспышки при обновлении, c */ uniform int ant_band_count_0 = 3; -const float ant_band_r0_0 = 0.3; +const float ant_band_r0_0 = 0.27 -const float ant_band_r1_0 = 0.4; +; + +const float ant_band_r1_0 = 0.47; float smooth_px(float r, float R, float dss) { @@ -97,7 +99,7 @@ void fragment() shader = SubResource("Shader_60ho7") shader_parameter/color = Color(1, 1, 1, 0.968627) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 73.0 +shader_parameter/speed = -118.48 shader_parameter/ant_band_count_0 = 3 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_hqs6j"] @@ -185,23 +187,14 @@ void fragment() } " -[sub_resource type="ShaderMaterial" id="ShaderMaterial_lpmq6"] -shader = SubResource("Shader_81bae") -shader_parameter/color = Color(0.0862745, 0.560784, 0.72549, 0.886275) -shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = -73.0 -shader_parameter/ant_band_count_0 = 9 -shader_parameter/ant_band_r0_0 = 0.45 -shader_parameter/ant_band_r1_0 = 0.5 - [sub_resource type="ShaderMaterial" id="ShaderMaterial_h3oo7"] shader = SubResource("Shader_81bae") shader_parameter/color = Color(1, 0, 0, 1) shader_parameter/color_up = Color(1, 1, 1, 0) -shader_parameter/speed = 66.064 -shader_parameter/ant_band_count_0 = 3 -shader_parameter/ant_band_r0_0 = 0.47 -shader_parameter/ant_band_r1_0 = 0.5 +shader_parameter/speed = 85.808 +shader_parameter/ant_band_count_0 = 4 +shader_parameter/ant_band_r0_0 = 0.3 +shader_parameter/ant_band_r1_0 = 0.45 [sub_resource type="ShaderMaterial" id="ShaderMaterial_lkrha"] shader = ExtResource("3_2a1qb") @@ -213,51 +206,63 @@ shader_parameter/point_5 = Vector2(0.214, 0.125) shader_parameter/point_6 = Vector2(0.25, 0.125) shader_parameter/point_7 = Vector2(0.125, 0.214) shader_parameter/point_8 = Vector2(0.125, 0.25) -shader_parameter/len = 0.264 -shader_parameter/speed = 71.0 +shader_parameter/len = 0.179 +shader_parameter/speed = 63.0 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_svd33"] +[sub_resource type="ShaderMaterial" id="ShaderMaterial_lpmq6"] +shader = SubResource("Shader_81bae") +shader_parameter/color = Color(0.0784314, 0.501961, 0.701961, 0.917647) +shader_parameter/color_up = Color(1, 1, 1, 0) +shader_parameter/speed = 158.179 +shader_parameter/ant_band_count_0 = 9 +shader_parameter/ant_band_r0_0 = 0.27 +shader_parameter/ant_band_r1_0 = 0.45 + [node name="threat" type="Control"] layout_mode = 3 anchors_preset = 0 -offset_right = 20.0 -offset_bottom = 20.0 +offset_left = -12.0 +offset_top = -12.0 +offset_right = 12.0 +offset_bottom = 12.0 script = ExtResource("1_h7l70") [node name="bip" type="Sprite2D" parent="."] material = SubResource("ShaderMaterial_qq6yq") -position = Vector2(10, 10) -scale = Vector2(20, 20) +position = Vector2(12, 12) +scale = Vector2(14, 14) texture = SubResource("PlaceholderTexture2D_xbpqf") [node name="selector" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_fkqwb") -scale = Vector2(20, 20) +position = Vector2(-1, -1) +scale = Vector2(26, 26) texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false - -[node name="recomendation" type="Sprite2D" parent="."] -visible = false -material = SubResource("ShaderMaterial_lpmq6") -scale = Vector2(20, 20) -texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false +offset = Vector2(0.5, 0.5) [node name="ecm_done" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_h3oo7") -position = Vector2(-5, -5) -scale = Vector2(30, 30) +position = Vector2(-2, -2) +scale = Vector2(28, 28) texture = SubResource("PlaceholderTexture2D_hqs6j") -centered = false +offset = Vector2(0.5, 0.5) [node name="track" type="Sprite2D" parent="."] visible = false material = SubResource("ShaderMaterial_lkrha") -position = Vector2(10, 10) -scale = Vector2(26, 26) +position = Vector2(12, 12) +scale = Vector2(34, 34) texture = SubResource("PlaceholderTexture2D_svd33") +[node name="recomendation" type="Sprite2D" parent="."] +visible = false +material = SubResource("ShaderMaterial_lpmq6") +scale = Vector2(24, 24) +texture = SubResource("PlaceholderTexture2D_hqs6j") +offset = Vector2(0.5, 0.5) + [connection signal="gui_input" from="." to="." method="_on_bip_gui_input"] diff --git a/scenes/button-flat/nine-patch-button.gd b/scenes/button-flat/nine-patch-button.gd index f18ef37e..7b9ed907 100644 --- a/scenes/button-flat/nine-patch-button.gd +++ b/scenes/button-flat/nine-patch-button.gd @@ -38,9 +38,10 @@ var _pressed: = false @export var disabled: bool = false: set(val): disabled = val - $button.set_disabled(val) - $back.disabled = val - $state.modulate.a = 0.5 if val else 1.0 + if is_inside_tree(): + $button.set_disabled(val) + $back.disabled = val + $state.modulate.a = 0.5 if val else 1.0 @export var pressed: bool = false: @@ -59,7 +60,7 @@ var _pressed: = false $button.set_toggle_mode(val) -@export var font_size: int = true: +@export var font_size: int = 15: set(val): $button.add_theme_font_size_override('theme_override_font_sizes/font_size', val) diff --git a/scenes/diagram/diagram.gd b/scenes/diagram/diagram.gd index 008dcd31..d0a346d8 100644 --- a/scenes/diagram/diagram.gd +++ b/scenes/diagram/diagram.gd @@ -2,7 +2,9 @@ class_name Diagram extends Sprite2D const NUM_OF_RANGE = 7 const NUM_OF_DIRECTIONS = 4 -var fs_default_colors: Array ## Цвета по умолчанию для блоков ФС. +var fs_default_colors: Array[Color] ## Цвета по умолчанию для блоков ФС. + +@export var SecZap: PackedScene func _ready() -> void: signaller.connect('map_mode_changed', Callable(self, 'set_view_mode')) @@ -11,20 +13,24 @@ func _ready() -> void: func sv(val: float) -> float: return val / ($строб.scale.x / 2.0) * 0.125 +func set_canvas_rotation(val: float) -> void: material.set('shader_parameter/rotation', val) func set_strob_visible(val: bool): $строб.visible = val func set_strob_center(val: Vector2): $строб.position = val -func set_strob_dir(val: float): $строб.material.set('shader_parameter/dir', val) -func set_strob_color(val: Color): $строб.material.set('shader_parameter/color', val) -func set_strob_width(val: float): $строб.material.set('shader_parameter/width', val) -func set_strob_band(val: float): $строб.material.set('shader_parameter/band', val / 125.0) -func set_strob_radius(val: float): $строб.material.set('shader_parameter/radius', sv(val)) +func set_strob_dir(val: float): $строб.set_instance_shader_parameter('dir', val) +func set_strob_width(val: float): $строб.set_instance_shader_parameter('width', val) +func set_strob_band(val: float): $строб.set_instance_shader_parameter('band', val / 125.0) +func set_strob_radius(val: float): $строб.set_instance_shader_parameter('radius', sv(val)) +func set_strob_color(val: Color): $строб.set_instance_shader_parameter('color', val) -func get_strob_center() -> Vector2: return $строб.position -func get_strob_visible() -> bool: return $строб.visible -func get_strob_width() -> float: return $строб.material.get('shader_parameter/width') -func get_strob_band() -> float: return $строб.material.get('shader_parameter/band') * 125.0 -func get_strob_radius() -> float: return $строб.material.get('shader_parameter/radius') * 125.0 +func get_strob_center() -> Vector2: return $строб.position +func get_strob_visible() -> bool: return $строб.visible +func get_strob_dir() -> float: return $строб.get_instance_shader_parameter('dir') +func get_strob_width() -> float: return $строб.get_instance_shader_parameter('width') +func get_strob_band() -> float: return $строб.get_instance_shader_parameter('band') * 125.0 +func get_strob_radius() -> float: return $строб.get_instance_shader_parameter('radius') * 125.0 +func get_strob_color() -> float: return $строб.get_instance_shader_parameter('color') +func get_canvas_rotation() -> float: return material.get('shader_parameter/rotation') func get_radius_outter() -> float: return material.get('shader_parameter/radius_outter') func get_radius_inner_0() -> float: return material.get('shader_parameter/radius_inner_0') func get_radius_inner_1() -> float: return material.get('shader_parameter/radius_inner_1') @@ -32,6 +38,51 @@ func get_radius_inner_1() -> float: return material.get('shader_parameter/radius func set_band_colors(val: Array): material.set('shader_parameter/ant_band_c', val) +## Добавляет сектор запрета[br] +## [param id] - Индекс сектора запрета.[br] +## [param szv.x] - Центральная частота (198...546).[br] +## [param szv.w] - Ширина диапазона (198...546).[br] +## [param szv.y] - Угол центра (0...360).[br] +## [param szv.z] - Ширина по углу (0...360).[br] +func add_seczap(id: int, szv: Vector4): + var seczap: = SecZap.instantiate() + seczap.name = StringName('SECZAP%d' % id) + seczap.position = $строб.position + seczap.set_instance_shader_parameter('dir', szv.y - 90.0) + seczap.set_instance_shader_parameter('width', szv.z) + seczap.set_instance_shader_parameter('band', sv(szv.w)) + seczap.set_instance_shader_parameter('radius', sv(szv.x)) + add_child(seczap) + + +## Удаляет сектор запрета[br] +## [param id] - Индекс сектора запрета[br] +func remove_seczap(id: int): + var seczap: = get_node_or_null('SECZAP%d' % id) + if not seczap: return + remove_child(seczap) + seczap.queue_free() + + +## Изменяет сектор запрета[br] +## [param id] - Индекс сектора запрета[br] +## [param szv.x] - Центральная частота[br] +## [param szv.w] - Ширина диапазона[br] +## [param szv.y] - Угол центра[br] +## [param szv.z] - Ширина по углу[br] +func set_seczap(id: int, szv: Vector4): + var seczap: = get_node('SECZAP%d' % id) + seczap.set_instance_shader_parameter('dir', szv.y) + seczap.set_instance_shader_parameter('width', szv.z) + seczap.set_instance_shader_parameter('band', sv(szv.w)) + seczap.set_instance_shader_parameter('radius', sv(szv.x)) + + +func set_seczap_color(id: int, color: Color): + var seczap: = get_node('SECZAP%d' % id) + seczap.set_instance_shader_parameter('color', color) + + func set_view_mode(val: int): if val == 1: $строб.hide() @@ -42,8 +93,10 @@ func set_view_mode(val: int): ## Закрашивание по умолчанию блоков ФС цветами из настроек. func set_def_colors(): - var color0: Vector3 = ProjectSettings.get_setting('application/interfer/default_color0', Vector3(0.38, 0.47, 0.51)) - var color1: Vector3 = ProjectSettings.get_setting('application/interfer/default_color1', Vector3(0.39, 0.44, 0.50)) + var color0: Color = ProjectSettings.get_setting('application/interfer/default_color0', Color(0.38, 0.47, 0.51, 1.0)) + var color1: Color = ProjectSettings.get_setting('application/interfer/default_color1', Color(0.39, 0.44, 0.50, 1.0)) + color0 *= Color(1.0, 1.0, 1.0, 0.0) + color1 *= Color(1.0, 1.0, 1.0, 0.0) var col_arr: Array = [color0, color1] var col = false for i in NUM_OF_RANGE: diff --git a/scenes/diagram/diagram.tscn b/scenes/diagram/diagram.tscn index 5e8dffd5..bc00d0ab 100644 --- a/scenes/diagram/diagram.tscn +++ b/scenes/diagram/diagram.tscn @@ -11,19 +11,13 @@ size = Vector2(1600, 1200) [sub_resource type="ShaderMaterial" id="ShaderMaterial_lniyv"] resource_local_to_scene = true shader = ExtResource("4_obn6s") -shader_parameter/color = Color(1, 1, 1, 0.168627) -shader_parameter/clip_color = Color(1, 0.5, 0.5, 1) -shader_parameter/width = 45.0 -shader_parameter/band = 0.02 -shader_parameter/radius = 0.08 -shader_parameter/dir = 0.0 -shader_parameter/inner_clip = 0.045 [node name="canvas" type="Sprite2D"] material = ExtResource("1_newdt") texture = SubResource("PlaceholderTexture2D_2bft1") centered = false script = ExtResource("2_8xjuy") +SecZap = ExtResource("3_tgnog") [node name="строб" parent="." instance=ExtResource("3_tgnog")] material = SubResource("ShaderMaterial_lniyv") diff --git a/scenes/diagram/sector.tscn b/scenes/diagram/sector.tscn index 07b8a30c..4edb09b8 100644 --- a/scenes/diagram/sector.tscn +++ b/scenes/diagram/sector.tscn @@ -5,18 +5,16 @@ [sub_resource type="ShaderMaterial" id="ShaderMaterial_xo5or"] resource_local_to_scene = true shader = ExtResource("1_e0gfn") -shader_parameter/color = Color(1, 1, 1, 0.168627) -shader_parameter/clip_color = Color(1, 0.5, 0.5, 1) -shader_parameter/width = 45.0 -shader_parameter/band = 0.02 -shader_parameter/radius = 0.08 -shader_parameter/dir = 0.0 -shader_parameter/inner_clip = 0.045 [sub_resource type="PlaceholderTexture2D" id="PlaceholderTexture2D_2lkm8"] [node name="sector" type="Sprite2D"] material = SubResource("ShaderMaterial_xo5or") +instance_shader_parameters/band = 0.02 +instance_shader_parameters/color = Color(1, 1, 1, 0.188235) +instance_shader_parameters/inner_clip = 0.045 +instance_shader_parameters/radius = 0.08 +instance_shader_parameters/width = 45.0 position = Vector2(610, 600) scale = Vector2(1108, 1108) texture = SubResource("PlaceholderTexture2D_2lkm8") diff --git a/scenes/frame-ecm-list/scroll-ecm-list.gd b/scenes/frame-ecm-list/scroll-ecm-list.gd index eb3beee7..e0f42344 100644 --- a/scenes/frame-ecm-list/scroll-ecm-list.gd +++ b/scenes/frame-ecm-list/scroll-ecm-list.gd @@ -20,7 +20,7 @@ const INTERFER_STATE = { 5: '' } -## Состояние выполнения сеанса помехи +## Названия помех const INTERFER_NAMES = { 'off': 'Откл', 'mchm1': 'МЧМ-1', @@ -46,6 +46,7 @@ const COLUMN_NAME = 1 const COLUMN_AOA = 2 const COLUMN_STATE = 3 +var course = 0.0 ## Курс корабля func on_rto_threat_unsel(_th_id): $table.clear_rows_selected() @@ -88,6 +89,8 @@ func _ready(): interfer.connect('interfer_recommendate', Callable(self, 'on_interfer_recommendate')) $table.connect('row_pressed', Callable(self, 'on_row_pressed')) call_deferred('init_table') + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) func init_table(): @@ -148,7 +151,10 @@ func map_th_to_row(ecm) -> Array: row[COLUMN_NAME] = '' if INTERFER_NAMES.has(ecm.krp): row[COLUMN_NAME] = '%s' % INTERFER_NAMES[ecm.krp] - row[COLUMN_AOA] = '%s' % ecm.kni + var aoa = ecm.kni + course + if aoa > 360.0: + aoa -= 360.0 + row[COLUMN_AOA] = '%5.1f' % aoa row[COLUMN_STATE] = '' if INTERFER_STATE.has(ecm.svk): row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk] @@ -159,7 +165,10 @@ func on_interfer_recommendate(ecm): var sel_rows: Array $table.get_selected_rows(sel_rows) if not len(sel_rows): return - var row = sel_rows[0] var sel_ecm = $table.get_node_user_data(0, sel_rows[0]) if ecm == sel_ecm: signaller.emit_signal('interfer_selected', ecm) + + +func on_navi_data_received(data: Dictionary): + course = data.get('k', 0.0) diff --git a/scenes/frame-threats/scroll-threats.gd b/scenes/frame-threats/scroll-threats.gd index a0f2056c..e2ef9d3b 100644 --- a/scenes/frame-threats/scroll-threats.gd +++ b/scenes/frame-threats/scroll-threats.gd @@ -89,7 +89,8 @@ func map_th_to_row(th) -> Array: row.resize(TABLE_COLUMN_PARAM.size()) var i_col: int = 0 for param_name in TABLE_COLUMN_PARAM: - row[i_col] = '%s' % th.get(param_name) + var val = th.get(param_name) + row[i_col] = '%0.1f' % val if val is float else '%s' % val i_col += 1 return row diff --git a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn index ddad15be..a1b2522a 100644 --- a/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn +++ b/scenes/grid-buttons-ecm/grid-buttons-ecm.tscn @@ -14,7 +14,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "Откл." disabled = true -font_size = 1 metadata/rfi_name = "off" [node name="btn_p12" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -24,7 +23,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "МЧМ-1" disabled = true -font_size = 1 metadata/rfi_name = "mchm1" [node name="btn_p16" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -34,7 +32,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "СРН-И1" disabled = true -font_size = 1 metadata/rfi_name = "srni1" [node name="btn_p15" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -44,7 +41,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "СРН-М2" disabled = true -font_size = 1 metadata/rfi_name = "srnm2" [node name="btn_p18" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -54,7 +50,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "СРН-GPS" disabled = true -font_size = 1 metadata/rfi_name = "srngps" [node name="btn_p14" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -64,7 +59,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ПД-М4" disabled = true -font_size = 1 metadata/rfi_name = "pdm4" [node name="btn_p13" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -74,7 +68,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ПД-М2" disabled = true -font_size = 1 metadata/rfi_name = "pdm2" [node name="btn_p11" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -84,7 +77,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ЛЧМ-1" disabled = true -font_size = 1 metadata/rfi_name = "lchm1" [node name="btn_p17" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -94,7 +86,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ЛЧМ-2" disabled = true -font_size = 1 metadata/rfi_name = "lchm2" [node name="btn_p10" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -104,7 +95,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ПД-М4С" disabled = true -font_size = 1 metadata/rfi_name = "pdm4s" [node name="btn_p9" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -114,7 +104,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ПД-ЧМ" disabled = true -font_size = 1 metadata/rfi_name = "pdchm" [node name="btn_p8" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -124,7 +113,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "СВ-И1" disabled = true -font_size = 1 metadata/rfi_name = "svi1" [node name="btn_p7" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -134,7 +122,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "K1" disabled = true -font_size = 1 metadata/rfi_name = "k1" [node name="btn_p6" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -144,7 +131,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "СВ-М2" disabled = true -font_size = 1 metadata/rfi_name = "svm2" [node name="btn_p5" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -154,7 +140,6 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ОЗП-1" disabled = true -font_size = 1 metadata/rfi_name = "ozp1" [node name="btn_p19" parent="." groups=["группа-режим-помехи"] instance=ExtResource("1_oy80h")] @@ -164,5 +149,4 @@ size_flags_vertical = 3 strips_rotation = 30.0 text = "ЕПРЛС" disabled = true -font_size = 1 metadata/rfi_name = "eprls" diff --git a/scenes/контроль/bort-afsp.tscn b/scenes/pribor-afsp/bort-afsp.tscn similarity index 100% rename from scenes/контроль/bort-afsp.tscn rename to scenes/pribor-afsp/bort-afsp.tscn diff --git a/scenes/pribor-afsp/pribor-afsp-1.tscn b/scenes/pribor-afsp/pribor-afsp-1.tscn index 4ae55a58..867517f0 100644 --- a/scenes/pribor-afsp/pribor-afsp-1.tscn +++ b/scenes/pribor-afsp/pribor-afsp-1.tscn @@ -1,14 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://8ll27id5ajq1"] +[gd_scene load_steps=4 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/контроль/bort-afsp.tscn" id="3_d7iti"] - -[sub_resource type="GDScript" id="GDScript_yhnwg"] -script/source = "extends Timer - -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_rr_request_period') -" +[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_d7iti"] [node name="pribor_afsp" type="Control"] layout_mode = 3 @@ -19,17 +13,20 @@ offset_right = 70.0 offset_bottom = 30.0 scale = Vector2(1, 0.9) script = ExtResource("1_151rh") +prefix_path = "DeviceDescription[DeviceName]" +this_afsp_name = "Устройство РР левого борта" +unit_name = &"уарэп-афсп-левый" +settings_path_to_url = "Адрес АФСП левого борта" +settings_path_to_wait_time = "Период опроса состояния АФСП, секунды" metadata/DeviceName = &"Устройство РР левого борта" [node name="request" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("2_4vyhj") -projsettings_path_left = "application/config/Адрес АФСП левого борта" -projsettings_path_right = "application/config/Адрес АФСП правого борта" +request_url = null [node name="timer" type="Timer" parent="request"] autostart = true -script = SubResource("GDScript_yhnwg") [node name="bort" parent="." instance=ExtResource("3_d7iti")] layout_mode = 0 diff --git a/scenes/pribor-afsp/pribor-afsp-2.tscn b/scenes/pribor-afsp/pribor-afsp-2.tscn index 9d8b4cc7..51ff32da 100644 --- a/scenes/pribor-afsp/pribor-afsp-2.tscn +++ b/scenes/pribor-afsp/pribor-afsp-2.tscn @@ -1,14 +1,8 @@ -[gd_scene load_steps=5 format=3 uid="uid://5uv1idl3lqet"] +[gd_scene load_steps=4 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/контроль/bort-afsp.tscn" id="3_xpxb5"] - -[sub_resource type="GDScript" id="GDScript_yhnwg"] -script/source = "extends Timer - -func _ready(): wait_time = ProjectSettings.get_setting('application/config/unit_rr_request_period') -" +[ext_resource type="PackedScene" uid="uid://dnxq870xf6pkh" path="res://scenes/pribor-afsp/bort-afsp.tscn" id="3_xpxb5"] [node name="pribor_afsp" type="Control"] layout_mode = 3 @@ -19,17 +13,20 @@ offset_right = 81.0 offset_bottom = 108.0 scale = Vector2(1, 0.9) script = ExtResource("1_tfses") +prefix_path = "DeviceDescription[DeviceName]" +this_afsp_name = "Устройство РР правого борта" +unit_name = &"уарэп-афсп-правый" +settings_path_to_url = "Адрес АФСП правого борта" +settings_path_to_wait_time = "Период опроса состояния АФСП, секунды" metadata/DeviceName = &"Устройство РР правого борта" [node name="request" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("2_miwrd") -projsettings_path_left = "application/config/Адрес АФСП левого борта" -projsettings_path_right = "application/config/Адрес АФСП правого борта" +request_url = null [node name="timer" type="Timer" parent="request"] autostart = true -script = SubResource("GDScript_yhnwg") [node name="bort" parent="." instance=ExtResource("3_xpxb5")] layout_mode = 0 diff --git a/scenes/pribor-afsp/pribor-afsp.gd b/scenes/pribor-afsp/pribor-afsp.gd index 319ed927..67a150ba 100644 --- a/scenes/pribor-afsp/pribor-afsp.gd +++ b/scenes/pribor-afsp/pribor-afsp.gd @@ -1,26 +1,57 @@ @tool class_name pribor_afsp extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescripton[DeviceName]' +@export var prefix_path: String = '' ## Должно быть в JSON +@export var this_afsp_name: String = '' ## Должно быть в JSON +@export var unit_name: StringName= '' ## Должно быть в settings.gd +@export var settings_path_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') +var ctrl_pos = 0 + +# SystemName: "gen" DevList - там состояние связи с генератором по кан шине + + +func _ready() -> void: + ProjectSettings.connect('settings_changed', on_settings_chaged) + on_settings_chaged() + + +func on_settings_chaged(): + $request.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path_to_url) + $request/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + tools.allways($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 = $request.get_result_string(result) log.error('\"%s\"' % rs) + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) return var json_str: String = body.get_string_from_utf8() if not json_str: push_error('не удаётся получить строку utf8 из данных (%s)' % headers) + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) return - var rc = json_conv.parse(json_str) + var rc: = json_conv.parse(json_str) if rc != Error.OK: - var err = json_conv.get_error_message() + 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 var pp = [] @@ -32,12 +63,18 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra push_error('путь %s не найден (%s)' % [pp_copy, ret_val[2]]) return - var this_afsp_name: StringName = $bort.get_meta('DeviceName', '') 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 + 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) + 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') @@ -63,4 +100,3 @@ 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) - print_debug('%s:%s' % [n, v]) diff --git a/scenes/pribor-afsp/pribor-bpo.gd b/scenes/pribor-afsp/pribor-bpo.gd index 941bde1a..e68f542c 100644 --- a/scenes/pribor-afsp/pribor-bpo.gd +++ b/scenes/pribor-afsp/pribor-bpo.gd @@ -1,29 +1,55 @@ @tool class_name pribor_rtr extends 'res://scenes/контроль/прибор.gd' -@export var prefix_path: String = 'DeviceDescripton[DeviceName]' +@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 settings_path1_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path2_to_url: String = '' ## Должно быть в ProjectSettings +@export var settings_path_to_wait_time: String = '' ## Должно быть в ProjectSettings + static var json_conv: JSON = JSON.new() static var node_maper = load('res://scenes/контроль/node-maper.gd') +var ctrl_pos = 110 -const bort_to_node_name = { - 'Устройство РР левого борта': 'grid_bpo_a1', - 'Устройство РР правого борта': 'grid_bpo_a2'} +var bort_to_node_name = {} +var bort_to_unit_name = {} + + + +func _ready() -> void: + ProjectSettings.connect('settings_changed', on_settings_changed) + on_settings_changed() + find_labels(self) + + +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}) + $request1.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path1_to_url) + $request1/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + $request2.request_url = ProjectSettings.get_setting('application/config/%s' % settings_path2_to_url) + $request2/timer.wait_time = float(ProjectSettings.get_setting('application/config/%s' % settings_path_to_wait_time)) + assert($request1.request_url != null) + assert($request2.request_url != null) func _on_request_completed(result, _response_code, headers, body: PackedByteArray): if result != 0: - var rs = $request.get_result_string(result) - log.error('\"%s\"' % rs) + var rs = $request1.get_result_string(result) + push_error('\"%s\"' % rs) return - var json_str: String = body.get_string_from_utf8() + var json_str: = body.get_string_from_utf8() if not json_str: push_error('не удаётся получить строку из utf8-данных (%s)' % headers) return - var rc = json_conv.parse(json_str) + 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]) @@ -39,10 +65,50 @@ func _on_request_completed(result, _response_code, headers, body: PackedByteArra return if not bort_to_node_name.has(ret_val[0]): + push_error('не известное устройство: \"%s\"' % ret_val[0]) return var node_name = bort_to_node_name[ret_val[0]] 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) + for item in bort_node.get_children(): node_maper.map_value_to_item(json_conv.data, item, 'state') + + var items = get_tree().get_nodes_in_group('управляется-по-шине-1') + for node in items: + if node.state == 1: + $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 + break + items = get_tree().get_nodes_in_group('потребитель-питания') + for node in items: + if node.state == 1: + $mod_pit_g1.state = 1 + break + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-afsp/pribor-bpo.tscn b/scenes/pribor-afsp/pribor-bpo.tscn index 71ae79cd..36d5db08 100644 --- a/scenes/pribor-afsp/pribor-bpo.tscn +++ b/scenes/pribor-afsp/pribor-bpo.tscn @@ -13,6 +13,14 @@ offset_top = 150.0 offset_right = 115.0 offset_bottom = 150.0 script = ExtResource("1_bhc4e") +prefix_path = "DeviceDescription[DeviceName]" +this_bpo1_name = "Устройство БПО левого борта" +this_bpo2_name = "Устройство БПО правого борта" +unit_name1 = &"уарэп-бпо-1" +unit_name2 = &"уарэп-бпо-2" +settings_path1_to_url = "Адрес БПО левого борта" +settings_path2_to_url = "Адрес БПО правого борта" +settings_path_to_wait_time = "Период опроса состояния БПО, секунды" [node name="mod_pit_g1" parent="." instance=ExtResource("2_jp6m0")] layout_mode = 2 @@ -43,63 +51,63 @@ offset_right = 498.0 offset_bottom = 320.0 columns = 4 -[node name="kanal1" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal1" parent="grid_bpo_a1" groups=["потребитель-питания"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 1" metadata/state = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']" -[node name="kanal2" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal2" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 2" metadata/state = "SelfTest[0].SystemList[0].DevList[1]['TestPassed']" -[node name="kanal3" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal3" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 3" metadata/state = "SelfTest[0].SystemList[0].DevList[2]['TestPassed']" -[node name="kanal4" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal4" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 4" metadata/state = "SelfTest[0].SystemList[0].DevList[3]['TestPassed']" -[node name="kanal5" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal5" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 5" metadata/state = "SelfTest[0].SystemList[0].DevList[4]['TestPassed']" -[node name="kanal6" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal6" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 6" metadata/state = "SelfTest[0].SystemList[0].DevList[5]['TestPassed']" -[node name="kanal7" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal7" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 7" metadata/state = "SelfTest[0].SystemList[0].DevList[6]['TestPassed']" -[node name="kanal8" parent="grid_bpo_a1" instance=ExtResource("2_jp6m0")] +[node name="kanal8" parent="grid_bpo_a1" groups=["потребитель-питания", "управляется-по-шине-1"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 8" metadata/state = "SelfTest[0].SystemList[0].DevList[7]['TestPassed']" -[node name="yas_bpo_a1" parent="." instance=ExtResource("3_jcpjs")] +[node name="yas_bpo_a1" parent="." groups=["потребитель-питания"] instance=ExtResource("3_jcpjs")] offset_left = 500.0 offset_top = 175.0 offset_right = 550.0 @@ -126,63 +134,63 @@ offset_right = 498.0 offset_bottom = 520.0 columns = 4 -[node name="kanal1" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal1" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 1" metadata/state = "SelfTest[0].SystemList[0].DevList[0]['TestPassed']" -[node name="kanal2" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal2" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 2" metadata/state = "SelfTest[0].SystemList[0].DevList[1]['TestPassed']" -[node name="kanal3" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal3" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 3" metadata/state = "SelfTest[0].SystemList[0].DevList[2]['TestPassed']" -[node name="kanal4" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal4" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 4" metadata/state = "SelfTest[0].SystemList[0].DevList[3]['TestPassed']" -[node name="kanal5" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal5" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 5" metadata/state = "SelfTest[0].SystemList[0].DevList[4]['TestPassed']" -[node name="kanal6" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal6" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 6" metadata/state = "SelfTest[0].SystemList[0].DevList[5]['TestPassed']" -[node name="kanal7" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal7" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 7" metadata/state = "SelfTest[0].SystemList[0].DevList[6]['TestPassed']" -[node name="kanal8" parent="grid_bpo_a2" instance=ExtResource("2_jp6m0")] +[node name="kanal8" parent="grid_bpo_a2" groups=["потребитель-питания", "управляется-по-шине-2"] instance=ExtResource("2_jp6m0")] layout_mode = 2 size_flags_horizontal = 7 size_flags_vertical = 7 fname = "Канал 8" metadata/state = "SelfTest[0].SystemList[0].DevList[7]['TestPassed']" -[node name="yas_bpo_a2" parent="." instance=ExtResource("3_jcpjs")] +[node name="yas_bpo_a2" parent="." groups=["потребитель-питания"] instance=ExtResource("3_jcpjs")] offset_left = 500.0 offset_top = 375.0 offset_right = 550.0 @@ -191,14 +199,22 @@ show_rname = false self_size = Vector2i(50, 145) fname = "Яч. связи" -[node name="request" type="HTTPRequest" parent="."] +[node name="request1" type="HTTPRequest" parent="."] use_threads = true script = ExtResource("4_crej3") -projsettings_path_left = "application/config/Адрес БПО левого борта" -projsettings_path_right = "application/config/Адрес БПО правого борта" +request_url = null -[node name="timer" type="Timer" parent="request"] +[node name="timer" type="Timer" parent="request1"] autostart = true -[connection signal="request_completed" from="request" to="." method="_on_request_completed"] -[connection signal="timeout" from="request/timer" to="request" method="_on_request_timer"] +[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"] diff --git a/scenes/pribor-prd-k/pribor-prd-k.gd b/scenes/pribor-prd-k/pribor-prd-k.gd index 18a4a231..12be8885 100644 --- a/scenes/pribor-prd-k/pribor-prd-k.gd +++ b/scenes/pribor-prd-k/pribor-prd-k.gd @@ -15,10 +15,10 @@ const constants_k: Dictionary = { 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, 'ATT_UM_1': 0x0, - 'ATT_UM_6': 0x7, - 'ATT_UM_7': 0x7, - 'POWER_UM': 85, - 'TIMER_DELAY': 5.0, + 'ATT_UM_6': 0x3, + 'ATT_UM_7': 0x2, + 'POWER_UM': 100, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора @@ -55,9 +55,9 @@ var block_kasseta_y5_prd_config_k: = { } # Основные переменные var start_litera: int = 1 -var ug_work_1: int = 0 -var ug_work_2: int = 0 -var ug_work_3: int = 0 +var ug_work_1: int = 3 ## Аттенюация усилителей мощности +var ug_work_2: int = 2 ## Аттенюация усилителей мощности +var ug_work_3: int = 0 ## Аттенюация усилителей мощности var mashine_timer: Timer = Timer.new() var prd_k_module: Object var unit_prd_k: Object @@ -77,6 +77,7 @@ var control_results_k: Dictionary = { } var test_control_k = preload('res://scripts/pribor-prd.gd') +var ctrl_pos = 30 func _ready() -> void: @@ -86,6 +87,7 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() + find_labels(self) func on_state_mashine() -> void: @@ -166,7 +168,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: #if not control_prd_k.block_kasseta_y5_config.yau07 or not control_prd_k.block_kasseta_y5_config.ukp1 or not control_prd_k.block_kasseta_y5_config.ukp2: #return var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') @@ -179,6 +181,9 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta == 'um_7' and not fs_result.fs_1: return + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_6: return + if powamp_meta in ['um_8', 'um_9', 'um_10', 'um_11', 'um_12', 'um_13'] and not fs_result.fs_7: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_k.POWER_THRESHOLD: @@ -228,7 +233,7 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: result_dic.fs_7 = false - power_fill(power_dic) + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): @@ -242,3 +247,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-prd-n/pribor-prd-n.gd b/scenes/pribor-prd-n/pribor-prd-n.gd index 6e177be2..c69b5530 100644 --- a/scenes/pribor-prd-n/pribor-prd-n.gd +++ b/scenes/pribor-prd-n/pribor-prd-n.gd @@ -13,10 +13,10 @@ const constants_n = { 'TEMP_THRESHOLD': 70, 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, - 'ATT_UM_2': 0x7, - 'ATT_UM_3': 0x7, - 'POWER_UM': 70, - 'TIMER_DELAY': 5.0, + 'ATT_UM_2': 0x2, + 'ATT_UM_3': 0x3, + 'POWER_UM': 100, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора @@ -28,7 +28,7 @@ const PRIBOR_CONFIG_N := { } # Конфигурация частот и ширин для каждого ФС const FS_PARAMS_N := { - 2: {'freq': 900.0, 'width': 100.0}, + 2: {'freq': 932.0, 'width': 100.0}, 3: {'freq': 1157.0, 'width': 100.0} } enum STATE_VAL { NONE = 0, GOOD = 1, ERROR = 2 } @@ -50,8 +50,8 @@ var block_kasseta_y5_prd_config_n: = { # Основные переменные var start_litera: int = 2 -var ug_work_1: int = 0 -var ug_work_2: int = 0 +var ug_work_1: int = 2 ## Аттенюация усилителей мощности +var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() var prd_n_module: Object @@ -69,8 +69,7 @@ var control_results_n: Dictionary = { 'fs_3': 2, } var test_control_n = preload('res://scripts/pribor-prd.gd') - - +var ctrl_pos = 0 ################################ func on_state_mashine() -> void: control_prd_n.state_control_machine() @@ -83,6 +82,7 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() + find_labels(self) func initialize_connections() -> void: @@ -159,7 +159,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: #if not control_prd_n.block_kasseta_y5_config.yau07 or not control_prd_n.block_kasseta_y5_config.ukp1 or not control_prd_n.block_kasseta_y5_config.ukp2: #return var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') @@ -169,6 +169,8 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_2: return + if powamp_meta in ['um_7', 'um_8', 'um_9', 'um_10', 'um_11', 'um_12'] and not fs_result.fs_3: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_n.POWER_THRESHOLD: @@ -207,14 +209,14 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: $kasseta_FS_ND/ref_A4.state = STATE_VAL.GOOD if result_dic.dkm_2 else STATE_VAL.ERROR $dou2_A5.state = STATE_VAL.GOOD if result_dic.dou_2 else STATE_VAL.ERROR else: - result_dic.fs_2 = false + result_dic.fs_2 = 0 if result_dic.fs_3 == 1: $kasseta_FS_ND/ref_A3.state = STATE_VAL.GOOD if result_dic.dkm_3 else STATE_VAL.ERROR $dou3_A6.state = STATE_VAL.GOOD if result_dic.dou_3 else STATE_VAL.ERROR else: - result_dic.fs_3 = false + result_dic.fs_3 = 0 - power_fill(power_dic) + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): @@ -228,3 +230,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-prd-v/pribor-prd-v.gd b/scenes/pribor-prd-v/pribor-prd-v.gd index ff1e90f9..a40768ad 100644 --- a/scenes/pribor-prd-v/pribor-prd-v.gd +++ b/scenes/pribor-prd-v/pribor-prd-v.gd @@ -13,10 +13,10 @@ const constants_v = { 'TEMP_THRESHOLD': 70, 'POWER_THRESHOLD': 40, 'RAY_DOU_NUM': 0x3, - 'ATT_UM_4': 0x7, - 'ATT_UM_5': 0x7, - 'POWER_UM': 75, - 'TIMER_DELAY': 5.0, + 'ATT_UM_4': 0x2, + 'ATT_UM_5': 0x3, + 'POWER_UM': 100, + 'TIMER_DELAY': 10.0, 'STATE_MASHINE_TIMER': 0.3, } # Конфигурация параметров для каждого прибора @@ -50,8 +50,8 @@ var block_kasseta_y5_prd_config_v: = { # Основные переменные var start_litera: int = 4 -var ug_work_1: int = 0 -var ug_work_2: int = 0 +var ug_work_1: int = 2 ## Аттенюация усилителей мощности +var ug_work_2: int = 3 ## Аттенюация усилителей мощности # Флаги и таймеры var mashine_timer: Timer = Timer.new() var prd_v_module: Object @@ -69,6 +69,7 @@ var control_results_v: Dictionary = { 'fs_5': 2, } var test_control_v = preload('res://scripts/pribor-prd.gd') +var ctrl_pos = 70 func on_state_mashine() -> void: @@ -82,6 +83,7 @@ func _ready() -> void: initialize_connections() setup_timer() set_default_state() + find_labels(self) func initialize_connections() -> void: @@ -159,9 +161,7 @@ func on_mode_changed(in_tree: bool) -> void: mashine_timer.start() -func power_fill(pow_dic: Dictionary) -> void: - #if not control_prd_v.block_kasseta_y5_config.yau07 or not control_prd_v.block_kasseta_y5_config.ukp1 or not control_prd_v.block_kasseta_y5_config.ukp2: - #return +func power_fill(pow_dic: Dictionary, fs_result: Dictionary) -> void: var power_amplifier: Array = get_tree().get_nodes_in_group('power_amplifier') for i_powapm in power_amplifier: var powamp_meta: String = i_powapm.get_meta('um') @@ -169,6 +169,8 @@ func power_fill(pow_dic: Dictionary) -> void: if pow_dic[powamp_meta].size() < 6: status = STATE_VAL.ERROR else: + if powamp_meta in ['um_1', 'um_2', 'um_3', 'um_4', 'um_5', 'um_6'] and not fs_result.fs_4: return + if powamp_meta in ['um_7', 'um_8', 'um_9', 'um_10', 'um_11', 'um_12'] and not fs_result.fs_5: return i_powapm.value0 = pow_dic[powamp_meta] for i_p in pow_dic[powamp_meta]: if i_p < constants_v.POWER_THRESHOLD: @@ -207,13 +209,13 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: $kasseta_FS_VD/ref_A2.state = STATE_VAL.GOOD if result_dic.dkm_5 else STATE_VAL.ERROR $dou5_A6.state = STATE_VAL.GOOD if result_dic.dou_5 else STATE_VAL.ERROR else: - result_dic.fs_5 = false + result_dic.fs_5 = 0 if result_dic.fs_4 == 1: $kasseta_FS_VD/ref_A6.state = STATE_VAL.GOOD if result_dic.dkm_4 else STATE_VAL.ERROR $dou4_A5.state = STATE_VAL.GOOD if result_dic.dou_4 else STATE_VAL.ERROR else: - result_dic.fs_4 = false - power_fill(power_dic) + result_dic.fs_4 = 0 + power_fill(power_dic, result_dic) var result = true for device in result_dic.values(): @@ -227,3 +229,19 @@ func on_control_result(result_dic: Dictionary, power_dic: Dictionary) -> void: else: $control_result.text = 'Прибор ПРД-%s неисправен' % name_prd $control_result.add_theme_color_override('font_color', Color.RED) + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-uf/pribor-uf.gd b/scenes/pribor-uf/pribor-uf.gd index 1c38a802..5f6b0380 100644 --- a/scenes/pribor-uf/pribor-uf.gd +++ b/scenes/pribor-uf/pribor-uf.gd @@ -5,18 +5,21 @@ enum STATE_VAL {NONE = 0, GOOD = 1, ERROR = 2} const DEV_LIST = ['00:1f.6', '07:00.0', '08:00.0', '0b:00.0'] const USB_TRACKERBALL = '13ba:0018' const REVFF = '(rev ff)' +var ctrl_pos = 100 func _ready() -> void: if Engine.is_editor_hint(): return - var unit_uf = network.get_unit_instance('уарэп-эмс') + var unit_uf: = network.get_unit_instance('уарэп-эмс') unit_uf.connect('line_changed', on_line_changed) - on_timer.bind(unit_uf) control_vk() + on_line_changed(unit_uf) + find_labels(self) -func on_timer(unit_uf: unit.Unit): +func on_timer(unit_name: StringName): + var unit_uf = network.get_unit_instance(unit_name) status_uf() # отслеживание состояния прибора if unit_uf.online: # проверка ЯУ, внутреннего коммутатора и ИП-5Б control_ems(unit_uf.status) # проверка ЭМС ячеек @@ -73,6 +76,8 @@ func control_vk() -> void: else: $ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.ERROR + $ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD ## заглушка для зеленения ВК-110 + func control_ems(status: Array) -> void: $ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.GOOD if ((status[0] >> 0) & 1) and ((status[0] >> 3) & 1) else STATE_VAL.ERROR @@ -98,3 +103,19 @@ func status_uf() -> void: $lbl_header2.text = 'Прибор не исправен' $lbl_header2.modulate = Color.RED $lbl_header2.visible = true + + +func find_labels(node1: Node): + if node1 is Label: + if node1.name in ["lbl_rname", "rname"]: + if not node1.has_meta("tooltip_set"): + ctrl_pos += 1 + var box_number = ceili(float(ctrl_pos) / 10.0) + var position_number = ctrl_pos % 10 + if position_number == 0: + position_number = 10 + node1.tooltip_text = "Ящик - %d, Позиция - %d" % [box_number, position_number] + node1.mouse_filter = Control.MOUSE_FILTER_STOP + node1.set_meta("tooltip_set", true) + for child in node1.get_children(): + find_labels(child) diff --git a/scenes/pribor-uf/pribor-uf.tscn b/scenes/pribor-uf/pribor-uf.tscn index 9b63dc86..998ace6e 100644 --- a/scenes/pribor-uf/pribor-uf.tscn +++ b/scenes/pribor-uf/pribor-uf.tscn @@ -155,3 +155,6 @@ horizontal_alignment = 1 vertical_alignment = 1 [node name="timer" type="Timer" parent="."] +autostart = true + +[connection signal="timeout" from="timer" to="." method="on_timer" binds= [&"уарэп-эмс"]] diff --git a/scenes/pribor-uyep/pribor-uyep.tscn b/scenes/pribor-uyep/pribor-uyep.tscn index 4748443f..e78e7826 100644 --- a/scenes/pribor-uyep/pribor-uyep.tscn +++ b/scenes/pribor-uyep/pribor-uyep.tscn @@ -33,6 +33,7 @@ offset_left = 88.0 offset_top = 319.0 offset_right = 343.0 offset_bottom = 749.0 +tooltip_text = "Ящик - 11, Позиция - 3" script = ExtResource("4_v0lil") unit_name = "уарэп-спт25-1" fname = "СПТ-25-230-400-3" @@ -67,6 +68,7 @@ offset_left = 392.0 offset_top = 320.0 offset_right = 642.0 offset_bottom = 750.0 +tooltip_text = "Ящик - 11, Позиция - 2" script = ExtResource("4_v0lil") unit_name = "уарэп-спт25-2" fname = "СПТ-25-230-400-3" diff --git a/scenes/pribor-uyep/sch3.tscn b/scenes/pribor-uyep/sch3.tscn index a175a03f..296270da 100644 --- a/scenes/pribor-uyep/sch3.tscn +++ b/scenes/pribor-uyep/sch3.tscn @@ -106,7 +106,7 @@ vertical_alignment = 1 layout_mode = 2 size_flags_horizontal = 3 size_flags_vertical = 6 -tooltip_text = "Позиционное обозначение" +tooltip_text = "Ящик - 11, Позиция - 1" mouse_filter = 0 theme_override_font_sizes/font_size = 22 horizontal_alignment = 2 diff --git a/scenes/pribor-uyep/spt25-view.gd b/scenes/pribor-uyep/spt25-view.gd index 30066a90..02938f55 100644 --- a/scenes/pribor-uyep/spt25-view.gd +++ b/scenes/pribor-uyep/spt25-view.gd @@ -3,8 +3,8 @@ extends 'res://scenes/контроль/элемент-я.gd' -func on_line_changed(unit0): - if not unit0.online: +func on_line_changed(unit_instance): + if not unit_instance.online: disable_all() diff --git a/scenes/tabs-switch/lbl_ready.gd b/scenes/tabs-switch/lbl_ready.gd new file mode 100644 index 00000000..f35d4eda --- /dev/null +++ b/scenes/tabs-switch/lbl_ready.gd @@ -0,0 +1,48 @@ +extends Label +# Используем более понятные имена переменных +const STATUS_GOOD := {"text": "Исправно", "color": Color.GREEN, "font_color": Color.BLACK} +const STATUS_BAD := {"text": "Отказ", "color": Color.RED, "font_color": Color.WHITE} +var _is_uf_status_initialized: bool = false +var is_prd_operational: bool = true +var is_uf_operational: bool = false + + +func _ready() -> void: + tooltip_text = 'Нет связи с приборами комплекса' + for prd_module in prd.prd_dict.values(): + prd_module.connect('update_serviceability', Callable(self, 'on_serviceability_changed').bind(prd_module)) + var unit_uf: = network.get_unit_instance('уарэп-эмс') + unit_uf.connect('data_received', Callable(self, 'on_uf_status_receive')) + add_theme_color_override("font_color", Color.BLACK) + + +func on_serviceability_changed(unit_prd_module: Object) -> void: + var check_service: bool = true + for prd_module in prd.prd_dict.values(): + if prd_module.unit_yau07.online: + if not unit_prd_module.serviceability: + check_service = false + if check_service != is_prd_operational: + is_prd_operational = check_service + _update_serviceability_display() + + +func _update_serviceability_display() -> void: + var status := STATUS_GOOD if (is_uf_operational and is_prd_operational) else STATUS_BAD + text = status.text + modulate = status.color + tooltip_text = 'Результаты обобщенного признака работоспособности изделия' + add_theme_color_override("font_color", status.font_color) + + +func on_uf_status_receive(unit_uf: Object) -> void: + var KEMS_B = ((unit_uf.status[0] >> 0) & 1) and ((unit_uf.status[0] >> 3) & 1) + var EMS_B_1 = ((unit_uf.status[0] >> 1) & 1) and ((unit_uf.status[0] >> 4) & 1) + var EMS_B_2 = ((unit_uf.status[0] >> 2) & 1) and ((unit_uf.status[0] >> 5) & 1) + var IP27B = ((unit_uf.status[2] >> 6) & 1) + var check_service: bool = KEMS_B and EMS_B_1 and EMS_B_2 and IP27B + if not _is_uf_status_initialized or check_service != is_uf_operational: + is_uf_operational = check_service + _update_serviceability_display() + signaller.emit_signal('update_uf_serviceability', check_service) + _is_uf_status_initialized = true diff --git a/scenes/tabs-switch/lbl_ready.gd.uid b/scenes/tabs-switch/lbl_ready.gd.uid new file mode 100644 index 00000000..6476ba86 --- /dev/null +++ b/scenes/tabs-switch/lbl_ready.gd.uid @@ -0,0 +1 @@ +uid://b5ykwyk5vpi6 diff --git a/scenes/tabs-switch/tab-switch.gd b/scenes/tabs-switch/tab-switch.gd index 66f14765..6e510749 100644 --- a/scenes/tabs-switch/tab-switch.gd +++ b/scenes/tabs-switch/tab-switch.gd @@ -9,21 +9,17 @@ const TAB_TOSIGNAL_NAME = { 5: 'режим_настройки' } +func on_ems2_hide_pressed(state): set_tab_hidden(4, state) +func _on_tab_changed(tab) -> void: signaller.emit_signal(TAB_TOSIGNAL_NAME[tab]) +func _on_button_trenazh_toggled(toggled_mode: bool) -> void: signaller.emit_signal('режим_тренаж', toggled_mode) + + func _enter_tree() -> void: network.logger_page = $Журнал signaller.connect('ems2_hide_pressed', on_ems2_hide_pressed) ProjectSettings.connect('settings_changed', on_setting_changed) -func on_ems2_hide_pressed(state): - set_tab_hidden(4, state) - - -func _on_tab_changed(tab) -> void: - if TAB_TOSIGNAL_NAME.has(tab): - signaller.emit_signal(TAB_TOSIGNAL_NAME[tab]) - - func on_setting_changed(): var ext_cu = ProjectSettings.get_setting('application/config/Внешнее управление', false) get_parent().get_node('remote_control').visible = ext_cu diff --git a/scenes/tabs-switch/tab-switch.tscn b/scenes/tabs-switch/tab-switch.tscn index 477a9670..b33b2b9e 100644 --- a/scenes/tabs-switch/tab-switch.tscn +++ b/scenes/tabs-switch/tab-switch.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=14 format=3 uid="uid://3slb0i3pvowc"] +[gd_scene load_steps=20 format=3 uid="uid://3slb0i3pvowc"] [ext_resource type="Script" uid="uid://bvo6tcreqyuex" path="res://scenes/tabs-switch/tab-switch.gd" id="1_fg0vd"] [ext_resource type="PackedScene" uid="uid://b276iygic5itk" path="res://scenes/работа/работа.tscn" id="2_u7p16"] @@ -7,6 +7,8 @@ [ext_resource type="PackedScene" uid="uid://dab6loryocc73" path="res://scenes/эмс/эмс.tscn" id="5_u71bh"] [ext_resource type="PackedScene" uid="uid://bnptm4rlp60dq" path="res://scenes/настройки/настройки.tscn" id="6_i8iv3"] [ext_resource type="PackedScene" uid="uid://musb21x2u0xs" path="res://scenes/эмс2/эмс2.tscn" id="6_rsg03"] +[ext_resource type="Script" uid="uid://b5ykwyk5vpi6" path="res://scenes/tabs-switch/lbl_ready.gd" id="8_tidwt"] +[ext_resource type="Script" uid="uid://roajn6c6wvc1" path="res://scenes/tabs-switch/тренаж_режим.gd" id="9_41d34"] [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_tidwt"] @@ -20,6 +22,17 @@ [sub_resource type="StyleBoxFlat" id="StyleBoxFlat_o1r22"] +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_nmdfd"] +bg_color = Color(0.061, 100, 0.051, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_cw2ss"] +bg_color = Color(0.473976, 0.473976, 0.473976, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_41d34"] +bg_color = Color(0.39, 100, 0.327, 1) + +[sub_resource type="StyleBoxFlat" id="StyleBoxFlat_imu1q"] + [node name="panel" type="Panel"] offset_right = 1600.0 offset_bottom = 1200.0 @@ -56,7 +69,7 @@ visible = false layout_mode = 2 metadata/_tab_index = 3 -[node name="ЭМС2" parent="tab_switch" instance=ExtResource("6_rsg03")] +[node name="ЭМС ТГ" parent="tab_switch" instance=ExtResource("6_rsg03")] visible = false layout_mode = 2 metadata/_tab_index = 4 @@ -73,12 +86,13 @@ offset_right = 1600.0 offset_bottom = 27.0 tooltip_text = "Готовность аппаратуры к работе" mouse_filter = 0 -theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_font_sizes/font_size = 14 theme_override_styles/normal = SubResource("StyleBoxFlat_o1r22") -text = "Исправно" +text = "Нет связи" horizontal_alignment = 1 vertical_alignment = 1 +script = ExtResource("8_tidwt") +metadata/_edit_lock_ = true [node name="remote_control" type="Label" parent="."] visible = false @@ -95,4 +109,23 @@ text = "Внешнее управление" horizontal_alignment = 1 vertical_alignment = 1 +[node name="тренаж_режим" type="Button" parent="."] +layout_mode = 0 +offset_left = 1404.0 +offset_right = 1501.0 +offset_bottom = 27.0 +tooltip_text = "Задействовать режим Тренаж" +focus_mode = 0 +theme_override_colors/font_hover_pressed_color = Color(0, 0, 0, 1) +theme_override_colors/font_color = Color(0, 0, 0, 1) +theme_override_colors/font_pressed_color = Color(0, 0, 0, 1) +theme_override_styles/hover_pressed = SubResource("StyleBoxFlat_nmdfd") +theme_override_styles/hover = SubResource("StyleBoxFlat_cw2ss") +theme_override_styles/pressed = SubResource("StyleBoxFlat_41d34") +theme_override_styles/normal = SubResource("StyleBoxFlat_imu1q") +toggle_mode = true +text = "Тренаж" +script = ExtResource("9_41d34") + [connection signal="tab_changed" from="tab_switch" to="tab_switch" method="_on_tab_changed"] +[connection signal="toggled" from="тренаж_режим" to="tab_switch" method="_on_button_trenaj_toggled"] diff --git a/scenes/tabs-switch/тренаж_режим.gd b/scenes/tabs-switch/тренаж_режим.gd new file mode 100644 index 00000000..ace4117d --- /dev/null +++ b/scenes/tabs-switch/тренаж_режим.gd @@ -0,0 +1,11 @@ +extends Button + +func _ready(): + connect("toggled", Callable(self, "_on_button_toggled")) + + +func _on_button_toggled(mode: bool): + if mode: + tooltip_text = "Режим \"Тренаж\" задействован\nТекущее состояние: включено" + else: + tooltip_text = "Задейстовать режим \"Тренаж\"\nТекущее состояние: отключено" diff --git a/scenes/tabs-switch/тренаж_режим.gd.uid b/scenes/tabs-switch/тренаж_режим.gd.uid new file mode 100644 index 00000000..89b2121e --- /dev/null +++ b/scenes/tabs-switch/тренаж_режим.gd.uid @@ -0,0 +1 @@ +uid://roajn6c6wvc1 diff --git a/scenes/tilemap/23900.png b/scenes/tilemap/23900.png index b92410e3..b7ca1d1b 100644 Binary files a/scenes/tilemap/23900.png and b/scenes/tilemap/23900.png differ diff --git a/scenes/tilemap/ship_mark.tscn b/scenes/tilemap/ship_mark.tscn index 78d04640..096387d0 100644 --- a/scenes/tilemap/ship_mark.tscn +++ b/scenes/tilemap/ship_mark.tscn @@ -3,6 +3,7 @@ [ext_resource type="Texture2D" uid="uid://cj1f2uy6qfvki" path="res://scenes/tilemap/23900.png" id="1_v0nwa"] [node name="23900" type="Sprite2D"] +position = Vector2(0.0, 0.0) rotation = 4.71239 -scale = Vector2(0.0257427, 0.0257427) +scale = Vector2(0.496934, 0.496934) texture = ExtResource("1_v0nwa") diff --git a/scenes/tilemap/tilemap.gd b/scenes/tilemap/tilemap.gd index d06c8f06..d546a2f8 100644 --- a/scenes/tilemap/tilemap.gd +++ b/scenes/tilemap/tilemap.gd @@ -23,6 +23,8 @@ const TILE_REQUEST_NAME: = 'tile_request_%d' @export_range(0, 20, 1) var min_zoom_level: int = 0 @export_range(0, 20, 1) var max_zoom_level_server: int = 20 @export_color_no_alpha() var back_color: = Color.BLACK +@export var show_ship_radius: bool = true +@export var ship_radius_km: float = 8.0 @onready var scale_label: String @onready var coordinates_label: String @onready var threat_mark: PackedScene = load("res://scenes/tilemap/threat.tscn") @@ -34,6 +36,8 @@ var is_centered: = false var is_out_border1: = true var is_out_border2: = true var threat_markers := {} +var zoom_timer: Timer +var zoom_action: String @export var animation_time: float = 0.1: set(val): @@ -86,7 +90,6 @@ var image: = Image.new() var image_load_proc: Callable var now: = 0 var visible_marks_count: = 0 -var map_server_available: = false var border1: ImageTexture var border2: ImageTexture @@ -129,6 +132,12 @@ func _ready() -> void: img.set_pixel(0, 1, Color.CORAL) border2 = ImageTexture.create_from_image(img) + zoom_timer = Timer.new() + add_child(zoom_timer) + zoom_timer.one_shot = false + zoom_timer.wait_time = 0.1 + zoom_timer.timeout.connect(_on_zoom_timeout) + _xyz.z = min_zoom_level image_type = 'png' $canvas.connect('mouse_entered', func(): _rollover = true) @@ -152,7 +161,7 @@ func on_data_received(coords: Dictionary) -> void: if not is_centered: return if coords.has_all(['latitude', 'longitude']): - set_coordinates(coords['longitude'], coords['latitude']) + set_coordinates(coords['longitude'], coords['latitude'], coords['k']) func _on_resize() -> void: @@ -252,6 +261,7 @@ func multiply_zoom(multiplier: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func increment_zoom(increment: float, pivot: Vector2) -> void: @@ -260,6 +270,7 @@ func increment_zoom(increment: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func set_zoom(zoom: float, pivot: Vector2) -> void: @@ -268,6 +279,7 @@ func set_zoom(zoom: float, pivot: Vector2) -> void: var p2: = screen_to_world(_xyz, pivot) _xyz.x -= p2.x - p1.x _xyz.y -= p2.y - p1.y + update_scale_label() func _draw() -> void: @@ -302,6 +314,9 @@ func _draw() -> void: if is_out_border2 and _dragging: draw_texture_rect(border2, Rect2(p1, p2), false, Color.WHITE, false) + if should_draw_ship_radius(): + draw_ship_radius() + func _clean_all() -> void: _queue.clear() @@ -366,21 +381,21 @@ func _process(delta) -> void: func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile) -> void: - + var unit_instance = network.get_unit_instance('уарэп-карта') _req_count -= 1 remove_child(req) req.queue_free() if result != HTTPRequest.RESULT_SUCCESS: - if map_server_available: - map_server_available = false - emit_signal('map_server_offline') + if unit_instance.online: + unit_instance.online = false + unit_instance.emit_signal('line_changed', unit_instance) _queue[tile.i] = tile return - if not map_server_available: - map_server_available = true - emit_signal('map_server_online') + if not unit_instance.online: + unit_instance.online = true + unit_instance.emit_signal('line_changed', unit_instance) if code == 404: push_error('на сервере нет \"%s\"' % tile.url) @@ -390,6 +405,11 @@ func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: push_error('не удалось получить изображение (неверный формат?) из \"%s\"' % tile.url) return + 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) + tile.texture = ImageTexture.create_from_image(image) _cache[tile.i] = tile @@ -677,7 +697,7 @@ func clear() -> void: queue_redraw() -func set_coordinates(lon: float, lat: float) -> void: +func set_coordinates(lon: float, lat: float, course: float) -> void: var anim: Animation = $player.get_animation('goto') var new_pos: Vector2 = lonlat_to_world(lon, lat) anim.track_insert_key(0, 0, _xyz.x) @@ -690,7 +710,8 @@ func set_coordinates(lon: float, lat: float) -> void: ship_instance = ship_mark.instantiate() add_mark_from_lon_lat(ship_id, lon, lat, ship_instance, 0.0) else: - _marks[ship_id].position = lonlat_to_world(lon, lat) + ship_instance.position = lonlat_to_world(lon, lat) + ship_instance.rotation_degrees = course - 90 func blend_mask(val: bool) -> void: @@ -699,7 +720,7 @@ func blend_mask(val: bool) -> void: func update_coordinates_label(lon: float, lat: float) -> void: - coordinates_label = 'Координаты:\nNS:%f\nEW: %f' % [lat, lon] + coordinates_label = 'Координаты:\nNS:%f\nEW:%f' % [lat, lon] signaller.emit_signal('update_coordinates_map', coordinates_label) @@ -731,3 +752,80 @@ func _on_threat_lost(th) -> void: var target = get_parent().get_node(str(th.id)) if target: target.queue_free() + + +func zoom_in() -> void: + if _xyz.z >= max_zoom_level: + return + var center: Vector2 = $canvas.size / 2.0 + increment_zoom(zoom_step, center) + queue_redraw() + + +func zoom_out() -> void: + if _xyz.z <= min_zoom_level: + return + var center: Vector2 = $canvas.size / 2.0 + increment_zoom(-zoom_step, center) + queue_redraw() + + +func _on_zoom_plus_button_down() -> void: + zoom_action = "in" + perform_zoom() + zoom_timer.start(0.3) + + +func _on_zoom_minus_button_down() -> void: + zoom_action = "out" + perform_zoom() + zoom_timer.start(0.3) + + +func _on_zoom_button_up() -> void: + zoom_action = "" + zoom_timer.stop() + + +func _on_zoom_timeout(): + perform_zoom() + zoom_timer.wait_time = 0.1 + + +func perform_zoom(): + if zoom_action != "": + if zoom_action == "in": + zoom_in() + else: + zoom_out() + update_scale_label() + + +# Вычисление для радиуса в мировых координатах +func get_ship_radius_world() -> float: + if not _marks.has(ship_id): + return 0.0 + var ship_world_pos = _marks[ship_id].position + var ship_lonlat = world_to_lonlat(ship_world_pos.x, ship_world_pos.y) + var earth_radius_km = 6371.0 + var distance_deg = (ship_radius_km / earth_radius_km) * (180.0 / PI) / cos(deg_to_rad(ship_lonlat.y)) + var east_lon = ship_lonlat.x + distance_deg + var east_point_world = lonlat_to_world(east_lon, ship_lonlat.y) + return abs(east_point_world.x - ship_world_pos.x) + + +func should_draw_ship_radius() -> bool: + if not show_ship_radius or not _marks.has(ship_id): + return false + return _xyz.z >= 11 + + +func draw_ship_radius() -> void: + var ship_world_pos = _marks[ship_id].position + var ship_screen_pos = world_to_screen(ship_world_pos) + var radius_world = get_ship_radius_world() + var radius_point_world = Vector2(ship_world_pos.x + radius_world, ship_world_pos.y) + var radius_point_screen = world_to_screen(radius_point_world) + var radius_screen = ship_screen_pos.distance_to(radius_point_screen) + #draw_arc(ship_screen_pos, radius_screen, 0, TAU, 64, Color.ORANGE, 2.0) # отрисовка контура + draw_circle(ship_screen_pos, radius_screen, Color.ORANGE_RED * Color(1, 1, 1, 0.1)) # отрисовка заливки diff --git a/scenes/журнал/журнал.gd b/scenes/журнал/журнал.gd index 401ad0d8..7bc53059 100644 --- a/scenes/журнал/журнал.gd +++ b/scenes/журнал/журнал.gd @@ -7,6 +7,7 @@ func on_threats_changed(th: Object, msg: String): log.message(Logger.INFO, '%s: func on_parse_error(unit_inst, msg: String): log.message(Logger.ERROR, '%s: %s' % [unit_inst.name, msg]) func on_interfer_off(ecm, msg: String): log.message(Logger.INFO, '%s: %s' % [msg, ecm.to_string()]) func on_set_program_mode(msg: String): log.message(Logger.INFO, msg) +func on_mode_trenazh(val: bool): log.message(Logger.INFO, 'Режим \"Тренаж\" %s' % ['отменён', 'задейсвован'][int(val)]) func on_interfer_new(ecm, msg: String): if ecm.krp != interfer.INTERFER_OFF: @@ -33,6 +34,7 @@ func _ready() -> void: signaller.conn(signaller.режим_эмс, Callable(log, 'info').bind('Программа в режиме \"ЭМС\"')) signaller.conn(signaller.режим_журнал, Callable(log, 'info').bind('Программа в режиме \"Журнал\"')) signaller.conn(signaller.режим_контроль, Callable(log, 'info').bind('Программа в режиме \"Контроль\"')) + signaller.conn(signaller.режим_тренаж, Callable(self, 'on_mode_trenazh')) func _on_clear_button_down() -> void: diff --git a/scenes/журнал/журнал.tscn b/scenes/журнал/журнал.tscn index 61ae1eba..b29cb183 100644 --- a/scenes/журнал/журнал.tscn +++ b/scenes/журнал/журнал.tscn @@ -36,6 +36,7 @@ colors = { 8: Color(0.91, 0, 0, 1), 16: Color(0.868077, 0.247988, 0.62812, 1) } +max_lines_count = 256 [node name="btn_save" type="Button" parent="."] layout_mode = 0 @@ -112,6 +113,12 @@ button_pressed = true text = "Контроль" metadata/filter = "Контроль" +[node name="CheckBox_SCROLL" type="CheckBox" parent="filtrs"] +layout_mode = 2 +button_pressed = true +text = "Прокручивать до конца" +metadata/filter = "Контроль" + [connection signal="button_down" from="btn_save" to="." method="_on_btn_save_button_down"] [connection signal="button_down" from="btn_clear" to="." method="_on_clear_button_down" flags=3] [connection signal="canceled" from="dlg_file" to="." method="_on_dlg_file_confirmed"] @@ -124,3 +131,4 @@ metadata/filter = "Контроль" [connection signal="pressed" from="filtrs/CheckBox_FATAL" to="." method="_on_check_box_pressed"] [connection signal="pressed" from="filtrs/CheckBox_THREAT" to="." method="_on_check_box_pressed"] [connection signal="pressed" from="filtrs/CheckBox_CONTROL" to="." method="_on_check_box_pressed"] +[connection signal="toggled" from="filtrs/CheckBox_SCROLL" to="content" method="_on_check_box_scroll_toggled"] diff --git a/scenes/контроль/request.gd b/scenes/контроль/request.gd index e52d0a47..284a8e1d 100644 --- a/scenes/контроль/request.gd +++ b/scenes/контроль/request.gd @@ -19,32 +19,16 @@ const RESULT_STRINGS = { RESULT_TIMEOUT: 'Время истекло' } -@export var projsettings_path_left: String = '' -@export var projsettings_path_right: String = '' - -var i_bort: int = 0 -var addr_left: String -var addr_right: String - - -func on_settings_changed(): - addr_left = ProjectSettings.get_setting(projsettings_path_left) - addr_right = ProjectSettings.get_setting(projsettings_path_right) +@export var request_url: String = '' func get_result_string(result: Result): return RESULT_STRINGS[result] if RESULT_STRINGS.has(result) else '<неизвестный код результата HTTPRequest - %d>' % result -func _ready(): - ProjectSettings.connect('settings_changed', on_settings_changed) - on_settings_changed() - - func _on_request_timer(): - var addr = [addr_left, addr_right][i_bort] - var rc = request(addr) + if HTTPClient.Status.STATUS_DISCONNECTED != get_http_client_status(): + return + var rc: = request(request_url) if rc != Error.OK: - var s: String = '%s: %s' % [error_string(rc), addr] - log.error('ошибка: %s' % s) - i_bort = (i_bort + 1) % 2 + push_error('%s: \"%s\"' % [error_string(rc), request_url]) diff --git a/scenes/контроль/блок-в.tscn b/scenes/контроль/блок-в.tscn index 12673c7b..06dcfa85 100644 --- a/scenes/контроль/блок-в.tscn +++ b/scenes/контроль/блок-в.tscn @@ -36,7 +36,6 @@ signal pressed(control: PanelContainer) return $margin/vbox/grid1/level7.value = v $margin/vbox/grid1/level7.tint_progress = Color.RED if v > 70 else Color.WHITE - @export var min_value0: float: @@ -141,16 +140,16 @@ signal pressed(control: PanelContainer) func _on_button_pressed(): emit_signal('pressed', self) -func _enter_tree() -> void: call_deferred('_enter_tree_defered') func set_value0(value: Array): value0.assign(value) +func _enter_tree() -> void: call_deferred('_enter_tree_defered') func _ready(): - var items: Array= get_level_nodes() + var items: Array = get_level_nodes() for item in items: - item.connect('value_changed', on_level_changed.bind(item, value1_info)) + item.connect('value_changed', on_level_changed.bind(item, value0_info)) on_level_changed(item.value, item, value0_info) - var level7 = $margin/vbox/grid1/level7 + var level7: = $margin/vbox/grid1/level7 level7.connect('value_changed', on_level_changed.bind(level7, value1_info)) on_level_changed(level7.value, level7, value1_info) @@ -225,11 +224,10 @@ func get_name_nodes() -> Array: func set_value0_animated(target_node, target_value: float) -> void: - var tween = create_tween() + var tween: Tween = create_tween() tween.set_ease(Tween.EASE_OUT) tween.set_trans(Tween.TRANS_QUINT) - - tween.tween_property(target_node, \"value\", target_value, animation_duration) + tween.tween_property(target_node, 'value', target_value, animation_duration) " [sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_rceim"] diff --git a/scenes/контроль/кнопка-прибора.gd b/scenes/контроль/кнопка-прибора.gd index 13d337b1..b6adb741 100644 --- a/scenes/контроль/кнопка-прибора.gd +++ b/scenes/контроль/кнопка-прибора.gd @@ -1,6 +1,6 @@ @tool -extends Node +extends TextureButton @export var state_colors: Array diff --git a/scenes/контроль/контроль.tscn b/scenes/контроль/контроль.tscn index b62b8584..5ed8246a 100644 --- a/scenes/контроль/контроль.tscn +++ b/scenes/контроль/контроль.tscn @@ -25,63 +25,99 @@ script/source = "extends Panel #TODO: рефактор: заменить подчёркивание на тире const PRIBORS_RES = \\ { - 'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'], - 'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'], - 'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'], - 'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'], - 'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'], - 'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'], - 'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'], - 'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'], - 'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'], - 'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'], - 'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'], - 'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'], - 'pribor_rtr': ['res://scenes/pribor-afsp/pribor-bpo.tscn', 'Контроль исправности прибора РТР'], - 'pribor_afsp_1': ['res://scenes/pribor-afsp/pribor-afsp-1.tscn', 'Контроль исправности прибора АФСП 1'], - 'pribor_afsp_2': ['res://scenes/pribor-afsp/pribor-afsp-2.tscn', 'Контроль исправности прибора АФСП 2'], - 'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'], - 'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности устройства У-ЭП'], + 'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'], + 'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'], + 'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'], + 'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'], + 'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'], + 'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'], + 'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'], + 'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'], + 'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'], + 'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'], + 'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'], + 'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'], + 'pribor_rtr': ['res://scenes/pribor-afsp/pribor-bpo.tscn', 'Контроль исправности прибора РТР'], + 'pribor_afsp_1': ['res://scenes/pribor-afsp/pribor-afsp-1.tscn', 'Контроль исправности прибора АФСП 1'], + 'pribor_afsp_2': ['res://scenes/pribor-afsp/pribor-afsp-2.tscn', 'Контроль исправности прибора АФСП 2'], + 'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'], + 'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности устройства У-ЭП'], } func on_line_changed(u, conn_node, _pribor_meta): conn_node.set_val(u.online) +func on_serv_changed(u, pribor_node, _pribor_meta): pribor_node.state = int(u.serviceability) + + +func on_mode_changed(): + clean_pribor_items() + reset_pribor_buttons() + + +func reset_pribor_buttons(): + var pribor_buttons: = get_tree().get_nodes_in_group('pribor_buttons') + for node in pribor_buttons: + node.button_pressed = false func _ready(): var group = ButtonGroup.new() + # Кнопки приборов, по нажатию на которые отображаеся мнемосхема for k in PRIBORS_RES: - var pribor_node = get_node(k) + var pribor_node: Node = get_node(k) var pribor_path = PRIBORS_RES[k][0] var header_text = PRIBORS_RES[k][1] pribor_node.set_button_group(group) pribor_node.connect('button_down', Callable(self, 'on_pribor_press').bind(pribor_path, header_text, pribor_node)) var conn_node = pribor_node.get_node('connect_pribor') - var pribor_meta = pribor_node.get_meta('unit_name', []) + var unit_names = pribor_node.get_meta('unit_name', []) var pribor_proc = pribor_node.get_meta('online_proc', '') if pribor_proc == '': continue - if pribor_meta.size(): - for i in pribor_meta.size(): - var unit_pribor = network.get_unit_instance(pribor_meta[i]) - unit_pribor.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, pribor_meta)) + if not unit_names.size(): + continue + for i in unit_names.size(): + var unit_instance: = network.get_unit_instance(unit_names[i]) + unit_instance.connect('line_changed', Callable(self, pribor_proc).bind(conn_node, unit_names)) + + for item in unit_names: + if prd.prd_dict.has(item): + var prd_module = prd.prd_dict[item] + prd_module.connect('update_serviceability', Callable(self, 'on_serviceability_changed').bind(prd_module, pribor_node)) + if item == 'уарэп-эмс': + signaller.connect('update_uf_serviceability', Callable(self, 'on_update_uf_serviceability').bind(pribor_node)) + # Пиктограммы приборов, которые отображают состояние подключения только + for pribor_node in get_tree().get_nodes_in_group('pribor_pics'): + var unit_name = pribor_node.get_meta('unit_name') + var unit_instance: = network.get_unit_instance(unit_name) + var conn_node: = pribor_node.get_node('connect_pribor') + unit_instance.connect('line_changed', on_line_changed.bind(conn_node, unit_name)) + + signaller.conn(signaller.режим_работа, on_mode_changed) + signaller.conn(signaller.режим_журнал, on_mode_changed) + signaller.conn(signaller.режим_настройки, on_mode_changed) + signaller.conn(signaller.режим_эмс, on_mode_changed) func online_change_arr(_u, conn_node, pribor_meta): - var state_online = true - for i in pribor_meta.size(): - var unit_pribor = network.get_unit_instance(pribor_meta[i]) - if not unit_pribor.online: - state_online = false + var state_online: = false + for meta in pribor_meta: + var unit_pribor = network.get_unit_instance(meta) + if unit_pribor.online: + state_online = true break conn_node.set_val(state_online) -func on_pribor_press(pribor_path, header_text, pribor_node): +func clean_pribor_items(): var items = get_tree().get_nodes_in_group('pribor_items') for item in items: remove_child(item) item.queue_free() + + +func on_pribor_press(pribor_path, header_text, pribor_node): + clean_pribor_items() var pribor_obj = load(pribor_path) if not pribor_obj: push_error('не загружено: \\\"%s\\\" (%s)' % [pribor_path, header_text]) @@ -97,6 +133,18 @@ func on_pribor_press(pribor_path, header_text, pribor_node): pribor.set_meta('unit_name', unit_name) pribor.add_to_group('pribor_items') add_child(pribor) + + +func on_serviceability_changed(prd_module: Object, prd_pribor:Node)-> void: + if not prd_module.unit_yau07.online: + prd_pribor.state = 0 + return + prd_pribor.state = 1 if prd_module.serviceability else 2 + + +func on_update_uf_serviceability(uf_serviceaability: bool, uf_pribor: Node)-> void: + + uf_pribor.state = 1 if uf_serviceaability else 2 " [sub_resource type="SpriteFrames" id="SpriteFrames_foasq"] @@ -122,7 +170,7 @@ grow_vertical = 2 script = SubResource("GDScript_iqgf5") metadata/_edit_lock_ = true -[node name="capsrpb" type="TextureRect" parent="."] +[node name="capsrpb" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -136,6 +184,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-капсрпб" +metadata/unit_name = &"уарэп-капсрпб" [node name="label" type="Label" parent="capsrpb"] layout_mode = 0 @@ -155,7 +204,7 @@ scale = Vector2(2.6, 2.6) sprite_frames = SubResource("SpriteFrames_foasq") script = ExtResource("11_u7tym") -[node name="5p28" type="TextureRect" parent="."] +[node name="5p28" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -169,6 +218,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-5п28" +metadata/unit_name = &"уарэп-5п28" [node name="label" type="Label" parent="5p28"] layout_mode = 0 @@ -189,7 +239,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="akng" type="TextureRect" parent="."] +[node name="akng" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -203,6 +253,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"навигация" +metadata/unit_name = &"навигация" [node name="label" type="Label" parent="akng"] layout_mode = 0 @@ -223,7 +274,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="maps" type="TextureRect" parent="."] +[node name="maps" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -236,7 +287,8 @@ size_flags_horizontal = 15 size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") -unit_name = &"навигация" +unit_name = &"уарэп-карта" +metadata/unit_name = &"уарэп-карта" [node name="label" type="Label" parent="maps"] layout_mode = 0 @@ -257,7 +309,7 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="trassa" type="TextureRect" parent="."] +[node name="trassa" type="TextureRect" parent="." groups=["pribor_pics"]] editor_description = "Кнопка для отображения внешних соединений." self_modulate = Color(0.788235, 0.788235, 0.788235, 1) layout_mode = 0 @@ -271,6 +323,7 @@ size_flags_vertical = 15 texture = ExtResource("2_oysma") script = ExtResource("2_8r80x") unit_name = &"уарэп-трасса" +metadata/unit_name = &"уарэп-трасса" [node name="label" type="Label" parent="trassa"] layout_mode = 0 @@ -291,6 +344,58 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") +[node name="pribor_prd_n_1" type="TextureButton" parent="." groups=["pribor_buttons"]] +editor_description = "Кнопка для выбора прибора." +layout_mode = 0 +offset_left = 1048.0 +offset_top = 193.0 +offset_right = 1125.0 +offset_bottom = 309.0 +size_flags_horizontal = 15 +size_flags_vertical = 15 +toggle_mode = true +action_mode = 0 +texture_normal = ExtResource("6_i1yfn") +stretch_mode = 4 +flip_h = true +script = ExtResource("3_4pt7j") +state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +metadata/online_proc = "on_line_changed" +metadata/unit_name = ["уарэп-яу07-1н"] + +[node name="label" type="Label" parent="pribor_prd_n_1"] +layout_mode = 0 +offset_left = 8.0 +offset_top = -38.0 +offset_right = 60.0 +offset_bottom = -19.0 +text = "ПРД Н1" +horizontal_alignment = 1 +vertical_alignment = 1 + +[node name="frame" type="NinePatchRect" parent="pribor_prd_n_1"] +visible = false +self_modulate = Color(0.890196, 0.486275, 0.196078, 1) +layout_mode = 0 +offset_left = -10.0 +offset_top = -24.0 +offset_right = 95.0 +offset_bottom = 126.0 +texture = ExtResource("4_rasbe") +region_rect = Rect2(-3, -3, 89, 89) +patch_margin_left = 16 +patch_margin_top = 16 +patch_margin_right = 16 +patch_margin_bottom = 16 + +[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_prd_n_1"] +light_mask = 3 +position = Vector2(35, -10) +scale = Vector2(0.625, 0.625) +sprite_frames = SubResource("SpriteFrames_foasq") +frame_progress = 0.72355 +script = ExtResource("11_u7tym") + [node name="pribor_uf" type="TextureButton" parent="." groups=["pribor_buttons"]] editor_description = "Кнопка для выбора прибора." layout_mode = 0 @@ -305,7 +410,8 @@ action_mode = 0 texture_normal = ExtResource("2_0nvm1") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.74, 0.37, 1), Color(0.854902, 0.0705882, 0.0705882, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] +state = 1 metadata/unit_name = ["уарэп-эмс"] metadata/online_proc = "on_line_changed" @@ -321,6 +427,7 @@ vertical_alignment = 1 [node name="frame" type="NinePatchRect" parent="pribor_uf"] visible = false +self_modulate = Color(0.890196, 0.486275, 0.196078, 1) layout_mode = 0 offset_left = -14.0 offset_top = -30.0 @@ -356,7 +463,9 @@ action_mode = 0 texture_normal = ExtResource("3_hhadv") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] +metadata/unit_name = [&"уарэп-бпо-1", &"уарэп-бпо-2"] +metadata/online_proc = "online_change_arr" [node name="label" type="Label" parent="pribor_rtr"] layout_mode = 0 @@ -417,7 +526,9 @@ action_mode = 0 texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] +metadata/unit_name = [&"уарэп-афсп-левый"] +metadata/online_proc = "on_line_changed" [node name="label" type="Label" parent="pribor_afsp_1"] layout_mode = 0 @@ -482,7 +593,9 @@ texture_normal = ExtResource("9_iqgf5") stretch_mode = 0 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] +metadata/unit_name = [&"уарэп-афсп-правый"] +metadata/online_proc = "on_line_changed" [node name="label" type="Label" parent="pribor_afsp_2"] layout_mode = 0 @@ -544,7 +657,7 @@ action_mode = 0 texture_normal = ExtResource("5_kvnex") stretch_mode = 0 script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-щ3", "уарэп-спт25-1", "уарэп-спт25-2"] metadata/online_proc = "online_change_arr" @@ -596,7 +709,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2в"] metadata/online_proc = "on_line_changed" @@ -648,7 +761,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2н"] metadata/online_proc = "on_line_changed" @@ -702,7 +815,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-2к"] metadata/online_proc = "on_line_changed" @@ -754,7 +867,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3в"] metadata/online_proc = "on_line_changed" @@ -806,7 +919,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3н"] metadata/online_proc = "on_line_changed" @@ -858,7 +971,7 @@ texture_normal = ExtResource("6_i1yfn") stretch_mode = 4 flip_h = true script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] +state_colors = [Color(1, 1, 1, 1), Color(0, 1, 0, 1), Color(1, 0, 0, 1)] metadata/unit_name = ["уарэп-яу07-3к"] metadata/online_proc = "on_line_changed" @@ -947,58 +1060,6 @@ sprite_frames = SubResource("SpriteFrames_foasq") frame_progress = 0.72355 script = ExtResource("11_u7tym") -[node name="pribor_prd_n_1" type="TextureButton" parent="." groups=["pribor_buttons"]] -editor_description = "Кнопка для выбора прибора." -layout_mode = 0 -offset_left = 1048.0 -offset_top = 193.0 -offset_right = 1125.0 -offset_bottom = 309.0 -size_flags_horizontal = 15 -size_flags_vertical = 15 -toggle_mode = true -action_mode = 0 -texture_normal = ExtResource("6_i1yfn") -stretch_mode = 4 -flip_h = true -script = ExtResource("3_4pt7j") -state_colors = [Color(1, 1, 1, 1), Color(0, 0.87, 0, 1), Color(0.65, 0.0715, 0.0715, 1)] -metadata/online_proc = "on_line_changed" -metadata/unit_name = ["уарэп-яу07-1н"] - -[node name="label" type="Label" parent="pribor_prd_n_1"] -layout_mode = 0 -offset_left = 8.0 -offset_top = -38.0 -offset_right = 60.0 -offset_bottom = -19.0 -text = "ПРД Н1" -horizontal_alignment = 1 -vertical_alignment = 1 - -[node name="frame" type="NinePatchRect" parent="pribor_prd_n_1"] -visible = false -self_modulate = Color(0.890196, 0.486275, 0.196078, 1) -layout_mode = 0 -offset_left = -10.0 -offset_top = -24.0 -offset_right = 95.0 -offset_bottom = 126.0 -texture = ExtResource("4_rasbe") -region_rect = Rect2(-3, -3, 89, 89) -patch_margin_left = 16 -patch_margin_top = 16 -patch_margin_right = 16 -patch_margin_bottom = 16 - -[node name="connect_pribor" type="AnimatedSprite2D" parent="pribor_prd_n_1"] -light_mask = 3 -position = Vector2(35, -10) -scale = Vector2(0.625, 0.625) -sprite_frames = SubResource("SpriteFrames_foasq") -frame_progress = 0.72355 -script = ExtResource("11_u7tym") - [node name="pribor_prd_k_1" type="TextureButton" parent="." groups=["pribor_buttons"]] editor_description = "Кнопка для выбора прибора." layout_mode = 0 @@ -1325,6 +1386,7 @@ points = PackedVector2Array(-8, 0, 608, 0) width = 2.0 default_color = Color(1, 1, 1, 0.352941) +[connection signal="toggled" from="pribor_prd_n_1" to="pribor_prd_n_1" method="_on_toggled"] [connection signal="toggled" from="pribor_uf" to="pribor_uf" method="_on_toggled"] [connection signal="toggled" from="pribor_rtr" to="pribor_rtr" method="_on_toggled"] [connection signal="toggled" from="pribor_afsp_1" to="pribor_afsp_1" method="_on_toggled"] @@ -1337,7 +1399,6 @@ default_color = Color(1, 1, 1, 0.352941) [connection signal="toggled" from="pribor_prd_n_3" to="pribor_prd_n_3" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_k_3" to="pribor_prd_k_3" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_v_1" to="pribor_prd_v_1" method="_on_toggled"] -[connection signal="toggled" from="pribor_prd_n_1" to="pribor_prd_n_1" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_k_1" to="pribor_prd_k_1" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_v_4" to="pribor_prd_v_4" method="_on_toggled"] [connection signal="toggled" from="pribor_prd_n_4" to="pribor_prd_n_4" method="_on_toggled"] diff --git a/scenes/настройки/настройки.tscn b/scenes/настройки/настройки.tscn index 64267b01..e7573903 100644 --- a/scenes/настройки/настройки.tscn +++ b/scenes/настройки/настройки.tscn @@ -38,7 +38,7 @@ const SETTING_TABLE = [ ['Текущая версия ПО УАРЭП', TableEdit, TableEdit, 'Время сборки, версия и номер фиксации'], ['уарэп-яу07-частный', TableEdit, TableEdit, 'IP-адрес для получения частных сообщений от ЯУ-07'], ['уарэп-яу07-общий', TableEdit, TableEdit, 'IP-адрес для получения широковещательных сообщений от ЯУ-07'], - ['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ'], + ['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'], ['уарэп-эмс', TableEdit, TableEdit, 'IP-адрес для связи с ЭМС'], ['уарэп-яу07-2в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 2'], ['уарэп-яу07-2н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 2'], @@ -61,7 +61,10 @@ const SETTING_TABLE = [ ['Адрес АФСП левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], ['Адрес АФСП правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора АФСП'], ['Адрес БПО левого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], - ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'] ] + ['Адрес БПО правого борта', TableEdit, TableEdit, 'http-адрес для запроса состояния прибора БПО'], + ['Период опроса состояния БПО, секунды', TableEdit, TableEdit, 'Время в секундах' ], + ['Период опроса состояния АФСП, секунды', TableEdit, TableEdit, 'Время в секундах' ], + ['уареп-трасса', TableEdit, TableEdit, 'IP-адрес для связи с Трассой [<адрес этого узла>, <адрес удалённого узла>, <порт этого узла>, <порт удалённого узла>]'] ] const EXTERNAL_CU = 16 ## Внешнее целеуказание const TRASSA = 17 @@ -86,20 +89,17 @@ func _ready() -> void: func on_external_cu_btn_pressed(btn) -> void: - var state = btn.button_pressed - ProjectSettings.set_setting('application/config/Внешнее управление', state) - if state: + ProjectSettings.set_setting('application/config/Внешнее управление', btn.button_pressed) + if btn.button_pressed: signaller.emit_signal('interfer_off_all') func on_trassa_btn_pressed(btn) -> void: - var state = btn.button_pressed - ProjectSettings.set_setting('application/config/Внешнее указание Трасса', state) + ProjectSettings.set_setting('application/config/Внешнее указание Трасса', btn.button_pressed) func on_vk_pressed(btn) -> void: - var state = btn.button_pressed - signaller.emit_signal('kb_pressed', state) + signaller.emit_signal('kb_pressed', btn.button_pressed) func on_ems2_pressed(btn) -> void: @@ -175,7 +175,7 @@ func setting_tab(): var child = node_values[0] if child is CheckButton: child.connect('pressed', Callable(self, 'on_checkbutton_pressed').bind(i)) - var val = settings_data[param_name] if settings_data.has(param_name) else false + var val = ProjectSettings.get_setting('application/config/%s' % param_name) child.set_pressed(val) else: if settings_data.has(param_name): @@ -213,11 +213,9 @@ func button_settings(): var extern_cu_node = $scroll_set/table.get_node2(1, EXTERNAL_CU).get_children()[0] extern_cu_node.connect('pressed', on_external_cu_btn_pressed.bind(extern_cu_node)) on_external_cu_btn_pressed(extern_cu_node) - - var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children()[0] + var trassa_node = $scroll_set/table.get_node2(1, TRASSA).get_children() + trassa_node = trassa_node[0] trassa_node.connect('pressed', on_trassa_btn_pressed.bind(trassa_node)) - on_trassa_btn_pressed(trassa_node) - var vk_node = $scroll_set/table.get_node2(1, KEYBOARD).get_children()[0] vk_node.connect('pressed', on_vk_pressed.bind(vk_node)) var ems2_hide_node = $scroll_set/table.get_node2(1, HIDE_EMS2).get_children()[0] diff --git a/scenes/работа/работа.gd b/scenes/работа/работа.gd index 9f46f221..fe9aae39 100644 --- a/scenes/работа/работа.gd +++ b/scenes/работа/работа.gd @@ -18,6 +18,7 @@ class_name work extends Panel @export var strob_min_width: float ## Минимальная ширина строба по углу. @export var window_0_id: int ## Идетификатор окна. Присваивается godot от 0 до количества созданных окон. +const SVK_EMIT = 1 ## Код состояния выполнения помехи - выполняется var drag_button: MouseButton ## Кнопка мыши нажатая при перетаскивании. var drag_fsm: DragFSM = DragFSM.IDLE ## Текущее состояние перетаскивания. @@ -30,7 +31,13 @@ var strob_band_begin: float ## Ширина строба в моме var strob_dir_begin: float ## Направление антенны в момент начала перетаскивания. var strob_width_begin: float ## Ширина строба по углу в момент начала перетаскивания. var view_mode: MapViewMode ## Режим отображения карты +var thrs_dict: Dictionary ## Ссылка на словарь целей +var color_ecm: Color +var color_select: Color +var color_emit: Color +var color_emit_sel: Color +var course = 0.0 ## Курс корабля signal drag_begin ## Вызывается в момент начала перетаскивания. signal drag_continue ## Вызывается во время продолжения перетаскивания. @@ -44,6 +51,7 @@ const map_sizes = [ var fs_band = prd.FS_BAND_RTO ## Текущий режим блоков ФС по частоте var fs_selected: Dictionary ## Словарь выбранных секторов var fs_active: Dictionary ## Словарь секторов назначенных на подавление +var fs_emit: Dictionary ## Словарь секторов назначенных на подавление ## Состояние перетаскивания. enum DragFSM { @@ -72,10 +80,6 @@ const VAL_TO_EVENT = { true: 'full_auto' } ## Выбор целей и установка помех автоматически. -## Обработчик сигнала изменения списка целей. -func on_threats_resized(threats: Dictionary): $count_all_pad/count_all.text = '%02d' % threats.size() - - ## Обработчик выбора цели. func on_threat_selected(th, ecm_btns): on_rto_threat_sel(th.id, ecm_btns) @@ -84,6 +88,25 @@ func on_threat_selected(th, ecm_btns): on_rto_threat_sel(th.id, ecm_btns) func on_enter_tree() -> void: call_deferred('on_button_strobe_pressed') +func on_settings_changed(): + color_emit_sel = ProjectSettings.get_setting('application/interfer/emit_sel_color', Color(1.0, 1.0, 1.0, 1.0)) + color_emit = ProjectSettings.get_setting('application/interfer/emit_color', Color(0.58, 0.47, 0.51, 1.0)) + color_ecm = ProjectSettings.get_setting('application/interfer/interfer_color', Color(0.58, 0.47, 0.51, 1.0)) + color_select = ProjectSettings.get_setting('application/interfer/select_color', Color(1.0, 1.0, 1.0, 1.0)) + + color_select *= Color(1.0, 1.0, 1.0, 0.0) + color_ecm *= Color(1.0, 1.0, 1.0, 0.0) + color_emit_sel *= Color(1.0, 1.0, 1.0, 0.2) + + +## Обработчик сигнала изменения списка целей. +func on_threats_resized(ths: Dictionary): + $count_all_pad/count_all.text = '%02d' % ths.size() + var c: int = ths.values().filter(func(th: threats.Threat): return th.proto != '').size() + $count_danger_pad/count_danger.text = '%02d' % c + thrs_dict = ths + + ## Обработчик нажатия на кнопку вид. func on_button_view_toggled(toggled: bool): signaller.emit_signal('map_mode_changed', int(toggled)) @@ -113,6 +136,8 @@ func _exit_tree() -> void: ## Производит инициализацию. func _ready(): + ProjectSettings.connect('settings_changed', on_settings_changed) + on_settings_changed() min_zoom = ProjectSettings.get_setting('application/config/map_minimum_zoom', 5) max_zoom = ProjectSettings.get_setting('application/config/map_maximum_zoom', 19) drag_fsm = DragFSM.OFF @@ -120,28 +145,42 @@ func _ready(): btns_select.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_select').bind(btn, btns_select))) var nodes: Array = get_tree().get_nodes_in_group('группа-режим-помехи') nodes.any(func(btn): btn.button_connect('pressed', Callable(self, 'on_button_pressed').bind(btn, nodes))) - threats.connect('threat_new', Callable(self, 'on_threat_new')) - threats.connect('threat_lost', Callable(self, 'on_threat_lost')) - threats.connect('threats_resized', Callable(self, 'on_threats_resized')) - threats.connect('threat_update', Callable(self, 'on_threat_update')) - signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes)) - signaller.connect('bip_pressed', Callable(self, 'on_bip_pressed').bind(nodes)) - signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(nodes)) - signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(nodes)) - signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected').bind(nodes)) - signaller.connect('interfer_new', Callable(self, 'on_interfer_new')) - signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all')) - signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno').bind(nodes)) - signaller.connect('fs_selected', Callable(self, 'on_fs_selected')) - signaller.connect('fs_update_color', Callable(self, 'on_fs_update_color')) - interfer.connect('interfer_update', Callable(self, 'on_interfer_new')) - signaller.connect('interfer_prinuditelno', Callable(self, 'on_chk_interfer_prinuditelno')) - signaller.connect('fs_update_state', Callable(self, 'on_fs_update_state')) - signaller.connect('map_user_panning', Callable(self, 'on_user_panning')) + threats.connect('threat_new', Callable(self, 'on_threat_new')) + threats.connect('threat_lost', Callable(self, 'on_threat_lost')) + threats.connect('threats_resized', Callable(self, 'on_threats_resized')) + threats.connect('threat_update', Callable(self, 'on_threat_update')) + signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(nodes)) + signaller.connect('bip_pressed', Callable(self, 'on_bip_pressed').bind(nodes)) + signaller.connect('rto_threat_unsel', Callable(self, 'on_rto_threat_unsel').bind(nodes)) + signaller.connect('threat_selected', Callable(self, 'on_threat_selected').bind(nodes)) + signaller.connect('interfer_selected', Callable(self, 'on_interfer_selected').bind(nodes)) + signaller.connect('interfer_new', Callable(self, 'on_interfer_new')) + signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all')) + signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno').bind(nodes)) + signaller.connect('fs_selected', Callable(self, 'on_fs_selected')) + signaller.connect('fs_update_color', Callable(self, 'on_fs_update_color')) + interfer.connect('interfer_update', Callable(self, 'on_interfer_new')) + signaller.connect('interfer_prinuditelno', Callable(self, 'on_chk_interfer_prinuditelno')) + signaller.connect('fs_update_state', Callable(self, 'on_fs_update_state')) + signaller.connect('map_user_panning', Callable(self, 'on_user_panning')) signaller.connect('update_coordinates_map', Callable(self, 'on_update_coordinates_label')) - signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) + signaller.connect('update_scale_map', Callable(self, 'on_update_scale_label')) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) on_btn_center_toggled(true) on_btn_activate_toggled(true) + #$canvas.add_seczap(0, Vector4(372, 0, 30, 348)) + #$canvas.add_seczap(1, Vector4(372, 90, 30, 348)) + #$canvas.add_seczap(2, Vector4(198 + 348, 180, 30, 5)) + #$canvas.add_seczap(3, Vector4(203, 270, 30, 5)) + + #$canvas.set_seczap_color(2, Color.MAGENTA) + #$canvas.set_seczap_color(3, Color.CHARTREUSE) + + +func on_navi_data_received(data: Dictionary): + $canvas.set_canvas_rotation(data.get('k', 0.0)) + course = data.get('k', 0.0) func on_user_panning(): @@ -166,7 +205,7 @@ func get_all_nodes(root): ## Производит отображение цели на диаграмму. -func map_threat_to_bip(th: threats.Threat, bip: Control): +func map_threat_to_bip(th: threats.Threat, bip: Control) -> bool: var freq = th.freq var sector_key = null var sector_width = 50.0 @@ -176,7 +215,7 @@ func map_threat_to_bip(th: threats.Threat, bip: Control): if freq_range[0] <= freq and freq <= freq_range[1]: sector_key = key break - if sector_key!= null: + if sector_key != null: radius_internal = fs_band[sector_key][0] radius_outter = fs_band[sector_key][1] freq_low = prd.FS_FREQ[sector_key][0] @@ -189,33 +228,34 @@ func map_threat_to_bip(th: threats.Threat, bip: Control): radius_outter, freq_low, freq_high) - bip.size / 2 + return sector_key != null ## Обработчик сигнала обновления цели. func on_threat_update(th): var bip = get_node('%d' % th.id) bip.update(th.tick_rx) - map_threat_to_bip(th, bip) + bip.visible = map_threat_to_bip(th, bip) ## Обработчик выбора помехи для цели. func on_interfer_new(ecm): - if interfer.thrs.has(ecm.ispp): - var th_id = interfer.thrs[ecm.ispp] - var bip = get_node('%d' % th_id) - if bip != null: - if ecm.krp!= interfer.INTERFER_OFF: - bip.set_track_visible(true) - if ecm.svk == 1: - bip.set_ecm_visible(true) - else: bip.set_ecm_visible(false) - else: - bip.set_ecm_visible(false) - bip.set_track_visible(false) + if not interfer.thrs.has(ecm.ispp): return + var th_id = interfer.thrs[ecm.ispp] + var bip = get_node('%d' % th_id) + if bip != null: + if ecm.krp!= interfer.INTERFER_OFF: + bip.set_track_visible(true) + if ecm.svk == 1: + bip.set_ecm_visible(true) + else: bip.set_ecm_visible(false) else: - interfer.thrs.erase(ecm.ispp) - set_fs_color(ecm) - update_fs_colors() + bip.set_ecm_visible(false) + bip.set_track_visible(false) + else: + interfer.thrs.erase(ecm.ispp) + set_fs_color(ecm) + update_fs_colors() set_fs_color(ecm) @@ -226,6 +266,7 @@ func on_interfer_off_all(): bip.set_ecm_visible(false) bip.set_track_visible(false) fs_active.clear() + fs_emit.clear() update_fs_colors() @@ -259,24 +300,33 @@ func on_rto_threat_sel(th_id, ecm_btns): unsel_fs_all(false) else: item.set_sel_visible(false) + var th = thrs_dict[th_id] + var krp = interfer.get_krp(th) for btn in ecm_btns: set_btns_disabled(false, btn) + var btn_meta = btn.get_meta('rfi_name') + if krp == btn_meta: + btn.modulate = Color.DEEP_SKY_BLUE + else: + btn.modulate = Color(1.0, 1.0, 1.0, 1.0) ## Обработчик снятия выбора РТО цели. -func on_rto_threat_unsel(th_id, _ecm_btns): +func on_rto_threat_unsel(th_id, ecm_btns): var bips: Array = get_children().filter(func(item): return item.name.is_valid_int()) for item in bips: if th_id == item.name.to_int(): item.set_sel_visible(false) break set_ecm_btns_state(true) + for btn in ecm_btns: + btn.modulate = Color(1.0, 1.0, 1.0, 1.0) ## Обработчик нажатия кнопки "Строб". Управляет отображением строба. func on_button_strobe_pressed() -> void: drag_fsm = DragFSM.IDLE if $btns_select/btn_strob.is_pressed() else DragFSM.OFF - $canvas.set_strob_visible(drag_fsm == DragFSM.IDLE) + $canvas.set_strob_visible((drag_fsm == DragFSM.IDLE) and (view_mode == MapViewMode.RTO)) ## Поведение радиокнопок в группе. Управляет состоянием кнопок выбора целей. @@ -341,6 +391,7 @@ func set_strob(pos: Vector2) -> void: ## Обработка движения мыши для управления стробом. Вызывается во время движения мыши. func _on_drag_continue(event) -> void: + if not $canvas.get_strob_visible(): return if drag_button == MOUSE_BUTTON_RIGHT: if shift_pressed: var strob_width: float = get_strob_width(event.position, strob_width_begin) @@ -354,6 +405,7 @@ func _on_drag_continue(event) -> void: ## Обработка движения мыши для управления стробом. Вызывается при нажатии мыши. func _on_drag_begin(event) -> void: + if not $canvas.get_strob_visible(): return drag_pos_begin = event.position if drag_button == MOUSE_BUTTON_LEFT: set_strob(event.position) @@ -390,7 +442,7 @@ func sel_fs_sector(event): if (event.button_index == MOUSE_BUTTON_LEFT) or (event.button_index == MOUSE_BUTTON_RIGHT): var center: Vector2 = $tilemap.position var center_offset: Vector2 = ProjectSettings.get_setting('application/interfer/center_offset', Vector2i(0, 25)) - var angle: float = event.position.angle_to_point(center + center_offset) * 180/PI - 45.0 + var angle: float = event.position.angle_to_point(center + center_offset) * 180/PI - 45.0 - course if angle < 0: angle += 360 var distance: float = event.position.distance_to(center + center_offset) @@ -418,21 +470,31 @@ func sel_fs_sector(event): func set_fs_color(ecm): + if not prd.fs_caps_id.has(ecm.nmfs): + push_warning('нет такого модуля ФС: %d, но имеется: %s' % [ecm.nmfs, prd.fs_caps_id.keys()]) + return if ecm.krp != interfer.INTERFER_OFF: fs_active[prd.fs_caps_id[ecm.nmfs]] = null else: fs_active.erase(prd.fs_caps_id[ecm.nmfs]) + if ecm.svk == SVK_EMIT: + fs_emit[prd.fs_caps_id[ecm.nmfs]] = null + else: + fs_emit.erase(prd.fs_caps_id[ecm.nmfs]) update_fs_colors() func update_fs_colors(): var fs_colors = $canvas.fs_default_colors.duplicate() - var color_ecm: Vector3 = ProjectSettings.get_setting('application/interfer/interfer_color', Vector3(0.58, 0.47, 0.51)) - var color_select: Vector3 = ProjectSettings.get_setting('application/interfer/select_color', Vector3(1.0, 1.0, 1.0)) for key in fs_active.keys(): fs_colors[key] = color_ecm + for key in fs_emit.keys(): + fs_colors[key] = color_emit for key in fs_selected.keys(): - fs_colors[key] = color_select + if key in fs_emit: + fs_colors[key] = color_emit_sel + else: + fs_colors[key] = color_select $canvas.set_band_colors(fs_colors) @@ -470,6 +532,7 @@ func set_btns_disabled(value: bool, btn): func on_fs_update_color(ecms): fs_active.clear() + fs_emit.clear() for ecm in ecms.values(): set_fs_color(ecm) update_fs_colors() diff --git a/scenes/работа/работа.tscn b/scenes/работа/работа.tscn index 692683ec..0e89ccb0 100644 --- a/scenes/работа/работа.tscn +++ b/scenes/работа/работа.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=17 format=3 uid="uid://b276iygic5itk"] +[gd_scene load_steps=18 format=3 uid="uid://b276iygic5itk"] [ext_resource type="Script" uid="uid://daudc0s3oox3i" path="res://scenes/работа/работа.gd" id="1_niok4"] [ext_resource type="PackedScene" uid="uid://nl1vklubr5kr" path="res://scenes/bip/bip.tscn" id="2_br3s6"] @@ -51,6 +51,10 @@ _data = { offsets = PackedFloat32Array(0.181818, 0.751623) colors = PackedColorArray(1, 1, 1, 0.352941, 1, 1, 1, 0) +[sub_resource type="SystemFont" id="SystemFont_5ffal"] +generate_mipmaps = true +subpixel_positioning = 0 + [node name="Работа" type="Panel"] script = ExtResource("1_niok4") Bip = ExtResource("2_br3s6") @@ -86,6 +90,7 @@ self_modulate = Color(1, 1, 1, 0.415686) position = Vector2(360, 360) min_zoom_level = 3 max_zoom_level_server = 11 +ship_radius_km = 3.0 az = 3.0 [node name="player" type="AnimationPlayer" parent="tilemap"] @@ -95,11 +100,10 @@ libraries = { [node name="grd_side" parent="." instance=ExtResource("3_s2j0e")] layout_mode = 0 -offset_left = 1114.0 +offset_left = 1116.0 offset_top = 7.0 offset_right = 1594.0 offset_bottom = 1170.0 -metadata/_edit_lock_ = true [node name="grd_btns" parent="." instance=ExtResource("5_2jnbs")] layout_mode = 0 @@ -203,6 +207,7 @@ offset_left = 115.0 offset_top = 1085.0 offset_right = 257.0 offset_bottom = 1112.0 +tooltip_text = "Автоматический выбор цели и помехи" action_mode = 0 text = "Автоматически" @@ -259,6 +264,7 @@ offset_top = 995.0 offset_right = 1136.0 offset_bottom = 1127.0 scale = Vector2(0.5, 0.5) +tooltip_text = "Применение выбранного режима помехи" toggle_mode = true button_pressed = true action_mode = 0 @@ -283,27 +289,58 @@ offset_top = 1005.0 offset_right = 1030.0 offset_bottom = 1121.0 scale = Vector2(0.5, 0.5) +tooltip_text = "Устанавливает центр карты на текущие координаты" toggle_mode = true button_pressed = true texture_normal = ExtResource("12_5ffal") texture_pressed = ExtResource("13_ggrwd") +[node name="label" type="Label" parent="btn_center"] +layout_mode = 0 +offset_left = -32.0 +offset_top = 100.0 +offset_right = 65.0 +offset_bottom = 119.0 +scale = Vector2(2, 2) +text = "Центрировать" +horizontal_alignment = 1 +vertical_alignment = 1 + [node name="coordinates_map" type="Label" parent="."] layout_mode = 0 -offset_left = 1000.0 +offset_left = 999.0 offset_top = 128.0 -offset_right = 1112.0 +offset_right = 1111.0 offset_bottom = 147.0 text = "Координаты:" [node name="scale_map" type="Label" parent="."] layout_mode = 0 -offset_left = 1000.0 -offset_top = 192.0 -offset_right = 1110.0 -offset_bottom = 213.0 +offset_left = 999.0 +offset_top = 202.0 +offset_right = 1109.0 +offset_bottom = 223.0 text = "Масштаб:" +[node name="zoom_plus" type="Button" parent="."] +layout_mode = 0 +offset_left = 1056.0 +offset_top = 230.0 +offset_right = 1088.0 +offset_bottom = 262.0 +theme_override_fonts/font = SubResource("SystemFont_5ffal") +theme_override_font_sizes/font_size = 20 +text = "+" + +[node name="zoom_minus" type="Button" parent="."] +layout_mode = 0 +offset_left = 1056.0 +offset_top = 270.0 +offset_right = 1088.0 +offset_bottom = 302.0 +theme_override_font_sizes/font_size = 20 +text = "−" + [connection signal="drag_begin" from="." to="." method="_on_drag_begin"] [connection signal="drag_continue" from="." to="." method="_on_drag_continue"] [connection signal="toggled" from="btn_view" to="." method="on_button_view_toggled"] @@ -311,3 +348,8 @@ text = "Масштаб:" [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate_toggled"] [connection signal="toggled" from="btn_activate" to="." method="on_btn_activate"] [connection signal="toggled" from="btn_center" to="." method="on_btn_center_toggled"] +[connection signal="button_down" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_down"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_plus_button_up"] +[connection signal="button_up" from="zoom_plus" to="tilemap" method="_on_zoom_button_up"] +[connection signal="button_down" from="zoom_minus" to="tilemap" method="_on_zoom_minus_button_down"] +[connection signal="button_up" from="zoom_minus" to="tilemap" method="_on_zoom_button_up"] diff --git a/scripts/capsrpb.gd b/scripts/capsrpb.gd index d889997d..6a56699e 100644 --- a/scripts/capsrpb.gd +++ b/scripts/capsrpb.gd @@ -17,7 +17,7 @@ class CapsRpb extends unit.Unit: var source_addr: Array ## Адрес отправителя данных func _to_string() -> String: return String('CapsRpb(\"%s\")' % self.name) - func _init(nm): self.name = nm + func _init(unit_name): self.name = unit_name func parse(data: PackedByteArray, now_tick: int): tick = now_tick diff --git a/scripts/interfer.gd b/scripts/interfer.gd index 37cd4b81..ee76a19c 100644 --- a/scripts/interfer.gd +++ b/scripts/interfer.gd @@ -5,7 +5,7 @@ class_name Iterfer extends Node ## Режимы помехи. const ITERFER_MODE = { INTERFER_OFF: [INTERFER_OFF, {}, 0], - 'srni1': ['ПСП + ФМ-2', SRNI1_PARAMS, 1], + 'srni1': [INTERFER_IQFILE, SRNI1_PARAMS, 1], 'srnm2': ['Линейная ЧМ', SRNM2_PARAMS, 2], 'srngps': [INTERFER_IQFILE, SRNGPS_PARAMS, 3], 'lchm1': ['Линейная ЧМ', LCHM1_PARAMS, 10], @@ -19,14 +19,17 @@ const ITERFER_MODE = { 'svm2': [INTERFER_IQFILE, SVM2_PARAMS, 21], 'k1': [INTERFER_IQFILE, K1_PARAMS, 50], 'ozp1': [INTERFER_IQFILE, OZP1_PARAMS, 51], - 'eprls': [INTERFER_IQFILE, EPRLS_PARAMS, 52], } + 'eprls': [INTERFER_IQFILE, EPRLS_PARAMS, 52] } const RECOMMEND_INTERFER = { 'ПСП + ФМ-2': 'srni1', 'Линейная ЧМ': 'lchm1' } -const SRNI1_PARAMS = {'par_names' : ['freq', 'width']} +const SRNI1_PARAMS = {'files': {3: ['SRNI1_LIT4.pcm', 1220], + 4: ['SRNI1_LIT5.pcm', 1555]}, + 'call_proc': 'call_diap', + 'par_names' : ['freq', 'filename']} const SRNM2_PARAMS = {'par_names' : ['freq', 'width', 'period']} const SRNGPS_PARAMS = {'par_names' : ['freq', 'filename'], 'files': 'SRNGPS.pcm', @@ -36,15 +39,27 @@ const LCHM2_PARAMS = {'par_names' : ['freq', 'width', 'period']} const MCHM1_PARAMS = {'par_names' : ['freq', 'filename'], 'files': 'MCHM1.pcm', 'call_proc': 'call_all_diap'} -const PDM2_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM2_20.pcm', - 'call_proc': 'call_all_diap'} -const PDM4_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM4_20.pcm', - 'call_proc': 'call_all_diap'} -const PDM4S_PARAMS = {'par_names' : ['freq', 'filename'], - 'files': 'PDM4S_5.pcm', - 'call_proc': 'call_all_diap'} +const PDM2_PARAMS = {'files': { + 20 : 'PDM2_20.pcm', + 40: 'PDM2_40.pcm', + 88: 'PDM2_88.pcm', + 112: 'PDM2_112.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} +const PDM4_PARAMS = {'files': { + 20 : 'PDM4_20.pcm', + 40: 'PDM4_40.pcm', + 84: 'PDM4_84.pcm', + 108: 'PDM4_108.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} +const PDM4S_PARAMS = {'files': { + 5 : 'PDM4S_5.pcm', + 7 : 'PDM4S_10.pcm', + 10: 'PDM4S_2_5.pcm', + 20: 'PDM4S_10.pcm' }, + 'call_proc': 'call_pdchm', + 'par_names' : ['freq', 'filename'],} const K1_PARAMS = {'files' : 'K1.pcm', 'call_proc' : 'call_all_diap', 'par_names' : ['freq', 'filename']} @@ -65,10 +80,10 @@ const EPRLS_PARAMS = {'files' : 'ERLS.pcm', 'par_names' : ['freq', 'filename']} # Файл : Ключ (ширина): ['имя файла'] const PDCHM_PARAMS = {'files': { - 5 : 'pdchm_5.pcm', - 10: 'pdchm__0.pcm', - 20: 'pdchm_20.pcm', - 40: 'pdchm_40.pcm' }, + 5 : 'PDCHM_5.pcm', + 10: 'PDCHM_10.pcm', + 20: 'PDCHM_20.pcm', + 40: 'PDCHM_40.pcm' }, 'call_proc': 'call_pdchm', 'par_names' : ['freq', 'filename'],} @@ -77,7 +92,7 @@ const EXCLUDE_INTERFER = ['srni1', 'srnm2', 'srngps', 'svi1', 'svm2'] const ID_INTERFERS_LEN = 63 ## Размер пула номеров целей. const INTERFER_OFF = 'off' const INTERFER_IQFILE = 'IQ-файл' -const POW_DEFAULT: float = 100.0 +const POW_DEFAULT: float = 50.0 var msg6_num: int = 0 ## Счётчик сообщений "тип 6" var msg8_num: int = 0 ## Счётчик сообщений "тип 8" var id_array: Array ## Массив id воздействий. @@ -87,6 +102,8 @@ var cu: Dictionary ## Словарь воздействий для 5 var thrs_dict: Dictionary ## Ссылка на словарь целей var auto_enabled: bool = false ## Режим автомата var emit_enable: bool = true ## Разрешить излучение +var trenazh_mode: bool = false ## Переключение режима Тренаж +var course = 0.0 ## Курс корабля ## Сеанс помехи. class Interfer: @@ -163,7 +180,6 @@ func on_full_auto() -> void: auto_enabled = true func _ready() -> void: - var ecms: Dictionary = {} ## Словарь помех. for i in ID_INTERFERS_LEN: # Заполняет массив ID целей id_array.append(i + 1) var unit_caps = network.get_unit_instance('уарэп-капсрпб') @@ -171,13 +187,15 @@ func _ready() -> void: var timer_check_state: = Timer.new() add_child(timer_check_state) var resend_timeout = ProjectSettings.get_setting('application/interfer/resend_timeout', 1000.0) + var ecms: Dictionary = {} ## Словарь помех. + var seczaps: Dictionary = {} ## Словарь секторов запрета timer_check_state.connect('timeout', Callable(self, 'on_timer_check_state').bind(unit_caps, ecms, resend_timeout)) timer_check_state.start(resend_timeout / 1000.0) - unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms)) + unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received').bind(ecms, seczaps)) 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_caps, ecms)) signaller.connect('interfer_rcv', Callable(self, 'on_interfer_rcv').bind(unit_5p28, ecms)) - signaller.connect('interfer_new', Callable(self, 'send_ecm').bind(unit_caps)) + signaller.connect('interfer_new', Callable(self, 'on_interfer_new').bind(unit_caps)) signaller.connect('interfer_off_all', Callable(self, 'on_interfer_off_all').bind(unit_caps, ecms)) signaller.connect('th_aoa_update', Callable(self, 'on_th_aoa_update').bind(ecms, unit_caps)) signaller.connect('interfer_off', Callable(self, 'on_interfer_off').bind(ecms)) @@ -185,15 +203,20 @@ func _ready() -> void: signaller.connect('full_auto', Callable(self, 'on_full_auto')) signaller.connect('interfer_prinuditelno', Callable(self, 'on_interfer_prinuditelno')) signaller.connect('emit_changed', Callable(self, 'on_emit_changed').bind(ecms)) + signaller.connect('режим_тренаж', on_trenazh_mode) threats.connect('threat_lost', Callable(self, 'on_threats_lost').bind(ecms, unit_caps)) - var unit_nav = network.get_unit_instance('навигация') - unit_nav.connect('data_received', on_nav_data_received.bind(unit_caps)) threats.connect('threats_resized', Callable(self, 'on_threats_resized')) threats.connect('threat_update', Callable(self, 'on_threats_update').bind(ecms, unit_caps)) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_nav_data_received.bind(unit_caps)) + + +func on_trenazh_mode(val: bool): trenazh_mode = val func on_nav_data_received(coords: Dictionary, unit_caps): var ship_time = Time.get_datetime_dict_from_system() + course = coords.get('k', 0.0) var data_to_json = { 'ts': 8, 'ss': msg8_num, @@ -216,25 +239,27 @@ func on_nav_data_received(coords: Dictionary, unit_caps): ## Проверяет состояние отправки пакета и если не доставлен, повторяет отправку. -func on_timer_check_state(unit, ecms, resend_timeout) -> void: +func on_timer_check_state(unit_instance, ecms, resend_timeout) -> void: var tick = Time.get_ticks_msec() for ecm in ecms.values(): if (tick - ecm.tick_tx) >= resend_timeout: - send_ecm(ecm, unit) + send_ecm(ecm, unit_instance) ecm.tick_tx = tick -func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit) -> void: +func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit_instance) -> void: for thr in threats.values(): var th_id = thr.id for ecm_i in thrs.keys(): if thrs[ecm_i] == th_id: var ecm = ecms[ecm_i] ecm.params['freq'] = thr.freq - ecm.kni = thr.aoa - send_ecm(ecm, unit) + ecm.kni = thr.aoa - course + if ecm.kni < 0: + ecm.kni += 360 + send_ecm(ecm, unit_instance) signaller.emit_signal('fs_update_color', ecms) - prd.update_fs_state(ecms) + prd.update_fs_state(ecms, trenazh_mode) if not auto_enabled: return @@ -247,84 +272,91 @@ func on_th_aoa_update(threats: Dictionary, ecms: Dictionary, unit) -> void: ## Производит приём состояния помех. [param unit] -> [param ecms]. -func on_data_capsrpb_received(unit0: capsrpb.CapsRpb, ecms: Dictionary) -> void: - if not unit0.json_dic.has('ts'): return - if not (unit0.json_dic['ts'] is float): return - if unit0.json_dic['ts'] != 5: return - if not unit0.json_dic.has('msvk'): return - if not (unit0.json_dic['msvk'] is Array): return - var msvk = unit0.json_dic['msvk'] +func on_data_capsrpb_received(unit_instance: capsrpb.CapsRpb, ecms: Dictionary, seczaps: Dictionary) -> void: + if not unit_instance.json_dic.has('ts'): return + if not tools.type_is_num(unit_instance.json_dic['ts']): return + if unit_instance.json_dic['ts'] != 5: return + map_msvk_to_ecms(unit_instance, ecms) + map_mpchf_to_seczaps(unit_instance, seczaps) + + +## Извлекает массив состояний выполнения команды +func map_msvk_to_ecms(unit_instance: unit.Unit, ecms: Dictionary): + var json_dic = unit_instance.json_dic + if not json_dic.has('msvk'): return + var msvk = unit_instance.json_dic.get('msvk', []) for dic_msvk in msvk: - if not (dic_msvk is Dictionary): continue - if dic_msvk.has('ispp'): - var ispp = int(dic_msvk['ispp']) - var errmsg = dic_msvk.get('errmsg', '') - if errmsg: - log.error('сеанс %d: \"%s\"' % [ispp, errmsg]) - 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, unit0) + if dic_msvk is not Dictionary: continue + if not dic_msvk.has('ispp'): continue + var ispp = int(dic_msvk['ispp']) + var errmsg = dic_msvk.get('errmsg', '') + if errmsg: + log.error('сеанс %d: \"%s\"' % [ispp, errmsg]) + 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_instance) + + +## Извлекает массив пространственно-частотных фильтров +func map_mpchf_to_seczaps(unit_instance: unit.Unit, seczaps: Dictionary): + var json_dic: = unit_instance.json_dic as Dictionary + var mpchf = json_dic.get('mpchf', []) + if mpchf is not Array: return + for item in mpchf: + if item is not Dictionary: continue + var id = item.get('index', -1) + if id < 0: continue + var freq = item.get('freq', 0) + if freq == 0: continue ## Вызыватся, когда пользователь выбрал помеху и выбраны цели. func on_interfer_create(interfer_name, sel_threats, fs_arr, power, u, ecms) -> void: - var ecm_name = interfer_name for item in sel_threats: var param: Dictionary = {} - var kni: float = item.aoa + var kni: float = item.aoa - course + if kni < 0: + kni += 360.0 var id = item.id param['freq'] = item.freq param['width'] = item.width - if (item.rkrp != '') and item.fflags.rkrp: + if (item.rkrp != '') and item.fflags.rkrp and auto_enabled: var krp = get_krp(item) if krp != '': - ecm_name = krp + interfer_name = krp set_rparams(item, param) if (param['width'] < settings.WIDTH_MIN): param['width'] = settings.WIDTH_MIN elif (param['width'] > settings.WIDTH_MAX): param['width'] = settings.WIDTH_MAX - interfer_create(u, ecm_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0], power) + interfer_create(u, interfer_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0], power) for item in fs_arr: var param: Dictionary = {} var kni: float = item[0] var id = item[3] - var th = null - if not interfer_name in EXCLUDE_INTERFER: - th = find_threat(item[1], kni) - if th != null: - param['freq'] = th.freq - param['width'] = th.width - if (th.rkrp != '') and th.fflags.rkrp: - var krp = get_krp(th) - if krp != '': - ecm_name = krp - set_rparams(th, param) - else: - param['freq'] = item[1] - param['width'] = item[2] + param['freq'] = item[1] + param['width'] = item[2] if (param['width'] < settings.WIDTH_MIN): param['width'] = settings.WIDTH_MIN elif (param['width'] > settings.WIDTH_MAX): param['width'] = settings.WIDTH_MAX - if th == null: - interfer_create(u, ecm_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1], power) - else: - id = th.id - interfer_create(u, ecm_name, ecms, param, kni, id, thrs, SOURCE_INTERFER[0], power) + interfer_create(u, interfer_name, ecms, param, kni, id, fs, SOURCE_INTERFER[1], power) + func on_interfer_rcv(interfer_params: Array, unit0, ecms) -> void: var err: bool = false var mode = interfer_params[0] var id = interfer_params[1] - var aoa = interfer_params[2] + var aoa = interfer_params[2] - course + if aoa < 0: + aoa += 360 var um = interfer_params[3] if (aoa < 0.0) and (aoa > 360.0): err = true @@ -402,8 +434,8 @@ func interfer_create(u, interfer_name, ecms, param, kni, id, dict, source_interf func send_ecm(ecm, unit0) -> void: if ecm.krp != INTERFER_OFF: if not emit_enable: - return - elif not ecm.modulation: + ecm.svk = 0 + call_deferred('emit_signal', 'interfer_update', ecm) return msg6_num += 1 var json_data = ecm.get_msg6_data(msg6_num) @@ -491,13 +523,15 @@ func on_threats_update(threat, ecms, unit_caps): ecm = ecms[ecm_i] ecm.params['freq'] = threat.freq ecm.params['width'] = threat.width - if (threat.rkrp != '') and threat.fflags.rkrp: + if (threat.rkrp != '') and threat.fflags.rkrp and auto_enabled: var krp = get_krp(threat) if krp != '': ecm.krp = krp set_rparams(threat, ecm.params) emit_signal('interfer_recommendate', ecm) - ecm.kni = threat.aoa + ecm.kni = threat.aoa - course + if ecm.kni < 0: + ecm.kni += 360 set_nmfs(ecm) if threat.tmod != 'fm': if ecm != null: @@ -607,3 +641,11 @@ func on_interfer_off(ecm: Interfer, ecms): interfer.push_id(ecm.ispp) if sz != ecms.size(): interfer.call_deferred('emit_signal', 'interfer_resized', ecms) + + +func on_interfer_new(ecm, unit_caps): + var ecm_params = ITERFER_MODE[ecm.krp][1] + if ecm_params.has('call_proc'): + var call_set_params = Callable(self, ecm_params['call_proc']).bind(ecm, ecm_params) + call_set_params.call() + send_ecm(ecm, unit_caps) diff --git a/scripts/navigation.gd b/scripts/navigation.gd index a5bd9170..2e8ed4a9 100644 --- a/scripts/navigation.gd +++ b/scripts/navigation.gd @@ -26,10 +26,10 @@ class NaviSource extends unit.Unit: if not online: online = true emit_signal('line_changed', self) - if rx_data.size() < 28: + if rx_data.size() < 32: emit_signal('parse_failed', self) return false - var flags: = rx_data.decode_u16(26) # Флаги достоверности полей структуры + var flags: = rx_data.decode_u16(28) # Флаги достоверности полей структуры data.clear() data['mode'] = akng_mode[(flags >> 4) & 3] # Режим работы АКНГ if flags & (1 << 0): diff --git a/scripts/network.gd b/scripts/network.gd index 31f19575..dea87069 100644 --- a/scripts/network.gd +++ b/scripts/network.gd @@ -1,3 +1,4 @@ +#@tool class_name Network extends Node const YAU07_PROTO: = {'yau07tx': yau07.YaU07} @@ -6,7 +7,7 @@ const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28} const SERIAL_PROTO: = {'spt25': spt25.SPT25} const MODBUS_PROTO: = {'mbcs': sch3.Sch3} const NAVI_PROTO: = {'navi': navi.NaviSource} - +const NULL_PROTO: = {null: unit.Unit} var tick: int = 0 @@ -19,32 +20,46 @@ class SocketSerial extends SerialPort: 'N': SerialPort.PARITY_NONE, 'E': SerialPort.PARITY_EVEN, 'O': SerialPort.PARITY_ODD } + static var tick: int + var unit_instance: unit.Unit - var tx_buffer: PackedByteArray + func on_serial_data(data: PackedByteArray): + unit_instance.parse(data, tick) - func _init() -> void: - tx_buffer.resize(256) + func on_settings_changed(): + try_close() + var rc = try_open() + if rc != Error.OK: + log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [self, unit_instance.name]) + else: + log.message(log.INFO, '%s для \"%s\"' % [self, unit_instance.name]) - func send_to(data: PackedByteArray): - tx_buffer[0] = 0x7e + func format_buffer(data: PackedByteArray): + var buffer: PackedByteArray + buffer.resize(64) var i: = 1 for v in data: if v != 0x7e: - tx_buffer[i] = v - i += 1 + buffer[i] = v; i += 1 else: - tx_buffer[i] = FLAG - i += 1 - tx_buffer[i] = FLAG ^ FLAG_MASK - i += 1 + buffer[i] = FLAG; i += 1 + buffer[i] = FLAG ^ FLAG_MASK; i += 1 var v_sum: = get_check_sum(data) - tx_buffer.encode_u16(i, v_sum) - i += 2 - tx_buffer[i] = FLAG - i += 1 + buffer.encode_u16(i, v_sum); i += 2 + buffer[i] = FLAG; i += 1 + buffer.resize(i) + return buffer + + func send_to(data: PackedByteArray): + if not is_open(): + try_open() + return + # var buffer = format_buffer(data) # Не проверено, но должно работать # Эта последовательность для запроса состояния, получена от разработчиков СПТ-25 - const tx_tula = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] - write_raw(tx_tula) + const tx_tula: = [0x7e, 0x01, 0x04, 0xbb, 0x50, 0x7e] + var sz = write_raw(tx_tula) + if sz != tx_tula.size(): + try_open() func _to_string() -> String: return 'последовательный порт \"%s\" @ %d (%s)' % [self.port, self.baudrate, 'открыт' if is_open() else 'закрыт'] @@ -65,12 +80,12 @@ class SocketSerial extends SerialPort: fcs = (fcs >> 1) ^ P_DIV if fcs & 1 else fcs >> 1 return (~fcs) & 0xffff - func try_open(parsing_proc: Callable): + func try_open() -> Error: if is_open(): return Error.OK var rc: = open(port) if rc == Error.OK: - data_received.connect(parsing_proc) + data_received.connect(on_serial_data) start_monitoring(timeout) return rc @@ -79,7 +94,7 @@ class SocketSerial extends SerialPort: return Error.FAILED stop_monitoring() close() - var connections = data_received.get_connections() + var connections: = data_received.get_connections() for conn in connections: data_received.disconnect(conn.callable) return Error.OK @@ -119,6 +134,7 @@ var units_udprx: Dictionary[StringName, unit.Unit] ## Экземпляры var units_tcp: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с tcp-соединением var units_serial: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с uart-соединением var units_modbus: Dictionary[StringName, unit.Unit] ## Экземпляры устройств с modbusserial-соединением +var units_nullp: Dictionary[StringName, unit.Unit] ## Экземпляры устройств без протокола var serials: Dictionary[StringName, SocketSerial] ## Последовательные порты (uart) var dst_ports: Dictionary[StringName, int] ## Преобразование имя устройства в порт назначения var dst_addrs: Dictionary[StringName, StringName] ## Преобразование имя устройства в адрес назначения @@ -128,9 +144,6 @@ var send_sockets: Dictionary[StringName, SocketUDP] ## Таблица <имя var addr_port_to_unit_name: Dictionary[StringName, StringName] ## Преобразование адрес:порт в имя устройства -func on_serial_data(data, unit): unit.parse(data, tick) - - ## [param unit_name] - Уникальное имя устройства[br] func create_socket_udp(unit_name: StringName) -> SocketUDP: var st = settings.UnitProfiles[unit_name][1] @@ -151,8 +164,8 @@ func create_socket_udp(unit_name: StringName) -> SocketUDP: func create_socket_caps(unit_name: StringName) -> SocketUDP: var st = settings.UnitProfiles[unit_name][1] - var addr = st[0] - var port = st[1] + var addr = st[1] + var port = st[2] var sock: = SocketUDP.new() var rc: = sock.bind(port, addr) if rc == Error.OK: @@ -179,8 +192,8 @@ func create_socket_tcp(unit_name: StringName) -> SocketTCP: ## [param unit_name] - Уникальное имя устройства[br] -func create_serial(unit_name: StringName) -> SocketSerial: - var st = settings.UnitProfiles[unit_name][1] +func create_serial(unit_instance: unit.Unit) -> SocketSerial: + var st = settings.UnitProfiles[unit_instance.name][1] var serial: = SocketSerial.new() serial.port = st[0] serial.baudrate = st[2] @@ -188,9 +201,14 @@ func create_serial(unit_name: StringName) -> SocketSerial: serial.timeout = 20000 serial.bytesize = st[4] serial.stopbits = st[5] + serial.unit_instance = unit_instance return serial +func on_serial_got_error(where: String, what: String, serial: SocketSerial, unit_instance: unit.Unit): + push_error([where, what, serial]) + + ## [param unit_name] - Уникальное имя устройства[br] func create_modbus(unit_name: StringName) -> sch_3.Sch3: var unit_modbus: = sch_3.Sch3.new(unit_name) @@ -198,6 +216,7 @@ func create_modbus(unit_name: StringName) -> sch_3.Sch3: func _ready() -> void: + if Engine.is_editor_hint(): return var sock_unicast: = create_socket_udp('уарэп-яу07-частный') var sock_broadcast: = create_socket_udp('уарэп-яу07-общий') var sock_navi: = create_socket_udp('навигация') @@ -249,7 +268,7 @@ func _ready() -> void: units[unit_name] = new_unit units_udptx[unit_name] = new_unit dst_addrs[unit_name] = unit_profile[0] - dst_ports[unit_name] = unit_profile[2] + dst_ports[unit_name] = unit_profile[3] if proto in TCP_PROTO: var unit_tcp = TCP_PROTO[proto].new(unit_name) @@ -265,14 +284,20 @@ func _ready() -> void: bind_modbuses.append([unit_modbus, unit_name]) if proto in SERIAL_PROTO: - var unit_serial = SERIAL_PROTO[proto].new(unit_name) - var serial: = create_serial(unit_name) - units_serial[unit_name] = unit_serial - units[unit_name] = unit_serial + var unit_instance = SERIAL_PROTO[proto].new(unit_name) + var serial: = create_serial(unit_instance) + serial.connect('got_error', on_serial_got_error.bind(serial, unit_instance)) + ProjectSettings.connect('settings_changed', serial.on_settings_changed) + units_serial[unit_name] = unit_instance + units[unit_name] = unit_instance serials[unit_name] = serial - bind_serials.append([serial, unit_serial, unit_name]) + bind_serials.append([serial, unit_instance, unit_name]) + + if proto in NULL_PROTO: + var unit_null = NULL_PROTO[proto].new(unit_name) + units[unit_name] = unit_null + units_nullp[unit_name] = unit_null - ProjectSettings.connect('settings_changed', Callable(self, '_on_settings_changed_serial').bind(bind_serials)) tcp_sockets.append([create_socket_tcp('уарэп-5п28'), units_tcp['уарэп-5п28']]) for key: StringName in dst_ports: @@ -291,21 +316,6 @@ func _on_settings_changed_modbus(bind_modbuses: Array): var _unit_name = bm[1] -func _on_settings_changed_serial(bind_serials: Array): - var external_ctl = ProjectSettings.get_setting('application/config/Внешнее управление', false) - for bs in bind_serials: - var serial = bs[0] - var unit_serial = bs[1] - var unit_name = bs[2] - serial.try_close() - if not external_ctl: - var rc = serial.try_open(on_serial_data.bind(unit_serial)) - if rc != Error.OK: - log.message(log.ERROR, 'невозможно открыть %s для \"%s\"' % [serial, unit_name]) - else: - log.message(log.INFO, '%s для \"%s\"' % [serial, unit_name]) - - func poll_receive_udp(sock: SocketUDP) -> bool: while sock.get_available_packet_count() > 0: var data: = sock.get_packet() @@ -397,6 +407,7 @@ func _process(_delta: float) -> void: for unit_name: StringName in units_serial: var unit_serial: = units_serial[unit_name] var serial: = serials[unit_name] + serial.tick = tick if Error.OK == unit_serial.process(tick): serial.send_to(unit_serial.tx_data) for unit_name: StringName in units_modbus: diff --git a/scripts/prd.gd b/scripts/prd.gd index 30cfe54f..46c8e08b 100644 --- a/scripts/prd.gd +++ b/scripts/prd.gd @@ -33,8 +33,8 @@ const FS_FREQ: Dictionary = { 0: [390.0, 510.0, 450.0], 1: [800.0, 1065.0, 932.0], 2: [1065.0, 1210.0, 1137.0], - 3: [1150.0, 1280.0, 1215.0], - 4: [1490.0, 2000.0, 1575.0], + 3: [1150.0, 1380.0, 1215.0], + 4: [1380.0, 2000.0, 1575.0], 5: [2000.0, 3500.0, 2750.0], 6: [3500.0, 6000.0, 4750.0] } @@ -86,18 +86,18 @@ const FS_PRD: Dictionary = { var fs_dict: Dictionary ## Словарь с модулями ФС var prd_dict: Dictionary ## Словарь с приборами ПРД - +var course = 0.0 ## Курс корабля var fs_caps_id: Dictionary ## Словарь соответствия номеров ФС от КАПС РПБ внутрипрограммной нумерации class Fs: const UM_PORTS: Dictionary = { 1 : 0x106, - 2 : 0x10A, + 2 : 0x108, 3 : 0x106, - 4 : 0x10A, + 4 : 0x108, 5 : 0x106, - 6 : 0x10A } + 6 : 0x108 } const CODE_UM: Array = [ [-5, 0], @@ -145,7 +145,7 @@ class Fs: if UM_PORTS.has(index/4): var val = um_code_tx if u.isa_ports.has(um_port): - val = tools.set_bits(u.isa_ports[um_port], um_code_tx, 0x0003) + val = tools.set_bits(u.isa_ports[um_port], um_code_tx, 0x0007) data_arr.append(um_port) data_arr.append(val) @@ -158,7 +158,9 @@ class PRD: var state = PrdState.WORK var cmd_array: Array ## Очередь команд var ug_online: bool = false ## Состояние ячейки УГ + var serviceability: bool = false var set_ug_state: bool = true ## Необходимо ли записать в УГ настройки + signal update_serviceability() func _init(u_name, u_yau07): prd_name = u_name @@ -185,6 +187,7 @@ class PRD: unit_yau07.connect('command_done', Callable(self, 'on_command_done')) unit_yau07.connect('line_changed', Callable(self, 'on_line_changed')) + func on_command_done(u): if yemsg_board.state_board != yemsg_board.WAIT or yemsg_board.state_cmd != yemsg_board.WAIT: yemsg_board.on_command_done(u) @@ -196,6 +199,7 @@ class PRD: func on_line_changed(unit_ems): + emit_signal('update_serviceability') if not unit_ems.online: yemsg_board.ems_load = yemsg_board.LoadState.NOT_DEFINED yemsg_board.set_wait() @@ -222,9 +226,18 @@ class PRD: ug_online = (unit_yau07.status[0] >> 1) & 1 if not ug_online: set_ug_state = true + var ukp_1_online = (unit_yau07.status[0] >> 2) & 1 + var ukp_2_online = (unit_yau07.status[0] >> 3) & 1 + var ems_g_online = (unit_yau07.status[0] & 1) & 1 + var check_serviceability = ug_online and ukp_1_online and ukp_2_online and ems_g_online + if serviceability != check_serviceability: + serviceability = check_serviceability + emit_signal('update_serviceability') + func execute_cmd(): if not len(cmd_array): return + if unit_yau07.cmd_state != unit_yau07.CmdState.DONE: return var cmd: Array = cmd_array.pop_front() unit_yau07.send_isa(cmd[0], cmd[1]) @@ -283,6 +296,8 @@ func _ready() -> void: unit_caps.connect('data_received', Callable(self, 'on_data_capsrpb_received')) signaller.connect('режим_контроль', Callable(self, 'on_mode_changed').bind(PrdState.CONTROL)) signaller.connect('режим_работа', Callable(self, 'on_mode_changed').bind(PrdState.WORK)) + var unit_nav = network.get_unit_instance('навигация') + unit_nav.connect('data_received', on_navi_data_received) func get_fs_param(index: int) -> Array: @@ -318,7 +333,7 @@ func find_fs_index(aoa: float, freq: int, fs_index_arr: Array): ## Обновление состояния модулей формирователя сигналов -func update_fs_state(ecms): +func update_fs_state(ecms, trenaz_mode: bool): for fs in fs_dict.values(): ## Запрет модуляции для всех ФС fs.set_modulation(false) for ecm in ecms.values(): ## Выставление состояния помехи в ФС @@ -330,7 +345,8 @@ func update_fs_state(ecms): for prd_module in prd_dict.values(): ## Отправка команды на исполнение в ПРД if prd_module.state != PrdState.WORK: continue if not prd_module.unit_yau07.online: continue - prd_module.cmd_array.append([prd_module.unit_yau07.CmdCode.WRITE_ISA, [prd_module.yemsg_board.base_addr_isa, 6666]]) + if not trenaz_mode: + prd_module.cmd_array.append([prd_module.unit_yau07.CmdCode.WRITE_ISA, [prd_module.yemsg_board.base_addr_isa, 6666]]) var um_data_array: Array = [] for fs in prd_module.fs_dic.values(): if not prd_module.ug_online: continue @@ -386,3 +402,7 @@ func on_data_capsrpb_received(unit0: capsrpb.CapsRpb): func on_mode_changed(changed_mode: int) -> void: for pdr in prd.prd_dict.values(): pdr.state = changed_mode + + +func on_navi_data_received(data: Dictionary): + course = data.get('k', 0.0) diff --git a/scripts/pribor-prd.gd b/scripts/pribor-prd.gd index 27c8a651..c717f50b 100644 --- a/scripts/pribor-prd.gd +++ b/scripts/pribor-prd.gd @@ -5,6 +5,20 @@ class TestPRD extends Node: const RAY_25:= 'RAY_25' const RAY_35:= 'RAY_35' const RAY_45:= 'RAY_45' + enum DataIndices { + STATUS_BOARD = 0, + IN_BLANK_PRD = 1, + IN_IMPULS_PRD = 7, + OUT_BLANK_PRD = 13, + OUT_IMPULS_PRD = 19, + DRY_CONTACT = 27, + DKM = 28, + POWER_UKP_1 = 31, + TEMPERATURE_UKP_1 = 47, + POWER_UKP_2 = 63, + TEMPERATURE_UKP_2 = 79, + } + enum STATE_MASHINE { INIT, FS_TURN_ON, @@ -60,7 +74,10 @@ class TestPRD extends Node: var self_name: String var state: int = STATE_MASHINE.INIT var current_litera: int - var flag_timer_started: bool = false + var flag_write_isa: bool = false + var flag_fs_status_ok: bool = false + var flag_si_fs_input: bool = false + var flag_si_fs_output: bool = false var unit_prd: Object var module_prd: Object var power_amplify: Array @@ -105,6 +122,7 @@ class TestPRD extends Node: block_kasseta_y5_config = check_block_kasseta_y5(status, block_kasseta_y5_config) block_ip_config = check_block_ip(status, block_ip_config) control_results.temperature = check_temperature_um(status, power_amplify) + socket_status_ems_g(status) _process_dkm_status(status) if current_litera != 0: var tek_litera: Dictionary = power_result[current_litera] @@ -114,6 +132,21 @@ class TestPRD extends Node: power_result[current_litera] = tek_litera + func socket_status_ems_g(packet_form_yau_07: PackedByteArray) -> void: + var number_socket_input: int + if current_litera >= 1 and current_litera <= 7: + number_socket_input = current_litera + 7 + + var in_blank: int = packet_form_yau_07.decode_u16(DataIndices.IN_BLANK_PRD) + flag_si_fs_input = (in_blank & (1 << number_socket_input)) != 0 ## Флаг СИ от ФС входа в ЭМС-Г для текущей литеры + + var number_socket_output: int + number_socket_output = 4 if current_litera in [2, 4, 6] else 3 if current_litera == 1 else 5 + + var out_blank: int = packet_form_yau_07.decode_u16(DataIndices.OUT_BLANK_PRD) + flag_si_fs_output = (out_blank & (1 << number_socket_output)) != 0 ## Флаг Модуляции УМ ЭМС-Г для текущей литеры + + ## Пакеты от MP550Service func on_fs_update_state(packet_type_7: Dictionary, fs_mapping: Dictionary) -> void: var fs_key: String = FS_KEYS.get(current_litera, '') @@ -123,6 +156,7 @@ class TestPRD extends Node: var fs_result := {fs_key: 0} fs_result = on_fs_state(packet_type_7, fs_mapping, fs_result) control_results[fs_key] = fs_result[fs_key] + flag_fs_status_ok = control_results[fs_key] == 1 ## @@ -134,24 +168,26 @@ class TestPRD extends Node: _handle_fs_turn_on_state() state = STATE_MASHINE.FS_WORK STATE_MASHINE.FS_WORK: - if ecms.size(): + if ecms.size() and flag_fs_status_ok: + ems_6666_timer.start() _handle_fs_work_state() STATE_MASHINE.CHEK_KASSETA_Y5: if block_kasseta_y5_config['yau07']: state = STATE_MASHINE.WRITE_ISA STATE_MASHINE.WRITE_ISA: - _handle_ug_set_state(0x6) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x6) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.READ_ISA: if (unit_prd.cmd_state == unit_prd.CmdState.DONE) or (unit_prd.cmd_state == unit_prd.CmdState.FAIL): _handle_read_isa(module_prd, unit_prd, [constants.ADDR_UG_LITERA_1, constants.ADDR_UG_LITERA_2, constants.ADDR_UG_LITERA_3]) + flag_write_isa = false state = STATE_MASHINE.UG_SET_RAY STATE_MASHINE.UG_SET_RAY: var addr: int = constants.ADDR_UG_LITERA_1 if current_litera == 3 or current_litera == 5 or current_litera == 7: addr = constants.ADDR_UG_LITERA_2 if unit_prd.isa_ports.has(addr) and (unit_prd.cmd_state == unit_prd.CmdState.DONE): - control_timer.stop() if unit_prd.isa_ports[addr] & 0x07 == 0: state = STATE_MASHINE.UG_SET_RAY_1 elif unit_prd.isa_ports[addr] & 0x07 == 1: @@ -170,28 +206,36 @@ class TestPRD extends Node: state = STATE_MASHINE.UG_SET_RAY_0 STATE_MASHINE.UG_SET_RAY_0: - _handle_ug_set_state(0x0) - await get_tree().create_timer(1.0).timeout - state = STATE_MASHINE.READ_ISA + if flag_si_fs_input and not flag_write_isa: + control_timer.stop() + _handle_ug_set_state(0x0) + await get_tree().create_timer(0.5).timeout + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_1: - _handle_ug_set_state(0x1) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x1) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_2: - _handle_ug_set_state(0x2) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x2) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_3: - _handle_ug_set_state(0x3) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x3) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_4: - _handle_ug_set_state(0x4) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x4) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.UG_SET_RAY_5: - _handle_ug_set_state(0x5) - state = STATE_MASHINE.READ_ISA + if not flag_write_isa: + _handle_ug_set_state(0x5) + state = STATE_MASHINE.READ_ISA STATE_MASHINE.IN_EMS_STOP: ems_6666_timer.stop() state = STATE_MASHINE.FS_TURN_OFF STATE_MASHINE.FS_TURN_OFF: + ems_6666_timer.stop() _handle_fs_turn_off_state() state = STATE_MASHINE.STOP_CONTROL STATE_MASHINE.STOP_CONTROL: @@ -248,28 +292,27 @@ class TestPRD extends Node: elif self_name == '1н' or self_name == '2н' or self_name == '3н' or self_name == '4н': dic_att['ATT_UM_1'] = constants.ATT_UM_2 dic_att['ATT_UM_2'] = constants.ATT_UM_3 - control_label.text = 'Выполняется настройка угла (%s) и атт (%s, %s, %s)' % [ + + var log_text = dic_att.ATT_UM_3 if current_litera == 1 else dic_att.ATT_UM_1 if current_litera in [2, 4, 6] else dic_att.ATT_UM_2 + control_label.text = 'Выполняется настройка угла (%s) и атт (0x0%s)' % [ dic_att.RAY_DOU_NUM, - dic_att.ATT_UM_1, - dic_att.ATT_UM_2, - dic_att.ATT_UM_3, + log_text ] - on_ug_setting(module_prd, unit_prd, dic_att) + flag_write_isa = on_ug_setting(module_prd, unit_prd, dic_att) func _on_ems_6666_timer() -> void: - print_debug('Write 6666') module_prd.cmd_array.append([unit_prd.CmdCode.WRITE_ISA, [constants.BASE_ADDR_EMS_G, 6666]]) func _handle_fs_turn_off_state() -> void: control_label.text = 'Выполняется отключение ФС-%s' % current_litera + flag_fs_status_ok = false manage_fs(false, self_name, pribor_config, fs_parameters, current_litera, constants.POWER_UM) func _handle_stop_control_state() -> void: control_label.text = 'Выполняется завершение проверки ФС-%s' % current_litera - flag_timer_started = false _advance_to_next_fs() state = STATE_MASHINE.INIT @@ -313,7 +356,7 @@ class TestPRD extends Node: add_child(ems_6666_timer) ems_6666_timer.timeout.connect(_on_ems_6666_timer) - ems_6666_timer.wait_time = 1.5 + ems_6666_timer.wait_time = 1.0 func _process_dkm_status(status: PackedByteArray) -> void: @@ -322,7 +365,15 @@ class TestPRD extends Node: var dkm_bit = _get_dkm_bit_for_current_fs(current_litera, constants) if dkm_bit == 0: control_results['dkm_1'] = check_dkm(status, dkm_bit) - elif dkm_bit == 1: + + var addr: int = constants.ADDR_UG_LITERA_1 + if current_litera == 3 or current_litera == 5 or current_litera == 7: + addr = constants.ADDR_UG_LITERA_2 + if not unit_prd.isa_ports.has(addr) or not (unit_prd.cmd_state == unit_prd.CmdState.DONE): + return + if not unit_prd.isa_ports[addr] & 0x07 == 6: return + + if dkm_bit == 1: control_results['dkm_2'] = check_dkm(status, dkm_bit) elif dkm_bit == 2: control_results['dkm_3'] = check_dkm(status, dkm_bit) @@ -379,16 +430,15 @@ class TestPRD extends Node: ## Установка угла и аттенюации для УМ - static func on_ug_setting(prd_module: Object, prd_unit: Object, settings_ug: Dictionary) -> void: + static func on_ug_setting(prd_module: Object, prd_unit: Object, settings_ug: Dictionary) -> bool: var result_1 = ((settings_ug.ATT_UM_1 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07) var result_2 = ((settings_ug.ATT_UM_2 & 0x07) << 3) | (settings_ug.RAY_DOU_NUM & 0x07) - - prd_module.cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [ settings_ug.BASE_EMS_G, 6666, - settings_ug.ADDR_UG_LITERA_1, result_1, + prd_module.cmd_array.append([prd_unit.CmdCode.WRITE_ISA, [ settings_ug.ADDR_UG_LITERA_1, result_1, settings_ug.ADDR_UG_LITERA_2, result_2, settings_ug.ADDR_UG_LITERA_3, settings_ug.ATT_UM_3, ] ]) + return true static func _handle_read_isa(prd_module: Object, prd_unit: Object, read_isa_ports: Array) -> void: @@ -414,6 +464,7 @@ class TestPRD extends Node: params.width, sectors[litera - 1] if litera == 1 else sectors[litera - 5] if litera > 5 else sectors[litera - 4] if litera > 3 else sectors[litera - 2] ]) + signaller.emit_signal('emit_changed', mode) signaller.emit_signal('interfer_init', interfer_name, fs_arr, power_um) @@ -635,7 +686,6 @@ class TestPRD extends Node: for i_pow_arr in ray_dic.values(): for i_pow in i_pow_arr.size(): if i_pow_arr[i_pow] < cnst.POWER_THRESHOLD: - #print_debug('dou_%s: false' % litera) all_dou_ok = false control_dic[dou] = all_dou_ok diff --git a/scripts/settings.gd b/scripts/settings.gd index 8d716db2..28069108 100644 --- a/scripts/settings.gd +++ b/scripts/settings.gd @@ -9,8 +9,8 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ # < Название: Протокол, Адрес, <Порт>|[, Порт], Широковещательное, Привязывать, Комментарий > 'уарэп-яу07-частный': ['yau07rx', ['10.1.1.2', 50002, false, true], 'IP-адрес для приёма частных сообщений от ЯУ-07'], 'уарэп-яу07-общий': ['yau07rx', ['*', 50000, true, true], 'IP-адрес для приёма широковещательных сообщений от ЯУ-07'], - 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], - 'уарэп-трасса': ['trassa', ['127.0.0.1', 50200, 10004, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], + 'уарэп-капсрпб': ['capsrpb', ['127.0.0.1', '127.0.0.1', 42023, 42022, false, true], 'IP-адрес для обмена сообщениями со службой \"МП550\" (СТЦ)'], + 'уарэп-трасса': ['trassa', ['192.168.1.23', '192.168.1.34', 50200, 10004, false, true], 'IP-адрес для обмена сообщениями с \"Трассой\"'], 'уарэп-эмс': ['yau07tx', ['10.1.1.52', 50052, false, false], 'IP-адрес прибора УФ'], 'уарэп-яу07-2в': ['yau07tx', ['10.1.1.22', 50022, false, false], 'IP-адрес прибора ПРД-В2'], 'уарэп-яу07-2н': ['yau07tx', ['10.1.1.21', 50021, false, false], 'IP-адрес прибора ПРД-Н2'], @@ -35,6 +35,11 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ # < Название: Протокол, < Имя порта, Адрес СПТ-25, Скорость, Чётность, Бит на символ, Стоп битов >, Комментарий > 'уарэп-спт25-1': ['spt25', ['/dev/ttyUSB1', 0, 19200, 'N', 8, 1], 'Прибор СПТ-25 (G1)'], 'уарэп-спт25-2': ['spt25', ['/dev/ttyUSB2', 0, 19200, 'N', 8, 1], 'Прибор СПТ-25 (G2)'], + 'уарэп-афсп-левый': [null, [], 'Прибор АФСП левого борта'], + 'уарэп-афсп-правый': [null, [], 'Прибор АФСП правого борта'], + 'уарэп-бпо-1': [null, [], 'Прибор БПО 1'], + 'уарэп-бпо-2': [null, [], 'Прибор БПО 2'], + 'уарэп-карта': [null, [], 'Сервер карты'], } ## Параметры цели. @@ -45,7 +50,7 @@ var UnitProfiles: Dictionary[StringName, Array] = { \ const FREQ_MAX: = 6000.0 const FREQ_MIN: = 400.0 -const WIDTH_MAX: = 100.0 +const WIDTH_MAX: = 120.0 const WIDTH_MIN: = 0.0 const DUR_MAX: = 1000000.0 const PERIOD_MAX: = 1000000.0 @@ -74,7 +79,7 @@ func _ready() -> void: log.warning('Будут использованы настройики по умолчанию.') return var json_data = json_conv.get_data() - settings_program.merge(json_data) + settings_program.merge(json_data, true) for key in settings_program: ProjectSettings.set_setting('application/config/%s' % key, settings_program[key]) for key: StringName in UnitProfiles.keys(): diff --git a/scripts/signaller.gd b/scripts/signaller.gd index 9e2a7c34..8a4ca5cc 100644 --- a/scripts/signaller.gd +++ b/scripts/signaller.gd @@ -34,6 +34,10 @@ signal режим_эмс() ## Вызывается при переходе в режим [b]Настройка[/b]. signal режим_настройки() +## Вызывается при включении/отключении режима [b]Тренаж[/b].[br] +## [param val] - [b]true[/b] тренаж включён. +signal режим_тренаж(val: bool) + ## Вызывается, когда оператор переводит программу в режим [b]Автомат выбора цели и помехи[/b]. signal full_auto() @@ -189,3 +193,11 @@ signal update_scale_map(new_scale) ## Вызывается при изменении текущих координат.[br] ## [param new_coordinates] - обновленное значение координат ([b]true[/b] signal update_coordinates_map(new_coordinates) + + +## Вызывается при изменении исправности прибора УФ.[br] +## [param uf_serviceaability] - обновленное значение состояния исправности ([b]true[/b] +signal update_uf_serviceability(uf_serviceaability: bool) + + +signal tool_tip(new_ctrl_pos) diff --git a/scripts/spt25.gd b/scripts/spt25.gd index 5e826f29..9bc9f601 100644 --- a/scripts/spt25.gd +++ b/scripts/spt25.gd @@ -13,40 +13,11 @@ class SPT25 extends unit.Unit: func _to_string() -> String: return String('СПТ-25 %s %s' % [self.name, ['отключен', 'на связи'][int(online)]]) - ##Вычисление контрольной суммы - func sciCalcFCS(src: PackedByteArray) -> int: - var P_DIV = 0 - var ln = src[0] - var FCS = ~((src[2]<<8) + src[1]) - for i in range(3, ln): - var C = src[i] - for j in 8: - if C & 1: - if FCS & 1: - FCS = ((FCS >> 1) | 0x8000)^P_DIV - else: - FCS = ((FCS >> 1) | 0x8000) - else: - if FCS & 1: - FCS = (FCS >> 1) ^ P_DIV - else: - FCS = FCS >> 1 - C >>= 1 - for j in 16: - if FCS & 1: - FCS = (FCS >> 1) ^ P_DIV - else: - FCS = FCS >> 1 - return ~FCS - - func _init(nm) -> void: - self.name = nm - tx_data.resize(5) - tx_data[0] = 0 # Адрес абонента, которому предназначен пакет - tx_data[1] = CmdCode.INFO # Тип пакета, КОД КОМАНДЫ - Получить информацию о состоянии преобразователя - tx_data[2] = 0 # Данные - tx_data[3] = 0 # Данные - tx_data[4] = 0 # Данные + func _init(unit_name) -> void: + self.name = unit_name + tx_data.resize(2) + tx_data[0] = 0 # Адрес абонента, которому предназначен пакет + tx_data[1] = CmdCode.INFO # Тип пакета, КОД КОМАНДЫ - Получить информацию о состоянии преобразователя func parse(rx_data: PackedByteArray, tick: int): diff --git a/scripts/threats.gd b/scripts/threats.gd index 11775bcd..83de85c5 100644 --- a/scripts/threats.gd +++ b/scripts/threats.gd @@ -45,13 +45,13 @@ signal threats_resized(th: Dictionary) func _ready() -> void: - var threats = {} ## Список целей. Индекс - <номер цели> var unit_caps = network.get_unit_instance('уарэп-капсрпб') var unit_5p28 = network.get_unit_instance('уарэп-5п28') var timer_check_lost: = Timer.new() var timer_aoa_update: = Timer.new() add_child(timer_check_lost) add_child(timer_aoa_update) + var threats = {} ## Список целей. Индекс - <номер цели> unit_caps.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(settings.ThreatParams.time_lost, threats)) @@ -69,7 +69,7 @@ func _ready() -> void: ## Периодически удаляет устаревшие цели. func on_timer_check_lost(time_lost: int, threats: Dictionary): - var tick = Time.get_ticks_msec() + var tick: = Time.get_ticks_msec() var sz: = threats.size() for th in threats.values(): if (tick - th.tick_rx) >= time_lost: @@ -84,7 +84,7 @@ func on_timer_aoa_update(threats:Dictionary, tmr): tmr.start(1.0) ## отправляет словарь целей в юнит, для запаковки и отправки в 5П28. -func on_get_threats(unit, threats): unit.pack_threats(threats) +func on_get_threats(unit_instance, threats): unit_instance.pack_threats(threats) ## Снимает выделение с цели, если нажать по отметке цели. func on_rto_threat_unsel(th_id, threats): threats[th_id].selected = false @@ -115,7 +115,7 @@ func on_interfer_init(interfer_name, fs_arr, power, threats): sel_threats.append(threat) if threat.auto_selected: sel_threats.append(threat) - if len(sel_threats) or (len(fs_arr)): + if len(sel_threats) or len(fs_arr): signaller.emit_signal('interfer_create', interfer_name, sel_threats, fs_arr, power) @@ -128,20 +128,22 @@ func on_data_capsrpb_received(unit: capsrpb.CapsRpb, threats: Dictionary): 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 dic_th is not Dictionary: + continue + if not dic_th.has('id'): + continue + 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) diff --git a/scripts/tools.gd b/scripts/tools.gd index 6b061c6a..de9232ca 100644 --- a/scripts/tools.gd +++ b/scripts/tools.gd @@ -9,7 +9,7 @@ func round_to(v: float, a: float) -> float: return snappedf(v, -a if v < 0 else ## Возвращает [b]true[/b], если [param val] число, [b]false[/b] - если иначе. -func type_is_num(val) -> bool: return (typeof(val) == TYPE_INT) or (typeof(val) == TYPE_FLOAT) +func type_is_num(val) -> bool: return (val is int) or (val is float) ## Возвращает значение в радианах для угла в градусах [param val]. @@ -33,7 +33,7 @@ func is_overlap(x1, x2, y1, y2) -> bool: return max(x1, y1) <= min(x2, y2) ## [param msg] - сообщение об ошибке func allways(val: bool, msg: String = '<не указано>'): if val: return - push_error('ошибка: %s\n' % msg) + push_error('%s\n' % msg) get_tree().quit(Error.FAILED) diff --git a/scripts/trassa.gd b/scripts/trassa.gd index b207aa69..fafcff6a 100644 --- a/scripts/trassa.gd +++ b/scripts/trassa.gd @@ -1,5 +1,4 @@ -class_name trassa_unit -extends Node +class_name trassa_unit extends Node const ONLINE_TIMEOUT: int = 5000 # Время ожидания данных const REQUEST_PERIOD: int = 3000 # Период отправки, мс @@ -7,24 +6,23 @@ const WORDS_TOTAL: int = 75 const NOINFO: int = 0x80000000 class Trassa extends unit.Unit: - + var source_addr: = [] var unit_caps = network.get_unit_instance('уарэп-капсрпб') - var source_addr: Array var tx_stack: Array[int] = [] var msg_counter: int = 0 var ecms: Dictionary = {} # Словарь всех активных помех - var srn = 0 + var srn = 0 var jtids = 0 var prinud_but: Array = [] var forced_buttons: Array = [] # Храним ссылки на кнопки - + # Инициализация func _init(nm: StringName, buttons: Array = []) -> void: self.name = nm - self.forced_buttons = buttons + self.forced_buttons = buttons tx_stack.resize(WORDS_TOTAL) tx_stack.fill(NOINFO) - interfer.connect("interfer_resized", Callable(self, "on_interfer_resized")) + interfer.connect('interfer_resized', Callable(self, 'on_interfer_resized')) # Обработка полученного пакета @@ -32,7 +30,7 @@ class Trassa extends unit.Unit: rx_tick = tick if not online: online = true - emit_signal("line_changed", self) + emit_signal('line_changed', self) var words: Array[int] = [] var offset: int = 0 while offset < rx_data.size(): @@ -85,7 +83,7 @@ class Trassa extends unit.Unit: func process(now_tick: int) -> int: if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT): online = false - emit_signal("line_changed", self) + emit_signal('line_changed', self) if (now_tick - tx_tick) > REQUEST_PERIOD: tx_tick = now_tick msg_counter += 1 @@ -119,15 +117,15 @@ class Trassa extends unit.Unit: tx_stack[65] = 0 tx_stack[66] = 0 for ecm in ecms.values(): - if ecm.krp == "srni1" and ecm.svk == 1: + if ecm.krp == 'srni' and ecm.svk == 1: tx_stack[65] = 1 - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: tx_stack[66] = 1 tx_stack[1] = msg_counter # Обработка указаний от Трассы по кнопке - func btn_trassa_pressed() -> void: + func btn_trassa_pressed() -> void: var state = ProjectSettings.get_setting('application/config/Внешнее указание Трасса', false) if state == true: var tree: SceneTree = Engine.get_main_loop() @@ -154,12 +152,12 @@ class Trassa extends unit.Unit: else: tx_stack[66] = 0 for ecm in ecms.values(): - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: ecm.krp = interfer.INTERFER_OFF interfer.send_ecm(ecm, unit_caps) signaller.emit_signal('interfer_off', ecm) for ecm in ecms.values(): - if ecm.krp == "svi1" and ecm.svk == 1: + if ecm.krp == 'svi1' and ecm.svk == 1: ecm.krp = interfer.INTERFER_OFF interfer.send_ecm(ecm, unit_caps) signaller.emit_signal('interfer_off', ecm) diff --git a/settings.json b/settings.json index f3eee9db..427f4455 100644 --- a/settings.json +++ b/settings.json @@ -1,9 +1,10 @@ { "Адрес АФСП левого борта": "http://172.22.246.13:8081/selftest", "Адрес АФСП правого борта": "http://172.22.246.11:8082/selftest", - "Адрес БПО левого борта": "http://172.22.246.13:8081/selftest", - "Адрес БПО правого борта": "http://172.22.246.11:8082/selftest", + "Адрес БПО левого борта": "http://172.22.246.13:8081/selftest?presetType=bpo&400000000", + "Адрес БПО правого борта": "http://172.22.246.11:8082/selftest?presetType=bpo&400000000", "Виртуальная клавиатура": false, + "Внешнее указание Трасса": false, "Внешнее управление": false, "Кнопка «JTIDS»": false, "Кнопка «К1»": false, @@ -22,28 +23,32 @@ "Кнопка «СВ-И1»": false, "Кнопка «СВ-М2»": false, "Ограниченный режим": false, + "Период опроса состояния АФСП, секунды": "30", + "Период опроса состояния БПО, секунды": "30", "Скрыть вкладку ЭМС 2": true, - "Текущая версия ПО УАРЭП": "HEAD 48353cc Fri Sep 5 14:44:15 2025 +0300", - "Шаблон адреса сервера карт": "http://169.254.27.71:8001/osm_tiles/{z}/{x}/{y}.png", + "Текущая версия ПО УАРЭП": "master b2633d8 Thu Sep 11 16:26:39 2025 +0300", + "Шаблон адреса сервера карт": "http://10.1.1.2:8001/osm_tiles/{z}/{x}/{y}.png", "навигация": [ "*", 60000, true, true ], + "уареп-трасса": "127.0.0.1,127.0.0.1,50200,10004", "уарэп-5п28": [ "127.0.0.1", - 50000 + 50777 ], "уарэп-капсрпб": [ - "127.0.0.1", + "192.168.11.102", + "192.168.11.105", 42023, 42022, false, true ], "уарэп-спт25-1": [ - "/dev/ttyUSB1", + "/home/user/tty0", 0, 19200, "N", @@ -51,7 +56,7 @@ 1 ], "уарэп-спт25-2": [ - "/dev/ttyUSB2", + "/home/user/tty1", 0, 19200, "N", @@ -59,7 +64,7 @@ 1 ], "уарэп-щ3": [ - "/dev/ttyUSB0", + "/home/user/tty3", 7, 19200, "N", @@ -152,8 +157,8 @@ true ], "уарэп-яу07-частный": [ - "10.1.1.2", - 50002, + "10.1.1.253", + 50253, false, true ] diff --git a/shaders/antenas.tres b/shaders/antenas.tres index 87248d14..2c689e09 100644 --- a/shaders/antenas.tres +++ b/shaders/antenas.tres @@ -1,4 +1,4 @@ -[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://s6xe8igevnv2"] +[gd_resource type="ShaderMaterial" load_steps=2 format=4 uid="uid://s6xe8igevnv2"] [sub_resource type="Shader" id="1"] code = "shader_type canvas_item; @@ -15,6 +15,7 @@ uniform vec4 color1: source_color = vec4(0.39, 0.44, 0.50, 0.4); uniform float radius_inner_0 = RADIUS_INNER_0; uniform float radius_inner_1 = RADIUS_INNER_1; uniform float radius_outter = 550.0; /* Радиус внешний. Должно быть равно ant_band_r1_6 */ +uniform float alpha: hint_range(0.0, 1.0) = 0.5; uniform int mode = 0; /* Режим отображения. Приоритет РТО - 0, приоритет РЛС - 1 */ const int ant_band_count_0 = 2; @@ -41,8 +42,7 @@ const float ant_band_r1_4[] = {450.0, 530.0}; const float ant_band_r1_5[] = {500.0, 540.0}; const float ant_band_r1_6[] = {550.0, 550.0}; -uniform vec3 ant_band_c[28]; - +uniform vec4 ant_band_c[28]; const float d4 = 90.0; const float ds = 1.0; @@ -76,21 +76,19 @@ void antenas(inout vec4 c, vec2 uv, vec2 p0, int cnt, float r0, float r1, inout index--; j = index - 3; } - col.x = ant_band_c[j].x; - col.y = ant_band_c[j].y; - col.z = ant_band_c[j].z; + col.rgb = ant_band_c[j].rgb; index++; - col.a = 0.5; - float v = float(i & 1); - vec4 color = v * col + (1.0f - v) * col; - sector(c, uv, p0, float(i) * da, da, r0, r1, color); - } + col.a = alpha + (random_timed(uv) - 0.5f) * ant_band_c[j].a; + float v = float(i & 1); + vec4 color = v * col + (1.0f - v) * col; + sector(c, uv, p0, float(i) * da, da, r0, r1, color); + } } void vertex() { - rotate_vec2(VERTEX, radians(rotation), pc0); + rotate_vec2(VERTEX, radians(360.0 - rotation), pc0); } @@ -98,7 +96,7 @@ void fragment() { ivec2 isz = textureSize(TEXTURE, 0); vec2 uv = UV * vec2(float(isz.x), float(isz.y)); // координаты текущей точки в пикселях - COLOR = vec4(0, 0, 0, 0); //texture(TEXTURE, UV); // Цвет текущей точки + COLOR = vec4(0, 0, 0, 0); int index = 0; // Сетка антенн antenas(COLOR, uv, pc0, ant_band_count_0, ant_band_r0_0[mode], ant_band_r1_0[mode], index); @@ -120,5 +118,6 @@ shader_parameter/color1 = Color(0.3315, 0.45645, 0.51, 0.537255) shader_parameter/radius_inner_0 = 200.0 shader_parameter/radius_inner_1 = 480.0 shader_parameter/radius_outter = 550.0 +shader_parameter/alpha = 0.5 shader_parameter/mode = 0 -shader_parameter/ant_band_c = PackedVector3Array(0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5, 0.38, 0.47, 0.51, 0.39, 0.44, 0.5) +shader_parameter/ant_band_c = PackedVector4Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) diff --git a/shaders/sector.gdshader b/shaders/sector.gdshader index 1fd8d166..d73ad643 100644 --- a/shaders/sector.gdshader +++ b/shaders/sector.gdshader @@ -4,18 +4,18 @@ shader_type canvas_item; /* Закрашенный сектор окружности ограниченный угловым сектором и радиусами */ -uniform vec4 color: source_color = vec4(1, 1, 1, 1); -uniform vec4 clip_color: source_color = vec4(1.0, 0.5, 0.5, 1.0); -uniform float width: hint_range(0.0, 360.0, 0.1) = 45.0; -uniform float band: hint_range(0.0, 0.125) = 0.02; -uniform float radius: hint_range(0.0, 0.125) = 0.08; -uniform float dir: hint_range(0.0, 360.0) = 0.0; -uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; +instance uniform vec4 color: source_color = vec4(1, 1, 1, 1); +instance uniform vec4 clip_color: source_color = vec4(1.0, 0.5, 0.5, 1.0); +instance uniform float width: hint_range(0.0, 360.0, 0.1) = 45.0; +instance uniform float band: hint_range(0.0, 0.125) = 0.02; +instance uniform float radius: hint_range(0.0, 0.125) = 0.08; +instance uniform float dir: hint_range(0.0, 360.0) = 0.0; +instance uniform float inner_clip: hint_range(0.0, 0.125) = 0.045; const vec2 center = vec2(0.125, 0.125); /* Центр. Должен быть в (0.5, 0.5), но это не так */ -const float dsa = 0.0025; /* Относительное расстояние на котором выполняется сглаживание краёв по радиальным линиям */ -const float dsr = 0.00025; /* Относительное расстояние на котором выполняется сглаживание краёв по круговым линиям */ +const float dsa = 0.003; /* Относительное расстояние на котором выполняется сглаживание краёв по радиальным линиям */ +const float dsr = 0.0003; /* Относительное расстояние на котором выполняется сглаживание краёв по круговым линиям */ vec4 sector(vec4 c, vec2 uv_pos, float r0, float r1, float w) diff --git a/shaders/tools.gdshaderinc b/shaders/tools.gdshaderinc index 8dc0df97..73ba7306 100644 --- a/shaders/tools.gdshaderinc +++ b/shaders/tools.gdshaderinc @@ -1,6 +1,12 @@ const float DS = 0.004; /* Относительное расстояние на котором выполняется сглаживание краёв */ +float random_timed(vec2 uv) +{ + return fract(sin(TIME * dot(uv.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + + float smooth_px(float r, float R, float ds) { return 1.0 - smoothstep(R - ds, R + ds, r); diff --git a/table/table.gd b/table/table.gd index 3a623609..f1706f3d 100644 --- a/table/table.gd +++ b/table/table.gd @@ -324,9 +324,12 @@ func _set_row_selected(i_row: int, selected: bool = true) -> void: if nodes.has(selector_key) and (not selected): var node = nodes[node_key] var selector = nodes[selector_key] - node.remove_child(selector) - selector.queue_free() nodes.erase(selector_key) + if is_instance_valid(selector): + node.remove_child(selector) + selector.queue_free() + else: + push_warning('обращение к удалённому элементу \"%s\"' % selector_key) elif (not nodes.has(selector_key)) and selected: var selector = ScnSelector.instantiate() var rect: = [0, 0, 0, 0]