Skip to content

Commit

Permalink
transmit wakeup frames to wake up sleepy device to join Thread network
Browse files Browse the repository at this point in the history
  • Loading branch information
zhanglongxia committed Dec 18, 2024
1 parent 147de7e commit 7b8ac4f
Show file tree
Hide file tree
Showing 23 changed files with 366 additions and 21 deletions.
2 changes: 2 additions & 0 deletions include/openthread/cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ void otCliPlatLogv(otLogLevel aLogLevel, otLogRegion aLogRegion, const char *aFo
*/
extern void otCliVendorSetUserCommands(void);

otError otCliWedAutoStart(bool aEnabled);

/**
* @}
*/
Expand Down
6 changes: 6 additions & 0 deletions include/openthread/link.h
Original file line number Diff line number Diff line change
Expand Up @@ -1200,6 +1200,12 @@ otError otLinkSetWakeupListenParameters(otInstance *aInstance, uint32_t aInterva
*/
otError otLinkSetRxOnWhenIdle(otInstance *aInstance, bool aRxOnWhenIdle);

typedef void (*otWakeupFrameReceivedCallback)(const otExtAddress *aWcAddress, void *aContext);

void otLinkSetWakeupFrameReceivedCallback(otInstance *aInstance,
otWakeupFrameReceivedCallback aCallback,
void *aContext);

/**
* @}
*/
Expand Down
4 changes: 4 additions & 0 deletions include/openthread/thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,10 @@ otError otThreadWakeup(otInstance *aInstance,
otWakeupCallback aCallback,
void *aCallbackContext);

typedef void (*otSetLedCallback)(uint32_t aPinName, int aLedState, void *aContext);
void otThreadSetLedCallback(otInstance *aInstance, otSetLedCallback aCallback, void *aContext);


/**
* @}
*/
Expand Down
109 changes: 109 additions & 0 deletions src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ Interpreter::Interpreter(Instance *aInstance, otCliOutputCallback aCallback, voi
, mCommandIsPending(false)
, mInternalDebugCommand(false)
, mTimer(*aInstance, HandleTimer, this)
#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
, mWedTimer(*aInstance, HandleWedTimer, this)
#endif
#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
, mSntpQueryingInProgress(false)
Expand Down Expand Up @@ -8318,6 +8321,17 @@ template <> otError Interpreter::Process<Cmd("wakeup")>(Arg aArgs[])
{
error = ProcessEnableDisable(aArgs + 1, otLinkIsWakeupListenEnabled, otLinkSetWakeUpListenEnabled);
}
else if (aArgs[0] == "wed")
{
if (aArgs[1] == "enable")
{
error = SetWedAutoStart(true);
}
else if (aArgs[1] == "disable")
{
error = SetWedAutoStart(false);
}
}
#endif // OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
/**
Expand Down Expand Up @@ -8356,6 +8370,97 @@ template <> otError Interpreter::Process<Cmd("wakeup")>(Arg aArgs[])
}
#endif // OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE || OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE

otError Interpreter::SetWedAutoStart(bool aEnabled)
{
otError error = OT_ERROR_NONE;

if (aEnabled)
{
SuccessOrExit(error = otLinkSetWakeUpListenEnabled(GetInstancePtr(), true));
mPreviousRole = otThreadGetDeviceRole(GetInstancePtr());
SuccessOrExit(error = otSetStateChangedCallback(GetInstancePtr(), HandleStateChanged, this));
otLinkSetWakeupFrameReceivedCallback(GetInstancePtr(), HandleWakeupFrameReceived, this);
}
else
{
SuccessOrExit(error = otLinkSetWakeUpListenEnabled(GetInstancePtr(), false));
SuccessOrExit(error = otSetStateChangedCallback(GetInstancePtr(), nullptr, nullptr));
otLinkSetWakeupFrameReceivedCallback(GetInstancePtr(), nullptr, nullptr);
}

exit:
return error;
}

void Interpreter::HandleWakeupFrameReceived(const otExtAddress *aWcAddress, void *aContext)
{
static_cast<Interpreter *>(aContext)->HandleWakeupFrameReceived(aWcAddress);
}

void Interpreter::HandleWakeupFrameReceived(const otExtAddress *aWcAddress)
{
OutputFormat("Wakeup Frame Received: ");
OutputExtAddressLine(*aWcAddress);

if (otThreadGetDeviceRole(GetInstancePtr()) != OT_DEVICE_ROLE_DISABLED)
{
// Restart Thread Stack to triger the device to quickly rejoin the thread network.
OutputLine("Re-attach to Thread network");
//otThreadSetEnabled(GetInstancePtr(), false);
//otThreadSetEnabled(GetInstancePtr(), true);

mWedTimer.Start(3000);
}
}

void Interpreter::HandleStateChanged(otChangedFlags aFlags, void *aContext)
{
static_cast<Interpreter *>(aContext)->HandleStateChanged(aFlags);
}

void Interpreter::HandleStateChanged(otChangedFlags aFlags)
{
if (aFlags & OT_CHANGED_THREAD_ROLE)
{
otDeviceRole role = otThreadGetDeviceRole(GetInstancePtr());

OutputLine("Role: %s -> %s", otThreadDeviceRoleToString(mPreviousRole), otThreadDeviceRoleToString(role));

// Disable Thread when the WED is deatched
if (((mPreviousRole == OT_DEVICE_ROLE_CHILD) || (mPreviousRole == OT_DEVICE_ROLE_ROUTER) ||
(mPreviousRole == OT_DEVICE_ROLE_LEADER)) &&
(role == OT_DEVICE_ROLE_DETACHED))
{
// Enable the wakeup listener again.After received a wakeup frame, the wakeup listener is disabled
// automatically.
OutputLine("Re-enable listening wakeup frames");
otLinkSetWakeUpListenEnabled(GetInstancePtr(), true);
}
mPreviousRole = role;
}
}

void Interpreter::HandleWedTimer(Timer &aTimer)
{
static_cast<Interpreter *>(static_cast<TimerMilliContext &>(aTimer).GetContext())->HandleWedTimer();
}

void Interpreter::HandleWedTimer(void)
{
otDeviceRole role = otThreadGetDeviceRole(GetInstancePtr());

// In case the WED is failed to join the Thread network.
if (role == OT_DEVICE_ROLE_DETACHED)
{
OutputLine("Re-enable listening wakeup frames");
otLinkSetWakeUpListenEnabled(GetInstancePtr(), true);
}
}

#endif

#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
void Interpreter::HandleWakeupResult(otError aError, void *aContext)
{
Expand Down Expand Up @@ -8761,5 +8866,9 @@ extern "C" void otCliPlatLogv(otLogLevel aLogLevel, otLogRegion aLogRegion, cons
return;
}

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
extern "C" otError otCliWedAutoStart(bool aEnabled) { return Interpreter::GetInterpreter().SetWedAutoStart(aEnabled); }
#endif

} // namespace Cli
} // namespace ot
21 changes: 21 additions & 0 deletions src/cli/cli.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,9 @@ class Interpreter : public OutputImplementer, public Utils
*/
otError SetUserCommands(const otCliCommand *aCommands, uint8_t aLength, void *aContext);

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
otError SetWedAutoStart(bool aEnabled);
#endif
protected:
static Interpreter *sInterpreter;

Expand Down Expand Up @@ -329,6 +332,17 @@ class Interpreter : public OutputImplementer, public Utils
static void HandleIp6Receive(otMessage *aMessage, void *aContext);
#endif

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
static void HandleWakeupFrameReceived(const otExtAddress *aWcAddress, void *aContext);
void HandleWakeupFrameReceived(const otExtAddress *aWcAddress);

static void HandleStateChanged(otChangedFlags aFlags, void *aContext);
void HandleStateChanged(otChangedFlags aFlags);

static void HandleWedTimer(Timer &aTimer);
void HandleWedTimer(void);
#endif

#if OPENTHREAD_CONFIG_WAKEUP_COORDINATOR_ENABLE
static void HandleWakeupResult(otError aError, void *aContext);
void HandleWakeupResult(otError aError);
Expand Down Expand Up @@ -359,6 +373,10 @@ class Interpreter : public OutputImplementer, public Utils

TimerMilliContext mTimer;

#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
TimerMilliContext mWedTimer;
#endif

#if OPENTHREAD_FTD || OPENTHREAD_MTD
#if OPENTHREAD_CONFIG_SNTP_CLIENT_ENABLE
bool mSntpQueryingInProgress;
Expand Down Expand Up @@ -433,6 +451,9 @@ class Interpreter : public OutputImplementer, public Utils
#if OPENTHREAD_CONFIG_TMF_ANYCAST_LOCATOR_ENABLE
bool mLocateInProgress : 1;
#endif
#if OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
otDeviceRole mPreviousRole;
#endif
};

} // namespace Cli
Expand Down
17 changes: 15 additions & 2 deletions src/cli/cli_dataset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1123,14 +1123,27 @@ template <> otError Dataset::Process<Cmd("set")>(Arg aArgs[])
otError error = OT_ERROR_NONE;
otOperationalDatasetTlvs datasetTlvs;

SuccessOrExit(error = ParseTlvs(aArgs[1], datasetTlvs));

if (aArgs[0] == "active")
{
if (aArgs[1] == "init")
{
char testDataset[] = "0e080000000000010000000300001635060004001fffe002083ae7ad5bd2c958ef0708fd77c6ccf72ab52"
"30510cceb51a2f1602439b0343c07d6ca981f030f4f70656e5468726561642d363834660102684f041011"
"6d23d1b996bd75d25bdc911aa33fb40c0402a0f7f8";
Arg arg;

arg.SetCString(testDataset);
SuccessOrExit(error = ParseTlvs(arg, datasetTlvs));
}
else
{
SuccessOrExit(error = ParseTlvs(aArgs[1], datasetTlvs));
}
error = otDatasetSetActiveTlvs(GetInstancePtr(), &datasetTlvs);
}
else if (aArgs[0] == "pending")
{
SuccessOrExit(error = ParseTlvs(aArgs[1], datasetTlvs));
error = otDatasetSetPendingTlvs(GetInstancePtr(), &datasetTlvs);
}
else
Expand Down
7 changes: 7 additions & 0 deletions src/core/api/link_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -530,4 +530,11 @@ otError otLinkSetWakeupListenParameters(otInstance *aInstance, uint32_t aInterva
{
return AsCoreType(aInstance).Get<Mac::Mac>().SetWakeupListenParameters(aInterval, aDuration);
}

void otLinkSetWakeupFrameReceivedCallback(otInstance *aInstance,
otWakeupFrameReceivedCallback aCallback,
void *aContext)
{
AsCoreType(aInstance).Get<Mac::Mac>().SetWakeupFrameReceivedCallback(aCallback, aContext);
}
#endif // OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
6 changes: 6 additions & 0 deletions src/core/api/thread_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,3 +539,9 @@ void otConvertDurationInSecondsToString(uint32_t aDuration, char *aBuffer, uint1
Uptime::UptimeToString(Uptime::SecToMsec(aDuration), writer, /* aIncludeMsec */ false);
}
#endif

void otThreadSetLedCallback(otInstance *aInstance, otSetLedCallback aCallback, void *aContext)
{
AsCoreType(aInstance).Get<Mle::Mle>().SetLedCallback(aCallback, aContext);
}

2 changes: 1 addition & 1 deletion src/core/config/logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@
* The maximum log string size (number of chars).
*/
#ifndef OPENTHREAD_CONFIG_LOG_MAX_SIZE
#define OPENTHREAD_CONFIG_LOG_MAX_SIZE 150
#define OPENTHREAD_CONFIG_LOG_MAX_SIZE 2048
#endif

/**
Expand Down
2 changes: 1 addition & 1 deletion src/core/config/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@
* The maximum number of state-changed callback handlers (set using `otSetStateChangedCallback()`).
*/
#ifndef OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS
#define OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS 1
#define OPENTHREAD_CONFIG_MAX_STATECHANGE_HANDLERS 3
#endif

/**
Expand Down
4 changes: 2 additions & 2 deletions src/core/config/wakeup.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
* frames to establish a link with a Wake-up Coordinator device.
*/
#ifndef OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE
#define OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 0
#define OPENTHREAD_CONFIG_WAKEUP_END_DEVICE_ENABLE 1
#endif

/**
Expand All @@ -104,7 +104,7 @@
* The default wake-up listen duration in microseconds.
*/
#ifndef OPENTHREAD_CONFIG_WED_LISTEN_DURATION
#define OPENTHREAD_CONFIG_WED_LISTEN_DURATION 8000
#define OPENTHREAD_CONFIG_WED_LISTEN_DURATION 32000 //8000
#endif

/**
Expand Down
3 changes: 2 additions & 1 deletion src/core/mac/data_poll_sender.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,7 +257,8 @@ class DataPollSender : public InstanceLocator, private NonCopyable
void ScheduleNextPoll(PollPeriodSelector aPollPeriodSelector);
uint32_t CalculatePollPeriod(void) const;
const Neighbor &GetParent(void) const;
void HandlePollTimer(void) { IgnoreError(SendDataPoll()); }

void HandlePollTimer(void) { IgnoreError(SendDataPoll()); }
#if OPENTHREAD_CONFIG_MULTI_RADIO
Error GetPollDestinationAddress(Mac::Address &aDest, Mac::RadioType &aRadioType) const;
#else
Expand Down
Loading

0 comments on commit 7b8ac4f

Please sign in to comment.