Skip to content

Commit 63da540

Browse files
TC OCC 3.1 and 3.2 CI Implementation (project-chip#34836)
* Update tests.yaml adding occ test case 3.1 and 3.2 * Update TC_OCC_3_1.py added CI on step 3 and 4 * Update TC_OCC_3_2.py added ci implementation on step 3a and 3c * Update AllClustersCommandDelegate.cpp Added occupancy sensor ci named path implementation * Update AllClustersCommandDelegate.h added occ ci named path implemetation * Update AllClustersCommandDelegate.cpp change to be restyled * Update TC_OCC_3_1.py restyled * Update TC_OCC_3_2.py restyled * Update TC_OCC_3_1.py restyled * Update TC_OCC_3_2.py restyled * Update TC_OCC_3_1.py sleep module fix * Update TC_OCC_3_2.py sleep module fix * Update TC_OCC_3_2.py restyled * Update TC_OCC_3_1.py minor fixes * Update TC_OCC_3_2.py Added one more write to consider proper callback sequence * Update TC_OCC_3_2.py restyled * Update TC_OCC_3_2.py * Update tests.yaml * Update TC_OCC_3_2.py Fixed a bug on occupancy attribute testing * Update TC_OCC_3_1.py * Update TC_OCC_3_1.py * Update TC_OCC_3_2.py * Update TC_OCC_3_1.py * Update TC_OCC_3_2.py * Update AllClustersCommandDelegate.cpp Removed 1 == endpointId at line 798 Replaced nullptr with reinterpret_cast<void *>(static_cast<uintptr_t>(endpointId)) at line 804 Replaced (1, cleaValue) in line 817 with (static_cast<EndpointId>(reinterpret_cast<uintptr_t>(appState)), clearValue) * Update TC_OCC_3_1.py Modified HoldTime implementation on testing and added Occupancy attribute subscription and event testing in 3.1. * Update TC_OCC_3_1.py * Update TC_OCC_3_1.py * Update AllClustersCommandDelegate.cpp * Update TC_OCC_3_1.py fixed python errors * Update TC_OCC_3_1.py * Update TC_OCC_3_2.py Undated with holdtime testing with holdtime Min/Max * Update TC_OCC_3_2.py * Update TC_OCC_3_2.py * Update TC_OCC_3_2.py * Update .github/workflows/tests.yaml Co-authored-by: Tennessee Carmel-Veilleux <tennessee.carmelveilleux@gmail.com> * Update .github/workflows/tests.yaml Co-authored-by: Tennessee Carmel-Veilleux <tennessee.carmelveilleux@gmail.com> * Fix TC-OCC-3.1/3.2 tests - Implement event handling - Properly implement event checks - Correctly handle HoldTime -> Legacy timing dependencies - Simplify flows - Add missing steps * Update AllClustersCommandDelegate.cpp restyled * Update occupancy-sensor-server.cpp restyled * Update TC_OCC_3_1.py restyled * Update TC_OCC_3_2.py restyled * Update matter_testing_support.py restyled * Update TC_OCC_3_2.py * Fix a lint --------- Co-authored-by: Tennessee Carmel-Veilleux <tennessee.carmelveilleux@gmail.com>
1 parent 9c34316 commit 63da540

File tree

7 files changed

+604
-361
lines changed

7 files changed

+604
-361
lines changed

examples/all-clusters-app/linux/AllClustersCommandDelegate.cpp

+99
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
#include "AllClustersCommandDelegate.h"
2020

2121
#include <app-common/zap-generated/attributes/Accessors.h>
22+
#include <app/EventLogging.h>
2223
#include <app/clusters/general-diagnostics-server/general-diagnostics-server.h>
24+
#include <app/clusters/occupancy-sensor-server/occupancy-sensor-server.h>
2325
#include <app/clusters/smoke-co-alarm-server/smoke-co-alarm-server.h>
2426
#include <app/clusters/software-diagnostics-server/software-diagnostics-server.h>
2527
#include <app/clusters/switch-server/switch-server.h>
@@ -246,6 +248,24 @@ void HandleSimulateLatchPosition(Json::Value & jsonValue)
246248
}
247249
}
248250

251+
void EmitOccupancyChangedEvent(EndpointId endpointId, uint8_t occupancyValue)
252+
{
253+
Clusters::OccupancySensing::Events::OccupancyChanged::Type event{};
254+
event.occupancy = static_cast<BitMask<Clusters::OccupancySensing::OccupancyBitmap>>(occupancyValue);
255+
EventNumber eventNumber = 0;
256+
257+
CHIP_ERROR err = LogEvent(event, endpointId, eventNumber);
258+
if (err != CHIP_NO_ERROR)
259+
{
260+
ChipLogError(NotSpecified, "Failed to log OccupancyChanged event: %" CHIP_ERROR_FORMAT, err.Format());
261+
}
262+
else
263+
{
264+
ChipLogProgress(NotSpecified, "Logged OccupancyChanged(occupancy=%u) on Endpoint %u", static_cast<unsigned>(occupancyValue),
265+
static_cast<unsigned>(endpointId));
266+
}
267+
}
268+
249269
} // namespace
250270

251271
AllClustersAppCommandHandler * AllClustersAppCommandHandler::FromJSON(const char * json)
@@ -407,6 +427,20 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context)
407427
{
408428
HandleSimulateLatchPosition(self->mJsonValue);
409429
}
430+
else if (name == "SetOccupancy")
431+
{
432+
uint8_t occupancy = static_cast<uint8_t>(self->mJsonValue["Occupancy"].asUInt());
433+
EndpointId endpointId = static_cast<EndpointId>(self->mJsonValue["EndpointId"].asUInt());
434+
435+
if (1 == occupancy || 0 == occupancy)
436+
{
437+
self->HandleSetOccupancyChange(endpointId, occupancy);
438+
}
439+
else
440+
{
441+
ChipLogError(NotSpecified, "Invalid Occupancy state to set.");
442+
}
443+
}
410444
else
411445
{
412446
ChipLogError(NotSpecified, "Unhandled command '%s': this hould never happen", name.c_str());
@@ -769,6 +803,71 @@ void AllClustersAppCommandHandler::OnAirQualityChange(uint32_t aNewValue)
769803
}
770804
}
771805

806+
void AllClustersAppCommandHandler::HandleSetOccupancyChange(EndpointId endpointId, uint8_t newOccupancyValue)
807+
{
808+
BitMask<chip::app::Clusters::OccupancySensing::OccupancyBitmap> currentOccupancy;
809+
Protocols::InteractionModel::Status status = OccupancySensing::Attributes::Occupancy::Get(endpointId, &currentOccupancy);
810+
811+
if (static_cast<BitMask<chip::app::Clusters::OccupancySensing::OccupancyBitmap>>(newOccupancyValue) == currentOccupancy)
812+
{
813+
ChipLogDetail(NotSpecified, "Skipping setting occupancy changed due to same value.");
814+
return;
815+
}
816+
817+
status = OccupancySensing::Attributes::Occupancy::Set(endpointId, newOccupancyValue);
818+
ChipLogDetail(NotSpecified, "Set Occupancy attribute to %u", newOccupancyValue);
819+
820+
if (status != Protocols::InteractionModel::Status::Success)
821+
{
822+
ChipLogDetail(NotSpecified, "Invalid value/endpoint to set.");
823+
return;
824+
}
825+
826+
EmitOccupancyChangedEvent(endpointId, newOccupancyValue);
827+
828+
if (1 == newOccupancyValue)
829+
{
830+
uint16_t * holdTime = chip::app::Clusters::OccupancySensing::GetHoldTimeForEndpoint(endpointId);
831+
if (holdTime != nullptr)
832+
{
833+
CHIP_ERROR err = chip::DeviceLayer::SystemLayer().StartTimer(
834+
chip::System::Clock::Seconds16(*holdTime), AllClustersAppCommandHandler::OccupancyPresentTimerHandler,
835+
reinterpret_cast<void *>(static_cast<uintptr_t>(endpointId)));
836+
ChipLogDetail(NotSpecified, "Start HoldTime timer");
837+
if (CHIP_NO_ERROR != err)
838+
{
839+
ChipLogError(NotSpecified, "Failed to start HoldTime timer.");
840+
}
841+
}
842+
}
843+
}
844+
845+
void AllClustersAppCommandHandler::OccupancyPresentTimerHandler(System::Layer * systemLayer, void * appState)
846+
{
847+
EndpointId endpointId = static_cast<EndpointId>(reinterpret_cast<uintptr_t>(appState));
848+
chip::BitMask<Clusters::OccupancySensing::OccupancyBitmap> currentOccupancy;
849+
850+
Protocols::InteractionModel::Status status = OccupancySensing::Attributes::Occupancy::Get(endpointId, &currentOccupancy);
851+
VerifyOrDie(status == Protocols::InteractionModel::Status::Success);
852+
853+
uint8_t clearValue = 0;
854+
if (!currentOccupancy.Has(Clusters::OccupancySensing::OccupancyBitmap::kOccupied))
855+
{
856+
return;
857+
}
858+
859+
status = OccupancySensing::Attributes::Occupancy::Set(endpointId, clearValue);
860+
if (status != Protocols::InteractionModel::Status::Success)
861+
{
862+
ChipLogDetail(NotSpecified, "Failed to set occupancy state.");
863+
}
864+
else
865+
{
866+
ChipLogDetail(NotSpecified, "Set Occupancy attribute to clear");
867+
EmitOccupancyChangedEvent(endpointId, clearValue);
868+
}
869+
}
870+
772871
void AllClustersCommandDelegate::OnEventCommandReceived(const char * json)
773872
{
774873
auto handler = AllClustersAppCommandHandler::FromJSON(json);

examples/all-clusters-app/linux/AllClustersCommandDelegate.h

+6
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,12 @@ class AllClustersAppCommandHandler
115115
* Should be called when it is necessary to change the operational state as a manual operation.
116116
*/
117117
void OnOvenOperationalStateChange(std::string device, std::string operation, Json::Value param);
118+
119+
/**
120+
* Should be called when it is necessary to change the Occupancy attribute.
121+
*/
122+
void HandleSetOccupancyChange(chip::EndpointId endpointId, uint8_t occupancyValue);
123+
static void OccupancyPresentTimerHandler(chip::System::Layer * systemLayer, void * appState);
118124
};
119125

120126
class AllClustersCommandDelegate : public NamedPipeCommandDelegate

src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.cpp

+17-5
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,10 @@ CHIP_ERROR Instance::Write(const ConcreteDataAttributePath & aPath, AttributeVal
9494

9595
switch (aPath.mAttributeId)
9696
{
97-
case Attributes::HoldTime::Id: {
98-
97+
case Attributes::HoldTime::Id:
98+
case Attributes::PIROccupiedToUnoccupiedDelay::Id:
99+
case Attributes::UltrasonicOccupiedToUnoccupiedDelay::Id:
100+
case Attributes::PhysicalContactOccupiedToUnoccupiedDelay::Id: {
99101
uint16_t newHoldTime;
100102

101103
ReturnErrorOnFailure(aDecoder.Decode(newHoldTime));
@@ -173,16 +175,26 @@ uint16_t * GetHoldTimeForEndpoint(EndpointId endpoint)
173175
return &sHoldTime[index];
174176
}
175177

176-
CHIP_ERROR SetHoldTime(EndpointId endpointId, const uint16_t & holdTime)
178+
CHIP_ERROR SetHoldTime(EndpointId endpointId, uint16_t newHoldTime)
177179
{
178180
VerifyOrReturnError(kInvalidEndpointId != endpointId, CHIP_ERROR_INVALID_ARGUMENT);
179181

180182
uint16_t * holdTimeForEndpoint = GetHoldTimeForEndpoint(endpointId);
181183
VerifyOrReturnError(holdTimeForEndpoint != nullptr, CHIP_ERROR_INVALID_ARGUMENT);
182184

183-
*holdTimeForEndpoint = holdTime;
185+
uint16_t previousHoldTime = *holdTimeForEndpoint;
186+
*holdTimeForEndpoint = newHoldTime;
187+
188+
if (previousHoldTime != newHoldTime)
189+
{
190+
MatterReportingAttributeChangeCallback(endpointId, OccupancySensing::Id, Attributes::HoldTime::Id);
191+
}
184192

185-
MatterReportingAttributeChangeCallback(endpointId, OccupancySensing::Id, Attributes::HoldTime::Id);
193+
// Blindly try to write RAM-backed legacy attributes (will fail silently if absent)
194+
// to keep them in sync.
195+
(void) Attributes::PIROccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime);
196+
(void) Attributes::UltrasonicOccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime);
197+
(void) Attributes::PhysicalContactOccupiedToUnoccupiedDelay::Set(endpointId, newHoldTime);
186198

187199
return CHIP_NO_ERROR;
188200
}

src/app/clusters/occupancy-sensor-server/occupancy-sensor-server.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class Instance : public AttributeAccessInterface
5454

5555
CHIP_ERROR SetHoldTimeLimits(EndpointId endpointId, const Structs::HoldTimeLimitsStruct::Type & holdTimeLimits);
5656

57-
CHIP_ERROR SetHoldTime(EndpointId endpointId, const uint16_t & holdTime);
57+
CHIP_ERROR SetHoldTime(EndpointId endpointId, uint16_t newHoldTime);
5858

5959
Structs::HoldTimeLimitsStruct::Type * GetHoldTimeLimitsForEndpoint(EndpointId endpoint);
6060

0 commit comments

Comments
 (0)