diff --git a/examples/lock-app/lock-common/include/LockEndpoint.h b/examples/lock-app/lock-common/include/LockEndpoint.h index bd193d388db02b..aa67a69481f23d 100644 --- a/examples/lock-app/lock-common/include/LockEndpoint.h +++ b/examples/lock-app/lock-common/include/LockEndpoint.h @@ -18,7 +18,9 @@ #pragma once +#include #include +#include #include struct LockUserInfo @@ -38,10 +40,10 @@ struct WeekDaysScheduleInfo; struct YearDayScheduleInfo; struct HolidayScheduleInfo; -static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 20; -static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_TYPES = 6; +static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_DATA_SIZE = 65; +static constexpr size_t DOOR_LOCK_CREDENTIAL_INFO_MAX_TYPES = 9; -class LockEndpoint +class LockEndpoint : public chip::app::Clusters::DoorLock::Delegate { public: LockEndpoint(chip::EndpointId endpointId, uint16_t numberOfLockUsersSupported, uint16_t numberOfCredentialsSupported, @@ -60,6 +62,7 @@ class LockEndpoint } DoorLockServer::Instance().SetDoorState(endpointId, mDoorState); DoorLockServer::Instance().SetLockState(endpointId, mLockState); + chip::Crypto::DRBG_get_bytes(mAliroReaderGroupSubIdentifier, sizeof(mAliroReaderGroupSubIdentifier)); } inline chip::EndpointId GetEndpointId() const { return mEndpointId; } @@ -100,6 +103,22 @@ class LockEndpoint DlStatus SetSchedule(uint8_t holidayIndex, DlScheduleStatus status, uint32_t localStartTime, uint32_t localEndTime, OperatingModeEnum operatingMode); + // DoorLock::Delegate API. + CHIP_ERROR GetAliroReaderVerificationKey(chip::MutableByteSpan & verificationKey) override; + CHIP_ERROR GetAliroReaderGroupIdentifier(chip::MutableByteSpan & groupIdentifier) override; + CHIP_ERROR GetAliroReaderGroupSubIdentifier(chip::MutableByteSpan & groupSubIdentifier) override; + CHIP_ERROR GetAliroExpeditedTransactionSupportedProtocolVersionAtIndex(size_t index, + chip::MutableByteSpan & protocolVersion) override; + CHIP_ERROR GetAliroGroupResolvingKey(chip::MutableByteSpan & groupResolvingKey) override; + CHIP_ERROR GetAliroSupportedBLEUWBProtocolVersionAtIndex(size_t index, chip::MutableByteSpan & protocolVersion) override; + uint8_t GetAliroBLEAdvertisingVersion() override; + uint16_t GetNumberOfAliroCredentialIssuerKeysSupported() override; + uint16_t GetNumberOfAliroEndpointKeysSupported() override; + CHIP_ERROR SetAliroReaderConfig(const chip::ByteSpan & signingKey, const chip::ByteSpan & verificationKey, + const chip::ByteSpan & groupIdentifier, + const chip::Optional & groupResolvingKey) override; + CHIP_ERROR ClearAliroReaderConfig() override; + private: bool setLockState(const Nullable & fabricIdx, const Nullable & nodeId, DlLockState lockState, const Optional & pin, OperationErrorEnum & err, @@ -130,6 +149,14 @@ class LockEndpoint std::vector> mWeekDaySchedules; std::vector> mYearDaySchedules; std::vector mHolidaySchedules; + + // Actual Aliro state would presumably be stored somewhere else, and persistently; this + // example just stores it in memory for illustration purposes. + uint8_t mAliroReaderVerificationKey[chip::app::Clusters::DoorLock::kAliroReaderVerificationKeySize]; + uint8_t mAliroReaderGroupIdentifier[chip::app::Clusters::DoorLock::kAliroReaderGroupIdentifierSize]; + uint8_t mAliroReaderGroupSubIdentifier[chip::app::Clusters::DoorLock::kAliroReaderGroupSubIdentifierSize]; + uint8_t mAliroGroupResolvingKey[chip::app::Clusters::DoorLock::kAliroGroupResolvingKeySize]; + bool mAliroStateInitialized = false; }; struct LockCredentialInfo diff --git a/examples/lock-app/lock-common/include/LockManager.h b/examples/lock-app/lock-common/include/LockManager.h index 71dcf6f02dc072..fb4299a534622c 100644 --- a/examples/lock-app/lock-common/include/LockManager.h +++ b/examples/lock-app/lock-common/include/LockManager.h @@ -70,7 +70,12 @@ class LockManager private: LockEndpoint * getEndpoint(chip::EndpointId endpointId); - std::vector mEndpoints; + /** + * We store the LockEndpoint instances by pointer, not value, so + * LockEndpoint can have a stable location in memory, which lets it + * implement DoorLock::Delegate. + */ + std::vector> mEndpoints; static LockManager instance; }; diff --git a/examples/lock-app/lock-common/src/LockEndpoint.cpp b/examples/lock-app/lock-common/src/LockEndpoint.cpp index bda27f18ba2c8c..5481d01471cfd0 100644 --- a/examples/lock-app/lock-common/src/LockEndpoint.cpp +++ b/examples/lock-app/lock-common/src/LockEndpoint.cpp @@ -17,10 +17,15 @@ */ #include "LockEndpoint.h" #include +#include #include +#include #include #include +using chip::ByteSpan; +using chip::MutableByteSpan; +using chip::Optional; using chip::to_underlying; using chip::app::DataModel::MakeNullable; @@ -204,7 +209,8 @@ bool LockEndpoint::GetCredential(uint16_t credentialIndex, CredentialTypeEnum cr if (credentialIndex >= mLockCredentials.at(to_underlying(credentialType)).size() || (0 == credentialIndex && CredentialTypeEnum::kProgrammingPIN != credentialType)) { - ChipLogError(Zcl, "Cannot get the credential - index out of range [endpoint=%d,index=%d]", mEndpointId, credentialIndex); + ChipLogError(Zcl, "Cannot get the credential - index out of range [endpoint=%d,index=%d]: %d", mEndpointId, credentialIndex, + static_cast(mLockCredentials.at(to_underlying(credentialType)).size())); return false; } @@ -407,6 +413,149 @@ DlStatus LockEndpoint::SetSchedule(uint8_t holidayIndex, DlScheduleStatus status return DlStatus::kSuccess; } +CHIP_ERROR LockEndpoint::GetAliroReaderVerificationKey(MutableByteSpan & verificationKey) +{ + if (!mAliroStateInitialized) + { + verificationKey.reduce_size(0); + return CHIP_NO_ERROR; + } + + return chip::CopySpanToMutableSpan(ByteSpan(mAliroReaderVerificationKey), verificationKey); +} + +CHIP_ERROR LockEndpoint::GetAliroReaderGroupIdentifier(MutableByteSpan & groupIdentifier) +{ + if (!mAliroStateInitialized) + { + groupIdentifier.reduce_size(0); + return CHIP_NO_ERROR; + } + + return CopySpanToMutableSpan(ByteSpan(mAliroReaderGroupIdentifier), groupIdentifier); +} + +CHIP_ERROR LockEndpoint::GetAliroReaderGroupSubIdentifier(MutableByteSpan & groupSubIdentifier) +{ + return CopySpanToMutableSpan(ByteSpan(mAliroReaderGroupSubIdentifier), groupSubIdentifier); +} + +namespace { + +CHIP_ERROR CopyProtocolVersionIntoSpan(uint16_t protocolVersionValue, MutableByteSpan & protocolVersion) +{ + using namespace chip::app::Clusters::DoorLock; + + static_assert(sizeof(protocolVersionValue) == kAliroProtocolVersionSize); + + if (protocolVersion.size() < kAliroProtocolVersionSize) + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + // Per Aliro spec, protocol version encoding is big-endian + chip::Encoding::BigEndian::Put16(protocolVersion.data(), protocolVersionValue); + protocolVersion.reduce_size(kAliroProtocolVersionSize); + return CHIP_NO_ERROR; +} + +} // anonymous namespace + +CHIP_ERROR LockEndpoint::GetAliroExpeditedTransactionSupportedProtocolVersionAtIndex(size_t index, + MutableByteSpan & protocolVersion) +{ + // Only claim support for the one known protocol version for now: 0x0100. + constexpr uint16_t knownProtocolVersion = 0x0100; + + if (index > 0) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + return CopyProtocolVersionIntoSpan(knownProtocolVersion, protocolVersion); +} + +CHIP_ERROR LockEndpoint::GetAliroGroupResolvingKey(MutableByteSpan & groupResolvingKey) +{ + if (!mAliroStateInitialized) + { + groupResolvingKey.reduce_size(0); + return CHIP_NO_ERROR; + } + + return CopySpanToMutableSpan(ByteSpan(mAliroGroupResolvingKey), groupResolvingKey); +} + +CHIP_ERROR LockEndpoint::GetAliroSupportedBLEUWBProtocolVersionAtIndex(size_t index, MutableByteSpan & protocolVersion) +{ + // Only claim support for the one known protocol version for now: 0x0100. + constexpr uint16_t knownProtocolVersion = 0x0100; + + if (index > 0) + { + return CHIP_ERROR_PROVIDER_LIST_EXHAUSTED; + } + + return CopyProtocolVersionIntoSpan(knownProtocolVersion, protocolVersion); +} + +uint8_t LockEndpoint::GetAliroBLEAdvertisingVersion() +{ + // For now the only define value of the BLE advertising version for Aliro is 0. + return 0; +} + +uint16_t LockEndpoint::GetNumberOfAliroCredentialIssuerKeysSupported() +{ + using namespace chip::app::Clusters::DoorLock; + + // Our vector has an extra entry at index 0 that is not a valid entry, so + // the actual number of credentials supported is one length than the length. + return static_cast(mLockCredentials.at(to_underlying(CredentialTypeEnum::kAliroCredentialIssuerKey)).size() - 1); +} + +uint16_t LockEndpoint::GetNumberOfAliroEndpointKeysSupported() +{ + using namespace chip::app::Clusters::DoorLock; + + // Our vector has an extra entry at index 0 that is not a valid entry, so + // the actual number of credentials supported is one length than the length. + // + // Also, our arrays are the same size, so we just return the size of one of + // the arrays: that is the cap on the total number of endpoint keys + // supported, which can be of either type. + return static_cast(mLockCredentials.at(to_underlying(CredentialTypeEnum::kAliroEvictableEndpointKey)).size() - 1); +} + +CHIP_ERROR LockEndpoint::SetAliroReaderConfig(const ByteSpan & signingKey, const ByteSpan & verificationKey, + const ByteSpan & groupIdentifier, const Optional & groupResolvingKey) +{ + // We ignore the signing key, since we never do anything with it. + + VerifyOrReturnError(verificationKey.size() == sizeof(mAliroReaderVerificationKey), CHIP_ERROR_INVALID_ARGUMENT); + memcpy(mAliroReaderVerificationKey, verificationKey.data(), sizeof(mAliroReaderVerificationKey)); + + VerifyOrReturnError(groupIdentifier.size() == sizeof(mAliroReaderGroupIdentifier), CHIP_ERROR_INVALID_ARGUMENT); + memcpy(mAliroReaderGroupIdentifier, groupIdentifier.data(), sizeof(mAliroReaderGroupIdentifier)); + + if (groupResolvingKey.HasValue()) + { + VerifyOrReturnError(groupResolvingKey.Value().size() == sizeof(mAliroGroupResolvingKey), CHIP_ERROR_INVALID_ARGUMENT); + memcpy(mAliroGroupResolvingKey, groupResolvingKey.Value().data(), sizeof(mAliroGroupResolvingKey)); + } + + mAliroStateInitialized = true; + return CHIP_NO_ERROR; +} + +CHIP_ERROR LockEndpoint::ClearAliroReaderConfig() +{ + // A real implementation would clear out key data from the other parts of + // the application that might use it. + mAliroStateInitialized = false; + return CHIP_NO_ERROR; +} + bool LockEndpoint::setLockState(const Nullable & fabricIdx, const Nullable & nodeId, DlLockState lockState, const Optional & pin, OperationErrorEnum & err, OperationSourceEnum opSource) diff --git a/examples/lock-app/lock-common/src/LockManager.cpp b/examples/lock-app/lock-common/src/LockManager.cpp index 8fd1ef5441b139..8af66051883aa4 100644 --- a/examples/lock-app/lock-common/src/LockManager.cpp +++ b/examples/lock-app/lock-common/src/LockManager.cpp @@ -20,6 +20,7 @@ #include #include +#include using chip::to_underlying; @@ -98,8 +99,9 @@ bool LockManager::InitEndpoint(chip::EndpointId endpointId) numberOfHolidaySchedules = 10; } - mEndpoints.emplace_back(endpointId, numberOfSupportedUsers, numberOfSupportedCredentials, numberOfWeekDaySchedulesPerUser, - numberOfYearDaySchedulesPerUser, numberOfCredentialsSupportedPerUser, numberOfHolidaySchedules); + mEndpoints.emplace_back(std::make_unique(endpointId, numberOfSupportedUsers, numberOfSupportedCredentials, + numberOfWeekDaySchedulesPerUser, numberOfYearDaySchedulesPerUser, + numberOfCredentialsSupportedPerUser, numberOfHolidaySchedules)); ChipLogProgress(Zcl, "Initialized new lock door endpoint " @@ -107,6 +109,7 @@ bool LockManager::InitEndpoint(chip::EndpointId endpointId) "numberOfCredentialsSupportedPerUser=%d,holidaySchedules=%d]", endpointId, numberOfSupportedUsers, numberOfSupportedCredentials, numberOfWeekDaySchedulesPerUser, numberOfYearDaySchedulesPerUser, numberOfCredentialsSupportedPerUser, numberOfHolidaySchedules); + DoorLockServer::Instance().SetDelegate(endpointId, mEndpoints.back().get()); return true; } @@ -303,11 +306,11 @@ DlStatus LockManager::SetSchedule(chip::EndpointId endpointId, uint8_t holidayIn LockEndpoint * LockManager::getEndpoint(chip::EndpointId endpointId) { - for (auto & mEndpoint : mEndpoints) + for (auto & endpoint : mEndpoints) { - if (mEndpoint.GetEndpointId() == endpointId) + if (endpoint->GetEndpointId() == endpointId) { - return &mEndpoint; + return endpoint.get(); } } return nullptr; diff --git a/src/app/clusters/door-lock-server/door-lock-server.cpp b/src/app/clusters/door-lock-server/door-lock-server.cpp index 3c395a3d7fa69f..68e5f398b5bc84 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.cpp +++ b/src/app/clusters/door-lock-server/door-lock-server.cpp @@ -957,7 +957,18 @@ void DoorLockServer::clearCredentialCommandHandler( } // Remove all the credentials of the particular type. - auto credentialType = credential.Value().credentialType; + auto credentialType = credential.Value().credentialType; + + if (!credentialTypeSupported(commandPath.mEndpointId, credentialType)) + { + ChipLogProgress(Zcl, + "[ClearCredential] Credential type is not supported [endpointId=%d,credentialType=%u" + "]", + commandPath.mEndpointId, to_underlying(credentialType)); + commandObj->AddStatus(commandPath, Status::InvalidCommand); + return; + } + auto credentialIndex = credential.Value().credentialIndex; if (0xFFFE == credentialIndex) { @@ -2410,6 +2421,42 @@ DlStatus DoorLockServer::createCredential(chip::EndpointId endpointId, chip::Fab return DlStatus::kInvalidField; } + // For Aliro endpoint keys, there is a single shared count for the total + // count of evictable and non-evictable keys that can be stored. This needs + // to be enforced specially, because none of the other logic we have handles that. + if (credentialType == CredentialTypeEnum::kAliroEvictableEndpointKey || + credentialType == CredentialTypeEnum::kAliroNonEvictableEndpointKey) + { + Delegate * delegate = GetDelegate(endpointId); + if (delegate == nullptr) + { + ChipLogError(Zcl, "Door lock delegate is null, can't handle Aliro credentials"); + return DlStatus::kFailure; + } + + size_t maxEndpointKeys = delegate->GetNumberOfAliroEndpointKeysSupported(); + size_t evictableEndpointKeys, nonEvictableEndpointKeys; + + if (!countOccupiedCredentials(endpointId, CredentialTypeEnum::kAliroEvictableEndpointKey, evictableEndpointKeys)) + { + ChipLogError(Zcl, "Unable to count Aliro evictable endpoint keys."); + return DlStatus::kFailure; + } + + if (!countOccupiedCredentials(endpointId, CredentialTypeEnum::kAliroNonEvictableEndpointKey, nonEvictableEndpointKeys)) + { + ChipLogError(Zcl, "Unable to count Aliro non-evictable endpoint keys."); + return DlStatus::kFailure; + } + + if (evictableEndpointKeys + nonEvictableEndpointKeys >= maxEndpointKeys) + { + // We have no space for another credential here. + ChipLogError(Zcl, "Unable to create Aliro endpoint key credential; too many exist already [endpointId=%d]", endpointId); + return DlStatus::kResourceExhausted; + } + } + CredentialStruct credential{ credentialType, credentialIndex }; // appclusters, 5.2.4.40: if userIndex is not provided we should create new user DlStatus status = DlStatus::kSuccess; @@ -2447,6 +2494,42 @@ DlStatus DoorLockServer::createCredential(chip::EndpointId endpointId, chip::Fab return status; } +bool DoorLockServer::countOccupiedCredentials(chip::EndpointId endpointId, CredentialTypeEnum credentialType, + size_t & occupiedCount) +{ + uint16_t maxCredentialCount; + + if (!getMaxNumberOfCredentials(endpointId, credentialType, maxCredentialCount)) + { + return false; + } + + uint16_t startIndex = 1; + // Programming PIN is a special case -- it is unique and its index assumed to be 0. + if (CredentialTypeEnum::kProgrammingPIN == credentialType) + { + startIndex = 0; + maxCredentialCount--; + } + + occupiedCount = 0; + for (uint16_t credentialIndex = startIndex; credentialIndex <= maxCredentialCount; ++credentialIndex) + { + EmberAfPluginDoorLockCredentialInfo credential; + if (!emberAfPluginDoorLockGetCredential(endpointId, credentialIndex, credentialType, credential)) + { + return false; + } + + if (credential.status == DlCredentialStatus::kOccupied) + { + ++occupiedCount; + } + } + + return true; +} + DlStatus DoorLockServer::modifyProgrammingPIN(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, chip::NodeId sourceNodeId, uint16_t credentialIndex, CredentialTypeEnum credentialType, diff --git a/src/app/clusters/door-lock-server/door-lock-server.h b/src/app/clusters/door-lock-server/door-lock-server.h index ccb62dde46712b..81b18c60e687e8 100644 --- a/src/app/clusters/door-lock-server/door-lock-server.h +++ b/src/app/clusters/door-lock-server/door-lock-server.h @@ -360,6 +360,12 @@ class DoorLockServer : public chip::app::AttributeAccessInterface const EmberAfPluginDoorLockCredentialInfo & existingCredential, const chip::ByteSpan & credentialData, Nullable userIndex, const Nullable & userStatus, Nullable userType, uint16_t & createdUserIndex); + /** + * countOccupiedCredentials counts the number of occupied credentials of the + * given type. Returns false on application-side errors (i.e. if the count + * cannot be determined). + */ + bool countOccupiedCredentials(chip::EndpointId endpointId, CredentialTypeEnum credentialType, size_t & occupiedCount); DlStatus modifyProgrammingPIN(chip::EndpointId endpointId, chip::FabricIndex modifierFabricIndex, chip::NodeId sourceNodeId, uint16_t credentialIndex, CredentialTypeEnum credentialType, const EmberAfPluginDoorLockCredentialInfo & existingCredential, diff --git a/src/darwin/Framework/CHIP/MTRBaseDevice.mm b/src/darwin/Framework/CHIP/MTRBaseDevice.mm index 331d61129b9daf..da40f1ca24d9ac 100644 --- a/src/darwin/Framework/CHIP/MTRBaseDevice.mm +++ b/src/darwin/Framework/CHIP/MTRBaseDevice.mm @@ -2290,8 +2290,12 @@ + (MTRAttributeRequestPath *)requestPathWithEndpointID:(NSNumber * _Nullable)end - (BOOL)isEqualToAttributeRequestPath:(MTRAttributeRequestPath *)path { - return [_endpoint isEqualToNumber:path.endpoint] && [_cluster isEqualToNumber:path.cluster] && - [_attribute isEqualToNumber:path.attribute]; + if (!path) + return NO; + + return (path.endpoint && [_endpoint isEqualToNumber:path.endpoint]) + && (path.cluster && [_cluster isEqualToNumber:path.cluster]) + && (path.attribute && [_attribute isEqualToNumber:path.attribute]); } - (BOOL)isEqual:(id)object @@ -2362,8 +2366,12 @@ + (MTREventRequestPath *)requestPathWithEndpointID:(NSNumber * _Nullable)endpoin - (BOOL)isEqualToEventRequestPath:(MTREventRequestPath *)path { - return - [_endpoint isEqualToNumber:path.endpoint] && [_cluster isEqualToNumber:path.cluster] && [_event isEqualToNumber:path.event]; + if (!path) + return NO; + + return (path.endpoint && [_endpoint isEqualToNumber:path.endpoint]) + && (path.cluster && [_cluster isEqualToNumber:path.cluster]) + && (path.event && [_event isEqualToNumber:path.event]); } - (BOOL)isEqual:(id)object @@ -2432,7 +2440,11 @@ ConcreteClusterPath path(static_cast([endpointID unsignedShort - (BOOL)isEqualToClusterPath:(MTRClusterPath *)clusterPath { - return [_endpoint isEqualToNumber:clusterPath.endpoint] && [_cluster isEqualToNumber:clusterPath.cluster]; + if (!clusterPath) + return NO; + + return (clusterPath.endpoint && [_endpoint isEqualToNumber:clusterPath.endpoint]) + && (clusterPath.cluster && [_cluster isEqualToNumber:clusterPath.cluster]); } - (BOOL)isEqual:(id)object @@ -2520,7 +2532,10 @@ ConcreteDataAttributePath path(static_cast([endpointID unsigne - (BOOL)isEqualToAttributePath:(MTRAttributePath *)attributePath { - return [self isEqualToClusterPath:attributePath] && [_attribute isEqualToNumber:attributePath.attribute]; + if (!attributePath) + return NO; + + return [self isEqualToClusterPath:attributePath] && attributePath.attribute && [_attribute isEqualToNumber:attributePath.attribute]; } - (BOOL)isEqual:(id)object @@ -2613,7 +2628,10 @@ ConcreteEventPath path(static_cast([endpointID unsignedShortVa - (BOOL)isEqualToEventPath:(MTREventPath *)eventPath { - return [self isEqualToClusterPath:eventPath] && [_event isEqualToNumber:eventPath.event]; + if (!eventPath) + return NO; + + return [self isEqualToClusterPath:eventPath] && eventPath.event && [_event isEqualToNumber:eventPath.event]; } - (BOOL)isEqual:(id)object @@ -2703,7 +2721,10 @@ ConcreteCommandPath path(static_cast([endpointID unsignedShort - (BOOL)isEqualToCommandPath:(MTRCommandPath *)commandPath { - return [self isEqualToClusterPath:commandPath] && [_command isEqualToNumber:commandPath.command]; + if (!commandPath) + return NO; + + return [self isEqualToClusterPath:commandPath] && commandPath.command && [_command isEqualToNumber:commandPath.command]; } - (BOOL)isEqual:(id)object diff --git a/src/darwin/Framework/CHIP/MTRDevice.mm b/src/darwin/Framework/CHIP/MTRDevice.mm index fff962dcc94188..eb490bdbe0d37c 100644 --- a/src/darwin/Framework/CHIP/MTRDevice.mm +++ b/src/darwin/Framework/CHIP/MTRDevice.mm @@ -336,7 +336,11 @@ - (id)copyWithZone:(NSZone *)zone - (BOOL)isEqualToClusterData:(MTRDeviceClusterData *)otherClusterData { - return [_dataVersion isEqual:otherClusterData.dataVersion] && [_attributes isEqual:otherClusterData.attributes]; + if (!otherClusterData) + return NO; + + return (otherClusterData.dataVersion && [_dataVersion isEqual:otherClusterData.dataVersion]) + && (otherClusterData.attributes && [_attributes isEqual:otherClusterData.attributes]); } - (BOOL)isEqual:(id)object diff --git a/src/darwin/Framework/CHIP/MTRDeviceController.mm b/src/darwin/Framework/CHIP/MTRDeviceController.mm index 0ba1b181ff6f4d..0f263d756c5e7b 100644 --- a/src/darwin/Framework/CHIP/MTRDeviceController.mm +++ b/src/darwin/Framework/CHIP/MTRDeviceController.mm @@ -295,6 +295,7 @@ - (void)shutdown return; } + MTR_LOG("Shutting down MTRDeviceController: %@", self); [self cleanupAfterStartup]; } @@ -306,6 +307,7 @@ - (void)cleanupAfterStartup // do the secure session shutdowns. Since we don't want to hold the lock // while calling out into arbitrary invalidation code, snapshot the list of // devices before we start invalidating. + MTR_LOG("cleanupAfterStartup MTRDeviceController: %@", self); os_unfair_lock_lock(&_deviceMapLock); NSEnumerator * devices = [_nodeIDToDeviceMap objectEnumerator]; [_nodeIDToDeviceMap removeAllObjects]; @@ -323,6 +325,7 @@ - (void)cleanupAfterStartup // in a very specific way that only MTRDeviceControllerFactory knows about. - (void)shutDownCppController { + MTR_LOG("shutDownCppController MTRDeviceController: %p", self); assertChipStackLockedByCurrentThread(); // Shut down all our endpoints. @@ -624,6 +627,7 @@ - (BOOL)startup:(MTRDeviceControllerStartupParamsInternal *)startupParams }); }]; } + MTR_LOG("MTRDeviceController startup: %@", self); return YES; } @@ -1259,7 +1263,7 @@ - (BOOL)checkIsRunning:(NSError * __autoreleasing *)error return YES; } - MTR_LOG_ERROR("Error: %s", [kErrorNotRunning UTF8String]); + MTR_LOG_ERROR("MTRDeviceController: %@ Error: %s", self, [kErrorNotRunning UTF8String]); if (error) { *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; } diff --git a/src/python_testing/TC_EEM_2_2.py b/src/python_testing/TC_EEM_2_2.py index 2aef2964789534..d44821c6cd2209 100644 --- a/src/python_testing/TC_EEM_2_2.py +++ b/src/python_testing/TC_EEM_2_2.py @@ -48,7 +48,7 @@ def steps_TC_EEM_2_2(self) -> list[TestStep]: TestStep("4", "Wait 3 seconds"), TestStep("4a", "TH reads from the DUT the CumulativeEnergyImported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 3 seconds"), + TestStep("5", "Wait 5 seconds"), TestStep("5a", "TH reads from the DUT the CumulativeEnergyImported attribute", "Verify the read is successful and that the value is greater than the value measured in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -75,7 +75,7 @@ async def test_TC_EEM_2_2(self): cumulative_energy_imported = await self.read_eem_attribute_expect_success("CumulativeEnergyImported") self.step("5") - time.sleep(3) + time.sleep(5) self.step("5a") cumulative_energy_imported_2 = await self.read_eem_attribute_expect_success("CumulativeEnergyImported") diff --git a/src/python_testing/TC_EEM_2_3.py b/src/python_testing/TC_EEM_2_3.py index b9df334f16ee71..49149dff4a9b70 100644 --- a/src/python_testing/TC_EEM_2_3.py +++ b/src/python_testing/TC_EEM_2_3.py @@ -48,7 +48,7 @@ def steps_TC_EEM_2_3(self) -> list[TestStep]: TestStep("4", "Wait 6 seconds"), TestStep("4a", "TH reads from the DUT the CumulativeEnergyExported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 6 seconds"), + TestStep("5", "Wait 11 seconds"), TestStep("5a", "TH reads from the DUT the CumulativeEnergyExported attribute", "Verify the read is successful and that the value is greater than the value measured in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -75,7 +75,7 @@ async def test_TC_EEM_2_3(self): cumulative_energy_exported = await self.read_eem_attribute_expect_success("CumulativeEnergyExported") self.step("5") - time.sleep(6) + time.sleep(11) self.step("5a") cumulative_energy_exported_2 = await self.read_eem_attribute_expect_success("CumulativeEnergyExported") diff --git a/src/python_testing/TC_EEM_2_4.py b/src/python_testing/TC_EEM_2_4.py index 5a77885cb9f17a..94cf7bd3670543 100644 --- a/src/python_testing/TC_EEM_2_4.py +++ b/src/python_testing/TC_EEM_2_4.py @@ -48,7 +48,7 @@ def steps_TC_EEM_2_4(self) -> list[TestStep]: TestStep("4", "Wait 3 seconds"), TestStep("4a", "TH reads from the DUT the PeriodicEnergyImported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 3 seconds"), + TestStep("5", "Wait 5 seconds"), TestStep("5a", "TH reads from the DUT the PeriodicEnergyImported attribute", "Verify the read is successful and that the value read has to be different from value measure in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -75,7 +75,7 @@ async def test_TC_EEM_2_4(self): periodic_energy_imported = await self.read_eem_attribute_expect_success("PeriodicEnergyImported") self.step("5") - time.sleep(3) + time.sleep(5) self.step("5a") periodic_energy_imported_2 = await self.read_eem_attribute_expect_success("PeriodicEnergyImported") diff --git a/src/python_testing/TC_EEM_2_5.py b/src/python_testing/TC_EEM_2_5.py index 239317c0b776fe..7a42913956ca19 100644 --- a/src/python_testing/TC_EEM_2_5.py +++ b/src/python_testing/TC_EEM_2_5.py @@ -48,7 +48,7 @@ def steps_TC_EEM_2_5(self) -> list[TestStep]: TestStep("4", "Wait 6 seconds"), TestStep("4a", "TH reads from the DUT the PeriodicEnergyExported attribute", "Verify the read is successful and note the value read."), - TestStep("5", "Wait 6 seconds"), + TestStep("5", "Wait 11 seconds"), TestStep("5a", "TH reads from the DUT the PeriodicEnergyExported attribute", "Verify the read is successful and that the value read has to be different from value measure in step 4a."), TestStep("6", "TH sends TestEventTrigger command to General Diagnostics Cluster on Endpoint 0 with EnableKey field set to PIXIT.EEM.TEST_EVENT_TRIGGER_KEY and EventTrigger field set to PIXIT.EEM.TEST_EVENT_TRIGGER for Stop Fake Readings Test Event."), @@ -75,7 +75,7 @@ async def test_TC_EEM_2_5(self): periodic_energy_exported = await self.read_eem_attribute_expect_success("PeriodicEnergyExported") self.step("5") - time.sleep(6) + time.sleep(11) self.step("5a") periodic_energy_exported_2 = await self.read_eem_attribute_expect_success("PeriodicEnergyExported") diff --git a/src/python_testing/TC_EPM_2_2.py b/src/python_testing/TC_EPM_2_2.py index 68c6c5919bbedc..629bf0e739d866 100644 --- a/src/python_testing/TC_EPM_2_2.py +++ b/src/python_testing/TC_EPM_2_2.py @@ -56,7 +56,7 @@ def steps_TC_EPM_2_2(self) -> list[TestStep]: "Verify the read is successful and that the value is between 3'848 and 4'848 mA. Note the value read."), TestStep("4c", "TH reads from the DUT the Voltage attribute", "Verify the read is successful and that the value is between 229'000 and 231'000 mV. Note the value read."), - TestStep("5", "Wait 3 seconds"), + TestStep("5", "Wait 5 seconds"), TestStep("5a", "TH reads from the DUT the ActivePower attribute", "Verify the read is successful, that the value is between '980'000 and 1'020'000 mW, and the value is different from the value read in step 4a."), TestStep("5b", "TH reads from the DUT the ActiveCurrent attribute", @@ -100,8 +100,8 @@ async def test_TC_EPM_2_2(self): voltage = await self.check_epm_attribute_in_range("Voltage", 229000, 231000) self.step("5") - # After 3 seconds... - time.sleep(3) + # After 5 seconds... + time.sleep(5) self.step("5a") # Active power is Mandatory