Skip to content

Commit ee8fbde

Browse files
committed
update: firmware: profile: support to update multiple nodes at once
'XBeeNetwork' class includes a new method 'update_nodes()' to update several nodes at once (firmware or profile). It requires a list of update tasks with the process details (node, files, timeout) and also an optional progress callback to get information about each single update process, similar to the callbacks in 'update_firmware()' and 'apply_profile()' methods of 'XBeeDevice' and 'RemoteXBeeDevice'. This commit adds the possibility of registering a new callback in the network using 'add_update_progress_callback()' method. This callback is executed every time the status of any update process (firmware or profile) changes. It indicates the XBee being updated, the tasks in process, and its current percentage. The corresponding 'del_update_progress_callback()' is also implemented. https://onedigi.atlassian.net/browse/DAL-5285 Signed-off-by: Tatiana Leon <Tatiana.Leon@digi.com>
1 parent fe6eb08 commit ee8fbde

File tree

8 files changed

+761
-73
lines changed

8 files changed

+761
-73
lines changed

CHANGELOG.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,13 @@ v1.4.1 - XX/XX/2021
1919

2020
* Do not work with network if the XBee does not support it (XBPL-374)
2121
* Fix creation of IMEI when reading cellular information.
22+
* Support to update a bunch of nodes at the same time (DAL-5285)
2223
* Documentation:
2324

2425
* Add info about the ``force_settings`` parameter of ``open`` method (#241)
2526
* Add missing ``exportutils`` module to documentation.
27+
* Set exclusive access mode to the XBee serial port (#222, #252)
28+
* Do not stop frames reader if a serial buffer empty exception occurs (#222, #252)
2629
* Do not use 'os.path.join()' for relative paths of zip entries (#247)
2730
* Fix bad conditions when checking for a received packet (#242)
2831
* Fix attribute name in find neighbors debug message (#122)

digi/xbee/devices.py

Lines changed: 78 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
from digi.xbee.io import IOSample, IOMode
5959
from digi.xbee.reader import PacketListener, PacketReceived, DeviceDiscovered, \
6060
DiscoveryProcessFinished, NetworkModified, RouteReceived, InitDiscoveryScan, \
61-
EndDiscoveryScan, XBeeEvent
61+
EndDiscoveryScan, XBeeEvent, NetworkUpdateProgress
6262
from digi.xbee.serial import FlowControl
6363
from digi.xbee.serial import XBeeSerialPort
6464

@@ -146,6 +146,7 @@ def __init__(self, local_xbee_device=None, serial_port=None,
146146
self._reachable = True
147147

148148
self._initializing = False
149+
self._active_update_type = None
149150

150151
self.__generic_lock = threading.Lock()
151152

@@ -8607,6 +8608,7 @@ def __init__(self, xbee_device):
86078608
self._network_modified = NetworkModified()
86088609
self._device_discovered = DeviceDiscovered()
86098610
self.__device_discovery_finished = DiscoveryProcessFinished()
8611+
self.__network_update_progress = NetworkUpdateProgress()
86108612
self.__discovery_thread = None
86118613
self.__sought_device_id = None
86128614
self.__discovered_device = None
@@ -8908,6 +8910,44 @@ def export(self, dir_path=None, name=None, desc=None):
89088910

89098911
return 0, str(file)
89108912

8913+
def update_nodes(self, task_list):
8914+
"""
8915+
Performs the provided update tasks. It blocks until all tasks finish.
8916+
8917+
Params:
8918+
task_list (List or tuple): List of update tasks
8919+
(:class:`.FwUpdateTask` or :class:`.ProfileUpdateTask`)
8920+
8921+
Returns:
8922+
Dictionary: Uses the 64-bit address of the XBee as key and, as
8923+
value, a Tuple with the XBee (:class:`.AbstractXBeeDevice`) and
8924+
an :class:`.XBeeException` if the process failed for that node
8925+
(`None` if it successes)
8926+
"""
8927+
from digi.xbee.firmware import FwUpdateTask
8928+
from digi.xbee.profile import ProfileUpdateTask
8929+
8930+
if not task_list:
8931+
return {}
8932+
8933+
result = {}
8934+
for task in task_list:
8935+
try:
8936+
if isinstance(task, FwUpdateTask):
8937+
task.xbee.update_firmware(task.xml_path,
8938+
xbee_firmware_file=task.fw_path,
8939+
bootloader_firmware_file=task.bl_path,
8940+
timeout=task.timeout,
8941+
progress_callback=task.callback)
8942+
elif isinstance(task, ProfileUpdateTask):
8943+
task.xbee.apply_profile(task.profile_path, timeout=task.timeout,
8944+
progress_callback=task.callback)
8945+
result.update({str(task.xbee.get_64bit_addr()): (task.xbee, None)})
8946+
except XBeeException as exc:
8947+
result.update({str(task.xbee.get_64bit_addr()): (task.xbee, exc)})
8948+
8949+
return result
8950+
89118951
def add_network_modified_callback(self, callback):
89128952
"""
89138953
Adds a callback for the event :class:`.NetworkModified`.
@@ -9028,6 +9068,20 @@ def __received_packet_from_cb(self, packet, remote):
90289068

90299069
cbs(packet, remote)
90309070

9071+
def add_update_progress_callback(self, callback):
9072+
"""
9073+
Adds a callback for the event :class:`.NetworkUpdateProgress`.
9074+
9075+
Args:
9076+
callback (Function): The callback. Receives three arguments.
9077+
* The XBee being updated.
9078+
* An :class:`.UpdateProgressStatus` with the current status.
9079+
9080+
.. seealso::
9081+
| :meth:`.XBeeNetwork.del_update_progress_callback`
9082+
"""
9083+
self.__network_update_progress += callback
9084+
90319085
def del_network_modified_callback(self, callback):
90329086
"""
90339087
Deletes a callback for the callback list of :class:`.NetworkModified`.
@@ -9128,6 +9182,29 @@ def del_packet_received_from_callback(self, node, callb=None):
91289182
self._local_xbee._packet_listener.del_packet_received_from_callback(
91299183
self.__received_packet_from_cb)
91309184

9185+
def del_update_progress_callback(self, callback):
9186+
"""
9187+
Deletes a callback for the callback list of :class:`.NetworkUpdateProgress`.
9188+
9189+
Args:
9190+
callback (Function): The callback to delete.
9191+
9192+
.. seealso::
9193+
| :meth:`.XBeeNetwork.add_update_progress_callback`
9194+
"""
9195+
if callback in self.__network_update_progress:
9196+
self.__network_update_progress -= callback
9197+
9198+
def get_update_progress_callbacks(self):
9199+
"""
9200+
Returns the list of registered callbacks for update progress.
9201+
This is only for internal use.
9202+
9203+
Returns:
9204+
List: List of :class:`.NetworkUpdateProgress` events.
9205+
"""
9206+
return self.__network_update_progress
9207+
91319208
def clear(self):
91329209
"""
91339210
Removes all remote XBee nodes from the network.

digi/xbee/filesystem.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3287,7 +3287,7 @@ def get_file_hash(self, file_path):
32873287

32883288
def update_remote_filesystem_image(remote_device, ota_filesystem_file,
32893289
max_block_size=0, timeout=None,
3290-
progress_callback=None, _prepare=True):
3290+
progress_callback=None):
32913291
"""
32923292
Performs a remote filesystem update operation in the given target.
32933293
@@ -3320,7 +3320,7 @@ def update_remote_filesystem_image(remote_device, ota_filesystem_file,
33203320
try:
33213321
update_remote_filesystem(
33223322
remote_device, ota_filesystem_file, max_block_size=max_block_size,
3323-
timeout=timeout, progress_callback=progress_callback, _prepare=_prepare)
3323+
timeout=timeout, progress_callback=progress_callback)
33243324
except FirmwareUpdateException as exc:
33253325
_log.error("ERROR: %s", str(exc))
33263326
raise FileSystemException(str(exc)) from None

0 commit comments

Comments
 (0)