mirror of
https://github.com/espressif/openthread.git
synced 2026-08-28 12:59:54 +00:00
[cli] support joiner discerner (#5298)
This commit adds support joiner discerner in CLI. The format of joiner discerner is `number/length`. For example `0xabc/12` means the discerner value is `0xabc` and the length is `12`.
This commit is contained in:
@@ -81,11 +81,12 @@ Energy: 00050000 0 0 0 0
|
||||
|
||||
### joiner add
|
||||
|
||||
Usage: `commissioner joiner add <eui64> <pskd>`
|
||||
Usage: `commissioner joiner add <eui64>|<discerner> <pskd>`
|
||||
|
||||
Add a Joiner entry.
|
||||
|
||||
- eui64: The IEEE EUI-64 of the Joiner or '\*' to match any Joiner.
|
||||
- discerner: The Joiner discerner in format `number/length`.
|
||||
- pskd: Pre-Shared Key for the Joiner.
|
||||
|
||||
```bash
|
||||
@@ -93,6 +94,11 @@ Add a Joiner entry.
|
||||
Done
|
||||
```
|
||||
|
||||
```bash
|
||||
> commissioner joiner add 0xabc/12 J01NME
|
||||
Done
|
||||
```
|
||||
|
||||
### joiner remove
|
||||
|
||||
Usage: `commissioner joiner remove <eui64>`
|
||||
|
||||
@@ -7,6 +7,7 @@ See [README_COMMISSIONING.md](README_COMMISSIONING.md).
|
||||
## Command List
|
||||
|
||||
- [help](#help)
|
||||
- [discerner](#discerner)
|
||||
- [id](#id)
|
||||
- [start](#start)
|
||||
- [stop](#stop)
|
||||
@@ -28,6 +29,24 @@ stop
|
||||
Done
|
||||
```
|
||||
|
||||
### discerner
|
||||
|
||||
Usage: `joiner discerner [discerner]`
|
||||
|
||||
Print or set the Joiner Discerner. Note this value takes the place of the place of EUI-64 during the joiner session of Thread commissioning.
|
||||
|
||||
- discerner: `clear` to clear discerner, `number/length` to set discerner
|
||||
|
||||
```bash
|
||||
> joiner discerner 0xabc/12
|
||||
Done
|
||||
> joiner discerner
|
||||
0xabc/12
|
||||
Done
|
||||
> joiner discerner clear
|
||||
Done
|
||||
```
|
||||
|
||||
### id
|
||||
|
||||
Usage: `joiner id`
|
||||
|
||||
@@ -399,6 +399,30 @@ otError Interpreter::ParseUnsignedLong(char *aString, unsigned long &aUnsignedLo
|
||||
return (*endptr == '\0') ? OT_ERROR_NONE : OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
otError Interpreter::ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aDiscerner)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
char * separator = strstr(aString, "/");
|
||||
unsigned long length;
|
||||
|
||||
VerifyOrExit(separator != nullptr, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
SuccessOrExit(error = ParseUnsignedLong(separator + 1, length));
|
||||
VerifyOrExit(length > 0 && length <= 64, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
{
|
||||
char * end;
|
||||
unsigned long long value = strtoull(aString, &end, 0);
|
||||
aDiscerner.mValue = value;
|
||||
VerifyOrExit(end == separator, error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
|
||||
aDiscerner.mLength = static_cast<uint8_t>(length);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Interpreter::ParsePingInterval(const char *aString, uint32_t &aInterval)
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
+5
-4
@@ -204,10 +204,11 @@ private:
|
||||
kDefaultPingCount = 1,
|
||||
};
|
||||
|
||||
otError ParsePingInterval(const char *aString, uint32_t &aInterval);
|
||||
void ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
|
||||
void ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]);
|
||||
void ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ParsePingInterval(const char *aString, uint32_t &aInterval);
|
||||
static otError ParseJoinerDiscerner(char *aString, otJoinerDiscerner &aJoinerDiscerner);
|
||||
void ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
|
||||
void ProcessBufferInfo(uint8_t aArgsLength, char *aArgs[]);
|
||||
void ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
|
||||
#if (OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2)
|
||||
void ProcessBackboneRouter(uint8_t aArgsLength, char *aArgs[]);
|
||||
|
||||
|
||||
@@ -116,20 +116,27 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error;
|
||||
otExtAddress addr;
|
||||
const otExtAddress *addrPtr;
|
||||
const otExtAddress *addrPtr = nullptr;
|
||||
otJoinerDiscerner discerner;
|
||||
|
||||
VerifyOrExit(aArgsLength > 2, error = OT_ERROR_INVALID_ARGS);
|
||||
|
||||
memset(&discerner, 0, sizeof(discerner));
|
||||
|
||||
if (strcmp(aArgs[2], "*") == 0)
|
||||
{
|
||||
addrPtr = nullptr;
|
||||
// Intentionally empty
|
||||
}
|
||||
else
|
||||
else if ((error = Interpreter::ParseJoinerDiscerner(aArgs[2], discerner)) == OT_ERROR_NOT_FOUND)
|
||||
{
|
||||
VerifyOrExit(Interpreter::Hex2Bin(aArgs[2], addr.m8, sizeof(addr)) == sizeof(addr),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
addrPtr = &addr;
|
||||
}
|
||||
else if (error != OT_ERROR_NONE)
|
||||
{
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (strcmp(aArgs[1], "add") == 0)
|
||||
{
|
||||
@@ -142,8 +149,16 @@ otError Commissioner::ProcessJoiner(uint8_t aArgsLength, char *aArgs[])
|
||||
SuccessOrExit(error = Interpreter::ParseUnsignedLong(aArgs[4], timeout));
|
||||
}
|
||||
|
||||
SuccessOrExit(
|
||||
error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3], static_cast<uint32_t>(timeout)));
|
||||
if (discerner.mLength)
|
||||
{
|
||||
SuccessOrExit(error = otCommissionerAddJoinerWithDiscerner(mInterpreter.mInstance, &discerner, aArgs[3],
|
||||
static_cast<uint32_t>(timeout)));
|
||||
}
|
||||
else
|
||||
{
|
||||
SuccessOrExit(error = otCommissionerAddJoiner(mInterpreter.mInstance, addrPtr, aArgs[3],
|
||||
static_cast<uint32_t>(timeout)));
|
||||
}
|
||||
}
|
||||
else if (strcmp(aArgs[1], "remove") == 0)
|
||||
{
|
||||
|
||||
+41
-4
@@ -33,6 +33,8 @@
|
||||
|
||||
#include "cli_joiner.hpp"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "cli/cli.hpp"
|
||||
#include "cli/cli_server.hpp"
|
||||
|
||||
@@ -42,12 +44,47 @@ namespace ot {
|
||||
namespace Cli {
|
||||
|
||||
const struct Joiner::Command Joiner::sCommands[] = {
|
||||
{"help", &Joiner::ProcessHelp},
|
||||
{"id", &Joiner::ProcessId},
|
||||
{"start", &Joiner::ProcessStart},
|
||||
{"stop", &Joiner::ProcessStop},
|
||||
{"discerner", &Joiner::ProcessDiscerner}, {"help", &Joiner::ProcessHelp}, {"id", &Joiner::ProcessId},
|
||||
{"start", &Joiner::ProcessStart}, {"stop", &Joiner::ProcessStop},
|
||||
};
|
||||
|
||||
otError Joiner::ProcessDiscerner(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
otError error = OT_ERROR_NONE;
|
||||
|
||||
if (aArgsLength == 2)
|
||||
{
|
||||
otJoinerDiscerner discerner;
|
||||
|
||||
memset(&discerner, 0, sizeof(discerner));
|
||||
if (strcmp(aArgs[1], "clear") == 0)
|
||||
{
|
||||
SuccessOrExit(error = otJoinerSetDiscerner(mInterpreter.mInstance, nullptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
VerifyOrExit(OT_ERROR_NONE == Interpreter::ParseJoinerDiscerner(aArgs[1], discerner),
|
||||
error = OT_ERROR_INVALID_ARGS);
|
||||
SuccessOrExit(error = otJoinerSetDiscerner(mInterpreter.mInstance, &discerner));
|
||||
}
|
||||
}
|
||||
else if (aArgsLength == 1)
|
||||
{
|
||||
const otJoinerDiscerner *discerner = otJoinerGetDiscerner(mInterpreter.mInstance);
|
||||
|
||||
VerifyOrExit(discerner != nullptr, error = OT_ERROR_NOT_FOUND);
|
||||
|
||||
mInterpreter.mServer->OutputFormat("0x%" PRIx64 "/%u\r\n", discerner->mValue, discerner->mLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
otError Joiner::ProcessHelp(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
OT_UNUSED_VARIABLE(aArgsLength);
|
||||
|
||||
@@ -79,6 +79,7 @@ private:
|
||||
otError (Joiner::*mCommand)(uint8_t aArgsLength, char *aArgs[]);
|
||||
};
|
||||
|
||||
otError ProcessDiscerner(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ProcessHelp(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ProcessId(uint8_t aArgsLength, char *aArgs[]);
|
||||
otError ProcessStart(uint8_t aArgsLength, char *aArgs[]);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
proc wait_for {command expected} {
|
||||
proc wait_for {command success {failure {[\r\n]FAILURE_NOT_EXPECTED[\r\n]}}} {
|
||||
set result 0
|
||||
set timeout 1
|
||||
for {set i 0} {$i < 20} {incr i} {
|
||||
@@ -36,9 +36,12 @@ proc wait_for {command expected} {
|
||||
}
|
||||
|
||||
expect {
|
||||
-re $expected {
|
||||
-re $success {
|
||||
set result 1
|
||||
}
|
||||
-re $failure {
|
||||
exit 1
|
||||
}
|
||||
timeout {
|
||||
# Do nothing
|
||||
}
|
||||
@@ -64,9 +67,38 @@ proc spawn_node {id} {
|
||||
return $spawn_id
|
||||
}
|
||||
|
||||
proc setup_leader {} {
|
||||
# Sets up a Thread network spawn_1 as the leader.
|
||||
global spawn_1
|
||||
global spawn_id
|
||||
global env
|
||||
|
||||
set spawn_1 [spawn_node 1]
|
||||
|
||||
set spawn_id $spawn_1
|
||||
send "dataset init new\n"
|
||||
expect "Done"
|
||||
send "dataset commit active\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\n"
|
||||
expect "Done"
|
||||
send "thread start\n"
|
||||
expect "Done"
|
||||
wait_for "state" "leader"
|
||||
expect "Done"
|
||||
}
|
||||
|
||||
proc dispose {} {
|
||||
send "\x04"
|
||||
expect eof
|
||||
}
|
||||
|
||||
proc dispose_leader {} {
|
||||
global spawn_1
|
||||
global spawn_id
|
||||
|
||||
set spawn_id $spawn_1
|
||||
dispose
|
||||
}
|
||||
|
||||
set timeout 10
|
||||
|
||||
@@ -38,7 +38,6 @@ proc setup_nodes {} {
|
||||
global spawn_id
|
||||
global env
|
||||
|
||||
set spawn_1 [spawn_node 1]
|
||||
set spawn_2 [spawn_node 2]
|
||||
set psk "J01NME"
|
||||
|
||||
@@ -48,17 +47,9 @@ proc setup_nodes {} {
|
||||
set eui64 $expect_out(1,string)
|
||||
expect "Done"
|
||||
|
||||
setup_leader
|
||||
|
||||
set spawn_id $spawn_1
|
||||
send "dataset init new\n"
|
||||
expect "Done"
|
||||
send "dataset commit active\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\n"
|
||||
expect "Done"
|
||||
send "thread start\n"
|
||||
expect "Done"
|
||||
wait_for "state" "leader"
|
||||
expect "Done"
|
||||
send "commissioner start\n"
|
||||
expect "Done"
|
||||
expect "Commissioner: active"
|
||||
@@ -84,12 +75,10 @@ proc setup_nodes {} {
|
||||
}
|
||||
|
||||
proc dispose_nodes {} {
|
||||
global spawn_1
|
||||
global spawn_2
|
||||
global spawn_id
|
||||
|
||||
set spawn_id $spawn_1
|
||||
dispose
|
||||
dispose_leader
|
||||
set spawn_id $spawn_2
|
||||
dispose
|
||||
}
|
||||
|
||||
Executable
+85
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/expect -f
|
||||
#
|
||||
# Copyright (c) 2020, The OpenThread Authors.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
# 3. Neither the name of the copyright holder nor the
|
||||
# names of its contributors may be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
|
||||
source "tests/scripts/expect/_common.exp"
|
||||
|
||||
setup_leader
|
||||
|
||||
set pskd "J01NME"
|
||||
set discerner "0xabc/12"
|
||||
|
||||
send "commissioner start\n"
|
||||
expect "Done"
|
||||
expect "Commissioner: active"
|
||||
send "commissioner joiner add 1/0 $pskd\n"
|
||||
expect "InvalidArgs"
|
||||
send "commissioner joiner add $discerner $pskd\n"
|
||||
expect "Done"
|
||||
|
||||
set spawn_2 [spawn_node 2]
|
||||
|
||||
set spawn_id $spawn_2
|
||||
send "mode rs\n"
|
||||
expect "Done"
|
||||
send "ifconfig up\n"
|
||||
expect "Done"
|
||||
send "joiner discerner\n"
|
||||
expect "NotFound"
|
||||
send "joiner discerner 1/1 2\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner 1\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner 1/\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner 1/128\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner 1/-1\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner 1/0\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner invalid/20\n"
|
||||
expect "InvalidArgs"
|
||||
send "joiner discerner clear\n"
|
||||
expect "Done"
|
||||
send "joiner discerner $discerner\n"
|
||||
expect "Done"
|
||||
send "joiner discerner\n"
|
||||
expect "$discerner"
|
||||
expect "Done"
|
||||
send "joiner start $pskd\n"
|
||||
expect "Done"
|
||||
wait_for "" "Join success" "Join failed"
|
||||
send "thread start\n"
|
||||
expect "Done"
|
||||
wait_for "state" "child"
|
||||
expect "Done"
|
||||
|
||||
dispose
|
||||
|
||||
dispose_leader
|
||||
Reference in New Issue
Block a user