|
19 | 19 | #include "AllClustersCommandDelegate.h"
|
20 | 20 |
|
21 | 21 | #include <app-common/zap-generated/attributes/Accessors.h>
|
| 22 | +#include <app/EventLogging.h> |
22 | 23 | #include <app/clusters/general-diagnostics-server/general-diagnostics-server.h>
|
| 24 | +#include <app/clusters/occupancy-sensor-server/occupancy-sensor-server.h> |
23 | 25 | #include <app/clusters/smoke-co-alarm-server/smoke-co-alarm-server.h>
|
24 | 26 | #include <app/clusters/software-diagnostics-server/software-diagnostics-server.h>
|
25 | 27 | #include <app/clusters/switch-server/switch-server.h>
|
@@ -246,6 +248,24 @@ void HandleSimulateLatchPosition(Json::Value & jsonValue)
|
246 | 248 | }
|
247 | 249 | }
|
248 | 250 |
|
| 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 | + |
249 | 269 | } // namespace
|
250 | 270 |
|
251 | 271 | AllClustersAppCommandHandler * AllClustersAppCommandHandler::FromJSON(const char * json)
|
@@ -407,6 +427,20 @@ void AllClustersAppCommandHandler::HandleCommand(intptr_t context)
|
407 | 427 | {
|
408 | 428 | HandleSimulateLatchPosition(self->mJsonValue);
|
409 | 429 | }
|
| 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 | + } |
410 | 444 | else
|
411 | 445 | {
|
412 | 446 | ChipLogError(NotSpecified, "Unhandled command '%s': this hould never happen", name.c_str());
|
@@ -769,6 +803,71 @@ void AllClustersAppCommandHandler::OnAirQualityChange(uint32_t aNewValue)
|
769 | 803 | }
|
770 | 804 | }
|
771 | 805 |
|
| 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, ¤tOccupancy); |
| 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, ¤tOccupancy); |
| 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 | + |
772 | 871 | void AllClustersCommandDelegate::OnEventCommandReceived(const char * json)
|
773 | 872 | {
|
774 | 873 | auto handler = AllClustersAppCommandHandler::FromJSON(json);
|
|
0 commit comments