mirror of
https://github.com/espressif/openthread.git
synced 2026-08-03 17:37:46 +00:00
[CoAP] Adding CLI commands (#1539)
* [CoAP] Adding CLI commands Adds CLI commands for a simple CoAP client and server with one resource
This commit is contained in:
committed by
Jonathan Hui
parent
6c44b0759a
commit
6a520dd63c
@@ -45,6 +45,10 @@ libopenthread_cli_a_SOURCES = \
|
||||
cli_uart.cpp \
|
||||
cli_udp.cpp \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
libopenthread_cli_a_SOURCES += cli_coap.cpp
|
||||
endif
|
||||
|
||||
noinst_HEADERS = \
|
||||
cli.hpp \
|
||||
@@ -54,6 +58,10 @@ noinst_HEADERS = \
|
||||
cli_server.hpp \
|
||||
cli_udp.hpp \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
noinst_HEADERS += cli_coap.hpp
|
||||
endif
|
||||
|
||||
if OPENTHREAD_BUILD_COVERAGE
|
||||
CLEANFILES = $(wildcard *.gcda *.gcno)
|
||||
|
||||
@@ -14,6 +14,7 @@ OpenThread test scripts use the CLI to execute test cases.
|
||||
* [child](#child-list)
|
||||
* [childmax](#childmax)
|
||||
* [childtimeout](#childtimeout)
|
||||
* [coap](#coap-server-phase)
|
||||
* [commissioner](#commissioner-start-provisioningurl)
|
||||
* [contextreusedelay](#contextreusedelay)
|
||||
* [counter](#counter)
|
||||
@@ -269,6 +270,57 @@ Set the Thread Child Timeout value.
|
||||
Done
|
||||
```
|
||||
|
||||
### coap server \<phase\>
|
||||
|
||||
Starts and stops the simple CoAP server.
|
||||
|
||||
* phase: Either "start" or "stop" the server.
|
||||
|
||||
```bash
|
||||
> coap server start
|
||||
Server started with resource '': Done
|
||||
> coap server stop
|
||||
Server stopped: Done
|
||||
```
|
||||
|
||||
### coap server name \[URI\]
|
||||
|
||||
Outputs the currently used URI String of the CoAP resource.
|
||||
|
||||
* URI: If provided the URI String will be changed to the new value.
|
||||
|
||||
```bash
|
||||
> coap server name
|
||||
Current resource name is '': Done
|
||||
> coap server name test
|
||||
Changing resource name to 'test': Done
|
||||
```
|
||||
|
||||
### coap client \<method\> \<IPv6address\> \<URI\> \[payload\] \[messageType\]
|
||||
|
||||
Simple CoAP client that can send Non-/Confirmable GET/PUT/POST/DELETE messages.
|
||||
|
||||
* method: CoAP method to be used (GET/PUT/POST/DELETE).
|
||||
* IPv6address: IP address of the CoAP server to query.
|
||||
* URI: URI String of the resource on the CoAP server.
|
||||
* payload: In case of PUT/POST/DELETE a payload can be encapsulated.
|
||||
* messageType: Switch between confirmable ("con") and non-confirmable (default).
|
||||
|
||||
```bash
|
||||
> coap client get fdde:ad00:beef:0:dbaa:f1d0:8afb:30dc test
|
||||
Sending CoAP message: Done
|
||||
Received CoAP request from [fdde:ad00:beef:0:dbaa:f1d0:8afb:30dc]: GET
|
||||
CoAP response sent successfully!
|
||||
Received CoAP response with payload: 30
|
||||
> coap client put fdde:ad00:beef:0:dbaa:f1d0:8afb:30dc test non-con somePayload
|
||||
Sending CoAP message: Done
|
||||
> coap client put fdde:ad00:beef:0:dbaa:f1d0:8afb:30dc test con 123
|
||||
Sending CoAP message: Done
|
||||
Received CoAP request from [fdde:ad00:beef:0:dbaa:f1d0:8afb:30dc]: PUT with payload: ba 00 00 20
|
||||
CoAP response sent successfully!
|
||||
Received CoAP response
|
||||
```
|
||||
|
||||
### commissioner start \<provisioningUrl\>
|
||||
|
||||
Start the Commissioner role.
|
||||
|
||||
@@ -66,6 +66,9 @@
|
||||
#include "cli.hpp"
|
||||
#include "cli_dataset.hpp"
|
||||
#include "cli_uart.hpp"
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
#include "cli_coap.hpp"
|
||||
#endif
|
||||
|
||||
using Thread::Encoding::BigEndian::HostSwap16;
|
||||
using Thread::Encoding::BigEndian::HostSwap32;
|
||||
@@ -84,6 +87,9 @@ const struct Command Interpreter::sCommands[] =
|
||||
{ "child", &Interpreter::ProcessChild },
|
||||
{ "childmax", &Interpreter::ProcessChildMax },
|
||||
{ "childtimeout", &Interpreter::ProcessChildTimeout },
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
{ "coap", &Interpreter::ProcessCoap },
|
||||
#endif
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
{ "commissioner", &Interpreter::ProcessCommissioner },
|
||||
#endif
|
||||
@@ -602,6 +608,17 @@ exit:
|
||||
AppendResult(error);
|
||||
}
|
||||
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
|
||||
void Interpreter::ProcessCoap(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error;
|
||||
error = Coap::Process(mInstance, argc, argv, *sServer);
|
||||
AppendResult(error);
|
||||
}
|
||||
|
||||
#endif // OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
|
||||
void Interpreter::ProcessContextIdReuseDelay(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
@@ -49,6 +49,10 @@
|
||||
#include <cli/cli_server.hpp>
|
||||
#include <common/code_utils.hpp>
|
||||
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
#include <coap/coap_header.hpp>
|
||||
#endif
|
||||
|
||||
#ifndef OTDLL
|
||||
#include <net/icmp6.hpp>
|
||||
#include <common/timer.hpp>
|
||||
@@ -162,6 +166,9 @@ private:
|
||||
void ProcessChild(int argc, char *argv[]);
|
||||
void ProcessChildTimeout(int argc, char *argv[]);
|
||||
void ProcessChildMax(int argc, char *argv[]);
|
||||
#if OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
void ProcessCoap(int argc, char *argv[]);
|
||||
#endif //OPENTHREAD_ENABLE_APPLICATION_COAP
|
||||
#if OPENTHREAD_ENABLE_COMMISSIONER
|
||||
void ProcessCommissioner(int argc, char *argv[]);
|
||||
#endif // OPENTHREAD_ENABLE_COMMISSIONER
|
||||
|
||||
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 coap server and client.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <cli/cli.hpp>
|
||||
#include <cli/cli_coap.hpp>
|
||||
#include <coap/coap_header.hpp>
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
const CoapCommand Coap::sCommands[] =
|
||||
{
|
||||
{ "client", &ProcessClient },
|
||||
{ "server", &ProcessServer }
|
||||
};
|
||||
|
||||
Server *Coap::sServer;
|
||||
otCoapResource Coap::sResource;
|
||||
otInstance *Coap::sInstance;
|
||||
char Coap::sUriPath[kMaxUriLength];
|
||||
|
||||
void Coap::PrintPayload(otMessage *aMessage)
|
||||
{
|
||||
uint8_t buf[kMaxBufferSize];
|
||||
uint16_t bytesToPrint;
|
||||
uint16_t bytesPrinted = 0;
|
||||
uint16_t length = otMessageGetLength(aMessage) - otMessageGetOffset(aMessage);
|
||||
|
||||
if (length > 0)
|
||||
{
|
||||
sServer->OutputFormat(" with payload: ");
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
bytesToPrint = (length < sizeof(buf)) ? length : sizeof(buf);
|
||||
otMessageRead(aMessage, otMessageGetOffset(aMessage) + bytesPrinted, buf, bytesToPrint);
|
||||
|
||||
OutputBytes(buf, static_cast<uint8_t>(bytesToPrint));
|
||||
|
||||
length -= bytesToPrint;
|
||||
bytesPrinted += bytesToPrint;
|
||||
}
|
||||
}
|
||||
sServer->OutputFormat("\r\n");
|
||||
}
|
||||
|
||||
void Coap::ConvertToLower(char *aString)
|
||||
{
|
||||
uint8_t i = 0;
|
||||
while (aString[i])
|
||||
{
|
||||
aString[i] = tolower(aString[i]);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
void Coap::OutputBytes(const uint8_t *aBytes, uint8_t aLength)
|
||||
{
|
||||
for (int i = 0; i < aLength; i++)
|
||||
{
|
||||
sServer->OutputFormat("%02x ", aBytes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError Coap::Process(otInstance *aInstance, int argc, char *argv[], Server &aServer)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
sInstance = aInstance;
|
||||
sServer = &aServer;
|
||||
sResource.mUriPath = sUriPath;
|
||||
sResource.mContext = aInstance;
|
||||
sResource.mHandler = (otCoapRequestHandler) &Coap::s_HandleServerResponse;
|
||||
|
||||
VerifyOrExit(argc > 0, error = kThreadError_InvalidArgs);
|
||||
for (unsigned int i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++)
|
||||
{
|
||||
if (strcmp(argv[0], sCommands[i].mName) == 0)
|
||||
{
|
||||
error = sCommands[i].mCommand(argc - 1, argv + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
ThreadError Coap::ProcessServer(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
|
||||
VerifyOrExit(argc > 0, error = kThreadError_InvalidArgs);
|
||||
|
||||
ConvertToLower(argv[0]);
|
||||
if (strcmp(argv[0], "start") == 0)
|
||||
{
|
||||
SuccessOrExit(error = otCoapServerStart(sInstance));
|
||||
SuccessOrExit(error = otCoapServerAddResource(sInstance, &sResource));
|
||||
sServer->OutputFormat("Server started with resource '%s': ", sResource.mUriPath);
|
||||
}
|
||||
else if (strcmp(argv[0], "stop") == 0)
|
||||
{
|
||||
otCoapServerRemoveResource(sInstance, &sResource);
|
||||
SuccessOrExit(error = otCoapServerStop(sInstance));
|
||||
sServer->OutputFormat("Server stopped: ");
|
||||
}
|
||||
else if (strcmp(argv[0], "name") == 0)
|
||||
{
|
||||
if (argc > 1)
|
||||
{
|
||||
strlcpy(sUriPath, argv[1], kMaxUriLength);
|
||||
sServer->OutputFormat("Changing resource name to '%s': ", sResource.mUriPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
sServer->OutputFormat("Current resource name is '%s': ", sResource.mUriPath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_InvalidArgs);
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
void OTCALL Coap::s_HandleServerResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
|
||||
otMessageInfo *aMessageInfo)
|
||||
{
|
||||
static_cast<Coap *>(aContext)->HandleServerResponse(aHeader, aMessage, aMessageInfo);
|
||||
}
|
||||
|
||||
void Coap::HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, otMessageInfo *aMessageInfo)
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
otCoapHeader responseHeader;
|
||||
otMessage *responseMessage;
|
||||
otCoapCode responseCode = kCoapCodeEmpty ;
|
||||
char responseContent = '0';
|
||||
|
||||
sServer->OutputFormat("Received CoAP request from [%x:%x:%x:%x:%x:%x:%x:%x]: ",
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[0]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[1]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[2]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[3]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[4]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[5]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[6]),
|
||||
HostSwap16(aMessageInfo->mSockAddr.mFields.m16[7]));
|
||||
|
||||
switch (otCoapHeaderGetCode(aHeader))
|
||||
{
|
||||
case kCoapRequestGet:
|
||||
sServer->OutputFormat("GET");
|
||||
break;
|
||||
|
||||
case kCoapRequestDelete:
|
||||
sServer->OutputFormat("DELETE");
|
||||
break;
|
||||
|
||||
case kCoapRequestPut:
|
||||
sServer->OutputFormat("PUT");
|
||||
break;
|
||||
|
||||
case kCoapRequestPost:
|
||||
sServer->OutputFormat("POST");
|
||||
break;
|
||||
|
||||
default:
|
||||
sServer->OutputFormat("Undefined\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
PrintPayload(aMessage);
|
||||
|
||||
if ((otCoapHeaderGetType(aHeader) == kCoapTypeConfirmable) || otCoapHeaderGetCode(aHeader) == kCoapRequestGet)
|
||||
{
|
||||
if (otCoapHeaderGetCode(aHeader) == kCoapRequestGet)
|
||||
{
|
||||
responseCode = kCoapResponseContent;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseCode = kCoapResponseValid;
|
||||
}
|
||||
|
||||
otCoapHeaderInit(&responseHeader, kCoapTypeAcknowledgment, responseCode);
|
||||
otCoapHeaderSetMessageId(&responseHeader, otCoapHeaderGetMessageId(aHeader));
|
||||
otCoapHeaderSetToken(&responseHeader, otCoapHeaderGetToken(aHeader), otCoapHeaderGetTokenLength(aHeader));
|
||||
|
||||
if (otCoapHeaderGetCode(aHeader) == kCoapRequestGet)
|
||||
{
|
||||
otCoapHeaderSetPayloadMarker(&responseHeader);
|
||||
}
|
||||
|
||||
responseMessage = otCoapNewMessage(sInstance, &responseHeader);
|
||||
VerifyOrExit(responseMessage != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
if (otCoapHeaderGetCode(aHeader) == kCoapRequestGet)
|
||||
{
|
||||
SuccessOrExit(error = otMessageAppend(responseMessage, &responseContent, sizeof(responseContent)));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = otCoapSendResponse(sInstance, responseMessage, aMessageInfo));
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
if (error != kThreadError_None && responseMessage != NULL)
|
||||
{
|
||||
sServer->OutputFormat("Cannot send CoAP response message: Error %d\r\n", error);
|
||||
otMessageFree(responseMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (responseCode >= kCoapResponseCodeMin)
|
||||
{
|
||||
sServer->OutputFormat("CoAP response sent successfully!\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ThreadError Coap::ProcessClient(int argc, char *argv[])
|
||||
{
|
||||
ThreadError error = kThreadError_None;
|
||||
otMessage *message = otCoapNewMessage(sInstance, NULL);
|
||||
otMessageInfo messageInfo;
|
||||
otCoapHeader header;
|
||||
|
||||
// Default parameters
|
||||
char coapUri[kMaxUriLength] = "test";
|
||||
otCoapType coapType = kCoapTypeNonConfirmable;
|
||||
otCoapCode coapCode = kCoapRequestGet;
|
||||
otIp6Address coapDestinationIp;
|
||||
|
||||
VerifyOrExit(argc > 0, error = kThreadError_InvalidArgs);
|
||||
|
||||
// CoAP-Code
|
||||
ConvertToLower(argv[0]);
|
||||
if (strcmp(argv[0], "get") == 0)
|
||||
{
|
||||
coapCode = kCoapRequestGet;
|
||||
}
|
||||
else if (strcmp(argv[0], "post") == 0)
|
||||
{
|
||||
coapCode = kCoapRequestPost;
|
||||
}
|
||||
else if (strcmp(argv[0], "put") == 0)
|
||||
{
|
||||
coapCode = kCoapRequestPut;
|
||||
}
|
||||
else if (strcmp(argv[0], "delete") == 0)
|
||||
{
|
||||
coapCode = kCoapRequestDelete;
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_Parse);
|
||||
}
|
||||
|
||||
// Destination IPv6 address
|
||||
if (argc > 1)
|
||||
{
|
||||
SuccessOrExit(error = otIp6AddressFromString(argv[1], &coapDestinationIp));
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_InvalidArgs);
|
||||
}
|
||||
|
||||
// CoAP-URI
|
||||
if (argc > 2)
|
||||
{
|
||||
strlcpy(coapUri, argv[2], kMaxUriLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
ExitNow(error = kThreadError_InvalidArgs);
|
||||
}
|
||||
|
||||
// CoAP-Type
|
||||
ConvertToLower(argv[3]);
|
||||
if ((argc > 3) && (strcmp(argv[3], "con") == 0))
|
||||
{
|
||||
coapType = kCoapTypeConfirmable;
|
||||
}
|
||||
|
||||
otCoapHeaderInit(&header, coapType, coapCode);
|
||||
otCoapHeaderGenerateToken(&header, Thread::Coap::Header::kDefaultTokenLength);
|
||||
SuccessOrExit(error = otCoapHeaderAppendUriPathOptions(&header, coapUri));
|
||||
otCoapHeaderSetPayloadMarker(&header);
|
||||
|
||||
message = otCoapNewMessage(sInstance, &header);
|
||||
VerifyOrExit(message != NULL, error = kThreadError_NoBufs);
|
||||
|
||||
// Embed content into message if given
|
||||
if (argc > 4)
|
||||
{
|
||||
SuccessOrExit(error = otMessageAppend(message, &argv[4], sizeof(argv[4])));
|
||||
}
|
||||
|
||||
memset(&messageInfo, 0, sizeof(messageInfo));
|
||||
messageInfo.mPeerAddr = coapDestinationIp;
|
||||
messageInfo.mPeerPort = OT_DEFAULT_COAP_PORT;
|
||||
messageInfo.mInterfaceId = OT_NETIF_INTERFACE_ID_THREAD;
|
||||
|
||||
if ((coapType == kCoapTypeConfirmable) || coapCode == kCoapRequestGet)
|
||||
{
|
||||
error = otCoapSendRequest(sInstance, message, &messageInfo,
|
||||
(otCoapResponseHandler) &Coap::s_HandleClientResponse, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = otCoapSendRequest(sInstance, message, &messageInfo, NULL, NULL);
|
||||
}
|
||||
|
||||
sServer->OutputFormat("Sending CoAP message: ");
|
||||
|
||||
exit:
|
||||
if ((error != kThreadError_None) && (message != NULL))
|
||||
{
|
||||
otMessageFree(message);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
void OTCALL Coap::s_HandleClientResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
|
||||
otMessageInfo *aMessageInfo, ThreadError aResult)
|
||||
{
|
||||
static_cast<Coap *>(aContext)->HandleClientResponse(aHeader, aMessage, aMessageInfo, aResult);
|
||||
}
|
||||
|
||||
void Coap::HandleClientResponse(otCoapHeader *aHeader, otMessage *aMessage, otMessageInfo *aMessageInfo,
|
||||
ThreadError aResult)
|
||||
{
|
||||
if (aResult != kThreadError_None)
|
||||
{
|
||||
sServer->OutputFormat("Error receiving CoAP response message: %d", aResult);
|
||||
}
|
||||
else
|
||||
{
|
||||
sServer->OutputFormat("Received CoAP response");
|
||||
PrintPayload(aMessage);
|
||||
}
|
||||
|
||||
(void)aHeader;
|
||||
(void)aMessageInfo;
|
||||
}
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright (c) 2017, 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 CoAP server and client.
|
||||
*/
|
||||
|
||||
#ifndef CLI_COAP_HPP_
|
||||
#define CLI_COAP_HPP_
|
||||
|
||||
namespace Thread {
|
||||
namespace Cli {
|
||||
|
||||
/**
|
||||
* This structure represents a CLI command.
|
||||
*
|
||||
*/
|
||||
struct CoapCommand
|
||||
{
|
||||
const char *mName; ///< A pointer to the command string.
|
||||
ThreadError(*mCommand)(int argc, char *argv[]); ///< A function pointer to process the command.
|
||||
};
|
||||
|
||||
/**
|
||||
* This class implements the CLI CoAP server and client.
|
||||
*
|
||||
*/
|
||||
class Coap
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* This method interprets a list of CLI arguments.
|
||||
*
|
||||
* @param[in] aInstance The OpenThread instance structure.
|
||||
* @param[in] argc The number of elements in argv.
|
||||
* @param[in] argv A pointer to an array of command line arguments.
|
||||
* @param[in] aServer A reference to the CLI server.
|
||||
*
|
||||
*/
|
||||
static ThreadError Process(otInstance *aInstance, int argc, char *argv[], Server &aServer);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
kMaxUriLength = 32,
|
||||
kMaxBufferSize = 16
|
||||
};
|
||||
static void PrintPayload(otMessage *aMessage);
|
||||
static void ConvertToLower(char *aString);
|
||||
static void OutputBytes(const uint8_t *aBytes, uint8_t aLength);
|
||||
|
||||
static ThreadError ProcessClient(int argc, char *argv[]);
|
||||
static ThreadError ProcessServer(int argc, char *argv[]);
|
||||
|
||||
static void OTCALL s_HandleServerResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
|
||||
otMessageInfo *aMessageInfo);
|
||||
static void HandleServerResponse(otCoapHeader *aHeader, otMessage *aMessage, otMessageInfo *aMessageInfo);
|
||||
static void OTCALL s_HandleClientResponse(void *aContext, otCoapHeader *aHeader, otMessage *aMessage,
|
||||
otMessageInfo *aMessageInfo, ThreadError aResult);
|
||||
static void HandleClientResponse(otCoapHeader *aHeader, otMessage *aMessage, otMessageInfo *aMessageInfo,
|
||||
ThreadError aResult);
|
||||
|
||||
static const CoapCommand sCommands[];
|
||||
static Server *sServer;
|
||||
static otCoapResource sResource;
|
||||
static otInstance *sInstance;
|
||||
static char sUriPath[kMaxUriLength];
|
||||
};
|
||||
|
||||
} // namespace Cli
|
||||
} // namespace Thread
|
||||
|
||||
#endif // CLI_COAP_HPP_
|
||||
Reference in New Issue
Block a user