[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:
Abtin Keshavarzian
2022-10-06 08:53:17 -07:00
committed by GitHub
parent d3e00fbd28
commit 4f57b8d461
4 changed files with 91 additions and 61 deletions
+5 -11
View File
@@ -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));
+22
View File
@@ -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;
/**
+53 -36
View File
@@ -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();
}
}
+11 -14
View File
@@ -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;
};