mirror of
https://github.com/espressif/openthread.git
synced 2026-09-05 08:40:06 +00:00
Add 'parent', 'child' and 'leaderdata' commands to spinel-cli.py (#1136)
* Add 'leaderdata' command to spinel-cli.py. * Add 'parent' command to the spinel-cli.py. * Add 'child' command to the spinel-cli.py * Add THREAD_NEIGHBOR_TABLE property to codec in spinel-cli.
This commit is contained in:
@@ -57,6 +57,7 @@ import traceback
|
||||
|
||||
import optparse
|
||||
|
||||
import binascii
|
||||
import struct
|
||||
import string
|
||||
import textwrap
|
||||
@@ -175,6 +176,7 @@ class SpinelCliCmd(Cmd, SpinelCodec):
|
||||
'networkidtimeout',
|
||||
'networkname',
|
||||
'panid',
|
||||
'parent',
|
||||
'ping',
|
||||
'prefix',
|
||||
'releaserouterid',
|
||||
@@ -545,7 +547,53 @@ class SpinelCliCmd(Cmd, SpinelCodec):
|
||||
Done
|
||||
\033[0m
|
||||
"""
|
||||
pass
|
||||
child_table = self.prop_get_value(SPINEL.PROP_THREAD_CHILD_TABLE)[0]
|
||||
|
||||
if line == 'list':
|
||||
result = ''
|
||||
for child_data in child_table:
|
||||
child_data = child_data[0]
|
||||
child_id = child_data[1] & 0x1FF
|
||||
result += '{} '.format(child_id)
|
||||
print(result)
|
||||
print("Done")
|
||||
|
||||
else:
|
||||
try:
|
||||
child_id = int(line)
|
||||
printed = False
|
||||
for child_data in child_table:
|
||||
child_data = child_data[0]
|
||||
id = child_data[1] & 0x1FF
|
||||
|
||||
if id == child_id:
|
||||
mode = ''
|
||||
if child_data[7] & 0x08:
|
||||
mode += 'r'
|
||||
if child_data[7] & 0x04:
|
||||
mode += 's'
|
||||
if child_data[7] & 0x02:
|
||||
mode += 'd'
|
||||
if child_data[7] & 0x01:
|
||||
mode += 'n'
|
||||
|
||||
print("Child ID: {}".format(id))
|
||||
print("Rloc: {:04x}".format(child_data[1]))
|
||||
print("Ext Addr: {}".format(binascii.hexlify(child_data[0])))
|
||||
print("Mode: {}".format(mode))
|
||||
print("Net Data: {}".format(child_data[4]))
|
||||
print("Timeout: {}".format(child_data[2]))
|
||||
print("Age: {}".format(child_data[3]))
|
||||
print("LQI: {}".format(child_data[5]))
|
||||
print("RSSI: {}".format(child_data[6]))
|
||||
print("Done")
|
||||
|
||||
printed = True
|
||||
|
||||
if not printed:
|
||||
print("Error")
|
||||
except ValueError:
|
||||
print("Error")
|
||||
|
||||
def do_childmax(self, line):
|
||||
"""\033[1m
|
||||
@@ -982,8 +1030,36 @@ class SpinelCliCmd(Cmd, SpinelCodec):
|
||||
def do_leaderdata(self, line):
|
||||
"""
|
||||
leaderdata
|
||||
|
||||
Get the Thread network Leader Data.
|
||||
|
||||
> leaderdata
|
||||
Partition ID: 1987912443
|
||||
Weighting: 64
|
||||
Data Version: 4
|
||||
Stable Data Version: 129
|
||||
Leader Router ID: 47
|
||||
Done
|
||||
"""
|
||||
pass
|
||||
partition_id = self.prop_get_value(SPINEL.PROP_NET_PARTITION_ID)
|
||||
weighting = self.prop_get_value(SPINEL.PROP_THREAD_LEADER_WEIGHT)
|
||||
data_version = self.prop_get_value(SPINEL.PROP_THREAD_NETWORK_DATA_VERSION)
|
||||
stable_version = self.prop_get_value(SPINEL.PROP_THREAD_STABLE_NETWORK_DATA_VERSION)
|
||||
leader_id = self.prop_get_value(SPINEL.PROP_THREAD_LEADER_RID)
|
||||
|
||||
if partition_id is None or \
|
||||
weighting is None or \
|
||||
data_version is None or \
|
||||
stable_version is None or \
|
||||
leader_id is None:
|
||||
print("Error")
|
||||
else:
|
||||
print("Partition ID: %d" % partition_id)
|
||||
print("Weighting: %d" % weighting)
|
||||
print("Data Version: %d" % data_version)
|
||||
print("Stable Data Version: %d" % stable_version)
|
||||
print("Leader Router ID: %d" % leader_id)
|
||||
print("Done")
|
||||
|
||||
def do_leaderweight(self, line):
|
||||
"""
|
||||
@@ -1174,6 +1250,26 @@ class SpinelCliCmd(Cmd, SpinelCodec):
|
||||
"""
|
||||
self.handle_property(line, SPINEL.PROP_MAC_15_4_PANID, 'H')
|
||||
|
||||
def do_parent(self, line):
|
||||
"""
|
||||
parent
|
||||
|
||||
Get the addresses of the parent node.
|
||||
|
||||
> parent
|
||||
Ext Addr: 3ad35f9846ceb9c7
|
||||
Rloc: bc00
|
||||
Done
|
||||
"""
|
||||
ext_addr, rloc = self.prop_get_value(SPINEL.PROP_THREAD_PARENT)
|
||||
|
||||
if ext_addr is None or\
|
||||
rloc is None:
|
||||
print("Error")
|
||||
else:
|
||||
print("Ext Addr: {}".format(binascii.hexlify(ext_addr)))
|
||||
print("Rloc: {:04x}".format(rloc))
|
||||
|
||||
def do_ping(self, line):
|
||||
"""
|
||||
ping <ipaddr> [size] [count] [interval]
|
||||
|
||||
@@ -169,7 +169,7 @@ class SpinelCodec(object):
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def parse_fields(cls, payload, spinel_format):
|
||||
def get_payload_size(cls, spinel_format):
|
||||
map_lengths = {
|
||||
'b': 1,
|
||||
'c': 1,
|
||||
@@ -182,7 +182,8 @@ class SpinelCodec(object):
|
||||
'E': 8,
|
||||
'e': 6,
|
||||
}
|
||||
result = []
|
||||
|
||||
result = 0
|
||||
|
||||
idx = 0
|
||||
while idx < len(spinel_format):
|
||||
@@ -195,15 +196,55 @@ class SpinelCodec(object):
|
||||
struct_end = idx + spinel_format[idx:].index(')')
|
||||
|
||||
struct_format = spinel_format[idx+2:struct_end]
|
||||
struct_len = sum([map_lengths[c] for c in struct_format])
|
||||
result += cls.get_payload_size(struct_format)
|
||||
|
||||
idx = struct_end + 1
|
||||
else:
|
||||
result += map_lengths[format]
|
||||
idx += 1
|
||||
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def parse_fields(cls, payload, spinel_format):
|
||||
result = []
|
||||
|
||||
idx = 0
|
||||
while idx < len(spinel_format):
|
||||
format = spinel_format[idx]
|
||||
|
||||
if format == 'A':
|
||||
if spinel_format[idx+1] != '(':
|
||||
raise ValueError('Invalid structure format')
|
||||
# TODO: count parentheses. There is a problem with arrays placed one by one.
|
||||
array_end = idx + spinel_format[idx:].rindex(')')
|
||||
|
||||
array_format = spinel_format[idx+2:array_end]
|
||||
|
||||
array = []
|
||||
while len(payload):
|
||||
array.append(cls.parse_fields(payload, array_format))
|
||||
payload = payload[cls.get_payload_size(array_format):]
|
||||
|
||||
result.append(tuple(array))
|
||||
idx = array_end + 1
|
||||
|
||||
elif format == 'T':
|
||||
if spinel_format[idx+1] != '(':
|
||||
raise ValueError('Invalid structure format')
|
||||
# TODO: count parentheses. There is a problem with nested structs.
|
||||
struct_end = idx + spinel_format[idx:].index(')')
|
||||
|
||||
struct_format = spinel_format[idx+2:struct_end]
|
||||
struct_len = cls.get_payload_size(struct_format)
|
||||
|
||||
result.append(cls.parse_fields(payload, struct_format))
|
||||
payload = payload[struct_len:]
|
||||
|
||||
idx = struct_end + 1
|
||||
else:
|
||||
result.append(cls.parse_field(payload, spinel_format))
|
||||
payload = payload[map_lengths[spinel_format[idx]]:]
|
||||
result.append(cls.parse_field(payload, format))
|
||||
payload = payload[cls.get_payload_size(format):]
|
||||
|
||||
idx += 1
|
||||
|
||||
@@ -391,9 +432,9 @@ class SpinelPropertyHandler(SpinelCodec):
|
||||
|
||||
def THREAD_LEADER_ADDR(self, _, payload): return self.parse_6(payload)
|
||||
|
||||
def THREAD_PARENT(self, _wpan_api, payload): pass
|
||||
def THREAD_PARENT(self, _wpan_api, payload): return self.parse_fields(payload, "ES")
|
||||
|
||||
def THREAD_CHILD_TABLE(self, _, payload): return self.parse_D(payload)
|
||||
def THREAD_CHILD_TABLE(self, _, payload): return self.parse_fields(payload, "A(T(ESLLCCcC))")
|
||||
|
||||
def THREAD_LEADER_RID(self, _, payload): return self.parse_C(payload)
|
||||
|
||||
@@ -406,11 +447,13 @@ class SpinelPropertyHandler(SpinelCodec):
|
||||
def THREAD_NETWORK_DATA(self, _, payload):
|
||||
return self.parse_D(payload)
|
||||
|
||||
def THREAD_NETWORK_DATA_VERSION(self, _wpan_api, payload): pass
|
||||
def THREAD_NETWORK_DATA_VERSION(self, _wpan_api, payload):
|
||||
return self.parse_C(payload)
|
||||
|
||||
def THREAD_STABLE_NETWORK_DATA(self, _wpan_api, payload): pass
|
||||
|
||||
def THREAD_STABLE_NETWORK_DATA_VERSION(self, _wpan_api, payload): pass
|
||||
def THREAD_STABLE_NETWORK_DATA_VERSION(self, _wpan_api, payload):
|
||||
return self.parse_C(payload)
|
||||
|
||||
def __init__(self):
|
||||
self.autoAddresses = set()
|
||||
@@ -543,6 +586,9 @@ class SpinelPropertyHandler(SpinelCodec):
|
||||
def THREAD_ROUTER_SELECTION_JITTER(self, _, payload):
|
||||
return self.parse_C(payload)
|
||||
|
||||
def THREAD_NEIGHBOR_TABLE(self, _, payload):
|
||||
return self.parse_fields(payload, 'A(T(ESLCcCbLL))')
|
||||
|
||||
def THREAD_CONTEXT_REUSE_DELAY(self, _, payload):
|
||||
return self.parse_L(payload)
|
||||
|
||||
@@ -738,6 +784,7 @@ SPINEL_PROP_DISPATCH = {
|
||||
SPINEL.PROP_THREAD_NETWORK_ID_TIMEOUT: WPAN_PROP_HANDLER.THREAD_NETWORK_ID_TIMEOUT,
|
||||
SPINEL.PROP_THREAD_ACTIVE_ROUTER_IDS: WPAN_PROP_HANDLER.THREAD_ACTIVE_ROUTER_IDS,
|
||||
SPINEL.PROP_THREAD_RLOC16_DEBUG_PASSTHRU: WPAN_PROP_HANDLER.THREAD_RLOC16_DEBUG_PASSTHRU,
|
||||
SPINEL.PROP_THREAD_NEIGHBOR_TABLE: WPAN_PROP_HANDLER.THREAD_NEIGHBOR_TABLE,
|
||||
|
||||
SPINEL.PROP_MESHCOP_JOINER_ENABLE: WPAN_PROP_HANDLER.MESHCOP_JOINER_ENABLE,
|
||||
SPINEL.PROP_MESHCOP_JOINER_CREDENTIAL: WPAN_PROP_HANDLER.MESHCOP_JOINER_CREDENTIAL,
|
||||
|
||||
Reference in New Issue
Block a user