mirror of
https://github.com/espressif/openthread.git
synced 2026-11-09 07:50:55 +00:00
[meshcop] simplify energy scan client and server (#8230)
This commit updates `EnergyScanClient` and `EnergyScanServer`. On server side, we prepare the report message after we parse the request and directly append the results in the report message as energy scans are performed. Client side is also updated to correctly handle the case where the report message contains greater number of results that can be supported on the client based on its configuration.
This commit is contained in:
@@ -43,6 +43,7 @@
|
||||
#include "common/instance.hpp"
|
||||
#include "common/locator_getters.hpp"
|
||||
#include "common/log.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "meshcop/meshcop.hpp"
|
||||
#include "meshcop/meshcop_tlvs.hpp"
|
||||
#include "thread/thread_netif.hpp"
|
||||
@@ -111,14 +112,8 @@ void EnergyScanClient::HandleReport(void *aContext, otMessage *aMessage, const o
|
||||
|
||||
void EnergyScanClient::HandleReport(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
uint32_t mask;
|
||||
|
||||
OT_TOOL_PACKED_BEGIN
|
||||
struct
|
||||
{
|
||||
MeshCoP::EnergyListTlv tlv;
|
||||
uint8_t list[OPENTHREAD_CONFIG_TMF_ENERGY_SCAN_MAX_RESULTS];
|
||||
} OT_TOOL_PACKED_END energyList;
|
||||
uint32_t mask;
|
||||
MeshCoP::EnergyListTlv energyListTlv;
|
||||
|
||||
VerifyOrExit(aMessage.IsConfirmablePostRequest());
|
||||
|
||||
@@ -126,12 +121,11 @@ void EnergyScanClient::HandleReport(Coap::Message &aMessage, const Ip6::MessageI
|
||||
|
||||
VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
|
||||
|
||||
SuccessOrExit(MeshCoP::Tlv::FindTlv(aMessage, MeshCoP::Tlv::kEnergyList, sizeof(energyList), energyList.tlv));
|
||||
VerifyOrExit(energyList.tlv.IsValid());
|
||||
SuccessOrExit(MeshCoP::Tlv::FindTlv(aMessage, MeshCoP::Tlv::kEnergyList, sizeof(energyListTlv), energyListTlv));
|
||||
|
||||
if (mCallback != nullptr)
|
||||
{
|
||||
mCallback(mask, energyList.list, energyList.tlv.GetLength(), mContext);
|
||||
mCallback(mask, energyListTlv.GetEnergyList(), energyListTlv.GetEnergyListLength(), mContext);
|
||||
}
|
||||
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "common/const_cast.hpp"
|
||||
#include "common/encoding.hpp"
|
||||
#include "common/message.hpp"
|
||||
#include "common/num_utils.hpp"
|
||||
#include "common/string.hpp"
|
||||
#include "common/tlvs.hpp"
|
||||
#include "mac/mac_types.hpp"
|
||||
@@ -1557,6 +1558,27 @@ public:
|
||||
*
|
||||
*/
|
||||
bool IsValid(void) const { return true; }
|
||||
|
||||
/**
|
||||
* This method returns a pointer to the start of energy measurement list.
|
||||
*
|
||||
* @returns A pointer to the start start of energy energy measurement list.
|
||||
*
|
||||
*/
|
||||
const uint8_t *GetEnergyList(void) const { return mEnergyList; }
|
||||
|
||||
/**
|
||||
* This method returns the length of energy measurement list.
|
||||
*
|
||||
* @returns The length of energy measurement list.
|
||||
*
|
||||
*/
|
||||
uint8_t GetEnergyListLength(void) const { return Min(kMaxListLength, GetLength()); }
|
||||
|
||||
private:
|
||||
static constexpr uint8_t kMaxListLength = OPENTHREAD_CONFIG_TMF_ENERGY_SCAN_MAX_RESULTS;
|
||||
|
||||
uint8_t mEnergyList[kMaxListLength];
|
||||
} OT_TOOL_PACKED_END;
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,8 +56,7 @@ EnergyScanServer::EnergyScanServer(Instance &aInstance)
|
||||
, mPeriod(0)
|
||||
, mScanDuration(0)
|
||||
, mCount(0)
|
||||
, mActive(false)
|
||||
, mScanResultsLength(0)
|
||||
, mReportMessage(nullptr)
|
||||
, mTimer(aInstance)
|
||||
, mEnergyScan(UriPath::kEnergyScan, &EnergyScanServer::HandleRequest, this)
|
||||
{
|
||||
@@ -71,11 +70,12 @@ void EnergyScanServer::HandleRequest(void *aContext, otMessage *aMessage, const
|
||||
|
||||
void EnergyScanServer::HandleRequest(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo)
|
||||
{
|
||||
uint8_t count;
|
||||
uint16_t period;
|
||||
uint16_t scanDuration;
|
||||
Ip6::MessageInfo responseInfo(aMessageInfo);
|
||||
uint32_t mask;
|
||||
uint8_t count;
|
||||
uint16_t period;
|
||||
uint16_t scanDuration;
|
||||
uint32_t mask;
|
||||
MeshCoP::Tlv tlv;
|
||||
MeshCoP::ChannelMaskTlv channelMaskTlv;
|
||||
|
||||
VerifyOrExit(aMessage.IsPostRequest());
|
||||
|
||||
@@ -85,20 +85,30 @@ void EnergyScanServer::HandleRequest(Coap::Message &aMessage, const Ip6::Message
|
||||
|
||||
VerifyOrExit((mask = MeshCoP::ChannelMaskTlv::GetChannelMask(aMessage)) != 0);
|
||||
|
||||
FreeMessage(mReportMessage);
|
||||
mReportMessage = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kEnergyReport);
|
||||
VerifyOrExit(mReportMessage != nullptr);
|
||||
|
||||
channelMaskTlv.Init();
|
||||
channelMaskTlv.SetChannelMask(mask);
|
||||
SuccessOrExit(channelMaskTlv.AppendTo(*mReportMessage));
|
||||
|
||||
tlv.SetType(MeshCoP::Tlv::kEnergyList);
|
||||
SuccessOrExit(mReportMessage->Append(tlv));
|
||||
|
||||
mNumScanResults = 0;
|
||||
mChannelMask = mask;
|
||||
mChannelMaskCurrent = mChannelMask;
|
||||
mCount = count;
|
||||
mPeriod = period;
|
||||
mScanDuration = scanDuration;
|
||||
mScanResultsLength = 0;
|
||||
mActive = true;
|
||||
mTimer.Start(kScanDelay);
|
||||
|
||||
mCommissioner = aMessageInfo.GetPeerAddr();
|
||||
|
||||
if (aMessage.IsConfirmable() && !aMessageInfo.GetSockAddr().IsMulticast())
|
||||
{
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, responseInfo));
|
||||
SuccessOrExit(Get<Tmf::Agent>().SendEmptyAck(aMessage, aMessageInfo));
|
||||
LogInfo("sent energy scan query response");
|
||||
}
|
||||
|
||||
@@ -108,12 +118,13 @@ exit:
|
||||
|
||||
void EnergyScanServer::HandleTimer(void)
|
||||
{
|
||||
VerifyOrExit(mActive);
|
||||
VerifyOrExit(mReportMessage != nullptr);
|
||||
|
||||
if (mCount)
|
||||
{
|
||||
// grab the lowest channel to scan
|
||||
uint32_t channelMask = mChannelMaskCurrent & ~(mChannelMaskCurrent - 1);
|
||||
|
||||
IgnoreError(Get<Mac::Mac>().EnergyScan(channelMask, mScanDuration, HandleScanResult, this));
|
||||
}
|
||||
else
|
||||
@@ -132,16 +143,31 @@ void EnergyScanServer::HandleScanResult(Mac::EnergyScanResult *aResult, void *aC
|
||||
|
||||
void EnergyScanServer::HandleScanResult(Mac::EnergyScanResult *aResult)
|
||||
{
|
||||
VerifyOrExit(mActive);
|
||||
VerifyOrExit(mReportMessage != nullptr);
|
||||
|
||||
if (aResult)
|
||||
{
|
||||
VerifyOrExit(mScanResultsLength < OPENTHREAD_CONFIG_TMF_ENERGY_SCAN_MAX_RESULTS);
|
||||
mScanResults[mScanResultsLength++] = aResult->mMaxRssi;
|
||||
if (mReportMessage->Append<int8_t>(aResult->mMaxRssi) != kErrorNone)
|
||||
{
|
||||
FreeMessage(mReportMessage);
|
||||
mReportMessage = nullptr;
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mNumScanResults++;
|
||||
|
||||
if (mNumScanResults == NumericLimits<uint8_t>::kMax)
|
||||
{
|
||||
// If we reach the max length that fit in the Energy List
|
||||
// TLV we send the current set of energy scan data.
|
||||
|
||||
mCount = 0;
|
||||
mTimer.Start(kReportDelay);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// clear the lowest channel to scan
|
||||
// Clear the lowest channel to scan
|
||||
mChannelMaskCurrent &= mChannelMaskCurrent - 1;
|
||||
|
||||
if (mChannelMaskCurrent == 0)
|
||||
@@ -166,42 +192,33 @@ exit:
|
||||
|
||||
void EnergyScanServer::SendReport(void)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
MeshCoP::ChannelMaskTlv channelMask;
|
||||
MeshCoP::EnergyListTlv energyList;
|
||||
Tmf::MessageInfo messageInfo(GetInstance());
|
||||
Coap::Message * message;
|
||||
Error error = kErrorNone;
|
||||
Tmf::MessageInfo messageInfo(GetInstance());
|
||||
uint16_t offset;
|
||||
|
||||
message = Get<Tmf::Agent>().NewPriorityConfirmablePostMessage(UriPath::kEnergyReport);
|
||||
VerifyOrExit(message != nullptr, error = kErrorNoBufs);
|
||||
|
||||
channelMask.Init();
|
||||
channelMask.SetChannelMask(mChannelMask);
|
||||
SuccessOrExit(error = channelMask.AppendTo(*message));
|
||||
|
||||
energyList.Init();
|
||||
energyList.SetLength(mScanResultsLength);
|
||||
SuccessOrExit(error = message->Append(energyList));
|
||||
SuccessOrExit(error = message->AppendBytes(mScanResults, mScanResultsLength));
|
||||
// Update the Energy List TLV length in Report message
|
||||
offset = mReportMessage->GetLength() - mNumScanResults - sizeof(uint8_t);
|
||||
mReportMessage->Write(offset, mNumScanResults);
|
||||
|
||||
messageInfo.SetSockAddrToRlocPeerAddrTo(mCommissioner);
|
||||
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*message, messageInfo));
|
||||
SuccessOrExit(error = Get<Tmf::Agent>().SendMessage(*mReportMessage, messageInfo));
|
||||
|
||||
LogInfo("sent scan results");
|
||||
|
||||
exit:
|
||||
FreeMessageOnError(message, error);
|
||||
FreeMessageOnError(mReportMessage, error);
|
||||
MeshCoP::LogError("send scan results", error);
|
||||
mActive = false;
|
||||
mReportMessage = nullptr;
|
||||
}
|
||||
|
||||
void EnergyScanServer::HandleNotifierEvents(Events aEvents)
|
||||
{
|
||||
if (aEvents.Contains(kEventThreadNetdataChanged) && !mActive &&
|
||||
if (aEvents.Contains(kEventThreadNetdataChanged) && (mReportMessage != nullptr) &&
|
||||
Get<NetworkData::Leader>().GetCommissioningData() == nullptr)
|
||||
{
|
||||
mActive = false;
|
||||
mReportMessage->Free();
|
||||
mReportMessage = nullptr;
|
||||
mTimer.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,8 @@ public:
|
||||
explicit EnergyScanServer(Instance &aInstance);
|
||||
|
||||
private:
|
||||
static constexpr uint32_t kScanDelay = 1000; ///< SCAN_DELAY (milliseconds)
|
||||
static constexpr uint32_t kReportDelay = 500; ///< Delay before sending a report (milliseconds)
|
||||
static constexpr uint32_t kScanDelay = 1000; // SCAN_DELAY (milliseconds)
|
||||
static constexpr uint32_t kReportDelay = 500; // Delay before sending a report (milliseconds)
|
||||
|
||||
static void HandleRequest(void *aContext, otMessage *aMessage, const otMessageInfo *aMessageInfo);
|
||||
void HandleRequest(Coap::Message &aMessage, const Ip6::MessageInfo &aMessageInfo);
|
||||
@@ -80,18 +80,15 @@ private:
|
||||
|
||||
using ScanTimer = TimerMilliIn<EnergyScanServer, &EnergyScanServer::HandleTimer>;
|
||||
|
||||
Ip6::Address mCommissioner;
|
||||
uint32_t mChannelMask;
|
||||
uint32_t mChannelMaskCurrent;
|
||||
uint16_t mPeriod;
|
||||
uint16_t mScanDuration;
|
||||
uint8_t mCount;
|
||||
bool mActive;
|
||||
|
||||
int8_t mScanResults[OPENTHREAD_CONFIG_TMF_ENERGY_SCAN_MAX_RESULTS];
|
||||
uint8_t mScanResultsLength;
|
||||
|
||||
ScanTimer mTimer;
|
||||
Ip6::Address mCommissioner;
|
||||
uint32_t mChannelMask;
|
||||
uint32_t mChannelMaskCurrent;
|
||||
uint16_t mPeriod;
|
||||
uint16_t mScanDuration;
|
||||
uint8_t mCount;
|
||||
uint8_t mNumScanResults;
|
||||
Coap::Message *mReportMessage;
|
||||
ScanTimer mTimer;
|
||||
|
||||
Coap::Resource mEnergyScan;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user