mirror of
https://github.com/espressif/openthread.git
synced 2026-08-02 00:57:47 +00:00
[diag] add diag receive command to show received specified number of frames (#11039)
The `diag frame` command can set the frame to be sent. But developers has no command to check if the received frame is the same as the sent frame. This commit adds the command `diag receive [async] <number> [lpr]` to show the detailed info of specified number of received frames.
This commit is contained in:
+11
-1
@@ -199,7 +199,17 @@ void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments, void
|
||||
static_cast<Interpreter *>(aContext)->HandleDiagOutput(aFormat, aArguments);
|
||||
}
|
||||
|
||||
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments) { OutputFormatV(aFormat, aArguments); }
|
||||
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments)
|
||||
{
|
||||
if (strcmp(aFormat, "OT_ERROR_NONE") == 0)
|
||||
{
|
||||
OutputResult(OT_ERROR_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
OutputFormatV(aFormat, aArguments);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
|
||||
|
||||
@@ -218,6 +218,26 @@ set radio from sleep to receive on channel 11
|
||||
status 0x00
|
||||
```
|
||||
|
||||
### diag radio receive \[async\] \<number\> \[lpr\]
|
||||
|
||||
Set the radio to receive mode and receive a specified number of frames.
|
||||
|
||||
- async: Use the non-blocking mode.
|
||||
- number: The number of frames expected to be received.
|
||||
- l: Show Lqi.
|
||||
- p: Show Psdu.
|
||||
- r: Show Rssi.
|
||||
|
||||
```bash
|
||||
> diag radio receive 5 lpr
|
||||
0, rssi:-49, lqi:119, len:10, psdu:000102030405060771e
|
||||
1, rssi:-51, lqi:112, len:10, psdu:000102030405060771e
|
||||
2, rssi:-42, lqi:120, len:10, psdu:000102030405060771e
|
||||
3, rssi:-54, lqi:111, len:10, psdu:000102030405060771e
|
||||
4, rssi:-56, lqi:108, len:10, psdu:000102030405060771e
|
||||
Done
|
||||
```
|
||||
|
||||
### diag radio state
|
||||
|
||||
Return the state of the radio.
|
||||
|
||||
@@ -587,6 +587,50 @@ void Diags::TransmitPacket(void)
|
||||
IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
|
||||
}
|
||||
|
||||
Error Diags::ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig)
|
||||
{
|
||||
Error error = kErrorNone;
|
||||
|
||||
VerifyOrExit(aFormat != nullptr, error = kErrorInvalidArgs);
|
||||
|
||||
for (const char *arg = aFormat; *arg != '\0'; arg++)
|
||||
{
|
||||
switch (*arg)
|
||||
{
|
||||
case 'r':
|
||||
aConfig.mShowRssi = true;
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
aConfig.mShowLqi = true;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
aConfig.mShowPsdu = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
ExitNow(error = OT_ERROR_INVALID_ARGS);
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Diags::RadioReceive(void)
|
||||
{
|
||||
Error error;
|
||||
|
||||
SuccessOrExit(error = Get<Radio>().Receive(mChannel));
|
||||
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
|
||||
otPlatDiagChannelSet(mChannel);
|
||||
otPlatDiagTxPowerSet(mTxPower);
|
||||
|
||||
exit:
|
||||
return error;
|
||||
}
|
||||
|
||||
Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
|
||||
{
|
||||
Error error = kErrorInvalidArgs;
|
||||
@@ -601,12 +645,44 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
|
||||
}
|
||||
else if (StringMatch(aArgs[0], "receive"))
|
||||
{
|
||||
SuccessOrExit(error = Get<Radio>().Receive(mChannel));
|
||||
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
|
||||
otPlatDiagChannelSet(mChannel);
|
||||
otPlatDiagTxPowerSet(mTxPower);
|
||||
ReceiveConfig receiveConfig;
|
||||
|
||||
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
|
||||
aArgs++;
|
||||
aArgsLength--;
|
||||
|
||||
if (aArgsLength == 0)
|
||||
{
|
||||
SuccessOrExit(error = RadioReceive());
|
||||
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
if (StringMatch(aArgs[0], "async"))
|
||||
{
|
||||
aArgs++;
|
||||
aArgsLength--;
|
||||
receiveConfig.mIsAsyncCommand = true;
|
||||
}
|
||||
|
||||
VerifyOrExit(aArgsLength > 0);
|
||||
SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint16(aArgs[0], receiveConfig.mNumFrames));
|
||||
aArgs++;
|
||||
aArgsLength--;
|
||||
|
||||
if (aArgsLength > 0)
|
||||
{
|
||||
SuccessOrExit(error = ParseReceiveConfigFormat(aArgs[0], receiveConfig));
|
||||
}
|
||||
|
||||
SuccessOrExit(error = RadioReceive());
|
||||
|
||||
receiveConfig.mIsEnabled = true;
|
||||
mReceiveConfig = receiveConfig;
|
||||
|
||||
if (!mReceiveConfig.mIsAsyncCommand)
|
||||
{
|
||||
error = kErrorPending;
|
||||
}
|
||||
}
|
||||
else if (StringMatch(aArgs[0], "state"))
|
||||
{
|
||||
@@ -668,10 +744,54 @@ void Diags::AlarmFired(void)
|
||||
}
|
||||
}
|
||||
|
||||
void Diags::OutputReceivedFrame(const otRadioFrame *aFrame)
|
||||
{
|
||||
VerifyOrExit(mReceiveConfig.mIsEnabled && (aFrame != nullptr));
|
||||
|
||||
Output("%u", mReceiveConfig.mReceiveCount++);
|
||||
|
||||
if (mReceiveConfig.mShowRssi)
|
||||
{
|
||||
Output(", rssi:%d", aFrame->mInfo.mRxInfo.mRssi);
|
||||
}
|
||||
|
||||
if (mReceiveConfig.mShowLqi)
|
||||
{
|
||||
Output(", lqi:%u", aFrame->mInfo.mRxInfo.mLqi);
|
||||
}
|
||||
|
||||
if (mReceiveConfig.mShowPsdu)
|
||||
{
|
||||
static constexpr uint16_t kBufSize = 255;
|
||||
char buf[kBufSize];
|
||||
StringWriter writer(buf, sizeof(buf));
|
||||
|
||||
writer.AppendHexBytes(aFrame->mPsdu, aFrame->mLength);
|
||||
Output(", len:%u, psdu:%s", aFrame->mLength, buf);
|
||||
}
|
||||
|
||||
Output("\r\n");
|
||||
|
||||
if (mReceiveConfig.mReceiveCount >= mReceiveConfig.mNumFrames)
|
||||
{
|
||||
mReceiveConfig.mIsEnabled = false;
|
||||
|
||||
if (!mReceiveConfig.mIsAsyncCommand)
|
||||
{
|
||||
Output("OT_ERROR_NONE");
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void Diags::ReceiveDone(otRadioFrame *aFrame, Error aError)
|
||||
{
|
||||
if (aError == kErrorNone)
|
||||
{
|
||||
OutputReceivedFrame(aFrame);
|
||||
|
||||
// for sensitivity test, only record the rssi and lqi for the first and last packet
|
||||
if (mStats.mReceivedPackets == 0)
|
||||
{
|
||||
@@ -910,7 +1030,7 @@ exit:
|
||||
|
||||
void Diags::AppendErrorResult(Error aError)
|
||||
{
|
||||
if (aError != kErrorNone)
|
||||
if ((aError != kErrorNone) && (aError != kErrorPending))
|
||||
{
|
||||
Output("failed\r\nstatus %#x\r\n", aError);
|
||||
}
|
||||
|
||||
@@ -177,6 +177,28 @@ private:
|
||||
RawPowerSetting mRawPowerSetting;
|
||||
};
|
||||
|
||||
struct ReceiveConfig
|
||||
{
|
||||
ReceiveConfig(void)
|
||||
: mIsEnabled(false)
|
||||
, mIsAsyncCommand(false)
|
||||
, mShowRssi(true)
|
||||
, mShowLqi(true)
|
||||
, mShowPsdu(false)
|
||||
, mReceiveCount(0)
|
||||
, mNumFrames(0)
|
||||
{
|
||||
}
|
||||
|
||||
bool mIsEnabled : 1;
|
||||
bool mIsAsyncCommand : 1;
|
||||
bool mShowRssi : 1;
|
||||
bool mShowLqi : 1;
|
||||
bool mShowPsdu : 1;
|
||||
uint16_t mReceiveCount;
|
||||
uint16_t mNumFrames;
|
||||
};
|
||||
|
||||
Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
|
||||
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
|
||||
Error ProcessFrame(uint8_t aArgsLength, char *aArgs[]);
|
||||
@@ -198,6 +220,9 @@ private:
|
||||
|
||||
Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting);
|
||||
Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings);
|
||||
Error ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig);
|
||||
Error RadioReceive(void);
|
||||
void OutputReceivedFrame(const otRadioFrame *aFrame);
|
||||
|
||||
void TransmitPacket(void);
|
||||
void Output(const char *aFormat, ...);
|
||||
@@ -223,6 +248,7 @@ private:
|
||||
bool mDiagSendOn : 1;
|
||||
#endif
|
||||
|
||||
ReceiveConfig mReceiveConfig;
|
||||
otDiagOutputCallback mOutputCallback;
|
||||
void *mOutputContext;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user