Skip to content

Commit a4203af

Browse files
committed
load-from-file: Updates to improve reliability of large .parm loads
The present implementation of do_load_from_file has a few performance issues. 1) All ConfigGetSet() requests are queued as fast as possible, and do not give time for the downstream system to even respond before the next transaction is sent. 2) Even thought the index is known for each parameter in the table the name based request for setting is _always_ used. This causes very heavy bus loading, expecially when combined with (1) This commit make the following core updates: 1) Stores the index in the param set such that it can be utilized later for setting parameters. 2) Queues the request transactions at 20ms increments to give the downstream unit a chance to process the request before sending the next. Additionally in this commit, the fetch speed was increased from 100ms intervals between fetching parameters to 10ms. The 10ms and 20ms settings could be added to the application config to allow some tuning/tweaking on a per user basis, but for now, all tests show these are sufficient values.
1 parent 9c67cc8 commit a4203af

1 file changed

Lines changed: 35 additions & 14 deletions

File tree

dronecan_gui_tool/widgets/node_properties.py

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,21 @@
1919
from .node_monitor import node_health_to_color, node_mode_to_color
2020
from .file_server import FileServer_PathKey
2121
from ..am32_rtttl import AM32_Rtttl
22+
from typing import Optional
2223

2324

2425
logger = getLogger(__name__)
2526

2627

2728
REQUEST_PRIORITY = 30
2829

30+
class ConfigParamEntry:
31+
def __init__(self, index, response):
32+
self._index = index
33+
self._value = response.value
34+
self._name = response.name
35+
self._response = response;
36+
self._sync=True
2937

3038
class FieldValueWidget(QLineEdit):
3139
def __init__(self, parent, initial_value=None):
@@ -656,7 +664,7 @@ def update_callback(value, is_melody=False):
656664
else:
657665
self._table.item(index, self.VALUE_COLUMN).setText(str(value))
658666

659-
win = ConfigParamEditWindow(self, self._node, self._target_node_id, self._params[index], update_callback)
667+
win = ConfigParamEditWindow(self, self._node, self._target_node_id, self._params[index]._response, update_callback)
660668
win.show()
661669

662670
def _on_fetch_response(self, index, e):
@@ -679,14 +687,17 @@ def _on_fetch_response(self, index, e):
679687
self.window().show_message('%d params fetched successfully', index)
680688
return
681689

682-
self._params.append(e.response)
690+
# create a parameter structure including the index from the response
691+
param = ConfigParamEntry(index, e.response)
692+
693+
self._params.append(param)
683694
self._table.setRowCount(self._table.rowCount() + 1)
684695
self._table.set_row(self._table.rowCount() - 1, (index, e.response))
685696

686697
try:
687698
index += 1
688699
self.window().show_message('Requesting index %d', index)
689-
self._node.defer(0.1, lambda: self._node.request(dronecan.uavcan.protocol.param.GetSet.Request(index=index),
700+
self._node.defer(0.01, lambda: self._node.request(dronecan.uavcan.protocol.param.GetSet.Request(index=index),
690701
self._target_node_id,
691702
partial(self._on_fetch_response, index),
692703
priority=REQUEST_PRIORITY))
@@ -740,9 +751,9 @@ def _do_save_to_file(self):
740751
print("save to file", param_file)
741752
f = open(param_file, "w")
742753
for p in self._params:
743-
value = p.value
744-
name = p.name
745-
value_string = self.param_as_string(value, AM32_Rtttl.is_am32_melody_param(p))
754+
value = p._value
755+
name = p._name
756+
value_string = self.param_as_string(value, AM32_Rtttl.is_am32_melody_param(p._response))
746757
if value_string:
747758
f.write("%s %s\n" % (name, value_string))
748759
f.close()
@@ -753,12 +764,12 @@ def _on_send_response(self, e):
753764
else:
754765
for i in range(len(self._params)):
755766
p = self._params[i]
756-
name = str(p.name)
767+
name = str(p._name)
757768
if name == str(e.response.name):
758769
logger.info('set %s to %s' % (name, self.param_as_string(e.response.value)))
759-
self._table.item(i, self.VALUE_COLUMN).setText(self.param_as_string(e.response.value, AM32_Rtttl.is_am32_melody_param(p)))
770+
self._table.item(i, self.VALUE_COLUMN).setText(self.param_as_string(e.response.value, AM32_Rtttl.is_am32_melody_param(p._response)))
760771

761-
def save_param(self, name, old_value, str_value):
772+
def save_param(self, name, old_value, str_value, index: Optional[int] = None, delay: Optional[float] = None):
762773
value_type = dronecan.get_active_union_field(old_value)
763774
v = old_value
764775

@@ -774,8 +785,16 @@ def save_param(self, name, old_value, str_value):
774785
raise RuntimeError('bad parameter type on save')
775786

776787
try:
777-
request = dronecan.uavcan.protocol.param.GetSet.Request(name=name, value=v)
778-
self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY)
788+
if index is None:
789+
request = dronecan.uavcan.protocol.param.GetSet.Request(name=name, value=v)
790+
else:
791+
request = dronecan.uavcan.protocol.param.GetSet.Request(index=index, value=v)
792+
793+
if delay is None:
794+
self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY)
795+
else:
796+
self._node.defer(delay, lambda: self._node.request(request, self._target_node_id, self._on_send_response, priority=REQUEST_PRIORITY))
797+
779798
except Exception as ex:
780799
show_error('Node error', 'Could not send param set request', ex, self)
781800

@@ -787,11 +806,12 @@ def _do_load_from_file(self):
787806
return
788807
pdict = {}
789808
for p in self._params:
790-
pdict[str(p.name)] = p.value
809+
pdict[str(p._name)] = p
791810

792811
param_file = os.path.normcase(os.path.abspath(param_file[0]))
793812
print("load from file", param_file)
794813
f = open(param_file, "r")
814+
delay = 0.0
795815
for line in f.readlines():
796816
a = line.split()
797817
name = a[0]
@@ -804,9 +824,10 @@ def _do_load_from_file(self):
804824
else:
805825
value = a[1]
806826
if name in pdict:
807-
s = self.param_as_string(pdict[name])
827+
s = self.param_as_string(pdict[name]._value)
808828
if s != value:
809-
self.save_param(name, pdict[name], value)
829+
self.save_param(name, pdict[name]._value, value, pdict[name]._index, delay)
830+
delay += 0.02
810831
f.close()
811832

812833
def _do_execute_opcode(self, opcode):

0 commit comments

Comments
 (0)