Merge remote-tracking branch 'sasha/master'

This commit is contained in:
MaD_CaT
2025-05-23 13:59:41 +03:00
11 changed files with 246 additions and 192 deletions

View File

@@ -1,8 +1,9 @@
# Ссылки на составные части
- [Собранные исполняемые файлы для шаблонов экспорта и редактора](https://gitea.srez.local:3000/sasha80/godot-bin)
- [Исполняемые файлы для шаблонов экспорта и редактора](https://gitea.srez.local:3000/sasha80/godot-bin)
- [Проброс последовательных портов через Ethernet](http://gitea.srez.local:3000/sasha80/uart-forwarder)
- [Сборка Godot из исходников](http://gitea.srez.local:3000/sasha80/godot-build)
- [Сервер карт](http://gitea.srez.local:3000/sasha80/map-tiles)
# Ссылки на имитаторы
@@ -24,7 +25,7 @@
приходящих на соответствующий порт. Скрипт `ip-tables-navigation.sh` выполняет
необходимые для этого настройки.
- Для доступа к последовательным портам расположенным на другом вычислительном модуле,
следует использовать [проброс портов](http://gitea.srez.local:3000/sasha80/uart-forwarder).
следует использовать [проброс портов](http://gitea.srez.local:3000/sasha80/uart-forwarder).
# Разработка

View File

@@ -24,7 +24,6 @@ config/map_bcs=Vector3(0.5, 1.5, 0.3)
config/map_tile_size=256
config/map_minimum_zoom=5
config/map_maximum_zoom=19
config/map_server_addr="https://b.tile.openstreetmap.org"
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)

View File

@@ -17,9 +17,10 @@ class_name MercatorTileMap
@export var tile_width: float = 256.0
@export var tile_height: float = 256.0
@export_range(1, 1000, 1) var max_concurrent_requests:int = 5
@export_range(100, 100000, 1) var max_cached_tiles: int = 200
@export_range(0, 25, 1) var max_zoom_level: int = 19
@export_range(0, 25, 1) var min_zoom_level: int = 0
@export_range(100, 100000, 1) var max_cached_tiles: int = 1024
@export_range(0, 20, 1) var max_zoom_level: int = 20
@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
const default_size: = 400.0
var is_centered: = false
@@ -104,7 +105,13 @@ const image_load_proc_names = {
set(v): image_load_proc = Callable(image, image_load_proc_names[v])
func _ready():
func on_map_centered(toggle_centered: bool): is_centered = toggle_centered
func get_marks_count(): return _marks.size()
func _ready() -> void:
image_type = 'png'
$canvas.connect('mouse_entered', func(): _rollover = true)
$canvas.connect('mouse_exited', func(): _rollover = false)
@@ -116,11 +123,7 @@ func _ready():
unit_nav.connect('data_received', on_data_received)
func on_map_centered(toggle_centered: bool):
is_centered = toggle_centered
func on_data_received(coords: Dictionary):
func on_data_received(coords: Dictionary) -> void:
if not is_centered:
return
if coords.has_all(['latitude', 'longitude']):
@@ -134,7 +137,7 @@ func _on_resize() -> void:
## Создаёт новую отметку из координат экрана
func add_mark_from_screen_pos(id: int, x: float, y: float, mark: Node):
func add_mark_from_screen_pos(id: int, x: float, y: float, mark: Node) -> bool:
if _marks.has(id):
return false
var wrld_pos = screen_to_world(_xyz, x, y)
@@ -147,19 +150,17 @@ func add_mark_from_screen_pos(id: int, x: float, y: float, mark: Node):
return true
func get_marks_count(): return _marks.size()
func delete_mark(id: int):
func delete_mark(id: int) -> bool:
if not _marks.has(id):
return false
_marks[id].mark.queue_free()
_marks.erase(id)
queue_redraw()
return true
## Создаёт новую отметку из долготы и широты
func add_mark_from_lon_lat(id: int, lon: float, lat: float, mark: Node, gap_size: float = 32):
func add_mark_from_lon_lat(id: int, lon: float, lat: float, mark: Node, gap_size: float = 32) -> bool:
if _marks.has(id):
return false
var wrld_pos = lonlat_to_world(lon, lat)
@@ -172,7 +173,7 @@ func add_mark_from_lon_lat(id: int, lon: float, lat: float, mark: Node, gap_size
## Возвращает новую позицию для точки, если она выходит из поля видимости
func fix_mark_position(dot):
func fix_mark_position(dot) -> void:
if is_mark_visible(dot):
return
var v = 2 * tile_width * pow(2, _xyz.z)
@@ -182,12 +183,12 @@ func fix_mark_position(dot):
dot.position.x = _xyz.x + $canvas.size.x / v
func is_mark_visible(dot):
func is_mark_visible(dot) -> bool:
var screen_pos = world_to_screen(dot.position.x, dot.position.y)
return screen_pos.x > 0 and screen_pos.x < $canvas.size.x
func _input(e):
func _input(e) -> void:
var lmp = get_local_mouse_position()
if not _rollover:
return
@@ -222,7 +223,7 @@ func is_border_visible():
return screen_to_tile(0, 0, z).y != 0
func multiply_zoom(multiplier: float, pivot: Vector2):
func multiply_zoom(multiplier: float, pivot: Vector2) -> void:
var p1: = screen_to_world(_xyz, pivot.x, pivot.y)
_xyz.z = clampf(_xyz.z * multiplier, min_zoom_level, max_zoom_level)
var p2: = screen_to_world(_xyz, pivot.x, pivot.y)
@@ -230,7 +231,7 @@ func multiply_zoom(multiplier: float, pivot: Vector2):
_xyz.y -= p2.y - p1.y
func set_zoom(zoom: float, pivot=null):
func set_zoom(zoom: float, pivot=null) -> void:
if pivot == null:
pivot = $canvas.size / 2.0
@@ -241,7 +242,7 @@ func set_zoom(zoom: float, pivot=null):
_xyz.y -= p2.y - p1.y
func _draw():
func _draw() -> void:
var lmp = get_local_mouse_position()
if mouse_wheel_count > 0:
@@ -275,7 +276,7 @@ func _draw():
visible_marks_count += int(dot.mark.visible)
func _clean_all():
func _clean_all() -> void:
_queue.clear()
_cache.clear()
_marks.clear()
@@ -286,7 +287,7 @@ func _clean_all():
# get the tile from queue with the newest timestamp
func get_next_in_queue():
func get_next_in_queue() -> Tile:
var tile = null
for idx in _queue:
var t = _queue.get(idx)
@@ -296,7 +297,7 @@ func get_next_in_queue():
# delete oldest tiles from cache
func _clean_cache():
func _clean_cache() -> void:
var overflow = _cache.size() - max_cached_tiles
if overflow <= 0:
return
@@ -307,7 +308,7 @@ func _clean_cache():
_cache.erase(vals[i].i)
func _process(delta):
func _process(delta) -> void:
now += delta
# if cache is overflowing - clean it
@@ -340,8 +341,7 @@ func _process(delta):
emit_signal('load_completed')
# result, response_code, headers, body
func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile):
func _response(result, code, _headers: Array, body: PackedByteArray, req, tile: Tile) -> void:
_req_count -= 1
remove_child(req)
@@ -401,7 +401,7 @@ func _draw_subtile(tx: int, ty: int, tz: int, origx: int, origy: int, origz: flo
return false
func _draw_tile(tx: int, ty: int, z: float):
func _draw_tile(tx: int, ty: int, z: float) -> void:
var tz = floor(z)
var p1 = tile_to_screen(tx, ty, z)
var p2 = tile_to_screen(tx + 1, ty + 1, z)
@@ -556,10 +556,12 @@ func get_tile(x: int, y: int, z: int, create: bool = true) -> Tile:
var queue_size: = _queue.size()
if create and (not $canvas/player.is_playing()):
tile = Tile.new(idx, x, y, z)
tile.url = base_url.replace('{x}', str(x)).replace('{y}', str(y)).replace('{z}', str(z))
tile.t = now
_queue[idx] = tile
if not tile:
tile = Tile.new(idx, x, y, z)
tile.url = base_url.replace('{x}', str(x)).replace('{y}', str(y)).replace('{z}', str(z))
tile.t = now
if z <= max_zoom_level_server:
_queue[idx] = tile
if queue_size == 0 and _queue.size():
emit_signal('load_started')
@@ -600,8 +602,8 @@ class Tile:
self.y = y0
self.z = z0
func haversine_m(lat1, lon1, lat2, lon2):
# Возвращает расстояние в метрах между двумя точками на карте
func haversine_m(lat1: float, lon1: float, lat2: float, lon2: float) -> float:
# Радиус Земли в метрах
const R: = 6372795.0
# Преобразование градусов в радианы
@@ -624,16 +626,17 @@ func haversine_m(lat1, lon1, lat2, lon2):
return dist
func remove_closest_dot(screen_pos):
func remove_closest_dot(screen_pos: Vector2) -> bool:
var closest_dot = find_at_screen_position(screen_pos)
if not closest_dot:
return
return false
remove_child(closest_dot.mark)
closest_dot.mark.queue_free()
_marks.erase(closest_dot)
return true
func find_at_screen_position(screen_pos: Vector2):
func find_at_screen_position(screen_pos: Vector2) -> Node:
var closest_dot = null
var closest_distance = INF
for mark in _marks.values():
@@ -650,7 +653,7 @@ func clear() -> void:
queue_redraw()
func set_coordinates(lon: float, lat: float):
func set_coordinates(lon: float, lat: float) -> void:
var anim: Animation = $player.get_animation('goto')
var new_pos = lonlat_to_world(lon, lat)
anim.track_insert_key(0, 0, _xyz.x)

View File

@@ -28,7 +28,9 @@ size = Vector2(400, 400)
[node name="tilemap" type="CanvasGroup" groups=["gui_items"]]
script = ExtResource("1_l64tp")
max_zoom_level = 21
base_url = "http://192.168.11.105:8001/osm_tiles/{z}/{x}/{y}.png"
max_zoom_level = 15
max_zoom_level_server = 10
az = 2.0
[node name="canvas" type="TextureRect" parent="." groups=["gui_items"]]

View File

@@ -8,56 +8,57 @@ const ALIGNMENT = [HORIZONTAL_ALIGNMENT_CENTER, HORIZONTAL_ALIGNMENT_CENTER]
const HEADER_ROW = [TableHeader, TableHeader]
const HEADER_ROW_TEXT = ['Параметр', 'Значение']
const SETTING_TABLE = [
['Ограниченный режим', TableEdit, TableToggle],
['Управление элементами в ограниченном режиме', TableEdit, TableToggle],
['Кнопка «ПД-М4»', TableEdit, TableToggle],
['Кнопка «ПД-М2»', TableEdit, TableToggle],
['Кнопка «ОЗП-1»', TableEdit, TableToggle],
['Кнопка «МЧМ-', TableEdit, TableToggle],
['Кнопка «ОРН-И1»', TableEdit, TableToggle],
['Кнопка «ОРН-М2»', TableEdit, TableToggle],
['Кнопка «ЛЧМ-1»', TableEdit, TableToggle],
['Кнопка «ПД-М4С»', TableEdit, TableToggle],
['Кнопка «ПД-ЧМ»', TableEdit, TableToggle],
['Кнопка «СВ', TableEdit, TableToggle],
['Кнопка «К1»', TableEdit, TableToggle],
['Кнопка «СВ-М2»', TableEdit, TableToggle],
['Кнопка «ОРН»', TableEdit, TableToggle],
['Кнопка «JTIDS»', TableEdit, TableToggle],
['Кнопка «КУПД»', TableEdit, TableToggle],
['Внешнее целеуказание', TableEdit, TableToggle],
['Кнопка «Подавление»', TableEdit, TableToggle],
['Виртуальная клавиатура', TableEdit, TableToggle],
['Скрыть вкладку ЭМС 2', TableEdit, TableToggle],
['Текущая версия ПО УАРЭП', TableEdit, TableEdit ],
['Адрес сервера карт', TableEdit, TableEdit ],
['уарэп-яу07-частный', TableEdit, TableEdit ],
['уарэп-яу07-общий', TableEdit, TableEdit ],
['уарэп-капсрпб', TableEdit, TableEdit ],
['уарэп-эмс', TableEdit, TableEdit ],
['уарэп-яу07-2в', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-4в', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-1в', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-', TableEdit, TableEdit ],
['уарэп-яу07-3в', TableEdit, TableEdit ],
['уарэп-яу07-3н', TableEdit, TableEdit ],
['уарэп-яу07-3к', TableEdit, TableEdit ],
['уарэп-5п28', TableEdit, TableEdit ],
['уарэп-щ3', TableEdit, TableEdit ],
['уарэп-спт25-1', TableEdit, TableEdit ],
['уарэп-спт25-2', TableEdit, TableEdit ]
]
const EXTERNAL_CU = 17 # Внешнее целееуказание
const SUPPRESS = 18 # Строка - Подавление
const KEYBOARD = 19 # Строка - Виртуальная клавиатура
const HIDE_EMS2 = 20 # Строка - Скрыть вкладку ЭМС 2
const COMMIT = 21 # Строка - Версия УАРЭП
const SERVER = 22 # Строка - Сервер карт
['Ограниченный режим', TableEdit, TableToggle, 'Ограничть возможности по постановке помех'],
['Кнопка «ПД-М', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-М2»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОЗП-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «МЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН-М2»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ЛЧМ-1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-М4С»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ПД-ЧМ»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «СВ-И1»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «К', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «СВ-М2»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «ОРН»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «JTIDS»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «КУПД»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Внешнее целеуказание', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Кнопка «Подавление»', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Виртуальная клавиатура', TableEdit, TableToggle, 'Разрешить отображение экранной клавиатуры'],
['Скрыть вкладку ЭМС 2', TableEdit, TableToggle, 'Разрешить отображение кнопки'],
['Текущая версия ПО УАРЭП', TableEdit, TableEdit, 'Время сборки, версия и номер фиксации'],
['уарэп-яу07-частный', TableEdit, TableEdit, 'IP-адрес для получения частных сообщений от ЯУ-07'],
['уарэп-яу07-общий', TableEdit, TableEdit, 'IP-адрес для получения широковещательных сообщений от ЯУ-07'],
['уарэп-капсрпб', TableEdit, TableEdit, 'IP-адрес для связи с КАПС-РПБ'],
['уарэп-эмс', TableEdit, TableEdit, 'IP-адрес для связи с ЭМС'],
['уарэп-яу07-2в', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 2'],
['уарэп-яу07-2н', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 2'],
['уарэп-яу07-2к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 2'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 4'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 4'],
['уарэп-яу07-4к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 4'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 1'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 1'],
['уарэп-яу07-1к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 1'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-В 3'],
['уарэп-яу07-', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-Н 3'],
['уарэп-яу07-3к', TableEdit, TableEdit, 'IP-адрес для связи с прибором ПРД-К 3'],
['уарэп-5п28', TableEdit, TableEdit, 'IP-адрес для связи с 5П28'],
['навигация', TableEdit, TableEdit, 'Порт назначения для получения данных от АКНГ'],
['уарэп-щ3', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором Щ3'],
['уарэп-спт25-1', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 1'],
['уарэп-спт25-2', TableEdit, TableEdit, 'Путь к UART-устройству для связи с прибором СПТ-25 2'],
['Шаблон адреса сервера карт', TableEdit, TableEdit, 'URL-адрес сервера карт, содержащий поля \"{x}\", \"{y}\", \"{z}\" для подстановки индекса плитки'] ]
const EXTERNAL_CU = 16 ## Внешнее целееуказание
const SUPPRESS = 17 ## Строка - Подавление
const KEYBOARD = 18 ## Строка - Виртуальная клавиатура
const HIDE_EMS2 = 19 ## Строка - Скрыть вкладку ЭМС 2
const COMMIT = 20 ## Строка - Версия УАРЭП
func on_checkbutton_pressed(i_row: int): on_row_pressed(i_row)
## Вызывается, когда узел впервые попадает в дерево сцены.
@@ -92,8 +93,57 @@ func on_row_pressed(i_row: int):
$scroll_set/table.set_row_selected(i_row, true)
func on_checkbutton_pressed(i_row: int):
on_row_pressed(i_row)
func parse_cmd_line_args(settings_data: Dictionary):
var args = OS.get_cmdline_args()
for i in range(0, args.size(), 2):
var key: String = args[i]
key = key.lstrip('\'\" ').rstrip('\'\" ').strip_edges().strip_escapes()
if not settings_data.has(key):
continue
if not ((i + 1) < args.size()):
push_error('для аргумента \"%s\" не указано значение.' % key)
break
var val0 = args[i + 1]
var val1 = settings_data[key]
val0 = val0.lstrip('\'\" ').rstrip('\'\" ').strip_edges().strip_escapes()
if typeof(val1) == TYPE_BOOL:
if val0 not in ['yes', 'true', 'да', 'no', 'false', 'нет']:
push_error('для аргумента \"%s\" указано неверное значение \"%s\".' % [key, val0])
break
settings_data[key] = true if val0 in ['yes', 'true', 'да'] else false
elif typeof(val1) == TYPE_ARRAY:
var val0s = val0.split(',')
if val0s.size() != val1.size():
push_error('для аргумента \"%s\" указано неверное значение \"%s\" (исходное: \"%s\").' % [key, val0, val1])
break
for j in val0s.size():
var val: String = val0s[j]
val = val.lstrip('\'\" ').rstrip('\'\" ').strip_edges().strip_escapes()
if tools.type_is_num(val):
val0s[j] = int(val)
elif val in ['true', 'false']:
val0s[j] = true if val == 'true' else false
else:
val0s[j] = val
elif typeof(val1) == TYPE_STRING:
settings_data[key] = val0
## Загружает настройки из файла
func load_settings(settings_data: Dictionary):
var settings_file = settings.get_settings_file_path()
var file = FileAccess.open(settings_file, FileAccess.READ)
var abs_path = ProjectSettings.globalize_path(settings_file)
if file:
var read = file.get_as_text()
file.close()
var json_conv = JSON.new()
if json_conv.parse(read) == OK:
settings_data.merge(json_conv.get_data())
else:
log.warning('Не удалось разобрать \"%s\", будут использованы настройки по умолчанию' % abs_path)
else:
log.warning('Файл \"%s\" не найден, будут использованы настройки по умолчанию' % abs_path)
func setting_tab():
@@ -101,57 +151,54 @@ func setting_tab():
$heard_table.set_header_text(HEADER_ROW_TEXT)
$heard_table.set_columns_min_size([600, 950])
$heard_table.set_columns_alignments(ALIGNMENT)
var settings_data = {} # Загружаем настройки из файла
var file = FileAccess.open(settings.settings_file, FileAccess.READ)
var abs_path = ProjectSettings.globalize_path(settings.settings_file)
if file:
var read = file.get_as_text()
file.close()
var json_conv = JSON.new()
if json_conv.parse(read) == OK:
settings_data = json_conv.get_data()
else:
log.warning('Не удалось разобрать \"%s\", будут использованы настройки по умолчанию' % abs_path)
else:
log.warning('Файл \"%s\" не найден, будут использованы настройки по умолчанию' % abs_path)
var settings_data = {}
load_settings(settings_data)
parse_cmd_line_args(settings_data)
for i in SETTING_TABLE.size():
var setting_str = SETTING_TABLE[i]
var parameter = setting_str[0]
var node_label = setting_str[1]
var node_value = setting_str[2]
var tbl_row = SETTING_TABLE[i]
var param_name = tbl_row[0]
var node_label = tbl_row[1]
var node_value = tbl_row[2]
var tootip_text = tbl_row[3]
$scroll_set/table.add_row([node_label, node_value])
var label_instance = $scroll_set/table.get_node2(0, i)
label_instance.text = parameter
label_instance.text = param_name
label_instance.tooltip_text = tootip_text
$scroll_set/table.set_node_editable(0, i, false)
var node_values = $scroll_set/table.get_node2(1, i).get_children()
if node_values.size():
var child = node_values[0]
if child is CheckButton:
child.connect('pressed', Callable(self, 'on_checkbutton_pressed').bind(i))
if parameter in settings_data:
child.set_pressed(settings_data[parameter])
else:
child.set_pressed(false)
var commit_instance = $scroll_set/table.get_node2(1, COMMIT)
var server_instance = $scroll_set/table.get_node2(1, SERVER)
commit_instance.text = '%s' % commit.VCS_HEAD
server_instance.text = ProjectSettings.get('application/config/map_server_addr')
var val = settings_data[param_name] if settings_data.has(param_name) else false
child.set_pressed(val)
else:
if settings_data.has(param_name):
var val = settings_data[param_name]
if typeof(val) == TYPE_STRING:
$scroll_set/table.get_node2(1, i).text = settings_data[param_name]
$scroll_set/table.set_node_editable(1, COMMIT, false)
$scroll_set/table.set_columns_min_size([600, 950])
$scroll_set/table.set_columns_alignments(ALIGNMENT)
for i in SETTING_TABLE.size():
var setting_str = SETTING_TABLE[i]
var parameter = setting_str[0]
if parameter in settings.UnitProfiles:
var unit_data = settings.UnitProfiles[parameter]
var profiles = $scroll_set/table.get_node2(1, i)
var joined_data = ''
for j in range(unit_data[2].size()):
joined_data += str(unit_data[2][j])
if j < unit_data[2].size() - 1:
joined_data += ','
profiles.text = str(unit_data[1]) + ' : ' + joined_data
$scroll_set/table.connect('row_pressed', Callable(self, 'on_row_pressed'))
var commit_instance = $scroll_set/table.get_node2(1, COMMIT)
commit_instance.text = '%s' % commit.VCS_HEAD
for i in SETTING_TABLE.size():
var param_name = SETTING_TABLE[i][0]
if not settings.UnitProfiles.has(param_name):
continue
var unit_data = settings.UnitProfiles[param_name]
var profile = $scroll_set/table.get_node2(1, i)
var joined_data = ''
for j in unit_data[2].size():
joined_data += str(unit_data[2][j])
if j < unit_data[2].size() - 1:
joined_data += ','
profile.text = '%s : %s' % [str(unit_data[1]), joined_data]
button_settings()
@@ -171,7 +218,7 @@ func button_settings():
func _on_btn_save_settings_pressed():
var json_data = {}
for i in range(SETTING_TABLE.size()):
for i in SETTING_TABLE.size():
var parameter = SETTING_TABLE[i][0]
if parameter in settings.UnitProfiles:
var profiles = $scroll_set/table.get_node2(1, i)
@@ -191,16 +238,19 @@ func _on_btn_save_settings_pressed():
else:
port = port.strip_edges()
if port.is_valid_int():
json_data[parameter].append(int(port))
else:
json_data[parameter].append(port)
port = int(port)
json_data[parameter].append(port)
else:
var children = $scroll_set/table.get_node2(1, i).get_children()
if len(children):
var child = children[0]
json_data[parameter] = child.is_pressed()
var file = FileAccess.open(settings.settings_file, FileAccess.WRITE)
var abs_path = ProjectSettings.globalize_path(settings.settings_file)
else:
var row = $scroll_set/table.get_row(i)
json_data[parameter] = row[1].text
var settings_file = settings.get_settings_file_path()
var file = FileAccess.open(settings_file, FileAccess.WRITE)
var abs_path = ProjectSettings.globalize_path(settings_file)
if not file:
log.error('Не удалось открыть файл для записи \"%s\"' % abs_path)
return

View File

@@ -164,7 +164,7 @@ func map_threat_to_bip(th: threats.Threat, bip: Control):
var sector_width = 50.0
for key in prd.FS_FREQ:
var freq_range = prd.FS_FREQ[key]
var _num_values = (freq_range[1]- freq_range[0]) / sector_width
var _num_values = (freq_range[1] - freq_range[0]) / sector_width
if freq_range[0] <= freq and freq <= freq_range[1]:
sector_key = key
break
@@ -195,7 +195,7 @@ 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 bip != null:
if ecm.krp!= interfer.INTERFER_OFF:
bip.set_track_visible(true)
if ecm.svk == 1:

View File

@@ -2,7 +2,7 @@ class_name navigation extends Node
## "Протокол №120-11435-09.PDF"
const ONLINE_TIMEOUT: = 5000 ## Время ожидания пакета, милисекунды
const ONLINE_TIMEOUT: = 5000 ## Время ожидания пакета, миллисекунды
const pow_2_30: = pow(2.0, 30.0)
## Источник данных навигации

View File

@@ -153,10 +153,7 @@ func _ready() -> void:
var unit_key = settings.get_unit_key(unit_name)
units[unit_key] = new_unit
units_udp[unit_key] = new_unit
if len(st[2]) > 1:
dst_ports[unit_key] = st[2][1]
else:
dst_ports[unit_key] = st[2][0]
dst_ports[unit_key] = st[2][1] if len(st[2]) > 1 else st[2][0]
if proto in TCP_PROTO:
var unit_tcp = TCP_PROTO[proto].new(unit_name)

View File

@@ -1,9 +1,7 @@
@tool
class_name rep_settings extends Node
class_name uarep_settings extends Node
## Параметры.
var settings_file = ProjectSettings.get_setting('application/config/settings_path', 'user://settings.json') # Путь к файлу с настройками
## Настройки программы
var settings_program: Dictionary
@@ -57,6 +55,7 @@ const UM_MAX: = 55.0
func _ready() -> void:
if Engine.is_editor_hint():
return
var settings_file = settings.get_settings_file_path()
var abs_path = ProjectSettings.globalize_path(settings_file)
log.info('Путь к файлу настроек: \"%s\"' % abs_path)
var file = FileAccess.open(settings_file, FileAccess.READ)
@@ -103,6 +102,13 @@ func _ready() -> void:
log.info('Не удалось прочитать значение \"%s\" из файла настроек, будет использовано значение по умолчанию' % key)
## Возвращает полный путь к файлу с настройками
func get_settings_file_path():
return ProjectSettings.get_setting(
'application/config/settings_path',
'user://settings.json')
## Возвращает ключ устройства.
func get_unit_key(unit_name: String) -> Array:
var item = UnitProfiles[unit_name]

View File

@@ -1,30 +1,30 @@
class_name tcp5_p28 extends Node
## Реализация "Протокол информационного сопряжения.
## СПО АСУ изделия «МП550» с СПО 5П-28".
## СПО АСУ изделия МП-550 с СПО 5П-28
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от 5П-28, мс.
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
## Тип модуляции для запаковки в пакет для 5П-28.
const MOD_TYPES: Array = ['',
'am',
'ook',
'ask',
'fm',
'qpsk',
'oqpsk',
'pi4qpsk',
'qam16',
'qam32',
'qam64',
'qam128',
'qam256',
'qam512',
'cpfsk',
'psk',
'ofdm',]
const MOD_TYPES: Array = [
'',
'am',
'ook',
'ask',
'fm',
'qpsk',
'oqpsk',
'pi4qpsk',
'qam16',
'qam32',
'qam64',
'qam128',
'qam256',
'qam512',
'cpfsk',
'psk',
'ofdm' ]
const CU_STATE: Dictionary = {
0: 2, # Подготовка к выполнению
@@ -42,19 +42,19 @@ class TCP5P28 extends unit.Unit:
const CMD_TYPE_IN: int = 3
const PR_STATE: Dictionary = {
'уарэп-эмс': [1, 1],
'уарэп-яу07-1н': [9, 8],
'уарэп-яу07-1в': [5, 4],
'уарэп-яу07-1к': [13, 12],
'уарэп-яу07-2н': [10, 9],
'уарэп-яу07-2в': [6, 5],
'уарэп-яу07-2к': [14, 13],
'уарэп-яу07-3н': [11, 10],
'уарэп-яу07-3в': [7, 6],
'уарэп-яу07-3к': [15, 14],
'уарэп-яу07-4н': [12, 11],
'уарэп-яу07-4в': [8, 7],
'уарэп-яу07-4к': [16, 15], }
'уарэп-эмс': [1, 1],
'уарэп-яу07-1н': [9, 8],
'уарэп-яу07-1в': [5, 4],
'уарэп-яу07-1к': [13, 12],
'уарэп-яу07-2н': [10, 9],
'уарэп-яу07-2в': [6, 5],
'уарэп-яу07-2к': [14, 13],
'уарэп-яу07-3н': [11, 10],
'уарэп-яу07-3в': [7, 6],
'уарэп-яу07-3к': [15, 14],
'уарэп-яу07-4н': [12, 11],
'уарэп-яу07-4в': [8, 7],
'уарэп-яу07-4к': [16, 15] }
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей.
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания.
@@ -125,7 +125,7 @@ class TCP5P28 extends unit.Unit:
var data_len = 12 # длинна блока данных в байтах
data.resize(data_len)
data.encode_u16(0, 0) # Код ошибки
data.encode_u16(2, len(interfers)) # Количество целей
data.encode_u16(2, interfers.size()) # Количество целей
data.encode_u32(4, uarep_state) # Состояние УА-РЕП
data.encode_u32(8, uarep_line) # Состояние линий связи
var cu_data: PackedByteArray = []
@@ -136,15 +136,11 @@ class TCP5P28 extends unit.Unit:
continue
var cu = ecms[id]
cu_data.encode_u16(0, cu.ispp)
var state: int
if CU_STATE.has(cu.svk):
state = CU_STATE[cu.svk]
else:
state = 9
var state: int = CU_STATE[cu.svk] if CU_STATE.has(cu.svk) else 9
cu_data.encode_u8(2, state) # Состояние выполнения команды
cu_data.encode_u8(3, 0xFF) # Эффективность работы помехи
data.append_array(cu_data)
var data_to_send: PackedByteArray = create_header(data_len + 4 * len(interfers))
var data_to_send: PackedByteArray = create_header(data_len + 4 * interfers.size())
data_to_send.append_array(data)
tx_stack.append(data_to_send)
@@ -195,7 +191,7 @@ class TCP5P28 extends unit.Unit:
func to_cp866(proto: String, th_data: PackedByteArray):
var cp866_proto: PackedByteArray = proto.to_ascii_buffer()
cp866_proto.resize(36)
for i in len(cp866_proto):
for i in cp866_proto.size():
th_data[28 + i] = cp866_proto[i]
func set_interfer(data: PackedByteArray):

View File

@@ -35,7 +35,7 @@ func allways(val: bool, msg: String = '<не указано>'):
get_tree().quit(Error.FAILED)
func _check_index(obj, index) -> bool:
func check_index(obj, index) -> bool:
if obj is Dictionary:
if obj.has(index):
return true
@@ -59,11 +59,11 @@ func get_value_by_path(obj, paths: Array, ret_val: Array):
var index = paths.pop_at(0)
ret_val[1] = false
if paths.size():
if _check_index(obj, index):
if check_index(obj, index):
ret_val[2] += 1
get_value_by_path(obj[index], paths, ret_val)
else:
if _check_index(obj, index):
if check_index(obj, index):
ret_val[0] = obj[index]
ret_val[1] = true