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

This commit is contained in:
lepshiy
2024-10-15 09:05:57 +03:00
12 changed files with 187 additions and 76 deletions

View File

@@ -10,6 +10,7 @@ import json
import argparse
import time
from socket import *
from threading import Timer
import logger
from pymodbus.client.sync import ModbusSerialClient
@@ -21,8 +22,17 @@ EXCEPT_MSGS = {
'write': 'ошибка: запись в регистры не выполнена',
'read_holding': 'ошибка: чтение регистров хранения не выполнено',
'read_input': 'ошибка: чтение регистров входов не выполнено',
'<unknown>': 'ошибка: получена неверная команда'
}
'<unknown>': 'ошибка: получена неверная команда'}
def on_timer(*args):
sock = args[0]
json_encoder = args[1]
udp_addr = args[2]
udp_port_tx = args[3]
tx_data = json_encoder.encode({'code': 'info', 'data': 'ok'})
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
Timer(1, on_timer, args).start()
def main():
@@ -52,12 +62,12 @@ def run_sync_client(udp_addr, udp_port_rx, udp_port_tx, serial_port, serial_baud
log.info('подключен к серверу через \"%s\" на скорости %d бод' % (serial_port, serial_baud))
Timer(1, on_timer, [sock, json_encoder, udp_addr, udp_port_tx]).start()
while True:
udp_data = sock.recv(2048) # Ждать команду от приложения
udp_data = udp_data.decode('utf-8')
message = json_decoder.decode(udp_data) # type: dict
if 'code' not in message:
message['code'] = '<unknown>'
@@ -69,21 +79,23 @@ def run_sync_client(udp_addr, udp_port_rx, udp_port_tx, serial_port, serial_baud
data = message['data']
rq = client.write_registers(data[0], data[1:], unit=unit_num)
rc = rq.isError()
if not rc:
tx_data = json_encoder.encode({'code': 'response', 'data': ''})
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
elif message['code'] == 'read_holding':
data = message['data']
print('client_serial_modbus.py: data', data)
rq = client.read_holding_registers(data[0], data[1:], unit=unit_num)
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})
sock.sendto(bytes(tx_data), (udp_addr, udp_port_tx))
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)
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})
sock.sendto(bytes(tx_data), (udp_addr, udp_port_tx))
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
elif message['code'] == '<unknown>':
rc = False
@@ -92,7 +104,7 @@ def run_sync_client(udp_addr, udp_port_rx, udp_port_tx, serial_port, serial_baud
data = message['data']
rc_msg = EXCEPT_MSGS[code]
tx_data = json_encoder.encode({'code': 'exception', 'data': rc_msg})
sock.sendto(bytes(tx_data), (udp_addr, udp_port_tx))
sock.sendto(bytes(tx_data, 'utf-8'), (udp_addr, udp_port_tx))
log.error(
'ошибка при выполнении команды: \"%s\". данные: \"%s\", порт: \"%s\", скорость: %s'
% (code, data, serial_port, serial_baud))

View File

@@ -8,7 +8,7 @@ def get_logger(source_file, log_dir='logs'):
log_format = '[%(asctime)s] %(module)s:%(lineno)s %(message)s'
logging.basicConfig(format=log_format)
log = logging.getLogger()
log.setLevel(logging.INFO)
log.setLevel(logging.DEBUG)
file_handler = logging.FileHandler(f'{log_dir}/{source_file}.log')
file_handler.setFormatter(logging.Formatter(log_format))
log.addHandler(file_handler)

View File

@@ -60,7 +60,7 @@ def main():
print_opts_error(opts_unk)
store = CallbackModbusSlaveContext()
context = ModbusServerContext(slaves=store, single=True)
log.info("серевер-заглушка Modbus serial работает: %s:%d" % (opts.serial_port, opts.serial_baud))
log.info("сервер-заглушка Modbus serial работает: %s:%d" % (opts.serial_port, opts.serial_baud))
StartSerialServer(context=context, framer=ModbusRtuFramer, port=opts.serial_port, timeout=opts.timeout, baudrate=opts.serial_baud)

View File

@@ -3,7 +3,7 @@
[ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="1_8dmgr"]
[ext_resource type="Script" path="res://scenes/контроль/прибор.gd" id="1_ufjwe"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="2_14h25"]
[ext_resource type="PackedScene" uid="uid://bk1655p4e8y4u" path="res://scenes/контроль/кассета-у-5.tscn" id="3_7orfk"]
[ext_resource type="PackedScene" uid="uid://cm5jd4gjrrpba" path="res://scenes/контроль/кассета-у-5.tscn" id="2_tb85r"]
[ext_resource type="PackedScene" uid="uid://bkxblfoj7ejv0" path="res://scenes/контроль/блок-а.tscn" id="6_fmhtx"]
[ext_resource type="PackedScene" uid="uid://dbxdb7lo7kofv" path="res://scenes/контроль/кассета-п-1.tscn" id="7_cjjs2"]
[ext_resource type="PackedScene" uid="uid://bmagw8nd0ulhj" path="res://scenes/pribor-prd-k/kasseta-fs-kd.tscn" id="7_ia27q"]
@@ -18,6 +18,13 @@ offset_right = 15.0
offset_bottom = 30.0
script = ExtResource("1_ufjwe")
[node name="kasseta_u5" parent="." instance=ExtResource("2_tb85r")]
layout_mode = 0
offset_left = 175.0
offset_top = 242.0
offset_right = 485.0
offset_bottom = 432.0
[node name="lbl_header" type="Label" parent="."]
layout_mode = 0
offset_left = 20.0
@@ -32,36 +39,36 @@ vertical_alignment = 1
[node name="maa2000_A22" parent="." instance=ExtResource("1_8dmgr")]
layout_mode = 0
offset_left = 485.0
offset_top = 877.0
offset_top = 907.0
offset_right = 645.0
offset_bottom = 942.0
offset_bottom = 949.0
fname = "MAA2000"
rname = "A22"
[node name="dou2_A7" parent="." instance=ExtResource("1_8dmgr")]
layout_mode = 0
offset_left = 485.0
offset_top = 812.0
offset_right = 645.0
offset_bottom = 877.0
offset_left = 8.0
offset_top = 862.0
offset_right = 168.0
offset_bottom = 907.0
fname = "ДОУ-6"
rname = "A7"
[node name="maa2000_A23" parent="." instance=ExtResource("1_8dmgr")]
layout_mode = 0
offset_left = 15.0
offset_top = 877.0
offset_right = 175.0
offset_bottom = 942.0
offset_left = 8.0
offset_top = 907.0
offset_right = 168.0
offset_bottom = 949.0
fname = "MAA2000"
rname = "A23"
[node name="dou2_A8" parent="." instance=ExtResource("1_8dmgr")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 812.0
offset_right = 175.0
offset_bottom = 877.0
offset_right = 168.0
offset_bottom = 860.0
fname = "ДОУ-7"
rname = "A8"
@@ -70,7 +77,7 @@ layout_mode = 0
offset_left = 175.0
offset_top = 812.0
offset_right = 485.0
offset_bottom = 942.0
offset_bottom = 949.0
texture = ExtResource("2_14h25")
patch_margin_left = 16
patch_margin_top = 16
@@ -203,9 +210,28 @@ name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
rname = "A15"
[node name="utm80_A9" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 485.0
offset_top = 812.0
offset_right = 645.0
offset_bottom = 907.0
value0 = 28.0
value1 = 57.0
max_value0 = 99.0
max_value1 = 99.0
step0 = 1.0
step1 = 1.0
value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УТМ80"
rname = "A9"
[node name="um1535_A16" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 242.0
offset_right = 175.0
offset_bottom = 337.0
@@ -219,14 +245,14 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A16"
[node name="um1535_A17" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 337.0
offset_right = 175.0
offset_right = 173.0
offset_bottom = 432.0
value0 = 28.0
value1 = 57.0
@@ -238,12 +264,12 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A17"
[node name="um1535_A18" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 432.0
offset_right = 175.0
offset_bottom = 527.0
@@ -257,12 +283,12 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A18"
[node name="um1535_A19" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 527.0
offset_right = 175.0
offset_bottom = 622.0
@@ -276,12 +302,12 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A19"
[node name="um1535_A20" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 622.0
offset_right = 175.0
offset_bottom = 717.0
@@ -295,12 +321,12 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A20"
[node name="um1535_A21" parent="." instance=ExtResource("6_fmhtx")]
layout_mode = 0
offset_left = 15.0
offset_left = 8.0
offset_top = 717.0
offset_right = 175.0
offset_bottom = 812.0
@@ -314,17 +340,9 @@ value_name0 = "°C"
value_name1 = "P, %"
name_min_size0 = Vector2i(35, 20)
name_min_size1 = Vector2i(35, 20)
fname = "УМ1535Б"
fname = "РМ16-20М"
rname = "A21"
[node name="kasseta_u5" parent="." instance=ExtResource("3_7orfk")]
layout_mode = 0
offset_left = 175.0
offset_top = 242.0
offset_right = 485.0
offset_bottom = 432.0
fname = "Кассета У5"
[node name="kasseta_fs_kd" parent="." instance=ExtResource("7_ia27q")]
layout_mode = 0
offset_left = 175.0

View File

@@ -3,7 +3,7 @@
[ext_resource type="Script" path="res://scenes/контроль/прибор.gd" id="1_mcea3"]
[ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_lpj3d"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="4_i1no5"]
[ext_resource type="PackedScene" uid="uid://bk1655p4e8y4u" path="res://scenes/контроль/кассета-у-5.tscn" id="5_ej152"]
[ext_resource type="PackedScene" uid="uid://bk1655p4e8y4u" path="res://scenes/контроль/кассета-у-5-нв.tscn" id="5_ej152"]
[ext_resource type="PackedScene" uid="uid://cd5sue1e8iyrv" path="res://scenes/pribor-prd-n/kasseta-fs-nd.tscn" id="6_1p3pi"]
[ext_resource type="PackedScene" uid="uid://dbxdb7lo7kofv" path="res://scenes/контроль/кассета-п-1.tscn" id="7_klldp"]
[ext_resource type="PackedScene" uid="uid://bkxblfoj7ejv0" path="res://scenes/контроль/блок-а.tscn" id="8_u7eqo"]

View File

@@ -3,7 +3,7 @@
[ext_resource type="Script" path="res://scenes/контроль/прибор.gd" id="1_dl7rt"]
[ext_resource type="PackedScene" uid="uid://d3iqb5e4g81m5" path="res://scenes/контроль/элемент-г.tscn" id="2_xpo4b"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="3_wyy1b"]
[ext_resource type="PackedScene" uid="uid://bk1655p4e8y4u" path="res://scenes/контроль/кассета-у-5.tscn" id="4_gl2bl"]
[ext_resource type="PackedScene" uid="uid://bk1655p4e8y4u" path="res://scenes/контроль/кассета-у-5-нв.tscn" id="4_gl2bl"]
[ext_resource type="PackedScene" uid="uid://cd5sue1e8iyrv" path="res://scenes/pribor-prd-n/kasseta-fs-nd.tscn" id="5_nhd2k"]
[ext_resource type="PackedScene" uid="uid://dbxdb7lo7kofv" path="res://scenes/контроль/кассета-п-1.tscn" id="6_d3awr"]
[ext_resource type="PackedScene" uid="uid://bkxblfoj7ejv0" path="res://scenes/контроль/блок-а.tscn" id="7_e22c6"]

View File

@@ -0,0 +1,74 @@
[gd_scene load_steps=4 format=3 uid="uid://cm5jd4gjrrpba"]
[ext_resource type="Texture2D" uid="uid://c4mdrmk7h638f" path="res://data/nine-patch-round.png" id="1_bdojw"]
[ext_resource type="Script" path="res://scenes/контроль/кассета.gd" id="2_csgh4"]
[ext_resource type="PackedScene" uid="uid://p2suppildvq0" path="res://scenes/контроль/элемент-в.tscn" id="3_wtlpi"]
[node name="kasseta_u5" type="NinePatchRect"]
offset_right = 310.0
offset_bottom = 190.0
texture = ExtResource("1_bdojw")
patch_margin_left = 16
patch_margin_top = 16
patch_margin_right = 16
patch_margin_bottom = 16
script = ExtResource("2_csgh4")
[node name="lbl_fname" type="Label" parent="."]
self_modulate = Color(1, 1, 1, 0.62)
layout_mode = 0
offset_left = 5.0
offset_top = 7.0
offset_right = 305.0
offset_bottom = 35.0
text = "Кассета"
horizontal_alignment = 1
vertical_alignment = 1
[node name="ref_A31" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 5.0
offset_top = 32.0
offset_right = 55.0
offset_bottom = 182.0
fname = "ИП5-25"
rname = "A31"
[node name="ref_A37" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 55.0
offset_top = 32.0
offset_right = 105.0
offset_bottom = 182.0
fname = "ЯУ-07Б"
rname = "A37"
[node name="ref_A33" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 105.0
offset_top = 32.0
offset_right = 155.0
offset_bottom = 182.0
fname = "ЭМС-Г"
rname = "A33"
[node name="ref_A34" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 155.0
offset_top = 32.0
offset_right = 205.0
offset_bottom = 182.0
fname = "УГ"
rname = "A34"
[node name="ref_A35" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 205.0
offset_top = 32.0
offset_right = 255.0
offset_bottom = 182.0
fname = "УКП"
rname = "A35"
[node name="ref_A36" parent="." instance=ExtResource("3_wtlpi")]
offset_left = 254.0
offset_top = 32.0
offset_right = 304.0
offset_bottom = 182.0
fname = "УКП"
rname = "A36"

View File

@@ -31,7 +31,7 @@ offset_top = 32.0
offset_right = 55.0
offset_bottom = 182.0
fname = "ИП5-25"
rname = "A31"
rname = "A24"
[node name="ref_A37" parent="." instance=ExtResource("3_picsk")]
offset_left = 55.0
@@ -39,7 +39,7 @@ offset_top = 32.0
offset_right = 105.0
offset_bottom = 182.0
fname = "ЯУ-07Б"
rname = "A37"
rname = "A30"
[node name="ref_A33" parent="." instance=ExtResource("3_picsk")]
offset_left = 105.0
@@ -47,7 +47,7 @@ offset_top = 32.0
offset_right = 155.0
offset_bottom = 182.0
fname = "ЭМС-Г"
rname = "A33"
rname = "A26"
[node name="ref_A34" parent="." instance=ExtResource("3_picsk")]
offset_left = 155.0
@@ -55,7 +55,7 @@ offset_top = 32.0
offset_right = 205.0
offset_bottom = 182.0
fname = "УГ"
rname = "A34"
rname = "A27"
[node name="ref_A35" parent="." instance=ExtResource("3_picsk")]
offset_left = 205.0
@@ -63,7 +63,7 @@ offset_top = 32.0
offset_right = 255.0
offset_bottom = 182.0
fname = "УКП"
rname = "A35"
rname = "A29"
[node name="ref_A36" parent="." instance=ExtResource("3_picsk")]
offset_left = 254.0
@@ -71,4 +71,4 @@ offset_top = 32.0
offset_right = 304.0
offset_bottom = 182.0
fname = "УКП"
rname = "A36"
rname = "A28"

View File

@@ -2,7 +2,6 @@ class_name mod_bus extends Node
const ONLINE_TIMEOUT = 5.0 ## Время ожидания пакета от ячейки, секунды.
class ModbusClient:
## Состояние автомата выполнения команды.
@@ -24,13 +23,12 @@ class ModbusClient:
static var json_conv: = JSON.new()
signal command_done() ## Вызывается при успешном выполнении команды.
signal command_fail() ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed() ## Вызывается при смене состояния связи с ячейкой.
signal command_fail(unit: ModbusClient) ## Вызывается при возникновении ошибки во время выполнения команды.
signal line_changed(unit: ModbusClient) ## Вызывается при смене состояния связи с ячейкой.
signal data_received() ## Вызывается при приёме сообщения, до его разбора.
signal parse_failed(msg: String) ## Вызывается при возникновении ошибки во время разбора пакета. Передаёт сообщение об ошибке.
signal holding_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal input_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров входов.
signal responce_received(addr: int, data: Array) ## Вызывается при получении сообщения c данными из регистров хранения.
signal info_received(msg: String) ## Вызывается при получении информационного сообщения.
signal except_received(msg: String) ## Вызывается при получении сообщения об исключительной ситуации.
@@ -43,10 +41,10 @@ class ModbusClient:
func process(tick: int):
if online and ((tick - tick_rx) > ONLINE_TIMEOUT):
online = false
emit_signal('line_changed')
emit_signal('line_changed', self)
if (cmd_state == CmdState.WAIT) or (cmd_state == CmdState.SEND):
#cmd_state = CmdState.FAIL
emit_signal('command_fail')
cmd_state = CmdState.FAIL
emit_signal('command_fail', self)
var rc = Error.ERR_BUSY
if cmd_state == CmdState.SEND:
rc = Error.OK
@@ -61,7 +59,7 @@ class ModbusClient:
tick_rx = tick
if not online:
online = true
emit_signal('line_changed')
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')
@@ -71,14 +69,10 @@ class ModbusClient:
var message_code = message['code']
var message_data = message['data']
match message_code:
'read_input':
'response':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('input_received', addr, regs)
'read_holding':
var addr = message_data[0]
var regs = message_data.slice(1)
emit_signal('holding_received', addr, regs)
emit_signal('responce_received', addr, regs)
'info':
var msg = message['data']
emit_signal('info_received', msg)
@@ -95,7 +89,7 @@ class ModbusClient:
emit_signal('command_done')
elif (cmd_state == CmdState.WAIT) and (not rc):
cmd_state = CmdState.FAIL
emit_signal('command_fail')
emit_signal('command_fail', self)
else:
var message = json_conv.get_error_message()
emit_signal('parse_failed', message)
@@ -115,7 +109,7 @@ class ModbusClient:
## [param addr] - Начальный адрес регистров.[br]
## [param count] - Количество регистров от начального адреса.[br]
func read_holdind(addr: int, count: int = 1) -> bool:
#if cmd_state != CmdState.DONE: return false
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

View File

@@ -67,6 +67,7 @@ func _ready() -> void:
poll_sockets.append(create_socket('уарэп-яу07-частный'))
poll_sockets.append(create_socket('уарэп-яу07-общий'))
poll_sockets.append(create_socket('уарэп-капсрпб'))
poll_sockets.append(create_socket('уарэп-щ3'))
sock_unicast = poll_sockets[0]
sock_capsrpb = poll_sockets[2]
@@ -84,7 +85,7 @@ func _ready() -> void:
dst_ports[unit_key] = settings[2][1]
else:
dst_ports[unit_key] = settings[2][0]
if proto in TCP_PROTO:
var unit = TCP_PROTO[proto].new(unit_name)
var unit_key = repsettings.get_unit_key(unit_name)
@@ -94,7 +95,7 @@ func _ready() -> void:
unit.connect('command_fail', Callable(logger_page, 'on_command_fail').bind(unit_key))
tcp_sockets.append([create_tcpsocket('уарэп-5п28'), units_tcp[repsettings.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:

View File

@@ -26,7 +26,7 @@ class_name rep_settings extends Node
# Название | Протокол | Адрес | Порт получения | Порт отправки | Комментарий
'уарэп-щ3': ['udp-json-mbcs', '127.0.0.1', [48000, 44100], false, true, 'IP-адрес и порты через которые производят обмен сообщения с драйвером клиента Modbus Serial'],
# Название | Протокол | Имя порта | Скорость, бод | Чётность | Комментарий
'уарэп-спт25-1': ['uart', '/dev/tty2', 115200, false, 'Адрес прибора СПТ-25 (G1)'],
'уарэп-спт25-2': ['uart', '/dev/tty3', 115200, false, 'Адрес прибора СПТ-25 (G2)'],

View File

@@ -1,14 +1,26 @@
extends Node
var cnt: int = 0
var rw: bool = true
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)
func on_timer(unit):
unit.read_holdind(0x0000)
cnt +=1
if rw:
unit.write(0x0000, [cnt])
else:
unit.read_holdind(0x0000)
rw = not rw
func on_command_fail(unit):
unit.cmd_state = unit.CmdState.DONE