diff --git a/src/ncp/ncp_base_dispatcher.cpp b/src/ncp/ncp_base_dispatcher.cpp index ef2003865..a9c0f7e23 100644 --- a/src/ncp/ncp_base_dispatcher.cpp +++ b/src/ncp/ncp_base_dispatcher.cpp @@ -452,6 +452,9 @@ NcpBase::PropertyHandler NcpBase::FindGetPropertyHandler(spinel_prop_key_t aKey) case SPINEL_PROP_CNTR_ALL_MAC_COUNTERS: handler = &NcpBase::HandlePropertyGet; break; + case SPINEL_PROP_CNTR_MLE_COUNTERS: + handler = &NcpBase::HandlePropertyGet; + break; // NCP counters case SPINEL_PROP_CNTR_TX_IP_SEC_TOTAL: handler = &NcpBase::HandlePropertyGet; diff --git a/src/ncp/ncp_base_mtd.cpp b/src/ncp/ncp_base_mtd.cpp index 24e826f1f..7ba50538a 100644 --- a/src/ncp/ncp_base_mtd.cpp +++ b/src/ncp/ncp_base_mtd.cpp @@ -2259,6 +2259,31 @@ exit: return error; } +template <> otError NcpBase::HandlePropertyGet(void) +{ + otError error = OT_ERROR_NONE; + const otMleCounters *counters = otThreadGetMleCounters(mInstance); + + if (counters == NULL) + { + error = mEncoder.OverwriteWithLastStatusError(SPINEL_STATUS_INVALID_COMMAND_FOR_PROP); + ExitNow(); + } + + SuccessOrExit(error = mEncoder.WriteUint16(counters->mDisabledRole)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mDetachedRole)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mChildRole)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mRouterRole)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mLeaderRole)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mAttachAttempts)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mPartitionIdChanges)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mBetterPartitionAttachAttempts)); + SuccessOrExit(error = mEncoder.WriteUint16(counters->mParentChanges)); + +exit: + return error; +} + #if OPENTHREAD_ENABLE_MAC_FILTER template <> otError NcpBase::HandlePropertyGet(void) diff --git a/src/ncp/spinel.c b/src/ncp/spinel.c index e96ff4ee8..080c8304c 100644 --- a/src/ncp/spinel.c +++ b/src/ncp/spinel.c @@ -2063,6 +2063,10 @@ const char *spinel_prop_key_to_cstr(spinel_prop_key_t prop_key) ret = "CNTR_ALL_MAC_COUNTERS"; break; + case SPINEL_PROP_CNTR_MLE_COUNTERS: + ret = "CNTR_MLE_COUNTERS"; + break; + case SPINEL_PROP_NEST_STREAM_MFG: ret = "NEST_STREAM_MFG"; break; diff --git a/src/ncp/spinel.h b/src/ncp/spinel.h index 473ab9ff9..8a4af9e5b 100644 --- a/src/ncp/spinel.h +++ b/src/ncp/spinel.h @@ -3327,6 +3327,22 @@ typedef enum */ SPINEL_PROP_CNTR_ALL_MAC_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 401, + /// Thread MLE counters. + /** Format: `SSSSSSSSS` (Read-only) + * + * 'S': DisabledRole (The number of times device entered OT_DEVICE_ROLE_DISABLED role). + * 'S': DetachedRole (The number of times device entered OT_DEVICE_ROLE_DETACHED role). + * 'S': ChildRole (The number of times device entered OT_DEVICE_ROLE_CHILD role). + * 'S': RouterRole (The number of times device entered OT_DEVICE_ROLE_ROUTER role). + * 'S': LeaderRole (The number of times device entered OT_DEVICE_ROLE_LEADER role). + * 'S': AttachAttempts (The number of attach attempts while device was detached). + * 'S': PartitionIdChanges (The number of changes to partition ID). + * 'S': BetterPartitionAttachAttempts (The number of attempts to attach to a better partition). + * 'S': ParentChanges (The number of times device changed its parents). + * + */ + SPINEL_PROP_CNTR_MLE_COUNTERS = SPINEL_PROP_CNTR__BEGIN + 402, + SPINEL_PROP_CNTR__END = 0x800, SPINEL_PROP_NEST__BEGIN = 0x3BC0,