-
Notifications
You must be signed in to change notification settings - Fork 36
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[example] add Minimum Thread Commissioner example
- Loading branch information
Showing
4 changed files
with
341 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Build Minimum Thread Commissioner | ||
|
||
## CMake Build | ||
|
||
```shell | ||
cd ~/ot-commissioner/example | ||
mkdir -p build && cd build | ||
cmake -GNinja .. | ||
ninja | ||
``` | ||
|
||
A `mini_commissioner` binary will be generated in `build/`. | ||
|
||
## Standalone build | ||
|
||
Build and install the OT Commissioner library: | ||
|
||
```c++ | ||
cd ~/ot-commissioner | ||
mkdir -p build && cd build | ||
cmake -GNinja .. | ||
sudo ninja install | ||
``` | ||
|
||
Build the `mini_commissioner` app: | ||
|
||
```c++ | ||
cd ~/ot-commissioner/example | ||
clang++ -std=c++11 -Wall -g mini_commissioner.cpp -o mini_commissioner -lcommissioner | ||
``` | ||
|
||
The `mini_commissioner` binary will be generated in current directory. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
# | ||
# Copyright (c) 2021, The OpenThread Commissioner 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. | ||
# | ||
|
||
project(mini-commissioner VERSION 0.0.1) | ||
|
||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/.. | ||
${CMAKE_CURRENT_BINARY_DIR}/commissioner | ||
) | ||
|
||
add_executable(mini_commissioner mini_commissioner.cpp) | ||
|
||
target_link_libraries(mini_commissioner PRIVATE commissioner) | ||
|
||
install(TARGETS mini_commissioner | ||
RUNTIME DESTINATION bin | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
# Minimum Thread Commissioner | ||
|
||
This directory includes an example of building a minimum Thread Commissioner with the OT Commissioner library. The minimum Thread Commissioner petitions to given Border Router, enables MeshCoP for all joiners and commissions joiners. | ||
|
||
## Build | ||
|
||
See [BUILDING.md](./BUILDING.md) for building this mini Commissioner program. You can find details about the Border Router (`ot-daemon`) and simulation devices in this [codelab](https://openthread.io/codelabs/openthread-simulation-posix). | ||
|
||
## Run the Commissioner | ||
|
||
### Start the BR (ot-daemon) | ||
|
||
See the [codelab](https://openthread.io/codelabs/openthread-simulation-posix). | ||
|
||
### Start the Mini Commissioner | ||
|
||
After a successful build, we should get a `mini_commissioner` binary which can be started with four arguments: | ||
|
||
```shell | ||
./mini_commissioner ::1 49191 00112233445566778899aabbccddeeff ABCDEF | ||
``` | ||
|
||
You can get the usage by starting `mini_commissioner` with no arguments: | ||
|
||
```shell | ||
./minim_commissioner | ||
usage: | ||
mini_commissioner <br-addr> <br-port> <pskc-hex> <pskd> | ||
``` | ||
|
||
> Note: the WiFi/ethernet interface address of the BR should be used but not the Thread interface address. | ||
If everything go smooth, we will get outputs like below: | ||
|
||
```shell | ||
./mini_commissioner ::1 49191 ca117352886a861cce8a91021e65dd1c ABCDEF | ||
=================================================== | ||
[Border Router address] : ::1 | ||
[Border Router port] : 49191 | ||
[PSKc] : ca117352886a861cce8a91021e65dd1c | ||
[PSKd] : ABCDEF | ||
=================================================== | ||
|
||
=================================================== | ||
type CRTL + C to quit! | ||
=================================================== | ||
|
||
petitioning to [::1]:49191 | ||
the commissioner is active: true | ||
enabling MeshCoP for all joiners | ||
waiting for joiners | ||
``` | ||
|
||
> Note: you are free to quit at any time with `CTRL+C`. | ||
### Start the joiner | ||
|
||
See the [codelab](https://openthread.io/codelabs/openthread-simulation-posix). | ||
|
||
if everything go smooth, we will get output like below for two times of joining: | ||
|
||
```shell | ||
joiner "5ab1f2745b625c90" is requesting join the Thread network | ||
joiner "5ab1f2745b625c90" is connected: OK | ||
joiner "5ab1f2745b625c90" is commissioned | ||
[Vendor Name] : OPENTHREAD | ||
[Vendor Model] : NRF52840 | ||
[Vendor SW Version] : 20191113-01632-g | ||
[Vendor Stack Version] : f4ce36000010 | ||
[Provisioning URL] : | ||
[Vendor Data] : | ||
|
||
joiner "5ab1f2745b625c90" is requesting join the Thread network | ||
joiner "5ab1f2745b625c90" is connected: OK | ||
joiner "5ab1f2745b625c90" is commissioned | ||
[Vendor Name] : OPENTHREAD | ||
[Vendor Model] : NRF52840 | ||
[Vendor SW Version] : 20191113-01632-g | ||
[Vendor Stack Version] : f4ce36000010 | ||
[Provisioning URL] : | ||
[Vendor Data] : | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
#include <iomanip> | ||
#include <sstream> | ||
|
||
#include <assert.h> | ||
#include <signal.h> | ||
#include <stdio.h> | ||
|
||
#include <unistd.h> | ||
|
||
#include <commissioner/commissioner.hpp> | ||
|
||
using namespace ot::commissioner; | ||
|
||
static std::string ToHexString(const ByteArray &aBytes) | ||
{ | ||
std::string str; | ||
|
||
for (uint8_t byte : aBytes) | ||
{ | ||
char buf[3]; | ||
|
||
sprintf(buf, "%02x", byte); | ||
str.append(buf); | ||
} | ||
|
||
return str; | ||
} | ||
|
||
static ByteArray FromHexString(const std::string &aHex) | ||
{ | ||
assert(aHex.size() % 2 == 0); | ||
|
||
ByteArray bytes; | ||
|
||
for (size_t i = 0; i < aHex.size(); i += 2) | ||
{ | ||
assert(isxdigit(aHex[i])); | ||
assert(isxdigit(aHex[i + 1])); | ||
|
||
uint8_t x = isdigit(aHex[i]) ? (aHex[i] - '0') : (tolower(aHex[i]) - 'a' + 10); | ||
uint8_t y = isdigit(aHex[i + 1]) ? (aHex[i + 1] - '0') : (tolower(aHex[i + 1]) - 'a' + 10); | ||
|
||
bytes.push_back((x << 4) | y); | ||
} | ||
return bytes; | ||
} | ||
|
||
class MyCommissionerHandler : public CommissionerHandler | ||
{ | ||
public: | ||
MyCommissionerHandler(const std::string &aPskd) | ||
: mPskd(aPskd) | ||
{ | ||
} | ||
|
||
std::string OnJoinerRequest(const ByteArray &aJoinerId) override | ||
{ | ||
auto joinerId = ToHexString(aJoinerId); | ||
|
||
printf("\n"); | ||
printf("joiner \"%s\" is requesting join the Thread network\n", joinerId.c_str()); | ||
|
||
return mPskd; | ||
} | ||
|
||
void OnJoinerConnected(const ByteArray &aJoinerId, Error aError) override | ||
{ | ||
auto joinerId = ToHexString(aJoinerId); | ||
|
||
printf("joiner \"%s\" is connected: %s\n", joinerId.c_str(), aError.ToString().c_str()); | ||
} | ||
|
||
bool OnJoinerFinalize(const ByteArray & aJoinerId, | ||
const std::string &aVendorName, | ||
const std::string &aVendorModel, | ||
const std::string &aVendorSwVersion, | ||
const ByteArray & aVendorStackVersion, | ||
const std::string &aProvisioningUrl, | ||
const ByteArray & aVendorData) override | ||
{ | ||
printf("joiner \"%s\" is commissioned\n", ToHexString(aJoinerId).c_str()); | ||
printf("[Vendor Name] : %s\n", aVendorName.c_str()); | ||
printf("[Vendor Model] : %s\n", aVendorModel.c_str()); | ||
printf("[Vendor SW Version] : %s\n", aVendorSwVersion.c_str()); | ||
printf("[Vendor Stack Version] : %s\n", ToHexString(aVendorStackVersion).c_str()); | ||
printf("[Provisioning URL] : %s\n", aProvisioningUrl.c_str()); | ||
printf("[Vendor Data] : %s\n", ToHexString(aVendorData).c_str()); | ||
|
||
return true; | ||
} | ||
|
||
private: | ||
std::string mPskd; | ||
}; | ||
|
||
std::shared_ptr<Commissioner> commissioner; | ||
|
||
void SignalHandler(int signal) | ||
{ | ||
if (commissioner != nullptr) | ||
{ | ||
printf("\nResigning the commissioner\n"); | ||
commissioner->Resign(); | ||
} | ||
|
||
exit(0); | ||
} | ||
|
||
int main(int argc, const char *argv[]) | ||
{ | ||
if (argc != 5) | ||
{ | ||
printf("usage:\n"); | ||
printf(" mini_commissioner <br-addr> <br-port> <pskc-hex> <pskd>\n"); | ||
return -1; | ||
} | ||
|
||
std::string brAddr = argv[1]; | ||
uint16_t brPort = std::stoul(argv[2]); | ||
ByteArray pskc = FromHexString(argv[3]); | ||
std::string pskd = argv[4]; | ||
|
||
printf("===================================================\n"); | ||
printf("[Border Router address] : %s\n", brAddr.c_str()); | ||
printf("[Border Router port] : %hu\n", brPort); | ||
printf("[PSKc] : %s\n", ToHexString(pskc).c_str()); | ||
printf("[PSKd] : %s\n", pskd.c_str()); | ||
printf("===================================================\n\n"); | ||
|
||
MyCommissionerHandler myHandler{pskd}; | ||
commissioner = Commissioner::Create(myHandler); | ||
|
||
signal(SIGINT, SignalHandler); | ||
printf("===================================================\n"); | ||
printf("type CRTL + C to quit!\n"); | ||
printf("===================================================\n\n"); | ||
|
||
Config config; | ||
config.mEnableCcm = false; | ||
config.mPSKc = pskc; | ||
|
||
Error error; | ||
|
||
if ((error = commissioner->Init(config)) != ErrorCode::kNone) | ||
{ | ||
printf("failed to initialize the commissioner: %s\n", error.ToString().c_str()); | ||
return -1; | ||
} | ||
|
||
std::string existingCommissionerId; | ||
|
||
printf("petitioning to [%s]:%hu\n", brAddr.c_str(), brPort); | ||
error = commissioner->Petition(existingCommissionerId, brAddr, brPort); | ||
if (error != ErrorCode::kNone) | ||
{ | ||
printf("failed to petition to BR at [%s]:%hu: %s\n", brAddr.c_str(), brPort, error.ToString().c_str()); | ||
return -1; | ||
} | ||
|
||
// Check if we are active now. | ||
printf("the commissioner is active: %s\n", commissioner->IsActive() ? "true" : "false"); | ||
assert(commissioner->IsActive()); | ||
|
||
CommissionerDataset dataset; | ||
|
||
printf("enabling MeshCoP for all joiners\n"); | ||
dataset.mPresentFlags |= CommissionerDataset::kSteeringDataBit; | ||
dataset.mSteeringData = {0xFF}; // Set the steeering data to all-ones to allow all joiners. | ||
error = commissioner->SetCommissionerDataset(dataset); | ||
if (error != ErrorCode::kNone) | ||
{ | ||
printf("failed to enable MeshCop for all joiners: %s\n", error.ToString().c_str()); | ||
return -1; | ||
} | ||
|
||
printf("waiting for joiners\n"); | ||
while (true) | ||
{ | ||
sleep(1); | ||
} | ||
|
||
commissioner->Resign().IgnoreError(); | ||
|
||
return 0; | ||
} |