def zha_security(controller=False): empty_key_data = t.EmberKeyData() empty_key_data.contents = t.fixed_list(16, t.uint8_t)([t.uint8_t(0)] * 16) zha_key = t.EmberKeyData() zha_key.contents = t.fixed_list( 16, t.uint8_t)([t.uint8_t(c) for c in b"ZigBeeAlliance09"]) isc = t.EmberInitialSecurityState() isc.bitmask = t.uint16_t( t.EmberInitialSecurityBitmask.HAVE_PRECONFIGURED_KEY | t.EmberInitialSecurityBitmask.REQUIRE_ENCRYPTED_KEY) isc.preconfiguredKey = zha_key isc.networkKey = empty_key_data isc.networkKeySequenceNumber = t.uint8_t(0) isc.preconfiguredTrustCenterEui64 = t.EmberEUI64([t.uint8_t(0)] * 8) if controller: isc.bitmask |= ( t.EmberInitialSecurityBitmask.TRUST_CENTER_GLOBAL_LINK_KEY | t.EmberInitialSecurityBitmask.HAVE_NETWORK_KEY) isc.bitmask = t.uint16_t(isc.bitmask) random_key = t.fixed_list( 16, t.uint8_t)([t.uint8_t(x) for x in os.urandom(16)]) isc.networkKey = random_key return isc
async def form_network(self, channel=15, pan_id=None, extended_pan_id=None): channel = t.uint8_t(channel) if pan_id is None: pan_id = t.uint16_t.from_bytes(os.urandom(2), 'little') pan_id = t.uint16_t(pan_id) if extended_pan_id is None: extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8) initial_security_state = bellows.zigbee.util.zha_security( controller=True) v = await self._ezsp.setInitialSecurityState(initial_security_state) assert v[0] == t.EmberStatus.SUCCESS # TODO: Better check parameters = t.EmberNetworkParameters() parameters.panId = pan_id parameters.extendedPanId = extended_pan_id parameters.radioTxPower = t.uint8_t(8) parameters.radioChannel = channel parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION parameters.nwkManagerId = t.EmberNodeId(0) parameters.nwkUpdateId = t.uint8_t(0) parameters.channels = t.uint32_t(0) await self._ezsp.formNetwork(parameters) await self._ezsp.setValue(t.EzspValueId.VALUE_STACK_TOKEN_WRITING, 1)
class Commissioning(Cluster): """Attributes and commands for commissioning and managing a ZigBee device.""" cluster_id = 0x0015 ep_attribute = 'commissioning' attributes = { # Startup Parameters 0x0000: ('short_address', t.uint16_t), 0x0001: ('extended_pan_id', t.EmberEUI64), 0x0002: ('pan_id', t.uint16_t), 0x0003: ('channelmask', t.uint32_t), # bitmap32 0x0004: ('protocol_version', t.uint8_t), 0x0005: ('stack_profile', t.uint8_t), 0x0006: ('startup_control', t.uint8_t), # enum8 0x0010: ('trust_center_address', t.EmberEUI64), 0x0011: ('trust_center_master_key', t.fixed_list(16, t.uint8_t)), 0x0012: ('network_key', t.fixed_list(16, t.uint8_t)), 0x0013: ('use_insecure_join', t.Bool), 0x0014: ('preconfigured_link_key', t.fixed_list(16, t.uint8_t)), 0x0015: ('network_key_seq_num', t.uint8_t), 0x0016: ('network_key_type', t.uint8_t), # enum8 0x0017: ('network_manager_address', t.uint16_t), # Join Parameters 0x0020: ('scan_attempts', t.uint8_t), 0x0021: ('time_between_scans', t.uint16_t), 0x0022: ('rejoin_interval', t.uint16_t), 0x0023: ('max_rejoin_interval', t.uint16_t), # End Device Parameters 0x0030: ('indirect_poll_rate', t.uint16_t), 0x0031: ('parent_retry_threshold', t.uint8_t), # Concentrator Parameters 0x0040: ('concentrator_flag', t.Bool), 0x0041: ('concentrator_radius', t.uint8_t), 0x0042: ('concentrator_discovery_time', t.uint8_t), } server_commands = { 0x0000: ('restart_device', (t.uint8_t, t.uint8_t, t.uint8_t), False), 0x0001: ('save_startup_parameters', (t.uint8_t, t.uint8_t), False), 0x0002: ('restore_startup_parameters', (t.uint8_t, t.uint8_t), False), 0x0003: ('reset_startup_parameters', (t.uint8_t, t.uint8_t), False), } client_commands = { 0x0000: ('restart_device_response', (t.uint8_t, ), True), 0x0001: ('save_startup_params_response', (t.uint8_t, ), True), 0x0002: ('restore_startup_params_response', (t.uint8_t, ), True), 0x0003: ('reset_startup_params_response', (t.uint8_t, ), True), }
def test_fixed_list(): list_type = t.fixed_list(2, t.uint8_t) data = b"\x01\xFE" extra = b"extarlist \xaa\55" res, rest = list_type.deserialize(data + extra) assert rest == extra assert res == [1, 254]
class MultistateValueReg(Cluster): cluster_id = 0x0612 attributes = { 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
class AnalogValueReg(Cluster): cluster_id = 0x0606 attributes = { 0x0016: ('cov_increment', t.Single), 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
class MultistateOutputReg(Cluster): cluster_id = 0x0610 attributes = { 0x001f: ('device_type', t.LVBytes), 0x0028: ('feed_back_value', t.uint8_t), # enum8 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
class MultistateInputRegular(Cluster): cluster_id = 0x060e ep_attribute = 'bacnet_regular_multistate_input' attributes = { 0x001f: ('device_type', t.LVBytes), 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
class AnalogOutputRegular(Cluster): cluster_id = 0x0604 ep_attribute = 'bacnet_regular_analog_output' attributes = { 0x0016: ('cov_increment', t.Single), 0x001f: ('device_type', t.LVBytes), 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x0076: ('update_interval', t.uint8_t), 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
class BinaryValueReg(Cluster): cluster_id = 0x060c attributes = { 0x000f: ('change_of_state_count', t.uint32_t), 0x0010: ('change_of_state_time', DateTime), 0x0021: ('elapsed_active_time', t.uint32_t), 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x0072: ('time_of_at_reset', DateTime), 0x0073: ('time_of_sc_reset', DateTime), 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
def aes_mmo_hash(data): result_len = 0 remaining_length = 0 length = len(data) result = bytearray([0] * AES.block_size) temp = bytearray([0] * AES.block_size) if (data and length > 0): remaining_length = length & (AES.block_size - 1) if (length >= AES.block_size): # Mask out the lower byte since hash update will hash # everything except the last piece, if the last piece # is less than 16 bytes. hashed_length = (length & ~(AES.block_size - 1)) (result_len, result) = aes_mmo_hash_update(result_len, result, data) data = data[hashed_length:] for i in range(remaining_length): temp[i] = data[i] # Per the spec, Concatenate a 1 bit followed by all zero bits # (previous memset() on temp[] set the rest of the bits to zero) temp[remaining_length] = 0x80 result_len += remaining_length # If appending the bit string will push us beyond the 16-byte boundary # we must hash that block and append another 16-byte block. if ((AES.block_size - remaining_length) < 3): (result_len, result) = aes_mmo_hash_update(result_len, result, temp) # Since this extra data is due to the concatenation, # we remove that length. We want the length of data only # and not the padding. result_len -= AES.block_size temp = bytearray([0] * AES.block_size) bit_size = result_len * 8 temp[AES.block_size - 2] = (bit_size >> 8) & 0xFF temp[AES.block_size - 1] = (bit_size) & 0xFF (result_len, result) = aes_mmo_hash_update(result_len, result, temp) key = t.EmberKeyData() key.contents = t.fixed_list(16, t.uint8_t)([t.uint8_t(c) for c in result]) return key
class BinaryOutputRegular(Cluster): cluster_id = 0x060a ep_attribute = 'bacnet_regular_binary_output' attributes = { 0x000f: ('change_of_state_count', t.uint32_t), 0x0010: ('change_of_state_time', DateTime), 0x001f: ('device_type', t.LVBytes), 0x0021: ('elapsed_active_time', t.uint32_t), 0x0028: ('feed_back_value', t.uint8_t), # enum8 0x004b: ('object_id', t.fixed_list(4, t.uint8_t)), 0x004d: ('object_name', t.LVBytes), 0x004f: ('object_type', t.uint16_t), # enum16 0x0072: ('time_of_at_reset', DateTime), 0x0073: ('time_of_sc_reset', DateTime), 0x00a8: ('profile_name', t.LVBytes), } server_commands = {} client_commands = {}
def form(ctx, channel, pan_id, extended_pan_id): """Create a new ZigBee network""" s = yield from util.setup(ctx.obj['device'], util.print_cb) v = yield from util.networkInit(s) if v[0] == t.EmberStatus.SUCCESS: LOGGER.debug("Network was up, leaving...") v = yield from s.leaveNetwork() util.check(v[0], "Failure leaving network: %s" % (v[0], )) yield from asyncio.sleep(1) # TODO initial_security_state = util.zha_security(controller=True) v = yield from s.setInitialSecurityState(initial_security_state) util.check(v[0], "Setting security state failed: %s" % (v[0], )) yield from util.basic_tc_permits(s) if channel: channel = t.uint8_t(channel) else: channel = t.uint8_t(17) if extended_pan_id: extended_pan_id = util.parse_epan(extended_pan_id) else: extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8) if pan_id: pan_id = t.uint16_t(pan_id) else: pan_id = t.uint16_t.from_bytes(os.urandom(2), 'little') parameters = t.EmberNetworkParameters() parameters.panId = pan_id parameters.extendedPanId = extended_pan_id parameters.radioTxPower = t.uint8_t(8) parameters.radioChannel = channel parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION parameters.nwkManagerId = t.EmberNodeId(0) parameters.nwkUpdateId = t.uint8_t(0) parameters.channels = t.uint32_t(0) click.echo(parameters) LOGGER.info("Forming network ...") fut = asyncio.Future() def cb(fut, frame_name, response): if frame_name == 'stackStatusHandler': fut.set_result(response) s.add_callback(functools.partial(cb, fut)) v = yield from s.formNetwork(parameters) util.check(v[0], "Failed to form network: %s" % (v[0], )) v = yield from fut util.check( v[0], "Network didn't come up after form", t.EmberStatus.NETWORK_UP, ) yield from s.setValue(t.EzspValueId.VALUE_STACK_TOKEN_WRITING, 1) yield from asyncio.sleep(0.1) s.close()
'setGpioCurrentConfiguration': (0xAC, (t.uint8_t, t.uint8_t, t.uint8_t), (t.EzspStatus, )), 'setGpioPowerUpDownConfiguration': (0xAD, (t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t), (t.EzspStatus, )), 'setGpioRadioPowerMask': (0xAE, (t.uint32_t, ), ()), 'setCtune': (0xF5, (t.uint16_t, ), ()), 'getCtune': (0xF6, (), (t.uint16_t, )), 'setChannelMap': (0xF7, (t.uint8_t, t.uint8_t), ()), # 5. Utilities Frames 'nop': (0x05, (), ()), 'echo': (0x81, (t.LVBytes, ), (t.LVBytes, )), 'invalidCommand': (0x58, (), (t.EzspStatus, )), 'callback': (0x06, (), ()), 'noCallbacks': (0x07, (), ()), 'setToken': (0x09, (t.uint8_t, t.fixed_list(8, t.uint8_t)), (t.EmberStatus, )), 'getToken': (0x0A, (t.uint8_t, ), (t.EmberStatus, t.fixed_list(8, t.uint8_t))), 'getMfgToken': (0x0B, (t.EzspMfgTokenId, ), (t.LVBytes, )), 'setMfgToken': (0x0C, (t.EzspMfgTokenId, t.LVBytes), (t.EmberStatus, )), 'stackTokenChangedHandler': (0x0D, (), (t.uint16_t, )), 'getRandomNumber': (0x49, (), (t.EmberStatus, t.uint16_t)), 'setTimer': (0x0E, (t.uint8_t, t.uint16_t, t.EmberEventUnits, t.Bool), (t.EmberStatus, )), 'getTimer': (0x4E, (t.uint8_t, ), (t.uint16_t, t.EmberEventUnits, t.Bool)), 'timerHandler': (0x0F, (), (t.uint8_t, )), 'debugWrite': (0x12, (t.Bool, t.LVBytes), (t.EmberStatus, )), 'readAndClearCounters': (0x65, (), (t.fixed_list(t.EmberCounterType.COUNTER_TYPE_COUNT, t.uint16_t), )),
'getPolicy': (0x56, (t.EzspPolicyId, ), (t.EzspStatus, t.EzspDecisionId)), 'getValue': (0xAA, (t.EzspValueId, ), (t.EzspStatus, t.LVBytes)), 'getExtendedValue': (0x03, (t.EzspExtendedValueId, t.uint32_t), (t.EzspStatus, t.LVBytes)), 'setValue': (0xAB, (t.EzspValueId, t.LVBytes), (t.EzspStatus, )), 'setGpioCurrentConfiguration': (0xAC, (t.uint8_t, t.uint8_t, t.uint8_t), (t.EzspStatus, )), 'setGpioPowerUpDownConfiguration': (0xAD, (t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t), (t.EzspStatus, )), 'setGpioRadioPowerMask': (0xAE, (t.uint32_t, ), ()), 'setCtune': (0xF5, (t.uint16_t, ), ()), 'getCtune': (0xF6, (), (t.uint16_t, )), # 5. Utilities Frames 'nop': (0x05, (), ()), 'echo': (0x81, (t.LVBytes, ), (t.LVBytes, )), 'invalidCommand': (0x58, (), (t.EzspStatus, )), 'callback': (0x06, (), ()), 'noCallbacks': (0x07, (), ()), 'setToken': (0x09, (t.uint8_t, t.fixed_list(8, t.uint8_t)), (t.EmberStatus, )), 'getToken': (0x0A, (t.uint8_t, ), (t.EmberStatus, t.fixed_list(8, t.uint8_t))), 'getMfgToken': (0x0B, (t.EzspMfgTokenId, ), (t.LVBytes, )), 'setMfgToken': (0x0C, (t.EzspMfgTokenId, t.LVBytes), (t.EmberStatus, )), 'stackTokenChangedHandler': (0x0D, (), (t.uint16_t, )), 'getRandomNumber': (0x49, (), (t.EmberStatus, t.uint16_t)), 'setTimer': (0x0E, (t.uint8_t, t.uint16_t, t.EmberEventUnits, t.Bool), (t.EmberStatus, )), 'getTimer': (0x4E, (t.uint8_t, ), (t.uint16_t, t.EmberEventUnits, t.Bool)), 'timerHandler': (0x0F, (), (t.uint8_t, )), 'debugWrite': (0x12, (t.Bool, t.LVBytes), (t.EmberStatus, )), 'readAndClearCounters': (0x65, (), (t.fixed_list(t.EmberCounterType.COUNTER_TYPE_COUNT, t.uint16_t), )), 'readCounters': (0xF1, (), (t.fixed_list(t.EmberCounterType.COUNTER_TYPE_COUNT, t.uint16_t), )), 'counterRolloverHandler': (0xF2, (), (t.EmberCounterType, )), 'delayTest': (0x9D, (t.uint16_t, ), ()), 'getLibraryStatus': (0x01, (t.uint8_t, ), (t.EmberLibraryStatus, )), 'getXncpInfo': (0x13, (), (t.EmberStatus, t.uint16_t, t.uint16_t)),
HARDWARE_FAILURE = 0xc0 # An operation was unsuccessful due to a SOFTWARE_FAILURE = 0xc1 # An operation was unsuccessful due to a CALIBRATION_ERROR = 0xc2 # An error occurred during calibration. class Analog: pass class Discrete: pass DATA_TYPES = { 0x00: ('No data', None, None), 0x08: ('General', t.fixed_list(1, t.uint8_t), Discrete), 0x09: ('General', t.fixed_list(2, t.uint8_t), Discrete), 0x0a: ('General', t.fixed_list(3, t.uint8_t), Discrete), 0x0b: ('General', t.fixed_list(4, t.uint8_t), Discrete), 0x0c: ('General', t.fixed_list(5, t.uint8_t), Discrete), 0x0d: ('General', t.fixed_list(6, t.uint8_t), Discrete), 0x0e: ('General', t.fixed_list(7, t.uint8_t), Discrete), 0x0f: ('General', t.fixed_list(8, t.uint8_t), Discrete), 0x10: ('Boolean', t.Bool, Discrete), 0x18: ('Bitmap', t.uint8_t, Discrete), 0x19: ('Bitmap', t.uint16_t, Discrete), 0x1a: ('Bitmap', t.uint24_t, Discrete), 0x1b: ('Bitmap', t.uint32_t, Discrete), 0x1c: ('Bitmap', t.uint40_t, Discrete), 0x1d: ('Bitmap', t.uint48_t, Discrete), 0x1e: ('Bitmap', t.uint56_t, Discrete),
def parse_epan(epan): """Parse a user specified extended PAN ID""" epan_list = [t.uint8_t(x, 16) for x in epan.split(":")] return t.fixed_list(8, t.uint8_t)(epan_list)
def join(ctx, channels, pan_id, extended_pan_id): """Join an existing ZigBee network as an end device""" def cb(fut, frame_name, response): if frame_name == 'stackStatusHandler': fut.set_result(response) s = yield from util.setup(ctx.obj['device'], ctx.obj['baudrate']) channel = None if len(channels) != 1: if pan_id or extended_pan_id: raise click.BadOptionUsage( "Specify exactly one channel to join a specific network") else: channel = t.uint8_t(channels[0]) if not (pan_id or extended_pan_id): scan_type = t.EzspNetworkScanType.ACTIVE_SCAN channel_mask = util.channel_mask(channels) click.echo("PAN not provided, scanning channels %s..." % (' '.join(map(str, channels)), )) v = yield from s.startScan(scan_type, channel_mask, 3) networks = [n[0] for n in v if n[0].allowingJoin] if len(networks) == 0: click.echo("No joinable networks found") return 1 if len(networks) > 1: click.echo("Multiple joinable networks found. Refusing to pick.") return 1 network = networks[0] pan_id = network.panId extended_pan_id = network.extendedPanId channel = network.channel click.echo("Found network %s %s on channel %s" % ( pan_id, extended_pan_id, channel, )) if pan_id is None: pan_id = t.uint16_t(0) else: pan_id = t.uint16_t(pan_id) if isinstance(extended_pan_id, str): extended_pan_id = util.parse_epan(extended_pan_id) if extended_pan_id is None: extended_pan_id = t.fixed_list(8, t.uint8_t)([t.uint8_t(0)] * 8) v = yield from util.network_init(s) if v[0] == t.EmberStatus.SUCCESS: LOGGER.debug("Network was up, leaving...") v = yield from s.leaveNetwork() util.check(v[0], "Failure leaving network: %s" % (v[0], )) yield from asyncio.sleep(1) # TODO initial_security_state = zutil.zha_security() v = yield from s.setInitialSecurityState(initial_security_state) util.check(v[0], "Setting security state failed: %s" % (v[0], )) parameters = t.EmberNetworkParameters() parameters.extendedPanId = extended_pan_id parameters.panId = pan_id parameters.radioTxPower = t.uint8_t(8) parameters.radioChannel = t.uint8_t(channel) parameters.joinMethod = t.EmberJoinMethod.USE_MAC_ASSOCIATION parameters.nwkManagerId = t.EmberNodeId(0) parameters.nwkUpdateId = t.uint8_t(0) parameters.channels = t.uint32_t(0) click.echo(parameters) fut = asyncio.Future() cbid = s.add_callback(functools.partial(cb, fut)) v = yield from s.joinNetwork(t.EmberNodeType.END_DEVICE, parameters) util.check(v[0], "Joining network failed: %s" % (v[0], )) v = yield from fut click.echo(v) s.remove_callback(cbid) s.close()
0x0001: ('IEEE_addr_req', (NWKI, ('RequestType', t.uint8_t), ('StartIndex', t.uint8_t))), 0x0002: ('Node_Desc_req', (NWKI, )), 0x0003: ('Power_Desc_req', (NWKI, )), 0x0004: ('Simple_Desc_req', (NWKI, ('EndPoint', t.uint8_t))), 0x0005: ('Active_EP_req', (NWKI, )), 0x0006: ('Match_Desc_req', (NWKI, ('ProfileID', t.uint16_t), ('InClusterList', t.LVList(t.uint16_t)), ('OutClusterList', t.LVList(t.uint16_t)))), # 0x0010: ('Complex_Desc_req', (NWKI, )), 0x0011: ('User_Desc_req', (NWKI, )), 0x0012: ('Discovery_Cache_req', (NWK, IEEE)), 0x0013: ('Device_annce', (NWK, IEEE, ('Capability', t.uint8_t))), 0x0014: ('User_Desc_set', (NWKI, ('UserDescriptor', t.fixed_list(16, t.uint8_t)))), # Really a string 0x0015: ('System_Server_Discovery_req', (('ServerMask', t.uint16_t), )), 0x0016: ('Discovery_store_req', (NWK, IEEE, ('NodeDescSize', t.uint8_t), ('PowerDescSize', t.uint8_t), ('ActiveEPSize', t.uint8_t), ('SimpleDescSizeList', t.LVList(t.uint8_t)))), 0x0017: ('Node_Desc_store_req', (NWK, IEEE, ('NodeDescriptor', NodeDescriptor))), 0x0019: ('Active_EP_store_req', (NWK, IEEE, ('ActiveEPList', t.LVList(t.uint8_t)))), 0x001a: ('Simple_Desc_store_req', (NWK, IEEE, ('SimpleDescriptor', SizePrefixedSimpleDescriptor))), 0x001b: ('Remove_node_cache_req', (NWK, IEEE)), 0x001c: ('Find_node_cache_req', (NWK, IEEE)), 0x001d: ('Extended_Simple_Desc_req', (NWKI, ('EndPoint', t.uint8_t), ('StartIndex', t.uint8_t))),
0xAD, (t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t, t.uint8_t), (t.EzspStatus, ), ), "setGpioRadioPowerMask": (0xAE, (t.uint32_t, ), ()), "setCtune": (0xF5, (t.uint16_t, ), ()), "getCtune": (0xF6, (), (t.uint16_t, )), "setChannelMap": (0xF7, (t.uint8_t, t.uint8_t), ()), # 5. Utilities Frames "nop": (0x05, (), ()), "echo": (0x81, (t.LVBytes, ), (t.LVBytes, )), "invalidCommand": (0x58, (), (t.EzspStatus, )), "callback": (0x06, (), ()), "noCallbacks": (0x07, (), ()), "setToken": (0x09, (t.uint8_t, t.fixed_list(8, t.uint8_t)), (t.EmberStatus, )), "getToken": (0x0A, (t.uint8_t, ), (t.EmberStatus, t.fixed_list(8, t.uint8_t))), "getMfgToken": (0x0B, (t.EzspMfgTokenId, ), (t.LVBytes, )), "setMfgToken": (0x0C, (t.EzspMfgTokenId, t.LVBytes), (t.EmberStatus, )), "stackTokenChangedHandler": (0x0D, (), (t.uint16_t, )), "getRandomNumber": (0x49, (), (t.EmberStatus, t.uint16_t)), "setTimer": ( 0x0E, (t.uint8_t, t.uint16_t, t.EmberEventUnits, t.Bool), (t.EmberStatus, ), ), "getTimer": (0x4E, (t.uint8_t, ), (t.uint16_t, t.EmberEventUnits, t.Bool)), "timerHandler": (0x0F, (), (t.uint8_t, )), "debugWrite": (0x12, (t.Bool, t.LVBytes), (t.EmberStatus, )), "readAndClearCounters": (