1""" 2 Copyright (c) 2024, The OpenThread Authors. 3 All rights reserved. 4 5 Redistribution and use in source and binary forms, with or without 6 modification, are permitted provided that the following conditions are met: 7 1. Redistributions of source code must retain the above copyright 8 notice, this list of conditions and the following disclaimer. 9 2. Redistributions in binary form must reproduce the above copyright 10 notice, this list of conditions and the following disclaimer in the 11 documentation and/or other materials provided with the distribution. 12 3. Neither the name of the copyright holder nor the 13 names of its contributors may be used to endorse or promote products 14 derived from this software without specific prior written permission. 15 16 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 POSSIBILITY OF SUCH DAMAGE. 27""" 28 29from cli.command import Command, CommandResultNone 30from dataset.dataset import ThreadDataset, initial_dataset 31from tlv.dataset_tlv import MeshcopTlvType 32 33 34def handle_dataset_entry_command(type: MeshcopTlvType, args, context): 35 ds: ThreadDataset = context['dataset'] 36 if len(args) == 0: 37 ds.get_entry(type).print_content() 38 return CommandResultNone() 39 40 ds.set_entry(type, args) 41 print('Done.') 42 return CommandResultNone() 43 44 45class DatasetHelpCommand(Command): 46 47 def get_help_string(self) -> str: 48 return 'Display help message and return.' 49 50 async def execute_default(self, args, context): 51 indent_width = 4 52 indentation = ' ' * indent_width 53 commands: ThreadDataset = context['commands'] 54 ds_command: Command = commands['dataset'] 55 print(ds_command.get_help_string()) 56 print('Subcommands:') 57 for name, subcommand in ds_command._subcommands.items(): 58 print(f'{indentation}{name}') 59 print(f'{indentation}{" " * indent_width}{subcommand.get_help_string()}') 60 return CommandResultNone() 61 62 63class PrintDatasetHexCommand(Command): 64 65 def get_help_string(self) -> str: 66 return 'Print current dataset as a hexadecimal string.' 67 68 async def execute_default(self, args, context): 69 ds: ThreadDataset = context['dataset'] 70 print(ds.to_bytes().hex()) 71 return CommandResultNone() 72 73 74class ReloadDatasetCommand(Command): 75 76 def get_help_string(self) -> str: 77 return 'Reset dataset to the initial value.' 78 79 async def execute_default(self, args, context): 80 context['dataset'].set_from_bytes(initial_dataset) 81 return CommandResultNone() 82 83 84class ActiveTimestampCommand(Command): 85 86 def get_help_string(self) -> str: 87 return 'View and set ActiveTimestamp seconds. Arguments: [seconds (int)]' 88 89 async def execute_default(self, args, context): 90 return handle_dataset_entry_command(MeshcopTlvType.ACTIVETIMESTAMP, args, context) 91 92 93class PendingTimestampCommand(Command): 94 95 def get_help_string(self) -> str: 96 return 'View and set PendingTimestamp seconds. Arguments: [seconds (int)]' 97 98 async def execute_default(self, args, context): 99 return handle_dataset_entry_command(MeshcopTlvType.PENDINGTIMESTAMP, args, context) 100 101 102class NetworkKeyCommand(Command): 103 104 def get_help_string(self) -> str: 105 return 'View and set NetworkKey. Arguments: [nk (hexstring, len=32)]' 106 107 async def execute_default(self, args, context): 108 return handle_dataset_entry_command(MeshcopTlvType.NETWORKKEY, args, context) 109 110 111class NetworkNameCommand(Command): 112 113 def get_help_string(self) -> str: 114 return 'View and set NetworkName. Arguments: [nn (string, maxlen=16)]' 115 116 async def execute_default(self, args, context): 117 return handle_dataset_entry_command(MeshcopTlvType.NETWORKNAME, args, context) 118 119 120class ExtPanIDCommand(Command): 121 122 def get_help_string(self) -> str: 123 return 'View and set ExtPanID. Arguments: [extpanid (hexstring, len=16)]' 124 125 async def execute_default(self, args, context): 126 return handle_dataset_entry_command(MeshcopTlvType.EXTPANID, args, context) 127 128 129class MeshLocalPrefixCommand(Command): 130 131 def get_help_string(self) -> str: 132 return 'View and set MeshLocalPrefix. Arguments: [mlp (hexstring, len=16)]' 133 134 async def execute_default(self, args, context): 135 return handle_dataset_entry_command(MeshcopTlvType.MESHLOCALPREFIX, args, context) 136 137 138class DelayTimerCommand(Command): 139 140 def get_help_string(self) -> str: 141 return 'View and set DelayTimer delay. Arguments: [delay (int)]' 142 143 async def execute_default(self, args, context): 144 return handle_dataset_entry_command(MeshcopTlvType.DELAYTIMER, args, context) 145 146 147class PanIDCommand(Command): 148 149 def get_help_string(self) -> str: 150 return 'View and set PanID. Arguments: [panid (hexstring, len=4)]' 151 152 async def execute_default(self, args, context): 153 return handle_dataset_entry_command(MeshcopTlvType.PANID, args, context) 154 155 156class ChannelCommand(Command): 157 158 def get_help_string(self) -> str: 159 return 'View and set Channel. Arguments: [channel (int)]' 160 161 async def execute_default(self, args, context): 162 return handle_dataset_entry_command(MeshcopTlvType.CHANNEL, args, context) 163 164 165class ChannelMaskCommand(Command): 166 167 def get_help_string(self) -> str: 168 return 'View and set ChannelMask. Arguments: [mask (hexstring)]' 169 170 async def execute_default(self, args, context): 171 return handle_dataset_entry_command(MeshcopTlvType.CHANNELMASK, args, context) 172 173 174class PskcCommand(Command): 175 176 def get_help_string(self) -> str: 177 return 'View and set Pskc. Arguments: [pskc (hexstring, maxlen=32)]' 178 179 async def execute_default(self, args, context): 180 return handle_dataset_entry_command(MeshcopTlvType.PSKC, args, context) 181 182 183class SecurityPolicyCommand(Command): 184 185 def get_help_string(self) -> str: 186 return 'View and set SecurityPolicy. Arguments: '\ 187 '[<rotation_time (int)> [flags (string)] [version_threshold (int)]]' 188 189 async def execute_default(self, args, context): 190 return handle_dataset_entry_command(MeshcopTlvType.SECURITYPOLICY, args, context) 191 192 193class DatasetCommand(Command): 194 195 def __init__(self): 196 self._subcommands = { 197 'help': DatasetHelpCommand(), 198 'hex': PrintDatasetHexCommand(), 199 'reload': ReloadDatasetCommand(), 200 'activetimestamp': ActiveTimestampCommand(), 201 'pendingtimestamp': PendingTimestampCommand(), 202 'networkkey': NetworkKeyCommand(), 203 'networkname': NetworkNameCommand(), 204 'extpanid': ExtPanIDCommand(), 205 'meshlocalprefix': MeshLocalPrefixCommand(), 206 'delay': DelayTimerCommand(), 207 'panid': PanIDCommand(), 208 'channel': ChannelCommand(), 209 'channelmask': ChannelMaskCommand(), 210 'pskc': PskcCommand(), 211 'securitypolicy': SecurityPolicyCommand() 212 } 213 214 def get_help_string(self) -> str: 215 return 'View and manipulate current dataset. ' \ 216 'Call without parameters to show current dataset.' 217 218 async def execute_default(self, args, context): 219 ds: ThreadDataset = context['dataset'] 220 ds.print_content() 221 return CommandResultNone() 222