diff --git a/Android.mk b/Android.mk
index 250f9d6a8..ee8c0a5de 100644
--- a/Android.mk
+++ b/Android.mk
@@ -312,6 +312,7 @@ LOCAL_SRC_FILES := \
src/cli/cli_coap.cpp \
src/cli/cli_console.cpp \
src/cli/cli_dataset.cpp \
+ src/cli/cli_joiner.cpp \
src/cli/cli_server.cpp \
src/cli/cli_uart.cpp \
src/cli/cli_udp.cpp \
diff --git a/etc/visual-studio/libopenthread-cli-windows.vcxproj b/etc/visual-studio/libopenthread-cli-windows.vcxproj
index 90023b00b..bec386723 100644
--- a/etc/visual-studio/libopenthread-cli-windows.vcxproj
+++ b/etc/visual-studio/libopenthread-cli-windows.vcxproj
@@ -60,6 +60,7 @@
+
diff --git a/etc/visual-studio/libopenthread-cli-windows.vcxproj.filters b/etc/visual-studio/libopenthread-cli-windows.vcxproj.filters
index 9bd264429..24477b720 100644
--- a/etc/visual-studio/libopenthread-cli-windows.vcxproj.filters
+++ b/etc/visual-studio/libopenthread-cli-windows.vcxproj.filters
@@ -16,6 +16,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/etc/visual-studio/libopenthread-cli.vcxproj b/etc/visual-studio/libopenthread-cli.vcxproj
index 056570495..4add881b5 100644
--- a/etc/visual-studio/libopenthread-cli.vcxproj
+++ b/etc/visual-studio/libopenthread-cli.vcxproj
@@ -58,6 +58,7 @@
+
diff --git a/etc/visual-studio/libopenthread-cli.vcxproj.filters b/etc/visual-studio/libopenthread-cli.vcxproj.filters
index 3e307f0a1..b28bcd5c1 100644
--- a/etc/visual-studio/libopenthread-cli.vcxproj.filters
+++ b/etc/visual-studio/libopenthread-cli.vcxproj.filters
@@ -13,6 +13,9 @@
Source Files
+
+ Source Files
+
Source Files
diff --git a/src/cli/Makefile.am b/src/cli/Makefile.am
index 880775087..a0e32ee2a 100644
--- a/src/cli/Makefile.am
+++ b/src/cli/Makefile.am
@@ -147,6 +147,7 @@ SOURCES_COMMON = \
cli_coap_secure.cpp \
cli_console.cpp \
cli_dataset.cpp \
+ cli_joiner.cpp \
cli_server.cpp \
cli_uart.cpp \
cli_udp.cpp \
@@ -166,6 +167,7 @@ noinst_HEADERS = \
cli_coap_secure.hpp \
cli_console.hpp \
cli_dataset.hpp \
+ cli_joiner.hpp \
cli_server.hpp \
cli_uart.hpp \
cli_udp.hpp \
diff --git a/src/cli/cli.cpp b/src/cli/cli.cpp
index d7108613c..4c8c9d03d 100644
--- a/src/cli/cli.cpp
+++ b/src/cli/cli.cpp
@@ -45,7 +45,6 @@
#include
#include
-#include
#include
#include
#include
@@ -165,7 +164,6 @@ const struct Command Interpreter::sCommands[] = {
#endif
#if OPENTHREAD_ENABLE_JOINER
{"joiner", &Interpreter::ProcessJoiner},
- {"joinerid", &Interpreter::ProcessJoinerId},
#endif
#if OPENTHREAD_FTD
{"joinerport", &Interpreter::ProcessJoinerPort},
@@ -305,6 +303,9 @@ Interpreter::Interpreter(Instance *aInstance)
#endif
#if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
, mCoapSecure(*this)
+#endif
+#if OPENTHREAD_ENABLE_JOINER
+ , mJoiner(*this)
#endif
, mInstance(aInstance)
{
@@ -3461,68 +3462,12 @@ void Interpreter::HandlePanIdConflict(uint16_t aPanId, uint32_t aChannelMask)
void Interpreter::ProcessJoiner(int argc, char *argv[])
{
- otError error = OT_ERROR_NONE;
-
- VerifyOrExit(argc > 0, error = OT_ERROR_INVALID_ARGS);
-
- if (strcmp(argv[0], "start") == 0)
- {
- const char *provisioningUrl;
- VerifyOrExit(argc > 1, error = OT_ERROR_INVALID_ARGS);
- provisioningUrl = (argc > 2) ? argv[2] : NULL;
- otJoinerStart(mInstance, argv[1], provisioningUrl, PACKAGE_NAME, OPENTHREAD_CONFIG_PLATFORM_INFO,
- PACKAGE_VERSION, NULL, &Interpreter::s_HandleJoinerCallback, this);
- }
- else if (strcmp(argv[0], "stop") == 0)
- {
- otJoinerStop(mInstance);
- }
- else
- {
- ExitNow(error = OT_ERROR_INVALID_ARGS);
- }
-
-exit:
+ otError error;
+ error = mJoiner.Process(argc, argv);
AppendResult(error);
}
-void Interpreter::ProcessJoinerId(int argc, char *argv[])
-{
- OT_UNUSED_VARIABLE(argv);
-
- otError error = OT_ERROR_NONE;
- otExtAddress joinerId;
-
- VerifyOrExit(argc == 0, error = OT_ERROR_INVALID_ARGS);
-
- otJoinerGetId(mInstance, &joinerId);
- OutputBytes(joinerId.m8, sizeof(joinerId));
- mServer->OutputFormat("\r\n");
-
-exit:
- AppendResult(error);
-}
-
-#endif // OPENTHREAD_ENABLE_JOINER
-
-void OTCALL Interpreter::s_HandleJoinerCallback(otError aError, void *aContext)
-{
- static_cast(aContext)->HandleJoinerCallback(aError);
-}
-
-void Interpreter::HandleJoinerCallback(otError aError)
-{
- switch (aError)
- {
- case OT_ERROR_NONE:
- mServer->OutputFormat("Join success\r\n");
- break;
-
- default:
- mServer->OutputFormat("Join failed [%s]\r\n", otThreadErrorToString(aError));
- break;
- }
-}
+#endif
#if OPENTHREAD_FTD
void Interpreter::ProcessJoinerPort(int argc, char *argv[])
diff --git a/src/cli/cli.hpp b/src/cli/cli.hpp
index c86e8c8fa..bca954be6 100644
--- a/src/cli/cli.hpp
+++ b/src/cli/cli.hpp
@@ -43,6 +43,7 @@
#include
#include "cli/cli_dataset.hpp"
+#include "cli/cli_joiner.hpp"
#include "cli/cli_udp.hpp"
#if OPENTHREAD_ENABLE_APPLICATION_COAP
@@ -102,6 +103,7 @@ class Interpreter
friend class Coap;
friend class CoapSecure;
friend class Dataset;
+ friend class Joiner;
friend class UdpExample;
public:
@@ -254,8 +256,7 @@ private:
#endif
#if OPENTHREAD_ENABLE_JOINER
void ProcessJoiner(int argc, char *argv[]);
- void ProcessJoinerId(int argc, char *argv[]);
-#endif // OPENTHREAD_ENABLE_JOINER
+#endif
#if OPENTHREAD_FTD
void ProcessJoinerPort(int argc, char *argv[]);
#endif
@@ -369,7 +370,6 @@ private:
const otMessageInfo *aMessageInfo,
void * aContext);
#endif
- static void OTCALL s_HandleJoinerCallback(otError aError, void *aContext);
#if OPENTHREAD_ENABLE_DNS_CLIENT
static void s_HandleDnsResponse(void * aContext,
@@ -397,7 +397,6 @@ private:
#ifndef OTDLL
void HandleDiagnosticGetResponse(Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
#endif
- void HandleJoinerCallback(otError aError);
#if OPENTHREAD_ENABLE_DNS_CLIENT
void HandleDnsResponse(const char *aHostname, Ip6::Address &aAddress, uint32_t aTtl, otError aResult);
#endif
@@ -453,15 +452,17 @@ private:
Dataset mDataset;
#if OPENTHREAD_ENABLE_APPLICATION_COAP
-
Coap mCoap;
+#endif
-#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
#if OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
-
CoapSecure mCoapSecure;
+#endif
+
+#if OPENTHREAD_ENABLE_JOINER
+ Joiner mJoiner;
+#endif
-#endif // OPENTHREAD_ENABLE_APPLICATION_COAP_SECURE
Instance *mInstance;
};
diff --git a/src/cli/cli_joiner.cpp b/src/cli/cli_joiner.cpp
new file mode 100644
index 000000000..fdecb42a3
--- /dev/null
+++ b/src/cli/cli_joiner.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+/**
+ * @file
+ * This file implements a simple CLI for the Joiner role.
+ */
+
+#include "cli_joiner.hpp"
+
+#include "cli/cli.hpp"
+#include "cli/cli_server.hpp"
+
+#if OPENTHREAD_ENABLE_JOINER
+
+namespace ot {
+namespace Cli {
+
+const struct Joiner::Command Joiner::sCommands[] = {
+ {"help", &Joiner::ProcessHelp},
+ {"id", &Joiner::ProcessId},
+ {"start", &Joiner::ProcessStart},
+ {"stop", &Joiner::ProcessStop},
+};
+
+otError Joiner::ProcessHelp(int argc, char *argv[])
+{
+ OT_UNUSED_VARIABLE(argc);
+ OT_UNUSED_VARIABLE(argv);
+
+ for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
+ {
+ mInterpreter.mServer->OutputFormat("%s\r\n", sCommands[i].mName);
+ }
+
+ return OT_ERROR_NONE;
+}
+
+otError Joiner::ProcessId(int argc, char *argv[])
+{
+ otError error;
+ otExtAddress joinerId;
+
+ OT_UNUSED_VARIABLE(argc);
+ OT_UNUSED_VARIABLE(argv);
+
+ SuccessOrExit(error = otJoinerGetId(mInterpreter.mInstance, &joinerId));
+
+ mInterpreter.OutputBytes(joinerId.m8, sizeof(joinerId));
+ mInterpreter.mServer->OutputFormat("\r\n");
+
+exit:
+ return error;
+}
+
+otError Joiner::ProcessStart(int argc, char *argv[])
+{
+ otError error;
+ const char *provisioningUrl = NULL;
+
+ VerifyOrExit(argc > 1, error = OT_ERROR_INVALID_ARGS);
+
+ if (argc > 2)
+ {
+ provisioningUrl = argv[2];
+ }
+
+ error = otJoinerStart(mInterpreter.mInstance, argv[1], provisioningUrl, PACKAGE_NAME,
+ OPENTHREAD_CONFIG_PLATFORM_INFO, PACKAGE_VERSION, NULL, &Joiner::HandleCallback, this);
+
+exit:
+ return error;
+}
+
+otError Joiner::ProcessStop(int argc, char *argv[])
+{
+ OT_UNUSED_VARIABLE(argc);
+ OT_UNUSED_VARIABLE(argv);
+
+ return otJoinerStop(mInterpreter.mInstance);
+}
+
+otError Joiner::Process(int argc, char *argv[])
+{
+ otError error = OT_ERROR_INVALID_ARGS;
+
+ if (argc < 1)
+ {
+ ProcessHelp(0, NULL);
+ }
+ else
+ {
+ for (size_t i = 0; i < OT_ARRAY_LENGTH(sCommands); i++)
+ {
+ if (strcmp(argv[0], sCommands[i].mName) == 0)
+ {
+ error = (this->*sCommands[i].mCommand)(argc, argv);
+ break;
+ }
+ }
+ }
+
+ return error;
+}
+
+void OTCALL Joiner::HandleCallback(otError aError, void *aContext)
+{
+ static_cast(aContext)->HandleCallback(aError);
+}
+
+void Joiner::HandleCallback(otError aError)
+{
+ switch (aError)
+ {
+ case OT_ERROR_NONE:
+ mInterpreter.mServer->OutputFormat("Join success\r\n");
+ break;
+
+ default:
+ mInterpreter.mServer->OutputFormat("Join failed [%s]\r\n", otThreadErrorToString(aError));
+ break;
+ }
+}
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_ENABLE_JOINER
diff --git a/src/cli/cli_joiner.hpp b/src/cli/cli_joiner.hpp
new file mode 100644
index 000000000..1cb712706
--- /dev/null
+++ b/src/cli/cli_joiner.hpp
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2019, 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.
+ */
+
+/**
+ * @file
+ * This file contains definitions for a simple CLI to control the Joiner role.
+ */
+
+#ifndef CLI_JOINER_HPP_
+#define CLI_JOINER_HPP_
+
+#include "openthread-core-config.h"
+
+#include
+
+#if OPENTHREAD_ENABLE_JOINER
+
+namespace ot {
+namespace Cli {
+
+class Interpreter;
+
+/**
+ * This class implements the CLI CoAP Secure server and client.
+ *
+ */
+class Joiner
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param[in] aInterpreter The CLI interpreter.
+ *
+ */
+ explicit Joiner(Interpreter &aInterpreter)
+ : mInterpreter(aInterpreter)
+ {
+ }
+
+ /**
+ * This method interprets a list of CLI arguments.
+ *
+ * @param[in] argc The number of elements in argv.
+ * @param[in] argv A pointer to an array of command line arguments.
+ *
+ */
+ otError Process(int argc, char *argv[]);
+
+private:
+ struct Command
+ {
+ const char *mName;
+ otError (Joiner::*mCommand)(int argc, char *argv[]);
+ };
+
+ otError ProcessHelp(int argc, char *argv[]);
+ otError ProcessId(int argc, char *argv[]);
+ otError ProcessStart(int argc, char *argv[]);
+ otError ProcessStop(int argc, char *argv[]);
+
+ static void OTCALL HandleCallback(otError aError, void *aContext);
+ void HandleCallback(otError aError);
+
+ static const Command sCommands[];
+ Interpreter & mInterpreter;
+};
+
+} // namespace Cli
+} // namespace ot
+
+#endif // OPENTHREAD_ENABLE_JOINER
+
+#endif // CLI_JOINER_HPP_
diff --git a/tests/scripts/thread-cert/node_cli.py b/tests/scripts/thread-cert/node_cli.py
index b7cc08ef3..4d4b6653f 100644
--- a/tests/scripts/thread-cert/node_cli.py
+++ b/tests/scripts/thread-cert/node_cli.py
@@ -326,7 +326,7 @@ class otCli:
return addr64
def get_joiner_id(self):
- self.send_command('joinerid')
+ self.send_command('joiner id')
i = self._expect('([0-9a-fA-F]{16})')
if i == 0:
addr = self.pexpect.match.groups()[0].decode("utf-8")
diff --git a/tools/harness-thci/OpenThread.py b/tools/harness-thci/OpenThread.py
index 0c785c83e..239cd8a6c 100644
--- a/tools/harness-thci/OpenThread.py
+++ b/tools/harness-thci/OpenThread.py
@@ -777,7 +777,7 @@ class OpenThread(IThci):
if bType == MacType.FactoryMac:
macAddr64 = self.__sendCommand('eui64')[0]
elif bType == MacType.HashMac:
- macAddr64 = self.__sendCommand('joinerid')[0]
+ macAddr64 = self.__sendCommand('joiner id')[0]
else:
macAddr64 = self.__sendCommand('extaddr')[0]
print macAddr64