diff --git a/src/app/BUILD.gn b/src/app/BUILD.gn index d2c97e188192ed..443919026df953 100644 --- a/src/app/BUILD.gn +++ b/src/app/BUILD.gn @@ -114,6 +114,12 @@ source_set("pre-encoded-value") { ] } +source_set("subscription-manager") { + sources = [ "SubscriptionManager.h" ] + + public_deps = [ "${chip_root}/src/lib/core" ] +} + source_set("message-def") { sources = [ "MessageDef/ArrayBuilder.cpp", @@ -247,6 +253,7 @@ static_library("interaction-model") { ":app_config", ":message-def", ":paths", + ":subscription-manager", "${chip_root}/src/app/icd:icd_config", "${chip_root}/src/app/icd:observer", "${chip_root}/src/lib/address_resolve", diff --git a/src/app/InteractionModelEngine.cpp b/src/app/InteractionModelEngine.cpp index 34e2c2055e36f2..2b73251fff3b09 100644 --- a/src/app/InteractionModelEngine.cpp +++ b/src/app/InteractionModelEngine.cpp @@ -330,7 +330,7 @@ void InteractionModelEngine::ShutdownMatchingSubscriptions(const Optional #include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - #include #include #include @@ -51,10 +36,14 @@ #include #include #include +#include +#include #include #include #include #include +#include +#include #include #include #include @@ -62,6 +51,17 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -79,7 +79,8 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, public Messaging::ExchangeDelegate, public CommandHandler::Callback, public ReadHandler::ManagementCallback, - public FabricTable::Delegate + public FabricTable::Delegate, + public SubscriptionManager { public: /** @@ -323,8 +324,9 @@ class InteractionModelEngine : public Messaging::UnsolicitedMessageHandler, CHIP_ERROR ResumeSubscriptions(); - // Check if a given subject (CAT or NodeId) has at least 1 active subscription - bool SubjectHasActiveSubscription(const FabricIndex aFabricIndex, const NodeId & subject); + bool SubjectHasActiveSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) override; + + bool SubjectHasPersistedSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) override; #if CONFIG_BUILD_FOR_HOST_UNIT_TEST // diff --git a/src/app/SubscriptionManager.h b/src/app/SubscriptionManager.h new file mode 100644 index 00000000000000..6ca47c19de8a8b --- /dev/null +++ b/src/app/SubscriptionManager.h @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * This file defines an interface that exposes all the public subscription management APIs. + * The interface is implemented by the InteractionModelEngine to avoid creating unnecessary dependencies + * Since the IMEgine has more dependency than its consummers need. + * By leveraging the SubscriptionManager APIs, a consummer avoids depending on the global data model functions. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace app { + +class SubscriptionManager +{ +public: + virtual ~SubscriptionManager(){}; + + /** + * @brief Check if a given subject (CAT or operational NodeId) has at least 1 active subscription. + * + * @param[in] aFabricIndex fabric index of the subject + * @param[in] subject NodeId of the subect + * + * @return true subject has at least one active subscription with the device + * false subject doesn't have any acitve subscription with the device + */ + virtual bool SubjectHasActiveSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) = 0; + + /** + * @brief Check if a given subject (CAT or operational NodeId) has at least 1 persisted subscription. + * If CHIP_CONFIG_PERSIST_SUBSCRIPTIONS is not enable, function alweays returns false. + * See the CHIP_CONFIG_PERSIST_SUBSCRIPTIONS for more information on persisted subscriptions. + * + * @param[in] aFabricIndex fabric index of the subject + * @param[in] subject NodeId of the subect + * + * @return true subject has at least one persisted subscription with the device + * false subject doesn't have any acitve subscription with the device + * false If CHIP_CONFIG_PERSIST_SUBSCRIPTIONS is not enabled + */ + virtual bool SubjectHasPersistedSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) = 0; +}; + +} // namespace app +} // namespace chip diff --git a/src/app/chip_data_model.gni b/src/app/chip_data_model.gni index 09d11860c7fed5..d4d4913a120ca6 100644 --- a/src/app/chip_data_model.gni +++ b/src/app/chip_data_model.gni @@ -356,6 +356,12 @@ template("chip_data_model") { "${_app_root}/clusters/${cluster}/${cluster}.h", "${_app_root}/clusters/${cluster}/EnergyReportingTestEventTriggerHandler.h", ] + } else if (cluster == "thread-network-diagnostics-server") { + sources += [ + "${_app_root}/clusters/${cluster}/${cluster}.cpp", + "${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.cpp", + "${_app_root}/clusters/${cluster}/thread-network-diagnostics-provider.h", + ] } else { sources += [ "${_app_root}/clusters/${cluster}/${cluster}.cpp" ] } diff --git a/src/app/clusters/color-control-server/color-control-server.cpp b/src/app/clusters/color-control-server/color-control-server.cpp index a21a44ada8d23f..0f24ccd5b01e43 100644 --- a/src/app/clusters/color-control-server/color-control-server.cpp +++ b/src/app/clusters/color-control-server/color-control-server.cpp @@ -2602,6 +2602,24 @@ void ColorControlServer::updateTempCommand(EndpointId endpoint) isColorTempTransitionDone = computeNewColor16uValue(colorTempTransitionState); + if (!isColorTempTransitionDone) + { + // Check whether our color temperature has actually changed. If not, do + // nothing, and wait for it to change. + uint16_t currentColorTemp; + if (Attributes::ColorTemperatureMireds::Get(endpoint, ¤tColorTemp) != EMBER_ZCL_STATUS_SUCCESS) + { + // Why can't we read our attribute? + return; + } + + if (currentColorTemp == colorTempTransitionState->currentValue) + { + scheduleTimerCallbackMs(configureTempEventControl(endpoint), TRANSITION_UPDATE_TIME_MS.count()); + return; + } + } + Attributes::RemainingTime::Set(endpoint, colorTempTransitionState->timeRemaining); if (isColorTempTransitionDone) diff --git a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.cpp b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.cpp new file mode 100644 index 00000000000000..26a988b1c51450 --- /dev/null +++ b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.cpp @@ -0,0 +1,861 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "thread-network-diagnostics-provider.h" + +#include +#include +#include +#include + +#if (CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK) +#include +#include + +#if CHIP_DEVICE_CONFIG_THREAD_FTD +#include +#endif // CHIP_DEVICE_CONFIG_THREAD_FTD +#endif // (CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK) + +using namespace chip::DeviceLayer; + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadNetworkDiagnostics { + +/* + * @brief Get runtime value from the thread network based on the given attribute ID. + * The info is encoded via the AttributeValueEncoder. + * + * @param attributeId Id of the attribute for the requested info. + * @param aEncoder Encoder to encode the attribute value. + * + * @return CHIP_NO_ERROR = Succes. + * CHIP_ERROR_NOT_IMPLEMENTED = Runtime value for this attribute not yet available to send as reply + * Use standard read. + * CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE = Is not a Runtime readable attribute. Use standard read + * All other errors should be treated as a read error and reported as such. + * + * @note This function implementation can compile in 3 different outcomes + * (1) CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK: + * - Generic implementation fetching the valid thread network data from the thread stack and encoding it respectively to + * the attributeID received. + * (2) CHIP_DEVICE_CONFIG_ENABLE_THREAD && CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK: + * - Encode a NULL value for nullable attributes or 0 for the others. + * - Devices using the ot-br-posix dbus stack have not yet provided the API to fetch the needed thread informations. + * (3) None of the conditions above + * - returns CHIP_ERROR_NOT_IMPLEMENTED. + */ +CHIP_ERROR WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder) +{ + CHIP_ERROR err; +#if (CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK) + otInstance * otInst = ThreadStackMgrImpl().OTInstance(); + + if (!otDatasetIsCommissioned(otInst)) + { + // For the following nullable attributes of the cluster, encodeNull since + // thread instance cannot provide the relevant data when it is not currently configured. + // + // Note that RoutingRole is nullable but not listed here as thread provides + // valid data even when disabled or detached + switch (attributeId) + { + case Attributes::Channel::Id: + case Attributes::NetworkName::Id: + case Attributes::PanId::Id: + case Attributes::ExtendedPanId::Id: + case Attributes::MeshLocalPrefix::Id: + case Attributes::PartitionId::Id: + case Attributes::Weighting::Id: + case Attributes::DataVersion::Id: + case Attributes::StableDataVersion::Id: + case Attributes::LeaderRouterId::Id: + case Attributes::ActiveTimestamp::Id: + case Attributes::PendingTimestamp::Id: + case Attributes::Delay::Id: + case Attributes::SecurityPolicy::Id: + case Attributes::ChannelPage0Mask::Id: + case Attributes::OperationalDatasetComponents::Id: + return encoder.EncodeNull(); + } + } + + switch (attributeId) + { + case Attributes::Channel::Id: { + uint16_t channel = otLinkGetChannel(otInst); + err = encoder.Encode(channel); + } + break; + + case Attributes::RoutingRole::Id: { + using ThreadNetworkDiagnostics::RoutingRoleEnum; + RoutingRoleEnum routingRole; + otDeviceRole otRole = otThreadGetDeviceRole(otInst); + + if (otRole == OT_DEVICE_ROLE_DISABLED) + { + routingRole = RoutingRoleEnum::kUnspecified; + } + else if (otRole == OT_DEVICE_ROLE_DETACHED) + { + routingRole = RoutingRoleEnum::kUnassigned; + } + else if (otRole == OT_DEVICE_ROLE_ROUTER) + { + routingRole = RoutingRoleEnum::kRouter; + } + else if (otRole == OT_DEVICE_ROLE_LEADER) + { + routingRole = RoutingRoleEnum::kLeader; + } + else if (otRole == OT_DEVICE_ROLE_CHILD) + { + otLinkModeConfig linkMode = otThreadGetLinkMode(otInst); + + if (linkMode.mRxOnWhenIdle) + { + routingRole = RoutingRoleEnum::kEndDevice; +#if CHIP_DEVICE_CONFIG_THREAD_FTD + if (otThreadIsRouterEligible(otInst)) + { + routingRole = RoutingRoleEnum::kReed; + } +#endif + } + else + { + routingRole = RoutingRoleEnum::kSleepyEndDevice; + } + } + + err = encoder.Encode(routingRole); + } + break; + + case Attributes::NetworkName::Id: { + const char * networkName = otThreadGetNetworkName(otInst); + err = encoder.Encode(CharSpan::fromCharString(networkName)); + } + break; + + case Attributes::PanId::Id: { + uint16_t panId = otLinkGetPanId(otInst); + err = encoder.Encode(panId); + } + break; + + case Attributes::ExtendedPanId::Id: { + const otExtendedPanId * pExtendedPanid = otThreadGetExtendedPanId(otInst); + err = encoder.Encode(Encoding::BigEndian::Get64(pExtendedPanid->m8)); + } + break; + + case Attributes::MeshLocalPrefix::Id: { + uint8_t meshLocaPrefix[OT_MESH_LOCAL_PREFIX_SIZE + 1] = { 0 }; // + 1 to encode prefix Len in the octstr + + const otMeshLocalPrefix * pMeshLocalPrefix = otThreadGetMeshLocalPrefix(otInst); + meshLocaPrefix[0] = OT_IP6_PREFIX_BITSIZE; + + memcpy(&meshLocaPrefix[1], pMeshLocalPrefix->m8, OT_MESH_LOCAL_PREFIX_SIZE); + err = encoder.Encode(ByteSpan(meshLocaPrefix)); + } + break; + + case Attributes::OverrunCount::Id: { + uint64_t overrunCount = 0; // mOverrunCount; + err = encoder.Encode(overrunCount); + } + break; + + case Attributes::NeighborTable::Id: { + err = encoder.EncodeList([otInst](const auto & aEncoder) -> CHIP_ERROR { + constexpr uint16_t kFrameErrorRate100Percent = 0xffff; + constexpr uint16_t kMessageErrorRate100Percent = 0xffff; + + otNeighborInfo neighInfo; + otNeighborInfoIterator iterator = OT_NEIGHBOR_INFO_ITERATOR_INIT; + + while (otThreadGetNextNeighborInfo(otInst, &iterator, &neighInfo) == OT_ERROR_NONE) + { + Structs::NeighborTableStruct::Type neighborTable; + app::DataModel::Nullable averageRssi; + app::DataModel::Nullable lastRssi; + + if (neighInfo.mAverageRssi == OT_RADIO_RSSI_INVALID) + { + averageRssi.SetNull(); + } + else + { + // Thread average calculation already restrict mAverageRssi to be between -128 and 0 + averageRssi.SetNonNull(neighInfo.mAverageRssi); + } + + if (neighInfo.mLastRssi == OT_RADIO_RSSI_INVALID) + { + lastRssi.SetNull(); + } + else + { + lastRssi.SetNonNull(min(static_cast(0), neighInfo.mLastRssi)); + } + + neighborTable.averageRssi = averageRssi; + neighborTable.lastRssi = lastRssi; + neighborTable.extAddress = Encoding::BigEndian::Get64(neighInfo.mExtAddress.m8); + neighborTable.age = neighInfo.mAge; + neighborTable.rloc16 = neighInfo.mRloc16; + neighborTable.linkFrameCounter = neighInfo.mLinkFrameCounter; + neighborTable.mleFrameCounter = neighInfo.mMleFrameCounter; + neighborTable.lqi = neighInfo.mLinkQualityIn; + neighborTable.frameErrorRate = + static_cast((static_cast(neighInfo.mFrameErrorRate) * 100) / kFrameErrorRate100Percent); + neighborTable.messageErrorRate = + static_cast((static_cast(neighInfo.mMessageErrorRate) * 100) / kMessageErrorRate100Percent); + neighborTable.rxOnWhenIdle = neighInfo.mRxOnWhenIdle; + neighborTable.fullThreadDevice = neighInfo.mFullThreadDevice; + neighborTable.fullNetworkData = neighInfo.mFullNetworkData; + neighborTable.isChild = neighInfo.mIsChild; + + ReturnErrorOnFailure(aEncoder.Encode(neighborTable)); + } + + return CHIP_NO_ERROR; + }); + } + break; + + case Attributes::RouteTable::Id: { + err = encoder.EncodeList([otInst](const auto & aEncoder) -> CHIP_ERROR { + otRouterInfo routerInfo; + +#if CHIP_DEVICE_CONFIG_THREAD_FTD + uint8_t maxRouterId = otThreadGetMaxRouterId(otInst); + CHIP_ERROR chipErr = CHIP_ERROR_INCORRECT_STATE; + + for (uint8_t i = 0; i <= maxRouterId; i++) + { + if (otThreadGetRouterInfo(otInst, i, &routerInfo) == OT_ERROR_NONE) + { + Structs::RouteTableStruct::Type routeTable; + + routeTable.extAddress = Encoding::BigEndian::Get64(routerInfo.mExtAddress.m8); + routeTable.rloc16 = routerInfo.mRloc16; + routeTable.routerId = routerInfo.mRouterId; + routeTable.nextHop = routerInfo.mNextHop; + routeTable.pathCost = routerInfo.mPathCost; + routeTable.LQIIn = routerInfo.mLinkQualityIn; + routeTable.LQIOut = routerInfo.mLinkQualityOut; + routeTable.age = routerInfo.mAge; + routeTable.allocated = routerInfo.mAllocated; + routeTable.linkEstablished = routerInfo.mLinkEstablished; + + ReturnErrorOnFailure(aEncoder.Encode(routeTable)); + chipErr = CHIP_NO_ERROR; + } + } + + return chipErr; + +#else // OPENTHREAD_MTD + otError otErr = otThreadGetParentInfo(otInst, &routerInfo); + ReturnErrorOnFailure(Internal::MapOpenThreadError(otErr)); + + Structs::RouteTableStruct::Type routeTable; + + routeTable.extAddress = Encoding::BigEndian::Get64(routerInfo.mExtAddress.m8); + routeTable.rloc16 = routerInfo.mRloc16; + routeTable.routerId = routerInfo.mRouterId; + routeTable.nextHop = routerInfo.mNextHop; + routeTable.pathCost = routerInfo.mPathCost; + routeTable.LQIIn = routerInfo.mLinkQualityIn; + routeTable.LQIOut = routerInfo.mLinkQualityOut; + routeTable.age = routerInfo.mAge; + routeTable.allocated = routerInfo.mAllocated; + routeTable.linkEstablished = routerInfo.mLinkEstablished; + + ReturnErrorOnFailure(aEncoder.Encode(routeTable)); + return CHIP_NO_ERROR; +#endif + }); + } + break; + + case Attributes::PartitionId::Id: { + uint32_t partitionId = otThreadGetPartitionId(otInst); + err = encoder.Encode(partitionId); + } + break; + + case Attributes::Weighting::Id: { + uint8_t weight = otThreadGetLeaderWeight(otInst); + err = encoder.Encode(weight); + } + break; + + case Attributes::DataVersion::Id: { + uint8_t dataVersion = otNetDataGetVersion(otInst); + err = encoder.Encode(dataVersion); + } + break; + + case Attributes::StableDataVersion::Id: { + uint8_t stableVersion = otNetDataGetStableVersion(otInst); + err = encoder.Encode(stableVersion); + } + break; + + case Attributes::LeaderRouterId::Id: { + uint8_t leaderRouterId = otThreadGetLeaderRouterId(otInst); + err = encoder.Encode(leaderRouterId); + } + break; + + case Attributes::DetachedRoleCount::Id: { + uint16_t detachedRole = otThreadGetMleCounters(otInst)->mDetachedRole; + err = encoder.Encode(detachedRole); + } + break; + + case Attributes::ChildRoleCount::Id: { + uint16_t childRole = otThreadGetMleCounters(otInst)->mChildRole; + err = encoder.Encode(childRole); + } + break; + + case Attributes::RouterRoleCount::Id: { + uint16_t routerRole = otThreadGetMleCounters(otInst)->mRouterRole; + err = encoder.Encode(routerRole); + } + break; + + case Attributes::LeaderRoleCount::Id: { + uint16_t leaderRole = otThreadGetMleCounters(otInst)->mLeaderRole; + err = encoder.Encode(leaderRole); + } + break; + + case Attributes::AttachAttemptCount::Id: { + uint16_t attachAttempts = otThreadGetMleCounters(otInst)->mAttachAttempts; + err = encoder.Encode(attachAttempts); + } + break; + + case Attributes::PartitionIdChangeCount::Id: { + uint16_t partitionIdChanges = otThreadGetMleCounters(otInst)->mPartitionIdChanges; + err = encoder.Encode(partitionIdChanges); + } + break; + + case Attributes::BetterPartitionAttachAttemptCount::Id: { + uint16_t betterPartitionAttachAttempts = otThreadGetMleCounters(otInst)->mBetterPartitionAttachAttempts; + err = encoder.Encode(betterPartitionAttachAttempts); + } + break; + + case Attributes::ParentChangeCount::Id: { + uint16_t parentChanges = otThreadGetMleCounters(otInst)->mParentChanges; + err = encoder.Encode(parentChanges); + } + break; + + case Attributes::TxTotalCount::Id: { + uint32_t txTotal = otLinkGetCounters(otInst)->mTxTotal; + err = encoder.Encode(txTotal); + } + break; + + case Attributes::TxUnicastCount::Id: { + uint32_t txUnicast = otLinkGetCounters(otInst)->mTxUnicast; + err = encoder.Encode(txUnicast); + } + break; + + case Attributes::TxBroadcastCount::Id: { + uint32_t txBroadcast = otLinkGetCounters(otInst)->mTxBroadcast; + err = encoder.Encode(txBroadcast); + } + break; + + case Attributes::TxAckRequestedCount::Id: { + uint32_t txAckRequested = otLinkGetCounters(otInst)->mTxAckRequested; + err = encoder.Encode(txAckRequested); + } + break; + + case Attributes::TxAckedCount::Id: { + uint32_t txAcked = otLinkGetCounters(otInst)->mTxAcked; + err = encoder.Encode(txAcked); + } + break; + + case Attributes::TxNoAckRequestedCount::Id: { + uint32_t txNoAckRequested = otLinkGetCounters(otInst)->mTxNoAckRequested; + err = encoder.Encode(txNoAckRequested); + } + break; + + case Attributes::TxDataCount::Id: { + uint32_t txData = otLinkGetCounters(otInst)->mTxData; + err = encoder.Encode(txData); + } + break; + + case Attributes::TxDataPollCount::Id: { + uint32_t txDataPoll = otLinkGetCounters(otInst)->mTxDataPoll; + err = encoder.Encode(txDataPoll); + } + break; + + case Attributes::TxBeaconCount::Id: { + uint32_t txBeacon = otLinkGetCounters(otInst)->mTxBeacon; + err = encoder.Encode(txBeacon); + } + break; + + case Attributes::TxBeaconRequestCount::Id: { + uint32_t txBeaconRequest = otLinkGetCounters(otInst)->mTxBeaconRequest; + err = encoder.Encode(txBeaconRequest); + } + break; + + case Attributes::TxOtherCount::Id: { + uint32_t txOther = otLinkGetCounters(otInst)->mTxOther; + err = encoder.Encode(txOther); + } + break; + + case Attributes::TxRetryCount::Id: { + uint32_t txRetry = otLinkGetCounters(otInst)->mTxRetry; + err = encoder.Encode(txRetry); + } + break; + + case Attributes::TxDirectMaxRetryExpiryCount::Id: { + uint32_t txDirectMaxRetryExpiry = otLinkGetCounters(otInst)->mTxDirectMaxRetryExpiry; + err = encoder.Encode(txDirectMaxRetryExpiry); + } + break; + + case Attributes::TxIndirectMaxRetryExpiryCount::Id: { + uint32_t txIndirectMaxRetryExpiry = otLinkGetCounters(otInst)->mTxIndirectMaxRetryExpiry; + err = encoder.Encode(txIndirectMaxRetryExpiry); + } + break; + + case Attributes::TxErrCcaCount::Id: { + uint32_t txErrCca = otLinkGetCounters(otInst)->mTxErrCca; + err = encoder.Encode(txErrCca); + } + break; + + case Attributes::TxErrAbortCount::Id: { + uint32_t TxErrAbort = otLinkGetCounters(otInst)->mTxErrAbort; + err = encoder.Encode(TxErrAbort); + } + break; + + case Attributes::TxErrBusyChannelCount::Id: { + uint32_t TxErrBusyChannel = otLinkGetCounters(otInst)->mTxErrBusyChannel; + err = encoder.Encode(TxErrBusyChannel); + } + break; + + case Attributes::RxTotalCount::Id: { + uint32_t rxTotal = otLinkGetCounters(otInst)->mRxTotal; + err = encoder.Encode(rxTotal); + } + break; + + case Attributes::RxUnicastCount::Id: { + uint32_t rxUnicast = otLinkGetCounters(otInst)->mRxUnicast; + err = encoder.Encode(rxUnicast); + } + break; + + case Attributes::RxBroadcastCount::Id: { + uint32_t rxBroadcast = otLinkGetCounters(otInst)->mRxBroadcast; + err = encoder.Encode(rxBroadcast); + } + break; + + case Attributes::RxDataCount::Id: { + uint32_t rxData = otLinkGetCounters(otInst)->mRxData; + err = encoder.Encode(rxData); + } + break; + + case Attributes::RxDataPollCount::Id: { + uint32_t rxDataPoll = otLinkGetCounters(otInst)->mRxDataPoll; + err = encoder.Encode(rxDataPoll); + } + break; + + case Attributes::RxBeaconCount::Id: { + uint32_t rxBeacon = otLinkGetCounters(otInst)->mRxBeacon; + err = encoder.Encode(rxBeacon); + } + break; + + case Attributes::RxBeaconRequestCount::Id: { + uint32_t rxBeaconRequest = otLinkGetCounters(otInst)->mRxBeaconRequest; + err = encoder.Encode(rxBeaconRequest); + } + break; + + case Attributes::RxOtherCount::Id: { + uint32_t rxOther = otLinkGetCounters(otInst)->mRxOther; + err = encoder.Encode(rxOther); + } + break; + + case Attributes::RxAddressFilteredCount::Id: { + uint32_t rxAddressFiltered = otLinkGetCounters(otInst)->mRxAddressFiltered; + err = encoder.Encode(rxAddressFiltered); + } + break; + + case Attributes::RxDestAddrFilteredCount::Id: { + uint32_t rxDestAddrFiltered = otLinkGetCounters(otInst)->mRxDestAddrFiltered; + err = encoder.Encode(rxDestAddrFiltered); + } + break; + + case Attributes::RxDuplicatedCount::Id: { + uint32_t rxDuplicated = otLinkGetCounters(otInst)->mRxDuplicated; + err = encoder.Encode(rxDuplicated); + } + break; + + case Attributes::RxErrNoFrameCount::Id: { + uint32_t rxErrNoFrame = otLinkGetCounters(otInst)->mRxErrNoFrame; + err = encoder.Encode(rxErrNoFrame); + } + break; + + case Attributes::RxErrUnknownNeighborCount::Id: { + uint32_t rxErrUnknownNeighbor = otLinkGetCounters(otInst)->mRxErrUnknownNeighbor; + err = encoder.Encode(rxErrUnknownNeighbor); + } + break; + + case Attributes::RxErrInvalidSrcAddrCount::Id: { + uint32_t rxErrInvalidSrcAddr = otLinkGetCounters(otInst)->mRxErrInvalidSrcAddr; + err = encoder.Encode(rxErrInvalidSrcAddr); + } + break; + + case Attributes::RxErrSecCount::Id: { + uint32_t rxErrSec = otLinkGetCounters(otInst)->mRxErrSec; + err = encoder.Encode(rxErrSec); + } + break; + + case Attributes::RxErrFcsCount::Id: { + uint32_t rxErrFcs = otLinkGetCounters(otInst)->mRxErrFcs; + err = encoder.Encode(rxErrFcs); + } + break; + + case Attributes::RxErrOtherCount::Id: { + uint32_t rxErrOther = otLinkGetCounters(otInst)->mRxErrOther; + err = encoder.Encode(rxErrOther); + } + break; + + case Attributes::ActiveTimestamp::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + uint64_t activeTimestamp = (activeDataset.mActiveTimestamp.mSeconds << 16) | (activeDataset.mActiveTimestamp.mTicks << 1) | + activeDataset.mActiveTimestamp.mAuthoritative; + err = encoder.Encode(activeTimestamp); + } + break; + + case Attributes::PendingTimestamp::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + uint64_t pendingTimestamp = (activeDataset.mPendingTimestamp.mSeconds << 16) | + (activeDataset.mPendingTimestamp.mTicks << 1) | activeDataset.mPendingTimestamp.mAuthoritative; + err = encoder.Encode(pendingTimestamp); + } + break; + + case Attributes::Delay::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + uint32_t delay = activeDataset.mDelay; + err = encoder.Encode(delay); + } + break; + + case Attributes::SecurityPolicy::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + + Structs::SecurityPolicy::Type securityPolicy; + static_assert(sizeof(securityPolicy) == sizeof(activeDataset.mSecurityPolicy), + "securityPolicy Struct do not match otSecurityPolicy"); + uint16_t policyAsInts[2]; + static_assert(sizeof(policyAsInts) == sizeof(activeDataset.mSecurityPolicy), + "We're missing some members of otSecurityPolicy?"); + memcpy(&policyAsInts, &activeDataset.mSecurityPolicy, sizeof(policyAsInts)); + securityPolicy.rotationTime = policyAsInts[0]; + securityPolicy.flags = policyAsInts[1]; + err = encoder.Encode(securityPolicy); + } + break; + + case Attributes::ChannelPage0Mask::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + + // In the resultant Octet string, the most significant bit of the left-most byte indicates channel 0 + // We have to bitswap the entire uint32_t before converting to octet string + uint32_t bitSwappedChannelMask = 0; + for (int i = 0, j = 31; i < 32; i++, j--) + { + bitSwappedChannelMask |= ((activeDataset.mChannelMask >> j) & 1) << i; + } + + uint8_t buffer[sizeof(uint32_t)] = { 0 }; + Encoding::BigEndian::Put32(buffer, bitSwappedChannelMask); + err = encoder.Encode(ByteSpan(buffer)); + } + break; + + case Attributes::OperationalDatasetComponents::Id: { + otOperationalDataset activeDataset; + otError otErr = otDatasetGetActive(otInst, &activeDataset); + VerifyOrReturnError(otErr == OT_ERROR_NONE, Internal::MapOpenThreadError(otErr)); + Structs::OperationalDatasetComponents::Type OpDatasetComponents; + + OpDatasetComponents.activeTimestampPresent = activeDataset.mComponents.mIsActiveTimestampPresent; + OpDatasetComponents.pendingTimestampPresent = activeDataset.mComponents.mIsPendingTimestampPresent; + OpDatasetComponents.masterKeyPresent = activeDataset.mComponents.mIsNetworkKeyPresent; + OpDatasetComponents.networkNamePresent = activeDataset.mComponents.mIsNetworkNamePresent; + OpDatasetComponents.extendedPanIdPresent = activeDataset.mComponents.mIsExtendedPanIdPresent; + OpDatasetComponents.meshLocalPrefixPresent = activeDataset.mComponents.mIsMeshLocalPrefixPresent; + OpDatasetComponents.delayPresent = activeDataset.mComponents.mIsDelayPresent; + OpDatasetComponents.panIdPresent = activeDataset.mComponents.mIsPanIdPresent; + OpDatasetComponents.channelPresent = activeDataset.mComponents.mIsChannelPresent; + OpDatasetComponents.pskcPresent = activeDataset.mComponents.mIsPskcPresent; + OpDatasetComponents.securityPolicyPresent = activeDataset.mComponents.mIsSecurityPolicyPresent; + OpDatasetComponents.channelMaskPresent = activeDataset.mComponents.mIsChannelMaskPresent; + + err = encoder.Encode(OpDatasetComponents); + } + break; + + case Attributes::ActiveNetworkFaultsList::Id: { + err = encoder.EncodeList([](const auto & aEncoder) -> CHIP_ERROR { + // TODO activeNetworkFaultsList isn't tracked. Encode the list of 4 entries at 0 none the less + NetworkFaultEnum activeNetworkFaultsList[4] = { NetworkFaultEnum(0) }; + for (auto fault : activeNetworkFaultsList) + { + ReturnErrorOnFailure(aEncoder.Encode(fault)); + } + + return CHIP_NO_ERROR; + }); + } + break; + + default: { + err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + } + break; + } + +#elif (CHIP_DEVICE_CONFIG_ENABLE_THREAD && CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK) + switch (attributeId) + { + case Attributes::NeighborTable::Id: + case Attributes::RouteTable::Id: + case Attributes::ActiveNetworkFaultsList::Id: + err = encoder.EncodeEmptyList(); + break; + case Attributes::Channel::Id: + case Attributes::RoutingRole::Id: + case Attributes::NetworkName::Id: + case Attributes::PanId::Id: + case Attributes::ExtendedPanId::Id: + case Attributes::MeshLocalPrefix::Id: + case Attributes::PartitionId::Id: + case Attributes::Weighting::Id: + case Attributes::DataVersion::Id: + case Attributes::StableDataVersion::Id: + case Attributes::LeaderRouterId::Id: + case Attributes::ActiveTimestamp::Id: + case Attributes::PendingTimestamp::Id: + case Attributes::Delay::Id: + case Attributes::ChannelPage0Mask::Id: + case Attributes::SecurityPolicy::Id: + case Attributes::OperationalDatasetComponents::Id: + err = encoder.EncodeNull(); + break; + case Attributes::OverrunCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::DetachedRoleCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::ChildRoleCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RouterRoleCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::LeaderRoleCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::AttachAttemptCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::PartitionIdChangeCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::BetterPartitionAttachAttemptCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::ParentChangeCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxTotalCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxUnicastCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxBroadcastCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxAckRequestedCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxAckedCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxNoAckRequestedCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxDataCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxDataPollCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxBeaconCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxBeaconRequestCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxOtherCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxRetryCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxDirectMaxRetryExpiryCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxIndirectMaxRetryExpiryCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxErrCcaCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxErrAbortCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::TxErrBusyChannelCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxTotalCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxUnicastCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxBroadcastCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxDataCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxDataPollCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxBeaconCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxBeaconRequestCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxOtherCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxAddressFilteredCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxDestAddrFilteredCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxDuplicatedCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrNoFrameCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrUnknownNeighborCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrInvalidSrcAddrCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrSecCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrFcsCount::Id: + err = encoder.Encode(static_cast(0)); + break; + case Attributes::RxErrOtherCount::Id: + err = encoder.Encode(static_cast(0)); + break; + default: + err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; + break; + } +#else + err = CHIP_ERROR_NOT_IMPLEMENTED; +#endif // (CHIP_DEVICE_CONFIG_ENABLE_THREAD && !CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK) + return err; +} + +} // namespace ThreadNetworkDiagnostics +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.h b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.h new file mode 100644 index 00000000000000..8b1a2a5640ce38 --- /dev/null +++ b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-provider.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ThreadNetworkDiagnostics { + +CHIP_ERROR WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); + +} // namespace ThreadNetworkDiagnostics +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp index 9908fc77c91334..cae2948e8e970e 100644 --- a/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp +++ b/src/app/clusters/thread-network-diagnostics-server/thread-network-diagnostics-server.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -29,7 +30,6 @@ #include #include #include -#include using namespace chip; using namespace chip::app; @@ -125,7 +125,7 @@ CHIP_ERROR ThreadDiagosticsAttrAccess::Read(const ConcreteReadAttributePath & aP case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: case ThreadNetworkDiagnostics::Attributes::Delay::Id: case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: - return ConnectivityMgr().WriteThreadNetworkDiagnosticAttributeToTlv(aPath.mAttributeId, aEncoder); + return WriteThreadNetworkDiagnosticAttributeToTlv(aPath.mAttributeId, aEncoder); default: break; } diff --git a/src/app/icd/BUILD.gn b/src/app/icd/BUILD.gn index ba72052fffbffa..f1d3a8a382c9d0 100644 --- a/src/app/icd/BUILD.gn +++ b/src/app/icd/BUILD.gn @@ -70,7 +70,7 @@ source_set("manager") { ":notifier", ":observer", ":sender", - "${chip_root}/src/app:interaction-model", + "${chip_root}/src/app:subscription-manager", "${chip_root}/src/credentials:credentials", ] } @@ -114,5 +114,6 @@ source_set("configuration-data") { deps = [ ":icd_config", "${chip_root}/src/lib/core", + "${chip_root}/src/lib/support", ] } diff --git a/src/app/icd/ICDConfigurationData.cpp b/src/app/icd/ICDConfigurationData.cpp index 4df2ca75f217b9..9c2079a4386742 100644 --- a/src/app/icd/ICDConfigurationData.cpp +++ b/src/app/icd/ICDConfigurationData.cpp @@ -17,6 +17,7 @@ #include "ICDConfigurationData.h" #include +#include namespace chip { @@ -36,4 +37,16 @@ System::Clock::Milliseconds32 ICDConfigurationData::GetSlowPollingInterval() return mSlowPollingInterval; } +CHIP_ERROR ICDConfigurationData::SetModeDurations(uint32_t activeModeDuration_ms, uint32_t idleModeInterval_s) +{ + VerifyOrReturnError(activeModeDuration_ms <= (idleModeInterval_s * 1000), CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(idleModeInterval_s <= kMaxIdleModeDuration_s, CHIP_ERROR_INVALID_ARGUMENT); + VerifyOrReturnError(idleModeInterval_s >= kMinIdleModeDuration_s, CHIP_ERROR_INVALID_ARGUMENT); + + mIdleModeDuration_s = idleModeInterval_s; + mActiveModeDuration_ms = activeModeDuration_ms; + + return CHIP_NO_ERROR; +} + } // namespace chip diff --git a/src/app/icd/ICDConfigurationData.h b/src/app/icd/ICDConfigurationData.h index 48f3966a5e5948..2762077429b006 100644 --- a/src/app/icd/ICDConfigurationData.h +++ b/src/app/icd/ICDConfigurationData.h @@ -25,6 +25,11 @@ namespace chip { namespace app { // Forward declaration of ICDManager to allow it to be friend with ICDConfigurationData class ICDManager; + +// Forward declaration of TestICDManager to allow it to be friend with the ICDConfigurationData +// Used in unit tests +class TestICDManager; + } // namespace app /** @@ -47,9 +52,9 @@ class ICDConfigurationData static ICDConfigurationData & GetInstance() { return instance; }; - uint32_t GetIdleModeDurationSec() { return mIdleInterval_s; } + uint32_t GetIdleModeDurationSec() { return mIdleModeDuration_s; } - uint32_t GetActiveModeDurationMs() { return mActiveInterval_ms; } + uint32_t GetActiveModeDurationMs() { return mActiveModeDuration_ms; } uint16_t GetActiveModeThresholdMs() { return mActiveThreshold_ms; } @@ -89,6 +94,7 @@ class ICDConfigurationData // the ICDManager, the ICDManager is a friend that can access the private setters. If a consummer needs to be notified when a // value is changed, they can leverage the Observer events the ICDManager generates. See src/app/icd/ICDStateObserver.h friend class chip::app::ICDManager; + friend class chip::app::TestICDManager; void SetICDMode(ICDMode mode) { mICDMode = mode; }; void SetICDCounter(uint32_t count) { mICDCounter = count; } @@ -97,15 +103,31 @@ class ICDConfigurationData static constexpr uint32_t kMinLitActiveModeThreshold_ms = 5000; - static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= 64800, + /** + * @brief Change the ActiveModeDuration and IdleModeDuration value + * To only change one value, pass the old value for the other one + * + * @param[in] activeModeDuration_ms new ActiveModeDuration value + * @param[in] idleModeDuration_s new IdleModeDuration value + * @return CHIP_ERROR CHIP_ERROR_INVALID_ARGUMENT is returned if idleModeDuration_s is smaller than activeModeDuration_ms + * is returned if idleModeDuration_s is greater than 64800 seconds + * is returned if idleModeDuration_s is smaller than 1 seconds + * CHIP_NO_ERROR is returned if the new intervals were set + */ + CHIP_ERROR SetModeDurations(uint32_t activeModeDuration_ms, uint32_t idleModeDuration_s); + + static constexpr uint32_t kMaxIdleModeDuration_s = 64800; + static constexpr uint32_t kMinIdleModeDuration_s = 1; + + static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) <= kMaxIdleModeDuration_s, "Spec requires the IdleModeDuration to be equal or inferior to 64800s."); - static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= 1, + static_assert((CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC) >= kMinIdleModeDuration_s, "Spec requires the IdleModeDuration to be equal or greater to 1s."); - uint32_t mIdleInterval_s = CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC; + uint32_t mIdleModeDuration_s = CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC; static_assert((CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS) <= (CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC * kMillisecondsPerSecond), "Spec requires the IdleModeDuration be equal or greater to the ActiveModeDuration."); - uint32_t mActiveInterval_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS; + uint32_t mActiveModeDuration_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS; uint16_t mActiveThreshold_ms = CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS; diff --git a/src/app/icd/ICDManager.cpp b/src/app/icd/ICDManager.cpp index 99e8e950dd853f..f6c1fe5cca32b8 100644 --- a/src/app/icd/ICDManager.cpp +++ b/src/app/icd/ICDManager.cpp @@ -18,7 +18,6 @@ #include #include #include -#include #include #include #include @@ -41,12 +40,13 @@ static_assert(UINT8_MAX >= CHIP_CONFIG_MAX_EXCHANGE_CONTEXTS, "ICDManager::mOpenExchangeContextCount cannot hold count for the max exchange count"); void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeystore, - Messaging::ExchangeManager * exchangeManager) + Messaging::ExchangeManager * exchangeManager, SubscriptionManager * manager) { VerifyOrDie(storage != nullptr); VerifyOrDie(fabricTable != nullptr); VerifyOrDie(symmetricKeystore != nullptr); VerifyOrDie(exchangeManager != nullptr); + VerifyOrDie(manager != nullptr); // LIT ICD Verification Checks if (SupportsFeature(Feature::kLongIdleTimeSupport)) @@ -63,11 +63,13 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT // "LIT support is required for slow polling intervals superior to 15 seconds"); } - mStorage = storage; - mFabricTable = fabricTable; VerifyOrDie(ICDNotifier::GetInstance().Subscribe(this) == CHIP_NO_ERROR); + + mStorage = storage; + mFabricTable = fabricTable; mSymmetricKeystore = symmetricKeystore; mExchangeManager = exchangeManager; + mSubManager = manager; VerifyOrDie(InitCounter() == CHIP_NO_ERROR); @@ -78,14 +80,19 @@ void ICDManager::Init(PersistentStorageDelegate * storage, FabricTable * fabricT void ICDManager::Shutdown() { ICDNotifier::GetInstance().Unsubscribe(this); + // cancel any running timer of the icd DeviceLayer::SystemLayer().CancelTimer(OnIdleModeDone, this); DeviceLayer::SystemLayer().CancelTimer(OnActiveModeDone, this); DeviceLayer::SystemLayer().CancelTimer(OnTransitionToIdle, this); + ICDConfigurationData::GetInstance().SetICDMode(ICDConfigurationData::ICDMode::SIT); mOperationalState = OperationalState::ActiveMode; - mStorage = nullptr; - mFabricTable = nullptr; + + mStorage = nullptr; + mFabricTable = nullptr; + mSubManager = nullptr; + mStateObserverPool.ReleaseAll(); mICDSenderPool.ReleaseAll(); } @@ -137,8 +144,7 @@ void ICDManager::SendCheckInMsgs() continue; } - bool active = - InteractionModelEngine::GetInstance()->SubjectHasActiveSubscription(entry.fabricIndex, entry.monitoredSubject); + bool active = mSubManager->SubjectHasActiveSubscription(entry.fabricIndex, entry.monitoredSubject); if (active) { continue; @@ -272,7 +278,9 @@ void ICDManager::UpdateOperationState(OperationalState state) mOperationalState = OperationalState::IdleMode; // When the active mode interval is 0, we stay in idleMode until a notification brings the icd into active mode - if (ICDConfigurationData::GetInstance().GetActiveModeDurationMs() > 0) + // unless the device would need to send Check-In messages + // TODO(#30281) : Verify how persistent subscriptions affects this at ICDManager::Init + if (ICDConfigurationData::GetInstance().GetActiveModeDurationMs() > 0 || CheckInMessagesWouldBeSent()) { uint32_t idleModeDuration = ICDConfigurationData::GetInstance().GetIdleModeDurationSec(); DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(idleModeDuration), OnIdleModeDone, this); @@ -538,5 +546,44 @@ void ICDManager::postObserverEvent(ObserverEventType event) } }); } + +bool ICDManager::CheckInMessagesWouldBeSent() +{ + for (const auto & fabricInfo : *mFabricTable) + { + uint16_t supported_clients = ICDConfigurationData::GetInstance().GetClientsSupportedPerFabric(); + + ICDMonitoringTable table(*mStorage, fabricInfo.GetFabricIndex(), supported_clients /*Table entry limit*/, + mSymmetricKeystore); + if (table.IsEmpty()) + { + continue; + } + + for (uint16_t i = 0; i < table.Limit(); i++) + { + ICDMonitoringEntry entry(mSymmetricKeystore); + CHIP_ERROR err = table.Get(i, entry); + if (err == CHIP_ERROR_NOT_FOUND) + { + break; + } + + if (err != CHIP_NO_ERROR) + { + // Try to fetch the next entry upon failure (should not happen). + ChipLogError(AppServer, "Failed to retrieved ICDMonitoring entry, will try next entry."); + continue; + } + + // At least one registration would require a Check-In message + VerifyOrReturnValue(mSubManager->SubjectHasActiveSubscription(entry.fabricIndex, entry.monitoredSubject), true); + } + } + + // None of the registrations would require a Check-In message + return false; +} + } // namespace app } // namespace chip diff --git a/src/app/icd/ICDManager.h b/src/app/icd/ICDManager.h index 81011c688858c3..429942302d2227 100644 --- a/src/app/icd/ICDManager.h +++ b/src/app/icd/ICDManager.h @@ -17,6 +17,7 @@ #pragma once #include +#include #include #include #include @@ -66,7 +67,7 @@ class ICDManager : public ICDListener ICDManager() {} void Init(PersistentStorageDelegate * storage, FabricTable * fabricTable, Crypto::SymmetricKeystore * symmetricKeyStore, - Messaging::ExchangeManager * exchangeManager); + Messaging::ExchangeManager * exchangeManager, SubscriptionManager * manager); void Shutdown(); void UpdateICDMode(); void UpdateOperationState(OperationalState state); @@ -100,7 +101,7 @@ class ICDManager : public ICDListener #endif // Implementation of ICDListener functions. - // Callers must origin from the chip task context or be holding the ChipStack lock. + // Callers must origin from the chip task context or hold the ChipStack lock. void OnNetworkActivity() override; void OnKeepActiveRequest(KeepActiveFlags request) override; void OnActiveRequestWithdrawal(KeepActiveFlags request) override; @@ -129,15 +130,28 @@ class ICDManager : public ICDListener uint8_t mCheckInRequestCount = 0; private: + /** + * @brief Function checks if at least one client registration would require a Check-In message + * + * @return true At least one registration would require an Check-In message if we were entering ActiveMode. + * @return false None of the registration would require a Check-In message either because there are no registration or because + * they all have associated subscriptions. + */ + bool CheckInMessagesWouldBeSent(); + KeepActiveFlags mKeepActiveFlags{ 0 }; // Initialize mOperationalState to ActiveMode so the init sequence at bootup triggers the IdleMode behaviour first. - OperationalState mOperationalState = OperationalState::ActiveMode; + OperationalState mOperationalState = OperationalState::ActiveMode; + PersistentStorageDelegate * mStorage = nullptr; FabricTable * mFabricTable = nullptr; Messaging::ExchangeManager * mExchangeManager = nullptr; - bool mTransitionToIdleCalled = false; Crypto::SymmetricKeystore * mSymmetricKeystore = nullptr; + SubscriptionManager * mSubManager = nullptr; + + bool mTransitionToIdleCalled = false; + ObjectPool mStateObserverPool; ObjectPool mICDSenderPool; diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index 4a0fa91f56d520..3c33c45537d5ef 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -339,7 +339,8 @@ CHIP_ERROR Server::Init(const ServerInitParams & initParams) mICDManager.RegisterObserver(mReportScheduler); mICDManager.RegisterObserver(&app::DnssdServer::Instance()); - mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr); + mICDManager.Init(mDeviceStorage, &GetFabricTable(), mSessionKeystore, &mExchangeMgr, + chip::app::InteractionModelEngine::GetInstance()); #endif // CHIP_CONFIG_ENABLE_ICD_SERVER // This code is necessary to restart listening to existing groups after a reboot diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 9a21f1f4589d81..520fb3adf85675 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -231,7 +231,7 @@ chip_test_suite_using_nltest("tests") { # Do not run TestCommissionManager when running ICD specific unit tests. # ICDManager has a dependency on the Accessors.h file which causes a link error # when building the TestCommissionManager - if (!chip_enable_icd_server && chip_config_network_layer_ble && + if (chip_config_network_layer_ble && (chip_device_platform == "linux" || chip_device_platform == "darwin")) { test_sources += [ "TestCommissionManager.cpp" ] public_deps += [ "${chip_root}/src/app/server" ] diff --git a/src/app/tests/TestICDManager.cpp b/src/app/tests/TestICDManager.cpp index f4ff46fd713556..06669b45d1cd51 100644 --- a/src/app/tests/TestICDManager.cpp +++ b/src/app/tests/TestICDManager.cpp @@ -16,11 +16,14 @@ * limitations under the License. */ #include +#include #include #include #include #include #include +#include +#include #include #include #include @@ -68,6 +71,21 @@ class TestICDStateObserver : public app::ICDStateObserver void OnICDModeChange() {} }; +class TestSubscriptionManager : public SubscriptionManager +{ +public: + TestSubscriptionManager() = default; + ~TestSubscriptionManager(){}; + + void SetReturnValue(bool value) { mReturnValue = value; }; + + bool SubjectHasActiveSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) { return mReturnValue; }; + bool SubjectHasPersistedSubscription(const FabricIndex & aFabricIndex, const NodeId & subject) { return mReturnValue; }; + +private: + bool mReturnValue = false; +}; + class TestContext : public chip::Test::AppContext { public: @@ -93,7 +111,7 @@ class TestContext : public chip::Test::AppContext CHIP_ERROR SetUp() override { ReturnErrorOnFailure(chip::Test::AppContext::SetUp()); - mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager()); + mICDManager.Init(&testStorage, &GetFabricTable(), &mKeystore, &GetExchangeManager(), &mSubManager); mICDManager.RegisterObserver(&mICDStateObserver); return CHIP_NO_ERROR; } @@ -108,6 +126,7 @@ class TestContext : public chip::Test::AppContext System::Clock::Internal::MockClock mMockClock; TestSessionKeystoreImpl mKeystore; app::ICDManager mICDManager; + TestSubscriptionManager mSubManager; TestPersistentStorageDelegate testStorage; private: @@ -142,17 +161,17 @@ class TestICDManager // After the init we should be in Idle mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(ICDConfigurationData::GetInstance().GetIdleModeDurationSec()) + 1); - // Idle mode interval expired, ICDManager transitioned to the ActiveMode. + // Idle mode Duration expired, ICDManager transitioned to the ActiveMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); - // Active mode interval expired, ICDManager transitioned to the IdleMode. + // Active mode Duration expired, ICDManager transitioned to the IdleMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(ICDConfigurationData::GetInstance().GetIdleModeDurationSec()) + 1); - // Idle mode interval expired, ICDManager transitioned to the ActiveMode. + // Idle mode Duration expired, ICDManager transitioned to the ActiveMode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); // Events updating the Operation to Active mode can extend the current active mode time by 1 Active mode threshold. - // Kick an active Threshold just before the end of the Active interval and validate that the active mode is extended. + // Kick an active Threshold just before the end of the ActiveMode duration and validate that the active mode is extended. AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() - 1); ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeThresholdMs() / 2); @@ -161,6 +180,175 @@ class TestICDManager NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); } + /** + * @brief Test verifies that the ICDManager starts its timers correctly based on if it will have any messages to send + * when the IdleModeDuration expires + */ + static void TestICDModeDurationsWith0ActiveModeDurationWithoutActiveSub(nlTestSuite * aSuite, void * aContext) + { + TestContext * ctx = static_cast(aContext); + typedef ICDListener::ICDManagementEvents ICDMEvent; + ICDConfigurationData & icdConfigData = ICDConfigurationData::GetInstance(); + + // Set FeatureMap - Configures CIP, UAT and LITS to 1 + ctx->mICDManager.SetTestFeatureMapValue(0x07); + + // Set that there are no matching subscriptions + ctx->mSubManager.SetReturnValue(false); + + // Set New durations for test case + uint32_t oldActiveModeDuration_ms = icdConfigData.GetActiveModeDurationMs(); + icdConfigData.SetModeDurations(0, icdConfigData.GetIdleModeDurationSec()); + + // Verify That ICDManager starts in Idle + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Reset IdleModeInterval since it was started before the ActiveModeDuration change + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Force the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is now 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire Idle mode duration; ICDManager should remain in IdleMode since it has no message to send + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Add an entry to the ICDMonitoringTable + ICDMonitoringTable table(ctx->testStorage, kTestFabricIndex1, kMaxTestClients, &(ctx->mKeystore)); + + ICDMonitoringEntry entry(&(ctx->mKeystore)); + entry.checkInNodeID = kClientNodeId11; + entry.monitoredSubject = kClientNodeId11; + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == entry.SetKey(ByteSpan(kKeyBuffer1a))); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table.Set(0, entry)); + + // Trigger register event after first entry was added + ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDMEvent::kTableUpdated); + + // Check ICDManager is now in the LIT operating mode + NL_TEST_ASSERT(aSuite, icdConfigData.GetICDMode() == ICDConfigurationData::ICDMode::LIT); + + // Kick an ActiveModeThreshold since a Registration can only happen from an incoming message that would transition the ICD + // to ActiveMode + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Return the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire IdleModeDuration - Device should be in ActiveMode since it has an ICDM registration + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Remove entry from the fabric - ICDManager won't have any messages to send + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table.Remove(0)); + NL_TEST_ASSERT(aSuite, table.IsEmpty()); + + // Return the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire Idle mode duration; ICDManager should remain in IdleMode since it has no message to send + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Reset Old durations + icdConfigData.SetModeDurations(oldActiveModeDuration_ms, icdConfigData.GetIdleModeDurationSec()); + } + + /** + * @brief Test verifies that the ICDManager remains in IdleMode since it will not have any messages to send + * when the IdleModeDuration expires + */ + static void TestICDModeDurationsWith0ActiveModeDurationWithActiveSub(nlTestSuite * aSuite, void * aContext) + { + TestContext * ctx = static_cast(aContext); + typedef ICDListener::ICDManagementEvents ICDMEvent; + ICDConfigurationData & icdConfigData = ICDConfigurationData::GetInstance(); + + // Set FeatureMap - Configures CIP, UAT and LITS to 1 + ctx->mICDManager.SetTestFeatureMapValue(0x07); + + // Set that there are not matching subscriptions + ctx->mSubManager.SetReturnValue(true); + + // Set New durations for test case + uint32_t oldActiveModeDuration_ms = icdConfigData.GetActiveModeDurationMs(); + icdConfigData.SetModeDurations(0, icdConfigData.GetIdleModeDurationSec()); + + // Verify That ICDManager starts in Idle + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Reset IdleModeInterval since it was started before the ActiveModeDuration change + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Force the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is now 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire Idle mode duration; ICDManager should remain in IdleMode since it has no message to send + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Add an entry to the ICDMonitoringTable + ICDMonitoringTable table(ctx->testStorage, kTestFabricIndex1, kMaxTestClients, &(ctx->mKeystore)); + + ICDMonitoringEntry entry(&(ctx->mKeystore)); + entry.checkInNodeID = kClientNodeId11; + entry.monitoredSubject = kClientNodeId11; + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == entry.SetKey(ByteSpan(kKeyBuffer1a))); + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table.Set(0, entry)); + + // Trigger register event after first entry was added + ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDMEvent::kTableUpdated); + + // Check ICDManager is now in the LIT operating mode + NL_TEST_ASSERT(aSuite, icdConfigData.GetICDMode() == ICDConfigurationData::ICDMode::LIT); + + // Kick an ActiveModeThreshold since a Registration can only happen from an incoming message that would transition the ICD + // to ActiveMode + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Return the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire IdleModeDuration - Device stay in IdleMode since it has an active subscription for the ICDM entry + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Remove entry from the fabric + NL_TEST_ASSERT(aSuite, CHIP_NO_ERROR == table.Remove(0)); + NL_TEST_ASSERT(aSuite, table.IsEmpty()); + + // Trigger unregister event after last entry was removed + ICDNotifier::GetInstance().NotifyICDManagementEvent(ICDMEvent::kTableUpdated); + + // Check ICDManager is now in the LIT operating mode + NL_TEST_ASSERT(aSuite, icdConfigData.GetICDMode() == ICDConfigurationData::ICDMode::SIT); + + // Kick an ActiveModeThreshold since a Unregistration can only happen from an incoming message that would transition the ICD + // to ActiveMode + ICDNotifier::GetInstance().NotifyNetworkActivityNotification(); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); + + // Return the device to return to IdleMode - Increase time by ActiveModeThreshold since ActiveModeDuration is 0 + AdvanceClockAndRunEventLoop(ctx, icdConfigData.GetActiveModeThresholdMs() + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Expire Idle mode duration; ICDManager should remain in IdleMode since it has no message to send + AdvanceClockAndRunEventLoop(ctx, SecondsToMilliseconds(icdConfigData.GetIdleModeDurationSec()) + 1); + NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); + + // Reset Old durations + icdConfigData.SetModeDurations(oldActiveModeDuration_ms, icdConfigData.GetIdleModeDurationSec()); + } + static void TestKeepActivemodeRequests(nlTestSuite * aSuite, void * aContext) { TestContext * ctx = static_cast(aContext); @@ -170,7 +358,7 @@ class TestICDManager // Setting a requirement will transition the ICD to active mode. notifier.NotifyActiveRequestNotification(ActiveFlag::kCommissioningWindowOpen); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - // Advance time so active mode interval expires. + // Advance time so active mode duration expires. AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); // Requirement flag still set. We stay in active mode NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -183,13 +371,13 @@ class TestICDManager // Requirement will transition us to active mode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - // Advance time, but by less than the active mode interval and remove the requirement. + // Advance time, but by less than the active mode duration and remove the requirement. // We should stay in active mode. AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() / 2); notifier.NotifyActiveRequestWithdrawal(ActiveFlag::kFailSafeArmed); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - // Advance time again, The activemode interval is completed. + // Advance time again, The activemode duration is completed. AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::IdleMode); @@ -197,7 +385,7 @@ class TestICDManager notifier.NotifyActiveRequestNotification(ActiveFlag::kFailSafeArmed); notifier.NotifyActiveRequestNotification(ActiveFlag::kExchangeContextOpen); NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); - // advance time so the active mode interval expires. + // advance time so the active mode duration expires. AdvanceClockAndRunEventLoop(ctx, ICDConfigurationData::GetInstance().GetActiveModeDurationMs() + 1); // A requirement flag is still set. We stay in active mode. NL_TEST_ASSERT(aSuite, ctx->mICDManager.mOperationalState == ICDManager::OperationalState::ActiveMode); @@ -352,6 +540,10 @@ namespace { static const nlTest sTests[] = { NL_TEST_DEF("TestICDModeDurations", TestICDManager::TestICDModeDurations), NL_TEST_DEF("TestOnSubscriptionReport", TestICDManager::TestOnSubscriptionReport), + NL_TEST_DEF("TestICDModeDurationsWith0ActiveModeDurationWithoutActiveSub", + TestICDManager::TestICDModeDurationsWith0ActiveModeDurationWithoutActiveSub), + NL_TEST_DEF("TestICDModeDurationsWith0ActiveModeDurationWithActiveSub", + TestICDManager::TestICDModeDurationsWith0ActiveModeDurationWithActiveSub), NL_TEST_DEF("TestKeepActivemodeRequests", TestICDManager::TestKeepActivemodeRequests), NL_TEST_DEF("TestICDMRegisterUnregisterEvents", TestICDManager::TestICDMRegisterUnregisterEvents), NL_TEST_DEF("TestICDCounter", TestICDManager::TestICDCounter), diff --git a/src/controller/python/ChipDeviceController-Discovery.cpp b/src/controller/python/ChipDeviceController-Discovery.cpp index a9fc93b2fbc40b..7b502140a36bb6 100644 --- a/src/controller/python/ChipDeviceController-Discovery.cpp +++ b/src/controller/python/ChipDeviceController-Discovery.cpp @@ -89,6 +89,11 @@ PyChipError pychip_DeviceController_DiscoverCommissionableNodes(Controller::Devi return ToPyChipError(devCtrl->DiscoverCommissionableNodes(filter)); } +PyChipError pychip_DeviceController_StopCommissionableDiscovery(Controller::DeviceCommissioner * devCtrl) +{ + return ToPyChipError(devCtrl->StopCommissionableDiscovery()); +} + void pychip_DeviceController_IterateDiscoveredCommissionableNodes(Controller::DeviceCommissioner * devCtrl, IterateDiscoveredCommissionableNodesFunct cb) { diff --git a/src/controller/python/chip/ChipDeviceCtrl.py b/src/controller/python/chip/ChipDeviceCtrl.py index 20e21177fe2b1d..402f2b7cea694d 100644 --- a/src/controller/python/chip/ChipDeviceCtrl.py +++ b/src/controller/python/chip/ChipDeviceCtrl.py @@ -594,6 +594,9 @@ def DiscoverCommissionableNodes(self, filterType: discovery.FilterType = discove else: time.sleep(timeoutSecond) + self._ChipStack.Call( + lambda: self._dmLib.pychip_DeviceController_StopCommissionableDiscovery(self.devCtrl)).raise_on_error() + return self.GetDiscoveredDevices() def DiscoverCommissionableNodesLongDiscriminator(self, long_discriminator): @@ -1567,6 +1570,10 @@ def _InitLib(self): c_void_p, c_uint8, c_char_p] self._dmLib.pychip_DeviceController_DiscoverCommissionableNodes.restype = PyChipError + self._dmLib.pychip_DeviceController_StopCommissionableDiscovery.argtypes = [ + c_void_p] + self._dmLib.pychip_DeviceController_StopCommissionableDiscovery.restype = PyChipError + self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator.argtypes = [ c_void_p, c_uint16] self._dmLib.pychip_DeviceController_DiscoverCommissionableNodesLongDiscriminator.restype = PyChipError diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index b203c997db8ff8..6ee7d9c9634999 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -953,6 +953,17 @@ static_assert(CHIP_DEVICE_CONFIG_BLE_EXT_ADVERTISING_INTERVAL_MIN < CHIP_DEVICE_ #ifndef CHIP_DEVICE_CONFIG_THREAD_BORDER_ROUTER #define CHIP_DEVICE_CONFIG_THREAD_BORDER_ROUTER 0 #endif + +/** + * CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK + * + * Indicate if the matter device thread stack is implemented using the ot-br-posix dbus API + * Rather than the standard openthread stack api + * + */ +#ifndef CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK +#define CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK 0 +#endif /** * CHIP_DEVICE_CONFIG_THREAD_TASK_NAME * diff --git a/src/include/platform/ConnectivityManager.h b/src/include/platform/ConnectivityManager.h index e874773886e51b..70f9d48a6bef07 100644 --- a/src/include/platform/ConnectivityManager.h +++ b/src/include/platform/ConnectivityManager.h @@ -202,7 +202,6 @@ class ConnectivityManager bool IsThreadProvisioned(); void ErasePersistentInfo(); void ResetThreadNetworkDiagnosticsCounts(); - CHIP_ERROR WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); CHIP_ERROR SetPollingInterval(System::Clock::Milliseconds32 pollingInterval); @@ -477,25 +476,6 @@ inline void ConnectivityManager::ResetThreadNetworkDiagnosticsCounts() static_cast(this)->_ResetThreadNetworkDiagnosticsCounts(); } -/* - * @brief Get runtime value from the thread network based on the given attribute ID. - * The info is encoded via the AttributeValueEncoder. - * - * @param attributeId Id of the attribute for the requested info. - * @param aEncoder Encoder to encode the attribute value. - * - * @return CHIP_NO_ERROR = Succes. - * CHIP_ERROR_NOT_IMPLEMENTED = Runtime value for this attribute to yet available to send as reply - * Use standard read. - * CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE = Is not a Runtime readable attribute. Use standard read - * All other errors should be treated as a read error and reported as such. - */ -inline CHIP_ERROR ConnectivityManager::WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - return static_cast(this)->_WriteThreadNetworkDiagnosticAttributeToTlv(attributeId, encoder); -} - inline Ble::BleLayer * ConnectivityManager::GetBleLayer() { return static_cast(this)->_GetBleLayer(); diff --git a/src/include/platform/ThreadStackManager.h b/src/include/platform/ThreadStackManager.h index b6c9a7e38dd7d5..86d895ec1cfe52 100644 --- a/src/include/platform/ThreadStackManager.h +++ b/src/include/platform/ThreadStackManager.h @@ -132,7 +132,6 @@ class ThreadStackManager #endif // CHIP_DEVICE_CONFIG_ENABLE_THREAD_SRP_CLIENT void ResetThreadNetworkDiagnosticsCounts(void); - CHIP_ERROR WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); private: // ===== Members for internal use by the following friends. @@ -425,24 +424,5 @@ inline void ThreadStackManager::ResetThreadNetworkDiagnosticsCounts() static_cast(this)->_ResetThreadNetworkDiagnosticsCounts(); } -/* - * @brief Get runtime value from the thread network based on the given attribute ID. - * The info is encoded via the AttributeValueEncoder. - * - * @param attributeId Id of the attribute for the requested info. - * @param aEncoder Encoder to encode the attribute value. - * - * @return CHIP_NO_ERROR = Succes. - * CHIP_ERROR_NOT_IMPLEMENTED = Runtime value for this attribute to yet available to send as reply - * Use standard read. - * CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE = Is not a Runtime readable attribute. Use standard read - * All other errors should be treated as a read error and reported as such. - */ -inline CHIP_ERROR ThreadStackManager::WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - return static_cast(this)->_WriteThreadNetworkDiagnosticAttributeToTlv(attributeId, encoder); -} - } // namespace DeviceLayer } // namespace chip diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl_NoThread.h b/src/include/platform/internal/GenericConnectivityManagerImpl_NoThread.h index e7af04965182fa..c84f2160a1457b 100755 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_NoThread.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_NoThread.h @@ -54,8 +54,6 @@ class GenericConnectivityManagerImpl_NoThread bool _IsThreadProvisioned(void); void _ErasePersistentInfo(void); void _ResetThreadNetworkDiagnosticsCounts(void); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); - ImplClass * Impl() { return static_cast(this); } }; @@ -116,100 +114,6 @@ template inline void GenericConnectivityManagerImpl_NoThread::_ResetThreadNetworkDiagnosticsCounts() {} -template -inline CHIP_ERROR GenericConnectivityManagerImpl_NoThread::_WriteThreadNetworkDiagnosticAttributeToTlv( - AttributeId attributeId, app::AttributeValueEncoder & encoder) -{ - // If we get here the Thread Network Diagnostic cluster is enabled on the device but doesn't run thread. - // Encode Null or default values for all attributes of the cluster. - CHIP_ERROR err = CHIP_NO_ERROR; - switch (attributeId) - { - // Encode EmptyList - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RouteTable::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::NeighborTable::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ActiveNetworkFaultsList::Id: - err = encoder.EncodeEmptyList(); - break; - // Encode Null - case app::Clusters::ThreadNetworkDiagnostics::Attributes::Channel::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RoutingRole::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::NetworkName::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::PanId::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::PartitionId::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::Weighting::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::DataVersion::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::Delay::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id: - err = encoder.EncodeNull(); - break; - // Encode UINT64_T 0 - case app::Clusters::ThreadNetworkDiagnostics::Attributes::OverrunCount::Id: - err = encoder.Encode(static_cast(0)); - break; - // Encode UINT16_T 0 - case app::Clusters::ThreadNetworkDiagnostics::Attributes::DetachedRoleCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RouterRoleCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::LeaderRoleCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::AttachAttemptCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::PartitionIdChangeCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::BetterPartitionAttachAttemptCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::ParentChangeCount::Id: - err = encoder.Encode(static_cast(0)); - break; - // Encode UINT32_T 0 - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxTotalCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxUnicastCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxBroadcastCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxAckedCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxAckRequestedCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxNoAckRequestedCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxDataCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxDataPollCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxBeaconCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxBeaconRequestCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxOtherCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxRetryCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxDirectMaxRetryExpiryCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxIndirectMaxRetryExpiryCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxErrCcaCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxErrAbortCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::TxErrBusyChannelCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxTotalCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxUnicastCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxBroadcastCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxDataCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxDataPollCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxBeaconCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxBeaconRequestCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxOtherCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxAddressFilteredCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxDestAddrFilteredCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxDuplicatedCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrNoFrameCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrUnknownNeighborCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrInvalidSrcAddrCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrSecCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrFcsCount::Id: - case app::Clusters::ThreadNetworkDiagnostics::Attributes::RxErrOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - default: - err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; - break; - } - - return err; -} } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/include/platform/internal/GenericConnectivityManagerImpl_Thread.h b/src/include/platform/internal/GenericConnectivityManagerImpl_Thread.h index a1d24c2e1c80d4..456d843c488224 100755 --- a/src/include/platform/internal/GenericConnectivityManagerImpl_Thread.h +++ b/src/include/platform/internal/GenericConnectivityManagerImpl_Thread.h @@ -70,7 +70,6 @@ class GenericConnectivityManagerImpl_Thread bool _IsThreadProvisioned(); void _ErasePersistentInfo(); void _ResetThreadNetworkDiagnosticsCounts(); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); // ===== Members for use by the implementation subclass. @@ -154,14 +153,6 @@ inline void GenericConnectivityManagerImpl_Thread::_ResetThreadNetwor ThreadStackMgrImpl().ResetThreadNetworkDiagnosticsCounts(); } -template -inline CHIP_ERROR -GenericConnectivityManagerImpl_Thread::_WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - return ThreadStackMgrImpl().WriteThreadNetworkDiagnosticAttributeToTlv(attributeId, encoder); -} - } // namespace Internal } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/BUILD.gn b/src/platform/BUILD.gn index c81a268849fa1e..f8dcd3b9d5f1e6 100644 --- a/src/platform/BUILD.gn +++ b/src/platform/BUILD.gn @@ -111,11 +111,20 @@ if (chip_device_platform != "none" && chip_device_platform != "external") { chip_enable_wifi && chip_device_platform != "darwin" chip_stack_lock_tracking_log = chip_stack_lock_tracking != "none" chip_stack_lock_tracking_fatal = chip_stack_lock_tracking == "fatal" + + # This is used to identify which platforms implement their ThreadStackManager + # with the otbr posix dbus api. + chip_device_uses_otbr_posix_dbus = + chip_enable_openthread && + (chip_device_platform == "linux" || chip_device_platform == "tizen" || + chip_device_platform == "webos") + defines = [ "CHIP_DEVICE_CONFIG_ENABLE_WPA=${chip_device_config_enable_wpa}", "CHIP_ENABLE_OPENTHREAD=${chip_enable_openthread}", "CHIP_DEVICE_CONFIG_THREAD_FTD=${chip_device_config_thread_ftd}", "CHIP_DEVICE_CONFIG_THREAD_BORDER_ROUTER=${chip_openthread_border_router}", + "CHIP_DEVICE_CONFIG_USES_OTBR_POSIX_DBUS_STACK=${chip_device_uses_otbr_posix_dbus}", "CHIP_STACK_LOCK_TRACKING_ENABLED=${chip_stack_lock_tracking_log}", "CHIP_STACK_LOCK_TRACKING_ERROR_FATAL=${chip_stack_lock_tracking_fatal}", "CHIP_ENABLE_ADDITIONAL_DATA_ADVERTISING=${chip_enable_additional_data_advertising}", diff --git a/src/platform/Linux/DnssdImpl.cpp b/src/platform/Linux/DnssdImpl.cpp index 5f46dd24d8728f..2a1873072fbb9e 100644 --- a/src/platform/Linux/DnssdImpl.cpp +++ b/src/platform/Linux/DnssdImpl.cpp @@ -893,7 +893,7 @@ void MdnsAvahi::HandleResolve(AvahiServiceResolver * resolver, AvahiIfIndex inte avahi_service_resolver_free(resolver); context->mResolver = avahi_service_resolver_new( context->mInstance->mClient, context->mInterface, context->mTransport, context->mName, context->mFullType.c_str(), - nullptr, context->mAddressType, static_cast(0), HandleResolve, context); + nullptr, context->mAddressType, static_cast(0), HandleResolve, userdata); if (context->mResolver == nullptr) { ChipLogError(DeviceLayer, "Avahi resolve failed on retry"); diff --git a/src/platform/Linux/ThreadStackManagerImpl.cpp b/src/platform/Linux/ThreadStackManagerImpl.cpp index 1eb5958bef17af..20bfe905144b8f 100644 --- a/src/platform/Linux/ThreadStackManagerImpl.cpp +++ b/src/platform/Linux/ThreadStackManagerImpl.cpp @@ -715,174 +715,6 @@ void ThreadStackManagerImpl::_OnNetworkScanFinished(GAsyncResult * res) void ThreadStackManagerImpl::_ResetThreadNetworkDiagnosticsCounts() {} -CHIP_ERROR ThreadStackManagerImpl::_WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - switch (attributeId) - { - case ThreadNetworkDiagnostics::Attributes::NeighborTable::Id: - case ThreadNetworkDiagnostics::Attributes::RouteTable::Id: - case ThreadNetworkDiagnostics::Attributes::ActiveNetworkFaultsList::Id: - err = encoder.EncodeEmptyList(); - break; - case ThreadNetworkDiagnostics::Attributes::Channel::Id: - case ThreadNetworkDiagnostics::Attributes::RoutingRole::Id: - case ThreadNetworkDiagnostics::Attributes::NetworkName::Id: - case ThreadNetworkDiagnostics::Attributes::PanId::Id: - case ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id: - case ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id: - case ThreadNetworkDiagnostics::Attributes::PartitionId::Id: - case ThreadNetworkDiagnostics::Attributes::Weighting::Id: - case ThreadNetworkDiagnostics::Attributes::DataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id: - case ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::Delay::Id: - case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: - case ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id: - case ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id: - err = encoder.EncodeNull(); - break; - case ThreadNetworkDiagnostics::Attributes::OverrunCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::DetachedRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RouterRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::LeaderRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::AttachAttemptCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::PartitionIdChangeCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::BetterPartitionAttachAttemptCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::ParentChangeCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxTotalCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxUnicastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBroadcastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxAckRequestedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxAckedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxNoAckRequestedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDataCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDataPollCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBeaconCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBeaconRequestCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxRetryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDirectMaxRetryExpiryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxIndirectMaxRetryExpiryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrCcaCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrAbortCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrBusyChannelCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxTotalCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxUnicastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBroadcastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDataCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDataPollCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBeaconCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBeaconRequestCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxAddressFilteredCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDestAddrFilteredCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDuplicatedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrNoFrameCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrUnknownNeighborCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrInvalidSrcAddrCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrSecCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrFcsCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - default: - err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; - break; - } - - return err; -} - CHIP_ERROR ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback) diff --git a/src/platform/Linux/ThreadStackManagerImpl.h b/src/platform/Linux/ThreadStackManagerImpl.h index 5e077cba3bd1fe..977c6b94d0027f 100755 --- a/src/platform/Linux/ThreadStackManagerImpl.h +++ b/src/platform/Linux/ThreadStackManagerImpl.h @@ -115,8 +115,6 @@ class ThreadStackManagerImpl : public ThreadStackManager void _ResetThreadNetworkDiagnosticsCounts(); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); - CHIP_ERROR _StartThreadScan(NetworkCommissioning::ThreadDriver::ScanCallback * callback); ~ThreadStackManagerImpl() = default; diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h index ccc3f65e3f6cad..161c2b202a8310 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.h @@ -37,7 +37,6 @@ #include #endif -#include #include #include #include @@ -111,7 +110,6 @@ class GenericThreadStackManagerImpl_OpenThread CHIP_ERROR _GetPrimary802154MACAddress(uint8_t * buf); CHIP_ERROR _GetExternalIPv6Address(chip::Inet::IPAddress & addr); void _ResetThreadNetworkDiagnosticsCounts(void); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); CHIP_ERROR _GetPollPeriod(uint32_t & buf); void _OnWoBLEAdvertisingStart(void); void _OnWoBLEAdvertisingStop(void); diff --git a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp index c1fd8635d33eb0..acc0c78d0c8eb7 100644 --- a/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp +++ b/src/platform/OpenThread/GenericThreadStackManagerImpl_OpenThread.hpp @@ -45,7 +45,6 @@ #include #endif -#include #include #include #include @@ -59,11 +58,6 @@ #include #include -#include -#include -#include -#include - #include extern "C" void otSysProcessDrivers(otInstance * aInstance); @@ -1036,652 +1030,6 @@ void GenericThreadStackManagerImpl_OpenThread::_ResetThreadNetworkDia // Based on the spec, only OverrunCount should be resetted. mOverrunCount = 0; } -/* - * @brief Get runtime value from the thread network based on the given attribute ID. - * The info is encoded via the AttributeValueEncoder. - * - * @param attributeId Id of the attribute for the requested info. - * @param aEncoder Encoder to encode the attribute value. - * - * @return CHIP_NO_ERROR = Succes. - * CHIP_ERROR_NOT_IMPLEMENTED = Runtime value for this attribute to yet available to send as reply - * Use standard read. - * CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE = Is not a Runtime readable attribute. Use standard read - * All other errors should be treated as a read error and reported as such. - */ -template -CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_WriteThreadNetworkDiagnosticAttributeToTlv( - AttributeId attributeId, app::AttributeValueEncoder & encoder) -{ - CHIP_ERROR err; - - namespace ThreadNetworkDiagnostics = app::Clusters::ThreadNetworkDiagnostics; - - if (!otDatasetIsCommissioned(mOTInst)) - { - // For the following nullable attributes of the cluster, encodeNull since - // thread instance cannot provide the related data when it is not currently configured. - // - // Note that RoutingRole is nullable but not listed here as thread provides - // valid data even when disabled or detached - switch (attributeId) - { - case ThreadNetworkDiagnostics::Attributes::Channel::Id: - case ThreadNetworkDiagnostics::Attributes::NetworkName::Id: - case ThreadNetworkDiagnostics::Attributes::PanId::Id: - case ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id: - case ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id: - case ThreadNetworkDiagnostics::Attributes::PartitionId::Id: - case ThreadNetworkDiagnostics::Attributes::Weighting::Id: - case ThreadNetworkDiagnostics::Attributes::DataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id: - case ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::Delay::Id: - case ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id: - case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: - case ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id: - return encoder.EncodeNull(); - } - } - - switch (attributeId) - { - case ThreadNetworkDiagnostics::Attributes::Channel::Id: { - uint16_t channel = otLinkGetChannel(mOTInst); - err = encoder.Encode(channel); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RoutingRole::Id: { - using ThreadNetworkDiagnostics::RoutingRoleEnum; - RoutingRoleEnum routingRole; - otDeviceRole otRole = otThreadGetDeviceRole(mOTInst); - - if (otRole == OT_DEVICE_ROLE_DISABLED) - { - routingRole = RoutingRoleEnum::kUnspecified; - } - else if (otRole == OT_DEVICE_ROLE_DETACHED) - { - routingRole = RoutingRoleEnum::kUnassigned; - } - else if (otRole == OT_DEVICE_ROLE_ROUTER) - { - routingRole = RoutingRoleEnum::kRouter; - } - else if (otRole == OT_DEVICE_ROLE_LEADER) - { - routingRole = RoutingRoleEnum::kLeader; - } - else if (otRole == OT_DEVICE_ROLE_CHILD) - { - otLinkModeConfig linkMode = otThreadGetLinkMode(mOTInst); - - if (linkMode.mRxOnWhenIdle) - { - routingRole = RoutingRoleEnum::kEndDevice; -#if CHIP_DEVICE_CONFIG_THREAD_FTD - if (otThreadIsRouterEligible(mOTInst)) - { - routingRole = RoutingRoleEnum::kReed; - } -#endif - } - else - { - routingRole = RoutingRoleEnum::kSleepyEndDevice; - } - } - - err = encoder.Encode(routingRole); - } - break; - - case ThreadNetworkDiagnostics::Attributes::NetworkName::Id: { - const char * networkName = otThreadGetNetworkName(mOTInst); - err = encoder.Encode(CharSpan::fromCharString(networkName)); - } - break; - - case ThreadNetworkDiagnostics::Attributes::PanId::Id: { - uint16_t panId = otLinkGetPanId(mOTInst); - err = encoder.Encode(panId); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id: { - const otExtendedPanId * pExtendedPanid = otThreadGetExtendedPanId(mOTInst); - err = encoder.Encode(Encoding::BigEndian::Get64(pExtendedPanid->m8)); - } - break; - - case ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id: { - uint8_t meshLocaPrefix[OT_MESH_LOCAL_PREFIX_SIZE + 1] = { 0 }; // + 1 to encode prefix Len in the octstr - - const otMeshLocalPrefix * pMeshLocalPrefix = otThreadGetMeshLocalPrefix(mOTInst); - meshLocaPrefix[0] = OT_IP6_PREFIX_BITSIZE; - - memcpy(&meshLocaPrefix[1], pMeshLocalPrefix->m8, OT_MESH_LOCAL_PREFIX_SIZE); - err = encoder.Encode(ByteSpan(meshLocaPrefix)); - } - break; - - case ThreadNetworkDiagnostics::Attributes::OverrunCount::Id: { - uint64_t overrunCount = mOverrunCount; - err = encoder.Encode(overrunCount); - } - break; - - case ThreadNetworkDiagnostics::Attributes::NeighborTable::Id: { - err = encoder.EncodeList([this](const auto & aEncoder) -> CHIP_ERROR { - constexpr uint16_t kFrameErrorRate100Percent = 0xffff; - constexpr uint16_t kMessageErrorRate100Percent = 0xffff; - - otNeighborInfo neighInfo; - otNeighborInfoIterator iterator = OT_NEIGHBOR_INFO_ITERATOR_INIT; - - while (otThreadGetNextNeighborInfo(mOTInst, &iterator, &neighInfo) == OT_ERROR_NONE) - { - ThreadNetworkDiagnostics::Structs::NeighborTableStruct::Type neighborTable; - app::DataModel::Nullable averageRssi; - app::DataModel::Nullable lastRssi; - - if (neighInfo.mAverageRssi == OT_RADIO_RSSI_INVALID) - { - averageRssi.SetNull(); - } - else - { - // Thread average calculation already restrict mAverageRssi to be between -128 and 0 - averageRssi.SetNonNull(neighInfo.mAverageRssi); - } - - if (neighInfo.mLastRssi == OT_RADIO_RSSI_INVALID) - { - lastRssi.SetNull(); - } - else - { - lastRssi.SetNonNull(min(static_cast(0), neighInfo.mLastRssi)); - } - - neighborTable.averageRssi = averageRssi; - neighborTable.lastRssi = lastRssi; - neighborTable.extAddress = Encoding::BigEndian::Get64(neighInfo.mExtAddress.m8); - neighborTable.age = neighInfo.mAge; - neighborTable.rloc16 = neighInfo.mRloc16; - neighborTable.linkFrameCounter = neighInfo.mLinkFrameCounter; - neighborTable.mleFrameCounter = neighInfo.mMleFrameCounter; - neighborTable.lqi = neighInfo.mLinkQualityIn; - neighborTable.frameErrorRate = - static_cast((static_cast(neighInfo.mFrameErrorRate) * 100) / kFrameErrorRate100Percent); - neighborTable.messageErrorRate = - static_cast((static_cast(neighInfo.mMessageErrorRate) * 100) / kMessageErrorRate100Percent); - neighborTable.rxOnWhenIdle = neighInfo.mRxOnWhenIdle; - neighborTable.fullThreadDevice = neighInfo.mFullThreadDevice; - neighborTable.fullNetworkData = neighInfo.mFullNetworkData; - neighborTable.isChild = neighInfo.mIsChild; - - ReturnErrorOnFailure(aEncoder.Encode(neighborTable)); - } - - return CHIP_NO_ERROR; - }); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RouteTable::Id: { - err = encoder.EncodeList([this](const auto & aEncoder) -> CHIP_ERROR { - otRouterInfo routerInfo; - -#if CHIP_DEVICE_CONFIG_THREAD_FTD - uint8_t maxRouterId = otThreadGetMaxRouterId(mOTInst); - CHIP_ERROR chipErr = CHIP_ERROR_INCORRECT_STATE; - - for (uint8_t i = 0; i <= maxRouterId; i++) - { - if (otThreadGetRouterInfo(mOTInst, i, &routerInfo) == OT_ERROR_NONE) - { - ThreadNetworkDiagnostics::Structs::RouteTableStruct::Type routeTable; - - routeTable.extAddress = Encoding::BigEndian::Get64(routerInfo.mExtAddress.m8); - routeTable.rloc16 = routerInfo.mRloc16; - routeTable.routerId = routerInfo.mRouterId; - routeTable.nextHop = routerInfo.mNextHop; - routeTable.pathCost = routerInfo.mPathCost; - routeTable.LQIIn = routerInfo.mLinkQualityIn; - routeTable.LQIOut = routerInfo.mLinkQualityOut; - routeTable.age = routerInfo.mAge; - routeTable.allocated = routerInfo.mAllocated; - routeTable.linkEstablished = routerInfo.mLinkEstablished; - - ReturnErrorOnFailure(aEncoder.Encode(routeTable)); - chipErr = CHIP_NO_ERROR; - } - } - - return chipErr; - -#else // OPENTHREAD_MTD - otError otErr = otThreadGetParentInfo(mOTInst, &routerInfo); - ReturnErrorOnFailure(MapOpenThreadError(otErr)); - - ThreadNetworkDiagnostics::Structs::RouteTableStruct::Type routeTable; - - routeTable.extAddress = Encoding::BigEndian::Get64(routerInfo.mExtAddress.m8); - routeTable.rloc16 = routerInfo.mRloc16; - routeTable.routerId = routerInfo.mRouterId; - routeTable.nextHop = routerInfo.mNextHop; - routeTable.pathCost = routerInfo.mPathCost; - routeTable.LQIIn = routerInfo.mLinkQualityIn; - routeTable.LQIOut = routerInfo.mLinkQualityOut; - routeTable.age = routerInfo.mAge; - routeTable.allocated = routerInfo.mAllocated; - routeTable.linkEstablished = routerInfo.mLinkEstablished; - - ReturnErrorOnFailure(aEncoder.Encode(routeTable)); - return CHIP_NO_ERROR; -#endif - }); - } - break; - - case ThreadNetworkDiagnostics::Attributes::PartitionId::Id: { - uint32_t partitionId = otThreadGetPartitionId(mOTInst); - err = encoder.Encode(partitionId); - } - break; - - case ThreadNetworkDiagnostics::Attributes::Weighting::Id: { - uint8_t weight = otThreadGetLeaderWeight(mOTInst); - err = encoder.Encode(weight); - } - break; - - case ThreadNetworkDiagnostics::Attributes::DataVersion::Id: { - uint8_t dataVersion = otNetDataGetVersion(mOTInst); - err = encoder.Encode(dataVersion); - } - break; - - case ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id: { - uint8_t stableVersion = otNetDataGetStableVersion(mOTInst); - err = encoder.Encode(stableVersion); - } - break; - - case ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id: { - uint8_t leaderRouterId = otThreadGetLeaderRouterId(mOTInst); - err = encoder.Encode(leaderRouterId); - } - break; - - case ThreadNetworkDiagnostics::Attributes::DetachedRoleCount::Id: { - uint16_t detachedRole = otThreadGetMleCounters(mOTInst)->mDetachedRole; - err = encoder.Encode(detachedRole); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id: { - uint16_t childRole = otThreadGetMleCounters(mOTInst)->mChildRole; - err = encoder.Encode(childRole); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RouterRoleCount::Id: { - uint16_t routerRole = otThreadGetMleCounters(mOTInst)->mRouterRole; - err = encoder.Encode(routerRole); - } - break; - - case ThreadNetworkDiagnostics::Attributes::LeaderRoleCount::Id: { - uint16_t leaderRole = otThreadGetMleCounters(mOTInst)->mLeaderRole; - err = encoder.Encode(leaderRole); - } - break; - - case ThreadNetworkDiagnostics::Attributes::AttachAttemptCount::Id: { - uint16_t attachAttempts = otThreadGetMleCounters(mOTInst)->mAttachAttempts; - err = encoder.Encode(attachAttempts); - } - break; - - case ThreadNetworkDiagnostics::Attributes::PartitionIdChangeCount::Id: { - uint16_t partitionIdChanges = otThreadGetMleCounters(mOTInst)->mPartitionIdChanges; - err = encoder.Encode(partitionIdChanges); - } - break; - - case ThreadNetworkDiagnostics::Attributes::BetterPartitionAttachAttemptCount::Id: { - uint16_t betterPartitionAttachAttempts = otThreadGetMleCounters(mOTInst)->mBetterPartitionAttachAttempts; - err = encoder.Encode(betterPartitionAttachAttempts); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ParentChangeCount::Id: { - uint16_t parentChanges = otThreadGetMleCounters(mOTInst)->mParentChanges; - err = encoder.Encode(parentChanges); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxTotalCount::Id: { - uint32_t txTotal = otLinkGetCounters(mOTInst)->mTxTotal; - err = encoder.Encode(txTotal); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxUnicastCount::Id: { - uint32_t txUnicast = otLinkGetCounters(mOTInst)->mTxUnicast; - err = encoder.Encode(txUnicast); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxBroadcastCount::Id: { - uint32_t txBroadcast = otLinkGetCounters(mOTInst)->mTxBroadcast; - err = encoder.Encode(txBroadcast); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxAckRequestedCount::Id: { - uint32_t txAckRequested = otLinkGetCounters(mOTInst)->mTxAckRequested; - err = encoder.Encode(txAckRequested); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxAckedCount::Id: { - uint32_t txAcked = otLinkGetCounters(mOTInst)->mTxAcked; - err = encoder.Encode(txAcked); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxNoAckRequestedCount::Id: { - uint32_t txNoAckRequested = otLinkGetCounters(mOTInst)->mTxNoAckRequested; - err = encoder.Encode(txNoAckRequested); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxDataCount::Id: { - uint32_t txData = otLinkGetCounters(mOTInst)->mTxData; - err = encoder.Encode(txData); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxDataPollCount::Id: { - uint32_t txDataPoll = otLinkGetCounters(mOTInst)->mTxDataPoll; - err = encoder.Encode(txDataPoll); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxBeaconCount::Id: { - uint32_t txBeacon = otLinkGetCounters(mOTInst)->mTxBeacon; - err = encoder.Encode(txBeacon); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxBeaconRequestCount::Id: { - uint32_t txBeaconRequest = otLinkGetCounters(mOTInst)->mTxBeaconRequest; - err = encoder.Encode(txBeaconRequest); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxOtherCount::Id: { - uint32_t txOther = otLinkGetCounters(mOTInst)->mTxOther; - err = encoder.Encode(txOther); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxRetryCount::Id: { - uint32_t txRetry = otLinkGetCounters(mOTInst)->mTxRetry; - err = encoder.Encode(txRetry); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxDirectMaxRetryExpiryCount::Id: { - uint32_t txDirectMaxRetryExpiry = otLinkGetCounters(mOTInst)->mTxDirectMaxRetryExpiry; - err = encoder.Encode(txDirectMaxRetryExpiry); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxIndirectMaxRetryExpiryCount::Id: { - uint32_t txIndirectMaxRetryExpiry = otLinkGetCounters(mOTInst)->mTxIndirectMaxRetryExpiry; - err = encoder.Encode(txIndirectMaxRetryExpiry); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxErrCcaCount::Id: { - uint32_t txErrCca = otLinkGetCounters(mOTInst)->mTxErrCca; - err = encoder.Encode(txErrCca); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxErrAbortCount::Id: { - uint32_t TxErrAbort = otLinkGetCounters(mOTInst)->mTxErrAbort; - err = encoder.Encode(TxErrAbort); - } - break; - - case ThreadNetworkDiagnostics::Attributes::TxErrBusyChannelCount::Id: { - uint32_t TxErrBusyChannel = otLinkGetCounters(mOTInst)->mTxErrBusyChannel; - err = encoder.Encode(TxErrBusyChannel); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxTotalCount::Id: { - uint32_t rxTotal = otLinkGetCounters(mOTInst)->mRxTotal; - err = encoder.Encode(rxTotal); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxUnicastCount::Id: { - uint32_t rxUnicast = otLinkGetCounters(mOTInst)->mRxUnicast; - err = encoder.Encode(rxUnicast); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxBroadcastCount::Id: { - uint32_t rxBroadcast = otLinkGetCounters(mOTInst)->mRxBroadcast; - err = encoder.Encode(rxBroadcast); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxDataCount::Id: { - uint32_t rxData = otLinkGetCounters(mOTInst)->mRxData; - err = encoder.Encode(rxData); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxDataPollCount::Id: { - uint32_t rxDataPoll = otLinkGetCounters(mOTInst)->mRxDataPoll; - err = encoder.Encode(rxDataPoll); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxBeaconCount::Id: { - uint32_t rxBeacon = otLinkGetCounters(mOTInst)->mRxBeacon; - err = encoder.Encode(rxBeacon); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxBeaconRequestCount::Id: { - uint32_t rxBeaconRequest = otLinkGetCounters(mOTInst)->mRxBeaconRequest; - err = encoder.Encode(rxBeaconRequest); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxOtherCount::Id: { - uint32_t rxOther = otLinkGetCounters(mOTInst)->mRxOther; - err = encoder.Encode(rxOther); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxAddressFilteredCount::Id: { - uint32_t rxAddressFiltered = otLinkGetCounters(mOTInst)->mRxAddressFiltered; - err = encoder.Encode(rxAddressFiltered); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxDestAddrFilteredCount::Id: { - uint32_t rxDestAddrFiltered = otLinkGetCounters(mOTInst)->mRxDestAddrFiltered; - err = encoder.Encode(rxDestAddrFiltered); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxDuplicatedCount::Id: { - uint32_t rxDuplicated = otLinkGetCounters(mOTInst)->mRxDuplicated; - err = encoder.Encode(rxDuplicated); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrNoFrameCount::Id: { - uint32_t rxErrNoFrame = otLinkGetCounters(mOTInst)->mRxErrNoFrame; - err = encoder.Encode(rxErrNoFrame); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrUnknownNeighborCount::Id: { - uint32_t rxErrUnknownNeighbor = otLinkGetCounters(mOTInst)->mRxErrUnknownNeighbor; - err = encoder.Encode(rxErrUnknownNeighbor); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrInvalidSrcAddrCount::Id: { - uint32_t rxErrInvalidSrcAddr = otLinkGetCounters(mOTInst)->mRxErrInvalidSrcAddr; - err = encoder.Encode(rxErrInvalidSrcAddr); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrSecCount::Id: { - uint32_t rxErrSec = otLinkGetCounters(mOTInst)->mRxErrSec; - err = encoder.Encode(rxErrSec); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrFcsCount::Id: { - uint32_t rxErrFcs = otLinkGetCounters(mOTInst)->mRxErrFcs; - err = encoder.Encode(rxErrFcs); - } - break; - - case ThreadNetworkDiagnostics::Attributes::RxErrOtherCount::Id: { - uint32_t rxErrOther = otLinkGetCounters(mOTInst)->mRxErrOther; - err = encoder.Encode(rxErrOther); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - uint64_t activeTimestamp = (activeDataset.mActiveTimestamp.mSeconds << 16) | (activeDataset.mActiveTimestamp.mTicks << 1) | - activeDataset.mActiveTimestamp.mAuthoritative; - err = encoder.Encode(activeTimestamp); - } - break; - - case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - uint64_t pendingTimestamp = (activeDataset.mPendingTimestamp.mSeconds << 16) | - (activeDataset.mPendingTimestamp.mTicks << 1) | activeDataset.mPendingTimestamp.mAuthoritative; - err = encoder.Encode(pendingTimestamp); - } - break; - - case ThreadNetworkDiagnostics::Attributes::Delay::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - uint32_t delay = activeDataset.mDelay; - err = encoder.Encode(delay); - } - break; - - case ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - - ThreadNetworkDiagnostics::Structs::SecurityPolicy::Type securityPolicy; - static_assert(sizeof(securityPolicy) == sizeof(activeDataset.mSecurityPolicy), - "securityPolicy Struct do not match otSecurityPolicy"); - uint16_t policyAsInts[2]; - static_assert(sizeof(policyAsInts) == sizeof(activeDataset.mSecurityPolicy), - "We're missing some members of otSecurityPolicy?"); - memcpy(&policyAsInts, &activeDataset.mSecurityPolicy, sizeof(policyAsInts)); - securityPolicy.rotationTime = policyAsInts[0]; - securityPolicy.flags = policyAsInts[1]; - err = encoder.Encode(securityPolicy); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - - // In the resultant Octet string, the most significant bit of the left-most byte indicates channel 0 - // We have to bitswap the entire uint32_t before converting to octet string - uint32_t bitSwappedChannelMask = 0; - for (int i = 0, j = 31; i < 32; i++, j--) - { - bitSwappedChannelMask |= ((activeDataset.mChannelMask >> j) & 1) << i; - } - - uint8_t buffer[sizeof(uint32_t)] = { 0 }; - Encoding::BigEndian::Put32(buffer, bitSwappedChannelMask); - err = encoder.Encode(ByteSpan(buffer)); - } - break; - - case ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id: { - otOperationalDataset activeDataset; - otError otErr = otDatasetGetActive(mOTInst, &activeDataset); - VerifyOrReturnError(otErr == OT_ERROR_NONE, MapOpenThreadError(otErr)); - ThreadNetworkDiagnostics::Structs::OperationalDatasetComponents::Type OpDatasetComponents; - - OpDatasetComponents.activeTimestampPresent = activeDataset.mComponents.mIsActiveTimestampPresent; - OpDatasetComponents.pendingTimestampPresent = activeDataset.mComponents.mIsPendingTimestampPresent; - OpDatasetComponents.masterKeyPresent = activeDataset.mComponents.mIsNetworkKeyPresent; - OpDatasetComponents.networkNamePresent = activeDataset.mComponents.mIsNetworkNamePresent; - OpDatasetComponents.extendedPanIdPresent = activeDataset.mComponents.mIsExtendedPanIdPresent; - OpDatasetComponents.meshLocalPrefixPresent = activeDataset.mComponents.mIsMeshLocalPrefixPresent; - OpDatasetComponents.delayPresent = activeDataset.mComponents.mIsDelayPresent; - OpDatasetComponents.panIdPresent = activeDataset.mComponents.mIsPanIdPresent; - OpDatasetComponents.channelPresent = activeDataset.mComponents.mIsChannelPresent; - OpDatasetComponents.pskcPresent = activeDataset.mComponents.mIsPskcPresent; - OpDatasetComponents.securityPolicyPresent = activeDataset.mComponents.mIsSecurityPolicyPresent; - OpDatasetComponents.channelMaskPresent = activeDataset.mComponents.mIsChannelMaskPresent; - - err = encoder.Encode(OpDatasetComponents); - } - break; - - case ThreadNetworkDiagnostics::Attributes::ActiveNetworkFaultsList::Id: { - err = encoder.EncodeList([](const auto & aEncoder) -> CHIP_ERROR { - // TODO activeNetworkFaultsList isn't tracked. Encode the list of 4 entries at 0 none the less - ThreadNetworkDiagnostics::NetworkFaultEnum activeNetworkFaultsList[4] = { ThreadNetworkDiagnostics::NetworkFaultEnum( - 0) }; - for (auto fault : activeNetworkFaultsList) - { - ReturnErrorOnFailure(aEncoder.Encode(fault)); - } - - return CHIP_NO_ERROR; - }); - } - break; - - default: { - err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; - } - break; - } - - return err; -} template CHIP_ERROR GenericThreadStackManagerImpl_OpenThread::_GetPollPeriod(uint32_t & buf) diff --git a/src/platform/Tizen/ThreadStackManagerImpl.cpp b/src/platform/Tizen/ThreadStackManagerImpl.cpp index a5169d462c0209..47a4548507e332 100644 --- a/src/platform/Tizen/ThreadStackManagerImpl.cpp +++ b/src/platform/Tizen/ThreadStackManagerImpl.cpp @@ -535,13 +535,6 @@ CHIP_ERROR ThreadStackManagerImpl::_StartThreadScan(NetworkCommissioning::Thread void ThreadStackManagerImpl::_ResetThreadNetworkDiagnosticsCounts() {} -CHIP_ERROR ThreadStackManagerImpl::_WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - ChipLogError(DeviceLayer, "Not implemented"); - return CHIP_ERROR_NOT_IMPLEMENTED; -} - CHIP_ERROR ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback) diff --git a/src/platform/Tizen/ThreadStackManagerImpl.h b/src/platform/Tizen/ThreadStackManagerImpl.h index efa2c84e93252a..05b300f574114b 100644 --- a/src/platform/Tizen/ThreadStackManagerImpl.h +++ b/src/platform/Tizen/ThreadStackManagerImpl.h @@ -102,8 +102,6 @@ class ThreadStackManagerImpl : public ThreadStackManager void _ResetThreadNetworkDiagnosticsCounts(); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); - CHIP_ERROR _StartThreadScan(NetworkCommissioning::ThreadDriver::ScanCallback * callback); ~ThreadStackManagerImpl() = default; diff --git a/src/platform/webos/ThreadStackManagerImpl.cpp b/src/platform/webos/ThreadStackManagerImpl.cpp index 6acb542d78a3c1..79ad2e408857fb 100644 --- a/src/platform/webos/ThreadStackManagerImpl.cpp +++ b/src/platform/webos/ThreadStackManagerImpl.cpp @@ -647,174 +647,6 @@ void ThreadStackManagerImpl::_OnNetworkScanFinished(GAsyncResult * res) void ThreadStackManagerImpl::_ResetThreadNetworkDiagnosticsCounts() {} -CHIP_ERROR ThreadStackManagerImpl::_WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, - app::AttributeValueEncoder & encoder) -{ - CHIP_ERROR err = CHIP_NO_ERROR; - - switch (attributeId) - { - case ThreadNetworkDiagnostics::Attributes::NeighborTable::Id: - case ThreadNetworkDiagnostics::Attributes::RouteTable::Id: - case ThreadNetworkDiagnostics::Attributes::ActiveNetworkFaultsList::Id: - err = encoder.EncodeEmptyList(); - break; - case ThreadNetworkDiagnostics::Attributes::Channel::Id: - case ThreadNetworkDiagnostics::Attributes::RoutingRole::Id: - case ThreadNetworkDiagnostics::Attributes::NetworkName::Id: - case ThreadNetworkDiagnostics::Attributes::PanId::Id: - case ThreadNetworkDiagnostics::Attributes::ExtendedPanId::Id: - case ThreadNetworkDiagnostics::Attributes::MeshLocalPrefix::Id: - case ThreadNetworkDiagnostics::Attributes::PartitionId::Id: - case ThreadNetworkDiagnostics::Attributes::Weighting::Id: - case ThreadNetworkDiagnostics::Attributes::DataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::StableDataVersion::Id: - case ThreadNetworkDiagnostics::Attributes::LeaderRouterId::Id: - case ThreadNetworkDiagnostics::Attributes::ActiveTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::PendingTimestamp::Id: - case ThreadNetworkDiagnostics::Attributes::Delay::Id: - case ThreadNetworkDiagnostics::Attributes::ChannelPage0Mask::Id: - case ThreadNetworkDiagnostics::Attributes::SecurityPolicy::Id: - case ThreadNetworkDiagnostics::Attributes::OperationalDatasetComponents::Id: - err = encoder.EncodeNull(); - break; - case ThreadNetworkDiagnostics::Attributes::OverrunCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::DetachedRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::ChildRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RouterRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::LeaderRoleCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::AttachAttemptCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::PartitionIdChangeCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::BetterPartitionAttachAttemptCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::ParentChangeCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxTotalCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxUnicastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBroadcastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxAckRequestedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxAckedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxNoAckRequestedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDataCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDataPollCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBeaconCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxBeaconRequestCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxRetryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxDirectMaxRetryExpiryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxIndirectMaxRetryExpiryCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrCcaCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrAbortCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::TxErrBusyChannelCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxTotalCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxUnicastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBroadcastCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDataCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDataPollCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBeaconCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxBeaconRequestCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxAddressFilteredCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDestAddrFilteredCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxDuplicatedCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrNoFrameCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrUnknownNeighborCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrInvalidSrcAddrCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrSecCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrFcsCount::Id: - err = encoder.Encode(static_cast(0)); - break; - case ThreadNetworkDiagnostics::Attributes::RxErrOtherCount::Id: - err = encoder.Encode(static_cast(0)); - break; - default: - err = CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE; - break; - } - - return err; -} - CHIP_ERROR ThreadStackManagerImpl::_AttachToThreadNetwork(const Thread::OperationalDataset & dataset, NetworkCommissioning::Internal::WirelessDriver::ConnectCallback * callback) diff --git a/src/platform/webos/ThreadStackManagerImpl.h b/src/platform/webos/ThreadStackManagerImpl.h index 330e601f75a7fd..876c339cceb6ae 100644 --- a/src/platform/webos/ThreadStackManagerImpl.h +++ b/src/platform/webos/ThreadStackManagerImpl.h @@ -104,8 +104,6 @@ class ThreadStackManagerImpl : public ThreadStackManager void _ResetThreadNetworkDiagnosticsCounts(); - CHIP_ERROR _WriteThreadNetworkDiagnosticAttributeToTlv(AttributeId attributeId, app::AttributeValueEncoder & encoder); - CHIP_ERROR _StartThreadScan(NetworkCommissioning::ThreadDriver::ScanCallback * callback); ~ThreadStackManagerImpl() = default; diff --git a/src/python_testing/TC_pics_checker.py b/src/python_testing/TC_pics_checker.py index d7f076b471173d..6d49142f8f40b2 100644 --- a/src/python_testing/TC_pics_checker.py +++ b/src/python_testing/TC_pics_checker.py @@ -20,7 +20,7 @@ from basic_composition_support import BasicCompositionTests from global_attribute_ids import GlobalAttributeIds from matter_testing_support import (AttributePathLocation, ClusterPathLocation, CommandPathLocation, FeaturePathLocation, - MatterBaseTest, async_test_body, default_matter_test_main) + MatterBaseTest, TestStep, async_test_body, default_matter_test_main) from mobly import asserts from spec_parsing_support import build_xml_clusters @@ -101,27 +101,48 @@ def _add_pics_for_lists(self, cluster_id: int, attribute_id_of_element_list: Glo self._check_and_record_errors(location, required, pics) - def test_TC_pics_checker(self): + def steps_TC_IDM_10_4(self): + return [TestStep(1, "TH performs a wildcard read of all attributes on the endpoint under test"), + TestStep(2, "For every standard cluster: If the cluster is present on the endpoint, ensure the server-side PICS code for the cluster is present in the PICS file (e.g. OO.S for On/Off cluster).If the cluster is not present on the endpoint, ensure the cluster server PICS code is not present in the PICS file."), + TestStep(3, "For every standard cluster, for every attribute in the cluster:If the cluster is present on the endpoint and the attribute ID is present in the AttributeList global attribute within the cluster, ensure the server-side PICS code for the attribute is present in the PICS file (e.g. OO.S.A000 for On/Off cluster’s OnOff attribute).Otherwise, ensure the attribute PICS code is NOT present in the PICS file."), + TestStep(4, "For every cluster present in the spec, for every client → server command in the cluster: If the cluster is present on the endpoint and the command id is present in the accepted commands list, ensure the PICS code for the accepted command is present in the PICS file. Otherwise, ensure the accepted command PICS code is not present in the PICS file."), + TestStep(5, "For every cluster present in the spec, for every server → client command in the cluster: If the cluster is present on the endpoint and the command id is present in the generated commands list, ensure the PICS code for the generated command is present in the PICS file. Otherwise, ensure the generated command PICS code is not present in the PICS file."), + TestStep(6, "For every cluster present in the spec, for every feature in the cluster: If the cluster is present on the endpoint and the feature is marked in the feature map, ensure the PICS code for the feature is present in the PICS file. Otherwise, ensure the feature PICS code is not present in the PICS file.")] + + def test_TC_IDM_10_4(self): + # wildcard read is done in setup_class + self.step(1) self.endpoint_id = self.matter_test_config.endpoint self.endpoint = self.endpoints_tlv[self.endpoint_id] self.success = True - for cluster_id, cluster in Clusters.ClusterObjects.ALL_CLUSTERS.items(): - # Data model XML is used to get the PICS code for this cluster. If we don't know the PICS - # code, we can't evaluate the PICS list. Clusters that are present on the device but are - # not present in the spec are checked in the IDM tests. - if cluster_id not in self.xml_clusters or self.xml_clusters[cluster_id].pics is None: - continue + # Data model XML is used to get the PICS code for this cluster. If we don't know the PICS + # code, we can't evaluate the PICS list. Clusters that are present on the device but are + # not present in the spec are checked in the IDM tests. + checkable_clusters = {cluster_id: cluster for cluster_id, cluster in Clusters.ClusterObjects.ALL_CLUSTERS.items( + ) if cluster_id in self.xml_clusters and self.xml_clusters[cluster_id].pics is not None} + self.step(2) + for cluster_id, cluster in checkable_clusters.items(): # Ensure the PICS.S code is correctly marked pics_cluster = f'{self.xml_clusters[cluster_id].pics}.S' location = ClusterPathLocation(endpoint_id=self.endpoint_id, cluster_id=cluster_id) self._check_and_record_errors(location, cluster_id in self.endpoint, pics_cluster) + self.step(3) + for cluster_id, cluster in checkable_clusters.items(): self._add_pics_for_lists(cluster_id, GlobalAttributeIds.ATTRIBUTE_LIST_ID) + + self.step(4) + for cluster_id, cluster in checkable_clusters.items(): self._add_pics_for_lists(cluster_id, GlobalAttributeIds.ACCEPTED_COMMAND_LIST_ID) + + self.step(5) + for cluster_id, cluster in checkable_clusters.items(): self._add_pics_for_lists(cluster_id, GlobalAttributeIds.GENERATED_COMMAND_LIST_ID) + self.step(6) + for cluster_id, cluster in checkable_clusters.items(): try: cluster_features = cluster.Bitmaps.Feature except AttributeError: