3939from digi .xbee .models .hw import HardwareVersion
4040from digi .xbee .models .mode import APIOutputModeBit
4141from digi .xbee .models .options import RemoteATCmdOptions
42- from digi .xbee .models .protocol import XBeeProtocol , Role , Region
42+ from digi .xbee .models .protocol import XBeeProtocol , Role , Region , OTAMethod
4343from digi .xbee .models .status import TransmitStatus , ATCommandStatus , \
4444 EmberBootloaderMessageType , ModemStatus , UpdateProgressStatus , NodeUpdateType
4545from digi .xbee .packets .aft import ApiFrameType
8181
8282_XBEE3_BL_DEF_PREFIX = "xb3-boot-rf_"
8383_XBEE3_RR_BL_DEF_PREFIX = "xb3-boot-rr_"
84+ _XBEE3_XR_BL_DEF_PREFIX = "xb3-boot-lr_"
8485_XBEE3_BOOTLOADER_FILE_PREFIX = {
8586 HardwareVersion .XBEE3 .code : _XBEE3_BL_DEF_PREFIX ,
8687 HardwareVersion .XBEE3_SMT .code : _XBEE3_BL_DEF_PREFIX ,
8788 HardwareVersion .XBEE3_TH .code : _XBEE3_BL_DEF_PREFIX ,
8889 HardwareVersion .XBEE3_RR .code : _XBEE3_RR_BL_DEF_PREFIX ,
89- HardwareVersion .XBEE3_RR_TH .code : _XBEE3_RR_BL_DEF_PREFIX
90+ HardwareVersion .XBEE3_RR_TH .code : _XBEE3_RR_BL_DEF_PREFIX ,
91+ HardwareVersion .XBEE3_DM_LR .code : _XBEE3_XR_BL_DEF_PREFIX ,
92+ HardwareVersion .XBEE3_DM_LR_868 .code : _XBEE3_XR_BL_DEF_PREFIX ,
93+ HardwareVersion .XBEE_XR_900_TH .code : _XBEE3_XR_BL_DEF_PREFIX ,
94+ HardwareVersion .XBEE_XR_868_TH .code : _XBEE3_XR_BL_DEF_PREFIX ,
9095}
9196
9297_GEN3_BOOTLOADER_ERROR_CHECKSUM = 0x12
297302 HardwareVersion .XBEE3_SMT .code ,
298303 HardwareVersion .XBEE3_TH .code ,
299304 HardwareVersion .XBEE3_RR .code ,
300- HardwareVersion .XBEE3_RR_TH .code ,
301- HardwareVersion .XBEE3_DM_LR .code ,
302- HardwareVersion .XBEE3_DM_LR_868 .code ,
303- HardwareVersion .XBEE_XR_900_TH .code ,
304- HardwareVersion .XBEE_XR_868_TH .code )
305+ HardwareVersion .XBEE3_RR_TH .code )
305306
306- LOCAL_SUPPORTED_HW_VERSIONS = SX_HW_VERSIONS + XBEE3_HW_VERSIONS
307- REMOTE_SUPPORTED_HW_VERSIONS = SX_HW_VERSIONS + XBEE3_HW_VERSIONS + S2C_HW_VERSIONS
307+ XR_HW_VERSIONS = (HardwareVersion .XBEE3_DM_LR .code ,
308+ HardwareVersion .XBEE3_DM_LR_868 .code ,
309+ HardwareVersion .XBEE_XR_900_TH .code ,
310+ HardwareVersion .XBEE_XR_868_TH .code )
311+
312+ LOCAL_SUPPORTED_HW_VERSIONS = SX_HW_VERSIONS + XBEE3_HW_VERSIONS + XR_HW_VERSIONS
313+ REMOTE_SUPPORTED_HW_VERSIONS = SX_HW_VERSIONS + XBEE3_HW_VERSIONS + S2C_HW_VERSIONS + XR_HW_VERSIONS
308314
309315_log = logging .getLogger (__name__ )
310316
@@ -1118,13 +1124,15 @@ class _BootloaderType(Enum):
11181124 | **name** (String): The name of this _BootloaderType.
11191125 | **value** (Integer): The ID of this _BootloaderType.
11201126 """
1121- GEN3_BOOTLOADER = (0x01 , "Generation 3 bootloader" )
1122- GECKO_BOOTLOADER = (0x02 , "Gecko bootloader" )
1123- EMBER_BOOTLOADER = (0x03 , "Ember bootloader" )
1127+ GEN3_BOOTLOADER = (0x01 , "Generation 3 bootloader" , OTAMethod .GPM )
1128+ GECKO_BOOTLOADER = (0x02 , "Gecko bootloader" , OTAMethod .ZCL )
1129+ EMBER_BOOTLOADER = (0x03 , "Ember bootloader" , OTAMethod .EMBER )
1130+ GECKO_BOOTLOADER_XR = (0x04 , "Gecko bootloader with GPM OTA" , OTAMethod .GPM )
11241131
1125- def __init__ (self , identifier , description ):
1132+ def __init__ (self , identifier , description , ota_method ):
11261133 self .__id = identifier
11271134 self .__desc = description
1135+ self .__ota_method = ota_method
11281136
11291137 @classmethod
11301138 def get (cls , identifier ):
@@ -1160,6 +1168,8 @@ def determine_bootloader_type(cls, hw_version):
11601168 return _BootloaderType .GEN3_BOOTLOADER
11611169 if hw_version in XBEE3_HW_VERSIONS :
11621170 return _BootloaderType .GECKO_BOOTLOADER
1171+ if hw_version in XR_HW_VERSIONS :
1172+ return _BootloaderType .GECKO_BOOTLOADER_XR
11631173 if hw_version in S2C_HW_VERSIONS :
11641174 return _BootloaderType .EMBER_BOOTLOADER
11651175
@@ -1185,6 +1195,16 @@ def description(self):
11851195 """
11861196 return self .__desc
11871197
1198+ @property
1199+ def ota_method (self ):
1200+ """
1201+ Returns the over-the-air update method for this bootloader type.
1202+
1203+ Returns:
1204+ :class:`OTAMethod`: OTA method to use with this bootloader.
1205+ """
1206+ return self .__ota_method
1207+
11881208
11891209@unique
11901210class _Gen3BootloaderCmd (Enum ):
@@ -1225,7 +1245,7 @@ def get(cls, identifier):
12251245 :class:`._Gen3BootloaderCommand`: _Gen3BootloaderCommand with the
12261246 given identifier, `None` if not found.
12271247 """
1228- for value in _BootloaderType :
1248+ for value in _Gen3BootloaderCmd :
12291249 if value .identifier == identifier :
12301250 return value
12311251
@@ -5760,7 +5780,8 @@ class _RemoteGPMFirmwareUpdater(_RemoteFirmwareUpdater):
57605780 __DEFAULT_TIMEOUT = 20 # Seconds.
57615781
57625782 def __init__ (self , remote , xml_fw_file , xbee_fw_file = None ,
5763- timeout = __DEFAULT_TIMEOUT , progress_cb = None ):
5783+ timeout = __DEFAULT_TIMEOUT , progress_cb = None ,
5784+ bootloader_type = _BootloaderType .GEN3_BOOTLOADER ):
57645785 """
57655786 Class constructor. Instantiates a new
57665787 :class:`._RemoteGPMFirmwareUpdater` with the given parameters.
@@ -5776,6 +5797,9 @@ def __init__(self, remote, xml_fw_file, xbee_fw_file=None,
57765797 * The current update task as a String
57775798 * The current update task percentage as an Integer
57785799
5800+ bootloader_type (:class:`_BootloaderType`): Bootloader type of the
5801+ remote node.
5802+
57795803 Raises:
57805804 FirmwareUpdateException: If there is any error performing the
57815805 remote firmware update.
@@ -5787,6 +5811,7 @@ def __init__(self, remote, xml_fw_file, xbee_fw_file=None,
57875811 self ._gpm_frame_sent = False
57885812 self ._gpm_frame_received = False
57895813 self ._num_bytes_per_blocks = 0
5814+ self ._bootloader_type = bootloader_type
57905815
57915816 def _get_default_reset_timeout (self ):
57925817 """
@@ -5808,7 +5833,15 @@ def _check_fw_binary_file(self):
58085833 # same folder as the XML firmware file.
58095834 if self ._fw_file is None :
58105835 path = Path (self ._xml_fw_file )
5811- self ._fw_file = str (Path (path .parent ).joinpath (path .stem + EXTENSION_EBIN ))
5836+ self ._fw_file = str (
5837+ Path (path .parent ).joinpath (
5838+ path .stem + (
5839+ EXTENSION_EBIN
5840+ if self ._bootloader_type == _BootloaderType .GEN3_BOOTLOADER
5841+ else EXTENSION_GBL
5842+ )
5843+ )
5844+ )
58125845
58135846 if not _file_exists (self ._fw_file ):
58145847 self ._exit_with_error (_ERROR_FILE_XBEE_FW_NOT_FOUND
@@ -7103,7 +7136,9 @@ def update_local_firmware(target, xml_fw_file, xbee_firmware_file=None,
71037136 hw_version = target .get_hardware_version ()
71047137 if hw_version and hw_version .code not in LOCAL_SUPPORTED_HW_VERSIONS :
71057138 raise OperationNotSupportedException (
7106- "Firmware update only supported in XBee 3 and XBee SX 868/900" )
7139+ "Firmware update only supported in XBee 3, XBee SX 868/900, "
7140+ "and XBee XR 868/900"
7141+ )
71077142
71087143 # Launch the update process.
71097144 if not timeout :
@@ -7120,7 +7155,10 @@ def update_local_firmware(target, xml_fw_file, xbee_firmware_file=None,
71207155 if isinstance (target , XBeeDevice ) and not target ._active_update_type :
71217156 target ._active_update_type = NodeUpdateType .FIRMWARE
71227157 bootloader_type = _determine_bootloader_type (target )
7123- if bootloader_type == _BootloaderType .GECKO_BOOTLOADER :
7158+ if bootloader_type in (
7159+ _BootloaderType .GECKO_BOOTLOADER ,
7160+ _BootloaderType .GECKO_BOOTLOADER_XR ,
7161+ ):
71247162 update_process = _LocalXBee3FirmwareUpdater (
71257163 target , xml_fw_file , xbee_fw_file = xbee_firmware_file ,
71267164 bootloader_fw_file = bootloader_firmware_file ,
@@ -7196,7 +7234,9 @@ def update_remote_firmware(remote, xml_fw_file, firmware_file=None, bootloader_f
71967234 hw_version = remote .get_hardware_version ()
71977235 if hw_version and hw_version .code not in REMOTE_SUPPORTED_HW_VERSIONS :
71987236 raise OperationNotSupportedException (
7199- "Firmware update only supported in XBee 3, XBee SX 868/900, and XBee S2C devices" )
7237+ "Firmware update only supported in XBee 3, XBee SX 868/900, "
7238+ "XBee S2C, and XBee XR 868/900 devices"
7239+ )
72007240
72017241 # Launch the update process.
72027242 if not timeout :
@@ -7217,16 +7257,17 @@ def update_remote_firmware(remote, xml_fw_file, firmware_file=None, bootloader_f
72177257 remote .set_sync_ops_timeout (max (orig_op_timeout , timeout ))
72187258 bootloader_type = _determine_bootloader_type (remote )
72197259 remote .set_sync_ops_timeout (orig_op_timeout )
7220- if bootloader_type == _BootloaderType . GECKO_BOOTLOADER :
7260+ if bootloader_type . ota_method == OTAMethod . ZCL :
72217261 update_process = _RemoteXBee3FirmwareUpdater (
72227262 remote , xml_fw_file , ota_fw_file = firmware_file ,
72237263 otb_fw_file = bootloader_file , timeout = timeout ,
72247264 max_block_size = max_block_size , progress_cb = progress_callback )
7225- elif bootloader_type == _BootloaderType . GEN3_BOOTLOADER :
7265+ elif bootloader_type . ota_method == OTAMethod . GPM :
72267266 update_process = _RemoteGPMFirmwareUpdater (
72277267 remote , xml_fw_file , xbee_fw_file = firmware_file ,
7228- timeout = timeout , progress_cb = progress_callback )
7229- elif bootloader_type == _BootloaderType .EMBER_BOOTLOADER :
7268+ timeout = timeout , progress_cb = progress_callback ,
7269+ bootloader_type = bootloader_type )
7270+ elif bootloader_type .ota_method == OTAMethod .EMBER :
72307271 update_process = _RemoteEmberFirmwareUpdater (
72317272 remote , xml_fw_file , xbee_fw_file = firmware_file ,
72327273 timeout = timeout , force_update = True , progress_cb = progress_callback )
@@ -7474,6 +7515,10 @@ def _get_bootloader_version(xbee):
74747515 _PARAM_READ_RETRIES )
74757516 if bootloader_version is None or len (bootloader_version ) < 2 :
74767517 return None
7518+ if len (bootloader_version ) == 3 :
7519+ # XR returns VH value as three bytes: 0XYYZZ.
7520+ return bootloader_version
7521+
74777522 bootloader_version_array [0 ] = bootloader_version [0 ] & 0x0F
74787523 bootloader_version_array [1 ] = (bootloader_version [1 ] & 0xF0 ) >> 4
74797524 bootloader_version_array [2 ] = bootloader_version [1 ] & 0x0F
0 commit comments