Доработан контроль
This commit is contained in:
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/DSEG7Classic-Regular.ttf-32df8fc6f2e5584d5a5b
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
|
||||
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/DejaVuSans.ttf-b4085dde282b5d503d6a56e258b526
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
|
||||
@@ -15,6 +15,7 @@ dest_files=["res://.godot/imported/DejaVuSansCondensed.ttf-7a8251b7291db131ffa4e
|
||||
Rendering=null
|
||||
antialiasing=1
|
||||
generate_mipmaps=false
|
||||
disable_embedded_bitmaps=true
|
||||
multichannel_signed_distance_field=false
|
||||
msdf_pixel_range=8
|
||||
msdf_size=48
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
[gd_scene load_steps=4 format=3 uid="uid://dwxn2puh462nl"]
|
||||
|
||||
[ext_resource type="Script" path="res://scenes/контроль/прибор.gd" id="1_2qyst"]
|
||||
[ext_resource type="Script" path="res://scenes/pribor-uf/pribor_uf.gd" id="1_7gtpa"]
|
||||
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="2_ho0da"]
|
||||
[ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_dp78y"]
|
||||
|
||||
[node name="pribor_uf" type="Control"]
|
||||
layout_mode = 3
|
||||
anchors_preset = 0
|
||||
script = ExtResource("1_2qyst")
|
||||
script = ExtResource("1_7gtpa")
|
||||
|
||||
[node name="ref_uf" type="NinePatchRect" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 98.0
|
||||
offset_left = 187.0
|
||||
offset_top = 247.0
|
||||
offset_right = 708.0
|
||||
offset_bottom = 1121.0
|
||||
offset_bottom = 955.0
|
||||
texture = ExtResource("2_ho0da")
|
||||
patch_margin_left = 16
|
||||
patch_margin_top = 16
|
||||
@@ -23,17 +23,17 @@ patch_margin_bottom = 16
|
||||
|
||||
[node name="ref_bu1" type="NinePatchRect" parent="ref_uf"]
|
||||
layout_mode = 0
|
||||
offset_left = 282.0
|
||||
offset_top = 138.0
|
||||
offset_right = 591.0
|
||||
offset_bottom = 468.0
|
||||
offset_left = 199.0
|
||||
offset_top = 14.0
|
||||
offset_right = 508.0
|
||||
offset_bottom = 344.0
|
||||
texture = ExtResource("2_ho0da")
|
||||
patch_margin_left = 16
|
||||
patch_margin_top = 16
|
||||
patch_margin_right = 16
|
||||
patch_margin_bottom = 16
|
||||
|
||||
[node name="ref_A13" parent="ref_uf/ref_bu1" instance=ExtResource("3_dp78y")]
|
||||
[node name="ref_A13_MKEG" parent="ref_uf/ref_bu1" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 7.0
|
||||
offset_top = 60.0
|
||||
offset_right = 59.0
|
||||
@@ -42,21 +42,14 @@ self_size = Vector2i(52, 262)
|
||||
fname = "MKEG/C"
|
||||
rname = "A13"
|
||||
|
||||
[node name="ref_A" parent="ref_uf/ref_bu1" instance=ExtResource("3_dp78y")]
|
||||
[node name="ref_A8_BU" parent="ref_uf/ref_bu1" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 59.0
|
||||
offset_top = 60.0
|
||||
offset_right = 302.0
|
||||
offset_bottom = 322.0
|
||||
self_size = Vector2i(243, 262)
|
||||
fname = "ВК-110"
|
||||
|
||||
[node name="А8" type="Label" parent="ref_uf/ref_bu1"]
|
||||
layout_mode = 0
|
||||
offset_left = 21.0
|
||||
offset_top = 12.0
|
||||
offset_right = 39.0
|
||||
offset_bottom = 31.0
|
||||
text = "А8"
|
||||
rname = "A8"
|
||||
|
||||
[node name="А1" type="Label" parent="ref_uf/ref_bu1"]
|
||||
layout_mode = 0
|
||||
@@ -68,83 +61,74 @@ text = "БУ-1"
|
||||
|
||||
[node name="ref_kassetav13" type="NinePatchRect" parent="ref_uf"]
|
||||
layout_mode = 0
|
||||
offset_left = 12.0
|
||||
offset_top = 513.0
|
||||
offset_right = 601.0
|
||||
offset_bottom = 852.0
|
||||
offset_left = 11.0
|
||||
offset_top = 353.0
|
||||
offset_right = 509.0
|
||||
offset_bottom = 692.0
|
||||
texture = ExtResource("2_ho0da")
|
||||
patch_margin_left = 16
|
||||
patch_margin_top = 16
|
||||
patch_margin_right = 16
|
||||
patch_margin_bottom = 16
|
||||
|
||||
[node name="ref_A18" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 6.0
|
||||
[node name="ref_A9_ESW" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 62.0
|
||||
offset_top = 65.0
|
||||
offset_right = 165.0
|
||||
offset_right = 170.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(159, 260)
|
||||
self_size = Vector2i(108, 260)
|
||||
fname = "ESW-6U16TP"
|
||||
rname = "A18"
|
||||
rname = "A9"
|
||||
|
||||
[node name="ref_A7" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 166.0
|
||||
[node name="ref_A7_YAU07" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 438.0
|
||||
offset_top = 65.0
|
||||
offset_right = 218.0
|
||||
offset_right = 490.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(52, 260)
|
||||
fname = "ЯУ-07Б"
|
||||
rname = "A7"
|
||||
|
||||
[node name="ref_A2" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 218.0
|
||||
[node name="ref_A4_KEMS" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 279.0
|
||||
offset_top = 65.0
|
||||
offset_right = 270.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(52, 260)
|
||||
fname = "КЭМС-Б"
|
||||
rname = "A2"
|
||||
|
||||
[node name="ref_A4" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 269.0
|
||||
offset_top = 65.0
|
||||
offset_right = 321.0
|
||||
offset_right = 331.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(52, 260)
|
||||
fname = "КЭМС-Б1"
|
||||
rname = "A4"
|
||||
|
||||
[node name="ref_A5" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 322.0
|
||||
[node name="ref_A5_EMS" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 225.0
|
||||
offset_top = 65.0
|
||||
offset_right = 374.0
|
||||
offset_right = 277.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(52, 260)
|
||||
fname = "ЭМС-Б"
|
||||
rname = "A5"
|
||||
|
||||
[node name="ref_A6" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 374.0
|
||||
[node name="ref_A6_EMS" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 171.0
|
||||
offset_top = 65.0
|
||||
offset_right = 426.0
|
||||
offset_right = 223.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(52, 260)
|
||||
fname = "ЭМС-Б"
|
||||
rname = "A6"
|
||||
|
||||
[node name="ref_A3" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 427.0
|
||||
[node name="ref_A3_IP5B" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 332.0
|
||||
offset_top = 65.0
|
||||
offset_right = 532.0
|
||||
offset_right = 437.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(105, 260)
|
||||
fname = "ИП-220-5Б"
|
||||
rname = "A3"
|
||||
|
||||
[node name="ref_A8" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 531.0
|
||||
[node name="ref_A12_IP27B" parent="ref_uf/ref_kassetav13" instance=ExtResource("3_dp78y")]
|
||||
offset_left = 9.0
|
||||
offset_top = 65.0
|
||||
offset_right = 582.0
|
||||
offset_right = 60.0
|
||||
offset_bottom = 325.0
|
||||
self_size = Vector2i(51, 260)
|
||||
fname = "ИП220-27Б"
|
||||
@@ -168,7 +152,7 @@ text = "Кассета В-13"
|
||||
|
||||
[node name="lbl_header" type="Label" parent="."]
|
||||
layout_mode = 0
|
||||
offset_left = 105.0
|
||||
offset_left = 199.0
|
||||
offset_top = 225.0
|
||||
offset_right = 704.0
|
||||
offset_bottom = 251.0
|
||||
@@ -177,3 +161,16 @@ text = "Контроль исправности прибора УФ
|
||||
"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
[node name="lbl_header2" type="Label" parent="."]
|
||||
visible = false
|
||||
layout_mode = 0
|
||||
offset_left = 199.0
|
||||
offset_top = 974.0
|
||||
offset_right = 704.0
|
||||
offset_bottom = 1000.0
|
||||
theme_override_font_sizes/font_size = 22
|
||||
text = "Прибор не исправен
|
||||
"
|
||||
horizontal_alignment = 1
|
||||
vertical_alignment = 1
|
||||
|
||||
@@ -1,14 +1,106 @@
|
||||
extends "res://scenes/контроль/прибор.gd"
|
||||
|
||||
# Called when the node enters the scene tree for the first time.
|
||||
enum STATE_VAL {
|
||||
NONE = 0,
|
||||
GOOD = 1,
|
||||
ERROR = 2 }
|
||||
|
||||
var timer = Timer.new()
|
||||
|
||||
var DEV_LIST = ['00:1f.6', '07:00.0', '08:00.0', '0b:00.0']
|
||||
var USB_TRACKERBALL = '046d:c31c'
|
||||
var REVFF = '(rev ff)'
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
var unit_key = settings.get_unit_key('уарэп-эмс')
|
||||
var unit_uf = network.units[unit_key]
|
||||
unit_uf.connect('data_received', on_data_received.bind(unit_uf))
|
||||
|
||||
func on_data_received(data, unit_uf):
|
||||
print_debug(data)
|
||||
var unit_key_5p28 = settings.get_unit_key('уарэп-5п28')
|
||||
var unit_5p28 = network.units[unit_key_5p28]
|
||||
|
||||
# Called every frame. 'delta' is the elapsed time since the previous frame.
|
||||
func _process(delta: float) -> void:
|
||||
pass
|
||||
self.add_child(timer)
|
||||
timer.connect('timeout', Callable(self, 'on_timer').bind(unit_uf, unit_5p28))
|
||||
timer.start(1)
|
||||
|
||||
|
||||
func on_timer(unit_uf, unit_5p28):
|
||||
Control_VK() # проверка трекбола и pci
|
||||
if unit_5p28.online: # проверка внешнего коммутатора
|
||||
$ref_uf/ref_bu1/ref_A13_MKEG.state = STATE_VAL.GOOD
|
||||
else:
|
||||
$ref_uf/ref_bu1/ref_A13_MKEG.state = STATE_VAL.NONE
|
||||
|
||||
if unit_uf.online: # проверка ЯУ, внутреннего коммутатора и ИП-5Б
|
||||
$ref_uf/ref_kassetav13/ref_A7_YAU07.state = STATE_VAL.GOOD
|
||||
$ref_uf/ref_kassetav13/ref_A3_IP5B.state = STATE_VAL.GOOD
|
||||
$ref_uf/ref_kassetav13/ref_A9_ESW.state = STATE_VAL.GOOD
|
||||
Control_EMS(unit_uf.status) # проверка ЭМС ячеек
|
||||
else:
|
||||
$ref_uf/ref_kassetav13/ref_A7_YAU07.state = STATE_VAL.ERROR
|
||||
$ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.NONE
|
||||
$ref_uf/ref_kassetav13/ref_A5_EMS.state = STATE_VAL.NONE
|
||||
$ref_uf/ref_kassetav13/ref_A6_EMS.state = STATE_VAL.NONE
|
||||
$ref_uf/ref_kassetav13/ref_A3_IP5B.state = STATE_VAL.NONE
|
||||
$ref_uf/ref_kassetav13/ref_A9_ESW.state = STATE_VAL.NONE
|
||||
$ref_uf/ref_kassetav13/ref_A12_IP27B.state = STATE_VAL.NONE
|
||||
status_uf() # отслеживание состояния прибора
|
||||
|
||||
func Control_VK() -> void:
|
||||
var out_usb_str = ''
|
||||
var out_pci_str = ''
|
||||
var out_usb = []
|
||||
var out_pci = []
|
||||
|
||||
OS.execute('lsusb', [], out_usb)
|
||||
for element in out_usb:
|
||||
out_usb_str += element
|
||||
|
||||
OS.execute('lspci', [], out_pci)
|
||||
for element in out_pci:
|
||||
out_pci_str += element
|
||||
|
||||
out_usb_str = out_usb_str.split("\n")
|
||||
out_pci_str = out_pci_str.split("\n")
|
||||
|
||||
var i: int = 0
|
||||
|
||||
for string in out_usb_str:
|
||||
if USB_TRACKERBALL in string:
|
||||
i += 1
|
||||
break
|
||||
for string in out_pci_str:
|
||||
for item in DEV_LIST:
|
||||
if item in string:
|
||||
i += 1
|
||||
if REVFF in string:
|
||||
i -= 1
|
||||
break
|
||||
|
||||
if i == (len(DEV_LIST) + 1):
|
||||
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.GOOD
|
||||
else:
|
||||
$ref_uf/ref_bu1/ref_A8_BU.state = STATE_VAL.ERROR
|
||||
|
||||
|
||||
func Control_EMS(status:Array) -> void:
|
||||
$ref_uf/ref_kassetav13/ref_A4_KEMS.state = STATE_VAL.GOOD if ((status[0] >> 0) & 1) and ((status[0] >> 3) & 1) else STATE_VAL.ERROR
|
||||
$ref_uf/ref_kassetav13/ref_A5_EMS.state = STATE_VAL.GOOD if ((status[0] >> 1) & 1) and ((status[0] >> 4) & 1) else STATE_VAL.ERROR
|
||||
$ref_uf/ref_kassetav13/ref_A6_EMS.state = STATE_VAL.GOOD if ((status[0] >> 2) & 1) and ((status[0] >> 5) & 1) else STATE_VAL.ERROR
|
||||
$ref_uf/ref_kassetav13/ref_A12_IP27B.state = STATE_VAL.GOOD if ((status[2] >> 6) & 1) else STATE_VAL.ERROR
|
||||
|
||||
|
||||
func status_uf() -> void:
|
||||
var status_bu:int = $ref_uf/ref_bu1/ref_A8_BU.state
|
||||
var status_yay:int = $ref_uf/ref_kassetav13/ref_A7_YAU07.state
|
||||
var status_kems:int = $ref_uf/ref_kassetav13/ref_A4_KEMS.state
|
||||
var status_ems0:int = $ref_uf/ref_kassetav13/ref_A5_EMS.state
|
||||
var status_ems1:int = $ref_uf/ref_kassetav13/ref_A6_EMS.state
|
||||
|
||||
if (status_yay == 1) and (status_bu == 1) and (status_kems == 1) and (status_ems0 == 1) and (status_ems1 == 1):
|
||||
$lbl_header2.text = "Прибор исправен"
|
||||
$lbl_header2.modulate = Color(0,1,0,1)
|
||||
else:
|
||||
$lbl_header2.text = "Прибор не исправен"
|
||||
$lbl_header2.modulate = Color(1,0,0,1)
|
||||
$lbl_header2.visible = true
|
||||
|
||||
@@ -26,10 +26,10 @@ var timer = Timer.new()
|
||||
|
||||
|
||||
class StackItem:
|
||||
var addr: = 0
|
||||
var data = null
|
||||
func _init(a: int, d): addr = a; data = d
|
||||
func _to_string() -> String: return '%s: %s' % [addr, data]
|
||||
var addr: = 0
|
||||
var data = null
|
||||
func _init(a: int, d): addr = a; data = d
|
||||
func _to_string() -> String: return '%s: %s' % [addr, data]
|
||||
|
||||
|
||||
func on_data_received(_data: PackedByteArray): pass
|
||||
@@ -37,147 +37,147 @@ func on_data_received(_data: PackedByteArray): pass
|
||||
|
||||
## Обработчик таймера
|
||||
func _on_timeout(unit_sch3) -> void:
|
||||
if write_stack.size():
|
||||
var ad = write_stack.pop_front()
|
||||
if not unit_sch3.write(ad.addr, ad.data):
|
||||
write_stack.push_back(ad)
|
||||
if (read_step == 0) and (input_stack.size() == 0):
|
||||
var ad = StackItem.new(base_input_address, regs_input_count)
|
||||
input_stack.push_back(ad)
|
||||
elif (read_step == 1) and (holding_stack.size() == 0):
|
||||
var ad = StackItem.new(base_holding_address, regs_holding_count)
|
||||
holding_stack.push_back(ad)
|
||||
if input_stack.size():
|
||||
var ad = input_stack.pop_front()
|
||||
if not unit_sch3.read_input(ad.addr, ad.data):
|
||||
input_stack.push_back(ad)
|
||||
if holding_stack.size():
|
||||
var ad = holding_stack.pop_front()
|
||||
if not unit_sch3.read_holding(ad.addr, ad.data):
|
||||
holding_stack.push_back(ad)
|
||||
read_step += 1
|
||||
read_step %= 2
|
||||
if write_stack.size():
|
||||
var ad = write_stack.pop_front()
|
||||
if not unit_sch3.write(ad.addr, ad.data):
|
||||
write_stack.push_back(ad)
|
||||
if (read_step == 0) and (input_stack.size() == 0):
|
||||
var ad = StackItem.new(base_input_address, regs_input_count)
|
||||
input_stack.push_back(ad)
|
||||
elif (read_step == 1) and (holding_stack.size() == 0):
|
||||
var ad = StackItem.new(base_holding_address, regs_holding_count)
|
||||
holding_stack.push_back(ad)
|
||||
if input_stack.size():
|
||||
var ad = input_stack.pop_front()
|
||||
if not unit_sch3.read_input(ad.addr, ad.data):
|
||||
input_stack.push_back(ad)
|
||||
if holding_stack.size():
|
||||
var ad = holding_stack.pop_front()
|
||||
if not unit_sch3.read_holding(ad.addr, ad.data):
|
||||
holding_stack.push_back(ad)
|
||||
read_step += 1
|
||||
read_step %= 2
|
||||
|
||||
|
||||
## Вызывается при изменении состояния выключателя[br]
|
||||
## [param val] - Состояние выключателя[br]
|
||||
## [param meta] - Адреса регистров и индексы битов назначенных выключателю[br]
|
||||
func on_toggled_switch(val: bool, meta: Array):
|
||||
var on_addr = meta[0]
|
||||
var on_bit = meta[1]
|
||||
var off_addr = meta[2]
|
||||
var off_bit = meta[3]
|
||||
if regs_holding.has(on_addr) and regs_holding.has(off_addr):
|
||||
regs_holding[on_addr] = tools.set_bit(regs_holding[on_addr], on_bit, val)
|
||||
regs_holding[off_addr] = tools.set_bit(regs_holding[off_addr], off_bit, not val)
|
||||
push_write_holding()
|
||||
var on_addr = meta[0]
|
||||
var on_bit = meta[1]
|
||||
var off_addr = meta[2]
|
||||
var off_bit = meta[3]
|
||||
if regs_holding.has(on_addr) and regs_holding.has(off_addr):
|
||||
regs_holding[on_addr] = tools.set_bit(regs_holding[on_addr], on_bit, val)
|
||||
regs_holding[off_addr] = tools.set_bit(regs_holding[off_addr], off_bit, not val)
|
||||
push_write_holding()
|
||||
|
||||
|
||||
## Заносит в очередь команду чтения регистров хранения
|
||||
func push_write_holding():
|
||||
var regs_data: = []
|
||||
var keys = regs_holding.keys()
|
||||
keys.sort() # Ключи в словаре хранятся не упорядочено
|
||||
for addr in keys:
|
||||
regs_data.append(regs_holding[addr])
|
||||
write_stack.push_back(StackItem.new(keys[0], regs_data))
|
||||
var regs_data: = []
|
||||
var keys = regs_holding.keys()
|
||||
keys.sort() # Ключи в словаре хранятся не упорядочено
|
||||
for addr in keys:
|
||||
regs_data.append(regs_holding[addr])
|
||||
write_stack.push_back(StackItem.new(keys[0], regs_data))
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if Engine.is_editor_hint(): return
|
||||
var unit_key = settings.get_unit_key(unit_name)
|
||||
var unit_sch3 = network.units[unit_key]
|
||||
unit_sch3.mb_addr = modbus_address
|
||||
var items = get_tree().get_nodes_in_group('bits_items_switch')
|
||||
for item in items:
|
||||
var meta = item.get_meta('bits')
|
||||
item.connect('toggled', on_toggled_switch.bind(meta))
|
||||
item.disabled = true
|
||||
unit_sch3.connect('resp_input', on_resp_input)
|
||||
unit_sch3.connect('resp_holding', on_resp_holding)
|
||||
unit_sch3.connect('command_fail', on_command_fail)
|
||||
timer.connect('timeout', _on_timeout.bind(unit_sch3))
|
||||
add_child(timer)
|
||||
timer.start(request_period)
|
||||
if Engine.is_editor_hint(): return
|
||||
var unit_key = settings.get_unit_key(unit_name)
|
||||
var unit_sch3 = network.units[unit_key]
|
||||
unit_sch3.mb_addr = modbus_address
|
||||
var items = get_tree().get_nodes_in_group('bits_items_switch')
|
||||
for item in items:
|
||||
var meta = item.get_meta('bits')
|
||||
item.connect('toggled', on_toggled_switch.bind(meta))
|
||||
item.disabled = true
|
||||
unit_sch3.connect('resp_input', on_resp_input)
|
||||
unit_sch3.connect('resp_holding', on_resp_holding)
|
||||
unit_sch3.connect('command_fail', on_command_fail)
|
||||
timer.connect('timeout', _on_timeout.bind(unit_sch3))
|
||||
add_child(timer)
|
||||
timer.start(request_period)
|
||||
|
||||
|
||||
func on_command_fail(unit_sch3):
|
||||
unit_sch3.cmd_state = unit.Unit.CmdState.DONE
|
||||
timer.stop()
|
||||
unit_sch3.cmd_state = unit.Unit.CmdState.DONE
|
||||
timer.stop()
|
||||
|
||||
|
||||
## Вызывается, когда состояния прибора Щ3 "на связи" изменяется[br]
|
||||
## [param unit_sch3] - Экземпляр представления прибора Щ3
|
||||
func on_line_changed(unit_sch3: sch_3.Sch3):
|
||||
for item in get_tree().get_nodes_in_group('bits_items_good'):
|
||||
item.texture = textures[STATE_VAL.NONE]
|
||||
if not unit_sch3.online:
|
||||
for item in get_tree().get_nodes_in_group('bits_items_switch'):
|
||||
item.disabled = true
|
||||
regs_holding.clear()
|
||||
regs_input.clear()
|
||||
write_stack.clear()
|
||||
input_stack.clear()
|
||||
holding_stack.clear()
|
||||
switches_sync = false
|
||||
$margin/vbox/grid1/lbl_freq.text = '<нет данных>'
|
||||
$margin/vbox/grid1/state_freq.texture = textures[STATE_VAL.NONE]
|
||||
else:
|
||||
timer.start(request_period)
|
||||
for item in get_tree().get_nodes_in_group('bits_items_good'):
|
||||
item.texture = textures[STATE_VAL.NONE]
|
||||
if not unit_sch3.online:
|
||||
for item in get_tree().get_nodes_in_group('bits_items_switch'):
|
||||
item.disabled = true
|
||||
regs_holding.clear()
|
||||
regs_input.clear()
|
||||
write_stack.clear()
|
||||
input_stack.clear()
|
||||
holding_stack.clear()
|
||||
switches_sync = false
|
||||
$margin/vbox/grid1/lbl_freq.text = '<нет данных>'
|
||||
$margin/vbox/grid1/state_freq.texture = textures[STATE_VAL.NONE]
|
||||
else:
|
||||
timer.start(request_period)
|
||||
|
||||
## Вызывается по сигналу "приняты данные чтения регистров хранения"[br]
|
||||
## [param base_addr] - Начальный адрес регистров.[br]
|
||||
## [param data] - Массив значений прочитанных из регистров.
|
||||
func on_resp_holding(base_addr: int, data: Array):
|
||||
if (base_addr != base_holding_address) or (data.size() < regs_holding_count):
|
||||
return
|
||||
for i in data.size():
|
||||
regs_holding[base_addr + i] = data[i]
|
||||
# Разрешить работу выключателей только когда прочитано их реальное состояние
|
||||
if not switches_sync:
|
||||
switches_sync = true
|
||||
for item in get_tree().get_nodes_in_group('bits_items_switch'):
|
||||
var bits = 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 val0: bool = regs_holding[byte0] & (1 << bit0) > 0
|
||||
item.button_pressed = val0
|
||||
item.disabled = false
|
||||
regs_holding[byte1] = tools.set_bit(regs_holding[byte1], bit1, not val0)
|
||||
push_write_holding()
|
||||
if (base_addr != base_holding_address) or (data.size() < regs_holding_count):
|
||||
return
|
||||
for i in data.size():
|
||||
regs_holding[base_addr + i] = data[i]
|
||||
# Разрешить работу выключателей только когда прочитано их реальное состояние
|
||||
if not switches_sync:
|
||||
switches_sync = true
|
||||
for item in get_tree().get_nodes_in_group('bits_items_switch'):
|
||||
var bits = 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 val0: bool = regs_holding[byte0] & (1 << bit0) > 0
|
||||
item.button_pressed = val0
|
||||
item.disabled = false
|
||||
regs_holding[byte1] = tools.set_bit(regs_holding[byte1], bit1, not val0)
|
||||
push_write_holding()
|
||||
|
||||
|
||||
## Вызывается по сигналу "приняты данные чтения регистров входов".[br]
|
||||
## [param base_addr] - Начальный адрес регистров.[br]
|
||||
## [param data] - Массив значений прочитанных из регистров.[br]
|
||||
func on_resp_input(base_addr: int, data: Array):
|
||||
if (base_addr != base_input_address) or (data.size() < regs_input_count):
|
||||
return
|
||||
# "Для контроля состояния управляющего элемента подачи электроэнергии на приборы ..."
|
||||
# "Для контроля подачи электроэнергии на приборы ..."
|
||||
# Таблицы 3.13 и 3.14. Ecли значения соответствующих битов в этих
|
||||
# регистрах равны, то "исправно".
|
||||
var items = get_tree().get_nodes_in_group('bits_items_good')
|
||||
for i in data.size():
|
||||
regs_input[base_addr + i] = data[i]
|
||||
# Таблица 3.15, Регистр PowerState
|
||||
$margin/vbox/grid1/lbl_freq.text = '%d' % (regs_input[4] & 0x1ff)
|
||||
$margin/vbox/grid1/state_freq.texture \
|
||||
= textures[STATE_VAL.GOOD] if regs_input[4] & (1 << 15) \
|
||||
else textures[STATE_VAL.ERROR]
|
||||
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
|
||||
if (base_addr != base_input_address) or (data.size() < regs_input_count):
|
||||
return
|
||||
# "Для контроля состояния управляющего элемента подачи электроэнергии на приборы ..."
|
||||
# "Для контроля подачи электроэнергии на приборы ..."
|
||||
# Таблицы 3.13 и 3.14. Ecли значения соответствующих битов в этих
|
||||
# регистрах равны, то "исправно".
|
||||
var items = get_tree().get_nodes_in_group('bits_items_good')
|
||||
for i in data.size():
|
||||
regs_input[base_addr + i] = data[i]
|
||||
# Таблица 3.15, Регистр PowerState
|
||||
$margin/vbox/grid1/lbl_freq.text = '%d' % (regs_input[4] & 0x1ff)
|
||||
$margin/vbox/grid1/state_freq.texture \
|
||||
= textures[STATE_VAL.GOOD] if regs_input[4] & (1 << 15) \
|
||||
else textures[STATE_VAL.ERROR]
|
||||
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
|
||||
|
||||
@@ -7,12 +7,12 @@ extends NinePatchRect
|
||||
"""
|
||||
|
||||
@export var fname: String:
|
||||
set(v):
|
||||
fname = v
|
||||
if is_inside_tree():
|
||||
$lbl_fname.text = v
|
||||
set(v):
|
||||
fname = v
|
||||
if is_inside_tree():
|
||||
$lbl_fname.text = v
|
||||
|
||||
|
||||
@export var rname: String:
|
||||
set(v):
|
||||
rname = v
|
||||
set(v):
|
||||
rname = v
|
||||
|
||||
@@ -7,7 +7,7 @@ extends Node
|
||||
func _on_toggled(toggled_on): $frame.visible = toggled_on
|
||||
|
||||
@export var state: int:
|
||||
set(v):
|
||||
v = 0 if v < 0 else v % state_colors.size()
|
||||
state = v
|
||||
$label.self_modulate = state_colors[v]
|
||||
set(v):
|
||||
v = 0 if v < 0 else v % state_colors.size()
|
||||
state = v
|
||||
$label.self_modulate = state_colors[v]
|
||||
|
||||
@@ -6,50 +6,50 @@ extends Panel
|
||||
|
||||
const PRIBORS_RES = \
|
||||
{
|
||||
'pribor_afsp_l': ['res://scenes/pribor-afsp/pribor-afsp.tscn', 'Контроль исправности прибора АФСП левый'],
|
||||
'pribor_afsp_r': ['res://scenes/pribor-afsp/pribor-afsp.tscn', 'Контроль исправности прибора АФСП правый'],
|
||||
'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'],
|
||||
'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'],
|
||||
'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'],
|
||||
'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'],
|
||||
'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'],
|
||||
'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'],
|
||||
'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'],
|
||||
'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'],
|
||||
'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'],
|
||||
'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'],
|
||||
'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'],
|
||||
'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'],
|
||||
'pribor_rtr': ['res://scenes/pribor-rtr/pribor-rtr.tscn', 'Контроль исправности прибора РТР'],
|
||||
'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'],
|
||||
'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности прибора УЭП'],
|
||||
}
|
||||
'pribor_afsp_l': ['res://scenes/pribor-afsp/pribor-afsp.tscn', 'Контроль исправности прибора АФСП левый'],
|
||||
'pribor_afsp_r': ['res://scenes/pribor-afsp/pribor-afsp.tscn', 'Контроль исправности прибора АФСП правый'],
|
||||
'pribor_prd_k_1': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 1'],
|
||||
'pribor_prd_k_2': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 2'],
|
||||
'pribor_prd_k_3': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 3'],
|
||||
'pribor_prd_k_4': ['res://scenes/pribor-prd-k/pribor-prd-k.tscn', 'Контроль исправности прибора ПРД-К 4'],
|
||||
'pribor_prd_n_1': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 1'],
|
||||
'pribor_prd_n_2': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 2'],
|
||||
'pribor_prd_n_3': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 3'],
|
||||
'pribor_prd_n_4': ['res://scenes/pribor-prd-n/pribor-prd-n.tscn', 'Контроль исправности прибора ПРД-Н 4'],
|
||||
'pribor_prd_v_1': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 1'],
|
||||
'pribor_prd_v_2': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 2'],
|
||||
'pribor_prd_v_3': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 3'],
|
||||
'pribor_prd_v_4': ['res://scenes/pribor-prd-v/pribor-prd-v.tscn', 'Контроль исправности прибора ПРД-В 4'],
|
||||
'pribor_rtr': ['res://scenes/pribor-rtr/pribor-rtr.tscn', 'Контроль исправности прибора РТР'],
|
||||
'pribor_uf': ['res://scenes/pribor-uf/pribor-uf.tscn', 'Контроль исправности прибора УФ'],
|
||||
'pribor_uyep': ['res://scenes/pribor-uyep/pribor-uyep.tscn', 'Контроль исправности прибора УЭП'],
|
||||
}
|
||||
|
||||
|
||||
func _ready():
|
||||
var group = ButtonGroup.new()
|
||||
for k in PRIBORS_RES:
|
||||
var pribor_node = get_node(k)
|
||||
assert(pribor_node)
|
||||
var pribor_path = PRIBORS_RES[k][0]
|
||||
var header_text = PRIBORS_RES[k][1]
|
||||
pribor_node.set_button_group(group)
|
||||
pribor_node.connect('button_down', Callable(self, 'on_pribor_press').bind(pribor_path, header_text))
|
||||
log.info('Модуль контроля работы готов')
|
||||
var group = ButtonGroup.new()
|
||||
for k in PRIBORS_RES:
|
||||
var pribor_node = get_node(k)
|
||||
assert(pribor_node)
|
||||
var pribor_path = PRIBORS_RES[k][0]
|
||||
var header_text = PRIBORS_RES[k][1]
|
||||
pribor_node.set_button_group(group)
|
||||
pribor_node.connect('button_down', Callable(self, 'on_pribor_press').bind(pribor_path, header_text))
|
||||
log.info('Модуль контроля работы готов')
|
||||
|
||||
|
||||
func on_pribor_press(pribor_path, header_text):
|
||||
clear_obj($mnemo_container)
|
||||
var pribor_obj = load(pribor_path)
|
||||
assert(pribor_obj)
|
||||
var pribor = pribor_obj.instantiate()
|
||||
assert(pribor)
|
||||
pribor.set_header_text(header_text)
|
||||
$mnemo_container.add_child(pribor)
|
||||
clear_obj($mnemo_container)
|
||||
var pribor_obj = load(pribor_path)
|
||||
assert(pribor_obj)
|
||||
var pribor = pribor_obj.instantiate()
|
||||
assert(pribor)
|
||||
pribor.set_header_text(header_text)
|
||||
$mnemo_container.add_child(pribor)
|
||||
|
||||
|
||||
func clear_obj(obj: Object):
|
||||
var items = obj.get_children()
|
||||
for item in items:
|
||||
obj.remove_child(item)
|
||||
item.queue_free()
|
||||
var items = obj.get_children()
|
||||
for item in items:
|
||||
obj.remove_child(item)
|
||||
item.queue_free()
|
||||
|
||||
@@ -18,55 +18,55 @@ extends Control
|
||||
|
||||
|
||||
@export var self_size: Vector2i = Vector2i(50, 150):
|
||||
set(v):
|
||||
self_size = v
|
||||
size = v
|
||||
$np_rect.size = v
|
||||
_resize_children()
|
||||
get: return size
|
||||
set(v):
|
||||
self_size = v
|
||||
size = v
|
||||
$np_rect.size = v
|
||||
_resize_children()
|
||||
get: return size
|
||||
|
||||
|
||||
@export var fname: String:
|
||||
set(v):
|
||||
fname = v
|
||||
$lbl_fname.text = v
|
||||
set(v):
|
||||
fname = v
|
||||
$lbl_fname.text = v
|
||||
|
||||
|
||||
@export var rname: String:
|
||||
set(v):
|
||||
rname = v
|
||||
$lbl_rname.text = v
|
||||
set(v):
|
||||
rname = v
|
||||
$lbl_rname.text = v
|
||||
|
||||
|
||||
func _resize_children() -> void:
|
||||
$lbl_rname.size.x = size.x
|
||||
$lbl_rname.position.y = margins[0]
|
||||
$lbl_fname.size.y = size.x
|
||||
$lbl_fname.position.y = size.y / 2 + $lbl_fname.size.x / 2
|
||||
$txr_state.position.x = size.x / 2 - ($txr_state.size.x * $txr_state.scale.x) / 2
|
||||
$txr_state.position.y = size.y - $txr_state.size.y * $txr_state.scale.x - margins[2]
|
||||
$lbl_rname.size.x = size.x
|
||||
$lbl_rname.position.y = margins[0]
|
||||
$lbl_fname.size.y = size.x
|
||||
$lbl_fname.position.y = size.y / 2 + $lbl_fname.size.x / 2
|
||||
$txr_state.position.x = size.x / 2 - ($txr_state.size.x * $txr_state.scale.x) / 2
|
||||
$txr_state.position.y = size.y - $txr_state.size.y * $txr_state.scale.x - margins[2]
|
||||
|
||||
|
||||
func _on_nine_patch_rect_resized() -> void:
|
||||
size = $np_rect.size
|
||||
self_size = $np_rect.size
|
||||
_resize_children()
|
||||
size = $np_rect.size
|
||||
self_size = $np_rect.size
|
||||
_resize_children()
|
||||
|
||||
|
||||
func _on_resized() -> void:
|
||||
$np_rect.size = size
|
||||
self_size = size
|
||||
_resize_children()
|
||||
$np_rect.size = size
|
||||
self_size = size
|
||||
_resize_children()
|
||||
|
||||
|
||||
@export var state: int:
|
||||
set(v):
|
||||
v = 0 if v < 0 else v
|
||||
v %= textures.size()
|
||||
state = v
|
||||
$txr_state.texture = textures[v]
|
||||
get:
|
||||
return state
|
||||
set(v):
|
||||
v = 0 if v < 0 else v
|
||||
v %= textures.size()
|
||||
state = v
|
||||
$txr_state.texture = textures[v]
|
||||
get:
|
||||
return state
|
||||
"
|
||||
|
||||
[node name="yelement_v" type="Control"]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -122,12 +122,13 @@ func _ready() -> void:
|
||||
dst_ports[unit_key] = st[2][0]
|
||||
|
||||
if proto in TCP_PROTO:
|
||||
var unit = TCP_PROTO[proto].new(unit_name)
|
||||
var unit_tcp = TCP_PROTO[proto].new(unit_name)
|
||||
var unit_key = settings.get_unit_key(unit_name)
|
||||
units_tcp[unit_key] = unit
|
||||
units_tcp[unit_key] = unit_tcp
|
||||
units[unit_key] = unit_tcp
|
||||
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))
|
||||
unit_tcp.connect('line_changed', Callable(logger_page, 'on_line_changed').bind(unit_key))
|
||||
unit_tcp.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
|
||||
|
||||
if proto in SERIAL_PROTO:
|
||||
var unit_serial = SERIAL_PROTO[proto].new(unit_name)
|
||||
|
||||
@@ -3,26 +3,26 @@ class_name base_unit extends Node
|
||||
## Базовый класс для управления подключаемыми устройствами
|
||||
class Unit extends Object:
|
||||
|
||||
## Состояние автомата выполнения команды.
|
||||
enum CmdState {
|
||||
UNCK, ## Номер команды не ининциирован.
|
||||
SEND, ## Буфер готов для отправки.
|
||||
WAIT, ## Ожидание выполнения.
|
||||
DONE, ## Команда выполнена.
|
||||
FAIL ## Команда не выполнена.
|
||||
}
|
||||
## Состояние автомата выполнения команды.
|
||||
enum CmdState {
|
||||
UNCK, ## Номер команды не ининциирован.
|
||||
SEND, ## Буфер готов для отправки.
|
||||
WAIT, ## Ожидание выполнения.
|
||||
DONE, ## Команда выполнена.
|
||||
FAIL ## Команда не выполнена.
|
||||
}
|
||||
|
||||
signal line_changed(unit) ## Вызывается при изменении состояния связи
|
||||
signal command_done(unit) ## Вызывается после успешного выполнения команды.
|
||||
signal command_fail(unit) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
|
||||
signal parse_failed(unit) ## Вызывается при обнаружении ошибки во входных данных
|
||||
signal data_received(data: PackedByteArray) ## Вызывается по приёму данных
|
||||
signal line_changed(unit) ## Вызывается при изменении состояния связи
|
||||
signal command_done(unit) ## Вызывается после успешного выполнения команды.
|
||||
signal command_fail(unit) ## Вызывается если возникла ошибка при выполнении команды и команда не выполнена.
|
||||
signal parse_failed(unit) ## Вызывается при обнаружении ошибки во входных данных
|
||||
signal data_received(data: PackedByteArray) ## Вызывается по приёму данных
|
||||
|
||||
var tx_data: = PackedByteArray() ## Буфер для отправки.
|
||||
var tx_len: int = 0 ## Длина последнего отправленного пакета.
|
||||
var tx_tick: int = 0 ## Тик-время отправки буфера
|
||||
var rx_tick: int = 0 ## Тик-время последнего приёма данных
|
||||
var online: bool = false ## Состояние подключения устройства
|
||||
var name: String = '<без имени>' ## Уникальное имя устройства
|
||||
func _init(nm) -> void: self.name = nm
|
||||
func _to_string() -> String: return String('устройство: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
|
||||
var tx_data: = PackedByteArray() ## Буфер для отправки.
|
||||
var tx_len: int = 0 ## Длина последнего отправленного пакета.
|
||||
var tx_tick: int = 0 ## Тик-время отправки буфера
|
||||
var rx_tick: int = 0 ## Тик-время последнего приёма данных
|
||||
var online: bool = false ## Состояние подключения устройства
|
||||
var name: String = '<без имени>' ## Уникальное имя устройства
|
||||
func _init(nm) -> void: self.name = nm
|
||||
func _to_string() -> String: return String('устройство: %s %s' % [self.name, ['отключен', 'на связи'][int(online)]])
|
||||
|
||||
Reference in New Issue
Block a user