Merge remote-tracking branch 'refs/remotes/Cat/master'

# Conflicts:
#	scripts/tools.gd
This commit is contained in:
lepshiy
2024-11-06 08:54:08 +03:00
44 changed files with 1316 additions and 454 deletions

20
.gitignore vendored
View File

@@ -15,15 +15,21 @@ mono_crash.*.json
# System/tool-specific ignores
.directory
*~
/.idea/
/build/
/html/
/commit.gd
.idea/
build/
html/
commit.gd
.fuse_hidden*
/bin/
bin/
# Godot 4+ specific ignores
.godot/
/override.cfg
/scripts/commit.gd
override.cfg
# контроль версий
scripts/commit.gd
# python специфичное
modbus/pymodbus/__pycache__
modbus/serial/__pycache__

View File

@@ -3,13 +3,13 @@
# ** Описание **
#
# - Этот скрипт создаёт исполняемый файл (загружаемый модуль) из файла проекта Godot.
# - Путь к шаблонам экспорта прописан в файле "export_presets.cfg".
# Параметр "--export-release" должен иметь имя указанное в поле "name"
# - Путь к шаблонам экспорта должен быть указан в файле "export_presets.cfg".
# - Параметр "--export-release" должен иметь значение указанное в поле "name" файла "export_presets.cfg".
# Имя выходного исполняемого файла (загружаемый модуль)
TARGET_BIN="uarep-ctl.linux.x86_64"
# Целевой путь папки в которой будет расположен исполняемый файл (загружаемый модуль)
# Путь к папке в которой будет расположен исполняемый файл (загружаемый модуль)
TARGET_PATH="./bin"
# Путь к исполняемому файлу редактора Godot
@@ -18,4 +18,8 @@ EDITOR="/opt/godot/godot.linuxbsd.editor.x86_64.llvm"
# Путь к файлу проекта Godot
PROJECT_PATH="$(pwd)"
# Обновление данных контроля версий
./git-hook.sh
# Вызов редактора для сборки исполняемого файла
${EDITOR} --headless --path "${PROJECT_PATH}" --export-release "Linux-X11" "${TARGET_PATH}/${TARGET_BIN}"

View File

@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://dd60btbqnpiqw"
uid="uid://nm7cpjw6rs51"
path="res://.godot/imported/document-new-0.png-4076926ba4469926b76b7d685aad96aa.ctex"
metadata={
"vram_texture": false

View File

@@ -2,7 +2,7 @@
importer="font_data_dynamic"
type="FontFile"
uid="uid://b8xqbrj2ontxe"
uid="uid://dvf4iwl08c1lt"
path="res://.godot/imported/ofont.ru_Franklin Gothic Book.ttf-52f1dac05bf20c0c7af86c6e9cfad8fc.fontdata"
[deps]

View File

@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://b6p0ndxcng02k"
uid="uid://cl8h2vaibabyi"
path="res://.godot/imported/кнопка-квадрат-1.png-3e8f354c4e789ff37e9c072bb90aa353.ctex"
metadata={
"vram_texture": false

View File

@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://bq67yytxgoopq"
uid="uid://b4oau2xgcka77"
path="res://.godot/imported/мп550-работа-эскиз.png-7af57230feae7557e482f8923843a550.ctex"
metadata={
"vram_texture": false

View File

@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://83m8t7nj4a60"
uid="uid://gkbvsypul1qg"
path="res://.godot/imported/отметка-самолёт.png-bb46afb23fe946fe2230cd3d30c66dca.ctex"
metadata={
"vram_texture": false

View File

@@ -2,7 +2,7 @@
importer="texture"
type="CompressedTexture2D"
uid="uid://cqu18m05sdl5w"
uid="uid://bq6biyc0nxjv4"
path="res://.godot/imported/прицел-табличка.png-45ba36412555fb1cbc42d6445071f6cd.ctex"
metadata={
"vram_texture": false

View File

@@ -23,7 +23,9 @@
GDSCRIPT_FILE="scripts/commit.gd"
HEAD="$(git rev-parse --abbrev-ref HEAD) $(git rev-parse --short HEAD) $(git log -1 --format=%cd)"
if [ -n "$(git status --porcelain)" ]; then
HEAD="Изменённый ${HEAD}"
fi
echo "extends Node" > ${GDSCRIPT_FILE}
echo "# Файл сгенерирован автоматически! Не изменять вручную!" >> ${GDSCRIPT_FILE}
echo "const VCS_HEAD = '${HEAD}'" >> ${GDSCRIPT_FILE}

View File

@@ -87,14 +87,14 @@ def run_sync_client(udp_addr, udp_port_rx, udp_port_tx, serial_port, serial_baud
rq = client.read_holding_registers(data[0], data[1], unit=unit_num)
rc = rq.isError()
if not rc:
tx_data = json_encoder.encode({'code': 'response', 'data': rq.registers})
tx_data = json_encoder.encode({'code': 'response', 'data': [data[0]] + rq.registers})
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
elif message['code'] == 'read_input':
data = message['data']
rq = client.read_input_registers(data[0], data[1], unit=unit_num)
rc = rq.isError()
if not rc:
tx_data = json_encoder.encode({'code': 'response', 'data': rq.registers})
tx_data = json_encoder.encode({'code': 'response', 'data': [data[0]] + rq.registers})
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
elif message['code'] == '<unknown>':
rc = False

View File

@@ -13,6 +13,7 @@ config_version=5
config/name="uarep-ctl"
run/main_scene="res://scenes/tabs-switch/tab-switch.tscn"
config/features=PackedStringArray("4.2")
run/flush_stdout_on_print=true
run/low_processor_mode=true
run/delta_smoothing=false
boot_splash/show_image=false
@@ -29,12 +30,8 @@ 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)
config/mod_bus_driver="client-serial-modbus.py"
config/mod_bus_driver_port="48000"
config/mod_bus_driver_address="localhost"
config/mod_bus_interpreter="python"
config/mod_bus_serial_baud="9600"
config/mod_bus_serial_port="/dev/pts/3"
interfer/resend_timeout=1000.0
config/external_cu=false
config/unit_rr_left_bort="http://127.0.0.1:8080/reports/left_SelfTestReport.json"
@@ -48,8 +45,8 @@ log="*res://addons/godot-logger/scripts/logger.gd"
unit="*res://scripts/unit.gd"
tools="*res://scripts/tools.gd"
signaller="*res://scripts/signaller.gd"
repsettings="*res://scripts/settings.gd"
repnetwork="*res://scripts/network.gd"
settings="*res://scripts/settings.gd"
network="*res://scripts/network.gd"
yau07="*res://scripts/yau07.gd"
capsrpb="*res://scripts/capsrpb.gd"
table="*res://table/table.gd"
@@ -60,7 +57,6 @@ yemsconsts="*res://scripts/yems-consts.gd"
interfer="*res://scripts/interfer.gd"
hotkeys="*res://scripts/hotkeys.gd"
mercator="*res://scripts/mercator.gd"
modbus="*res://scripts/modbus.gd"
tcp5p28="*res://scripts/tcp5p28.gd"
sch3="*res://scripts/sch3.gd"
spt25="*res://scripts/spt25.gd"

View File

@@ -65,7 +65,11 @@ func _enter_tree() -> void:
$back.scale = size
$back.material.set('shader_parameter/scale', size / Vector2(20.0, 20.0))
$button.set_toggle_mode(true)
$button.connect('toggled', Callable(self, '_on_button_toggled'))
$button.connect('toggled', _on_button_toggled)
func _exit_tree() -> void:
$button.disconnect('toggled', _on_button_toggled)
func set_toggle_mode(val: bool):

View File

@@ -47,6 +47,9 @@ const COLUMN_AOA = 3
const COLUMN_STATE = 4
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()
## Вызывается при нажатии указателем мыши на выбранный ряд.
func on_row_pressed(i_row: int):
$table.clear_rows_selected()
@@ -148,5 +151,3 @@ func map_th_to_row(ecm) -> Array:
row[COLUMN_STATE] = '%s' % INTERFER_STATE[ecm.svk]
return row
func on_rto_threat_unsel(_th_id): $table.clear_rows_selected()

View File

@@ -12,7 +12,7 @@ patch_margin_top = 30
patch_margin_right = 15
patch_margin_bottom = 10
script = ExtResource("2_ki0kf")
text = ""
text = "заголовок"
[node name="header" type="Label" parent="."]
clip_contents = true
@@ -22,6 +22,6 @@ anchor_right = 1.0
offset_bottom = 22.0
grow_horizontal = 2
theme_override_colors/font_color = Color(0, 0, 0, 1)
text = "caption text"
text = "заголовок"
horizontal_alignment = 1
vertical_alignment = 1

View File

@@ -21,6 +21,19 @@ signal pressed(control: PanelContainer)
fname = v
$margin/vbox/title/fname.text = v
@export var state: int:
set(v):
state = v
if v == 0:
$margin/vbox/title/lbl_using.text = 'неизвестно'
$margin/vbox/title/lbl_using.self_modulate = Color.CADET_BLUE
elif v == 1:
$margin/vbox/title/lbl_using.text = 'используется'
$margin/vbox/title/lbl_using.self_modulate = Color.GREEN
elif v == 2:
$margin/vbox/title/lbl_using.text = 'отключено'
$margin/vbox/title/lbl_using.self_modulate = Color.WHITE
@export var state0: int:
set(v):
@@ -114,16 +127,23 @@ alignment = -1
[node name="title" type="GridContainer" parent="margin/vbox"]
layout_mode = 2
columns = 2
[node name="fname" type="Label" parent="margin/vbox/title"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 6
size_flags_horizontal = 6
theme_override_font_sizes/font_size = 17
horizontal_alignment = 1
vertical_alignment = 1
[node name="lbl_using" type="Label" parent="margin/vbox/title"]
layout_mode = 2
size_flags_horizontal = 6
text = "неизвестно"
horizontal_alignment = 1
vertical_alignment = 1
[node name="table" type="GridContainer" parent="margin/vbox"]
layout_mode = 2
columns = 2

View File

@@ -43,7 +43,7 @@ signal pressed(control: PanelContainer)
@export var state2: int:
set(v):
state1 = tools.clip_value(v, 0, textures.size() - 1)
state2 = tools.clip_value(v, 0, textures.size() - 1)
$margin/vbox/table/state2.texture = textures[v]

View File

@@ -1,11 +1,13 @@
[gd_scene load_steps=7 format=3 uid="uid://bs7h65e7bodp3"]
[gd_scene load_steps=9 format=3 uid="uid://bs7h65e7bodp3"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="1_6olof"]
[ext_resource type="Script" path="res://scenes/контроль/прибор.gd" id="1_46rp6"]
[ext_resource type="PackedScene" uid="uid://ku8rdjoyscai" path="res://scenes/pribor-uyep/block-input.tscn" id="4_mrvir"]
[ext_resource type="Script" path="res://scenes/pribor-uyep/spt25_view.gd" id="4_v0lil"]
[ext_resource type="Script" path="res://scenes/pribor-uyep/spt25-view.gd" id="4_v0lil"]
[ext_resource type="PackedScene" uid="uid://bsixhjfesq6r4" path="res://scenes/pribor-uyep/block-output.tscn" id="5_x74mk"]
[ext_resource type="PackedScene" uid="uid://btpc78gucr57f" path="res://scenes/контроль/элемент-я.tscn" id="6_60xs3"]
[ext_resource type="PackedScene" uid="uid://5c24lfvp72en" path="res://scenes/pribor-uyep/sch3.tscn" id="7_13r50"]
[ext_resource type="Script" path="res://scenes/pribor-uyep/sch3-view.gd" id="8_4t3jv"]
[node name="pribor_uyep" type="Control"]
layout_mode = 3
@@ -39,20 +41,20 @@ vertical_alignment = 1
[node name="Label" type="Label" parent="."]
self_modulate = Color(0.835294, 0.141176, 0.286275, 1)
layout_mode = 0
offset_left = 135.0
offset_top = 990.0
offset_right = 665.0
offset_bottom = 1009.0
offset_left = 145.0
offset_top = 1055.0
offset_right = 675.0
offset_bottom = 1074.0
text = "** Позиционные обозначения требуют уточнения **"
horizontal_alignment = 1
vertical_alignment = 1
[node name="spt25_A1" parent="." instance=ExtResource("6_60xs3")]
layout_mode = 0
offset_left = 135.0
offset_top = 485.0
offset_right = 375.0
offset_bottom = 895.0
offset_left = 175.0
offset_top = 275.0
offset_right = 415.0
offset_bottom = 685.0
script = ExtResource("4_v0lil")
unit_name = "уарэп-спт25-1"
fname = "СПТ-25-230-400"
@@ -83,10 +85,10 @@ offset_bottom = 367.0
[node name="spt25_A2" parent="." instance=ExtResource("6_60xs3")]
layout_mode = 0
offset_left = 435.0
offset_top = 485.0
offset_right = 675.0
offset_bottom = 895.0
offset_left = 440.0
offset_top = 275.0
offset_right = 680.0
offset_bottom = 685.0
script = ExtResource("4_v0lil")
unit_name = "уарэп-спт25-2"
fname = "СПТ-25-230-400"
@@ -114,3 +116,12 @@ offset_left = 15.0
offset_top = 275.0
offset_right = 225.0
offset_bottom = 367.0
[node name="sch3" parent="." instance=ExtResource("7_13r50")]
offset_left = 175.0
offset_top = 714.0
offset_right = 680.0
offset_bottom = 929.0
script = ExtResource("8_4t3jv")
fname = "Щ3"
rname = "A3"

View File

@@ -0,0 +1,47 @@
@tool
extends "res://scenes/контроль/элемент-я.gd"
func on_data_received(data): pass
func _enter_tree() -> void:
if Engine.is_editor_hint(): return
var unit_key = settings.get_unit_key(unit_name)
var unit = network.units[unit_key]
unit.connect('responce_received', Callable(self, 'on_responce_received'))
func _exit_tree() -> void:
if Engine.is_editor_hint(): return
var unit_key = settings.get_unit_key(unit_name)
var unit = network.units[unit_key]
unit.disconnect('responce_received', Callable(self, 'responce_received'))
func on_line_changed(_unit):
var items = get_tree().get_nodes_in_group('bits_items')
for item in items:
item.texture = textures[STATE_VAL.ERROR]
func on_responce_received(addr: int, data: PackedByteArray):
print_debug([addr, data])
if (addr != 0) or (data.size() != 4):
return
var items = get_tree().get_nodes_in_group('bits_items')
var cnt_good: int = 0
for item in items:
var bits: Array = item.get_meta('bits')
var byte0: int = bits[0]
var bit0: int = bits[1]
var byte1: int = bits[2]
var bit1: int = bits[3]
var v = STATE_VAL.GOOD \
if (data[byte0] & (1 << bit0)) \
== (data[byte1] & (1 << bit1)) \
else STATE_VAL.ERROR
cnt_good += int(v == STATE_VAL.GOOD)
item.texture = textures[v]
state = STATE_VAL.GOOD if cnt_good == items.size() else STATE_VAL.ERROR

View File

@@ -0,0 +1,427 @@
[gd_scene load_steps=12 format=3 uid="uid://5c24lfvp72en"]
[ext_resource type="Script" path="res://scenes/контроль/элемент-я.gd" id="1_mb0l2"]
[ext_resource type="Texture2D" uid="uid://c6nve6f8sfyj2" path="res://data/состояние-исправности-0.png" id="2_qglal"]
[ext_resource type="Texture2D" uid="uid://dnreyfh3cd1k2" path="res://data/состояние-исправности-1.png" id="3_gqvwf"]
[ext_resource type="Texture2D" uid="uid://c6booa8753u5t" path="res://data/состояние-исправности-2.png" id="4_2lj00"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="5_eanbw"]
[sub_resource type="GDScript" id="GDScript_45hqb"]
script/source = "@tool
extends MarginContainer
func _enter_tree() -> void:
margins = [8, 8, 8, 8]
@export var margins: Array:
set(vals):
add_theme_constant_override('margin_top', vals[0])
add_theme_constant_override('margin_left', vals[1])
add_theme_constant_override('margin_bottom', vals[2])
add_theme_constant_override('margin_right', vals[3])
get:
var vals = [0, 0, 0, 0]
vals[0] = get_theme_constant('margin_top')
vals[1] = get_theme_constant('margin_left')
vals[2] = get_theme_constant('margin_bottom')
vals[3] = get_theme_constant('margin_right')
return vals
"
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_ox0yw"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_xxyaa"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_cd4fw"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_emtms"]
[sub_resource type="StyleBoxEmpty" id="StyleBoxEmpty_evx06"]
[node name="sch3" type="Control"]
editor_description = "Элемент замены из ЗИП"
custom_minimum_size = Vector2(32, 32)
layout_mode = 3
anchors_preset = 0
offset_left = 125.0
offset_top = 635.0
offset_right = 635.0
offset_bottom = 865.0
script = ExtResource("1_mb0l2")
textures = [ExtResource("2_qglal"), ExtResource("3_gqvwf"), ExtResource("4_2lj00")]
unit_name = "уарэп-щ3"
[node name="rect" type="NinePatchRect" parent="."]
layout_mode = 2
offset_right = 510.0
offset_bottom = 230.0
size_flags_horizontal = 3
size_flags_vertical = 3
texture = ExtResource("5_eanbw")
draw_center = false
region_rect = Rect2(0, 0, 63, 63)
patch_margin_left = 17
patch_margin_top = 17
patch_margin_right = 17
patch_margin_bottom = 15
[node name="margin" type="MarginContainer" parent="."]
layout_mode = 2
offset_right = 510.0
offset_bottom = 230.0
theme_override_constants/margin_left = 8
theme_override_constants/margin_top = 8
theme_override_constants/margin_right = 8
theme_override_constants/margin_bottom = 8
script = SubResource("GDScript_45hqb")
margins = [8, 8, 8, 8]
[node name="vbox" type="VBoxContainer" parent="margin"]
layout_mode = 2
[node name="grid" type="GridContainer" parent="margin/vbox"]
layout_mode = 2
size_flags_vertical = 2
columns = 3
[node name="state" type="TextureRect" parent="margin/vbox/grid"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
[node name="fname" type="Label" parent="margin/vbox/grid"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 6
theme_override_font_sizes/font_size = 17
vertical_alignment = 1
[node name="rname" type="Label" parent="margin/vbox/grid"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_vertical = 6
theme_override_font_sizes/font_size = 22
horizontal_alignment = 2
vertical_alignment = 1
[node name="table" type="GridContainer" parent="margin/vbox"]
layout_mode = 2
size_flags_vertical = 6
columns = 8
[node name="state0" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 0, 2, 0]
[node name="name0" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "УФ"
[node name="state1" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 1, 2, 1]
[node name="name1" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "РТР"
[node name="state2" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 2, 2, 2]
[node name="name2" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-Н.1"
[node name="state3" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 3, 2, 3]
[node name="name3" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-Н.2"
[node name="state4" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 4, 2, 4]
[node name="name4" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-Н.3"
[node name="state5" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 5, 2, 5]
[node name="name5" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-Н.4"
[node name="state6" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 6, 2, 6]
[node name="name6" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-В.1"
[node name="state7" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 7, 2, 7]
[node name="name7" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-В.2"
[node name="state8" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 8, 2, 8]
[node name="name8" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-В.3"
[node name="state9" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 9, 2, 9]
[node name="name9" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-В.4"
[node name="state10" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 10, 2, 10]
[node name="name10" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-К.1"
[node name="state11" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [0, 11, 2, 11]
[node name="name11" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-К.2"
[node name="state12" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 0, 3, 0]
[node name="name12" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-К.3"
[node name="state13" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 1, 3, 1]
[node name="name13" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ПРД-К.4"
[node name="state14" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 2, 3, 2]
[node name="name14" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Бл. по вент."
[node name="state15" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 3, 3, 3]
[node name="name15" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "ДУ"
[node name="state16" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 7, 3, 7]
[node name="name16" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Вент. РТР"
[node name="state17" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
size_flags_horizontal = 4
size_flags_vertical = 4
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 8, 3, 8]
[node name="name17" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Вент. ПРД.1"
[node name="state18" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 9, 3, 9]
[node name="name18" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Вент. ПРД.2"
[node name="state19" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 10, 3, 10]
[node name="name19" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Вент. ПРД.3"
[node name="state20" type="TextureRect" parent="margin/vbox/table" groups=["bits_items"]]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("2_qglal")
expand_mode = 1
metadata/bits = [1, 11, 3, 11]
[node name="name20" type="Label" parent="margin/vbox/table"]
self_modulate = Color(1, 1, 1, 0.627451)
layout_mode = 2
theme_override_font_sizes/font_size = 17
text = "Вент. ПРД.4"
[node name="button" type="Button" parent="."]
layout_mode = 2
offset_right = 510.0
offset_bottom = 230.0
theme_override_styles/normal = SubResource("StyleBoxEmpty_ox0yw")
theme_override_styles/hover = SubResource("StyleBoxEmpty_xxyaa")
theme_override_styles/pressed = SubResource("StyleBoxEmpty_cd4fw")
theme_override_styles/disabled = SubResource("StyleBoxEmpty_emtms")
theme_override_styles/focus = SubResource("StyleBoxEmpty_evx06")
[connection signal="resized" from="." to="." method="_on_resized"]
[connection signal="pressed" from="button" to="." method="_on_button_pressed"]

View File

@@ -0,0 +1,59 @@
@tool
extends "res://scenes/контроль/элемент-я.gd"
func on_line_changed(unit):
if not unit.online:
state = STATE_VAL.NONE
$block_output.state0 = STATE_VAL.NONE
$block_output.state1 = STATE_VAL.NONE
$block_output.state2 = STATE_VAL.NONE
$block_input1.state = STATE_VAL.NONE
$block_input1.state0 = STATE_VAL.NONE
$block_input1.state1 = STATE_VAL.NONE
$block_input1.state2 = STATE_VAL.NONE
$block_input2.state = STATE_VAL.NONE
$block_input2.state0 = STATE_VAL.NONE
$block_input2.state1 = STATE_VAL.NONE
$block_input2.state2 = STATE_VAL.NONE
func on_data_received(data: PackedByteArray):
# Сеть 1. Использование
$block_input1.state = STATE_VAL.GOOD if data[4] & (1 << 5) else STATE_VAL.ERROR
# Сеть 1. Вход
$block_input1.state0 = STATE_VAL.GOOD if ((data[4] & (1 << 1)) == 0) and ((data[4] & (1 << 3)) == 0) else STATE_VAL.ERROR
# Сеть 1. Неисправность блока инвертора 1 канала
$block_input1.state1 = STATE_VAL.GOOD if (data[6] & (1 << 2)) == 0 else STATE_VAL.ERROR
# Сеть 1. Перегрев 1 канала
$block_input1.state2 = STATE_VAL.GOOD if (data[5] & (1 << 3)) == 0 else STATE_VAL.ERROR
# Сеть 2. Использование
$block_input2.state = STATE_VAL.GOOD if data[4] & (1 << 6) else STATE_VAL.ERROR
# Сеть 2. Вход
$block_input2.state0 = STATE_VAL.GOOD if ((data[4] & (1 << 2)) == 0) and ((data[4] & (1 << 4)) == 0) else STATE_VAL.ERROR
# Сеть 2. Неисправность блока инвертора 2 канала
$block_input2.state1 = STATE_VAL.GOOD if (data[6] & (1 << 3)) == 0 else STATE_VAL.ERROR
# Сеть 2. Перегрев 2 канала
$block_input2.state2 = STATE_VAL.GOOD if (data[5] & (1 << 4)) == 0 else STATE_VAL.ERROR
# Неисправность, напряжение меньше номинального, напряжение выше номинального
$block_output.state0 = STATE_VAL.GOOD if ((data[4] & (1 << 0)) == 0) and ((data[4] & (1 << 7)) == 0) and ((data[5] & (1 << 2)) == 0) else STATE_VAL.ERROR
# Перегрузка и короткое замыкание по выходу
$block_output.state1 = STATE_VAL.GOOD if ((data[5] & (1 << 0)) == 0) and ((data[5] & (1 << 1)) == 0) else STATE_VAL.ERROR
# Критическая температура
$block_output.state2 = STATE_VAL.GOOD if ((data[5] & (1 << 5)) == 0) else STATE_VAL.ERROR
# Обобщённое состояние
state = STATE_VAL.GOOD \
if $block_input1.state1 == STATE_VAL.GOOD \
and $block_input1.state2 == STATE_VAL.GOOD \
and $block_input2.state0 == STATE_VAL.GOOD \
and $block_input2.state1 == STATE_VAL.GOOD \
and $block_input2.state2 == STATE_VAL.GOOD \
and $block_output.state0 == STATE_VAL.GOOD \
and $block_output.state1 == STATE_VAL.GOOD \
and $block_output.state2 == STATE_VAL.GOOD \
else STATE_VAL.ERROR

View File

@@ -1,45 +0,0 @@
@tool
extends "res://scenes/контроль/элемент-я.gd"
@export var unit_name: String = ''
enum STATE_VAL
{
NONE = 0,
GOOD = 1,
ERROR = 2
}
func _enter_tree() -> void:
var unit_key = repsettings.get_unit_key(unit_name)
var unit = repnetwork.units[unit_key]
unit.connect('data_received', on_data_received.bind(unit))
func _exit_tree() -> void:
var unit_key = repsettings.get_unit_key(unit_name)
var unit = repnetwork.units[unit_key]
unit.disconnect('data_received', on_data_received)
func on_data_received(data, unit):
# Неисправность, напряжение на выходе меньше номинального
$block_output.state0 = STATE_VAL.GOOD if (data[4] & (1 << 0)) == 0 else STATE_VAL.ERROR
# Перегрузка и короткое замыкание по выходу
$block_output.state1 = STATE_VAL.GOOD if ((data[5] & (1 << 0)) == 0) or ((data[5] & (1 << 1)) == 0) else STATE_VAL.ERROR
# Критическая температура
$block_output.state2 = STATE_VAL.GOOD if ((data[5] & (1 << 5)) == 0) else STATE_VAL.ERROR
# Сеть 1. Вход
$block_input1.state0 = STATE_VAL.GOOD if ((data[4] & (1 << 1)) == 0) or ((data[4] & (1 << 3)) == 0) else STATE_VAL.ERROR
# Сеть 2. Вход
$block_input2.state0 = STATE_VAL.GOOD if ((data[4] & (1 << 2)) == 0) or ((data[4] & (1 << 4)) == 0) else STATE_VAL.ERROR
# Неисправность блока инвертора 1 канала
$block_input1.state1 = STATE_VAL.GOOD if (data[6] & (1 << 2)) == 0 else STATE_VAL.ERROR
# Неисправность блока инвертора 2 канала
$block_input2.state1 = STATE_VAL.GOOD if (data[6] & (1 << 3)) == 0 else STATE_VAL.ERROR
# Перегрев 1 канала
$block_input1.state2 = STATE_VAL.GOOD if (data[5] & (1 << 3)) == 0 else STATE_VAL.ERROR
# Перегрев 2 канала
$block_input1.state2 = STATE_VAL.GOOD if (data[5] & (1 << 4)) == 0 else STATE_VAL.ERROR

View File

@@ -4,7 +4,7 @@ const TAB_TOSIGNAL_NAME = {0: 'режим_работа', 1: 'режим_конт
func _enter_tree() -> void:
repnetwork.logger_page = $Журнал
network.logger_page = $Журнал
func _on_tab_changed(tab) -> void:

View File

@@ -9,14 +9,11 @@ extends Control
@export var fname: String:
set(v):
fname = v
get:
return fname
@export var rname: String:
set(v):
rname = v
get:
return rname
func set_header_text(header_text: String):

View File

@@ -2,6 +2,16 @@
extends Control
@export var textures: Array
@export var unit_name: String = ''
enum STATE_VAL {
NONE = 0,
GOOD = 1,
ERROR = 2 }
signal pressed(control: PanelContainer)
@@ -9,6 +19,12 @@ func _on_button_pressed():
emit_signal('pressed', self)
@export var state: int:
set(v):
state = tools.clip_value(v, 0, textures.size() - 1)
$margin/vbox/grid/state.texture = textures[v]
@export var fname: String:
set(v):
fname = v
@@ -26,9 +42,26 @@ func _on_button_pressed():
$margin/vbox.alignment = v
func _enter_tree() -> void: _on_resized()
func _ready() -> void: call_deferred('_on_resized')
func _on_resized() -> void:
$rect.size = size
$margin.size = size
$button.size = size
func _enter_tree() -> void:
if Engine.is_editor_hint(): return
var unit_key = settings.get_unit_key(unit_name)
var unit = network.units[unit_key]
unit.connect('data_received', Callable(self, 'on_data_received'))
unit.connect('line_changed', Callable(self, 'on_line_changed'))
func _exit_tree() -> void:
if Engine.is_editor_hint(): return
var unit_key = settings.get_unit_key(unit_name)
var unit = network.units[unit_key]
unit.disconnect('data_received', Callable(self, 'on_data_received'))
unit.disconnect('line_changed', Callable(self, 'on_line_changed'))

View File

@@ -1,6 +1,9 @@
[gd_scene load_steps=9 format=3 uid="uid://btpc78gucr57f"]
[gd_scene load_steps=12 format=3 uid="uid://btpc78gucr57f"]
[ext_resource type="Script" path="res://scenes/контроль/элемент-я.gd" id="1_fwxi0"]
[ext_resource type="Texture2D" uid="uid://c6nve6f8sfyj2" path="res://data/состояние-исправности-0.png" id="3_dktys"]
[ext_resource type="Texture2D" uid="uid://dnreyfh3cd1k2" path="res://data/состояние-исправности-1.png" id="3_t4y6r"]
[ext_resource type="Texture2D" uid="uid://c6booa8753u5t" path="res://data/состояние-исправности-2.png" id="4_bdhnj"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="4_or1kj"]
[sub_resource type="GDScript" id="GDScript_45hqb"]
@@ -48,6 +51,7 @@ anchors_preset = 0
offset_right = 180.0
offset_bottom = 155.0
script = ExtResource("1_fwxi0")
textures = [ExtResource("3_dktys"), ExtResource("3_t4y6r"), ExtResource("4_bdhnj")]
[node name="rect" type="NinePatchRect" parent="."]
layout_mode = 2
@@ -79,7 +83,13 @@ layout_mode = 2
[node name="grid" type="GridContainer" parent="margin/vbox"]
layout_mode = 2
columns = 2
columns = 3
[node name="state" type="TextureRect" parent="margin/vbox/grid"]
custom_minimum_size = Vector2(24, 24)
layout_mode = 2
texture = ExtResource("3_dktys")
expand_mode = 1
[node name="fname" type="Label" parent="margin/vbox/grid"]
self_modulate = Color(1, 1, 1, 0.627451)
@@ -92,7 +102,7 @@ vertical_alignment = 1
[node name="rname" type="Label" parent="margin/vbox/grid"]
layout_mode = 2
size_flags_horizontal = 3
size_flags_horizontal = 10
size_flags_vertical = 6
theme_override_font_sizes/font_size = 22
horizontal_alignment = 2

View File

@@ -1,5 +1,3 @@
@tool
class_name work extends Panel
## Основной скрипт для режима "Работа".

View File

@@ -19,6 +19,7 @@ const IN_SET_ROW: Array = [CellLineEdit, CellLEEmpty, CellLEEmpty, CellLEEmpty,
var g_boards: Dictionary ## Словарь плат ЭМС.
var active_board = null ## Активная плата ЭМС
var posx: int = 125 ## Позиция элементов по x.
var posy: int = 70 ## Позиция элементов по y.
@@ -29,6 +30,9 @@ func _ready() -> void:
## Инициализация основных элементов экрана ЭМС.
func init_boards():
var unit_key = settings.get_unit_key('уарэп-эмс')
var unit_ems = network.units[unit_key]
# Выставление позиций элементов ЭМС на экране
$scrollin.set_position(Vector2(posx,posy))
$scrollout.set_position(Vector2(posx + 650,posy))
@@ -40,10 +44,12 @@ func init_boards():
$btn_connect.set_position(Vector2(posx + 590,posy - 25))
$btn_disconnect.set_position(Vector2(posx + 587,posy + 675))
g_boards['КЭМС-Б'] = yemsboards.EmsBoard.new(0, 0x130, yemsconsts.INPUT_KEMS, yemsconsts.OUTPUT_KEMS)
g_boards['ЭМС-Б1'] = yemsboards.EmsBoard.new(1, 0x110, yemsconsts.INPUT_EMS1, yemsconsts.OUTPUT_EMS1)
g_boards['ЭМС-Б2'] = yemsboards.EmsBoard.new(2, 0x120, yemsconsts.INPUT_EMS2, yemsconsts.OUTPUT_EMS2)
g_boards['КЭМС-Б'] = yemsboards.EmsBoard.new(0, 0x130, yemsconsts.INPUT_KEMS, yemsconsts.OUTPUT_KEMS, unit_ems)
g_boards['ЭМС-Б1'] = yemsboards.EmsBoard.new(1, 0x110, yemsconsts.INPUT_EMS1, yemsconsts.OUTPUT_EMS1, unit_ems)
g_boards['ЭМС-Б2'] = yemsboards.EmsBoard.new(2, 0x120, yemsconsts.INPUT_EMS2, yemsconsts.OUTPUT_EMS2, unit_ems)
active_board = g_boards['КЭМС-Б']
init_tbl_in()
$scrollin/tbl_in.pin_header($scrollin, self)
init_tbl_out()
@@ -52,15 +58,14 @@ func init_boards():
$scrl_out_set/tbl_out_set.pin_header($scrl_out_set, self)
init_tbl_files()
$scrl_files/tbl_files.pin_header($scrl_files, self)
var unit_key = repsettings.get_unit_key('уарэп-эмс')
var unit = repnetwork.units[unit_key]
unit.connect('data_received', Callable(self, 'on_data_ems_received'))
unit_ems.connect('data_received', Callable(self, 'on_data_ems_received'))
unit_ems.connect('command_done', Callable(self, 'on_command_done'))
$btn_connect.connect('pressed', Callable(self, 'on_btn_connect'))
$btn_disconnect.connect('pressed', Callable(self, 'on_btn_disconnect'))
$btn_flash_read.button_connect('pressed', Callable(self, 'on_btn_flash_read').bind($btn_flash_read))
$btn_flash_write.button_connect('pressed', Callable(self, 'on_btn_flash_write').bind($btn_flash_write))
## Обработчик нажатия кнопки disconnect.
@@ -126,9 +131,9 @@ func init_tbl_in():
$scrollin/tbl_in.add_row(row_type)
var row_index : int = $scrollin/tbl_in.get_rows_count() - 1
var params : Array = item[1]
var in_dev: yemsdevs.InDev = yemsdevs.InDev.new(item[0], params, row_index)
var in_dev: yemsdevs.InDev = yemsdevs.InDev.new(item[0], params, row_index, g_boards[board].base_addr_isa)
g_boards[board].in_devs[in_dev.id] = in_dev
in_dev.board = board
in_dev.isa_addr = g_boards[board].base_addr_isa
for i in range(len(row_type)):
if i < len(params):
var node = $scrollin/tbl_in.get_node2(i, row_index)
@@ -209,9 +214,10 @@ func init_tbl_out():
$scrollout/tbl_out.add_row([CellLineEdit, CellLineEdit, CellLineEdit, CellLineEdit, CellState, CellLineEdit])
var row_index : int = $scrollout/tbl_out.get_rows_count() - 1
var params : Array = item[1]
var out_dev = yemsdevs.OutDev.new(item[0], params, row_index)
var out_dev = yemsdevs.OutDev.new(item[0], params, row_index, g_boards[board].base_addr_isa)
g_boards[board].out_devs[out_dev.id] = out_dev
out_dev.set_default_mode()
out_dev.board = board
out_dev.isa_addr = g_boards[board].base_addr_isa
for i in range(len(header_text)):
var cell = $scrollout/tbl_out.get_node2(i, row_index)
if i < len(params):
@@ -219,7 +225,7 @@ func init_tbl_out():
cell.editable = false
$scrollout/tbl_out.set_node_user_data(i, row_index, [out_dev, board])
if i in COLUMN_OPTS_BTN:
cell.text = out_dev.mode
cell.text = OUT_MODE[out_dev.mode]
$scrollout/tbl_out.set_columns_min_size([250, 100, 70, 70, 70, 100])
$scrollout/tbl_out.set_columns_alignments(yams_alligment_out)
$scrollout/tbl_out.connect('row_pressed', Callable(self, 'on_row_pressed_out'))
@@ -277,9 +283,7 @@ func set_out_dev(dev):
var mode = $scrl_out_set/tbl_out_set.get_node2(5, 0)
for opt in OUT_MODE:
mode.add_item(opt)
var mode_index: int = OUT_MODE.find(dev.mode)
if mode_index != -1:
mode.select(mode_index)
mode.select(dev.mode)
## Выбор входного или выходного устройства.[br]
@@ -373,5 +377,22 @@ func on_row_pressed(i_row: int, tbl):
func on_data_ems_received(unit):
print_debug(unit.status)
for board in g_boards.values():
board.set_status(unit.status)
if active_board.state_read == active_board.WAIT:
if board.online and not board.read_done:
active_board = board
active_board.state_read = active_board.READ
active_board.start_rw_kems(true)
for i_row in range($scrollin/tbl_in.get_rows_count()):
var state_pic = ($scrollin/tbl_in.get_node2(4, i_row))
var dev = $scrollin/tbl_in.get_node_user_data(4, i_row)[0]
state_pic.set_frame(dev.state)
for i_row in range($scrollout/tbl_out.get_rows_count()):
var state_pic = ($scrollout/tbl_out.get_node2(4, i_row))
var dev = $scrollout/tbl_out.get_node_user_data(4, i_row)[0]
state_pic.set_frame(dev.state)
func on_command_done(unit_ems):
active_board.on_command_done(unit_ems)

View File

@@ -2,7 +2,7 @@
[ext_resource type="Script" path="res://scenes/эмс/эмс.gd" id="1_mk57x"]
[ext_resource type="PackedScene" uid="uid://da7w3vkhadfwe" path="res://scenes/button-flat/button-flat.tscn" id="2_eju8r"]
[ext_resource type="Texture2D" uid="uid://dd60btbqnpiqw" path="res://data/document-new-0.png" id="3_w7rqa"]
[ext_resource type="Texture2D" uid="uid://nm7cpjw6rs51" path="res://data/document-new-0.png" id="3_w7rqa"]
[ext_resource type="Texture2D" uid="uid://coqg6wsftvtxr" path="res://data/document-save-0.png" id="4_gyaoq"]
[ext_resource type="Texture2D" uid="uid://cywuevvpkxl7v" path="res://data/edit-copy-0.png" id="5_dxpqo"]
[ext_resource type="Texture2D" uid="uid://7h55yvh84cve" path="res://data/connect.png" id="6_axj2m"]

View File

@@ -8,18 +8,11 @@ const ONLINE_TIMEOUT = 3000 ## Время ожидания пакета от К
const BUFFER_SIZE = 2048 ## Размер приёмного буфера для датаграмм.
class CapsRpb:
signal line_changed(unit: CapsRpb) ## Сигнал состояние связи изменилось.
signal data_received(unit: CapsRpb) ## Сигнал данные приняты.
signal command_fail(unit: CapsRpb) ## Сигнал при не выполнении команды.
signal parse_error(unit: CapsRpb, msg: String) ## Сигнал ошибки разбора сообщения.
class CapsRpb extends unit.Unit:
static var json_conv: = JSON.new()
var online: = false ## Состояние связи с источником сообщений.
var name: String ## Имя экземпляра.
var json_dic: Dictionary ## Аппарат для разбора сообщений.
var tick: = 0 ## Тик время последнего обновления, мс.
var tx_data: = PackedByteArray() ## Пакет для отправки.
var tx_stack: Array ## Массив пакетов для отправки.
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
@@ -44,6 +37,7 @@ class CapsRpb:
emit_signal('line_changed', self)
if len(tx_stack):
tx_data = tx_stack[0]
tx_len = len(tx_data)
tx_stack.remove_at(0)
return Error.OK
else:

View File

@@ -97,10 +97,10 @@ func _ready():
var ecms: Dictionary = {} ## Словарь помех.
for i in range(ID_INTERFERS_LEN): # Заполняет массив ID целей
id_array.append(i + 1)
var unit_key = repsettings.get_unit_key('уарэп-капсрпб')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_key]
var unit_key = settings.get_unit_key('уарэп-капсрпб')
var unit = network.units[unit_key]
var unit_5p28_key = settings.get_unit_key('уарэп-5п28')
var unit_5p28 = network.units_tcp[unit_5p28_key]
var timer_check_state: = Timer.new()
add_child(timer_check_state)
var resend_timeout = ProjectSettings.get_setting('application/interfer/resend_timeout', 1000.0)

View File

@@ -1,126 +0,0 @@
class_name mod_bus extends Node
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды.
class ModbusClient:
## Состояние автомата выполнения команды.
enum CmdState {
DONE, ## Команда выполнена.
FAIL, ## Команда не выполнена.
SEND, ## Буфер готов для отправки.
WAIT ## Ожидание выполнения.
}
var name: String
var unit: = 1 ## Адрес устройства Modbus.
var cmd_state: = CmdState.DONE ## Код текущей команды.
var tx_data: PackedByteArray ## Данные для отправки.
var online: = false ## Флаг. Если установлен, устройство на связи. Активный уровень - [b]true[/b].
var tick_rx: = 0 ## Время приёма крайнего сообщения.
var tick_tx: = 0 ## Время отправки крайнего сообщения.
static var json_conv: = JSON.new()
signal command_done() ## Вызывается при успешном выполнении команды.
signal command_fail(unit: ModbusClient) ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed(unit: ModbusClient) ## Вызывается при смене состояния связи с ячейкой.
signal data_received() ## Вызывается при приёме сообщения, до его разбора.
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке.
signal responce_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
func _init(nm: String, u: int = 1):
unit = u
name = nm
## Изменяет состояние. Вызывать периодически.[br]
## [param tick] - Текущщее время в мс.[br]
func process(tick: int):
if online and ((tick - tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if (cmd_state == CmdState.WAIT) or (cmd_state == CmdState.SEND):
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
tick_tx = tick
cmd_state = CmdState.WAIT
return rc
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
## [param data] - Данные принятые на сокете.[br]
## [param tick] - Текущщее время в мс.[br]
func parse(data: PackedByteArray, tick: int) -> bool:
tick_rx = tick
if not online:
online = true
emit_signal('line_changed', self)
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
emit_signal('data_received')
var message: Dictionary = json_conv.get_data()
if message.has('code') and message.has('data'):
var rc: = true
var message_code = message['code']
var message_data = message['data']
match message_code:
'response':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('responce_received', addr, regs)
'info':
var msg = message['data']
emit_signal('info_received', msg)
'exception':
var msg = message['data']
emit_signal('except_received', msg)
rc = false
_:
var msg: String = 'код команды \"%s\" - не распознан' % message_code
emit_signal('parse_failed', msg)
rc = false
if (cmd_state == CmdState.WAIT) and rc:
cmd_state = CmdState.DONE
emit_signal('command_done')
elif (cmd_state == CmdState.WAIT) and (not rc):
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
else:
var message = json_conv.get_error_message()
emit_signal('parse_failed', message)
return true
## Отправляет команду "записать в регистры".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Данные для записи в регистры от начального адреса.[br]
func write(addr: int, data: Array) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'write', 'data': [addr] + data}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры хранения".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_holdind(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_holding', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры входов".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_input(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_input', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
cmd_state = CmdState.SEND
return true

View File

@@ -1,21 +1,24 @@
@tool
class_name rep_network extends Node
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'json-capsrpb': capsrpb.CapsRpb, 'udp-json-mbcs': modbus.ModbusClient}
const PROTOCOL_TYPES: = {'yau07tx': yau07.YaU07, 'json-capsrpb': capsrpb.CapsRpb, 'udp-json-mbcs': sch3.Sch3}
const TCP_PROTO: = {'5p28': tcp5p28.TCP5P28}
const SERIAL_PROTO: = {'uart': spt25.SPT25 }
var tick: int = 0
class Serial extends SerialPort:
func send_to(data: PackedByteArray):
write_raw(data)
func send_to(data: PackedByteArray): return write_raw(data)
func _to_string() -> String: return 'последовательный порт \"%s\" @ %d (%s)' % [self.port, self.baudrate, 'открыт' if is_open() else 'закрыт']
func try_open(parsing_proc: Callable):
if not is_open():
open(port)
if is_open():
data_received.connect(parsing_proc)
start_monitoring(timeout)
if is_open():
return Error.OK
var rc = open(port)
if rc == Error.OK:
data_received.connect(parsing_proc)
start_monitoring(timeout)
return rc
class Socket extends PacketPeerUDP:
@@ -56,11 +59,14 @@ var sock_capsrpb: Socket
var logger_page: Node
func on_serial_data(data, unit): unit.parse(data, tick)
func create_socket(nm) -> Socket:
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2][0]
var broad = repsettings.UnitProfiles[nm][3]
var bind = repsettings.UnitProfiles[nm][4]
var addr = settings.UnitProfiles[nm][1]
var port = settings.UnitProfiles[nm][2][0]
var broad = settings.UnitProfiles[nm][3]
var bind = settings.UnitProfiles[nm][4]
var sock: = Socket.new()
sock.set_broadcast_enabled(broad)
var rc = Error.OK if not bind else sock.bind(port, addr)
@@ -70,26 +76,22 @@ func create_socket(nm) -> Socket:
func create_tcpsocket(nm) -> SocketTCP:
var addr = repsettings.UnitProfiles[nm][1]
var port = repsettings.UnitProfiles[nm][2][0]
var addr = settings.UnitProfiles[nm][1]
var port = settings.UnitProfiles[nm][2][0]
var sock = SocketTCP.new()
sock.unit_key = repsettings.get_unit_key(nm)
sock.unit_key = settings.get_unit_key(nm)
sock.listen(port, addr)
log.message(log.INFO, '%s: сокет:%s:%d привязанный:' % [nm, addr, port])
return sock
func create_serial(nm) -> Serial:
var port = repsettings.UnitProfiles[nm][1]
var baud = repsettings.UnitProfiles[nm][2][0]
var port = settings.UnitProfiles[nm][1]
var baud = settings.UnitProfiles[nm][2][0]
var sp: = Serial.new()
sp.port = port
sp.baudrate = baud
sp.timeout = 20000
var rc = sp.open(port)
if rc != Error.OK:
log.message(log.ERROR, 'Невозможно открыть порт \"%s\" для \"%s\"' % [port, nm])
else:
log.message(log.INFO, 'Последовательный порт \"%s\"@%d открыт для \"%s\"' % [port, baud, nm])
return sp
@@ -102,25 +104,25 @@ func _ready() -> void:
sock_unicast = poll_sockets[0]
sock_capsrpb = poll_sockets[2]
for unit_name in repsettings.UnitProfiles:
var settings = repsettings.UnitProfiles[unit_name]
var proto = settings[0]
for unit_name in settings.UnitProfiles:
var st = settings.UnitProfiles[unit_name]
var proto = st[0]
if proto in PROTOCOL_TYPES:
var unit = PROTOCOL_TYPES[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
var unit_key = settings.get_unit_key(unit_name)
units[unit_key] = unit
units_udp[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
if len(settings[2]) > 1:
dst_ports[unit_key] = settings[2][1]
if len(st[2]) > 1:
dst_ports[unit_key] = st[2][1]
else:
dst_ports[unit_key] = settings[2][0]
dst_ports[unit_key] = st[2][0]
if proto in TCP_PROTO:
var unit = TCP_PROTO[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
var unit_key = settings.get_unit_key(unit_name)
units_tcp[unit_key] = unit
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
@@ -128,7 +130,7 @@ func _ready() -> void:
if proto in SERIAL_PROTO:
var unit = SERIAL_PROTO[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
var unit_key = settings.get_unit_key(unit_name)
if logger_page:
unit.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
@@ -136,16 +138,20 @@ func _ready() -> void:
units_serial[unit_key] = unit
units[unit_key] = unit
serials[unit_key] = serial
serial.try_open(unit.parse)
var rc = serial.try_open(on_serial_data.bind(unit))
if rc != Error.OK:
log.message(log.ERROR, 'Невозможно открыть %s для \"%s\"' % [serial, unit_name])
else:
log.message(log.INFO, '%s для \"%s\"' % [serial, unit_name])
tcp_sockets.append([create_tcpsocket('уарэп-5п28'), units_tcp[repsettings.get_unit_key('уарэп-5п28')]])
tcp_sockets.append([create_tcpsocket('уарэп-5п28'), units_tcp[settings.get_unit_key('уарэп-5п28')]])
for key in units: log.info('%s %s:%d' % [units[key].name, key[0], key[1]])
for key in units_tcp: log.info('%s %s:%d' % [units_tcp[key].name, key[0], key[1]])
for key in dst_ports: unit_keys[dst_ports[key]] = key
func poll_receive(sock: Socket, tick: int) -> bool:
func poll_receive(sock: Socket) -> bool:
while sock.get_available_packet_count() > 0:
var data: = sock.get_packet()
var addr: = sock.get_packet_ip()
@@ -159,7 +165,7 @@ func poll_receive(sock: Socket, tick: int) -> bool:
return false
func poll_receive_tcp(sock: SocketTCP, tick: int) -> bool:
func poll_receive_tcp(sock: SocketTCP) -> bool:
if sock.is_connection_available(): # check if someone's trying to connect
var client = sock.take_connection() # accept connection
sock.peerstream.set_stream_peer(client) # bind peerstream to new client
@@ -167,12 +173,12 @@ func poll_receive_tcp(sock: SocketTCP, tick: int) -> bool:
if peer:
var peer_len_data = peer.get_available_bytes()
if peer_len_data > 0:
get_client_data(sock, peer_len_data, peer, tick)
get_client_data(sock, peer_len_data, peer)
if sock.unit_key in units_tcp and sock.rx_all: units_tcp[sock.unit_key].parse(sock.rx_data, tick)
return false
func get_client_data(sock: SocketTCP, peer_len_data, peer, tick):
func get_client_data(sock: SocketTCP, peer_len_data, peer):
if tick - sock.rx_tick > sock.RX_TIMEOUT:
sock.rx_all = true
sock.rx_tick = tick
@@ -205,11 +211,11 @@ func get_tcp_data(sock: SocketTCP, peer, len_rx):
func _process(_delta: float) -> void:
var tick = Time.get_ticks_msec()
tick = Time.get_ticks_msec()
for addr in units_udp:
var unit = units[addr]
match unit.process(tick):
Error.OK: sock_unicast.send_to([addr[0], dst_ports[addr]], unit.tx_data)
Error.OK: sock_unicast.send_to([addr[0], dst_ports[addr]], unit.tx_data.slice(0, unit.tx_len))
Error.FAILED: emit_signal('socket_error', 'ошибка: %s %s:%d' % [unit, addr[0], addr[1]])
for key in units_serial:
var unit = units_serial[key]
@@ -223,5 +229,5 @@ func _process(_delta: float) -> void:
match unit.process(tick):
Error.OK: sock.send_to(unit.tx_data)
Error.FAILED: emit_signal('socket_error', 'ошибка: %s' % unit)
poll_receive_tcp(sock, tick)
poll_sockets.any(func(sock): poll_receive(sock, tick))
poll_receive_tcp(sock)
poll_sockets.any(func(sock): poll_receive(sock))

View File

@@ -1,26 +1,125 @@
extends Node
class_name sch_3 extends Node
var cnt: int = 0
var rw: bool = true
const ONLINE_TIMEOUT: int = 5000 ## Время ожидания данных
const REQUEST_PERIOD: int = 3000 ## Переиод запроса, мс
func _ready():
var unit_key = repsettings.get_unit_key('уарэп-щ3')
var unit = repnetwork.units[unit_key]
var timer = Timer.new()
add_child(timer)
unit.connect('command_fail', Callable(self, 'on_command_fail'))
timer.connect('timeout', Callable(self, 'on_timer').bind(unit))
timer.start(1.0)
class Sch3 extends unit.Unit:
## Состояние автомата выполнения команды.
enum CmdState {
DONE, ## Команда выполнена.
FAIL, ## Команда не выполнена.
SEND, ## Буфер готов для отправки.
WAIT ## Ожидание выполнения.
}
var unit: = 1 ## Адрес устройства Modbus.
var cmd_state: = CmdState.DONE ## Код текущей команды.
var tick_rx: = 0 ## Время приёма крайнего сообщения.
var tick_tx: = 0 ## Время отправки крайнего сообщения.
static var json_conv: = JSON.new()
signal responce_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
func _init(nm: String, u: int = 1):
unit = u
name = nm
## Изменяет состояние. Вызывать периодически.[br]
## [param tick] - Текущщее время в мс.[br]
func process(tick: int):
if online and ((tick - rx_tick) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if cmd_state == CmdState.WAIT:
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
var rc = Error.ERR_BUSY
if (tick - tx_tick) > REQUEST_PERIOD:
if read_input(0, 4):
tx_tick = tick
cmd_state = CmdState.WAIT
rc = Error.OK
return rc
func on_timer(unit):
cnt +=1
if rw:
unit.write(0x0000, [cnt])
else:
unit.read_holdind(0x0000)
rw = not rw
## Производит разбор принятых данных. Вызывать при приёме данных на сокете.[br]
## [param data] - Данные принятые на сокете.[br]
## [param tick] - Текущщее время в мс.[br]
func parse(data: PackedByteArray, tick: int) -> bool:
rx_tick = tick
if not online:
online = true
emit_signal('line_changed', self)
var utf8_data = data.get_string_from_utf8()
if Error.OK == json_conv.parse(utf8_data):
emit_signal('data_received')
var message: Dictionary = json_conv.get_data()
if message.has('code') and message.has('data'):
var rc: = true
var message_code = message['code']
var message_data = message['data']
match message_code:
'response':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('responce_received', addr, regs)
rc = true
'info':
var msg = message['data']
emit_signal('info_received', msg)
'exception':
var msg = message['data']
cmd_state = CmdState.FAIL
emit_signal('except_received', msg)
rc = false
_:
var msg: String = 'код команды \"%s\" - не распознан' % message_code
cmd_state = CmdState.FAIL
emit_signal('parse_failed', msg)
rc = false
if (cmd_state == CmdState.WAIT) and rc:
cmd_state = CmdState.DONE
emit_signal('command_done')
elif (cmd_state == CmdState.WAIT) and (not rc):
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
else:
var message = json_conv.get_error_message()
emit_signal('parse_failed', message)
return true
## Отправляет команду "записать в регистры".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Данные для записи в регистры от начального адреса.[br]
func write(addr: int, data: Array) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'write', 'data': [addr] + data}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
tx_len = len(tx_data)
cmd_state = CmdState.SEND
return true
func on_command_fail(unit):
unit.cmd_state = unit.CmdState.DONE
## Отправляет команду "читать регистры хранения".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_holding(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_holding', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
tx_len = len(tx_data)
cmd_state = CmdState.SEND
return true
## Отправляет команду "читать регистры входов".[br]
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_input(addr: int, count: int = 1) -> bool:
if cmd_state != CmdState.DONE: return false
var json_dict = {'code': 'read_input', 'data': [addr, count]}
tx_data = JSON.stringify(json_dict).to_utf8_buffer()
tx_len = len(tx_data)
cmd_state = CmdState.SEND
return true

View File

@@ -6,9 +6,9 @@ class_name rep_settings extends Node
@export var UnitProfiles: = { \
# Название | Протокол | Адрес | Порт | Широковещательное | Привязывать к адресу | Комментарий
'уарэп-яу07-частный': ['yau07rx', '10.1.1.2', [50002], false, true, 'IP-адрес на котором принимают частные сообщения от ЯУ-07'],
'уарэп-яу07-общий': ['yau07rx', '10.1.1.255', [50000], true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
'уарэп-яу07-общий': ['yau07rx', '*', [50000], true, true, 'IP-адрес на котором принимают широковещательные сообщения от ЯУ-07'],
'уарэп-капсрпб': ['json-capsrpb', '127.0.0.1', [42023, 42022], false, true, 'IP-адрес на котором принимают сообщения от КАПС РПБ'],
'уарэп-эмс': ['yau07tx', '10.1.1.52', [50027], false, false, 'IP-адрес ЯУ-07 прибора УФ'],
'уарэп-эмс': ['yau07tx', '10.1.1.52', [50052], false, false, 'IP-адрес ЯУ-07 прибора УФ'],
'уарэп-яу07-2в': ['yau07tx', '10.1.1.34', [50034], false, false, 'IP-адрес ЯУ-07 прибора ПРД-В'],
'уарэп-яу07-2н': ['yau07tx', '10.1.1.33', [50033], false, false, 'IP-адрес ЯУ-07 прибора ПРД-Н'],
'уарэп-яу07-2к': ['yau07tx', '10.1.1.35', [50035], false, false, 'IP-адрес ЯУ-07 прибора ПРД-К'],
@@ -44,6 +44,5 @@ func _ready() -> void: log.info('Модуль настроек готов')
## Возвращает ключ устройства.
func get_unit_key(unit_name: String) -> Array:
assert(UnitProfiles.has(unit_name), 'ошибка: нет такого устройства \"%s\"' % unit_name)
var item = UnitProfiles[unit_name]
return [item[1], item[2][0]]

View File

@@ -1,11 +1,11 @@
class_name spt25_unit extends Node
const ONLINE_TIMEOUT: int = 5000 ## Время ожидания данных
const REQUEST_PERIOD: int = 3000 ## Переиод запроса, мс
class SPT25 extends unit.Unit:
var tx_tick: int = 0
var req_period = 3000
func _to_string() -> String: return String('СПТ-25: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
func _to_string() -> String: return String('СПТ-25 %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
func _init(nm) -> void:
self.name = nm
@@ -19,14 +19,25 @@ class SPT25 extends unit.Unit:
tx_data[6] = 0 # Контрольная сумма
tx_data[7] = 0x7e # Флаги синхронизации пакета
func parse(rx_data: PackedByteArray):
if not self.online:
self.online = true
func parse(rx_data: PackedByteArray, tick: int):
rx_tick = tick
if not online:
online = true
emit_signal('line_changed', self)
if rx_data.size() <= 6:
emit_signal('parse_failed', self)
return
emit_signal('data_received', rx_data)
func process(delta: float):
tick += delta
if (tick - tx_tick) > req_period:
return Error.OK
return Error.ERR_BUSY
func process(tick: int):
var rc: = Error.ERR_BUSY
if (tick - tx_tick) > REQUEST_PERIOD:
tx_tick = tick
rc = Error.OK
if online:
if (tick - rx_tick) > ONLINE_TIMEOUT:
online = false
emit_signal('line_changed', self)
return rc

View File

@@ -27,30 +27,29 @@ const MOD_TYPES: Array = ['',
'ofdm',]
const CU_STATE: Dictionary = {
0:2, # Подготовка к выполнению
1:1, # Выполняется
2:9, # Ошибка в команде
3:7, # Занят выполнением другого ЦУ
4:9, # Неисправность
0: 2, # Подготовка к выполнению
1: 1, # Выполняется
2: 9, # Ошибка в команде
3: 7, # Занят выполнением другого ЦУ
4: 9, # Неисправность
}
class TCP5P28 extends unit.Unit:
const PACK_TYPE_CMD: int = 1
const PACK_TYPE_RES: int = 2
const PACK_TYPE_CMD: int = 1
const PACK_TYPE_RES: int = 2
const CMD_TYPE_STATE: int = 1
const CMD_TYPE_TH: int = 2
const CMD_TYPE_IN: int = 3
const CMD_TYPE_TH: int = 2
const CMD_TYPE_IN: int = 3
signal get_threats(unit: TCP5P28) ## Сигнал запрос целей.
signal get_interfers(unit: TCP5P28) ## Запрос состояния выполнения целеуказания.
var rx_tick: = 0 ## Тик время последнего приёма, мс.
var tx_stack: Array ## Массив пакетов для отправки.
func _to_string() -> String: return String('капсрпб: "%s" %s ' % [self.name, ['отключен', 'на связи'][int(online)]])
func parse(data: PackedByteArray, now_tick: int):
rx_tick = now_tick
func parse(data: PackedByteArray, tick: int):
rx_tick = tick
if not online:
online = true
emit_signal('line_changed', self)
@@ -65,8 +64,8 @@ class TCP5P28 extends unit.Unit:
if cmd_type == CMD_TYPE_IN and external_cu:
set_interfer(data)
func process(now_tick: int):
if online and ((now_tick - rx_tick) > ONLINE_TIMEOUT):
func process(tick: int):
if online and ((tick - rx_tick) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
if len(tx_stack):

View File

@@ -46,18 +46,18 @@ signal threats_resized(th: Dictionary)
func _ready() -> void:
log.info('Модуль обработки целей готов')
var threats = {} ## Список целей. Индекс - <номер цели>
var unit_key = repsettings.get_unit_key('уарэп-капсрпб')
var unit = repnetwork.units[unit_key]
var unit_5p28_key = repsettings.get_unit_key('уарэп-5п28')
var unit_5p28 = repnetwork.units_tcp[unit_5p28_key]
var unit_key = settings.get_unit_key('уарэп-капсрпб')
var unit = network.units[unit_key]
var unit_5p28_key = settings.get_unit_key('уарэп-5п28')
var unit_5p28 = network.units_tcp[unit_5p28_key]
var timer_check_lost: = Timer.new()
var timer_aoa_update: = Timer.new()
add_child(timer_check_lost)
add_child(timer_aoa_update)
unit.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(repsettings.ThreatParams.time_lost, threats))
timer_check_lost.start(repsettings.ThreatParams.time_lost / 1000.0)
timer_check_lost.connect('timeout', Callable(self, 'on_timer_check_lost').bind(settings.ThreatParams.time_lost, threats))
timer_check_lost.start(settings.ThreatParams.time_lost / 1000.0)
timer_aoa_update.connect('timeout', Callable(self, 'on_timer_aoa_update').bind(threats))
timer_aoa_update.start(0.25)
signaller.connect('rto_threat_sel', Callable(self, 'on_rto_threat_sel').bind(threats))

View File

@@ -74,7 +74,6 @@ func get_string_slice(s_in: String, s_out: Array, i0: int, i1: int):
func pos_calc(freq: float, aoa: float, pos0: Vector2, r0: float, r1: float, f0: float, f1: float):
var r = remap(freq, f0, f1, r0, r1)
var aoa_rad = radians(aoa) - PI / 2.0
return Vector2(cos(aoa_rad), sin(aoa_rad)) * r + pos0
@@ -112,11 +111,6 @@ func map_dec_to_rad(pos0: Vector2, pos: Vector2) -> Vector2:
return Vector2(ang + 360.0 * float(ang < 0.0), hypot(x1, y1))
## Переводит значение val из диапазона a0...a1 в диапазон b0...b1.
func map_range(val: float, a0: float, a1: float, b0: float, b1: float) -> float:
return (((val - a0) * (b1 - b0)) / (a1 - a0)) + b0
## Возвращает [b]true[/b], если точка внутри заданного полигона.[br]
## [param pos] - Проверяемая точка.[br]
## [param p] - Координаты вершин полигона.[br]
@@ -138,3 +132,31 @@ func is_point_in_polygon(pos: Vector2, p: PackedVector2Array) -> bool:
func set_wordi(buf: PackedByteArray, index: int, val: int) -> void:
buf[index] = val & 0xff
buf[index + 1] = (val >> 8) & 0xff
func set_bit(bits, index, val, mask = 0xfffffffffffffff):
"""
:param bits: прежние значения
:param index: индекс бита
:param val: новое значение бита
:param mask:
:return:
мастер
"""
bits &= mask
if val:
bits |= 1 << index
else:
bits &= ~(1 << index)
return (bits & mask)
func set_bits(v, a, m):
"""
Устанавливает биты в соответствии с маской
:param v: Прежние значения бит
:param a: Новые значения бит
:param m: Маска изменяемых бит
:return: Изменённые значения бит
"""
return v & a & (~m) | (~v) & a & m | v & a & m | v & (~a) & (~m)

View File

@@ -1,17 +1,17 @@
class_name base_unit extends Node
## Базовый класс для управления подключаемыми устройствами
class Unit:
signal line_changed(unit) ## Вызывается при изменение состояния связи
signal line_changed(unit) ## Вызывается при изменении состояния связи
signal command_done(unit) ## Вызывается после выполнения команды.
signal command_fail(unit) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
signal parse_failed(unit) ## Вызывается при обнаружении ошибки во входных данных
signal data_received(unit) ## Вызывается по приёму данных
signal data_received(data: PackedByteArray) ## Вызывается по приёму данных
var tick = 0.0 ## Текущее тик-время в мс.
var tx_data: = PackedByteArray() ## Буфер отправленный.
var tx_len = 0 ## Длина последнего отправленного пакета.
var tx_data: = PackedByteArray() ## Буфер отправленный.
var tx_len = 0 ## Длина последнего отправленного пакета.
var tx_tick: int = 0
var rx_tick: int = 0
var online: bool
var name: String
func _init(nm) -> void: self.name = nm

View File

@@ -2,8 +2,8 @@ class_name yau_07 extends Node
## Протокол ячейки ЯУ-07.
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды
const RESEND_TIMEOUT = 0.3 ## Задержка для повторной отправки команды, секунды
const ONLINE_TIMEOUT = 5000 ## Время ожидания пакета от ячейки, милисекунды
const RESEND_TIMEOUT = 300 ## Задержка для повторной отправки команды, секунды
const RETRY_COUNT = 5 ## Количество повторных отправок
const BUFFER_SIZE = 2048 ## Размер буфера для приёма датаграмм
@@ -13,10 +13,14 @@ class YaU07 extends unit.Unit:
## Коды выполняемых команд.
enum CmdCode {
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07.
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07.
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07.
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07.
READ_ISA = 0, ## Код команды "читать порт ISA" ячейки ЯУ-07
WRITE_ISA = 1, ## Код команды "записать порт ISA" ячейки ЯУ-07
ERASE_FLASH = 49, ## Код команды "стереть данные из FLASH" ячейки ЯУ-07
WRITE_FLASH = 50, ## Код команды "записать данные в FLASH" ячейки ЯУ-07
READ_FLASH = 51, ## Код команды "прочитать данные из FLASH" ячейки ЯУ-07
LOAD_FLASH = 52, ## Код команды "записать данные из FLASH в КЭМС" ячейки ЯУ-07
WRITE_BLOCK = 60, ## Код команды "записать блок данных ISA" внешней шины ячейки ЯУ-07
READ_BLOCK = 61, ## Код команды "читать блок данных ISA" внешней шины ячейки ЯУ-07
}
## Состояние автомата выполнения команды.
@@ -28,17 +32,20 @@ class YaU07 extends unit.Unit:
FAIL ## Команда не выполнена.
}
var cmd_num_rx: = 0 ## Номер команды принятый.
var cmd_num_tx: = 0 ## Номер команды переданный.
var cmd_state = CmdState.UNCK ## Состояние выполнения команды.
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07.
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07.
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду.
var cmd_tick_tx = 0.0 ## Время последней отправки команды.
var cmd_tick_rx = 0.0 ## Время последнего приёма команды.
var status: = PackedByteArray() ## Поле "состояние прибора".
var isa_ports = {} ## Результат выполнения команды "читать порт".
var isa_block = {} ## Результат выполнения команды "читать массив из порта".
var cmd_num_rx: = 0 ## Номер команды принятый
var cmd_num_tx: = 0 ## Номер команды переданный
var cmd_state = CmdState.UNCK ## Состояние выполнения команды
var cmd_result: = 1 ## Результат выполнения команды. Устанавливается в ЯУ-07
var cmd_data: = PackedByteArray() ## Данные команды. Устанавливается в ЯУ-07
var cmd_retry = 0 ## Счётчик оставшихся попыток выполнить команду
var cmd_code_rx = 0 ## Код последней выполненой команды
var cmd_tick_tx = 0.0 ## Время последней отправки команды
var cmd_tick_rx = 0.0 ## Время последнего приёма команды
var status: = PackedByteArray() ## Поле "состояние прибора"
var isa_ports = {} ## Результат выполнения команды "читать порт"
var isa_block = {} ## Результат выполнения команды "читать массив из порта"
var flash_data: = PackedByteArray() ## Данные прочитанные из Flash
var flash_len: = 0 ## Длинна данных прочитанных из Flash
func _to_string() -> String: return String('яу07: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
@@ -48,11 +55,9 @@ class YaU07 extends unit.Unit:
self.name = nm
tx_data.resize(BUFFER_SIZE)
tx_data.fill(0)
tick = 0.0
func process(delta: float):
tick += delta
func process(tick: int):
if online and ((tick - cmd_tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed', self)
@@ -75,6 +80,33 @@ class YaU07 extends unit.Unit:
rc = Error.FAILED
return rc
func send_flash(cmd_code: int, fl_data: Array, num_byte_rd: int) -> bool:
if (cmd_state == CmdState.WAIT) \
or (cmd_state == CmdState.SEND) \
or (cmd_state == CmdState.UNCK):
return false
if not ((cmd_code == CmdCode.ERASE_FLASH) or (cmd_code == CmdCode.WRITE_FLASH) \
or (cmd_code == CmdCode.READ_FLASH) or (cmd_code == CmdCode.LOAD_FLASH)):
return false
cmd_num_tx = (cmd_num_rx + 1) % 0xffff
tx_data.encode_u16(0, cmd_retry)
tx_data.encode_u16(2, cmd_num_tx)
tx_data.encode_u8(6, cmd_code)
if cmd_code == CmdCode.ERASE_FLASH:
tx_len = 7
elif cmd_code == CmdCode.WRITE_FLASH:
tx_data.encode_u8(7, 1)
tx_data.encode_u16(8, 0)
tx_data.encode_u16(10, len(fl_data))
tx_len = 11 + len(fl_data) * 2
for i in range(len(fl_data)):
tx_data.encode_u16(12 + i * 2, fl_data[i])
elif cmd_code == CmdCode.READ_FLASH:
tx_len = 11
tx_data.encode_u16(7, 0)
tx_data.encode_u16(9, num_byte_rd)
cmd_state = CmdState.SEND
return true
func send_isa(cmd_code: int, ports_data: Array) -> bool:
if (cmd_state == CmdState.WAIT) \
@@ -175,13 +207,18 @@ class YaU07 extends unit.Unit:
isa_block[block_adr] = block_data
return true
func parse_flash(rx_data: PackedByteArray, status_len, cmd_code) -> bool:
if cmd_code == CmdCode.READ_FLASH:
flash_len = rx_data.decode_u16(status_len + 12)
flash_data = rx_data.slice(status_len + 14)
return true
## Заполняет состояние прибора данными прочитанными из портов ЯУ-07.
## для команд "читать порты" или "записать порты".[br]
## [param rx_data] - Принятые данные.[br]
## Возвращает [b]true[/b] - Данные обработаны успешно.[br]
## Возвращает [b]false[/b] - Данные не обработаны из за ошибки.[br]
func parse(rx_data: PackedByteArray) -> bool:
func parse(rx_data: PackedByteArray, tick: int) -> bool:
cmd_tick_rx = tick
@@ -208,6 +245,7 @@ class YaU07 extends unit.Unit:
if byte_i < len_rx_data:
status[i] = rx_data[byte_i] # Массив байтовый "состояние прибора"
i += 1
emit_signal('data_received', self)
if rx_data_len == (status_len + 6):
return true # Нет поля "ответ на команду", разбор пакета завершить
@@ -231,9 +269,14 @@ class YaU07 extends unit.Unit:
elif (cmd_code == CmdCode.READ_BLOCK) or (cmd_code == CmdCode.WRITE_BLOCK):
rc = parse_block(rx_data, status_len)
elif (cmd_code == CmdCode.ERASE_FLASH) or (cmd_code == CmdCode.WRITE_FLASH) \
or (cmd_code == CmdCode.READ_FLASH) or (cmd_code == CmdCode.LOAD_FLASH):
rc = parse_flash(rx_data, status_len, cmd_code)
if rc:
if (cmd_state == CmdState.WAIT) and (cmd_num_rx == cmd_num_tx):
cmd_state = CmdState.DONE
cmd_code_rx = cmd_code
emit_signal('command_done', self)
else:
emit_signal('parse_failed', self)

View File

@@ -1,15 +1,185 @@
class_name yems_boards extends Node
class EmsBoard:
enum {WAIT, WR_DEV_NUM_W, WRITE, WR_DEV_NUM_R, READ, READ_FLASH, WRITE_FLASH_BEGIN, \
LOAD_KEMS, WRITE_FLASH_END}
var id_board: int ## id платы
var in_devs: Dictionary ## Словарь с входными устройствами.
var out_devs: Dictionary ## Словарь с выходными устройствами.
var base_addr_isa: int ## Базовый адрес ячейки isa.
var ports_to_wr: Array ## Порты для записи
var in_tbl: Array
var out_tbl: Array
var online: bool ## статус платы
var ems_load: bool ## флаг загрузки платы
var state = WAIT ## текущее состояние платы ЭМС
var state_read = WAIT ## текущее состояние платы ЭМС
var cur_dev ## Текущее устройство
var cur_dev_num: = 0 ## Номер текущего устройства
var cur_dev_index: = 0 ## Индекс текущего устройства в списке
var dev_num_list: = Array() ## Список всех устройств
var need_next_dev: bool = false ## Нужно ли переходить к следующему устройству
var unit_ems ## Юнит эмс
var read_done: bool = false ## Флаг, что данные из ячейки прочитанны
func _init(id, base_addr, in_table, out_table):
signal upd_delay_offset(board, cur_dev)
signal upd_o_state(board, cur_dev)
func _init(id, base_addr, in_table, out_table, u):
id_board = id
in_tbl = in_table
out_tbl = out_table
base_addr_isa = base_addr
unit_ems = u
for i in range(4):
ports_to_wr.append(base_addr_isa + 4 + i * 2) # Заполнение списка портами для записи
dev_num_list = in_tbl + out_tbl
func set_status(status):
var offset = yemsconsts.STATUS_OFFSET[id_board]
var bit_online = 0 + id_board
var bit_load = 3 + id_board
online = (status[0] >> bit_online) & 1
ems_load = (status[0] >> bit_load) & 1
var in_blank = int(status[1 + offset] | (status[2 + offset] << 8) | (status[3 + offset] << 16) | \
(status[4 + offset] << 24) | (status[5 + offset] << 32))
var in_imp = int(status[7 + offset] | (status[8 + offset] << 8) | (status[9 + offset] << 16) | \
(status[10 + offset] << 24) | (status[11 + offset] << 32))
var out_blank = int(status[13 + offset] | (status[14 + offset] << 8) | (status[15 + offset] << 16) | \
(status[16 + offset] << 24) | (status[17 + offset] << 32))
var out_imp = int(status[19 + offset] | (status[20 + offset] << 8) | (status[21 + offset] << 16)| \
(status[22 + offset] << 24) | (status[23 + offset] << 32))
var out_kz = int(status[25 + offset] | (status[26 + offset] << 8))
if id_board > 0:
out_kz = 0
for in_dev in in_devs.values():
if (in_blank >> (in_dev.id - 1)) & 1:
in_dev.state = 1
elif (in_imp >> (in_dev.id - 1)) & 1:
in_dev.state = 2
else:
in_dev.state = 0
for out_dev in out_devs.values():
if (out_kz >> (out_dev.id - 1)) & 1:
out_dev.state = 3
elif (out_blank >> (out_dev.id - 1)) & 1:
out_dev.state = 1
elif (out_imp >> (out_dev.id - 1)) & 1:
out_dev.state = 2
else:
out_dev.state = 0
# Отправка команды на запись или чтение порта
func on_wr_device(dev_number):
print_debug([id_board, dev_number])
if (state == WR_DEV_NUM_W) or (state == WR_DEV_NUM_R):
unit_ems.send_isa(unit_ems.CmdCode.WRITE_ISA, [base_addr_isa + 2, dev_number])
elif state == WRITE:
var ports: Array = []
if not check_dev_number():
return
for port in cur_dev.ports_data:
if port in ports_to_wr:
var data = cur_dev.ports_data[port]
ports.append(port)
ports.append(data)
unit_ems.send_isa(unit_ems.CmdCode.WRITE_ISA, ports)
elif state == READ:
var ports: Array = []
for port in cur_dev.ports_data:
if port in ports_to_wr:
ports.append(port)
unit_ems.send_isa(unit_ems.CmdCode.READ_ISA, ports)
# Обработчик сообщения, о том, что команда выполнена (машина состояний)
func on_command_done(_yau_07):
if not check_dev_number():
return
if (unit_ems.cmd_code_rx == 1) and state == WR_DEV_NUM_W:
state = WRITE
cur_dev_num = unit_ems.isa_ports[base_addr_isa + 2]
if not check_dev_number():
return
on_wr_device(cur_dev_num)
elif (unit_ems.cmd_code_rx == 1) and state == WR_DEV_NUM_R:
state = READ
cur_dev_num = unit_ems.isa_ports[base_addr_isa + 2]
if not check_dev_number():
return
on_wr_device(cur_dev_num)
elif (state == READ) or (state == WRITE) \
and ((unit_ems.cmd_code_rx == 1) or (unit_ems.cmd_code_rx == 0)):
for key in unit_ems.isa_ports.keys():
if cur_dev.ports_data.has(key):
cur_dev.ports_data[key] = unit_ems.isa_ports[key]
cur_dev.set_delay_offset()
emit_signal('upd_delay_offset', self, cur_dev)
if cur_dev is yemsdevs.OutDev: # Если это выход, заполняем комбобоксы и чекбатоны
cur_dev.set_mode()
cur_dev.set_btns_state()
emit_signal('upd_o_state', self, cur_dev)
if need_next_dev: # Если нужно вычитать все устройства, выбираем следующее
cur_dev_index += 1
if cur_dev_index < len(dev_num_list):
cur_dev_num = dev_num_list[cur_dev_index][0]
if state == READ:
state = WR_DEV_NUM_R
on_wr_device(cur_dev_num)
else:
state = WR_DEV_NUM_W
on_wr_device(cur_dev_num)
else: # Пробег закончен, выбираем последнее устройство
state = WAIT
state_read = WAIT
read_done = true
cur_dev_index -= 1
need_next_dev = false
else:
state = WAIT
elif (state == READ_FLASH) and (unit_ems.cmd_code_rx == 51):
pass
#read_flash()
elif (state == WRITE_FLASH_BEGIN) and (unit_ems.cmd_code_rx == 49):
pass
#write_flash()
#emit_signal('write_msg', 'Произведено чтение из ПЗУ ячейки ЯУ-07')
elif (state == LOAD_KEMS) and (unit_ems.cmd_code_rx == 52):
pass
#start_rw_kems(true)
elif (state == WRITE_FLASH_END) and (unit_ems.cmd_code_rx == 50):
pass
#load_flash()
#emit_signal('write_msg', 'Произведена запись в ПЗУ ячейки ЯУ-07')
# Выбор текущего устройства и проверка правильности его номера
func check_dev_number():
cur_dev = get_dev()
if not cur_dev:
state = WAIT
return false
return true
# Возвращает устройство по текущему номеру, если он есть в словарях
func get_dev():
if in_devs.has(cur_dev_num):
return in_devs[cur_dev_num]
elif out_devs.has(cur_dev_num):
return out_devs[cur_dev_num]
else:
return null
# Запуск чтения/записи данных из/в ячейки КЭМС
func start_rw_kems(read: bool):
cur_dev_index = 0
cur_dev_num = dev_num_list[cur_dev_index][0]
need_next_dev = true
if read:
state = WR_DEV_NUM_R
else:
state = WR_DEV_NUM_W
on_wr_device(cur_dev_num)

View File

@@ -1,5 +1,11 @@
class_name yerms_consts extends Node
const NUM_INPUT = 38
const NUM_OUTPUT = 38
const STATUS_OFFSET = { # Смещение статуса, ключ id платы
0: 0,
1: 26,
2: 52 }
## Таблица с данными для входов, первое значение - индекс устройства в ячейке КЭМС.
const INPUT_KEMS = [
@@ -65,40 +71,40 @@ const INPUT_EMS1 = [
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС.
const OUTPUT_EMS1 = [
[1 ,['СЗИ1 Л1','X31 : 11', '0.00', '0.00']],
[18,['СЗИ1 Л6','X31 : 14', '0.00', '0.00']],
[2 ,['СЗИ1 Л7','X31 : 17', '0.00', '0.00']],
[19,['СЗИ2 Л1','X32 : 11', '0.00', '0.00']],
[3 ,['СЗИ2 Л6','X32 : 14', '0.00', '0.00']],
[20,['СЗИ2 Л7','X32 : 17', '0.00', '0.00']],
[4 ,['СЗИ3 Л1','X33 : 11', '0.00', '0.00']],
[21,['СЗИ3 Л6','X33 : 14', '0.00', '0.00']],
[5 ,['СЗИ3 Л7','X33 : 17', '0.00', '0.00']],
[22,['СЗИ4 Л1','X34 : 11', '0.00', '0.00']],
[6 ,['СЗИ4 Л6','X34 : 14', '0.00', '0.00']],
[23,['СЗИ4 Л7','X34 : 17', '0.00', '0.00']],
[7 ,['СЗИ1 Л2','X38 : 11', '0.00', '0.00']],
[24,['СЗИ1 Л3','X38 : 14', '0.00', '0.00']],
[8 ,['СЗИ2 Л2','X39 : 11', '0.00', '0.00']],
[25,['СЗИ2 Л3','X39 : 14', '0.00', '0.00']],
[9 ,['СЗИ3 Л2','X40 : 11', '0.00', '0.00']],
[26,['СЗИ3 Л3','X40 : 14', '0.00', '0.00']],
[10,['СЗИ4 Л2','X41 : 11', '0.00', '0.00']],
[27,['СЗИ4 Л3','X41 : 14', '0.00', '0.00']],
[11,['СЗИ1 Л4','X42 : 11', '0.00', '0.00']],
[28,['СЗИ1 Л5','X42 : 14', '0.00', '0.00']],
[12,['СЗИ2 Л4','X43 : 11', '0.00', '0.00']],
[29,['СЗИ2 Л5','X43 : 14', '0.00', '0.00']],
[13,['СЗИ3 Л4','X44 : 11', '0.00', '0.00']],
[30,['СЗИ3 Л5','X44 : 14', '0.00', '0.00']],
[14,['СЗИ4 Л4','X45 : 11', '0.00', '0.00']],
[31,['СЗИ4 Л5','X45 : 14', '0.00', '0.00']],
[33,['УИЗП_МП №1', 'X29 : 8', '0.00', '0.00']],
[34,['УИЗП_МП №2', 'X29 : 9', '0.00', '0.00']],
[35,['Выход 35', 'X29 : 10', '0.00', '0.00']],
[36,['Выход 36', 'X29 : 11', '0.00', '0.00']],
[37,['Выход 37', 'X29 : 12', '0.00', '0.00']],
[38,['Выход 38', 'X29 : 13', '0.00', '0.00']],]
[47 ,['СЗИ1 Л1','X31 : 11', '0.00', '0.00']],
[64,['СЗИ1 Л6','X31 : 14', '0.00', '0.00']],
[48 ,['СЗИ1 Л7','X31 : 17', '0.00', '0.00']],
[65,['СЗИ2 Л1','X32 : 11', '0.00', '0.00']],
[49 ,['СЗИ2 Л6','X32 : 14', '0.00', '0.00']],
[66,['СЗИ2 Л7','X32 : 17', '0.00', '0.00']],
[50 ,['СЗИ3 Л1','X33 : 11', '0.00', '0.00']],
[67,['СЗИ3 Л6','X33 : 14', '0.00', '0.00']],
[51 ,['СЗИ3 Л7','X33 : 17', '0.00', '0.00']],
[68,['СЗИ4 Л1','X34 : 11', '0.00', '0.00']],
[52 ,['СЗИ4 Л6','X34 : 14', '0.00', '0.00']],
[69,['СЗИ4 Л7','X34 : 17', '0.00', '0.00']],
[53 ,['СЗИ1 Л2','X38 : 11', '0.00', '0.00']],
[70,['СЗИ1 Л3','X38 : 14', '0.00', '0.00']],
[54 ,['СЗИ2 Л2','X39 : 11', '0.00', '0.00']],
[71,['СЗИ2 Л3','X39 : 14', '0.00', '0.00']],
[55 ,['СЗИ3 Л2','X40 : 11', '0.00', '0.00']],
[72,['СЗИ3 Л3','X40 : 14', '0.00', '0.00']],
[56,['СЗИ4 Л2','X41 : 11', '0.00', '0.00']],
[73,['СЗИ4 Л3','X41 : 14', '0.00', '0.00']],
[57,['СЗИ1 Л4','X42 : 11', '0.00', '0.00']],
[74,['СЗИ1 Л5','X42 : 14', '0.00', '0.00']],
[58,['СЗИ2 Л4','X43 : 11', '0.00', '0.00']],
[76,['СЗИ2 Л5','X43 : 14', '0.00', '0.00']],
[59,['СЗИ3 Л4','X44 : 11', '0.00', '0.00']],
[76,['СЗИ3 Л5','X44 : 14', '0.00', '0.00']],
[60,['СЗИ4 Л4','X45 : 11', '0.00', '0.00']],
[77,['СЗИ4 Л5','X45 : 14', '0.00', '0.00']],
[79,['УИЗП_МП №1', 'X29 : 8', '0.00', '0.00']],
[80,['УИЗП_МП №2', 'X29 : 9', '0.00', '0.00']],
[81,['Выход 35', 'X29 : 10', '0.00', '0.00']],
[82,['Выход 36', 'X29 : 11', '0.00', '0.00']],
[83,['Выход 37', 'X29 : 12', '0.00', '0.00']],
[84,['Выход 38', 'X29 : 13', '0.00', '0.00']],]
## Таблица с данными для входов, первое значение - индекс устройства в ячейке КЭМС.
@@ -141,18 +147,18 @@ const INPUT_EMS2 = [
## Таблица с данными для выходов, первое значение - индекс устройства в ячейке КЭМС.
const OUTPUT_EMS2 = [
[1,['БИ РТР №1','X47 : 2', '0.00', '0.00']],
[19,['БИ РТР №2','X47 : 5', '0.00', '0.00']],
[2,['БИ РТР №3','X47 : 8', '0.00', '0.00']],
[19,['БИ РТР №4','X47 : 11', '0.00', '0.00']],
[3,['СИ В Лб', 'Х49 : 21', '0.00', '0.00']],
[20,['СИ В ПрБ', 'Х49 : 19', '0.00', '0.00']],
[4,['СИ Г Лб', 'Х49 : 28', '0.00', '0.00']],
[21,['СИ Г ПрБ', 'Х49 : 30', '0.00', '0.00']],
[5,['СИ Д Лб', 'Х49 : 13', '0.00', '0.00']],
[22,['СИ Д ПрБ', 'Х49 : 11', '0.00', '0.00']],
[6,['СИ Е Лб', 'Х49 : 26', '0.00', '0.00']],
[23,['СИ Е ПрБ', 'Х49 : 35', '0.00', '0.00']],
[33,['УИЗП_МП №3', 'X30 : 8', '0.00', '0.00']],
[34,['УИЗП_МП №4', 'X30 : 9', '0.00', '0.00']],
[35,['УИЗП_МП №5', 'X30 : 10', '0.00', '0.00']],]
[47,['БИ РТР №1','X47 : 2', '0.00', '0.00']],
[64,['БИ РТР №2','X47 : 5', '0.00', '0.00']],
[48,['БИ РТР №3','X47 : 8', '0.00', '0.00']],
[65,['БИ РТР №4','X47 : 11', '0.00', '0.00']],
[49,['СИ В Лб', 'Х49 : 21', '0.00', '0.00']],
[66,['СИ В ПрБ', 'Х49 : 19', '0.00', '0.00']],
[50,['СИ Г Лб', 'Х49 : 28', '0.00', '0.00']],
[67,['СИ Г ПрБ', 'Х49 : 30', '0.00', '0.00']],
[51,['СИ Д Лб', 'Х49 : 13', '0.00', '0.00']],
[68,['СИ Д ПрБ', 'Х49 : 11', '0.00', '0.00']],
[52,['СИ Е Лб', 'Х49 : 26', '0.00', '0.00']],
[69,['СИ Е ПрБ', 'Х49 : 35', '0.00', '0.00']],
[79,['УИЗП_МП №3', 'X30 : 8', '0.00', '0.00']],
[80,['УИЗП_МП №4', 'X30 : 9', '0.00', '0.00']],
[81,['УИЗП_МП №5', 'X30 : 10', '0.00', '0.00']],]

View File

@@ -16,23 +16,71 @@ class InDev:
var board: String ## Плата в которой находится устройство.
var isa_addr: int ## Адрес устройства на шине isa
func _init(dev_id : int, params : Array, row_id : int):
func _init(dev_id : int, params : Array, row_id : int, base_addr: int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
isa_addr = base_addr
ports_data[isa_addr + 4] = 0xFFFF
ports_data[isa_addr + 6] = 0xFFFF
ports_data[isa_addr + 8] = 0xFFFF
ports_data[isa_addr + 10] = 0xFFFF
func set_delay_offset():
delay = float(ports_data[isa_addr + 10] & 0x003F)/10
offset = float((ports_data[isa_addr + 10] >> 6) & 0x01FF)/10
func set_delay(val):
delay = val
var bin_val = int(val * 10)
ports_data[isa_addr + 10] = tools.set_bits(ports_data[isa_addr + 10], bin_val, 0x003F)
func set_offset(val):
offset = val
var bin_val = int(val * 10)
ports_data[isa_addr + 10] = tools.set_bits(ports_data[isa_addr + 10], (bin_val << 6), 0x7FC0)
class OutDev extends InDev:
var mode: String ## Режим работы выхода.
var mode: int ## Режим работы выхода.
var btns_state: = Dictionary()
func _init(dev_id : int, params : Array, row_id : int):
id = dev_id
dev_name = String(params[0])
connector = String(params[1])
delay = float(params[2])
offset = float(params[3])
tbl_row_id = row_id
mode = 'Работа'
func set_default_mode(): mode = 0
func set_mode():
if (ports_data[isa_addr + 8] >> 13) & 1:
mode = 1
elif (ports_data[isa_addr + 8] >> 14) & 1:
mode = 2
elif (ports_data[isa_addr + 8] >> 15) & 1:
mode = 3
else:
mode = 0
func set_btns_state():
var data = ports_data[isa_addr + 4] | (ports_data[isa_addr + 6] << 16) | ((ports_data[isa_addr + 8] & 0x3f) << 32)
for i in range(yemsconsts.NUM_INPUT):
btns_state[i+1] = bool((data >> i) & 1)
func set_dot(i_dev):
if btns_state.has(i_dev):
btns_state[i_dev] = not btns_state[i_dev]
var data = 0
for i in range(yemsconsts.NUM_INPUT):
data = data | (int(btns_state[i+1]) << i)
ports_data[isa_addr + 4] = data & 0xffff
ports_data[isa_addr + 6] = (data >> 16) & 0xffff
ports_data[isa_addr + 8] = tools.set_bits(ports_data[isa_addr + 8], ((data >> 32) & 0x3f), 0x003F)
func set_sw_mode(o_state):
mode = o_state
if mode == 0:
ports_data[isa_addr + 8] = tools.set_bits(ports_data[isa_addr + 8], 0x0000, 0xE000)
elif mode == 1:
ports_data[isa_addr + 8] = tools.set_bits(ports_data[isa_addr + 8], 0x2000, 0xE000)
elif mode == 2:
ports_data[isa_addr + 8] = tools.set_bits(ports_data[isa_addr + 8], 0x4000, 0xE000)
elif mode == 3:
ports_data[isa_addr + 8] = tools.set_bits(ports_data[isa_addr + 8], 0x8000, 0xE000)

View File

@@ -3,7 +3,7 @@ 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.01425; /* Относительное расстояние на котором выполняется сглаживание краёв */
const float dsr = 12.125;
const float dsr = 12.125;
const vec2 center = vec2(0.5, 0.5); /* Центр должен быть в (0.5, 0.5), но это не так */
const float radius = 0.075 - ds * 2.0; /* Радиус должен быть 0.5, но это не так */
@@ -60,7 +60,7 @@ vec2 rotateUVmatrinx(vec2 uv, vec2 pivot, float rotation)
void vertex()
{
{
float dir = 0.0;
dir += speed * TIME;
VERTEX = rotateUVmatrinx(VERTEX, center, radians(dir));
@@ -70,7 +70,7 @@ void vertex()
void fragment()
{
ivec2 isz = textureSize(TEXTURE, 0);
vec2 uv = UV * vec2(float(isz.x), float(isz.y)); // координаты текущей точки в пикселях
COLOR = vec4(0, 0, 0, 0.0); //texture(TEXTURE, UV); // Цвет текущей точки