diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter index aad30bcebd8de2..29fd0a23fd21dd 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.matter @@ -3990,13 +3990,19 @@ provisional cluster ElectricalEnergyMeasurement = 145 { /** This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). */ provisional cluster DeviceEnergyManagement = 152 { - revision 2; + revision 3; + + enum AdjustmentCauseEnum : enum8 { + kLocalOptimization = 0; + kGridOptimization = 1; + } enum CauseEnum : enum8 { kNormalCompletion = 0; kOffline = 1; kFault = 2; kUserOptOut = 3; + kCancelled = 4; } enum CostTypeEnum : enum8 { @@ -4010,9 +4016,8 @@ provisional cluster DeviceEnergyManagement = 152 { kOffline = 0; kOnline = 1; kFault = 2; - kUserOptOut = 3; - kPowerAdjustActive = 4; - kPaused = 5; + kPowerAdjustActive = 3; + kPaused = 4; } enum ESATypeEnum : enum8 { @@ -4033,11 +4038,27 @@ provisional cluster DeviceEnergyManagement = 152 { kOther = 255; } + enum ForecastUpdateReasonEnum : enum8 { + kInternalOptimization = 0; + kLocalOptimization = 1; + kGridOptimization = 2; + } + + enum OptOutStateEnum : enum8 { + kNoOptOut = 0; + kLocalOptOut = 1; + kGridOptOut = 2; + kOptOut = 3; + } + bitmap Feature : bitmap32 { kPowerAdjustment = 0x1; kPowerForecastReporting = 0x2; kStateForecastReporting = 0x4; - kForecastAdjustment = 0x8; + kStartTimeAdjustment = 0x8; + kPausable = 0x10; + kForecastAdjustment = 0x20; + kConstraintBasedAdjustment = 0x40; } struct CostStruct { @@ -4053,9 +4074,9 @@ provisional cluster DeviceEnergyManagement = 152 { elapsed_s defaultDuration = 2; elapsed_s elapsedSlotTime = 3; elapsed_s remainingSlotTime = 4; - boolean slotIsPauseable = 5; - elapsed_s minPauseDuration = 6; - elapsed_s maxPauseDuration = 7; + optional boolean slotIsPauseable = 5; + optional elapsed_s minPauseDuration = 6; + optional elapsed_s maxPauseDuration = 7; optional int16u manufacturerESAState = 8; optional power_mw nominalPower = 9; optional power_mw minPower = 10; @@ -4077,6 +4098,7 @@ provisional cluster DeviceEnergyManagement = 152 { optional epoch_s latestEndTime = 5; boolean isPauseable = 6; SlotStruct slots[] = 7; + ForecastUpdateReasonEnum forecastUpdateReason = 8; } struct ConstraintsStruct { @@ -4113,6 +4135,7 @@ provisional cluster DeviceEnergyManagement = 152 { } info event Resumed = 3 { + CauseEnum cause = 0; } readonly attribute ESATypeEnum ESAType = 0; @@ -4122,6 +4145,7 @@ provisional cluster DeviceEnergyManagement = 152 { readonly attribute power_mw absMaxPower = 4; readonly attribute optional nullable PowerAdjustStruct powerAdjustmentCapability[] = 5; readonly attribute optional nullable ForecastStruct forecast = 6; + readonly attribute optional OptOutStateEnum optOutState = 7; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -4132,23 +4156,28 @@ provisional cluster DeviceEnergyManagement = 152 { request struct PowerAdjustRequestRequest { power_mw power = 0; elapsed_s duration = 1; + AdjustmentCauseEnum cause = 2; } request struct StartTimeAdjustRequestRequest { epoch_s requestedStartTime = 0; + AdjustmentCauseEnum cause = 1; } request struct PauseRequestRequest { elapsed_s duration = 0; + AdjustmentCauseEnum cause = 1; } request struct ModifyForecastRequestRequest { int32u forecastId = 0; SlotAdjustmentStruct slotAdjustments[] = 1; + AdjustmentCauseEnum cause = 2; } request struct RequestConstraintBasedForecastRequest { ConstraintsStruct constraints[] = 0; + AdjustmentCauseEnum cause = 1; } /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */ @@ -4165,6 +4194,8 @@ provisional cluster DeviceEnergyManagement = 152 { command ModifyForecastRequest(ModifyForecastRequestRequest): DefaultSuccess = 5; /** Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. */ command RequestConstraintBasedForecast(RequestConstraintBasedForecastRequest): DefaultSuccess = 6; + /** Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command */ + command CancelRequest(): DefaultSuccess = 7; } /** Electric Vehicle Supply Equipment (EVSE) is equipment used to charge an Electric Vehicle (EV) or Plug-In Hybrid Electric Vehicle. This cluster provides an interface to the functionality of Electric Vehicle Supply Equipment (EVSE) management. */ @@ -8012,12 +8043,13 @@ endpoint 1 { callback attribute absMaxPower; callback attribute powerAdjustmentCapability; callback attribute forecast; + callback attribute optOutState; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command PowerAdjustRequest; handle command CancelPowerAdjustRequest; @@ -8026,6 +8058,7 @@ endpoint 1 { handle command ResumeRequest; handle command ModifyForecastRequest; handle command RequestConstraintBasedForecast; + handle command CancelRequest; } server cluster EnergyEvse { diff --git a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap index 4c70ec90228595..d92f36f946b704 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -17,12 +17,6 @@ } ], "package": [ - { - "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/app-templates.json", - "type": "gen-templates-json", - "version": "chip-v1" - }, { "pathRelativity": "relativeToZap", "path": "../../../src/app/zap-templates/zcl/zcl-with-test-extensions.json", @@ -30,6 +24,12 @@ "category": "matter", "version": 1, "description": "Matter SDK ZCL data with some extensions" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" } ], "endpointTypes": [ @@ -12917,6 +12917,14 @@ "source": "client", "isIncoming": 1, "isEnabled": 1 + }, + { + "name": "CancelRequest", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 } ], "attributes": [ @@ -13032,6 +13040,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "OptOutState", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "OptOutStateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -13074,7 +13098,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": null, + "defaultValue": "0", "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -13122,7 +13146,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp index 385c1cfa43c8ee..190702c61af464 100644 --- a/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp +++ b/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp @@ -50,10 +50,10 @@ void emberAfDeviceEnergyManagementClusterInitCallback(chip::EndpointId endpointI gInstance = std::make_unique( endpointId, *gDelegate, BitMask( - DeviceEnergyManagement::Feature::kPowerForecastReporting, DeviceEnergyManagement::Feature::kStateForecastReporting, - DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kForecastAdjustment), - BitMask(OptionalCommands::kSupportsModifyForecastRequest, - OptionalCommands::kSupportsRequestConstraintBasedForecast)); + DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, + DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, + DeviceEnergyManagement::Feature::kPausable, DeviceEnergyManagement::Feature::kForecastAdjustment, + DeviceEnergyManagement::Feature::kConstraintBasedAdjustment)); if (!gInstance) { diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.matter b/examples/energy-management-app/energy-management-common/energy-management-app.matter index 6fff020aa05417..56e288bc712b9b 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.matter +++ b/examples/energy-management-app/energy-management-common/energy-management-app.matter @@ -902,13 +902,19 @@ cluster GroupKeyManagement = 63 { /** This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). */ provisional cluster DeviceEnergyManagement = 152 { - revision 2; + revision 3; + + enum AdjustmentCauseEnum : enum8 { + kLocalOptimization = 0; + kGridOptimization = 1; + } enum CauseEnum : enum8 { kNormalCompletion = 0; kOffline = 1; kFault = 2; kUserOptOut = 3; + kCancelled = 4; } enum CostTypeEnum : enum8 { @@ -922,9 +928,8 @@ provisional cluster DeviceEnergyManagement = 152 { kOffline = 0; kOnline = 1; kFault = 2; - kUserOptOut = 3; - kPowerAdjustActive = 4; - kPaused = 5; + kPowerAdjustActive = 3; + kPaused = 4; } enum ESATypeEnum : enum8 { @@ -945,11 +950,27 @@ provisional cluster DeviceEnergyManagement = 152 { kOther = 255; } + enum ForecastUpdateReasonEnum : enum8 { + kInternalOptimization = 0; + kLocalOptimization = 1; + kGridOptimization = 2; + } + + enum OptOutStateEnum : enum8 { + kNoOptOut = 0; + kLocalOptOut = 1; + kGridOptOut = 2; + kOptOut = 3; + } + bitmap Feature : bitmap32 { kPowerAdjustment = 0x1; kPowerForecastReporting = 0x2; kStateForecastReporting = 0x4; - kForecastAdjustment = 0x8; + kStartTimeAdjustment = 0x8; + kPausable = 0x10; + kForecastAdjustment = 0x20; + kConstraintBasedAdjustment = 0x40; } struct CostStruct { @@ -965,9 +986,9 @@ provisional cluster DeviceEnergyManagement = 152 { elapsed_s defaultDuration = 2; elapsed_s elapsedSlotTime = 3; elapsed_s remainingSlotTime = 4; - boolean slotIsPauseable = 5; - elapsed_s minPauseDuration = 6; - elapsed_s maxPauseDuration = 7; + optional boolean slotIsPauseable = 5; + optional elapsed_s minPauseDuration = 6; + optional elapsed_s maxPauseDuration = 7; optional int16u manufacturerESAState = 8; optional power_mw nominalPower = 9; optional power_mw minPower = 10; @@ -989,6 +1010,7 @@ provisional cluster DeviceEnergyManagement = 152 { optional epoch_s latestEndTime = 5; boolean isPauseable = 6; SlotStruct slots[] = 7; + ForecastUpdateReasonEnum forecastUpdateReason = 8; } struct ConstraintsStruct { @@ -1025,6 +1047,7 @@ provisional cluster DeviceEnergyManagement = 152 { } info event Resumed = 3 { + CauseEnum cause = 0; } readonly attribute ESATypeEnum ESAType = 0; @@ -1034,6 +1057,7 @@ provisional cluster DeviceEnergyManagement = 152 { readonly attribute power_mw absMaxPower = 4; readonly attribute optional nullable PowerAdjustStruct powerAdjustmentCapability[] = 5; readonly attribute optional nullable ForecastStruct forecast = 6; + readonly attribute optional OptOutStateEnum optOutState = 7; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -1044,23 +1068,28 @@ provisional cluster DeviceEnergyManagement = 152 { request struct PowerAdjustRequestRequest { power_mw power = 0; elapsed_s duration = 1; + AdjustmentCauseEnum cause = 2; } request struct StartTimeAdjustRequestRequest { epoch_s requestedStartTime = 0; + AdjustmentCauseEnum cause = 1; } request struct PauseRequestRequest { elapsed_s duration = 0; + AdjustmentCauseEnum cause = 1; } request struct ModifyForecastRequestRequest { int32u forecastId = 0; SlotAdjustmentStruct slotAdjustments[] = 1; + AdjustmentCauseEnum cause = 2; } request struct RequestConstraintBasedForecastRequest { ConstraintsStruct constraints[] = 0; + AdjustmentCauseEnum cause = 1; } /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */ @@ -1077,6 +1106,8 @@ provisional cluster DeviceEnergyManagement = 152 { command ModifyForecastRequest(ModifyForecastRequestRequest): DefaultSuccess = 5; /** Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. */ command RequestConstraintBasedForecast(RequestConstraintBasedForecastRequest): DefaultSuccess = 6; + /** Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command */ + command CancelRequest(): DefaultSuccess = 7; } /** Electric Vehicle Supply Equipment (EVSE) is equipment used to charge an Electric Vehicle (EV) or Plug-In Hybrid Electric Vehicle. This cluster provides an interface to the functionality of Electric Vehicle Supply Equipment (EVSE) management. */ @@ -1478,12 +1509,13 @@ endpoint 1 { callback attribute absMaxPower; callback attribute powerAdjustmentCapability; callback attribute forecast; + callback attribute optOutState; callback attribute generatedCommandList; callback attribute acceptedCommandList; callback attribute eventList; callback attribute attributeList; callback attribute featureMap; - ram attribute clusterRevision default = 2; + ram attribute clusterRevision default = 3; handle command PowerAdjustRequest; handle command CancelPowerAdjustRequest; @@ -1492,6 +1524,7 @@ endpoint 1 { handle command ResumeRequest; handle command ModifyForecastRequest; handle command RequestConstraintBasedForecast; + handle command CancelRequest; } server cluster EnergyEvse { diff --git a/examples/energy-management-app/energy-management-common/energy-management-app.zap b/examples/energy-management-app/energy-management-common/energy-management-app.zap index 92430d761980ab..d00270b2ed5717 100644 --- a/examples/energy-management-app/energy-management-common/energy-management-app.zap +++ b/examples/energy-management-app/energy-management-common/energy-management-app.zap @@ -2581,6 +2581,14 @@ "source": "client", "isIncoming": 1, "isEnabled": 1 + }, + { + "name": "CancelRequest", + "code": 7, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 } ], "attributes": [ @@ -2696,6 +2704,22 @@ "maxInterval": 65534, "reportableChange": 0 }, + { + "name": "OptOutState", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "OptOutStateEnum", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, { "name": "GeneratedCommandList", "code": 65528, @@ -2786,7 +2810,7 @@ "storageOption": "RAM", "singleton": 0, "bounded": 0, - "defaultValue": "2", + "defaultValue": "3", "reportable": 1, "minInterval": 1, "maxInterval": 65534, diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h index 464a683510b3d7..973e1e622576a4 100644 --- a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h +++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h @@ -36,16 +36,19 @@ namespace DeviceEnergyManagement { class DeviceEnergyManagementDelegate : public DeviceEnergyManagement::Delegate { public: - virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration) override; + virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration, AdjustmentCauseEnum cause) override; virtual Status CancelPowerAdjustRequest() override; - virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime) override; - virtual Status PauseRequest(const uint32_t duration) override; + virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime, AdjustmentCauseEnum cause) override; + virtual Status PauseRequest(const uint32_t duration, AdjustmentCauseEnum cause) override; virtual Status ResumeRequest() override; virtual Status ModifyForecastRequest(const uint32_t forecastId, - const DataModel::DecodableList & slotAdjustments) override; - virtual Status RequestConstraintBasedForecast( - const DataModel::DecodableList & constraints) override; + const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) override; + virtual Status + RequestConstraintBasedForecast(const DataModel::DecodableList & constraints, + AdjustmentCauseEnum cause) override; + virtual Status CancelRequest() override; // ------------------------------------------------------------------ // Get attribute methods @@ -56,6 +59,7 @@ class DeviceEnergyManagementDelegate : public DeviceEnergyManagement::Delegate virtual int64_t GetAbsMaxPower() override; virtual Attributes::PowerAdjustmentCapability::TypeInfo::Type GetPowerAdjustmentCapability() override; virtual DataModel::Nullable GetForecast() override; + virtual OptOutStateEnum GetOptOutState() override; // ------------------------------------------------------------------ // Set attribute methods @@ -75,6 +79,8 @@ class DeviceEnergyManagementDelegate : public DeviceEnergyManagement::Delegate int64_t mAbsMaxPower; Attributes::PowerAdjustmentCapability::TypeInfo::Type mPowerAdjustmentCapability; DataModel::Nullable mForecast; + // Default to NoOptOut + OptOutStateEnum mOptOutState = OptOutStateEnum::kNoOptOut; }; } // namespace DeviceEnergyManagement diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h index 6d131dd4ae90fa..aec875ff0d1f99 100644 --- a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h +++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h @@ -31,9 +31,8 @@ using namespace chip::app::Clusters::DeviceEnergyManagement; class DeviceEnergyManagementManager : public Instance { public: - DeviceEnergyManagementManager(EndpointId aEndpointId, DeviceEnergyManagementDelegate & aDelegate, Feature aFeature, - OptionalCommands aOptionalCmds) : - DeviceEnergyManagement::Instance(aEndpointId, aDelegate, aFeature, aOptionalCmds) + DeviceEnergyManagementManager(EndpointId aEndpointId, DeviceEnergyManagementDelegate & aDelegate, Feature aFeature) : + DeviceEnergyManagement::Instance(aEndpointId, aDelegate, aFeature) { mDelegate = &aDelegate; } diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp index 4d4d9bf05bbdbb..28c6b8942ff493 100644 --- a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp +++ b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp @@ -49,7 +49,7 @@ using CostsList = DataModel::List; * 6) generate a PowerAdjustEnd event with cause NormalCompletion * 7) if necessary, update the forecast with new expected end time */ -Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t power, const uint32_t duration) +Status DeviceEnergyManagementDelegate::PowerAdjustRequest(const int64_t power, const uint32_t duration, AdjustmentCauseEnum cause) { Status status = Status::UnsupportedCommand; // Status::Success; @@ -98,7 +98,7 @@ Status DeviceEnergyManagementDelegate::CancelPowerAdjustRequest() * 1) update the forecast attribute with the revised start time * 2) send a callback notification to the appliance so it can refresh its internal schedule */ -Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t requestedStartTime) +Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t requestedStartTime, AdjustmentCauseEnum cause) { DataModel::Nullable forecast = GetForecast(); @@ -136,7 +136,7 @@ Status DeviceEnergyManagementDelegate::StartTimeAdjustRequest(const uint32_t req * 6) generate a Resumed event * 7) if necessary, update the forecast with new expected end time */ -Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t duration) +Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t duration, AdjustmentCauseEnum cause) { Status status = Status::UnsupportedCommand; // Status::Success; // TODO: implement the behaviour above @@ -181,7 +181,8 @@ Status DeviceEnergyManagementDelegate::ResumeRequest() * 3) notify the appliance to follow the revised schedule */ Status DeviceEnergyManagementDelegate::ModifyForecastRequest( - const uint32_t forecastId, const DataModel::DecodableList & slotAdjustments) + const uint32_t forecastId, const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) { Status status = Status::UnsupportedCommand; // Status::Success; @@ -202,7 +203,25 @@ Status DeviceEnergyManagementDelegate::ModifyForecastRequest( * 3) notify the appliance to follow the revised schedule */ Status DeviceEnergyManagementDelegate::RequestConstraintBasedForecast( - const DataModel::DecodableList & constraints) + const DataModel::DecodableList & constraints, AdjustmentCauseEnum cause) +{ + Status status = Status::UnsupportedCommand; // Status::Success; + // TODO: implement the behaviour above + return status; +} + +/** + * @brief Delegate handler for CancelRequest + * + * Note: This is a more complex use-case and requires higher-level work by the delegate. + * + * It SHALL: + * 1) Check if the forecastUpdateReason was already InternalOptimization (and reject the command) + * 2) Update its forecast (based on its optimization strategy) ignoring previous requests + * 3) Update its Forecast attribute to match its new intended operation, and update the + * ForecastStruct.ForecastUpdateReason to `Internal Optimization`. + */ +Status DeviceEnergyManagementDelegate::CancelRequest() { Status status = Status::UnsupportedCommand; // Status::Success; // TODO: implement the behaviour above @@ -246,6 +265,11 @@ DataModel::Nullable DeviceEnergyManagementDelegat return mForecast; } +OptOutStateEnum DeviceEnergyManagementDelegate::GetOptOutState() +{ + return mOptOutState; +} + // ------------------------------------------------------------------ // Set attribute methods diff --git a/examples/energy-management-app/linux/args.gni b/examples/energy-management-app/linux/args.gni index cca4c8f39e09fe..b7c71c3097a680 100644 --- a/examples/energy-management-app/linux/args.gni +++ b/examples/energy-management-app/linux/args.gni @@ -29,3 +29,4 @@ chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] matter_enable_tracing_support = true chip_enable_read_client = false +chip_enable_energy_evse_trigger = true diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp index 23ec97e267f45d..df544484975f4f 100644 --- a/examples/energy-management-app/linux/main.cpp +++ b/examples/energy-management-app/linux/main.cpp @@ -73,11 +73,10 @@ CHIP_ERROR DeviceEnergyManagementInit() gDEMInstance = std::make_unique( EndpointId(ENERGY_EVSE_ENDPOINT), *gDEMDelegate, BitMask( - DeviceEnergyManagement::Feature::kPowerForecastReporting, DeviceEnergyManagement::Feature::kStateForecastReporting, - DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kForecastAdjustment), - BitMask( - DeviceEnergyManagement::OptionalCommands::kSupportsModifyForecastRequest, - DeviceEnergyManagement::OptionalCommands::kSupportsRequestConstraintBasedForecast)); + DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kPowerForecastReporting, + DeviceEnergyManagement::Feature::kStateForecastReporting, DeviceEnergyManagement::Feature::kStartTimeAdjustment, + DeviceEnergyManagement::Feature::kPausable, DeviceEnergyManagement::Feature::kForecastAdjustment, + DeviceEnergyManagement::Feature::kConstraintBasedAdjustment)); if (!gDEMInstance) { diff --git a/examples/platform/linux/CommissioneeShellCommands.cpp b/examples/platform/linux/CommissioneeShellCommands.cpp index f04051b36e8f88..18f8355080201d 100644 --- a/examples/platform/linux/CommissioneeShellCommands.cpp +++ b/examples/platform/linux/CommissioneeShellCommands.cpp @@ -37,7 +37,8 @@ namespace chip { namespace Shell { #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT -static CHIP_ERROR SendUDC(bool printHeader, chip::Transport::PeerAddress commissioner) +static CHIP_ERROR SendUDC(bool printHeader, chip::Transport::PeerAddress commissioner, + Protocols::UserDirectedCommissioning::IdentificationDeclaration id) { streamer_t * sout = streamer_get(); @@ -46,7 +47,7 @@ static CHIP_ERROR SendUDC(bool printHeader, chip::Transport::PeerAddress commiss streamer_printf(sout, "SendUDC: "); } - Server::GetInstance().SendUserDirectedCommissioningRequest(commissioner); + Server::GetInstance().SendUserDirectedCommissioningRequest(commissioner, id); streamer_printf(sout, "done\r\n"); @@ -60,6 +61,13 @@ static CHIP_ERROR PrintAllCommands() streamer_printf(sout, " help Usage: commissionee \r\n"); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT streamer_printf(sout, " sendudc
Send UDC message to address. Usage: commissionee sendudc ::1 5543\r\n"); + streamer_printf(sout, " udccancel
Send UDC cancel message to address. Usage: cast udccancel ::1 5543\r\n"); + streamer_printf(sout, + " udccommissionerpasscode
[CommissionerPasscodeReady] [PairingHint] [PairingInst] Send UDC " + "commissioner passcode message to address. Usage: udccommissionerpasscode ::1 5543 t 5 HelloWorld\r\n"); + streamer_printf(sout, + " testudc
[NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst] Send UDC " + "message to address. Usage: cast testudc ::1 5543 t t 5 HelloWorld\r\n"); #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // TODO: Figure out whether setdiscoverytimeout is a reasonable thing to do // at all, and if so what semantics it should have. Presumably it should @@ -92,12 +100,93 @@ static CHIP_ERROR CommissioneeHandler(int argc, char ** argv) } #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT if (strcmp(argv[0], "sendudc") == 0) + { + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + return SendUDC(true, chip::Transport::PeerAddress::UDP(commissioner, port), id); + } + if (strcmp(argv[0], "udccancel") == 0) + { + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + id.SetCancelPasscode(true); + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); + } + if (strcmp(argv[0], "udccommissionerpasscode") == 0) { char * eptr; chip::Inet::IPAddress commissioner; chip::Inet::IPAddress::FromString(argv[1], commissioner); uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); - return SendUDC(true, chip::Transport::PeerAddress::UDP(commissioner, port)); + + // udccommissionerpasscode
[CommissionerPasscodeReady] [PairingHint] [PairingInst] + // ex. udccommissionerpasscode
t 5 'hello world' + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + id.SetCommissionerPasscode(true); + if (argc > 3) + { + id.SetCommissionerPasscodeReady(strcmp(argv[3], "t") == 0); + } + if (argc > 4) + { + uint16_t hint = (uint16_t) strtol(argv[4], &eptr, 10); + id.SetPairingHint(hint); + } + if (argc > 5) + { + id.SetPairingInst(argv[5]); + } + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); + } + if (strcmp(argv[0], "testudc") == 0) + { + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + // sendudc
[NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst] + // ex. sendudc
t t 111 5 'hello world' + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + if (argc > 3) + { + id.SetNoPasscode(strcmp(argv[3], "t") == 0); + } + if (argc > 4) + { + id.SetCdUponPasscodeDialog(strcmp(argv[4], "t") == 0); + } + if (argc > 5) + { + uint16_t vid = (uint16_t) strtol(argv[5], &eptr, 10); + Protocols::UserDirectedCommissioning::TargetAppInfo info; + info.vendorId = vid; + id.AddTargetAppInfo(info); + } + if (argc > 6) + { + uint16_t hint = (uint16_t) strtol(argv[6], &eptr, 10); + id.SetPairingHint(hint); + } + if (argc > 7) + { + id.SetPairingInst(argv[7]); + } + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); } #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT // TODO: Figure out whether setdiscoverytimeout is a reasonable thing to do diff --git a/examples/platform/linux/ControllerShellCommands.cpp b/examples/platform/linux/ControllerShellCommands.cpp index 3d5af4a3a387a1..27116b28c15256 100644 --- a/examples/platform/linux/ControllerShellCommands.cpp +++ b/examples/platform/linux/ControllerShellCommands.cpp @@ -266,8 +266,8 @@ static CHIP_ERROR ControllerHandler(int argc, char ** argv) { if (argc >= 3) { - uint32_t pincode = (uint32_t) strtol(argv[2], &eptr, 10); - GetCommissionerDiscoveryController()->CommissionWithPincode(pincode); + uint32_t passcode = (uint32_t) strtol(argv[2], &eptr, 10); + GetCommissionerDiscoveryController()->CommissionWithPasscode(passcode); return CHIP_NO_ERROR; } GetCommissionerDiscoveryController()->Ok(); @@ -280,15 +280,15 @@ static CHIP_ERROR ControllerHandler(int argc, char ** argv) } else if (strcmp(argv[0], "udc-commission") == 0) { - // udc-commission pincode index + // udc-commission passcode index if (argc < 3) { return PrintAllCommands(); } char * eptr; - uint32_t pincode = (uint32_t) strtol(argv[1], &eptr, 10); - size_t index = (size_t) strtol(argv[2], &eptr, 10); - return pairUDC(true, pincode, index); + uint32_t passcode = (uint32_t) strtol(argv[1], &eptr, 10); + size_t index = (size_t) strtol(argv[2], &eptr, 10); + return pairUDC(true, passcode, index); } #endif // CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp index 29fff989fdff57..3d29126e5b838a 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.cpp @@ -116,7 +116,8 @@ void JNIMyUserPrompter::PromptForCommissionOKPermission(uint16_t vendorId, uint1 * If user responds with Cancel then implementor calls UserPrompterResolver.OnPinCodeDeclined(); * */ -void JNIMyUserPrompter::PromptForCommissionPincode(uint16_t vendorId, uint16_t productId, const char * commissioneeName) +void JNIMyUserPrompter::PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint16_t pairingHint, const char * pairingInstruction) { CHIP_ERROR err = CHIP_NO_ERROR; JNIEnv * env = JniReferences::GetInstance().GetEnvForCurrentThread(); @@ -148,6 +149,50 @@ void JNIMyUserPrompter::PromptForCommissionPincode(uint16_t vendorId, uint16_t p } } +/** + * Called to when CancelCommissioning is received via UDC. + * Indicates that commissioner can stop showing the passcode entry or display dialog. + * For example, can show text such as "Commissioning cancelled by client" before hiding dialog. + */ +void JNIMyUserPrompter::HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) +{ + // TODO + ChipLogError(Zcl, "JNIMyUserPrompter::HidePromptsOnCancel Needs Implementation"); +} + +/** + * Return true if this UserPrompter displays QR code along with passcode + * When PromptWithCommissionerPasscode is called during Commissioner Passcode functionality. + */ +bool JNIMyUserPrompter::DisplaysPasscodeAndQRCode() +{ + // TODO + ChipLogError(Zcl, "JNIMyUserPrompter::DisplaysPasscodeAndQRCode Needs Implementation"); + return false; +} + +/** + * Called to display the given setup passcode to the user, + * for commissioning the given commissioneeName with the given vendorId and productId, + * and provide instructions for where to enter it in the commissionee (when pairingHint and pairingInstruction are provided). + * For example "Casting Passcode: [passcode]. For more instructions, click here." + */ +void JNIMyUserPrompter::PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint32_t passcode, uint16_t pairingHint, const char * pairingInstruction) +{ + // TODO + ChipLogError(Zcl, "JNIMyUserPrompter::PromptWithCommissionerPasscode Needs Implementation"); +} + +/** + * Called to alert the user that commissioning has begun." + */ +void JNIMyUserPrompter::PromptCommissioningStarted(uint16_t vendorId, uint16_t productId, const char * commissioneeName) +{ + // TODO + ChipLogError(Zcl, "JNIMyUserPrompter::PromptCommissioningStarted Needs Implementation"); +} + /* * Called to notify the user that commissioning succeeded. It can be in form of UI Notification. */ diff --git a/examples/tv-app/android/java/MyUserPrompter-JNI.h b/examples/tv-app/android/java/MyUserPrompter-JNI.h index cecdcb305643d2..f4d93ad49b10e1 100644 --- a/examples/tv-app/android/java/MyUserPrompter-JNI.h +++ b/examples/tv-app/android/java/MyUserPrompter-JNI.h @@ -23,9 +23,16 @@ class JNIMyUserPrompter : public UserPrompter { public: + // TODO JNIMyUserPrompter(jobject prompter); void PromptForCommissionOKPermission(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; - void PromptForCommissionPincode(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; + void PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint16_t pairingHint, + const char * pairingInstruction) override; + void HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; + bool DisplaysPasscodeAndQRCode() override; + void PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, uint32_t passcode, + uint16_t pairingHint, const char * pairingInstruction) override; + void PromptCommissioningStarted(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; void PromptCommissioningSucceeded(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override; void PromptCommissioningFailed(const char * commissioneeName, CHIP_ERROR error) override; diff --git a/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp b/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp index ebe342da2f4a43..2e6bd0aa1f54e3 100644 --- a/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp +++ b/examples/tv-app/android/java/MyUserPrompterResolver-JNI.cpp @@ -34,7 +34,7 @@ JNI_METHOD(void, OnPinCodeEntered)(JNIEnv *, jobject, jint jPinCode) chip::DeviceLayer::StackLock lock; uint32_t pinCode = (uint32_t) jPinCode; ChipLogProgress(Zcl, "OnPinCodeEntered %d", pinCode); - GetCommissionerDiscoveryController()->CommissionWithPincode(pinCode); + GetCommissionerDiscoveryController()->CommissionWithPasscode(pinCode); #endif } diff --git a/examples/tv-app/android/java/TVApp-JNI.cpp b/examples/tv-app/android/java/TVApp-JNI.cpp index d7081419c0c645..f8afdfeb9c3b5f 100644 --- a/examples/tv-app/android/java/TVApp-JNI.cpp +++ b/examples/tv-app/android/java/TVApp-JNI.cpp @@ -189,11 +189,23 @@ JNI_METHOD(void, setChipDeviceEventProvider)(JNIEnv *, jobject, jobject provider } #if CHIP_DEVICE_CONFIG_APP_PLATFORM_ENABLED -class MyPincodeService : public PincodeService +class MyPincodeService : public PasscodeService { - uint32_t FetchCommissionPincodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) override + bool HasTargetContentApp(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo & info, uint32_t & passcode) override { - return ContentAppPlatform::GetInstance().GetPincodeFromContentApp(vendorId, productId, rotatingId); + return ContentAppPlatform::GetInstance().HasTargetContentApp(vendorId, productId, rotatingId, info, passcode); + } + + uint32_t GetCommissionerPasscode(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId) override + { + // TODO: randomly generate this value + return 12345678; + } + + uint32_t FetchCommissionPasscodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) override + { + return ContentAppPlatform::GetInstance().GetPasscodeFromContentApp(vendorId, productId, rotatingId); } }; MyPincodeService gMyPincodeService; @@ -329,7 +341,7 @@ void TvAppJNI::InitializeCommissioner(JNIMyUserPrompter * userPrompter) CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController(); if (cdc != nullptr && userPrompter != nullptr) { - cdc->SetPincodeService(&gMyPincodeService); + cdc->SetPasscodeService(&gMyPincodeService); cdc->SetUserPrompter(userPrompter); cdc->SetPostCommissioningListener(&gMyPostCommissioningListener); } diff --git a/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h b/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h index 99274da0114257..e5ec3f064a2fbf 100644 --- a/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h +++ b/examples/tv-app/tv-common/include/CHIPProjectAppConfig.h @@ -30,6 +30,9 @@ // TVs need to be commissioners and likely want to be discoverable #define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY 1 +// TVs will often enable this feature +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_PASSCODE 1 + // TVs need to be both commissioners and commissionees #define CHIP_DEVICE_CONFIG_ENABLE_BOTH_COMMISSIONER_AND_COMMISSIONEE 1 diff --git a/examples/tv-app/tv-common/src/AppTv.cpp b/examples/tv-app/tv-common/src/AppTv.cpp index ae87badcbcc1e4..8cd0cd409b783a 100644 --- a/examples/tv-app/tv-common/src/AppTv.cpp +++ b/examples/tv-app/tv-common/src/AppTv.cpp @@ -62,7 +62,27 @@ class MyUserPrompter : public UserPrompter } // tv should override this with a dialog prompt - inline void PromptForCommissionPincode(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override + inline void PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint16_t pairingHint, const char * pairingInstruction) override + { + return; + } + + // tv should override this with a dialog prompt + inline void HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override { return; } + + // set to true when TV displays both QR and Passcode during Commissioner Passcode display. + inline bool DisplaysPasscodeAndQRCode() override { return true; } + + // tv should override this with a dialog prompt + inline void PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint32_t passcode, uint16_t pairingHint, const char * pairingInstruction) override + { + return; + } + + // tv should override this with a dialog prompt + inline void PromptCommissioningStarted(uint16_t vendorId, uint16_t productId, const char * commissioneeName) override { return; } @@ -79,14 +99,26 @@ class MyUserPrompter : public UserPrompter MyUserPrompter gMyUserPrompter; -class MyPincodeService : public PincodeService +class MyPasscodeService : public PasscodeService { - uint32_t FetchCommissionPincodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) override + bool HasTargetContentApp(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo & info, uint32_t & passcode) override + { + return ContentAppPlatform::GetInstance().HasTargetContentApp(vendorId, productId, rotatingId, info, passcode); + } + + uint32_t GetCommissionerPasscode(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId) override + { + // TODO: randomly generate this value + return 12345678; + } + + uint32_t FetchCommissionPasscodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) override { - return ContentAppPlatform::GetInstance().GetPincodeFromContentApp(vendorId, productId, rotatingId); + return ContentAppPlatform::GetInstance().GetPasscodeFromContentApp(vendorId, productId, rotatingId); } }; -MyPincodeService gMyPincodeService; +MyPasscodeService gMyPasscodeService; class MyPostCommissioningListener : public PostCommissioningListener { @@ -558,7 +590,7 @@ CHIP_ERROR AppTvInit() CommissionerDiscoveryController * cdc = GetCommissionerDiscoveryController(); if (cdc != nullptr) { - cdc->SetPincodeService(&gMyPincodeService); + cdc->SetPasscodeService(&gMyPasscodeService); cdc->SetUserPrompter(&gMyUserPrompter); cdc->SetPostCommissioningListener(&gMyPostCommissioningListener); } diff --git a/examples/tv-casting-app/linux/CastingShellCommands.cpp b/examples/tv-casting-app/linux/CastingShellCommands.cpp index 136c0fef46625f..f6b245b42dc13a 100644 --- a/examples/tv-casting-app/linux/CastingShellCommands.cpp +++ b/examples/tv-casting-app/linux/CastingShellCommands.cpp @@ -60,6 +60,13 @@ static CHIP_ERROR PrintAllCommands() sout, " access Read and display clusters on each endpoint for . Usage: cast access 0xFFFFFFEFFFFFFFFF\r\n"); streamer_printf(sout, " sendudc
Send UDC message to address. Usage: cast sendudc ::1 5543\r\n"); + streamer_printf(sout, " udccancel
Send UDC cancel message to address. Usage: cast udccancel ::1 5543\r\n"); + streamer_printf(sout, + " udccommissionerpasscode
[CommissionerPasscodeReady] [PairingHint] [PairingInst] Send UDC " + "commissioner passcode message to address. Usage: udccommissionerpasscode ::1 5543 t 5 HelloWorld\r\n"); + streamer_printf(sout, + " testudc
[NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst] Send UDC " + "message to address. Usage: cast testudc ::1 5543 t t 5 HelloWorld\r\n"); streamer_printf( sout, " cluster [clustercommand] Send cluster command. Usage: cast cluster keypadinput send-key 1 18446744004990074879 1\r\n"); @@ -148,6 +155,84 @@ static CHIP_ERROR CastingHandler(int argc, char ** argv) return CastingServer::GetInstance()->SendUserDirectedCommissioningRequest( chip::Transport::PeerAddress::UDP(commissioner, port)); } + if (strcmp(argv[0], "udccancel") == 0) + { + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + id.SetCancelPasscode(true); + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); + } + if (strcmp(argv[0], "udccommissionerpasscode") == 0) + { + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + // udccommissionerpasscode
[CommissionerPasscodeReady] [PairingHint] [PairingInst] + // ex. udccommissionerpasscode
t 5 'hello world' + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + id.SetCommissionerPasscode(true); + if (argc > 3) + { + id.SetCommissionerPasscodeReady(strcmp(argv[3], "t") == 0); + } + if (argc > 4) + { + uint16_t hint = (uint16_t) strtol(argv[4], &eptr, 10); + id.SetPairingHint(hint); + } + if (argc > 5) + { + id.SetPairingInst(argv[5]); + } + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); + } + if (strcmp(argv[0], "testudc") == 0) + { + char * eptr; + chip::Inet::IPAddress commissioner; + chip::Inet::IPAddress::FromString(argv[1], commissioner); + uint16_t port = (uint16_t) strtol(argv[2], &eptr, 10); + + // sendudc
[NoPasscode] [CdUponPasscodeDialog] [vid] [PairingHint] [PairingInst] + // ex. sendudc
t t 111 5 'hello world' + + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + if (argc > 3) + { + id.SetNoPasscode(strcmp(argv[3], "t") == 0); + } + if (argc > 4) + { + id.SetCdUponPasscodeDialog(strcmp(argv[4], "t") == 0); + } + if (argc > 5) + { + uint16_t vid = (uint16_t) strtol(argv[5], &eptr, 10); + Protocols::UserDirectedCommissioning::TargetAppInfo info; + info.vendorId = vid; + id.AddTargetAppInfo(info); + } + if (argc > 6) + { + uint16_t hint = (uint16_t) strtol(argv[6], &eptr, 10); + id.SetPairingHint(hint); + } + if (argc > 7) + { + id.SetPairingInst(argv[7]); + } + return Server::GetInstance().SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress::UDP(commissioner, port), + id); + } #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT if (strcmp(argv[0], "print-bindings") == 0) { diff --git a/examples/tv-casting-app/tv-casting-common/BUILD.gn b/examples/tv-casting-app/tv-casting-common/BUILD.gn index d9c391b1e1b037..e8b62bce23969f 100644 --- a/examples/tv-casting-app/tv-casting-common/BUILD.gn +++ b/examples/tv-casting-app/tv-casting-common/BUILD.gn @@ -52,6 +52,8 @@ chip_data_model("tv-casting-common") { "${chip_root}/src/controller/ExamplePersistentStorage.h", "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp", "${chip_root}/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp", + "clusters/content-app-observer/ContentAppObserver.cpp", + "clusters/content-app-observer/ContentAppObserver.h", "commands/clusters/ModelCommand.cpp", "commands/common/CHIPCommand.cpp", "include/AppParams.h", @@ -89,6 +91,7 @@ chip_data_model("tv-casting-common") { "src/TargetNavigator.cpp", "src/TargetVideoPlayerInfo.cpp", "src/WakeOnLan.cpp", + "src/ZCLCallbacks.cpp", ] # Add simplified casting API files here diff --git a/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp new file mode 100644 index 00000000000000..a6010a54b0a0f5 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.cpp @@ -0,0 +1,50 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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 "ContentAppObserver.h" + +#include +#include + +using namespace std; +using namespace chip; +using namespace chip::app::Clusters::ContentAppObserver; + +ContentAppObserverManager::ContentAppObserverManager() +{ + // Create Test Data +} + +void ContentAppObserverManager::HandleContentAppMessage(chip::app::CommandResponseHelper & helper, + const chip::Optional & data, + const chip::CharSpan & encodingHint) +{ + ChipLogProgress(Zcl, "ContentAppObserverManager::HandleContentAppMessage"); + + string dataString(data.HasValue() ? data.Value().data() : "", data.HasValue() ? data.Value().size() : 0); + string encodingHintString(encodingHint.data(), encodingHint.size()); + + ChipLogProgress(Zcl, "ContentAppObserverManager::HandleContentAppMessage TEST CASE hint=%s data=%s ", + encodingHintString.c_str(), dataString.c_str()); + + ContentAppMessageResponse response; + // TODO: Insert code here + response.data = chip::MakeOptional(CharSpan::fromCharString("exampleData")); + response.encodingHint = chip::MakeOptional(CharSpan::fromCharString(encodingHintString.c_str())); + response.status = StatusEnum::kSuccess; + helper.Success(response); +} diff --git a/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.h b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.h new file mode 100644 index 00000000000000..0c0f6fb6efbaec --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/clusters/content-app-observer/ContentAppObserver.h @@ -0,0 +1,37 @@ +/* + * + * Copyright (c) 2023 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 + +using ContentAppObserverDelegate = chip::app::Clusters::ContentAppObserver::Delegate; +using ContentAppMessageResponse = chip::app::Clusters::ContentAppObserver::Commands::ContentAppMessageResponse::Type; + +class ContentAppObserverManager : public ContentAppObserverDelegate +{ +public: + ContentAppObserverManager(); + + void HandleContentAppMessage(chip::app::CommandResponseHelper & helper, + const chip::Optional & data, const chip::CharSpan & encodingHint) override; + +protected: +}; diff --git a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp index e469775ce27bc0..8ea90c21edb969 100644 --- a/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp +++ b/examples/tv-casting-app/tv-casting-common/core/CastingPlayer.cpp @@ -163,8 +163,10 @@ CHIP_ERROR CastingPlayer::SendUserDirectedCommissioningRequest() ReturnErrorOnFailure(support::ChipDeviceEventHandler::SetUdcStatus(true)); + // TODO: expose options to the higher layer + chip::Protocols::UserDirectedCommissioning::IdentificationDeclaration id; ReturnErrorOnFailure(chip::Server::GetInstance().SendUserDirectedCommissioningRequest( - chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId))); + chip::Transport::PeerAddress::UDP(*ipAddressToUse, mAttributes.port, mAttributes.interfaceId), id)); return CHIP_NO_ERROR; } diff --git a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp index fbbb9d32d8f030..e4bb7647085b40 100644 --- a/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp +++ b/examples/tv-casting-app/tv-casting-common/src/CastingServer.cpp @@ -191,7 +191,9 @@ void CastingServer::OnCommissioningSessionEstablishmentStarted() #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT CHIP_ERROR CastingServer::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner) { - return Server::GetInstance().SendUserDirectedCommissioningRequest(commissioner); + // TODO: expose options to the higher layer + Protocols::UserDirectedCommissioning::IdentificationDeclaration id; + return Server::GetInstance().SendUserDirectedCommissioningRequest(commissioner, id); } chip::Inet::IPAddress * CastingServer::getIpAddressForUDCRequest(chip::Inet::IPAddress ipAddresses[], const size_t numIPs) diff --git a/examples/tv-casting-app/tv-casting-common/src/ZCLCallbacks.cpp b/examples/tv-casting-app/tv-casting-common/src/ZCLCallbacks.cpp new file mode 100644 index 00000000000000..608d10b4ef5da2 --- /dev/null +++ b/examples/tv-casting-app/tv-casting-common/src/ZCLCallbacks.cpp @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * + * 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 implements the handler for data model messages. + */ + +#include +#include +#include +#include +#include + +#include "clusters/content-app-observer/ContentAppObserver.h" + +namespace { +static ContentAppObserverManager contentAppObserverManager; +} // namespace + +using namespace ::chip; +using namespace ::chip::app::Clusters; + +void MatterPostAttributeChangeCallback(const chip::app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, + uint8_t * value) +{ + ClusterId clusterId = attributePath.mClusterId; + AttributeId attributeId = attributePath.mAttributeId; + ChipLogProgress(Zcl, "AttributeChangeCallback cluster: " ChipLogFormatMEI " attribute:" ChipLogFormatMEI, + ChipLogValueMEI(clusterId), ChipLogValueMEI(attributeId)); +} + +/** @brief OnOff Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + * + * @param endpoint Ver.: always + * + * TODO Issue #3841 + * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster + * attributes to the default value. + * The logic here expects something similar to the deprecated Plugins callback + * emberAfPluginOnOffClusterServerPostInitCallback. + * + */ + +void emberAfContentAppObserverClusterInitCallback(EndpointId endpoint) +{ + ChipLogProgress(Zcl, "TV Casting Linux App: ContentAppObserverManager::SetDefaultDelegate"); + ContentAppObserver::SetDefaultDelegate(endpoint, &contentAppObserverManager); +} diff --git a/integrations/cloudbuild/chef.yaml b/integrations/cloudbuild/chef.yaml index 08c15518725956..45af39306ff657 100644 --- a/integrations/cloudbuild/chef.yaml +++ b/integrations/cloudbuild/chef.yaml @@ -18,7 +18,7 @@ steps: args: - >- perl -i -pe 's/^gdbgui==/# gdbgui==/' /opt/espressif/esp-idf/requirements.txt && - ./examples/chef/chef.py --build_all --build_exclude noip + ./examples/chef/chef.py --build_all --build_exclude noip --build_exclude basicvideo id: CompileAll waitFor: - Bootstrap diff --git a/src/app/app-platform/ContentAppPlatform.cpp b/src/app/app-platform/ContentAppPlatform.cpp index 4162693b19508f..fa720418264739 100644 --- a/src/app/app-platform/ContentAppPlatform.cpp +++ b/src/app/app-platform/ContentAppPlatform.cpp @@ -451,7 +451,64 @@ void ContentAppPlatform::UnsetIfCurrentApp(ContentApp * app) } } -uint32_t ContentAppPlatform::GetPincodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) +bool ContentAppPlatform::HasTargetContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo & info, uint32_t & passcode) +{ + // TODO: perform more complex search for matching apps + ContentApp * app = LoadContentAppByClient(info.vendorId, info.productId); + if (app == nullptr) + { + ChipLogProgress(DeviceLayer, "no app found for vendor id=%d \r\n", info.vendorId); + return false; + } + + if (app->GetApplicationBasicDelegate() == nullptr) + { + ChipLogProgress(DeviceLayer, "no ApplicationBasic cluster for app with vendor id=%d \r\n", info.vendorId); + return false; + } + + // first check if the vendor id matches the client + bool allow = app->GetApplicationBasicDelegate()->HandleGetVendorId() == vendorId; + if (!allow) + { + // if no match, then check allowed vendor list + for (const auto & allowedVendor : app->GetApplicationBasicDelegate()->GetAllowedVendorList()) + { + if (allowedVendor == vendorId) + { + allow = true; + break; + } + } + if (!allow) + { + ChipLogProgress( + DeviceLayer, + "no permission given by ApplicationBasic cluster on app with vendor id=%d to client with vendor id=%d\r\n", + info.vendorId, vendorId); + return false; + } + } + + if (app->GetAccountLoginDelegate() == nullptr) + { + ChipLogProgress(DeviceLayer, "no AccountLogin cluster for app with vendor id=%d \r\n", info.vendorId); + return true; + } + + static const size_t kSetupPasscodeSize = 12; + char mSetupPasscode[kSetupPasscodeSize]; + + app->GetAccountLoginDelegate()->GetSetupPin(mSetupPasscode, kSetupPasscodeSize, rotatingId); + std::string passcodeString(mSetupPasscode); + + char * eptr; + passcode = (uint32_t) strtol(passcodeString.c_str(), &eptr, 10); + return true; +} + +uint32_t ContentAppPlatform::GetPasscodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId) { ContentApp * app = LoadContentAppByClient(vendorId, productId); if (app == nullptr) @@ -466,14 +523,14 @@ uint32_t ContentAppPlatform::GetPincodeFromContentApp(uint16_t vendorId, uint16_ return 0; } - static const size_t kSetupPINSize = 12; - char mSetupPIN[kSetupPINSize]; + static const size_t kSetupPasscodeSize = 12; + char mSetupPasscode[kSetupPasscodeSize]; - app->GetAccountLoginDelegate()->GetSetupPin(mSetupPIN, kSetupPINSize, rotatingId); - std::string pinString(mSetupPIN); + app->GetAccountLoginDelegate()->GetSetupPin(mSetupPasscode, kSetupPasscodeSize, rotatingId); + std::string passcodeString(mSetupPasscode); char * eptr; - return (uint32_t) strtol(pinString.c_str(), &eptr, 10); + return (uint32_t) strtol(passcodeString.c_str(), &eptr, 10); } // Returns ACL entry with match subject or CHIP_ERROR_NOT_FOUND if no match is found diff --git a/src/app/app-platform/ContentAppPlatform.h b/src/app/app-platform/ContentAppPlatform.h index f05a94ceda7613..3dd0b138d2e9d1 100644 --- a/src/app/app-platform/ContentAppPlatform.h +++ b/src/app/app-platform/ContentAppPlatform.h @@ -27,6 +27,7 @@ #include #include #include +#include using chip::app::Clusters::ApplicationBasic::CatalogVendorApp; using chip::Controller::CommandResponseFailureCallback; @@ -148,9 +149,15 @@ class DLL_EXPORT ContentAppPlatform // unset this as current app, if it is current app void UnsetIfCurrentApp(ContentApp * app); - // loads content app identified by vid/pid of client and calls HandleGetSetupPin. - // Returns 0 if pin cannot be obtained. - uint32_t GetPincodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId); + // loads content app identified by vid/pid of client and calls HandleGetSetupPasscode. + // Returns 0 if passcode cannot be obtained. + uint32_t GetPasscodeFromContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId); + + // locates app identified by target info and confirms that it grants access to given vid/pid of client, + // loads given app and calls HandleGetSetupPasscode. Sets passcode to 0 if it cannot be obtained. + // return true if a matching app was found (and it granted this client access), even if a passcode was not obtained + bool HasTargetContentApp(uint16_t vendorId, uint16_t productId, CharSpan rotatingId, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo & info, uint32_t & passcode); /** * @brief diff --git a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp index 81dd97503e36af..8189ae3d67ae12 100644 --- a/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp +++ b/src/app/clusters/administrator-commissioning-server/administrator-commissioning-server.cpp @@ -35,6 +35,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -82,6 +83,7 @@ bool emberAfAdministratorCommissioningClusterOpenCommissioningWindowCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::OpenCommissioningWindow::DecodableType & commandData) { + MATTER_TRACE_SCOPE("OpenCommissioningWindow", "AdministratorCommissioning"); auto commissioningTimeout = System::Clock::Seconds16(commandData.commissioningTimeout); auto & pakeVerifier = commandData.PAKEPasscodeVerifier; auto & discriminator = commandData.discriminator; @@ -141,6 +143,7 @@ bool emberAfAdministratorCommissioningClusterOpenBasicCommissioningWindowCallbac app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::OpenBasicCommissioningWindow::DecodableType & commandData) { + MATTER_TRACE_SCOPE("OpenBasicCommissioningWindow", "AdministratorCommissioning"); auto commissioningTimeout = System::Clock::Seconds16(commandData.commissioningTimeout); Optional status = Optional::Missing(); @@ -187,6 +190,7 @@ bool emberAfAdministratorCommissioningClusterRevokeCommissioningCallback( app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::RevokeCommissioning::DecodableType & commandData) { + MATTER_TRACE_SCOPE("RevokeCommissioning", "AdministratorCommissioning"); ChipLogProgress(Zcl, "Received command to close commissioning window"); Server::GetInstance().GetFailSafeContext().ForceFailSafeTimerExpiry(); diff --git a/src/app/clusters/basic-information/basic-information.cpp b/src/app/clusters/basic-information/basic-information.cpp index 510e4991b25bae..f241bb2cf5a008 100644 --- a/src/app/clusters/basic-information/basic-information.cpp +++ b/src/app/clusters/basic-information/basic-information.cpp @@ -33,6 +33,7 @@ #include #include +#include using namespace chip; using namespace chip::app; @@ -410,6 +411,7 @@ class PlatformMgrDelegate : public DeviceLayer::PlatformManagerDelegate { void OnStartUp(uint32_t softwareVersion) override { + MATTER_TRACE_INSTANT("OnStartUp", "BasicInfo"); // The StartUp event SHALL be emitted by a Node after completing a boot or reboot process ChipLogDetail(Zcl, "Emitting StartUp event"); @@ -429,6 +431,7 @@ class PlatformMgrDelegate : public DeviceLayer::PlatformManagerDelegate void OnShutDown() override { + MATTER_TRACE_INSTANT("OnShutDown", "BasicInfo"); // The ShutDown event SHOULD be emitted on a best-effort basis by a Node prior to any orderly shutdown sequence. ChipLogDetail(Zcl, "Emitting ShutDown event"); diff --git a/src/app/clusters/bridged-device-basic-information-server/bridged-device-basic-information-server.cpp b/src/app/clusters/bridged-device-basic-information-server/bridged-device-basic-information-server.cpp index a8785abd516954..0f4137f07b2a1d 100644 --- a/src/app/clusters/bridged-device-basic-information-server/bridged-device-basic-information-server.cpp +++ b/src/app/clusters/bridged-device-basic-information-server/bridged-device-basic-information-server.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -36,6 +37,7 @@ namespace { void ReachableChanged(EndpointId endpointId) { + MATTER_TRACE_INSTANT("ReachableChanged", "BridgeBasicInfo"); bool reachable = false; if (EMBER_ZCL_STATUS_SUCCESS != Attributes::Reachable::Get(endpointId, &reachable)) { 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 cb0d7e5be78605..a21a44ada8d23f 100644 --- a/src/app/clusters/color-control-server/color-control-server.cpp +++ b/src/app/clusters/color-control-server/color-control-server.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef EMBER_AF_PLUGIN_SCENES_MANAGEMENT #include @@ -1354,6 +1355,7 @@ bool ColorControlServer::moveHueCommand(app::CommandHandler * commandObj, const HueMoveMode moveMode, uint16_t rate, uint8_t optionsMask, uint8_t optionsOverride, bool isEnhanced) { + MATTER_TRACE_SCOPE("moveHue", "ColorControl"); EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); @@ -1459,6 +1461,7 @@ bool ColorControlServer::moveToHueCommand(app::CommandHandler * commandObj, cons uint16_t hue, HueDirection moveDirection, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride, bool isEnhanced) { + MATTER_TRACE_SCOPE("moveToHue", "ColorControl"); EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; @@ -1593,6 +1596,7 @@ bool ColorControlServer::moveToHueAndSaturationCommand(app::CommandHandler * com uint8_t saturation, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride, bool isEnhanced) { + MATTER_TRACE_SCOPE("moveToHueAndSaturation", "ColorControl"); // limit checking: hue and saturation are 0..254. Spec dictates we ignore // this and report a constraint error. if ((!isEnhanced && hue > MAX_HUE_VALUE) || saturation > MAX_SATURATION_VALUE) @@ -1632,6 +1636,7 @@ bool ColorControlServer::stepHueCommand(app::CommandHandler * commandObj, const HueStepMode stepMode, uint16_t stepSize, uint16_t transitionTime, uint8_t optionsMask, uint8_t optionsOverride, bool isEnhanced) { + MATTER_TRACE_SCOPE("stepHue", "ColorControl"); EndpointId endpoint = commandPath.mEndpointId; Status status = Status::Success; @@ -1715,6 +1720,7 @@ bool ColorControlServer::stepHueCommand(app::CommandHandler * commandObj, const bool ColorControlServer::moveSaturationCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::MoveSaturation::DecodableType & commandData) { + MATTER_TRACE_SCOPE("moveSaturation", "ColorControl"); auto & moveMode = commandData.moveMode; auto & rate = commandData.rate; auto & optionsMask = commandData.optionsMask; @@ -1798,6 +1804,7 @@ bool ColorControlServer::moveSaturationCommand(app::CommandHandler * commandObj, bool ColorControlServer::moveToSaturationCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::MoveToSaturation::DecodableType & commandData) { + MATTER_TRACE_SCOPE("moveToSaturation", "ColorControl"); // limit checking: saturation is 0..254. Spec dictates we ignore // this and report a malformed packet. if (commandData.saturation > MAX_SATURATION_VALUE) @@ -1822,6 +1829,7 @@ bool ColorControlServer::moveToSaturationCommand(app::CommandHandler * commandOb bool ColorControlServer::stepSaturationCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::StepSaturation::DecodableType & commandData) { + MATTER_TRACE_SCOPE("stepSaturation", "ColorControl"); auto stepMode = commandData.stepMode; uint8_t stepSize = commandData.stepSize; uint8_t transitionTime = commandData.transitionTime; @@ -1885,6 +1893,7 @@ bool ColorControlServer::stepSaturationCommand(app::CommandHandler * commandObj, bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::ColorLoopSet::DecodableType & commandData) { + MATTER_TRACE_SCOPE("colorLoop", "ColorControl"); auto updateFlags = commandData.updateFlags; auto action = commandData.action; auto direction = commandData.direction; @@ -2010,6 +2019,7 @@ bool ColorControlServer::colorLoopCommand(app::CommandHandler * commandObj, cons */ void ColorControlServer::updateHueSatCommand(EndpointId endpoint) { + MATTER_TRACE_SCOPE("updateHueSat", "ColorControl"); ColorHueTransitionState * colorHueTransitionState = getColorHueTransitionState(endpoint); Color16uTransitionState * colorSaturationTransitionState = getSaturationTransitionState(endpoint); diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp index bfe3cac5f2e89e..7836e91295412f 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.cpp @@ -53,11 +53,6 @@ bool Instance::HasFeature(Feature aFeature) const return mFeature.Has(aFeature); } -bool Instance::SupportsOptCmd(OptionalCommands aOptionalCmds) const -{ - return mOptionalCmds.Has(aOptionalCmds); -} - // AttributeAccessInterface CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) { @@ -87,6 +82,16 @@ CHIP_ERROR Instance::Read(const ConcreteReadAttributePath & aPath, AttributeValu return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); } return aEncoder.Encode(mDelegate.GetForecast()); + case OptOutState::Id: + /* PA | STA | PAU | FA | CON */ + if (!HasFeature(Feature::kPowerAdjustment) && !HasFeature(Feature::kStartTimeAdjustment) && + !HasFeature(Feature::kPausable) && !HasFeature(Feature::kForecastAdjustment) && + !HasFeature(Feature::kConstraintBasedAdjustment)) + { + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + } + return aEncoder.Encode(mDelegate.GetOptOutState()); + /* FeatureMap - is held locally */ case FeatureMap::Id: return aEncoder.Encode(mFeature); @@ -112,28 +117,33 @@ CHIP_ERROR Instance::EnumerateAcceptedCommands(const ConcreteClusterPath & clust } } - if (HasFeature(Feature::kForecastAdjustment)) + if (HasFeature(Feature::kStartTimeAdjustment)) { - for (auto && cmd : { - StartTimeAdjustRequest::Id, - PauseRequest::Id, - ResumeRequest::Id, - }) - { - VerifyOrExit(callback(cmd, context) == Loop::Continue, /**/); - } + VerifyOrExit(callback(StartTimeAdjustRequest::Id, context) == Loop::Continue, /**/); + } + + if (HasFeature(Feature::kPausable)) + { + VerifyOrExit(callback(PauseRequest::Id, context) == Loop::Continue, /**/); + VerifyOrExit(callback(ResumeRequest::Id, context) == Loop::Continue, /**/); } - if (SupportsOptCmd(OptionalCommands::kSupportsModifyForecastRequest)) + if (HasFeature(Feature::kForecastAdjustment)) { VerifyOrExit(callback(ModifyForecastRequest::Id, context) == Loop::Continue, /**/); } - if (SupportsOptCmd(OptionalCommands::kSupportsRequestConstraintBasedForecast)) + if (HasFeature(Feature::kConstraintBasedAdjustment)) { VerifyOrExit(callback(RequestConstraintBasedForecast::Id, context) == Loop::Continue, /**/); } + if (HasFeature(Feature::kStartTimeAdjustment) || HasFeature(Feature::kForecastAdjustment) || + HasFeature(Feature::kConstraintBasedAdjustment)) + { + VerifyOrExit(callback(CancelRequest::Id, context) == Loop::Continue, /**/); + } + exit: return CHIP_NO_ERROR; } @@ -169,7 +179,7 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) } return; case StartTimeAdjustRequest::Id: - if (!HasFeature(Feature::kForecastAdjustment)) + if (!HasFeature(Feature::kStartTimeAdjustment)) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); } @@ -181,7 +191,7 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) } return; case PauseRequest::Id: - if (!HasFeature(Feature::kForecastAdjustment)) + if (!HasFeature(Feature::kPausable)) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); } @@ -192,7 +202,7 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) } return; case ResumeRequest::Id: - if (!HasFeature(Feature::kForecastAdjustment)) + if (!HasFeature(Feature::kPausable)) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); } @@ -203,7 +213,7 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) } return; case ModifyForecastRequest::Id: - if (!SupportsOptCmd(OptionalCommands::kSupportsModifyForecastRequest)) + if (!HasFeature(Feature::kForecastAdjustment)) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); } @@ -215,7 +225,7 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) } return; case RequestConstraintBasedForecast::Id: - if (!SupportsOptCmd(OptionalCommands::kSupportsRequestConstraintBasedForecast)) + if (!HasFeature(Feature::kConstraintBasedAdjustment)) { handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); } @@ -226,19 +236,88 @@ void Instance::InvokeCommand(HandlerContext & handlerContext) [this](HandlerContext & ctx, const auto & commandData) { HandleRequestConstraintBasedForecast(ctx, commandData); }); } return; + case CancelRequest::Id: + if (!HasFeature(Feature::kStartTimeAdjustment) && !HasFeature(Feature::kForecastAdjustment) && + !HasFeature(Feature::kConstraintBasedAdjustment)) + { + handlerContext.mCommandHandler.AddStatus(handlerContext.mRequestPath, Status::UnsupportedCommand); + } + else + { + HandleCommand( + handlerContext, [this](HandlerContext & ctx, const auto & commandData) { HandleCancelRequest(ctx, commandData); }); + } + return; } } -void Instance::HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::PowerAdjustRequest::DecodableType & commandData) +Status Instance::CheckOptOutAllowsRequest(AdjustmentCauseEnum adjustmentCause) { - int64_t power = commandData.power; - uint32_t durationSec = commandData.duration; - bool validArgs = false; - Status status = Status::Success; + OptOutStateEnum optOutState = mDelegate.GetOptOutState(); + + if (adjustmentCause == AdjustmentCauseEnum::kUnknownEnumValue) + { + ChipLogError(Zcl, "DEM: adjustment cause is invalid (%d)", static_cast(adjustmentCause)); + return Status::InvalidValue; + } + + switch (optOutState) + { + case OptOutStateEnum::kNoOptOut: /* User has NOT opted out so allow it */ + ChipLogProgress(Zcl, "DEM: OptOutState = kNoOptOut"); + return Status::Success; + + case OptOutStateEnum::kLocalOptOut: /* User has opted out from Local only*/ + ChipLogProgress(Zcl, "DEM: OptOutState = kLocalOptOut"); + switch (adjustmentCause) + { + case AdjustmentCauseEnum::kGridOptimization: + return Status::Success; + case AdjustmentCauseEnum::kLocalOptimization: + default: + return Status::Failure; + } + + case OptOutStateEnum::kGridOptOut: /* User has opted out from Grid only */ + ChipLogProgress(Zcl, "DEM: OptOutState = kGridOptOut"); + switch (adjustmentCause) + { + case AdjustmentCauseEnum::kLocalOptimization: + return Status::Success; + case AdjustmentCauseEnum::kGridOptimization: + default: + return Status::Failure; + } + + case OptOutStateEnum::kOptOut: /* User has opted out from both local and grid */ + ChipLogProgress(Zcl, "DEM: OptOutState = kOptOut"); + return Status::Failure; + default: + ChipLogError(Zcl, "DEM: invalid optOutState %d", static_cast(optOutState)); + return Status::InvalidValue; + } +} + +void Instance::HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::PowerAdjustRequest::DecodableType & commandData) +{ + Status status; + bool validArgs = false; PowerAdjustmentCapability::TypeInfo::Type powerAdjustmentCapability; - powerAdjustmentCapability = mDelegate.GetPowerAdjustmentCapability(); + int64_t power = commandData.power; + uint32_t durationSec = commandData.duration; + AdjustmentCauseEnum adjustmentCause = commandData.cause; + + status = CheckOptOutAllowsRequest(adjustmentCause); + if (status != Status::Success) + { + ChipLogError(Zcl, "DEM: PowerAdjustRequest command rejected"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + return; + } + + powerAdjustmentCapability = mDelegate.GetPowerAdjustmentCapability(); if (powerAdjustmentCapability.IsNull()) { ChipLogError(Zcl, "DEM: powerAdjustmentCapability IsNull"); @@ -267,7 +346,7 @@ void Instance::HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::Po ChipLogProgress(Zcl, "DEM: Good PowerAdjustRequest() args."); - status = mDelegate.PowerAdjustRequest(power, durationSec); + status = mDelegate.PowerAdjustRequest(power, durationSec, adjustmentCause); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { @@ -278,11 +357,10 @@ void Instance::HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::Po void Instance::HandleCancelPowerAdjustRequest(HandlerContext & ctx, const Commands::CancelPowerAdjustRequest::DecodableType & commandData) { - Status status = Status::Success; - ESAStateEnum esaStatus; + Status status; /* Check that the ESA state is PowerAdjustActive */ - esaStatus = mDelegate.GetESAState(); + ESAStateEnum esaStatus = mDelegate.GetESAState(); if (ESAStateEnum::kPowerAdjustActive != esaStatus) { ChipLogError(Zcl, "DEM: kPowerAdjustActive != esaStatus"); @@ -302,24 +380,27 @@ void Instance::HandleCancelPowerAdjustRequest(HandlerContext & ctx, void Instance::HandleStartTimeAdjustRequest(HandlerContext & ctx, const Commands::StartTimeAdjustRequest::DecodableType & commandData) { - Status status = Status::Success; - uint32_t earliestStartTimeEpoch = 0; - uint32_t latestEndTimeEpoch = 0; - uint32_t requestedStartTimeEpoch = commandData.requestedStartTime; + Status status; + uint32_t earliestStartTimeEpoch = 0; + uint32_t latestEndTimeEpoch = 0; uint32_t duration; - DataModel::Nullable forecastNullable = mDelegate.GetForecast(); + uint32_t requestedStartTimeEpoch = commandData.requestedStartTime; + AdjustmentCauseEnum adjustmentCause = commandData.cause; - if (forecastNullable.IsNull()) + status = CheckOptOutAllowsRequest(adjustmentCause); + if (status != Status::Success) { - ChipLogError(Zcl, "DEM: Forecast is Null"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: StartTimeAdjustRequest command rejected"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } - if (ESAStateEnum::kUserOptOut == mDelegate.GetESAState()) + DataModel::Nullable forecastNullable = mDelegate.GetForecast(); + + if (forecastNullable.IsNull()) { - ChipLogError(Zcl, "DEM: ESAState = kUserOptOut"); + ChipLogError(Zcl, "DEM: Forecast is Null"); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); return; } @@ -395,7 +476,7 @@ void Instance::HandleStartTimeAdjustRequest(HandlerContext & ctx, } ChipLogProgress(Zcl, "DEM: Good requestedStartTimeEpoch %ld.", static_cast(requestedStartTimeEpoch)); - status = mDelegate.StartTimeAdjustRequest(requestedStartTimeEpoch); + status = mDelegate.StartTimeAdjustRequest(requestedStartTimeEpoch, adjustmentCause); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { @@ -410,18 +491,20 @@ void Instance::HandlePauseRequest(HandlerContext & ctx, const Commands::PauseReq CHIP_ERROR err = CHIP_NO_ERROR; DataModel::Nullable forecast = mDelegate.GetForecast(); - uint32_t duration = commandData.duration; + uint32_t duration = commandData.duration; + AdjustmentCauseEnum adjustmentCause = commandData.cause; - if (forecast.IsNull()) + status = CheckOptOutAllowsRequest(adjustmentCause); + if (status != Status::Success) { - ChipLogError(Zcl, "DEM: Forecast is Null"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: PauseRequest command rejected"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } - if (ESAStateEnum::kUserOptOut == mDelegate.GetESAState()) + if (forecast.IsNull()) { - ChipLogError(Zcl, "DEM: ESAState = kUserOptOut"); + ChipLogError(Zcl, "DEM: Forecast is Null"); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); return; } @@ -446,15 +529,37 @@ void Instance::HandlePauseRequest(HandlerContext & ctx, const Commands::PauseReq return; } - if (!forecast.Value().slots[activeSlotNumber].slotIsPauseable) + /* We expect that there should be a slotIsPauseable entry (but it is optional) */ + if (!forecast.Value().slots[activeSlotNumber].slotIsPauseable.HasValue()) + { + ChipLogError(Zcl, "DEM: activeSlotNumber %d does not include slotIsPauseable.", activeSlotNumber); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + return; + } + + if (!forecast.Value().slots[activeSlotNumber].minPauseDuration.HasValue()) + { + ChipLogError(Zcl, "DEM: activeSlotNumber %d does not include minPauseDuration.", activeSlotNumber); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + return; + } + + if (!forecast.Value().slots[activeSlotNumber].maxPauseDuration.HasValue()) + { + ChipLogError(Zcl, "DEM: activeSlotNumber %d does not include minPauseDuration.", activeSlotNumber); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + return; + } + + if (!forecast.Value().slots[activeSlotNumber].slotIsPauseable.Value()) { ChipLogError(Zcl, "DEM: activeSlotNumber %d is NOT pauseable.", activeSlotNumber); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); return; } - if ((duration < forecast.Value().slots[activeSlotNumber].minPauseDuration) && - (duration > forecast.Value().slots[activeSlotNumber].maxPauseDuration)) + if ((duration < forecast.Value().slots[activeSlotNumber].minPauseDuration.Value()) && + (duration > forecast.Value().slots[activeSlotNumber].maxPauseDuration.Value())) { ChipLogError(Zcl, "DEM: out of range pause duration %ld", static_cast(duration)); ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::ConstraintError); @@ -469,19 +574,18 @@ void Instance::HandlePauseRequest(HandlerContext & ctx, const Commands::PauseReq return; } - status = mDelegate.PauseRequest(duration); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + status = mDelegate.PauseRequest(duration, adjustmentCause); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { - ChipLogError(Zcl, "DEM: mDelegate.PauseRequest(%ld) FAILURE", static_cast(duration)); + ChipLogError(Zcl, "DEM: PauseRequest(%ld) FAILURE", static_cast(duration)); return; } } void Instance::HandleResumeRequest(HandlerContext & ctx, const Commands::ResumeRequest::DecodableType & commandData) { - Status status = Status::Success; - DataModel::Nullable forecast = mDelegate.GetForecast(); + Status status; if (ESAStateEnum::kPaused != mDelegate.GetESAState()) { @@ -491,24 +595,28 @@ void Instance::HandleResumeRequest(HandlerContext & ctx, const Commands::ResumeR } status = mDelegate.ResumeRequest(); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { - ChipLogError(Zcl, "DEM: mDelegate.ResumeRequest() FAILURE"); + ChipLogError(Zcl, "DEM: ResumeRequest FAILURE"); return; } } void Instance::HandleModifyForecastRequest(HandlerContext & ctx, const Commands::ModifyForecastRequest::DecodableType & commandData) { - Status status = Status::Success; - uint32_t forecastId = commandData.forecastId; + Status status; DataModel::Nullable forecast; - if (ESAStateEnum::kUserOptOut == mDelegate.GetESAState()) + uint32_t forecastId = commandData.forecastId; + DataModel::DecodableList slotAdjustments = commandData.slotAdjustments; + AdjustmentCauseEnum adjustmentCause = commandData.cause; + + status = CheckOptOutAllowsRequest(adjustmentCause); + if (status != Status::Success) { - ChipLogError(Zcl, "DEM: ESAState = kUserOptOut"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: ModifyForecastRequest command rejected"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } @@ -520,12 +628,11 @@ void Instance::HandleModifyForecastRequest(HandlerContext & ctx, const Commands: return; } - DataModel::DecodableList slotAdjustments = commandData.slotAdjustments; - status = mDelegate.ModifyForecastRequest(forecastId, slotAdjustments); + status = mDelegate.ModifyForecastRequest(forecastId, slotAdjustments, adjustmentCause); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { - ChipLogError(Zcl, "DEM: mDelegate.ModifyForecastRequest() FAILURE"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: ModifyForecastRequest FAILURE"); return; } } @@ -533,20 +640,37 @@ void Instance::HandleModifyForecastRequest(HandlerContext & ctx, const Commands: void Instance::HandleRequestConstraintBasedForecast(HandlerContext & ctx, const Commands::RequestConstraintBasedForecast::DecodableType & commandData) { - Status status = Status::Success; + Status status; - if (ESAStateEnum::kUserOptOut == mDelegate.GetESAState()) + DataModel::DecodableList constraints = commandData.constraints; + AdjustmentCauseEnum adjustmentCause = commandData.cause; + + status = CheckOptOutAllowsRequest(adjustmentCause); + if (status != Status::Success) { - ChipLogError(Zcl, "DEM: ESAState = kUserOptOut"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: RequestConstraintBasedForecast command rejected"); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); return; } - status = mDelegate.RequestConstraintBasedForecast(commandData.constraints); + status = mDelegate.RequestConstraintBasedForecast(constraints, adjustmentCause); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); if (status != Status::Success) { - ChipLogError(Zcl, "DEM: mDelegate.commandData.constraints() FAILURE"); - ctx.mCommandHandler.AddStatus(ctx.mRequestPath, Status::Failure); + ChipLogError(Zcl, "DEM: RequestConstraintBasedForecast FAILURE"); + return; + } +} + +void Instance::HandleCancelRequest(HandlerContext & ctx, const Commands::CancelRequest::DecodableType & commandData) +{ + Status status; + + status = mDelegate.CancelRequest(); + ctx.mCommandHandler.AddStatus(ctx.mRequestPath, status); + if (status != Status::Success) + { + ChipLogError(Zcl, "DEM: CancelRequest FAILURE"); return; } } diff --git a/src/app/clusters/device-energy-management-server/device-energy-management-server.h b/src/app/clusters/device-energy-management-server/device-energy-management-server.h index 7ab6a8aa60f306..3620379d4ed8e2 100644 --- a/src/app/clusters/device-energy-management-server/device-energy-management-server.h +++ b/src/app/clusters/device-energy-management-server/device-energy-management-server.h @@ -52,7 +52,7 @@ class Delegate * @param duration The duration that the ESA SHALL maintain the requested power for. * @return Success if the adjustment is accepted; otherwise the command SHALL be rejected with appropriate error. */ - virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration) = 0; + virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration, AdjustmentCauseEnum cause) = 0; /** * @brief Delegate SHALL make the ESA end the active power adjustment session & return to normal (or idle) power levels. @@ -76,7 +76,7 @@ class Delegate * @return Success if the StartTime in the Forecast is updated, otherwise the command SHALL be rejected with appropriate * IM_Status. */ - virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime) = 0; + virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime, AdjustmentCauseEnum cause) = 0; /** * @brief Delegate handler for PauseRequest command @@ -91,7 +91,7 @@ class Delegate * @param duration Duration that the ESA SHALL be paused for. * @return Success if the ESA is paused, otherwise returns other IM_Status. */ - virtual Status PauseRequest(const uint32_t duration) = 0; + virtual Status PauseRequest(const uint32_t duration, AdjustmentCauseEnum cause) = 0; /** * @brief Delegate handler for ResumeRequest command @@ -119,7 +119,8 @@ class Delegate * SHALL be rejected returning other IM_Status. */ virtual Status ModifyForecastRequest(const uint32_t forecastId, - const DataModel::DecodableList & slotAdjustments) = 0; + const DataModel::DecodableList & slotAdjustments, + AdjustmentCauseEnum cause) = 0; /** * @brief Delegate handler for RequestConstraintBasedForecast @@ -132,8 +133,27 @@ class Delegate * @param constraints Sequence of turn up/down power requests that the ESA is being asked to constrain its operation within. * @return Success if successful, otherwise the command SHALL be rejected returning other IM_Status. */ - virtual Status - RequestConstraintBasedForecast(const DataModel::DecodableList & constraints) = 0; + virtual Status RequestConstraintBasedForecast(const DataModel::DecodableList & constraints, + AdjustmentCauseEnum cause) = 0; + + /** + * @brief Delegate handler for CancelRequest + * + * The ESA SHALL attempt to cancel the effects of any previous adjustment request commands, and re-evaluate its + * forecast for intended operation ignoring those previous requests. + * + * If the ESA ForecastStruct ForecastUpdateReason was already `Internal Optimization`, then the command SHALL + * be rejected with FAILURE. + * + * If the command is accepted, the ESA SHALL update its ESAState if required, and the command status returned + * SHALL be SUCCESS. + * + * The ESA SHALL update its Forecast attribute to match its new intended operation, and update the + * ForecastStruct.ForecastUpdateReason to `Internal Optimization` + * + * @return Success if successful, otherwise the command SHALL be rejected returning other IM_Status. + */ + virtual Status CancelRequest() = 0; // ------------------------------------------------------------------ // Get attribute methods @@ -144,6 +164,7 @@ class Delegate virtual int64_t GetAbsMaxPower() = 0; virtual PowerAdjustmentCapability::TypeInfo::Type GetPowerAdjustmentCapability() = 0; virtual DataModel::Nullable GetForecast() = 0; + virtual OptOutStateEnum GetOptOutState() = 0; // ------------------------------------------------------------------ // Set attribute methods @@ -159,18 +180,12 @@ class Delegate EndpointId mEndpointId = 0; }; -enum class OptionalCommands : uint32_t -{ - kSupportsModifyForecastRequest = 0x1, - kSupportsRequestConstraintBasedForecast = 0x2 -}; - class Instance : public AttributeAccessInterface, public CommandHandlerInterface { public: - Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature, OptionalCommands aOptionalCmds) : + Instance(EndpointId aEndpointId, Delegate & aDelegate, Feature aFeature) : AttributeAccessInterface(MakeOptional(aEndpointId), Id), CommandHandlerInterface(MakeOptional(aEndpointId), Id), - mDelegate(aDelegate), mFeature(aFeature), mOptionalCmds(aOptionalCmds) + mDelegate(aDelegate), mFeature(aFeature) { /* set the base class delegates endpointId */ mDelegate.SetEndpointId(aEndpointId); @@ -182,12 +197,10 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface void Shutdown(); bool HasFeature(Feature aFeature) const; - bool SupportsOptCmd(OptionalCommands aOptionalCmds) const; private: Delegate & mDelegate; BitMask mFeature; - BitMask mOptionalCmds; // AttributeAccessInterface CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; @@ -197,6 +210,7 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface void InvokeCommand(HandlerContext & handlerContext) override; CHIP_ERROR EnumerateAcceptedCommands(const ConcreteClusterPath & cluster, CommandIdCallback callback, void * context) override; + Status CheckOptOutAllowsRequest(AdjustmentCauseEnum adjustmentCause); void HandlePowerAdjustRequest(HandlerContext & ctx, const Commands::PowerAdjustRequest::DecodableType & commandData); void HandleCancelPowerAdjustRequest(HandlerContext & ctx, const Commands::CancelPowerAdjustRequest::DecodableType & commandData); @@ -206,6 +220,7 @@ class Instance : public AttributeAccessInterface, public CommandHandlerInterface void HandleModifyForecastRequest(HandlerContext & ctx, const Commands::ModifyForecastRequest::DecodableType & commandData); void HandleRequestConstraintBasedForecast(HandlerContext & ctx, const Commands::RequestConstraintBasedForecast::DecodableType & commandData); + void HandleCancelRequest(HandlerContext & ctx, const Commands::CancelRequest::DecodableType & commandData); }; } // namespace DeviceEnergyManagement diff --git a/src/app/clusters/groups-server/groups-server.cpp b/src/app/clusters/groups-server/groups-server.cpp index 4ab5fa24ee577e..a6d502acb18e52 100644 --- a/src/app/clusters/groups-server/groups-server.cpp +++ b/src/app/clusters/groups-server/groups-server.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #ifdef EMBER_AF_PLUGIN_SCENES_MANAGEMENT #include @@ -141,6 +142,7 @@ void emberAfGroupsClusterServerInitCallback(EndpointId endpointId) bool emberAfGroupsClusterAddGroupCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::AddGroup::DecodableType & commandData) { + MATTER_TRACE_SCOPE("AddGroup", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); Groups::Commands::AddGroupResponse::Type response; @@ -153,6 +155,7 @@ bool emberAfGroupsClusterAddGroupCallback(app::CommandHandler * commandObj, cons bool emberAfGroupsClusterViewGroupCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::ViewGroup::DecodableType & commandData) { + MATTER_TRACE_SCOPE("ViewGroup", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto groupId = commandData.groupID; GroupDataProvider * provider = GetGroupDataProvider(); @@ -255,6 +258,7 @@ struct GroupMembershipResponse bool emberAfGroupsClusterGetGroupMembershipCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::GetGroupMembership::DecodableType & commandData) { + MATTER_TRACE_SCOPE("GetGroupMembership", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto * provider = GetGroupDataProvider(); Status status = Status::Failure; @@ -284,6 +288,7 @@ bool emberAfGroupsClusterGetGroupMembershipCallback(app::CommandHandler * comman bool emberAfGroupsClusterRemoveGroupCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::RemoveGroup::DecodableType & commandData) { + MATTER_TRACE_SCOPE("RemoveGroup", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); Groups::Commands::RemoveGroupResponse::Type response; @@ -301,6 +306,7 @@ bool emberAfGroupsClusterRemoveGroupCallback(app::CommandHandler * commandObj, c bool emberAfGroupsClusterRemoveAllGroupsCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::RemoveAllGroups::DecodableType & commandData) { + MATTER_TRACE_SCOPE("RemoveAllGroups", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto * provider = GetGroupDataProvider(); Status status = Status::Failure; @@ -342,6 +348,7 @@ bool emberAfGroupsClusterAddGroupIfIdentifyingCallback(app::CommandHandler * com const app::ConcreteCommandPath & commandPath, const Commands::AddGroupIfIdentifying::DecodableType & commandData) { + MATTER_TRACE_SCOPE("AddGroupIfIdentifying", "Groups"); auto fabricIndex = commandObj->GetAccessingFabricIndex(); auto groupId = commandData.groupID; auto groupName = commandData.groupName; diff --git a/src/app/clusters/identify-server/identify-server.cpp b/src/app/clusters/identify-server/identify-server.cpp index e60b89d7d6931b..55a0e15ee59c2f 100644 --- a/src/app/clusters/identify-server/identify-server.cpp +++ b/src/app/clusters/identify-server/identify-server.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #if CHIP_DEVICE_LAYER_NONE #error "identify requrires a device layer" @@ -196,6 +197,7 @@ void MatterIdentifyClusterServerAttributeChangedCallback(const app::ConcreteAttr bool emberAfIdentifyClusterIdentifyCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::Identify::DecodableType & commandData) { + MATTER_TRACE_SCOPE("IdentifyCommand", "Identify"); auto & identifyTime = commandData.identifyTime; // cmd Identify @@ -207,6 +209,7 @@ bool emberAfIdentifyClusterIdentifyCallback(CommandHandler * commandObj, const C bool emberAfIdentifyClusterTriggerEffectCallback(CommandHandler * commandObj, const ConcreteCommandPath & commandPath, const Commands::TriggerEffect::DecodableType & commandData) { + MATTER_TRACE_SCOPE("TriggerEffect", "Identify"); auto & effectIdentifier = commandData.effectIdentifier; auto & effectVariant = commandData.effectVariant; diff --git a/src/app/clusters/level-control/level-control.cpp b/src/app/clusters/level-control/level-control.cpp index ba22be03055886..f3f31d58982d93 100644 --- a/src/app/clusters/level-control/level-control.cpp +++ b/src/app/clusters/level-control/level-control.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #ifdef EMBER_AF_PLUGIN_SCENES_MANAGEMENT #include @@ -577,6 +578,7 @@ static bool shouldExecuteIfOff(EndpointId endpoint, CommandId commandId, chip::O bool emberAfLevelControlClusterMoveToLevelCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::MoveToLevel::DecodableType & commandData) { + MATTER_TRACE_SCOPE("MoveToLevel", "LevelControl"); commandObj->AddStatus(commandPath, LevelControlServer::MoveToLevel(commandPath.mEndpointId, commandData)); return true; } @@ -621,6 +623,7 @@ bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(app::CommandHandler const app::ConcreteCommandPath & commandPath, const Commands::MoveToLevelWithOnOff::DecodableType & commandData) { + MATTER_TRACE_SCOPE("MoveToLevelWithOnOff", "LevelControl"); auto & level = commandData.level; auto & transitionTime = commandData.transitionTime; auto & optionsMask = commandData.optionsMask; @@ -650,6 +653,7 @@ bool emberAfLevelControlClusterMoveToLevelWithOnOffCallback(app::CommandHandler bool emberAfLevelControlClusterMoveCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::Move::DecodableType & commandData) { + MATTER_TRACE_SCOPE("Move", "LevelControl"); auto & moveMode = commandData.moveMode; auto & rate = commandData.rate; auto & optionsMask = commandData.optionsMask; @@ -674,6 +678,7 @@ bool emberAfLevelControlClusterMoveCallback(app::CommandHandler * commandObj, co bool emberAfLevelControlClusterMoveWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::MoveWithOnOff::DecodableType & commandData) { + MATTER_TRACE_SCOPE("MoveWithOnOff", "LevelControl"); auto & moveMode = commandData.moveMode; auto & rate = commandData.rate; auto & optionsMask = commandData.optionsMask; @@ -698,6 +703,7 @@ bool emberAfLevelControlClusterMoveWithOnOffCallback(app::CommandHandler * comma bool emberAfLevelControlClusterStepCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::Step::DecodableType & commandData) { + MATTER_TRACE_SCOPE("Step", "LevelControl"); auto & stepMode = commandData.stepMode; auto & stepSize = commandData.stepSize; auto & transitionTime = commandData.transitionTime; @@ -723,6 +729,7 @@ bool emberAfLevelControlClusterStepCallback(app::CommandHandler * commandObj, co bool emberAfLevelControlClusterStepWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::StepWithOnOff::DecodableType & commandData) { + MATTER_TRACE_SCOPE("StepWithOnOff", "LevelControl"); auto & stepMode = commandData.stepMode; auto & stepSize = commandData.stepSize; auto & transitionTime = commandData.transitionTime; @@ -748,6 +755,7 @@ bool emberAfLevelControlClusterStepWithOnOffCallback(app::CommandHandler * comma bool emberAfLevelControlClusterStopCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::Stop::DecodableType & commandData) { + MATTER_TRACE_SCOPE("Stop", "LevelControl"); auto & optionsMask = commandData.optionsMask; auto & optionsOverride = commandData.optionsOverride; @@ -760,6 +768,7 @@ bool emberAfLevelControlClusterStopCallback(app::CommandHandler * commandObj, co bool emberAfLevelControlClusterStopWithOnOffCallback(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::StopWithOnOff::DecodableType & commandData) { + MATTER_TRACE_SCOPE("StopWithOnOff", "LevelControl"); auto & optionsMask = commandData.optionsMask; auto & optionsOverride = commandData.optionsOverride; ChipLogProgress(Zcl, "%s STOP_WITH_ON_OFF", "RX level-control:"); diff --git a/src/app/clusters/low-power-server/low-power-server.cpp b/src/app/clusters/low-power-server/low-power-server.cpp index 5881d2e56fc322..4e8b10e8f082ea 100644 --- a/src/app/clusters/low-power-server/low-power-server.cpp +++ b/src/app/clusters/low-power-server/low-power-server.cpp @@ -31,6 +31,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app::Clusters; @@ -93,6 +94,7 @@ void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) bool emberAfLowPowerClusterSleepCallback(app::CommandHandler * command, const app::ConcreteCommandPath & commandPath, const Commands::Sleep::DecodableType & commandData) { + MATTER_TRACE_SCOPE("Sleep", "LowPower"); using Protocols::InteractionModel::Status; EndpointId endpoint = commandPath.mEndpointId; diff --git a/src/app/clusters/mode-base-server/mode-base-server.cpp b/src/app/clusters/mode-base-server/mode-base-server.cpp index 28d958d25f2651..1d01c10c718ac2 100644 --- a/src/app/clusters/mode-base-server/mode-base-server.cpp +++ b/src/app/clusters/mode-base-server/mode-base-server.cpp @@ -24,6 +24,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -378,6 +379,7 @@ void Instance::UnregisterThisInstance() void Instance::HandleChangeToMode(HandlerContext & ctx, const Commands::ChangeToMode::DecodableType & commandData) { + MATTER_TRACE_SCOPE("ChangeToMode", "ModeBase"); uint8_t newMode = commandData.newMode; Commands::ChangeToModeResponse::Type response; diff --git a/src/app/clusters/mode-select-server/mode-select-server.cpp b/src/app/clusters/mode-select-server/mode-select-server.cpp index 2c9d88c1872737..4ca641e8e48d95 100644 --- a/src/app/clusters/mode-select-server/mode-select-server.cpp +++ b/src/app/clusters/mode-select-server/mode-select-server.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #ifdef EMBER_AF_PLUGIN_ON_OFF #include @@ -98,6 +99,7 @@ CHIP_ERROR ModeSelectAttrAccess::Read(const ConcreteReadAttributePath & aPath, A bool emberAfModeSelectClusterChangeToModeCallback(CommandHandler * commandHandler, const ConcreteCommandPath & commandPath, const ModeSelect::Commands::ChangeToMode::DecodableType & commandData) { + MATTER_TRACE_SCOPE("ChangeToMode", "ModeSelect"); ChipLogProgress(Zcl, "ModeSelect: Entering emberAfModeSelectClusterChangeToModeCallback"); EndpointId endpointId = commandPath.mEndpointId; uint8_t newMode = commandData.newMode; diff --git a/src/app/clusters/on-off-server/on-off-server.cpp b/src/app/clusters/on-off-server/on-off-server.cpp index eb867fb4ef893c..ea7dd0786a9917 100644 --- a/src/app/clusters/on-off-server/on-off-server.cpp +++ b/src/app/clusters/on-off-server/on-off-server.cpp @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef EMBER_AF_PLUGIN_SCENES_MANAGEMENT #include @@ -341,6 +342,7 @@ EmberAfStatus OnOffServer::getOnOffValue(chip::EndpointId endpoint, bool * curre */ EmberAfStatus OnOffServer::setOnOffValue(chip::EndpointId endpoint, chip::CommandId command, bool initiatedByLevelChange) { + MATTER_TRACE_SCOPE("setOnOffValue", "OnOff"); EmberAfStatus status; bool currentValue, newValue; @@ -568,6 +570,7 @@ EmberAfStatus OnOffServer::getOnOffValueForStartUp(chip::EndpointId endpoint, bo bool OnOffServer::offCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath) { + MATTER_TRACE_SCOPE("OffCommand", "OnOff"); EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::Off::Id, false); commandObj->AddStatus(commandPath, app::ToInteractionModelStatus(status)); @@ -576,6 +579,7 @@ bool OnOffServer::offCommand(app::CommandHandler * commandObj, const app::Concre bool OnOffServer::onCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath) { + MATTER_TRACE_SCOPE("OnCommand", "OnOff"); EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::On::Id, false); commandObj->AddStatus(commandPath, app::ToInteractionModelStatus(status)); @@ -584,6 +588,7 @@ bool OnOffServer::onCommand(app::CommandHandler * commandObj, const app::Concret bool OnOffServer::toggleCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath) { + MATTER_TRACE_SCOPE("ToggleCommand", "OnOff"); EmberAfStatus status = setOnOffValue(commandPath.mEndpointId, Commands::Toggle::Id, false); commandObj->AddStatus(commandPath, app::ToInteractionModelStatus(status)); @@ -593,6 +598,7 @@ bool OnOffServer::toggleCommand(app::CommandHandler * commandObj, const app::Con bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::OffWithEffect::DecodableType & commandData) { + MATTER_TRACE_SCOPE("offWithEffectCommand", "OnOff"); auto effectId = commandData.effectIdentifier; auto effectVariant = commandData.effectVariant; chip::EndpointId endpoint = commandPath.mEndpointId; @@ -650,6 +656,7 @@ bool OnOffServer::offWithEffectCommand(app::CommandHandler * commandObj, const a bool OnOffServer::OnWithRecallGlobalSceneCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath) { + MATTER_TRACE_SCOPE("OnWithRecallGlobalSceneCommand", "OnOff"); chip::EndpointId endpoint = commandPath.mEndpointId; if (!SupportsLightingApplications(endpoint)) @@ -711,6 +718,7 @@ uint32_t OnOffServer::calculateNextWaitTimeMS() bool OnOffServer::OnWithTimedOffCommand(app::CommandHandler * commandObj, const app::ConcreteCommandPath & commandPath, const Commands::OnWithTimedOff::DecodableType & commandData) { + MATTER_TRACE_SCOPE("OnWithTimedOffCommand", "OnOff"); BitFlags onOffControl = commandData.onOffControl; uint16_t onTime = commandData.onTime; uint16_t offWaitTime = commandData.offWaitTime; diff --git a/src/app/clusters/scenes-server/scenes-server.cpp b/src/app/clusters/scenes-server/scenes-server.cpp index 29dbab3b119cf9..05e8ec8addb23d 100644 --- a/src/app/clusters/scenes-server/scenes-server.cpp +++ b/src/app/clusters/scenes-server/scenes-server.cpp @@ -31,6 +31,7 @@ #include #include #include +#include using SceneTableEntry = chip::scenes::DefaultSceneTableImpl::SceneTableEntry; using SceneStorageId = chip::scenes::DefaultSceneTableImpl::SceneStorageId; @@ -812,16 +813,19 @@ void ScenesServer::RemoveFabric(EndpointId aEndpointId, FabricIndex aFabricIndex void ScenesServer::HandleAddScene(HandlerContext & ctx, const Commands::AddScene::DecodableType & req) { + MATTER_TRACE_SCOPE("AddScene", "Scenes"); AddSceneParse(ctx, req, mGroupProvider); } void ScenesServer::HandleViewScene(HandlerContext & ctx, const Commands::ViewScene::DecodableType & req) { + MATTER_TRACE_SCOPE("ViewScene", "Scenes"); ViewSceneParse(ctx, req, mGroupProvider); } void ScenesServer::HandleRemoveScene(HandlerContext & ctx, const Commands::RemoveScene::DecodableType & req) { + MATTER_TRACE_SCOPE("RemoveScene", "Scenes"); Commands::RemoveSceneResponse::Type response; uint16_t endpointTableSize = 0; @@ -878,6 +882,7 @@ void ScenesServer::HandleRemoveScene(HandlerContext & ctx, const Commands::Remov void ScenesServer::HandleRemoveAllScenes(HandlerContext & ctx, const Commands::RemoveAllScenes::DecodableType & req) { + MATTER_TRACE_SCOPE("RemoveAllScenes", "Scenes"); Commands::RemoveAllScenesResponse::Type response; uint16_t endpointTableSize = 0; @@ -927,6 +932,7 @@ void ScenesServer::HandleRemoveAllScenes(HandlerContext & ctx, const Commands::R void ScenesServer::HandleStoreScene(HandlerContext & ctx, const Commands::StoreScene::DecodableType & req) { + MATTER_TRACE_SCOPE("StoreScene", "Scenes"); Commands::StoreSceneResponse::Type response; // Response data @@ -947,6 +953,7 @@ void ScenesServer::HandleStoreScene(HandlerContext & ctx, const Commands::StoreS void ScenesServer::HandleRecallScene(HandlerContext & ctx, const Commands::RecallScene::DecodableType & req) { + MATTER_TRACE_SCOPE("RecallScene", "Scenes"); CHIP_ERROR err = RecallSceneParse(ctx.mCommandHandler.GetAccessingFabricIndex(), ctx.mRequestPath.mEndpointId, req.groupID, req.sceneID, req.transitionTime, mGroupProvider); @@ -968,6 +975,7 @@ void ScenesServer::HandleRecallScene(HandlerContext & ctx, const Commands::Recal void ScenesServer::HandleGetSceneMembership(HandlerContext & ctx, const Commands::GetSceneMembership::DecodableType & req) { + MATTER_TRACE_SCOPE("GetSceneMembership", "Scenes"); Commands::GetSceneMembershipResponse::Type response; uint16_t endpointTableSize = 0; @@ -1014,15 +1022,18 @@ void ScenesServer::HandleGetSceneMembership(HandlerContext & ctx, const Commands void ScenesServer::HandleEnhancedAddScene(HandlerContext & ctx, const Commands::EnhancedAddScene::DecodableType & req) { + MATTER_TRACE_SCOPE("EnhancedAddScene", "Scenes"); AddSceneParse(ctx, req, mGroupProvider); } void ScenesServer::HandleEnhancedViewScene(HandlerContext & ctx, const Commands::EnhancedViewScene::DecodableType & req) { + MATTER_TRACE_SCOPE("EnhancedViewScene", "Scenes"); ViewSceneParse(ctx, req, mGroupProvider); } void ScenesServer::HandleCopyScene(HandlerContext & ctx, const Commands::CopyScene::DecodableType & req) { + MATTER_TRACE_SCOPE("CopyScene", "Scenes"); Commands::CopySceneResponse::Type response; uint16_t endpointTableSize = 0; diff --git a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp index 52a98d7b157b82..bd02f36d731cf2 100644 --- a/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp +++ b/src/app/clusters/wifi-network-diagnostics-server/wifi-network-diagnostics-server.cpp @@ -27,6 +27,7 @@ #include #include #include +#include using namespace chip; using namespace chip::app; @@ -242,6 +243,7 @@ class WiFiDiagnosticsDelegate : public DeviceLayer::WiFiDiagnosticsDelegate // Gets called when the Node detects Node’s Wi-Fi connection has been disconnected. void OnDisconnectionDetected(uint16_t reasonCode) override { + MATTER_TRACE_SCOPE("OnDisconnectionDetected", "WiFiDiagnosticsDelegate"); ChipLogProgress(Zcl, "WiFiDiagnosticsDelegate: OnDisconnectionDetected"); for (auto endpoint : EnabledEndpointsWithServerCluster(WiFiNetworkDiagnostics::Id)) @@ -260,6 +262,7 @@ class WiFiDiagnosticsDelegate : public DeviceLayer::WiFiDiagnosticsDelegate // Gets called when the Node fails to associate or authenticate an access point. void OnAssociationFailureDetected(uint8_t associationFailureCause, uint16_t status) override { + MATTER_TRACE_SCOPE("OnAssociationFailureDetected", "WiFiDiagnosticsDelegate"); ChipLogProgress(Zcl, "WiFiDiagnosticsDelegate: OnAssociationFailureDetected"); Events::AssociationFailure::Type event{ static_cast(associationFailureCause), status }; @@ -279,6 +282,7 @@ class WiFiDiagnosticsDelegate : public DeviceLayer::WiFiDiagnosticsDelegate // Gets when the Node’s connection status to a Wi-Fi network has changed. void OnConnectionStatusChanged(uint8_t connectionStatus) override { + MATTER_TRACE_SCOPE("OnConnectionStatusChanged", "WiFiDiagnosticsDelegate"); ChipLogProgress(Zcl, "WiFiDiagnosticsDelegate: OnConnectionStatusChanged"); Events::ConnectionStatus::Type event{ static_cast(connectionStatus) }; diff --git a/src/app/server/Dnssd.cpp b/src/app/server/Dnssd.cpp index 81c3754b891412..e91ef563007cfb 100644 --- a/src/app/server/Dnssd.cpp +++ b/src/app/server/Dnssd.cpp @@ -329,13 +329,20 @@ CHIP_ERROR DnssdServer::Advertise(bool commissionableNode, chip::Dnssd::Commissi } } } +#if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_PASSCODE + else + { + advertiseParameters.SetCommissionerPasscodeSupported(Optional(true)); + } +#endif auto & mdnsAdvertiser = chip::Dnssd::ServiceAdvertiser::Instance(); - ChipLogProgress(Discovery, "Advertise commission parameter vendorID=%u productID=%u discriminator=%04u/%02u cm=%u", + ChipLogProgress(Discovery, "Advertise commission parameter vendorID=%u productID=%u discriminator=%04u/%02u cm=%u cp=%u", advertiseParameters.GetVendorId().ValueOr(0), advertiseParameters.GetProductId().ValueOr(0), advertiseParameters.GetLongDiscriminator(), advertiseParameters.GetShortDiscriminator(), - to_underlying(advertiseParameters.GetCommissioningMode())); + to_underlying(advertiseParameters.GetCommissioningMode()), + advertiseParameters.GetCommissionerPasscodeSupported().ValueOr(false) ? 1 : 0); return mdnsAdvertiser.Advertise(advertiseParameters); } diff --git a/src/app/server/Server.cpp b/src/app/server/Server.cpp index eb9b5835dd23d5..4a0fa91f56d520 100644 --- a/src/app/server/Server.cpp +++ b/src/app/server/Server.cpp @@ -567,65 +567,84 @@ void Server::Shutdown() // NOTE: UDC client is located in Server.cpp because it really only makes sense // to send UDC from a Matter device. The UDC message payload needs to include the device's // randomly generated service name. -CHIP_ERROR Server::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner) +CHIP_ERROR Server::SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner, + Protocols::UserDirectedCommissioning::IdentificationDeclaration & id) { ChipLogDetail(AppServer, "SendUserDirectedCommissioningRequest2"); CHIP_ERROR err; - char nameBuffer[chip::Dnssd::Commission::kInstanceNameMaxLength + 1]; - err = app::DnssdServer::Instance().GetCommissionableInstanceName(nameBuffer, sizeof(nameBuffer)); - if (err != CHIP_NO_ERROR) - { - ChipLogError(AppServer, "Failed to get mdns instance name error: %" CHIP_ERROR_FORMAT, err.Format()); - return err; - } - ChipLogDetail(AppServer, "instanceName=%s", nameBuffer); - - Protocols::UserDirectedCommissioning::IdentificationDeclaration id; - id.SetInstanceName(nameBuffer); - uint16_t vendorId = 0; - if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendorId) != CHIP_NO_ERROR) + // only populate fields left blank by the client + if (strlen(id.GetInstanceName()) == 0) { - ChipLogDetail(Discovery, "Vendor ID not known"); - } - else - { - id.SetVendorId(vendorId); + char nameBuffer[chip::Dnssd::Commission::kInstanceNameMaxLength + 1]; + err = app::DnssdServer::Instance().GetCommissionableInstanceName(nameBuffer, sizeof(nameBuffer)); + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "Failed to get mdns instance name error: %" CHIP_ERROR_FORMAT, err.Format()); + return err; + } + id.SetInstanceName(nameBuffer); } + ChipLogDetail(AppServer, "instanceName=%s", id.GetInstanceName()); - uint16_t productId = 0; - if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(productId) != CHIP_NO_ERROR) - { - ChipLogDetail(Discovery, "Product ID not known"); - } - else + if (id.GetVendorId() == 0) { - id.SetProductId(productId); + uint16_t vendorId = 0; + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetVendorId(vendorId) != CHIP_NO_ERROR) + { + ChipLogDetail(Discovery, "Vendor ID not known"); + } + else + { + id.SetVendorId(vendorId); + } } - char deviceName[chip::Dnssd::kKeyDeviceNameMaxLength + 1] = {}; - if (!chip::DeviceLayer::ConfigurationMgr().IsCommissionableDeviceNameEnabled() || - chip::DeviceLayer::ConfigurationMgr().GetCommissionableDeviceName(deviceName, sizeof(deviceName)) != CHIP_NO_ERROR) + if (id.GetProductId() == 0) { - ChipLogDetail(Discovery, "Device Name not known"); + uint16_t productId = 0; + if (DeviceLayer::GetDeviceInstanceInfoProvider()->GetProductId(productId) != CHIP_NO_ERROR) + { + ChipLogDetail(Discovery, "Product ID not known"); + } + else + { + id.SetProductId(productId); + } } - else + + if (strlen(id.GetDeviceName()) == 0) { - id.SetDeviceName(deviceName); + char deviceName[chip::Dnssd::kKeyDeviceNameMaxLength + 1] = {}; + if (!chip::DeviceLayer::ConfigurationMgr().IsCommissionableDeviceNameEnabled() || + chip::DeviceLayer::ConfigurationMgr().GetCommissionableDeviceName(deviceName, sizeof(deviceName)) != CHIP_NO_ERROR) + { + ChipLogDetail(Discovery, "Device Name not known"); + } + else + { + id.SetDeviceName(deviceName); + } } #if CHIP_ENABLE_ROTATING_DEVICE_ID && defined(CHIP_DEVICE_CONFIG_ROTATING_DEVICE_ID_UNIQUE_ID) - char rotatingDeviceIdHexBuffer[RotatingDeviceId::kHexMaxLength]; - ReturnErrorOnFailure( - app::DnssdServer::Instance().GenerateRotatingDeviceId(rotatingDeviceIdHexBuffer, ArraySize(rotatingDeviceIdHexBuffer))); + if (id.GetRotatingIdLength() == 0) + { + char rotatingDeviceIdHexBuffer[RotatingDeviceId::kHexMaxLength]; + ReturnErrorOnFailure( + app::DnssdServer::Instance().GenerateRotatingDeviceId(rotatingDeviceIdHexBuffer, ArraySize(rotatingDeviceIdHexBuffer))); - uint8_t * rotatingId = reinterpret_cast(rotatingDeviceIdHexBuffer); - size_t rotatingIdLen = strlen(rotatingDeviceIdHexBuffer); - id.SetRotatingId(rotatingId, rotatingIdLen); + uint8_t * rotatingId = reinterpret_cast(rotatingDeviceIdHexBuffer); + size_t rotatingIdLen = strlen(rotatingDeviceIdHexBuffer); + id.SetRotatingId(rotatingId, rotatingIdLen); + } #endif - id.SetCdPort(mCdcListenPort); + if (id.GetCdPort() == 0) + { + id.SetCdPort(mCdcListenPort); + } err = gUDCClient->SendUDCMessage(&mTransports, id, commissioner); diff --git a/src/app/server/Server.h b/src/app/server/Server.h index e6263ccddc6431..e574b52b159957 100644 --- a/src/app/server/Server.h +++ b/src/app/server/Server.h @@ -314,7 +314,14 @@ class Server CHIP_ERROR Init(const ServerInitParams & initParams); #if CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT - CHIP_ERROR SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner); + CHIP_ERROR + SendUserDirectedCommissioningRequest(chip::Transport::PeerAddress commissioner, + Protocols::UserDirectedCommissioning::IdentificationDeclaration & id); + + Protocols::UserDirectedCommissioning::UserDirectedCommissioningClient * GetUserDirectedCommissioningClient() + { + return gUDCClient; + } #endif // CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT /** diff --git a/src/app/zap-templates/zcl/data-model/chip/device-energy-management-cluster.xml b/src/app/zap-templates/zcl/data-model/chip/device-energy-management-cluster.xml index 1d98820d274442..01aef8e7bc06ae 100644 --- a/src/app/zap-templates/zcl/data-model/chip/device-energy-management-cluster.xml +++ b/src/app/zap-templates/zcl/data-model/chip/device-energy-management-cluster.xml @@ -18,11 +18,15 @@ limitations under the License. - - - - + + + + + + + + Device Energy Management Energy Management @@ -31,53 +35,61 @@ limitations under the License. true true This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). - - + - ESAType - ESACanGenerate - ESAState + ESAType + ESACanGenerate + ESAState AbsMinPower AbsMaxPower - PowerAdjustmentCapability + PowerAdjustmentCapability Forecast - + OptOutState + + Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. - Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. + - + Allows a client to cancel an ongoing PowerAdjustmentRequest operation. - - + Allows a client to adjust the start time of a Forecast sequence that has not yet started operation (i.e. where the current Forecast StartTime is in the future). + + - - + Allows a client to temporarily pause an operation and reduce the ESAs energy demand. + + - + Allows a client to cancel the PauseRequest command and enable earlier resumption of operation. - - - + Allows a client to modify a Forecast within the limits allowed by the ESA. + + + - - + Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. + + + + + Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command PowerAdjustStart PowerAdjustEnd - + @@ -86,6 +98,7 @@ limitations under the License. Resumed + @@ -95,6 +108,7 @@ limitations under the License. + @@ -113,47 +127,75 @@ limitations under the License. + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - - + + + + - - + + - + - + + + @@ -161,26 +203,28 @@ limitations under the License. - - - + + + - + + + @@ -189,4 +233,5 @@ limitations under the License. + diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index b071fd42c77cb8..7cf25d5e4c4795 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -186,6 +186,7 @@ "AbsMaxPower", "PowerAdjustmentCapability", "Forecast", + "OptOutState", "FeatureMap" ], "Energy EVSE": [ diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index c645c66e91fc5c..addb14b89f25ba 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -184,6 +184,7 @@ "AbsMaxPower", "PowerAdjustmentCapability", "Forecast", + "OptOutState", "FeatureMap" ], "Energy EVSE": [ diff --git a/src/controller/CommissionerDiscoveryController.cpp b/src/controller/CommissionerDiscoveryController.cpp index bd6bee4d098078..c1c6492636ecd0 100644 --- a/src/controller/CommissionerDiscoveryController.cpp +++ b/src/controller/CommissionerDiscoveryController.cpp @@ -50,6 +50,47 @@ void CommissionerDiscoveryController::OnUserDirectedCommissioningRequest(UDCClie ChipLogDetail(Controller, "CommissionerDiscoveryController not read. Current instance=%s", mCurrentInstance); return; } + // first check if this is a cancel + if (state.GetCancelPasscode()) + { + ChipLogDetail(Controller, "------PROMPT USER: %s cancelled commissioning [" ChipLogFormatMEI "," ChipLogFormatMEI ",%s]", + state.GetDeviceName(), ChipLogValueMEI(state.GetVendorId()), ChipLogValueMEI(state.GetProductId()), + state.GetInstanceName()); + if (mUserPrompter != nullptr) + { + mUserPrompter->HidePromptsOnCancel(state.GetVendorId(), state.GetProductId(), state.GetDeviceName()); + } + return; + } + if (state.GetCommissionerPasscodeReady() && state.GetCdPort() != 0) + { + uint32_t passcode = state.GetCachedCommissionerPasscode(); + if (!mReady || passcode == 0) + { + ChipLogError(AppServer, "On UDC: commissioner passcode ready but no passcode"); + CommissionerDeclaration cd; + cd.SetErrorCode(CommissionerDeclaration::CdError::kUnexpectedCommissionerPasscodeReady); + + if (mUdcServer == nullptr) + { + ChipLogError(AppServer, "On UDC: no udc server"); + return; + } + mUdcServer->SendCDCMessage(cd, + chip::Transport::PeerAddress::UDP(state.GetPeerAddress().GetIPAddress(), state.GetCdPort())); + return; + } + else + { + // can only get here is ok() has already been called + ChipLogError(AppServer, "On UDC: commissioner passcode ready with passcode - commissioning"); + + // start commissioning using the cached passcode + CommissionWithPasscode(passcode); + return; + } + } + mReady = false; Platform::CopyString(mCurrentInstance, state.GetInstanceName()); mPendingConsent = true; @@ -73,7 +114,7 @@ void CommissionerDiscoveryController::Ok() { if (!mPendingConsent) { - ChipLogError(AppServer, "UX Cancel: no current instance"); + ChipLogError(AppServer, "UX Ok: no current instance"); return; } if (mUdcServer == nullptr) @@ -94,7 +135,7 @@ void CommissionerDiscoveryController::Ok() } client->SetUDCClientProcessingState(UDCClientProcessingState::kObtainingOnboardingPayload); - if (mPincodeService != nullptr) + if (mPasscodeService != nullptr) { char rotatingIdString[chip::Dnssd::kMaxRotatingIdLen * 2 + 1] = ""; Encoding::BytesToUppercaseHexString(client->GetRotatingId(), client->GetRotatingIdLength(), rotatingIdString, @@ -103,24 +144,122 @@ void CommissionerDiscoveryController::Ok() // sizeof(rotatingIdString)); CharSpan rotatingIdSpan = chip::CharSpan(rotatingIdString, sizeof(rotatingIdString)); - uint32_t pincode = - mPincodeService->FetchCommissionPincodeFromContentApp(client->GetVendorId(), client->GetProductId(), rotatingIdSpan); - if (pincode != 0) + uint32_t passcode = 0; + uint8_t targetAppCount = client->GetNumTargetAppInfos(); + if (targetAppCount > 0) + { + bool hasTargetApp = false; + for (uint8_t i = 0; i < targetAppCount; i++) + { + TargetAppInfo info; + if (client->GetTargetAppInfo(i, info)) + { + if (mPasscodeService->HasTargetContentApp(client->GetVendorId(), client->GetProductId(), rotatingIdSpan, info, + passcode)) + { + // found one + hasTargetApp = true; + } + } + } + // handle NoAppsFound CDC case + if (!hasTargetApp) + { + ChipLogError(AppServer, "UX Ok: target apps specified but none found, sending CDC"); + CommissionerDeclaration cd; + cd.SetNoAppsFound(true); + mUdcServer->SendCDCMessage( + cd, chip::Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); + return; + } + } + else + { + passcode = mPasscodeService->FetchCommissionPasscodeFromContentApp(client->GetVendorId(), client->GetProductId(), + rotatingIdSpan); + } + + // if CommissionerPasscode + // - if CommissionerPasscodeReady, then start commissioning + // - if CommissionerPasscode, then call new UX method to show passcode, send CDC + if (passcode == 0 && client->GetCommissionerPasscode() && client->GetCdPort() != 0) + { + // first step of commissioner passcode + ChipLogError(AppServer, "UX Ok: commissioner passcode, sending CDC"); + // generate a passcode + passcode = mPasscodeService->GetCommissionerPasscode(client->GetVendorId(), client->GetProductId(), rotatingIdSpan); + if (passcode == 0) + { + // passcode feature disabled + ChipLogError(AppServer, "UX Ok: commissioner passcode disabled, sending CDC with error"); + CommissionerDeclaration cd; + cd.SetErrorCode(CommissionerDeclaration::CdError::kCommissionerPasscodeDisabled); + cd.SetNeedsPasscode(true); + mUdcServer->SendCDCMessage( + cd, chip::Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); + return; + } + client->SetCachedCommissionerPasscode(passcode); + + CommissionerDeclaration cd; + cd.SetCommissionerPasscode(true); + if (mUserPrompter->DisplaysPasscodeAndQRCode()) + { + cd.SetQRCodeDisplayed(true); + } + mUdcServer->SendCDCMessage( + cd, chip::Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); + + // dialog + ChipLogDetail(Controller, + "------PROMPT USER: %s is requesting permission to cast to this TV. Casting passcode: [" ChipLogFormatMEI + "]. Additional instructions [" ChipLogFormatMEI "] [%s]. [" ChipLogFormatMEI "," ChipLogFormatMEI ",%s]", + client->GetDeviceName(), ChipLogValueMEI(passcode), ChipLogValueMEI(client->GetPairingHint()), + client->GetPairingInst(), ChipLogValueMEI(client->GetVendorId()), ChipLogValueMEI(client->GetProductId()), + client->GetInstanceName()); + mUserPrompter->PromptWithCommissionerPasscode(client->GetVendorId(), client->GetProductId(), client->GetDeviceName(), + passcode, client->GetPairingHint(), client->GetPairingInst()); + return; + } + if (passcode != 0) { - CommissionWithPincode(pincode); + CommissionWithPasscode(passcode); return; } } - ChipLogDetail(Controller, "------PROMPT USER: please enter pin displayed in casting app "); + // if NoPasscode, send CDC + if (client->GetNoPasscode() && client->GetCdPort() != 0) + { + ChipLogError(AppServer, "UX Ok: no app passcode and NoPasscode in UDC, sending CDC"); + CommissionerDeclaration cd; + cd.SetNeedsPasscode(true); + mUdcServer->SendCDCMessage(cd, + chip::Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); + return; + } + + // if CdUponPasscodeDialog, send CDC + if (client->GetCdUponPasscodeDialog() && client->GetCdPort() != 0) + { + ChipLogError(AppServer, "UX Ok: no app passcode and GetCdUponPasscodeDialog in UDC, sending CDC"); + CommissionerDeclaration cd; + cd.SetNeedsPasscode(true); // TODO: should this be set? + cd.SetPasscodeDialogDisplayed(true); + mUdcServer->SendCDCMessage(cd, + chip::Transport::PeerAddress::UDP(client->GetPeerAddress().GetIPAddress(), client->GetCdPort())); + } + + ChipLogDetail(Controller, "------PROMPT USER: please enter passcode displayed in casting app "); if (mUserPrompter != nullptr) { - mUserPrompter->PromptForCommissionPincode(client->GetVendorId(), client->GetProductId(), client->GetDeviceName()); + mUserPrompter->PromptForCommissionPasscode(client->GetVendorId(), client->GetProductId(), client->GetDeviceName(), + client->GetPairingHint(), client->GetPairingInst()); } - ChipLogDetail(Controller, "------Via Shell Enter: controller ux ok [pincode]"); + ChipLogDetail(Controller, "------Via Shell Enter: controller ux ok [passcode]"); } -void CommissionerDiscoveryController::CommissionWithPincode(uint32_t pincode) +void CommissionerDiscoveryController::CommissionWithPasscode(uint32_t passcode) { if (!mPendingConsent) { @@ -129,7 +268,7 @@ void CommissionerDiscoveryController::CommissionWithPincode(uint32_t pincode) } if (mUdcServer == nullptr) { - ChipLogError(AppServer, "UX CommissionWithPincode: no udc server"); + ChipLogError(AppServer, "UX CommissionWithPasscode: no udc server"); return; } UDCClientState * client = mUdcServer->GetUDCClients().FindUDCClientState(mCurrentInstance); @@ -142,14 +281,18 @@ void CommissionerDiscoveryController::CommissionWithPincode(uint32_t pincode) if (!(client->GetUDCClientProcessingState() == UDCClientProcessingState::kPromptingUser || client->GetUDCClientProcessingState() == UDCClientProcessingState::kObtainingOnboardingPayload)) { - ChipLogError(AppServer, "UX CommissionWithPincode: invalid state for CommissionWithPincode"); + ChipLogError(AppServer, "UX CommissionWithPasscode: invalid state for CommissionWithPasscode"); return; } Transport::PeerAddress peerAddress = client->GetPeerAddress(); client->SetUDCClientProcessingState(UDCClientProcessingState::kCommissioningNode); if (mCommissionerCallback != nullptr) { - mCommissionerCallback->ReadyForCommissioning(pincode, client->GetLongDiscriminator(), peerAddress); + if (mUserPrompter != nullptr) + { + mUserPrompter->PromptCommissioningStarted(client->GetVendorId(), client->GetProductId(), client->GetDeviceName()); + } + mCommissionerCallback->ReadyForCommissioning(passcode, client->GetLongDiscriminator(), peerAddress); } } diff --git a/src/controller/CommissionerDiscoveryController.h b/src/controller/CommissionerDiscoveryController.h index 8d7fee99e3d25b..42a0bb6f327fc9 100644 --- a/src/controller/CommissionerDiscoveryController.h +++ b/src/controller/CommissionerDiscoveryController.h @@ -65,18 +65,70 @@ class DLL_EXPORT UserPrompter /** * @brief - * Called to prompt the user to enter the setup pincode displayed by the given commissioneeName/vendorId/productId to be - * commissioned. For example "Please enter pin displayed in casting app." + * Called to prompt the user to enter the setup passcode displayed by the given commissioneeName/vendorId/productId to be + * commissioned. For example "Please enter passcode displayed in casting app." * - * If user enters with pin then implementor should call CommissionerRespondPincode(uint32_t pincode); + * If user enters passcode then implementor should call CommissionerRespondPasscode(uint32_t passcode); * If user responds with Cancel then implementor should call CommissionerRespondCancel(); * * @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee. * @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee. * @param[in] commissioneeName The commissioneeName in the DNS-SD advertisement of the requesting commissionee. + * @param[in] pairingHint The pairingHint in the DNS-SD advertisement of the requesting commissionee. + * @param[in] pairingInstruction The pairingInstruction in the DNS-SD advertisement of the requesting commissionee. * */ - virtual void PromptForCommissionPincode(uint16_t vendorId, uint16_t productId, const char * commissioneeName) = 0; + virtual void PromptForCommissionPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint16_t pairingHint, const char * pairingInstruction) = 0; + + /** + * @brief + * Called to when CancelCommissioning is received via UDC. + * Indicates that commissioner can stop showing the passcode entry or display dialog. + * For example, can show text such as "Commissioning cancelled by client" before hiding dialog. + * + * @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] commissioneeName The commissioneeName in the DNS-SD advertisement of the requesting commissionee. + * + */ + virtual void HidePromptsOnCancel(uint16_t vendorId, uint16_t productId, const char * commissioneeName) = 0; + + /** + * @brief + * Return true if this UserPrompter displays QR code along with passcode + * When PromptWithCommissionerPasscode is called during Commissioner Passcode functionality. + */ + virtual bool DisplaysPasscodeAndQRCode() = 0; + + /** + * @brief + * Called to display the given setup passcode to the user, + * for commissioning the given commissioneeName with the given vendorId and productId, + * and provide instructions for where to enter it in the commissionee (when pairingHint and pairingInstruction are provided). + * For example "Casting Passcode: [passcode]. For more instructions, click here." + * + * @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] commissioneeName The commissioneeName in the DNS-SD advertisement of the requesting commissionee. + * @param[in] passcode The passcode to display. + * @param[in] pairingHint The pairingHint in the DNS-SD advertisement of the requesting commissionee. + * @param[in] pairingInstruction The pairingInstruction in the DNS-SD advertisement of the requesting commissionee. + * + */ + virtual void PromptWithCommissionerPasscode(uint16_t vendorId, uint16_t productId, const char * commissioneeName, + uint32_t passcode, uint16_t pairingHint, const char * pairingInstruction) = 0; + + /** + * @brief + * Called to alert the user that commissioning has begun." + * + * @param[in] vendorId The vendorid from the DAC of the new node. + * @param[in] productId The productid from the DAC of the new node. + * @param[in] commissioneeName The commissioneeName in the DNS-SD advertisement of the requesting commissionee. + * + */ + virtual void PromptCommissioningStarted(uint16_t vendorId, uint16_t productId, const char * commissioneeName) = 0; /** * @brief @@ -101,13 +153,41 @@ class DLL_EXPORT UserPrompter virtual ~UserPrompter() = default; }; -class DLL_EXPORT PincodeService +// TODO: rename this to Passcode? +class DLL_EXPORT PasscodeService { public: /** * @brief - * Called to get the setup pincode from the content app corresponding to the given vendorId/productId - * Returns 0 if pincode cannot be obtained + * Called to determine if the given target app is available to the commissionee with the given given + * vendorId/productId, and if so, return the passcode. + * + * @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] rotatingId The rotatingId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] info App info to look for. + * @param[in] passcode Passcode for the given commissionee, or 0 if passcode cannot be obtained. + * + */ + virtual bool HasTargetContentApp(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId, + chip::Protocols::UserDirectedCommissioning::TargetAppInfo & info, uint32_t & passcode) = 0; + + /** + * @brief + * Called to get the commissioner-generated setup passcode. + * Returns 0 if feature is disabled. + * + * @param[in] vendorId The vendorId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] productId The productId in the DNS-SD advertisement of the requesting commissionee. + * @param[in] rotatingId The rotatingId in the DNS-SD advertisement of the requesting commissionee. + * + */ + virtual uint32_t GetCommissionerPasscode(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId) = 0; + + /** + * @brief + * Called to get the setup passcode from the content app corresponding to the given vendorId/productId + * Returns 0 if passcode cannot be obtained * * If user responds with OK then implementor should call CommissionerRespondOk(); * If user responds with Cancel then implementor should call CommissionerRespondCancel(); @@ -117,9 +197,9 @@ class DLL_EXPORT PincodeService * @param[in] rotatingId The rotatingId in the DNS-SD advertisement of the requesting commissionee. * */ - virtual uint32_t FetchCommissionPincodeFromContentApp(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId) = 0; + virtual uint32_t FetchCommissionPasscodeFromContentApp(uint16_t vendorId, uint16_t productId, chip::CharSpan rotatingId) = 0; - virtual ~PincodeService() = default; + virtual ~PasscodeService() = default; }; class DLL_EXPORT PostCommissioningListener @@ -152,12 +232,12 @@ class DLL_EXPORT CommissionerCallback * Called to notify the commissioner that commissioning can now proceed for * the node identified by the given arguments. * - * @param[in] pincode The pin code to use for the commissionee. + * @param[in] passcode The passcode to use for the commissionee. * @param[in] longDiscriminator The long discriminator for the commissionee. * @param[in] peerAddress The peerAddress for the commissionee. * */ - virtual void ReadyForCommissioning(uint32_t pincode, uint16_t longDiscriminator, PeerAddress peerAddress) = 0; + virtual void ReadyForCommissioning(uint32_t passcode, uint16_t longDiscriminator, PeerAddress peerAddress) = 0; virtual ~CommissionerCallback() = default; }; @@ -201,10 +281,10 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm void Cancel(); /** - * This method should be called with the pincode for the client - * indicated in the UserPrompter's PromptForCommissionPincode callback + * This method should be called with the passcode for the client + * indicated in the UserPrompter's PromptForCommissionPasscode callback */ - void CommissionWithPincode(uint32_t pincode); + void CommissionWithPasscode(uint32_t passcode); /** * This method should be called by the commissioner to indicate that commissioning succeeded. @@ -253,9 +333,9 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm inline void SetUserPrompter(UserPrompter * userPrompter) { mUserPrompter = userPrompter; } /** - * Assign a PincodeService + * Assign a PasscodeService */ - inline void SetPincodeService(PincodeService * pincodeService) { mPincodeService = pincodeService; } + inline void SetPasscodeService(PasscodeService * passcodeService) { mPasscodeService = passcodeService; } /** * Assign a Commissioner Callback to perform commissioning once user consent has been given @@ -293,7 +373,7 @@ class CommissionerDiscoveryController : public chip::Protocols::UserDirectedComm UserDirectedCommissioningServer * mUdcServer = nullptr; UserPrompter * mUserPrompter = nullptr; - PincodeService * mPincodeService = nullptr; + PasscodeService * mPasscodeService = nullptr; CommissionerCallback * mCommissionerCallback = nullptr; PostCommissioningListener * mPostCommissioningListener = nullptr; }; diff --git a/src/controller/data_model/controller-clusters.matter b/src/controller/data_model/controller-clusters.matter index 0a2bc772a5bbf9..ea24f74daa5e4c 100644 --- a/src/controller/data_model/controller-clusters.matter +++ b/src/controller/data_model/controller-clusters.matter @@ -4421,13 +4421,19 @@ provisional cluster DemandResponseLoadControl = 150 { /** This cluster allows a client to manage the power draw of a device. An example of such a client could be an Energy Management System (EMS) which controls an Energy Smart Appliance (ESA). */ provisional cluster DeviceEnergyManagement = 152 { - revision 2; + revision 3; + + enum AdjustmentCauseEnum : enum8 { + kLocalOptimization = 0; + kGridOptimization = 1; + } enum CauseEnum : enum8 { kNormalCompletion = 0; kOffline = 1; kFault = 2; kUserOptOut = 3; + kCancelled = 4; } enum CostTypeEnum : enum8 { @@ -4441,9 +4447,8 @@ provisional cluster DeviceEnergyManagement = 152 { kOffline = 0; kOnline = 1; kFault = 2; - kUserOptOut = 3; - kPowerAdjustActive = 4; - kPaused = 5; + kPowerAdjustActive = 3; + kPaused = 4; } enum ESATypeEnum : enum8 { @@ -4464,11 +4469,27 @@ provisional cluster DeviceEnergyManagement = 152 { kOther = 255; } + enum ForecastUpdateReasonEnum : enum8 { + kInternalOptimization = 0; + kLocalOptimization = 1; + kGridOptimization = 2; + } + + enum OptOutStateEnum : enum8 { + kNoOptOut = 0; + kLocalOptOut = 1; + kGridOptOut = 2; + kOptOut = 3; + } + bitmap Feature : bitmap32 { kPowerAdjustment = 0x1; kPowerForecastReporting = 0x2; kStateForecastReporting = 0x4; - kForecastAdjustment = 0x8; + kStartTimeAdjustment = 0x8; + kPausable = 0x10; + kForecastAdjustment = 0x20; + kConstraintBasedAdjustment = 0x40; } struct CostStruct { @@ -4484,9 +4505,9 @@ provisional cluster DeviceEnergyManagement = 152 { elapsed_s defaultDuration = 2; elapsed_s elapsedSlotTime = 3; elapsed_s remainingSlotTime = 4; - boolean slotIsPauseable = 5; - elapsed_s minPauseDuration = 6; - elapsed_s maxPauseDuration = 7; + optional boolean slotIsPauseable = 5; + optional elapsed_s minPauseDuration = 6; + optional elapsed_s maxPauseDuration = 7; optional int16u manufacturerESAState = 8; optional power_mw nominalPower = 9; optional power_mw minPower = 10; @@ -4508,6 +4529,7 @@ provisional cluster DeviceEnergyManagement = 152 { optional epoch_s latestEndTime = 5; boolean isPauseable = 6; SlotStruct slots[] = 7; + ForecastUpdateReasonEnum forecastUpdateReason = 8; } struct ConstraintsStruct { @@ -4544,6 +4566,7 @@ provisional cluster DeviceEnergyManagement = 152 { } info event Resumed = 3 { + CauseEnum cause = 0; } readonly attribute ESATypeEnum ESAType = 0; @@ -4553,6 +4576,7 @@ provisional cluster DeviceEnergyManagement = 152 { readonly attribute power_mw absMaxPower = 4; readonly attribute optional nullable PowerAdjustStruct powerAdjustmentCapability[] = 5; readonly attribute optional nullable ForecastStruct forecast = 6; + readonly attribute optional OptOutStateEnum optOutState = 7; readonly attribute command_id generatedCommandList[] = 65528; readonly attribute command_id acceptedCommandList[] = 65529; readonly attribute event_id eventList[] = 65530; @@ -4563,23 +4587,28 @@ provisional cluster DeviceEnergyManagement = 152 { request struct PowerAdjustRequestRequest { power_mw power = 0; elapsed_s duration = 1; + AdjustmentCauseEnum cause = 2; } request struct StartTimeAdjustRequestRequest { epoch_s requestedStartTime = 0; + AdjustmentCauseEnum cause = 1; } request struct PauseRequestRequest { elapsed_s duration = 0; + AdjustmentCauseEnum cause = 1; } request struct ModifyForecastRequestRequest { int32u forecastId = 0; SlotAdjustmentStruct slotAdjustments[] = 1; + AdjustmentCauseEnum cause = 2; } request struct RequestConstraintBasedForecastRequest { ConstraintsStruct constraints[] = 0; + AdjustmentCauseEnum cause = 1; } /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */ @@ -4596,6 +4625,8 @@ provisional cluster DeviceEnergyManagement = 152 { command ModifyForecastRequest(ModifyForecastRequestRequest): DefaultSuccess = 5; /** Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. */ command RequestConstraintBasedForecast(RequestConstraintBasedForecastRequest): DefaultSuccess = 6; + /** Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command */ + command CancelRequest(): DefaultSuccess = 7; } /** Electric Vehicle Supply Equipment (EVSE) is equipment used to charge an Electric Vehicle (EV) or Plug-In Hybrid Electric Vehicle. This cluster provides an interface to the functionality of Electric Vehicle Supply Equipment (EVSE) management. */ diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java index 0bbc57d9698c34..1e3f65f09fec06 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipClusters.java @@ -29463,6 +29463,7 @@ public static class DeviceEnergyManagementCluster extends BaseChipCluster { private static final long ABS_MAX_POWER_ATTRIBUTE_ID = 4L; private static final long POWER_ADJUSTMENT_CAPABILITY_ATTRIBUTE_ID = 5L; private static final long FORECAST_ATTRIBUTE_ID = 6L; + private static final long OPT_OUT_STATE_ATTRIBUTE_ID = 7L; private static final long GENERATED_COMMAND_LIST_ATTRIBUTE_ID = 65528L; private static final long ACCEPTED_COMMAND_LIST_ATTRIBUTE_ID = 65529L; private static final long EVENT_LIST_ATTRIBUTE_ID = 65530L; @@ -29480,11 +29481,11 @@ public long initWithDevice(long devicePtr, int endpointId) { return 0L; } - public void powerAdjustRequest(DefaultClusterCallback callback, Long power, Long duration) { - powerAdjustRequest(callback, power, duration, 0); + public void powerAdjustRequest(DefaultClusterCallback callback, Long power, Long duration, Integer cause) { + powerAdjustRequest(callback, power, duration, cause, 0); } - public void powerAdjustRequest(DefaultClusterCallback callback, Long power, Long duration, int timedInvokeTimeoutMs) { + public void powerAdjustRequest(DefaultClusterCallback callback, Long power, Long duration, Integer cause, int timedInvokeTimeoutMs) { final long commandId = 0L; ArrayList elements = new ArrayList<>(); @@ -29496,6 +29497,10 @@ public void powerAdjustRequest(DefaultClusterCallback callback, Long power, Long BaseTLVType durationtlvValue = new UIntType(duration); elements.add(new StructElement(durationFieldID, durationtlvValue)); + final long causeFieldID = 2L; + BaseTLVType causetlvValue = new UIntType(cause); + elements.add(new StructElement(causeFieldID, causetlvValue)); + StructType value = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -29520,11 +29525,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, value, timedInvokeTimeoutMs); } - public void startTimeAdjustRequest(DefaultClusterCallback callback, Long requestedStartTime) { - startTimeAdjustRequest(callback, requestedStartTime, 0); + public void startTimeAdjustRequest(DefaultClusterCallback callback, Long requestedStartTime, Integer cause) { + startTimeAdjustRequest(callback, requestedStartTime, cause, 0); } - public void startTimeAdjustRequest(DefaultClusterCallback callback, Long requestedStartTime, int timedInvokeTimeoutMs) { + public void startTimeAdjustRequest(DefaultClusterCallback callback, Long requestedStartTime, Integer cause, int timedInvokeTimeoutMs) { final long commandId = 2L; ArrayList elements = new ArrayList<>(); @@ -29532,6 +29537,10 @@ public void startTimeAdjustRequest(DefaultClusterCallback callback, Long request BaseTLVType requestedStartTimetlvValue = new UIntType(requestedStartTime); elements.add(new StructElement(requestedStartTimeFieldID, requestedStartTimetlvValue)); + final long causeFieldID = 1L; + BaseTLVType causetlvValue = new UIntType(cause); + elements.add(new StructElement(causeFieldID, causetlvValue)); + StructType value = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -29540,11 +29549,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, value, timedInvokeTimeoutMs); } - public void pauseRequest(DefaultClusterCallback callback, Long duration) { - pauseRequest(callback, duration, 0); + public void pauseRequest(DefaultClusterCallback callback, Long duration, Integer cause) { + pauseRequest(callback, duration, cause, 0); } - public void pauseRequest(DefaultClusterCallback callback, Long duration, int timedInvokeTimeoutMs) { + public void pauseRequest(DefaultClusterCallback callback, Long duration, Integer cause, int timedInvokeTimeoutMs) { final long commandId = 3L; ArrayList elements = new ArrayList<>(); @@ -29552,6 +29561,10 @@ public void pauseRequest(DefaultClusterCallback callback, Long duration, int tim BaseTLVType durationtlvValue = new UIntType(duration); elements.add(new StructElement(durationFieldID, durationtlvValue)); + final long causeFieldID = 1L; + BaseTLVType causetlvValue = new UIntType(cause); + elements.add(new StructElement(causeFieldID, causetlvValue)); + StructType value = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -29576,11 +29589,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, value, timedInvokeTimeoutMs); } - public void modifyForecastRequest(DefaultClusterCallback callback, Long forecastId, ArrayList slotAdjustments) { - modifyForecastRequest(callback, forecastId, slotAdjustments, 0); + public void modifyForecastRequest(DefaultClusterCallback callback, Long forecastId, ArrayList slotAdjustments, Integer cause) { + modifyForecastRequest(callback, forecastId, slotAdjustments, cause, 0); } - public void modifyForecastRequest(DefaultClusterCallback callback, Long forecastId, ArrayList slotAdjustments, int timedInvokeTimeoutMs) { + public void modifyForecastRequest(DefaultClusterCallback callback, Long forecastId, ArrayList slotAdjustments, Integer cause, int timedInvokeTimeoutMs) { final long commandId = 5L; ArrayList elements = new ArrayList<>(); @@ -29592,6 +29605,10 @@ public void modifyForecastRequest(DefaultClusterCallback callback, Long forecast BaseTLVType slotAdjustmentstlvValue = ArrayType.generateArrayType(slotAdjustments, (elementslotAdjustments) -> elementslotAdjustments.encodeTlv()); elements.add(new StructElement(slotAdjustmentsFieldID, slotAdjustmentstlvValue)); + final long causeFieldID = 2L; + BaseTLVType causetlvValue = new UIntType(cause); + elements.add(new StructElement(causeFieldID, causetlvValue)); + StructType value = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -29600,11 +29617,11 @@ public void onResponse(StructType invokeStructValue) { }}, commandId, value, timedInvokeTimeoutMs); } - public void requestConstraintBasedForecast(DefaultClusterCallback callback, ArrayList constraints) { - requestConstraintBasedForecast(callback, constraints, 0); + public void requestConstraintBasedForecast(DefaultClusterCallback callback, ArrayList constraints, Integer cause) { + requestConstraintBasedForecast(callback, constraints, cause, 0); } - public void requestConstraintBasedForecast(DefaultClusterCallback callback, ArrayList constraints, int timedInvokeTimeoutMs) { + public void requestConstraintBasedForecast(DefaultClusterCallback callback, ArrayList constraints, Integer cause, int timedInvokeTimeoutMs) { final long commandId = 6L; ArrayList elements = new ArrayList<>(); @@ -29612,6 +29629,26 @@ public void requestConstraintBasedForecast(DefaultClusterCallback callback, Arra BaseTLVType constraintstlvValue = ArrayType.generateArrayType(constraints, (elementconstraints) -> elementconstraints.encodeTlv()); elements.add(new StructElement(constraintsFieldID, constraintstlvValue)); + final long causeFieldID = 1L; + BaseTLVType causetlvValue = new UIntType(cause); + elements.add(new StructElement(causeFieldID, causetlvValue)); + + StructType value = new StructType(elements); + invoke(new InvokeCallbackImpl(callback) { + @Override + public void onResponse(StructType invokeStructValue) { + callback.onSuccess(); + }}, commandId, value, timedInvokeTimeoutMs); + } + + public void cancelRequest(DefaultClusterCallback callback) { + cancelRequest(callback, 0); + } + + public void cancelRequest(DefaultClusterCallback callback, int timedInvokeTimeoutMs) { + final long commandId = 7L; + + ArrayList elements = new ArrayList<>(); StructType value = new StructType(elements); invoke(new InvokeCallbackImpl(callback) { @Override @@ -29819,6 +29856,31 @@ public void onSuccess(byte[] tlv) { }, FORECAST_ATTRIBUTE_ID, minInterval, maxInterval); } + public void readOptOutStateAttribute( + IntegerAttributeCallback callback) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, OPT_OUT_STATE_ATTRIBUTE_ID); + + readAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Integer value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + callback.onSuccess(value); + } + }, OPT_OUT_STATE_ATTRIBUTE_ID, true); + } + + public void subscribeOptOutStateAttribute( + IntegerAttributeCallback callback, int minInterval, int maxInterval) { + ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, OPT_OUT_STATE_ATTRIBUTE_ID); + + subscribeAttribute(new ReportCallbackImpl(callback, path) { + @Override + public void onSuccess(byte[] tlv) { + Integer value = ChipTLVValueDecoder.decodeAttributeValue(path, tlv); + } + }, OPT_OUT_STATE_ATTRIBUTE_ID, minInterval, maxInterval); + } + public void readGeneratedCommandListAttribute( GeneratedCommandListAttributeCallback callback) { ChipAttributePath path = ChipAttributePath.newInstance(endpointId, clusterId, GENERATED_COMMAND_LIST_ATTRIBUTE_ID); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java index 9f5c25260c131b..c1d134f2735191 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipEventStructs.java @@ -3921,13 +3921,18 @@ public String toString() { } } public static class DeviceEnergyManagementClusterResumedEvent { + public Integer cause; + private static final long CAUSE_ID = 0L; public DeviceEnergyManagementClusterResumedEvent( + Integer cause ) { + this.cause = cause; } public StructType encodeTlv() { ArrayList values = new ArrayList<>(); + values.add(new StructElement(CAUSE_ID, new UIntType(cause))); return new StructType(values); } @@ -3936,7 +3941,17 @@ public static DeviceEnergyManagementClusterResumedEvent decodeTlv(BaseTLVType tl if (tlvValue == null || tlvValue.type() != TLVType.Struct) { return null; } + Integer cause = null; + for (StructElement element: ((StructType)tlvValue).value()) { + if (element.contextTagNum() == CAUSE_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + cause = castingValue.value(Integer.class); + } + } + } return new DeviceEnergyManagementClusterResumedEvent( + cause ); } @@ -3944,6 +3959,9 @@ public static DeviceEnergyManagementClusterResumedEvent decodeTlv(BaseTLVType tl public String toString() { StringBuilder output = new StringBuilder(); output.append("DeviceEnergyManagementClusterResumedEvent {\n"); + output.append("\tcause: "); + output.append(cause); + output.append("\n"); output.append("}\n"); return output.toString(); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java index c676d026aa2597..6aa20f9a2f796c 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ChipStructs.java @@ -6556,9 +6556,9 @@ public static class DeviceEnergyManagementClusterSlotStruct { public Long defaultDuration; public Long elapsedSlotTime; public Long remainingSlotTime; - public Boolean slotIsPauseable; - public Long minPauseDuration; - public Long maxPauseDuration; + public Optional slotIsPauseable; + public Optional minPauseDuration; + public Optional maxPauseDuration; public Optional manufacturerESAState; public Optional nominalPower; public Optional minPower; @@ -6594,9 +6594,9 @@ public DeviceEnergyManagementClusterSlotStruct( Long defaultDuration, Long elapsedSlotTime, Long remainingSlotTime, - Boolean slotIsPauseable, - Long minPauseDuration, - Long maxPauseDuration, + Optional slotIsPauseable, + Optional minPauseDuration, + Optional maxPauseDuration, Optional manufacturerESAState, Optional nominalPower, Optional minPower, @@ -6635,9 +6635,9 @@ public StructType encodeTlv() { values.add(new StructElement(DEFAULT_DURATION_ID, new UIntType(defaultDuration))); values.add(new StructElement(ELAPSED_SLOT_TIME_ID, new UIntType(elapsedSlotTime))); values.add(new StructElement(REMAINING_SLOT_TIME_ID, new UIntType(remainingSlotTime))); - values.add(new StructElement(SLOT_IS_PAUSEABLE_ID, new BooleanType(slotIsPauseable))); - values.add(new StructElement(MIN_PAUSE_DURATION_ID, new UIntType(minPauseDuration))); - values.add(new StructElement(MAX_PAUSE_DURATION_ID, new UIntType(maxPauseDuration))); + values.add(new StructElement(SLOT_IS_PAUSEABLE_ID, slotIsPauseable.map((nonOptionalslotIsPauseable) -> new BooleanType(nonOptionalslotIsPauseable)).orElse(new EmptyType()))); + values.add(new StructElement(MIN_PAUSE_DURATION_ID, minPauseDuration.map((nonOptionalminPauseDuration) -> new UIntType(nonOptionalminPauseDuration)).orElse(new EmptyType()))); + values.add(new StructElement(MAX_PAUSE_DURATION_ID, maxPauseDuration.map((nonOptionalmaxPauseDuration) -> new UIntType(nonOptionalmaxPauseDuration)).orElse(new EmptyType()))); values.add(new StructElement(MANUFACTURER_E_S_A_STATE_ID, manufacturerESAState.map((nonOptionalmanufacturerESAState) -> new UIntType(nonOptionalmanufacturerESAState)).orElse(new EmptyType()))); values.add(new StructElement(NOMINAL_POWER_ID, nominalPower.map((nonOptionalnominalPower) -> new IntType(nonOptionalnominalPower)).orElse(new EmptyType()))); values.add(new StructElement(MIN_POWER_ID, minPower.map((nonOptionalminPower) -> new IntType(nonOptionalminPower)).orElse(new EmptyType()))); @@ -6661,9 +6661,9 @@ public static DeviceEnergyManagementClusterSlotStruct decodeTlv(BaseTLVType tlvV Long defaultDuration = null; Long elapsedSlotTime = null; Long remainingSlotTime = null; - Boolean slotIsPauseable = null; - Long minPauseDuration = null; - Long maxPauseDuration = null; + Optional slotIsPauseable = Optional.empty(); + Optional minPauseDuration = Optional.empty(); + Optional maxPauseDuration = Optional.empty(); Optional manufacturerESAState = Optional.empty(); Optional nominalPower = Optional.empty(); Optional minPower = Optional.empty(); @@ -6703,17 +6703,17 @@ public static DeviceEnergyManagementClusterSlotStruct decodeTlv(BaseTLVType tlvV } else if (element.contextTagNum() == SLOT_IS_PAUSEABLE_ID) { if (element.value(BaseTLVType.class).type() == TLVType.Boolean) { BooleanType castingValue = element.value(BooleanType.class); - slotIsPauseable = castingValue.value(Boolean.class); + slotIsPauseable = Optional.of(castingValue.value(Boolean.class)); } } else if (element.contextTagNum() == MIN_PAUSE_DURATION_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); - minPauseDuration = castingValue.value(Long.class); + minPauseDuration = Optional.of(castingValue.value(Long.class)); } } else if (element.contextTagNum() == MAX_PAUSE_DURATION_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { UIntType castingValue = element.value(UIntType.class); - maxPauseDuration = castingValue.value(Long.class); + maxPauseDuration = Optional.of(castingValue.value(Long.class)); } } else if (element.contextTagNum() == MANUFACTURER_E_S_A_STATE_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { @@ -6860,6 +6860,7 @@ public static class DeviceEnergyManagementClusterForecastStruct { public Optional latestEndTime; public Boolean isPauseable; public ArrayList slots; + public Integer forecastUpdateReason; private static final long FORECAST_ID_ID = 0L; private static final long ACTIVE_SLOT_NUMBER_ID = 1L; private static final long START_TIME_ID = 2L; @@ -6868,6 +6869,7 @@ public static class DeviceEnergyManagementClusterForecastStruct { private static final long LATEST_END_TIME_ID = 5L; private static final long IS_PAUSEABLE_ID = 6L; private static final long SLOTS_ID = 7L; + private static final long FORECAST_UPDATE_REASON_ID = 8L; public DeviceEnergyManagementClusterForecastStruct( Integer forecastId, @@ -6877,7 +6879,8 @@ public DeviceEnergyManagementClusterForecastStruct( @Nullable Optional earliestStartTime, Optional latestEndTime, Boolean isPauseable, - ArrayList slots + ArrayList slots, + Integer forecastUpdateReason ) { this.forecastId = forecastId; this.activeSlotNumber = activeSlotNumber; @@ -6887,6 +6890,7 @@ public DeviceEnergyManagementClusterForecastStruct( this.latestEndTime = latestEndTime; this.isPauseable = isPauseable; this.slots = slots; + this.forecastUpdateReason = forecastUpdateReason; } public StructType encodeTlv() { @@ -6899,6 +6903,7 @@ public StructType encodeTlv() { values.add(new StructElement(LATEST_END_TIME_ID, latestEndTime.map((nonOptionallatestEndTime) -> new UIntType(nonOptionallatestEndTime)).orElse(new EmptyType()))); values.add(new StructElement(IS_PAUSEABLE_ID, new BooleanType(isPauseable))); values.add(new StructElement(SLOTS_ID, ArrayType.generateArrayType(slots, (elementslots) -> elementslots.encodeTlv()))); + values.add(new StructElement(FORECAST_UPDATE_REASON_ID, new UIntType(forecastUpdateReason))); return new StructType(values); } @@ -6915,6 +6920,7 @@ public static DeviceEnergyManagementClusterForecastStruct decodeTlv(BaseTLVType Optional latestEndTime = Optional.empty(); Boolean isPauseable = null; ArrayList slots = null; + Integer forecastUpdateReason = null; for (StructElement element: ((StructType)tlvValue).value()) { if (element.contextTagNum() == FORECAST_ID_ID) { if (element.value(BaseTLVType.class).type() == TLVType.UInt) { @@ -6956,6 +6962,11 @@ public static DeviceEnergyManagementClusterForecastStruct decodeTlv(BaseTLVType ArrayType castingValue = element.value(ArrayType.class); slots = castingValue.map((elementcastingValue) -> ChipStructs.DeviceEnergyManagementClusterSlotStruct.decodeTlv(elementcastingValue)); } + } else if (element.contextTagNum() == FORECAST_UPDATE_REASON_ID) { + if (element.value(BaseTLVType.class).type() == TLVType.UInt) { + UIntType castingValue = element.value(UIntType.class); + forecastUpdateReason = castingValue.value(Integer.class); + } } } return new DeviceEnergyManagementClusterForecastStruct( @@ -6966,7 +6977,8 @@ public static DeviceEnergyManagementClusterForecastStruct decodeTlv(BaseTLVType earliestStartTime, latestEndTime, isPauseable, - slots + slots, + forecastUpdateReason ); } @@ -6998,6 +7010,9 @@ public String toString() { output.append("\tslots: "); output.append(slots); output.append("\n"); + output.append("\tforecastUpdateReason: "); + output.append(forecastUpdateReason); + output.append("\n"); output.append("}\n"); return output.toString(); } diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java index cb21688a2ec313..608a378fc281c1 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterIDMapping.java @@ -9359,6 +9359,7 @@ public enum Attribute { AbsMaxPower(4L), PowerAdjustmentCapability(5L), Forecast(6L), + OptOutState(7L), GeneratedCommandList(65528L), AcceptedCommandList(65529L), EventList(65530L), @@ -9415,7 +9416,8 @@ public enum Command { PauseRequest(3L), ResumeRequest(4L), ModifyForecastRequest(5L), - RequestConstraintBasedForecast(6L),; + RequestConstraintBasedForecast(6L), + CancelRequest(7L),; private final long id; Command(long id) { this.id = id; @@ -9433,7 +9435,7 @@ public static Command value(long id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }public enum PowerAdjustRequestCommandField {Power(0),Duration(1),; + }public enum PowerAdjustRequestCommandField {Power(0),Duration(1),Cause(2),; private final int id; PowerAdjustRequestCommandField(int id) { this.id = id; @@ -9450,7 +9452,7 @@ public static PowerAdjustRequestCommandField value(int id) throws NoSuchFieldErr } throw new NoSuchFieldError(); } - }public enum StartTimeAdjustRequestCommandField {RequestedStartTime(0),; + }public enum StartTimeAdjustRequestCommandField {RequestedStartTime(0),Cause(1),; private final int id; StartTimeAdjustRequestCommandField(int id) { this.id = id; @@ -9467,7 +9469,7 @@ public static StartTimeAdjustRequestCommandField value(int id) throws NoSuchFiel } throw new NoSuchFieldError(); } - }public enum PauseRequestCommandField {Duration(0),; + }public enum PauseRequestCommandField {Duration(0),Cause(1),; private final int id; PauseRequestCommandField(int id) { this.id = id; @@ -9484,7 +9486,7 @@ public static PauseRequestCommandField value(int id) throws NoSuchFieldError { } throw new NoSuchFieldError(); } - }public enum ModifyForecastRequestCommandField {ForecastId(0),SlotAdjustments(1),; + }public enum ModifyForecastRequestCommandField {ForecastId(0),SlotAdjustments(1),Cause(2),; private final int id; ModifyForecastRequestCommandField(int id) { this.id = id; @@ -9501,7 +9503,7 @@ public static ModifyForecastRequestCommandField value(int id) throws NoSuchField } throw new NoSuchFieldError(); } - }public enum RequestConstraintBasedForecastCommandField {Constraints(0),; + }public enum RequestConstraintBasedForecastCommandField {Constraints(0),Cause(1),; private final int id; RequestConstraintBasedForecastCommandField(int id) { this.id = id; diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java index a030b14c6b218b..342feb2ef08dc4 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterInfoMapping.java @@ -23346,6 +23346,9 @@ public Map> getCommandMap() { CommandParameterInfo deviceEnergyManagementpowerAdjustRequestdurationCommandParameterInfo = new CommandParameterInfo("duration", Long.class, Long.class); deviceEnergyManagementpowerAdjustRequestCommandParams.put("duration",deviceEnergyManagementpowerAdjustRequestdurationCommandParameterInfo); + + CommandParameterInfo deviceEnergyManagementpowerAdjustRequestcauseCommandParameterInfo = new CommandParameterInfo("cause", Integer.class, Integer.class); + deviceEnergyManagementpowerAdjustRequestCommandParams.put("cause",deviceEnergyManagementpowerAdjustRequestcauseCommandParameterInfo); InteractionInfo deviceEnergyManagementpowerAdjustRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.DeviceEnergyManagementCluster) cluster) @@ -23354,6 +23357,8 @@ public Map> getCommandMap() { commandArguments.get("power") , (Long) commandArguments.get("duration") + , (Integer) + commandArguments.get("cause") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -23377,12 +23382,17 @@ public Map> getCommandMap() { CommandParameterInfo deviceEnergyManagementstartTimeAdjustRequestrequestedStartTimeCommandParameterInfo = new CommandParameterInfo("requestedStartTime", Long.class, Long.class); deviceEnergyManagementstartTimeAdjustRequestCommandParams.put("requestedStartTime",deviceEnergyManagementstartTimeAdjustRequestrequestedStartTimeCommandParameterInfo); + + CommandParameterInfo deviceEnergyManagementstartTimeAdjustRequestcauseCommandParameterInfo = new CommandParameterInfo("cause", Integer.class, Integer.class); + deviceEnergyManagementstartTimeAdjustRequestCommandParams.put("cause",deviceEnergyManagementstartTimeAdjustRequestcauseCommandParameterInfo); InteractionInfo deviceEnergyManagementstartTimeAdjustRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.DeviceEnergyManagementCluster) cluster) .startTimeAdjustRequest((DefaultClusterCallback) callback , (Long) commandArguments.get("requestedStartTime") + , (Integer) + commandArguments.get("cause") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -23394,12 +23404,17 @@ public Map> getCommandMap() { CommandParameterInfo deviceEnergyManagementpauseRequestdurationCommandParameterInfo = new CommandParameterInfo("duration", Long.class, Long.class); deviceEnergyManagementpauseRequestCommandParams.put("duration",deviceEnergyManagementpauseRequestdurationCommandParameterInfo); + + CommandParameterInfo deviceEnergyManagementpauseRequestcauseCommandParameterInfo = new CommandParameterInfo("cause", Integer.class, Integer.class); + deviceEnergyManagementpauseRequestCommandParams.put("cause",deviceEnergyManagementpauseRequestcauseCommandParameterInfo); InteractionInfo deviceEnergyManagementpauseRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.DeviceEnergyManagementCluster) cluster) .pauseRequest((DefaultClusterCallback) callback , (Long) commandArguments.get("duration") + , (Integer) + commandArguments.get("cause") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -23424,6 +23439,9 @@ public Map> getCommandMap() { CommandParameterInfo deviceEnergyManagementmodifyForecastRequestforecastIdCommandParameterInfo = new CommandParameterInfo("forecastId", Long.class, Long.class); deviceEnergyManagementmodifyForecastRequestCommandParams.put("forecastId",deviceEnergyManagementmodifyForecastRequestforecastIdCommandParameterInfo); + + CommandParameterInfo deviceEnergyManagementmodifyForecastRequestcauseCommandParameterInfo = new CommandParameterInfo("cause", Integer.class, Integer.class); + deviceEnergyManagementmodifyForecastRequestCommandParams.put("cause",deviceEnergyManagementmodifyForecastRequestcauseCommandParameterInfo); InteractionInfo deviceEnergyManagementmodifyForecastRequestInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.DeviceEnergyManagementCluster) cluster) @@ -23432,6 +23450,8 @@ public Map> getCommandMap() { commandArguments.get("forecastId") , (ArrayList) commandArguments.get("slotAdjustments") + , (Integer) + commandArguments.get("cause") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -23441,12 +23461,17 @@ public Map> getCommandMap() { Map deviceEnergyManagementrequestConstraintBasedForecastCommandParams = new LinkedHashMap(); + + CommandParameterInfo deviceEnergyManagementrequestConstraintBasedForecastcauseCommandParameterInfo = new CommandParameterInfo("cause", Integer.class, Integer.class); + deviceEnergyManagementrequestConstraintBasedForecastCommandParams.put("cause",deviceEnergyManagementrequestConstraintBasedForecastcauseCommandParameterInfo); InteractionInfo deviceEnergyManagementrequestConstraintBasedForecastInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { ((ChipClusters.DeviceEnergyManagementCluster) cluster) .requestConstraintBasedForecast((DefaultClusterCallback) callback , (ArrayList) commandArguments.get("constraints") + , (Integer) + commandArguments.get("cause") ); }, () -> new DelegatedDefaultClusterCallback(), @@ -23454,6 +23479,18 @@ public Map> getCommandMap() { ); deviceEnergyManagementClusterInteractionInfoMap.put("requestConstraintBasedForecast", deviceEnergyManagementrequestConstraintBasedForecastInteractionInfo); + Map deviceEnergyManagementcancelRequestCommandParams = new LinkedHashMap(); + InteractionInfo deviceEnergyManagementcancelRequestInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.DeviceEnergyManagementCluster) cluster) + .cancelRequest((DefaultClusterCallback) callback + ); + }, + () -> new DelegatedDefaultClusterCallback(), + deviceEnergyManagementcancelRequestCommandParams + ); + deviceEnergyManagementClusterInteractionInfoMap.put("cancelRequest", deviceEnergyManagementcancelRequestInteractionInfo); + commandMap.put("deviceEnergyManagement", deviceEnergyManagementClusterInteractionInfoMap); Map energyEvseClusterInteractionInfoMap = new LinkedHashMap<>(); diff --git a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java index 95880d5849ce0f..bbd205aaca8b22 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java +++ b/src/controller/java/generated/java/chip/devicecontroller/ClusterReadMapping.java @@ -9336,6 +9336,17 @@ private static Map readDeviceEnergyManagementInteractio readDeviceEnergyManagementPowerAdjustmentCapabilityCommandParams ); result.put("readPowerAdjustmentCapabilityAttribute", readDeviceEnergyManagementPowerAdjustmentCapabilityAttributeInteractionInfo); + Map readDeviceEnergyManagementOptOutStateCommandParams = new LinkedHashMap(); + InteractionInfo readDeviceEnergyManagementOptOutStateAttributeInteractionInfo = new InteractionInfo( + (cluster, callback, commandArguments) -> { + ((ChipClusters.DeviceEnergyManagementCluster) cluster).readOptOutStateAttribute( + (ChipClusters.IntegerAttributeCallback) callback + ); + }, + () -> new ClusterInfoMapping.DelegatedIntegerAttributeCallback(), + readDeviceEnergyManagementOptOutStateCommandParams + ); + result.put("readOptOutStateAttribute", readDeviceEnergyManagementOptOutStateAttributeInteractionInfo); Map readDeviceEnergyManagementGeneratedCommandListCommandParams = new LinkedHashMap(); InteractionInfo readDeviceEnergyManagementGeneratedCommandListAttributeInteractionInfo = new InteractionInfo( (cluster, callback, commandArguments) -> { diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt new file mode 100644 index 00000000000000..5b4be5cfc2fd55 --- /dev/null +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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. + */ +package chip.devicecontroller.cluster.eventstructs + +import chip.devicecontroller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class DeviceEnergyManagementClusterResumedEvent(val cause: UInt) { + override fun toString(): String = buildString { + append("DeviceEnergyManagementClusterResumedEvent {\n") + append("\tcause : $cause\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_CAUSE), cause) + endStructure() + } + } + + companion object { + private const val TAG_CAUSE = 0 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): DeviceEnergyManagementClusterResumedEvent { + tlvReader.enterStructure(tlvTag) + val cause = tlvReader.getUInt(ContextSpecificTag(TAG_CAUSE)) + + tlvReader.exitContainer() + + return DeviceEnergyManagementClusterResumedEvent(cause) + } + } +} diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni index 57b30e5acdf821..dc97dce9da6268 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/files.gni @@ -146,6 +146,7 @@ eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DemandResponseLoadControlClusterLoadControlEventStatusChangeEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DeviceEnergyManagementClusterPowerAdjustEndEvent.kt", + "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DishwasherAlarmClusterNotifyEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DoorLockClusterDoorLockAlarmEvent.kt", "${chip_root}/src/controller/java/generated/java/chip/devicecontroller/cluster/eventstructs/DoorLockClusterDoorStateChangeEvent.kt", diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt index 648d202043f9c5..17e45fa732ea47 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt @@ -32,7 +32,8 @@ class DeviceEnergyManagementClusterForecastStruct( val earliestStartTime: Optional?, val latestEndTime: Optional, val isPauseable: Boolean, - val slots: List + val slots: List, + val forecastUpdateReason: UInt ) { override fun toString(): String = buildString { append("DeviceEnergyManagementClusterForecastStruct {\n") @@ -44,6 +45,7 @@ class DeviceEnergyManagementClusterForecastStruct( append("\tlatestEndTime : $latestEndTime\n") append("\tisPauseable : $isPauseable\n") append("\tslots : $slots\n") + append("\tforecastUpdateReason : $forecastUpdateReason\n") append("}\n") } @@ -76,6 +78,7 @@ class DeviceEnergyManagementClusterForecastStruct( item.toTlv(AnonymousTag, this) } endArray() + put(ContextSpecificTag(TAG_FORECAST_UPDATE_REASON), forecastUpdateReason) endStructure() } } @@ -89,6 +92,7 @@ class DeviceEnergyManagementClusterForecastStruct( private const val TAG_LATEST_END_TIME = 5 private const val TAG_IS_PAUSEABLE = 6 private const val TAG_SLOTS = 7 + private const val TAG_FORECAST_UPDATE_REASON = 8 fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): DeviceEnergyManagementClusterForecastStruct { tlvReader.enterStructure(tlvTag) @@ -128,6 +132,7 @@ class DeviceEnergyManagementClusterForecastStruct( } tlvReader.exitContainer() } + val forecastUpdateReason = tlvReader.getUInt(ContextSpecificTag(TAG_FORECAST_UPDATE_REASON)) tlvReader.exitContainer() @@ -139,7 +144,8 @@ class DeviceEnergyManagementClusterForecastStruct( earliestStartTime, latestEndTime, isPauseable, - slots + slots, + forecastUpdateReason ) } } diff --git a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt index 736a81804244ce..18759432dc2ce4 100644 --- a/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt +++ b/src/controller/java/generated/java/chip/devicecontroller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt @@ -30,9 +30,9 @@ class DeviceEnergyManagementClusterSlotStruct( val defaultDuration: ULong, val elapsedSlotTime: ULong, val remainingSlotTime: ULong, - val slotIsPauseable: Boolean, - val minPauseDuration: ULong, - val maxPauseDuration: ULong, + val slotIsPauseable: Optional, + val minPauseDuration: Optional, + val maxPauseDuration: Optional, val manufacturerESAState: Optional, val nominalPower: Optional, val minPower: Optional, @@ -75,9 +75,18 @@ class DeviceEnergyManagementClusterSlotStruct( put(ContextSpecificTag(TAG_DEFAULT_DURATION), defaultDuration) put(ContextSpecificTag(TAG_ELAPSED_SLOT_TIME), elapsedSlotTime) put(ContextSpecificTag(TAG_REMAINING_SLOT_TIME), remainingSlotTime) - put(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE), slotIsPauseable) - put(ContextSpecificTag(TAG_MIN_PAUSE_DURATION), minPauseDuration) - put(ContextSpecificTag(TAG_MAX_PAUSE_DURATION), maxPauseDuration) + if (slotIsPauseable.isPresent) { + val optslotIsPauseable = slotIsPauseable.get() + put(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE), optslotIsPauseable) + } + if (minPauseDuration.isPresent) { + val optminPauseDuration = minPauseDuration.get() + put(ContextSpecificTag(TAG_MIN_PAUSE_DURATION), optminPauseDuration) + } + if (maxPauseDuration.isPresent) { + val optmaxPauseDuration = maxPauseDuration.get() + put(ContextSpecificTag(TAG_MAX_PAUSE_DURATION), optmaxPauseDuration) + } if (manufacturerESAState.isPresent) { val optmanufacturerESAState = manufacturerESAState.get() put(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE), optmanufacturerESAState) @@ -153,9 +162,24 @@ class DeviceEnergyManagementClusterSlotStruct( val defaultDuration = tlvReader.getULong(ContextSpecificTag(TAG_DEFAULT_DURATION)) val elapsedSlotTime = tlvReader.getULong(ContextSpecificTag(TAG_ELAPSED_SLOT_TIME)) val remainingSlotTime = tlvReader.getULong(ContextSpecificTag(TAG_REMAINING_SLOT_TIME)) - val slotIsPauseable = tlvReader.getBoolean(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE)) - val minPauseDuration = tlvReader.getULong(ContextSpecificTag(TAG_MIN_PAUSE_DURATION)) - val maxPauseDuration = tlvReader.getULong(ContextSpecificTag(TAG_MAX_PAUSE_DURATION)) + val slotIsPauseable = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE))) { + Optional.of(tlvReader.getBoolean(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE))) + } else { + Optional.empty() + } + val minPauseDuration = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_MIN_PAUSE_DURATION))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_MIN_PAUSE_DURATION))) + } else { + Optional.empty() + } + val maxPauseDuration = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_MAX_PAUSE_DURATION))) { + Optional.of(tlvReader.getULong(ContextSpecificTag(TAG_MAX_PAUSE_DURATION))) + } else { + Optional.empty() + } val manufacturerESAState = if (tlvReader.isNextTag(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE))) { Optional.of(tlvReader.getUInt(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE))) diff --git a/src/controller/java/generated/java/matter/controller/cluster/clusters/DeviceEnergyManagementCluster.kt b/src/controller/java/generated/java/matter/controller/cluster/clusters/DeviceEnergyManagementCluster.kt index 8481bbf3ccf788..eb68ec47c75ee1 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/clusters/DeviceEnergyManagementCluster.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/clusters/DeviceEnergyManagementCluster.kt @@ -114,6 +114,7 @@ class DeviceEnergyManagementCluster( suspend fun powerAdjustRequest( power: Long, duration: UInt, + cause: UByte, timedInvokeTimeout: Duration? = null ) { val commandId: UInt = 0u @@ -126,6 +127,9 @@ class DeviceEnergyManagementCluster( val TAG_DURATION_REQ: Int = 1 tlvWriter.put(ContextSpecificTag(TAG_DURATION_REQ), duration) + + val TAG_CAUSE_REQ: Int = 2 + tlvWriter.put(ContextSpecificTag(TAG_CAUSE_REQ), cause) tlvWriter.endStructure() val request: InvokeRequest = @@ -159,6 +163,7 @@ class DeviceEnergyManagementCluster( suspend fun startTimeAdjustRequest( requestedStartTime: UInt, + cause: UByte, timedInvokeTimeout: Duration? = null ) { val commandId: UInt = 2u @@ -168,6 +173,9 @@ class DeviceEnergyManagementCluster( val TAG_REQUESTED_START_TIME_REQ: Int = 0 tlvWriter.put(ContextSpecificTag(TAG_REQUESTED_START_TIME_REQ), requestedStartTime) + + val TAG_CAUSE_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_CAUSE_REQ), cause) tlvWriter.endStructure() val request: InvokeRequest = @@ -181,7 +189,7 @@ class DeviceEnergyManagementCluster( logger.log(Level.FINE, "Invoke command succeeded: ${response}") } - suspend fun pauseRequest(duration: UInt, timedInvokeTimeout: Duration? = null) { + suspend fun pauseRequest(duration: UInt, cause: UByte, timedInvokeTimeout: Duration? = null) { val commandId: UInt = 3u val tlvWriter = TlvWriter() @@ -189,6 +197,9 @@ class DeviceEnergyManagementCluster( val TAG_DURATION_REQ: Int = 0 tlvWriter.put(ContextSpecificTag(TAG_DURATION_REQ), duration) + + val TAG_CAUSE_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_CAUSE_REQ), cause) tlvWriter.endStructure() val request: InvokeRequest = @@ -223,6 +234,7 @@ class DeviceEnergyManagementCluster( suspend fun modifyForecastRequest( forecastId: UInt, slotAdjustments: List, + cause: UByte, timedInvokeTimeout: Duration? = null ) { val commandId: UInt = 5u @@ -239,6 +251,9 @@ class DeviceEnergyManagementCluster( item.toTlv(AnonymousTag, tlvWriter) } tlvWriter.endArray() + + val TAG_CAUSE_REQ: Int = 2 + tlvWriter.put(ContextSpecificTag(TAG_CAUSE_REQ), cause) tlvWriter.endStructure() val request: InvokeRequest = @@ -254,6 +269,7 @@ class DeviceEnergyManagementCluster( suspend fun requestConstraintBasedForecast( constraints: List, + cause: UByte, timedInvokeTimeout: Duration? = null ) { val commandId: UInt = 6u @@ -267,6 +283,27 @@ class DeviceEnergyManagementCluster( item.toTlv(AnonymousTag, tlvWriter) } tlvWriter.endArray() + + val TAG_CAUSE_REQ: Int = 1 + tlvWriter.put(ContextSpecificTag(TAG_CAUSE_REQ), cause) + tlvWriter.endStructure() + + val request: InvokeRequest = + InvokeRequest( + CommandPath(endpointId, clusterId = CLUSTER_ID, commandId), + tlvPayload = tlvWriter.getEncoded(), + timedRequest = timedInvokeTimeout + ) + + val response: InvokeResponse = controller.invoke(request) + logger.log(Level.FINE, "Invoke command succeeded: ${response}") + } + + suspend fun cancelRequest(timedInvokeTimeout: Duration? = null) { + val commandId: UInt = 7u + + val tlvWriter = TlvWriter() + tlvWriter.startStructure(AnonymousTag) tlvWriter.endStructure() val request: InvokeRequest = @@ -910,6 +947,97 @@ class DeviceEnergyManagementCluster( } } + suspend fun readOptOutStateAttribute(): UByte? { + val ATTRIBUTE_ID: UInt = 7u + + val attributePath = + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + + val readRequest = ReadRequest(eventPaths = emptyList(), attributePaths = listOf(attributePath)) + + val response = controller.read(readRequest) + + if (response.successes.isEmpty()) { + logger.log(Level.WARNING, "Read command failed") + throw IllegalStateException("Read command failed with failures: ${response.failures}") + } + + logger.log(Level.FINE, "Read command succeeded") + + val attributeData = + response.successes.filterIsInstance().firstOrNull { + it.path.attributeId == ATTRIBUTE_ID + } + + requireNotNull(attributeData) { "Optoutstate attribute not found in response" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UByte? = + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getUByte(AnonymousTag) + } else { + null + } + + return decodedValue + } + + suspend fun subscribeOptOutStateAttribute( + minInterval: Int, + maxInterval: Int + ): Flow { + val ATTRIBUTE_ID: UInt = 7u + val attributePaths = + listOf( + AttributePath(endpointId = endpointId, clusterId = CLUSTER_ID, attributeId = ATTRIBUTE_ID) + ) + + val subscribeRequest: SubscribeRequest = + SubscribeRequest( + eventPaths = emptyList(), + attributePaths = attributePaths, + minInterval = Duration.ofSeconds(minInterval.toLong()), + maxInterval = Duration.ofSeconds(maxInterval.toLong()) + ) + + return controller.subscribe(subscribeRequest).transform { subscriptionState -> + when (subscriptionState) { + is SubscriptionState.SubscriptionErrorNotification -> { + emit( + UByteSubscriptionState.Error( + Exception( + "Subscription terminated with error code: ${subscriptionState.terminationCause}" + ) + ) + ) + } + is SubscriptionState.NodeStateUpdate -> { + val attributeData = + subscriptionState.updateState.successes + .filterIsInstance() + .firstOrNull { it.path.attributeId == ATTRIBUTE_ID } + + requireNotNull(attributeData) { "Optoutstate attribute not found in Node State update" } + + // Decode the TLV data into the appropriate type + val tlvReader = TlvReader(attributeData.data) + val decodedValue: UByte? = + if (tlvReader.isNextTag(AnonymousTag)) { + tlvReader.getUByte(AnonymousTag) + } else { + null + } + + decodedValue?.let { emit(UByteSubscriptionState.Success(it)) } + } + SubscriptionState.SubscriptionEstablished -> { + emit(UByteSubscriptionState.SubscriptionEstablished) + } + } + } + } + suspend fun readGeneratedCommandListAttribute(): GeneratedCommandListAttribute { val ATTRIBUTE_ID: UInt = 65528u diff --git a/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt new file mode 100644 index 00000000000000..db5219f72dba0e --- /dev/null +++ b/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * 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. + */ +package matter.controller.cluster.eventstructs + +import matter.controller.cluster.* +import matter.tlv.ContextSpecificTag +import matter.tlv.Tag +import matter.tlv.TlvReader +import matter.tlv.TlvWriter + +class DeviceEnergyManagementClusterResumedEvent(val cause: UByte) { + override fun toString(): String = buildString { + append("DeviceEnergyManagementClusterResumedEvent {\n") + append("\tcause : $cause\n") + append("}\n") + } + + fun toTlv(tlvTag: Tag, tlvWriter: TlvWriter) { + tlvWriter.apply { + startStructure(tlvTag) + put(ContextSpecificTag(TAG_CAUSE), cause) + endStructure() + } + } + + companion object { + private const val TAG_CAUSE = 0 + + fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): DeviceEnergyManagementClusterResumedEvent { + tlvReader.enterStructure(tlvTag) + val cause = tlvReader.getUByte(ContextSpecificTag(TAG_CAUSE)) + + tlvReader.exitContainer() + + return DeviceEnergyManagementClusterResumedEvent(cause) + } + } +} diff --git a/src/controller/java/generated/java/matter/controller/cluster/files.gni b/src/controller/java/generated/java/matter/controller/cluster/files.gni index 635cff6021ba99..42d42d93cbfbc8 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/files.gni +++ b/src/controller/java/generated/java/matter/controller/cluster/files.gni @@ -146,6 +146,7 @@ matter_eventstructs_sources = [ "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/BridgedDeviceBasicInformationClusterStartUpEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DemandResponseLoadControlClusterLoadControlEventStatusChangeEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DeviceEnergyManagementClusterPowerAdjustEndEvent.kt", + "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DeviceEnergyManagementClusterResumedEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DishwasherAlarmClusterNotifyEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DoorLockClusterDoorLockAlarmEvent.kt", "${chip_root}/src/controller/java/generated/java/matter/controller/cluster/eventstructs/DoorLockClusterDoorStateChangeEvent.kt", diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt index 6910c799cd8268..a83d26ee3815d0 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterForecastStruct.kt @@ -32,7 +32,8 @@ class DeviceEnergyManagementClusterForecastStruct( val earliestStartTime: Optional?, val latestEndTime: Optional, val isPauseable: Boolean, - val slots: List + val slots: List, + val forecastUpdateReason: UByte ) { override fun toString(): String = buildString { append("DeviceEnergyManagementClusterForecastStruct {\n") @@ -44,6 +45,7 @@ class DeviceEnergyManagementClusterForecastStruct( append("\tlatestEndTime : $latestEndTime\n") append("\tisPauseable : $isPauseable\n") append("\tslots : $slots\n") + append("\tforecastUpdateReason : $forecastUpdateReason\n") append("}\n") } @@ -76,6 +78,7 @@ class DeviceEnergyManagementClusterForecastStruct( item.toTlv(AnonymousTag, this) } endArray() + put(ContextSpecificTag(TAG_FORECAST_UPDATE_REASON), forecastUpdateReason) endStructure() } } @@ -89,6 +92,7 @@ class DeviceEnergyManagementClusterForecastStruct( private const val TAG_LATEST_END_TIME = 5 private const val TAG_IS_PAUSEABLE = 6 private const val TAG_SLOTS = 7 + private const val TAG_FORECAST_UPDATE_REASON = 8 fun fromTlv(tlvTag: Tag, tlvReader: TlvReader): DeviceEnergyManagementClusterForecastStruct { tlvReader.enterStructure(tlvTag) @@ -128,6 +132,7 @@ class DeviceEnergyManagementClusterForecastStruct( } tlvReader.exitContainer() } + val forecastUpdateReason = tlvReader.getUByte(ContextSpecificTag(TAG_FORECAST_UPDATE_REASON)) tlvReader.exitContainer() @@ -139,7 +144,8 @@ class DeviceEnergyManagementClusterForecastStruct( earliestStartTime, latestEndTime, isPauseable, - slots + slots, + forecastUpdateReason ) } } diff --git a/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt b/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt index d3121dc411a4de..992a41573e295e 100644 --- a/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt +++ b/src/controller/java/generated/java/matter/controller/cluster/structs/DeviceEnergyManagementClusterSlotStruct.kt @@ -30,9 +30,9 @@ class DeviceEnergyManagementClusterSlotStruct( val defaultDuration: UInt, val elapsedSlotTime: UInt, val remainingSlotTime: UInt, - val slotIsPauseable: Boolean, - val minPauseDuration: UInt, - val maxPauseDuration: UInt, + val slotIsPauseable: Optional, + val minPauseDuration: Optional, + val maxPauseDuration: Optional, val manufacturerESAState: Optional, val nominalPower: Optional, val minPower: Optional, @@ -75,9 +75,18 @@ class DeviceEnergyManagementClusterSlotStruct( put(ContextSpecificTag(TAG_DEFAULT_DURATION), defaultDuration) put(ContextSpecificTag(TAG_ELAPSED_SLOT_TIME), elapsedSlotTime) put(ContextSpecificTag(TAG_REMAINING_SLOT_TIME), remainingSlotTime) - put(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE), slotIsPauseable) - put(ContextSpecificTag(TAG_MIN_PAUSE_DURATION), minPauseDuration) - put(ContextSpecificTag(TAG_MAX_PAUSE_DURATION), maxPauseDuration) + if (slotIsPauseable.isPresent) { + val optslotIsPauseable = slotIsPauseable.get() + put(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE), optslotIsPauseable) + } + if (minPauseDuration.isPresent) { + val optminPauseDuration = minPauseDuration.get() + put(ContextSpecificTag(TAG_MIN_PAUSE_DURATION), optminPauseDuration) + } + if (maxPauseDuration.isPresent) { + val optmaxPauseDuration = maxPauseDuration.get() + put(ContextSpecificTag(TAG_MAX_PAUSE_DURATION), optmaxPauseDuration) + } if (manufacturerESAState.isPresent) { val optmanufacturerESAState = manufacturerESAState.get() put(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE), optmanufacturerESAState) @@ -153,9 +162,24 @@ class DeviceEnergyManagementClusterSlotStruct( val defaultDuration = tlvReader.getUInt(ContextSpecificTag(TAG_DEFAULT_DURATION)) val elapsedSlotTime = tlvReader.getUInt(ContextSpecificTag(TAG_ELAPSED_SLOT_TIME)) val remainingSlotTime = tlvReader.getUInt(ContextSpecificTag(TAG_REMAINING_SLOT_TIME)) - val slotIsPauseable = tlvReader.getBoolean(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE)) - val minPauseDuration = tlvReader.getUInt(ContextSpecificTag(TAG_MIN_PAUSE_DURATION)) - val maxPauseDuration = tlvReader.getUInt(ContextSpecificTag(TAG_MAX_PAUSE_DURATION)) + val slotIsPauseable = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE))) { + Optional.of(tlvReader.getBoolean(ContextSpecificTag(TAG_SLOT_IS_PAUSEABLE))) + } else { + Optional.empty() + } + val minPauseDuration = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_MIN_PAUSE_DURATION))) { + Optional.of(tlvReader.getUInt(ContextSpecificTag(TAG_MIN_PAUSE_DURATION))) + } else { + Optional.empty() + } + val maxPauseDuration = + if (tlvReader.isNextTag(ContextSpecificTag(TAG_MAX_PAUSE_DURATION))) { + Optional.of(tlvReader.getUInt(ContextSpecificTag(TAG_MAX_PAUSE_DURATION))) + } else { + Optional.empty() + } val manufacturerESAState = if (tlvReader.isNextTag(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE))) { Optional.of(tlvReader.getUShort(ContextSpecificTag(TAG_MANUFACTURER_E_S_A_STATE))) diff --git a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp index 1ca2a96af986df..2778b037f8e694 100644 --- a/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPAttributeTLVValueDecoder.cpp @@ -22214,26 +22214,60 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR newElement_2_remainingSlotTimeClassName.c_str(), newElement_2_remainingSlotTimeCtorSignature.c_str(), jninewElement_2_remainingSlotTime, newElement_2_remainingSlotTime); jobject newElement_2_slotIsPauseable; - std::string newElement_2_slotIsPauseableClassName = "java/lang/Boolean"; - std::string newElement_2_slotIsPauseableCtorSignature = "(Z)V"; - jboolean jninewElement_2_slotIsPauseable = static_cast(entry_2.slotIsPauseable); - chip::JniReferences::GetInstance().CreateBoxedObject( - newElement_2_slotIsPauseableClassName.c_str(), newElement_2_slotIsPauseableCtorSignature.c_str(), - jninewElement_2_slotIsPauseable, newElement_2_slotIsPauseable); + if (!entry_2.slotIsPauseable.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_2_slotIsPauseable); + } + else + { + jobject newElement_2_slotIsPauseableInsideOptional; + std::string newElement_2_slotIsPauseableInsideOptionalClassName = "java/lang/Boolean"; + std::string newElement_2_slotIsPauseableInsideOptionalCtorSignature = "(Z)V"; + jboolean jninewElement_2_slotIsPauseableInsideOptional = + static_cast(entry_2.slotIsPauseable.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_2_slotIsPauseableInsideOptionalClassName.c_str(), + newElement_2_slotIsPauseableInsideOptionalCtorSignature.c_str(), + jninewElement_2_slotIsPauseableInsideOptional, newElement_2_slotIsPauseableInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(newElement_2_slotIsPauseableInsideOptional, + newElement_2_slotIsPauseable); + } jobject newElement_2_minPauseDuration; - std::string newElement_2_minPauseDurationClassName = "java/lang/Long"; - std::string newElement_2_minPauseDurationCtorSignature = "(J)V"; - jlong jninewElement_2_minPauseDuration = static_cast(entry_2.minPauseDuration); - chip::JniReferences::GetInstance().CreateBoxedObject( - newElement_2_minPauseDurationClassName.c_str(), newElement_2_minPauseDurationCtorSignature.c_str(), - jninewElement_2_minPauseDuration, newElement_2_minPauseDuration); + if (!entry_2.minPauseDuration.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_2_minPauseDuration); + } + else + { + jobject newElement_2_minPauseDurationInsideOptional; + std::string newElement_2_minPauseDurationInsideOptionalClassName = "java/lang/Long"; + std::string newElement_2_minPauseDurationInsideOptionalCtorSignature = "(J)V"; + jlong jninewElement_2_minPauseDurationInsideOptional = static_cast(entry_2.minPauseDuration.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_2_minPauseDurationInsideOptionalClassName.c_str(), + newElement_2_minPauseDurationInsideOptionalCtorSignature.c_str(), + jninewElement_2_minPauseDurationInsideOptional, newElement_2_minPauseDurationInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(newElement_2_minPauseDurationInsideOptional, + newElement_2_minPauseDuration); + } jobject newElement_2_maxPauseDuration; - std::string newElement_2_maxPauseDurationClassName = "java/lang/Long"; - std::string newElement_2_maxPauseDurationCtorSignature = "(J)V"; - jlong jninewElement_2_maxPauseDuration = static_cast(entry_2.maxPauseDuration); - chip::JniReferences::GetInstance().CreateBoxedObject( - newElement_2_maxPauseDurationClassName.c_str(), newElement_2_maxPauseDurationCtorSignature.c_str(), - jninewElement_2_maxPauseDuration, newElement_2_maxPauseDuration); + if (!entry_2.maxPauseDuration.HasValue()) + { + chip::JniReferences::GetInstance().CreateOptional(nullptr, newElement_2_maxPauseDuration); + } + else + { + jobject newElement_2_maxPauseDurationInsideOptional; + std::string newElement_2_maxPauseDurationInsideOptionalClassName = "java/lang/Long"; + std::string newElement_2_maxPauseDurationInsideOptionalCtorSignature = "(J)V"; + jlong jninewElement_2_maxPauseDurationInsideOptional = static_cast(entry_2.maxPauseDuration.Value()); + chip::JniReferences::GetInstance().CreateBoxedObject( + newElement_2_maxPauseDurationInsideOptionalClassName.c_str(), + newElement_2_maxPauseDurationInsideOptionalCtorSignature.c_str(), + jninewElement_2_maxPauseDurationInsideOptional, newElement_2_maxPauseDurationInsideOptional); + chip::JniReferences::GetInstance().CreateOptional(newElement_2_maxPauseDurationInsideOptional, + newElement_2_maxPauseDuration); + } jobject newElement_2_manufacturerESAState; if (!entry_2.manufacturerESAState.HasValue()) { @@ -22496,10 +22530,10 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR jmethodID slotStructStructCtor_3; err = chip::JniReferences::GetInstance().FindMethod( env, slotStructStructClass_3, "", - "(Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Boolean;Ljava/" - "lang/Long;Ljava/lang/Long;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/" + "(Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/" + "Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/" "Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/Optional;Ljava/util/" - "Optional;Ljava/util/Optional;)V", + "Optional;Ljava/util/Optional;Ljava/util/Optional;)V", &slotStructStructCtor_3); if (err != CHIP_NO_ERROR || slotStructStructCtor_3 == nullptr) { @@ -22516,6 +22550,13 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR newElement_2_maxPowerAdjustment, newElement_2_minDurationAdjustment, newElement_2_maxDurationAdjustment); chip::JniReferences::GetInstance().AddToList(value_slots, newElement_2); } + jobject value_forecastUpdateReason; + std::string value_forecastUpdateReasonClassName = "java/lang/Integer"; + std::string value_forecastUpdateReasonCtorSignature = "(I)V"; + jint jnivalue_forecastUpdateReason = static_cast(cppValue.Value().forecastUpdateReason); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_forecastUpdateReasonClassName.c_str(), value_forecastUpdateReasonCtorSignature.c_str(), + jnivalue_forecastUpdateReason, value_forecastUpdateReason); jclass forecastStructStructClass_1; err = chip::JniReferences::GetInstance().GetClassRef( @@ -22531,7 +22572,7 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR err = chip::JniReferences::GetInstance().FindMethod( env, forecastStructStructClass_1, "", "(Ljava/lang/Integer;Ljava/lang/Integer;Ljava/lang/Long;Ljava/lang/Long;Ljava/util/Optional;Ljava/util/" - "Optional;Ljava/lang/Boolean;Ljava/util/ArrayList;)V", + "Optional;Ljava/lang/Boolean;Ljava/util/ArrayList;Ljava/lang/Integer;)V", &forecastStructStructCtor_1); if (err != CHIP_NO_ERROR || forecastStructStructCtor_1 == nullptr) { @@ -22541,8 +22582,24 @@ jobject DecodeAttributeValue(const app::ConcreteAttributePath & aPath, TLV::TLVR value = env->NewObject(forecastStructStructClass_1, forecastStructStructCtor_1, value_forecastId, value_activeSlotNumber, value_startTime, value_endTime, value_earliestStartTime, - value_latestEndTime, value_isPauseable, value_slots); + value_latestEndTime, value_isPauseable, value_slots, value_forecastUpdateReason); + } + return value; + } + case Attributes::OptOutState::Id: { + using TypeInfo = Attributes::OptOutState::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = app::DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) + { + return nullptr; } + jobject value; + std::string valueClassName = "java/lang/Integer"; + std::string valueCtorSignature = "(I)V"; + jint jnivalue = static_cast(cppValue); + chip::JniReferences::GetInstance().CreateBoxedObject(valueClassName.c_str(), valueCtorSignature.c_str(), jnivalue, + value); return value; } case Attributes::GeneratedCommandList::Id: { diff --git a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp index 2dc5ac3303b7df..d7e0a8debab4ae 100644 --- a/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp +++ b/src/controller/java/zap-generated/CHIPEventTLVValueDecoder.cpp @@ -5282,6 +5282,13 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & { return nullptr; } + jobject value_cause; + std::string value_causeClassName = "java/lang/Integer"; + std::string value_causeCtorSignature = "(I)V"; + jint jnivalue_cause = static_cast(cppValue.cause); + chip::JniReferences::GetInstance().CreateBoxedObject( + value_causeClassName.c_str(), value_causeCtorSignature.c_str(), jnivalue_cause, value_cause); + jclass resumedStructClass; err = chip::JniReferences::GetInstance().GetClassRef( env, "chip/devicecontroller/ChipEventStructs$DeviceEnergyManagementClusterResumedEvent", resumedStructClass); @@ -5292,14 +5299,15 @@ jobject DecodeEventValue(const app::ConcreteEventPath & aPath, TLV::TLVReader & } jmethodID resumedStructCtor; - err = chip::JniReferences::GetInstance().FindMethod(env, resumedStructClass, "", "()V", &resumedStructCtor); + err = chip::JniReferences::GetInstance().FindMethod(env, resumedStructClass, "", "(Ljava/lang/Integer;)V", + &resumedStructCtor); if (err != CHIP_NO_ERROR || resumedStructCtor == nullptr) { ChipLogError(Zcl, "Could not find ChipEventStructs$DeviceEnergyManagementClusterResumedEvent constructor"); return nullptr; } - jobject value = env->NewObject(resumedStructClass, resumedStructCtor); + jobject value = env->NewObject(resumedStructClass, resumedStructCtor, value_cause); return value; } diff --git a/src/controller/python/chip/clusters/CHIPClusters.py b/src/controller/python/chip/clusters/CHIPClusters.py index d599bd7f46f730..eddfbd257eb58f 100644 --- a/src/controller/python/chip/clusters/CHIPClusters.py +++ b/src/controller/python/chip/clusters/CHIPClusters.py @@ -6619,6 +6619,7 @@ class ChipClusters: "args": { "power": "int", "duration": "int", + "cause": "int", }, }, 0x00000001: { @@ -6632,6 +6633,7 @@ class ChipClusters: "commandName": "StartTimeAdjustRequest", "args": { "requestedStartTime": "int", + "cause": "int", }, }, 0x00000003: { @@ -6639,6 +6641,7 @@ class ChipClusters: "commandName": "PauseRequest", "args": { "duration": "int", + "cause": "int", }, }, 0x00000004: { @@ -6653,6 +6656,7 @@ class ChipClusters: "args": { "forecastId": "int", "slotAdjustments": "SlotAdjustmentStruct", + "cause": "int", }, }, 0x00000006: { @@ -6660,6 +6664,13 @@ class ChipClusters: "commandName": "RequestConstraintBasedForecast", "args": { "constraints": "ConstraintsStruct", + "cause": "int", + }, + }, + 0x00000007: { + "commandId": 0x00000007, + "commandName": "CancelRequest", + "args": { }, }, }, @@ -6706,6 +6717,12 @@ class ChipClusters: "type": "", "reportable": True, }, + 0x00000007: { + "attributeName": "OptOutState", + "attributeId": 0x00000007, + "type": "int", + "reportable": True, + }, 0x0000FFF8: { "attributeName": "GeneratedCommandList", "attributeId": 0x0000FFF8, diff --git a/src/controller/python/chip/clusters/Objects.py b/src/controller/python/chip/clusters/Objects.py index 6a2d53df035fe1..4887280c0f91c6 100644 --- a/src/controller/python/chip/clusters/Objects.py +++ b/src/controller/python/chip/clusters/Objects.py @@ -23371,6 +23371,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="absMaxPower", Tag=0x00000004, Type=int), ClusterObjectFieldDescriptor(Label="powerAdjustmentCapability", Tag=0x00000005, Type=typing.Union[None, Nullable, typing.List[DeviceEnergyManagement.Structs.PowerAdjustStruct]]), ClusterObjectFieldDescriptor(Label="forecast", Tag=0x00000006, Type=typing.Union[None, Nullable, DeviceEnergyManagement.Structs.ForecastStruct]), + ClusterObjectFieldDescriptor(Label="optOutState", Tag=0x00000007, Type=typing.Optional[DeviceEnergyManagement.Enums.OptOutStateEnum]), ClusterObjectFieldDescriptor(Label="generatedCommandList", Tag=0x0000FFF8, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="acceptedCommandList", Tag=0x0000FFF9, Type=typing.List[uint]), ClusterObjectFieldDescriptor(Label="eventList", Tag=0x0000FFFA, Type=typing.List[uint]), @@ -23386,6 +23387,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: absMaxPower: 'int' = None powerAdjustmentCapability: 'typing.Union[None, Nullable, typing.List[DeviceEnergyManagement.Structs.PowerAdjustStruct]]' = None forecast: 'typing.Union[None, Nullable, DeviceEnergyManagement.Structs.ForecastStruct]' = None + optOutState: 'typing.Optional[DeviceEnergyManagement.Enums.OptOutStateEnum]' = None generatedCommandList: 'typing.List[uint]' = None acceptedCommandList: 'typing.List[uint]' = None eventList: 'typing.List[uint]' = None @@ -23394,16 +23396,26 @@ def descriptor(cls) -> ClusterObjectDescriptor: clusterRevision: 'uint' = None class Enums: + class AdjustmentCauseEnum(MatterIntEnum): + kLocalOptimization = 0x00 + kGridOptimization = 0x01 + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving and unknown + # enum value. This specific should never be transmitted. + kUnknownEnumValue = 2, + class CauseEnum(MatterIntEnum): kNormalCompletion = 0x00 kOffline = 0x01 kFault = 0x02 kUserOptOut = 0x03 + kCancelled = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only # be used by code to process how it handles receiving and unknown # enum value. This specific should never be transmitted. - kUnknownEnumValue = 4, + kUnknownEnumValue = 5, class CostTypeEnum(MatterIntEnum): kFinancial = 0x00 @@ -23420,14 +23432,13 @@ class ESAStateEnum(MatterIntEnum): kOffline = 0x00 kOnline = 0x01 kFault = 0x02 - kUserOptOut = 0x03 - kPowerAdjustActive = 0x04 - kPaused = 0x05 + kPowerAdjustActive = 0x03 + kPaused = 0x04 # All received enum values that are not listed above will be mapped # to kUnknownEnumValue. This is a helper enum value that should only # be used by code to process how it handles receiving and unknown # enum value. This specific should never be transmitted. - kUnknownEnumValue = 6, + kUnknownEnumValue = 5, class ESATypeEnum(MatterIntEnum): kEvse = 0x00 @@ -23451,12 +23462,36 @@ class ESATypeEnum(MatterIntEnum): # enum value. This specific should never be transmitted. kUnknownEnumValue = 14, + class ForecastUpdateReasonEnum(MatterIntEnum): + kInternalOptimization = 0x00 + kLocalOptimization = 0x01 + kGridOptimization = 0x02 + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving and unknown + # enum value. This specific should never be transmitted. + kUnknownEnumValue = 3, + + class OptOutStateEnum(MatterIntEnum): + kNoOptOut = 0x00 + kLocalOptOut = 0x01 + kGridOptOut = 0x02 + kOptOut = 0x03 + # All received enum values that are not listed above will be mapped + # to kUnknownEnumValue. This is a helper enum value that should only + # be used by code to process how it handles receiving and unknown + # enum value. This specific should never be transmitted. + kUnknownEnumValue = 4, + class Bitmaps: class Feature(IntFlag): kPowerAdjustment = 0x1 kPowerForecastReporting = 0x2 kStateForecastReporting = 0x4 - kForecastAdjustment = 0x8 + kStartTimeAdjustment = 0x8 + kPausable = 0x10 + kForecastAdjustment = 0x20 + kConstraintBasedAdjustment = 0x40 class Structs: @dataclass @@ -23487,9 +23522,9 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="defaultDuration", Tag=2, Type=uint), ClusterObjectFieldDescriptor(Label="elapsedSlotTime", Tag=3, Type=uint), ClusterObjectFieldDescriptor(Label="remainingSlotTime", Tag=4, Type=uint), - ClusterObjectFieldDescriptor(Label="slotIsPauseable", Tag=5, Type=bool), - ClusterObjectFieldDescriptor(Label="minPauseDuration", Tag=6, Type=uint), - ClusterObjectFieldDescriptor(Label="maxPauseDuration", Tag=7, Type=uint), + ClusterObjectFieldDescriptor(Label="slotIsPauseable", Tag=5, Type=typing.Optional[bool]), + ClusterObjectFieldDescriptor(Label="minPauseDuration", Tag=6, Type=typing.Optional[uint]), + ClusterObjectFieldDescriptor(Label="maxPauseDuration", Tag=7, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="manufacturerESAState", Tag=8, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="nominalPower", Tag=9, Type=typing.Optional[int]), ClusterObjectFieldDescriptor(Label="minPower", Tag=10, Type=typing.Optional[int]), @@ -23507,9 +23542,9 @@ def descriptor(cls) -> ClusterObjectDescriptor: defaultDuration: 'uint' = 0 elapsedSlotTime: 'uint' = 0 remainingSlotTime: 'uint' = 0 - slotIsPauseable: 'bool' = False - minPauseDuration: 'uint' = 0 - maxPauseDuration: 'uint' = 0 + slotIsPauseable: 'typing.Optional[bool]' = None + minPauseDuration: 'typing.Optional[uint]' = None + maxPauseDuration: 'typing.Optional[uint]' = None manufacturerESAState: 'typing.Optional[uint]' = None nominalPower: 'typing.Optional[int]' = None minPower: 'typing.Optional[int]' = None @@ -23535,6 +23570,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: ClusterObjectFieldDescriptor(Label="latestEndTime", Tag=5, Type=typing.Optional[uint]), ClusterObjectFieldDescriptor(Label="isPauseable", Tag=6, Type=bool), ClusterObjectFieldDescriptor(Label="slots", Tag=7, Type=typing.List[DeviceEnergyManagement.Structs.SlotStruct]), + ClusterObjectFieldDescriptor(Label="forecastUpdateReason", Tag=8, Type=DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum), ]) forecastId: 'uint' = 0 @@ -23545,6 +23581,7 @@ def descriptor(cls) -> ClusterObjectDescriptor: latestEndTime: 'typing.Optional[uint]' = None isPauseable: 'bool' = False slots: 'typing.List[DeviceEnergyManagement.Structs.SlotStruct]' = field(default_factory=lambda: []) + forecastUpdateReason: 'DeviceEnergyManagement.Enums.ForecastUpdateReasonEnum' = 0 @dataclass class ConstraintsStruct(ClusterObject): @@ -23611,10 +23648,12 @@ def descriptor(cls) -> ClusterObjectDescriptor: Fields=[ ClusterObjectFieldDescriptor(Label="power", Tag=0, Type=int), ClusterObjectFieldDescriptor(Label="duration", Tag=1, Type=uint), + ClusterObjectFieldDescriptor(Label="cause", Tag=2, Type=DeviceEnergyManagement.Enums.AdjustmentCauseEnum), ]) power: 'int' = 0 duration: 'uint' = 0 + cause: 'DeviceEnergyManagement.Enums.AdjustmentCauseEnum' = 0 @dataclass class CancelPowerAdjustRequest(ClusterCommand): @@ -23641,9 +23680,11 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="requestedStartTime", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="cause", Tag=1, Type=DeviceEnergyManagement.Enums.AdjustmentCauseEnum), ]) requestedStartTime: 'uint' = 0 + cause: 'DeviceEnergyManagement.Enums.AdjustmentCauseEnum' = 0 @dataclass class PauseRequest(ClusterCommand): @@ -23657,9 +23698,11 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="duration", Tag=0, Type=uint), + ClusterObjectFieldDescriptor(Label="cause", Tag=1, Type=DeviceEnergyManagement.Enums.AdjustmentCauseEnum), ]) duration: 'uint' = 0 + cause: 'DeviceEnergyManagement.Enums.AdjustmentCauseEnum' = 0 @dataclass class ResumeRequest(ClusterCommand): @@ -23687,10 +23730,12 @@ def descriptor(cls) -> ClusterObjectDescriptor: Fields=[ ClusterObjectFieldDescriptor(Label="forecastId", Tag=0, Type=uint), ClusterObjectFieldDescriptor(Label="slotAdjustments", Tag=1, Type=typing.List[DeviceEnergyManagement.Structs.SlotAdjustmentStruct]), + ClusterObjectFieldDescriptor(Label="cause", Tag=2, Type=DeviceEnergyManagement.Enums.AdjustmentCauseEnum), ]) forecastId: 'uint' = 0 slotAdjustments: 'typing.List[DeviceEnergyManagement.Structs.SlotAdjustmentStruct]' = field(default_factory=lambda: []) + cause: 'DeviceEnergyManagement.Enums.AdjustmentCauseEnum' = 0 @dataclass class RequestConstraintBasedForecast(ClusterCommand): @@ -23704,9 +23749,24 @@ def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ ClusterObjectFieldDescriptor(Label="constraints", Tag=0, Type=typing.List[DeviceEnergyManagement.Structs.ConstraintsStruct]), + ClusterObjectFieldDescriptor(Label="cause", Tag=1, Type=DeviceEnergyManagement.Enums.AdjustmentCauseEnum), ]) constraints: 'typing.List[DeviceEnergyManagement.Structs.ConstraintsStruct]' = field(default_factory=lambda: []) + cause: 'DeviceEnergyManagement.Enums.AdjustmentCauseEnum' = 0 + + @dataclass + class CancelRequest(ClusterCommand): + cluster_id: typing.ClassVar[int] = 0x00000098 + command_id: typing.ClassVar[int] = 0x00000007 + is_client: typing.ClassVar[bool] = True + response_type: typing.ClassVar[str] = None + + @ChipUtility.classproperty + def descriptor(cls) -> ClusterObjectDescriptor: + return ClusterObjectDescriptor( + Fields=[ + ]) class Attributes: @dataclass @@ -23821,6 +23881,22 @@ def attribute_type(cls) -> ClusterObjectFieldDescriptor: value: 'typing.Union[None, Nullable, DeviceEnergyManagement.Structs.ForecastStruct]' = None + @dataclass + class OptOutState(ClusterAttributeDescriptor): + @ChipUtility.classproperty + def cluster_id(cls) -> int: + return 0x00000098 + + @ChipUtility.classproperty + def attribute_id(cls) -> int: + return 0x00000007 + + @ChipUtility.classproperty + def attribute_type(cls) -> ClusterObjectFieldDescriptor: + return ClusterObjectFieldDescriptor(Type=typing.Optional[DeviceEnergyManagement.Enums.OptOutStateEnum]) + + value: 'typing.Optional[DeviceEnergyManagement.Enums.OptOutStateEnum]' = None + @dataclass class GeneratedCommandList(ClusterAttributeDescriptor): @ChipUtility.classproperty @@ -23987,8 +24063,11 @@ def event_id(cls) -> int: def descriptor(cls) -> ClusterObjectDescriptor: return ClusterObjectDescriptor( Fields=[ + ClusterObjectFieldDescriptor(Label="cause", Tag=0, Type=DeviceEnergyManagement.Enums.CauseEnum), ]) + cause: 'DeviceEnergyManagement.Enums.CauseEnum' = 0 + @dataclass class EnergyEvse(Cluster): diff --git a/src/credentials/BUILD.gn b/src/credentials/BUILD.gn index 0e23eb497cf702..6aa10311560fa5 100644 --- a/src/credentials/BUILD.gn +++ b/src/credentials/BUILD.gn @@ -128,6 +128,8 @@ static_library("credentials") { "${chip_root}/src/lib/support", "${chip_root}/src/platform", "${chip_root}/src/protocols:type_definitions", + "${chip_root}/src/tracing", + "${chip_root}/src/tracing:macros", "${nlassert_root}:nlassert", ] } diff --git a/src/credentials/FabricTable.cpp b/src/credentials/FabricTable.cpp index 0091fdec291c30..ade5189a738f27 100644 --- a/src/credentials/FabricTable.cpp +++ b/src/credentials/FabricTable.cpp @@ -29,6 +29,7 @@ #include #include #include +#include namespace chip { using namespace Credentials; @@ -279,6 +280,7 @@ CHIP_ERROR FabricTable::ValidateIncomingNOCChain(const ByteSpan & noc, const Byt NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey, Crypto::P256PublicKey & outRootPubkey) { + MATTER_TRACE_SCOPE("ValidateIncomingNOCChain", "Fabric"); Credentials::ValidationContext validContext; // Note that we do NOT set a time in the validation context. This will @@ -328,6 +330,7 @@ CHIP_ERROR FabricTable::ValidateIncomingNOCChain(const ByteSpan & noc, const Byt CHIP_ERROR FabricInfo::SignWithOpKeypair(ByteSpan message, P256ECDSASignature & outSignature) const { + MATTER_TRACE_SCOPE("SignWithOpKeypair", "Fabric"); VerifyOrReturnError(mOperationalKey != nullptr, CHIP_ERROR_KEY_NOT_FOUND); return mOperationalKey->ECDSA_sign_msg(message.data(), message.size(), outSignature); @@ -335,6 +338,7 @@ CHIP_ERROR FabricInfo::SignWithOpKeypair(ByteSpan message, P256ECDSASignature & CHIP_ERROR FabricInfo::FetchRootPubkey(Crypto::P256PublicKey & outPublicKey) const { + MATTER_TRACE_SCOPE("FetchRootPubKey", "Fabric"); VerifyOrReturnError(IsInitialized(), CHIP_ERROR_KEY_NOT_FOUND); outPublicKey = mRootPublicKey; return CHIP_NO_ERROR; @@ -345,6 +349,7 @@ CHIP_ERROR FabricTable::VerifyCredentials(FabricIndex fabricIndex, const ByteSpa FabricId & outFabricId, NodeId & outNodeId, Crypto::P256PublicKey & outNocPubkey, Crypto::P256PublicKey * outRootPublicKey) const { + MATTER_TRACE_SCOPE("VerifyCredentials", "Fabric"); assertChipStackLockedByCurrentThread(); uint8_t rootCertBuf[kMaxCHIPCertLength]; MutableByteSpan rootCertSpan{ rootCertBuf }; @@ -562,12 +567,14 @@ const FabricInfo * FabricTable::FindFabricWithCompressedId(CompressedFabricId co CHIP_ERROR FabricTable::FetchRootCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const { + MATTER_TRACE_SCOPE("FetchRootCert", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); return mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kRcac, outCert); } CHIP_ERROR FabricTable::FetchPendingNonFabricAssociatedRootCert(MutableByteSpan & outCert) const { + MATTER_TRACE_SCOPE("FetchPendingNonFabricAssociatedRootCert", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); if (!mStateFlags.Has(StateFlags::kIsTrustedRootPending)) { @@ -586,6 +593,7 @@ CHIP_ERROR FabricTable::FetchPendingNonFabricAssociatedRootCert(MutableByteSpan CHIP_ERROR FabricTable::FetchICACert(FabricIndex fabricIndex, MutableByteSpan & outCert) const { + MATTER_TRACE_SCOPE("FetchICACert", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); CHIP_ERROR err = mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kIcac, outCert); @@ -605,12 +613,14 @@ CHIP_ERROR FabricTable::FetchICACert(FabricIndex fabricIndex, MutableByteSpan & CHIP_ERROR FabricTable::FetchNOCCert(FabricIndex fabricIndex, MutableByteSpan & outCert) const { + MATTER_TRACE_SCOPE("FetchNOCCert", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); return mOpCertStore->GetCertificate(fabricIndex, CertChainElement::kNoc, outCert); } CHIP_ERROR FabricTable::FetchRootPubkey(FabricIndex fabricIndex, Crypto::P256PublicKey & outPublicKey) const { + MATTER_TRACE_SCOPE("FetchRootPubkey", "Fabric"); const FabricInfo * fabricInfo = FindFabricWithIndex(fabricIndex); ReturnErrorCodeIf(fabricInfo == nullptr, CHIP_ERROR_INVALID_FABRIC_INDEX); return fabricInfo->FetchRootPubkey(outPublicKey); @@ -747,6 +757,7 @@ class NotBeforeCollector : public Credentials::CertificateValidityPolicy CHIP_ERROR FabricTable::NotifyFabricUpdated(FabricIndex fabricIndex) { + MATTER_TRACE_SCOPE("NotifyFabricUpdated", "Fabric"); FabricTable::Delegate * delegate = mDelegateListRoot; while (delegate) { @@ -761,6 +772,8 @@ CHIP_ERROR FabricTable::NotifyFabricUpdated(FabricIndex fabricIndex) CHIP_ERROR FabricTable::NotifyFabricCommitted(FabricIndex fabricIndex) { + MATTER_TRACE_SCOPE("NotifyFabricCommitted", "Fabric"); + FabricTable::Delegate * delegate = mDelegateListRoot; while (delegate) { @@ -919,6 +932,7 @@ FabricTable::AddOrUpdateInner(FabricIndex fabricIndex, bool isAddition, Crypto:: CHIP_ERROR FabricTable::Delete(FabricIndex fabricIndex) { + MATTER_TRACE_SCOPE("Delete", "Fabric"); VerifyOrReturnError(mStorage != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_ARGUMENT); @@ -1608,6 +1622,7 @@ CHIP_ERROR FabricTable::AddNewPendingTrustedRootCert(const ByteSpan & rcac) CHIP_ERROR FabricTable::FindExistingFabricByNocChaining(FabricIndex pendingFabricIndex, const ByteSpan & noc, FabricIndex & outMatchingFabricIndex) const { + MATTER_TRACE_SCOPE("FindExistingFabricByNocChaining", "Fabric"); // Check whether we already have a matching fabric from a cert chain perspective. // To do so we have to extract the FabricID from the NOC and the root public key from the RCAC. // We assume the RCAC is currently readable from OperationalCertificateStore, whether pending @@ -1653,6 +1668,7 @@ CHIP_ERROR FabricTable::AddNewPendingFabricCommon(const ByteSpan & noc, const By Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned, AdvertiseIdentity advertiseIdentity, FabricIndex * outNewFabricIndex) { + MATTER_TRACE_SCOPE("AddNewPendingFabricCommon", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(outNewFabricIndex != nullptr, CHIP_ERROR_INVALID_ARGUMENT); static_assert(kMaxValidFabricIndex <= UINT8_MAX, "Cannot create more fabrics than UINT8_MAX"); @@ -1724,6 +1740,7 @@ CHIP_ERROR FabricTable::UpdatePendingFabricCommon(FabricIndex fabricIndex, const Crypto::P256Keypair * existingOpKey, bool isExistingOpKeyExternallyOwned, AdvertiseIdentity advertiseIdentity) { + MATTER_TRACE_SCOPE("UpdatePendingFabricCommon", "Fabric"); VerifyOrReturnError(mOpCertStore != nullptr, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(IsValidFabricIndex(fabricIndex), CHIP_ERROR_INVALID_ARGUMENT); @@ -2009,6 +2026,7 @@ CHIP_ERROR FabricTable::CommitPendingFabricData() void FabricTable::RevertPendingFabricData() { + MATTER_TRACE_SCOPE("RevertPendingFabricData", "Fabric"); // Will clear pending UpdateNoc/AddNOC RevertPendingOpCertsExceptRoot(); @@ -2031,6 +2049,7 @@ void FabricTable::RevertPendingFabricData() void FabricTable::RevertPendingOpCertsExceptRoot() { + MATTER_TRACE_SCOPE("RevertPendingOpCertsExceptRoot", "Fabric"); mPendingFabric.Reset(); if (mStateFlags.Has(StateFlags::kIsPendingFabricDataPresent)) diff --git a/src/darwin/Framework/CHIP/templates/availability.yaml b/src/darwin/Framework/CHIP/templates/availability.yaml index 611851a064c183..e1f129f9d0e763 100644 --- a/src/darwin/Framework/CHIP/templates/availability.yaml +++ b/src/darwin/Framework/CHIP/templates/availability.yaml @@ -8557,12 +8557,54 @@ - NumberOfAliroCredentialIssuerKeysSupported - NumberOfAliroEndpointKeysSupported ICDManagement: + # Targeting Spring 2024 Matter release - OperatingMode + Thermostat: + # Targeting Spring 2024 Matter release + - PresetTypes + - ScheduleTypes + - NumberOfPresets + - NumberOfSchedules + - NumberOfScheduleTransitions + - NumberOfScheduleTransitionPerDay + - ActivePresetHandle + - Presets + - Schedules + - PresetsSchedulesEditable + - TemperatureSetpointHoldPolicy + - SetpointHoldExpiryTimestamp + - QueuedPreset + - ActiveScheduleHandle commands: DoorLock: # Aliro is not ready yet. - SetAliroReaderConfig - ClearAliroReaderConfig + Thermostat: + # Targeting Spring 2024 Matter release + - SetActiveScheduleRequest + - SetActivePresetRequest + - StartPresetsSchedulesEditRequest + - CancelPresetsSchedulesEditRequest + - CommitPresetsSchedulesRequest + - CancelSetActivePresetRequest + - SetTemperatureSetpointHoldPolicy + RVCOperationalState: + # Targeting Spring 2024 Matter release + - GoHome + structs: + Thermostat: + # Targeting Spring 2024 Matter release + - ScheduleTransitionStruct + - ScheduleStruct + - PresetStruct + - PresetTypeStruct + - ScheduleTypeStruct + - QueuedPresetStruct + enums: + Thermostat: + # Targeting Spring 2024 Matter release + - PresetScenarioEnum enum values: DoorLock: CredentialTypeEnum: @@ -8578,9 +8620,26 @@ OperationSourceEnum: # Aliro is not ready yet. - Aliro + RVCRunMode: + ModeTag: + # Targeting Spring 2024 Matter release + - Mapping + bitmaps: + Thermostat: + # Targeting Spring 2024 Matter release + - PresetTypeFeaturesBitmap + - ScheduleTypeFeaturesBitmap + - TemperatureSetpointHoldPolicyBitmap bitmap values: DoorLock: Feature: # Aliro is not ready yet. - AliroProvisioning - AliroBLEUWB + Thermostat: + Feature: + # Targeting Spring 2024 Matter release + - QueuedPresetsSupported + - Setpoints + - Presets + - MatterScheduleConfiguration diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm index d7d9849a4f9c57..a63147b8a9eedf 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeSpecifiedCheck.mm @@ -3063,6 +3063,9 @@ static BOOL AttributeIsSpecifiedInDeviceEnergyManagementCluster(AttributeId aAtt case Attributes::Forecast::Id: { return YES; } + case Attributes::OptOutState::Id: { + return YES; + } case Attributes::GeneratedCommandList::Id: { return YES; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm index acf77070414712..eb5827496fc0d5 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRAttributeTLVValueDecoder.mm @@ -8446,9 +8446,21 @@ static id _Nullable DecodeAttributeValueForDeviceEnergyManagementCluster(Attribu newElement_2.defaultDuration = [NSNumber numberWithUnsignedInt:entry_2.defaultDuration]; newElement_2.elapsedSlotTime = [NSNumber numberWithUnsignedInt:entry_2.elapsedSlotTime]; newElement_2.remainingSlotTime = [NSNumber numberWithUnsignedInt:entry_2.remainingSlotTime]; - newElement_2.slotIsPauseable = [NSNumber numberWithBool:entry_2.slotIsPauseable]; - newElement_2.minPauseDuration = [NSNumber numberWithUnsignedInt:entry_2.minPauseDuration]; - newElement_2.maxPauseDuration = [NSNumber numberWithUnsignedInt:entry_2.maxPauseDuration]; + if (entry_2.slotIsPauseable.HasValue()) { + newElement_2.slotIsPauseable = [NSNumber numberWithBool:entry_2.slotIsPauseable.Value()]; + } else { + newElement_2.slotIsPauseable = nil; + } + if (entry_2.minPauseDuration.HasValue()) { + newElement_2.minPauseDuration = [NSNumber numberWithUnsignedInt:entry_2.minPauseDuration.Value()]; + } else { + newElement_2.minPauseDuration = nil; + } + if (entry_2.maxPauseDuration.HasValue()) { + newElement_2.maxPauseDuration = [NSNumber numberWithUnsignedInt:entry_2.maxPauseDuration.Value()]; + } else { + newElement_2.maxPauseDuration = nil; + } if (entry_2.manufacturerESAState.HasValue()) { newElement_2.manufacturerESAState = [NSNumber numberWithUnsignedShort:entry_2.manufacturerESAState.Value()]; } else { @@ -8531,9 +8543,21 @@ static id _Nullable DecodeAttributeValueForDeviceEnergyManagementCluster(Attribu } value.slots = array_2; } + value.forecastUpdateReason = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue.Value().forecastUpdateReason)]; } return value; } + case Attributes::OptOutState::Id: { + using TypeInfo = Attributes::OptOutState::TypeInfo; + TypeInfo::DecodableType cppValue; + *aError = DataModel::Decode(aReader, cppValue); + if (*aError != CHIP_NO_ERROR) { + return nil; + } + NSNumber * _Nonnull value; + value = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue)]; + return value; + } default: { break; } diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h index f484ada4d19774..f30370c30b409a 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.h @@ -7591,6 +7591,14 @@ MTR_PROVISIONALLY_AVAILABLE * Allows a client to ask the ESA to recompute its Forecast based on power and time constraints. */ - (void)requestConstraintBasedForecastWithParams:(MTRDeviceEnergyManagementClusterRequestConstraintBasedForecastParams *)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +/** + * Command CancelRequest + * + * Allows a client to request cancellation of a previous adjustment request in a StartTimeAdjustRequest, ModifyForecastRequest or RequestConstraintBasedForecast command + */ +- (void)cancelRequestWithParams:(MTRDeviceEnergyManagementClusterCancelRequestParams * _Nullable)params completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)cancelRequestWithCompletion:(MTRStatusCompletion)completion + MTR_PROVISIONALLY_AVAILABLE; - (void)readAttributeESATypeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeESATypeWithParams:(MTRSubscribeParams *)params @@ -7634,6 +7642,12 @@ MTR_PROVISIONALLY_AVAILABLE reportHandler:(void (^)(MTRDeviceEnergyManagementClusterForecastStruct * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; + (void)readAttributeForecastWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(MTRDeviceEnergyManagementClusterForecastStruct * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)readAttributeOptOutStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; +- (void)subscribeAttributeOptOutStateWithParams:(MTRSubscribeParams *)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler MTR_PROVISIONALLY_AVAILABLE; ++ (void)readAttributeOptOutStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion MTR_PROVISIONALLY_AVAILABLE; - (void)subscribeAttributeGeneratedCommandListWithParams:(MTRSubscribeParams *)params subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished @@ -17357,11 +17371,17 @@ typedef NS_OPTIONS(uint32_t, MTRDemandResponseLoadControlFeature) { MTRDemandResponseLoadControlFeatureHeatingSource MTR_PROVISIONALLY_AVAILABLE = 0x40, } MTR_PROVISIONALLY_AVAILABLE; +typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementAdjustmentCause) { + MTRDeviceEnergyManagementAdjustmentCauseLocalOptimization MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRDeviceEnergyManagementAdjustmentCauseGridOptimization MTR_PROVISIONALLY_AVAILABLE = 0x01, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementCause) { MTRDeviceEnergyManagementCauseNormalCompletion MTR_PROVISIONALLY_AVAILABLE = 0x00, MTRDeviceEnergyManagementCauseOffline MTR_PROVISIONALLY_AVAILABLE = 0x01, MTRDeviceEnergyManagementCauseFault MTR_PROVISIONALLY_AVAILABLE = 0x02, MTRDeviceEnergyManagementCauseUserOptOut MTR_PROVISIONALLY_AVAILABLE = 0x03, + MTRDeviceEnergyManagementCauseCancelled MTR_PROVISIONALLY_AVAILABLE = 0x04, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementCostType) { @@ -17375,9 +17395,8 @@ typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementESAState) { MTRDeviceEnergyManagementESAStateOffline MTR_PROVISIONALLY_AVAILABLE = 0x00, MTRDeviceEnergyManagementESAStateOnline MTR_PROVISIONALLY_AVAILABLE = 0x01, MTRDeviceEnergyManagementESAStateFault MTR_PROVISIONALLY_AVAILABLE = 0x02, - MTRDeviceEnergyManagementESAStateUserOptOut MTR_PROVISIONALLY_AVAILABLE = 0x03, - MTRDeviceEnergyManagementESAStatePowerAdjustActive MTR_PROVISIONALLY_AVAILABLE = 0x04, - MTRDeviceEnergyManagementESAStatePaused MTR_PROVISIONALLY_AVAILABLE = 0x05, + MTRDeviceEnergyManagementESAStatePowerAdjustActive MTR_PROVISIONALLY_AVAILABLE = 0x03, + MTRDeviceEnergyManagementESAStatePaused MTR_PROVISIONALLY_AVAILABLE = 0x04, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementESAType) { @@ -17398,11 +17417,27 @@ typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementESAType) { MTRDeviceEnergyManagementESATypeOther MTR_PROVISIONALLY_AVAILABLE = 0xFF, } MTR_PROVISIONALLY_AVAILABLE; +typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementForecastUpdateReason) { + MTRDeviceEnergyManagementForecastUpdateReasonInternalOptimization MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRDeviceEnergyManagementForecastUpdateReasonLocalOptimization MTR_PROVISIONALLY_AVAILABLE = 0x01, + MTRDeviceEnergyManagementForecastUpdateReasonGridOptimization MTR_PROVISIONALLY_AVAILABLE = 0x02, +} MTR_PROVISIONALLY_AVAILABLE; + +typedef NS_ENUM(uint8_t, MTRDeviceEnergyManagementOptOutState) { + MTRDeviceEnergyManagementOptOutStateNoOptOut MTR_PROVISIONALLY_AVAILABLE = 0x00, + MTRDeviceEnergyManagementOptOutStateLocalOptOut MTR_PROVISIONALLY_AVAILABLE = 0x01, + MTRDeviceEnergyManagementOptOutStateGridOptOut MTR_PROVISIONALLY_AVAILABLE = 0x02, + MTRDeviceEnergyManagementOptOutStateOptOut MTR_PROVISIONALLY_AVAILABLE = 0x03, +} MTR_PROVISIONALLY_AVAILABLE; + typedef NS_OPTIONS(uint32_t, MTRDeviceEnergyManagementFeature) { MTRDeviceEnergyManagementFeaturePowerAdjustment MTR_PROVISIONALLY_AVAILABLE = 0x1, MTRDeviceEnergyManagementFeaturePowerForecastReporting MTR_PROVISIONALLY_AVAILABLE = 0x2, MTRDeviceEnergyManagementFeatureStateForecastReporting MTR_PROVISIONALLY_AVAILABLE = 0x4, - MTRDeviceEnergyManagementFeatureForecastAdjustment MTR_PROVISIONALLY_AVAILABLE = 0x8, + MTRDeviceEnergyManagementFeatureStartTimeAdjustment MTR_PROVISIONALLY_AVAILABLE = 0x8, + MTRDeviceEnergyManagementFeaturePausable MTR_PROVISIONALLY_AVAILABLE = 0x10, + MTRDeviceEnergyManagementFeatureForecastAdjustment MTR_PROVISIONALLY_AVAILABLE = 0x20, + MTRDeviceEnergyManagementFeatureConstraintBasedAdjustment MTR_PROVISIONALLY_AVAILABLE = 0x40, } MTR_PROVISIONALLY_AVAILABLE; typedef NS_ENUM(uint8_t, MTREnergyEVSEEnergyTransferStoppedReason) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm index aa248a596e44b3..2b8f1dbfc61eec 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRBaseClusters.mm @@ -51414,6 +51414,34 @@ - (void)requestConstraintBasedForecastWithParams:(MTRDeviceEnergyManagementClust queue:self.callbackQueue completion:responseHandler]; } +- (void)cancelRequestWithCompletion:(MTRStatusCompletion)completion +{ + [self cancelRequestWithParams:nil completion:completion]; +} +- (void)cancelRequestWithParams:(MTRDeviceEnergyManagementClusterCancelRequestParams * _Nullable)params completion:(MTRStatusCompletion)completion +{ + if (params == nil) { + params = [[MTRDeviceEnergyManagementClusterCancelRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = DeviceEnergyManagement::Commands::CancelRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.callbackQueue + completion:responseHandler]; +} - (void)readAttributeESATypeWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion { @@ -51667,6 +51695,42 @@ + (void)readAttributeForecastWithClusterStateCache:(MTRClusterStateCacheContaine completion:completion]; } +- (void)readAttributeOptOutStateWithCompletion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = DeviceEnergyManagement::Attributes::OptOutState::TypeInfo; + [self.device _readKnownAttributeWithEndpointID:@(self.endpoint) + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:nil + queue:self.callbackQueue + completion:completion]; +} + +- (void)subscribeAttributeOptOutStateWithParams:(MTRSubscribeParams * _Nonnull)params + subscriptionEstablished:(MTRSubscriptionEstablishedHandler _Nullable)subscriptionEstablished + reportHandler:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))reportHandler +{ + using TypeInfo = DeviceEnergyManagement::Attributes::OptOutState::TypeInfo; + [self.device _subscribeToKnownAttributeWithEndpointID:@(self.endpoint) + clusterID:@(TypeInfo::GetClusterId()) + attributeID:@(TypeInfo::GetAttributeId()) + params:params + queue:self.callbackQueue + reportHandler:reportHandler + subscriptionEstablished:subscriptionEstablished]; +} + ++ (void)readAttributeOptOutStateWithClusterStateCache:(MTRClusterStateCacheContainer *)clusterStateCacheContainer endpoint:(NSNumber *)endpoint queue:(dispatch_queue_t)queue completion:(void (^)(NSNumber * _Nullable value, NSError * _Nullable error))completion +{ + using TypeInfo = DeviceEnergyManagement::Attributes::OptOutState::TypeInfo; + [clusterStateCacheContainer + _readKnownCachedAttributeWithEndpointID:static_cast([endpoint unsignedShortValue]) + clusterID:TypeInfo::GetClusterId() + attributeID:TypeInfo::GetAttributeId() + queue:queue + completion:completion]; +} + - (void)readAttributeGeneratedCommandListWithCompletion:(void (^)(NSArray * _Nullable value, NSError * _Nullable error))completion { using TypeInfo = DeviceEnergyManagement::Attributes::GeneratedCommandList::TypeInfo; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h index fedd4aa13d0628..f598a052c31fb4 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusterConstants.h @@ -2618,6 +2618,7 @@ typedef NS_ENUM(uint32_t, MTRAttributeIDType) { MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeAbsMaxPowerID MTR_PROVISIONALLY_AVAILABLE = 0x00000004, MTRAttributeIDTypeClusterDeviceEnergyManagementAttributePowerAdjustmentCapabilityID MTR_PROVISIONALLY_AVAILABLE = 0x00000005, MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeForecastID MTR_PROVISIONALLY_AVAILABLE = 0x00000006, + MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeOptOutStateID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeGeneratedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeGeneratedCommandListID, MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeAcceptedCommandListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeAcceptedCommandListID, MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeEventListID MTR_PROVISIONALLY_AVAILABLE = MTRAttributeIDTypeGlobalAttributeEventListID, @@ -6220,6 +6221,7 @@ typedef NS_ENUM(uint32_t, MTRCommandIDType) { MTRCommandIDTypeClusterDeviceEnergyManagementCommandResumeRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000004, MTRCommandIDTypeClusterDeviceEnergyManagementCommandModifyForecastRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000005, MTRCommandIDTypeClusterDeviceEnergyManagementCommandRequestConstraintBasedForecastID MTR_PROVISIONALLY_AVAILABLE = 0x00000006, + MTRCommandIDTypeClusterDeviceEnergyManagementCommandCancelRequestID MTR_PROVISIONALLY_AVAILABLE = 0x00000007, // Cluster EnergyEVSE commands MTRCommandIDTypeClusterEnergyEVSECommandGetTargetsResponseID MTR_PROVISIONALLY_AVAILABLE = 0x00000000, diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h index a102f158d5b0a4..38d6ca3aba518e 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.h @@ -3583,6 +3583,9 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE; - (void)modifyForecastRequestWithParams:(MTRDeviceEnergyManagementClusterModifyForecastRequestParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; - (void)requestConstraintBasedForecastWithParams:(MTRDeviceEnergyManagementClusterRequestConstraintBasedForecastParams *)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)cancelRequestWithParams:(MTRDeviceEnergyManagementClusterCancelRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedDataValueDictionaries expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion MTR_PROVISIONALLY_AVAILABLE; +- (void)cancelRequestWithExpectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion + MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeESATypeWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; @@ -3598,6 +3601,8 @@ MTR_PROVISIONALLY_AVAILABLE - (NSDictionary * _Nullable)readAttributeForecastWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; +- (NSDictionary * _Nullable)readAttributeOptOutStateWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; - (NSDictionary * _Nullable)readAttributeAcceptedCommandListWithParams:(MTRReadParams * _Nullable)params MTR_PROVISIONALLY_AVAILABLE; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm index 11ca8e1ab2e8eb..b9373e99317821 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRClusters.mm @@ -9735,6 +9735,37 @@ - (void)requestConstraintBasedForecastWithParams:(MTRDeviceEnergyManagementClust completion:responseHandler]; } +- (void)cancelRequestWithExpectedValues:(NSArray *> *)expectedValues expectedValueInterval:(NSNumber *)expectedValueIntervalMs completion:(MTRStatusCompletion)completion +{ + [self cancelRequestWithParams:nil expectedValues:expectedValues expectedValueInterval:expectedValueIntervalMs completion:completion]; +} +- (void)cancelRequestWithParams:(MTRDeviceEnergyManagementClusterCancelRequestParams * _Nullable)params expectedValues:(NSArray *> * _Nullable)expectedValues expectedValueInterval:(NSNumber * _Nullable)expectedValueIntervalMs completion:(MTRStatusCompletion)completion +{ + if (params == nil) { + params = [[MTRDeviceEnergyManagementClusterCancelRequestParams + alloc] init]; + } + + auto responseHandler = ^(id _Nullable response, NSError * _Nullable error) { + completion(error); + }; + + auto * timedInvokeTimeoutMs = params.timedInvokeTimeoutMs; + + using RequestType = DeviceEnergyManagement::Commands::CancelRequest::Type; + [self.device _invokeKnownCommandWithEndpointID:@(self.endpoint) + clusterID:@(RequestType::GetClusterId()) + commandID:@(RequestType::GetCommandId()) + commandPayload:params + expectedValues:expectedValues + expectedValueInterval:expectedValueIntervalMs + timedInvokeTimeout:timedInvokeTimeoutMs + serverSideProcessingTimeout:params.serverSideProcessingTimeout + responseClass:nil + queue:self.callbackQueue + completion:responseHandler]; +} + - (NSDictionary * _Nullable)readAttributeESATypeWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:@(self.endpoint) clusterID:@(MTRClusterIDTypeDeviceEnergyManagementID) attributeID:@(MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeESATypeID) params:params]; @@ -9770,6 +9801,11 @@ - (void)requestConstraintBasedForecastWithParams:(MTRDeviceEnergyManagementClust return [self.device readAttributeWithEndpointID:@(self.endpoint) clusterID:@(MTRClusterIDTypeDeviceEnergyManagementID) attributeID:@(MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeForecastID) params:params]; } +- (NSDictionary * _Nullable)readAttributeOptOutStateWithParams:(MTRReadParams * _Nullable)params +{ + return [self.device readAttributeWithEndpointID:@(self.endpoint) clusterID:@(MTRClusterIDTypeDeviceEnergyManagementID) attributeID:@(MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeOptOutStateID) params:params]; +} + - (NSDictionary * _Nullable)readAttributeGeneratedCommandListWithParams:(MTRReadParams * _Nullable)params { return [self.device readAttributeWithEndpointID:@(self.endpoint) clusterID:@(MTRClusterIDTypeDeviceEnergyManagementID) attributeID:@(MTRAttributeIDTypeClusterDeviceEnergyManagementAttributeGeneratedCommandListID) params:params]; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h index 1656beb4969d85..968322f3f3ff47 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.h @@ -5639,6 +5639,8 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull power MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull duration MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5697,6 +5699,8 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRDeviceEnergyManagementClusterStartTimeAdjustRequestParams : NSObject @property (nonatomic, copy) NSNumber * _Nonnull requestedStartTime MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5727,6 +5731,8 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRDeviceEnergyManagementClusterPauseRequestParams : NSObject @property (nonatomic, copy) NSNumber * _Nonnull duration MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5787,6 +5793,8 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull forecastId MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSArray * _Nonnull slotAdjustments MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; /** * Controls whether the command is a timed command (using Timed Invoke). * @@ -5817,6 +5825,36 @@ MTR_PROVISIONALLY_AVAILABLE @interface MTRDeviceEnergyManagementClusterRequestConstraintBasedForecastParams : NSObject @property (nonatomic, copy) NSArray * _Nonnull constraints MTR_PROVISIONALLY_AVAILABLE; + +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; +/** + * Controls whether the command is a timed command (using Timed Invoke). + * + * If nil (the default value), a regular invoke is done for commands that do + * not require a timed invoke and a timed invoke with some default timed request + * timeout is done for commands that require a timed invoke. + * + * If not nil, a timed invoke is done, with the provided value used as the timed + * request timeout. The value should be chosen small enough to provide the + * desired security properties but large enough that it will allow a round-trip + * from the sever to the client (for the status response and actual invoke + * request) within the timeout window. + * + */ +@property (nonatomic, copy, nullable) NSNumber * timedInvokeTimeoutMs; + +/** + * Controls how much time, in seconds, we will allow for the server to process the command. + * + * The command will then time out if that much time, plus an allowance for retransmits due to network failures, passes. + * + * If nil, the framework will try to select an appropriate timeout value itself. + */ +@property (nonatomic, copy, nullable) NSNumber * serverSideProcessingTimeout; +@end + +MTR_PROVISIONALLY_AVAILABLE +@interface MTRDeviceEnergyManagementClusterCancelRequestParams : NSObject /** * Controls whether the command is a timed command (using Timed Invoke). * diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm index a1e41d3407a968..e19b1ee4477e4d 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloadsObjc.mm @@ -15903,6 +15903,8 @@ - (instancetype)init _power = @(0); _duration = @(0); + + _cause = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -15915,6 +15917,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.power = self.power; other.duration = self.duration; + other.cause = self.cause; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -15923,7 +15926,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: power:%@; duration:%@; >", NSStringFromClass([self class]), _power, _duration]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: power:%@; duration:%@; cause:%@; >", NSStringFromClass([self class]), _power, _duration, _cause]; return descriptionString; } @@ -15941,6 +15944,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { encodableStruct.duration = self.duration.unsignedIntValue; } + { + encodableStruct.cause = static_cast>(self.cause.unsignedCharValue); + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -16059,6 +16065,8 @@ - (instancetype)init if (self = [super init]) { _requestedStartTime = @(0); + + _cause = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -16070,6 +16078,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; auto other = [[MTRDeviceEnergyManagementClusterStartTimeAdjustRequestParams alloc] init]; other.requestedStartTime = self.requestedStartTime; + other.cause = self.cause; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -16078,7 +16087,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: requestedStartTime:%@; >", NSStringFromClass([self class]), _requestedStartTime]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: requestedStartTime:%@; cause:%@; >", NSStringFromClass([self class]), _requestedStartTime, _cause]; return descriptionString; } @@ -16093,6 +16102,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { encodableStruct.requestedStartTime = self.requestedStartTime.unsignedIntValue; } + { + encodableStruct.cause = static_cast>(self.cause.unsignedCharValue); + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -16138,6 +16150,8 @@ - (instancetype)init if (self = [super init]) { _duration = @(0); + + _cause = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -16149,6 +16163,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; auto other = [[MTRDeviceEnergyManagementClusterPauseRequestParams alloc] init]; other.duration = self.duration; + other.cause = self.cause; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -16157,7 +16172,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: duration:%@; >", NSStringFromClass([self class]), _duration]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: duration:%@; cause:%@; >", NSStringFromClass([self class]), _duration, _cause]; return descriptionString; } @@ -16172,6 +16187,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader { encodableStruct.duration = self.duration.unsignedIntValue; } + { + encodableStruct.cause = static_cast>(self.cause.unsignedCharValue); + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -16292,6 +16310,8 @@ - (instancetype)init _forecastId = @(0); _slotAdjustments = [NSArray array]; + + _cause = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -16304,6 +16324,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; other.forecastId = self.forecastId; other.slotAdjustments = self.slotAdjustments; + other.cause = self.cause; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -16312,7 +16333,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: forecastId:%@; slotAdjustments:%@; >", NSStringFromClass([self class]), _forecastId, _slotAdjustments]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: forecastId:%@; slotAdjustments:%@; cause:%@; >", NSStringFromClass([self class]), _forecastId, _slotAdjustments, _cause]; return descriptionString; } @@ -16353,6 +16374,9 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } } } + { + encodableStruct.cause = static_cast>(self.cause.unsignedCharValue); + } auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { @@ -16398,6 +16422,8 @@ - (instancetype)init if (self = [super init]) { _constraints = [NSArray array]; + + _cause = @(0); _timedInvokeTimeoutMs = nil; _serverSideProcessingTimeout = nil; } @@ -16409,6 +16435,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; auto other = [[MTRDeviceEnergyManagementClusterRequestConstraintBasedForecastParams alloc] init]; other.constraints = self.constraints; + other.cause = self.cause; other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; @@ -16417,7 +16444,7 @@ - (id)copyWithZone:(NSZone * _Nullable)zone; - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: constraints:%@; >", NSStringFromClass([self class]), _constraints]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: constraints:%@; cause:%@; >", NSStringFromClass([self class]), _constraints, _cause]; return descriptionString; } @@ -16466,6 +16493,82 @@ - (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader } } } + { + encodableStruct.cause = static_cast>(self.cause.unsignedCharValue); + } + + auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); + if (buffer.IsNull()) { + return CHIP_ERROR_NO_MEMORY; + } + + chip::System::PacketBufferTLVWriter writer; + // Commands never need chained buffers, since they cannot be chunked. + writer.Init(std::move(buffer), /* useChainedBuffers = */ false); + + ReturnErrorOnFailure(chip::app::DataModel::Encode(writer, chip::TLV::AnonymousTag(), encodableStruct)); + + ReturnErrorOnFailure(writer.Finalize(&buffer)); + + reader.Init(std::move(buffer)); + return reader.Next(chip::TLV::kTLVType_Structure, chip::TLV::AnonymousTag()); +} + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error +{ + chip::System::PacketBufferTLVReader reader; + CHIP_ERROR err = [self _encodeToTLVReader:reader]; + if (err != CHIP_NO_ERROR) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:err]; + } + return nil; + } + + auto decodedObj = MTRDecodeDataValueDictionaryFromCHIPTLV(&reader); + if (decodedObj == nil) { + if (error) { + *error = [MTRError errorForCHIPErrorCode:CHIP_ERROR_INCORRECT_STATE]; + } + } + return decodedObj; +} +@end + +@implementation MTRDeviceEnergyManagementClusterCancelRequestParams +- (instancetype)init +{ + if (self = [super init]) { + _timedInvokeTimeoutMs = nil; + _serverSideProcessingTimeout = nil; + } + return self; +} + +- (id)copyWithZone:(NSZone * _Nullable)zone; +{ + auto other = [[MTRDeviceEnergyManagementClusterCancelRequestParams alloc] init]; + + other.timedInvokeTimeoutMs = self.timedInvokeTimeoutMs; + other.serverSideProcessingTimeout = self.serverSideProcessingTimeout; + + return other; +} + +- (NSString *)description +{ + NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + return descriptionString; +} + +@end + +@implementation MTRDeviceEnergyManagementClusterCancelRequestParams (InternalMethods) + +- (CHIP_ERROR)_encodeToTLVReader:(chip::System::PacketBufferTLVReader &)reader +{ + chip::app::Clusters::DeviceEnergyManagement::Commands::CancelRequest::Type encodableStruct; + ListFreer listFreer; auto buffer = chip::System::PacketBufferHandle::New(chip::System::PacketBuffer::kMaxSizeWithoutReserve, 0); if (buffer.IsNull()) { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h index 7b33d80c72c54b..8f2f5b835c45f2 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRCommandPayloads_Internal.h @@ -1096,6 +1096,12 @@ NS_ASSUME_NONNULL_BEGIN @end +@interface MTRDeviceEnergyManagementClusterCancelRequestParams (InternalMethods) + +- (NSDictionary * _Nullable)_encodeAsDataValue:(NSError * __autoreleasing *)error; + +@end + @interface MTREnergyEVSEClusterGetTargetsResponseParams (InternalMethods) - (CHIP_ERROR)_setFieldsFromDecodableStruct:(const chip::app::Clusters::EnergyEvse::Commands::GetTargetsResponse::DecodableType &)decodableStruct; diff --git a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm index 119031161f5195..bd2e8e5b3470b5 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTREventTLVValueDecoder.mm @@ -2863,6 +2863,12 @@ static id _Nullable DecodeEventPayloadForDeviceEnergyManagementCluster(EventId a __auto_type * value = [MTRDeviceEnergyManagementClusterResumedEvent new]; + do { + NSNumber * _Nonnull memberValue; + memberValue = [NSNumber numberWithUnsignedChar:chip::to_underlying(cppValue.cause)]; + value.cause = memberValue; + } while (0); + return value; } default: { diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h index d57f138fa53256..0244d93dcea469 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.h @@ -1206,9 +1206,9 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nonnull defaultDuration MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull elapsedSlotTime MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull remainingSlotTime MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nonnull slotIsPauseable MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nonnull minPauseDuration MTR_PROVISIONALLY_AVAILABLE; -@property (nonatomic, copy) NSNumber * _Nonnull maxPauseDuration MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable slotIsPauseable MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable minPauseDuration MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nullable maxPauseDuration MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable manufacturerESAState MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable nominalPower MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nullable minPower MTR_PROVISIONALLY_AVAILABLE; @@ -1231,6 +1231,7 @@ MTR_PROVISIONALLY_AVAILABLE @property (nonatomic, copy) NSNumber * _Nullable latestEndTime MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSNumber * _Nonnull isPauseable MTR_PROVISIONALLY_AVAILABLE; @property (nonatomic, copy) NSArray * _Nonnull slots MTR_PROVISIONALLY_AVAILABLE; +@property (nonatomic, copy) NSNumber * _Nonnull forecastUpdateReason MTR_PROVISIONALLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE @@ -1274,6 +1275,7 @@ MTR_PROVISIONALLY_AVAILABLE MTR_PROVISIONALLY_AVAILABLE @interface MTRDeviceEnergyManagementClusterResumedEvent : NSObject +@property (nonatomic, copy) NSNumber * _Nonnull cause MTR_PROVISIONALLY_AVAILABLE; @end MTR_PROVISIONALLY_AVAILABLE diff --git a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm index 810e778412f5c8..22ee409b968bf3 100644 --- a/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm +++ b/src/darwin/Framework/CHIP/zap-generated/MTRStructsObjc.mm @@ -4887,11 +4887,11 @@ - (instancetype)init _remainingSlotTime = @(0); - _slotIsPauseable = @(0); + _slotIsPauseable = nil; - _minPauseDuration = @(0); + _minPauseDuration = nil; - _maxPauseDuration = @(0); + _maxPauseDuration = nil; _manufacturerESAState = nil; @@ -4970,6 +4970,8 @@ - (instancetype)init _isPauseable = @(0); _slots = [NSArray array]; + + _forecastUpdateReason = @(0); } return self; } @@ -4986,13 +4988,14 @@ - (id)copyWithZone:(NSZone * _Nullable)zone other.latestEndTime = self.latestEndTime; other.isPauseable = self.isPauseable; other.slots = self.slots; + other.forecastUpdateReason = self.forecastUpdateReason; return other; } - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: forecastId:%@; activeSlotNumber:%@; startTime:%@; endTime:%@; earliestStartTime:%@; latestEndTime:%@; isPauseable:%@; slots:%@; >", NSStringFromClass([self class]), _forecastId, _activeSlotNumber, _startTime, _endTime, _earliestStartTime, _latestEndTime, _isPauseable, _slots]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: forecastId:%@; activeSlotNumber:%@; startTime:%@; endTime:%@; earliestStartTime:%@; latestEndTime:%@; isPauseable:%@; slots:%@; forecastUpdateReason:%@; >", NSStringFromClass([self class]), _forecastId, _activeSlotNumber, _startTime, _endTime, _earliestStartTime, _latestEndTime, _isPauseable, _slots, _forecastUpdateReason]; return descriptionString; } @@ -5189,6 +5192,8 @@ @implementation MTRDeviceEnergyManagementClusterResumedEvent - (instancetype)init { if (self = [super init]) { + + _cause = @(0); } return self; } @@ -5197,12 +5202,14 @@ - (id)copyWithZone:(NSZone * _Nullable)zone { auto other = [[MTRDeviceEnergyManagementClusterResumedEvent alloc] init]; + other.cause = self.cause; + return other; } - (NSString *)description { - NSString * descriptionString = [NSString stringWithFormat:@"<%@: >", NSStringFromClass([self class])]; + NSString * descriptionString = [NSString stringWithFormat:@"<%@: cause:%@; >", NSStringFromClass([self class]), _cause]; return descriptionString; } diff --git a/src/include/platform/CHIPDeviceConfig.h b/src/include/platform/CHIPDeviceConfig.h index bafca37458c8a3..9734e4bfa28b35 100644 --- a/src/include/platform/CHIPDeviceConfig.h +++ b/src/include/platform/CHIPDeviceConfig.h @@ -844,6 +844,20 @@ #define CHIP_DEVICE_CONFIG_PAIRING_SECONDARY_INSTRUCTION "" #endif +/** + * CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_PASSCODE + * + * Enable or disable commissioner passcode feature. + * With this feature enabled, the commissioner can generate a commissioning passcode + * and display it to the user so that the user can enter it into a commissionable + * node, such as a phone app, during user directed commissioning. + * + * For Video Players, this value will often be 1 + */ +#ifndef CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_PASSCODE +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_PASSCODE 0 +#endif + // -------------------- Thread Configuration -------------------- /** diff --git a/src/lib/dnssd/Advertiser.h b/src/lib/dnssd/Advertiser.h index bfb587acec2ad7..0a98a90fa89a7e 100644 --- a/src/lib/dnssd/Advertiser.h +++ b/src/lib/dnssd/Advertiser.h @@ -263,6 +263,13 @@ class CommissionAdvertisingParameters : public BaseAdvertisingParams commissionerPasscodeSupported) + { + mCommissionerPasscodeSupported = commissionerPasscodeSupported; + return *this; + } + Optional GetCommissionerPasscodeSupported() const { return mCommissionerPasscodeSupported; } + private: uint8_t mShortDiscriminator = 0; uint16_t mLongDiscriminator = 0; // 12-bit according to spec @@ -281,6 +288,8 @@ class CommissionAdvertisingParameters : public BaseAdvertisingParams mCommissionerPasscodeSupported; }; /** diff --git a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp index 92499460b0db5c..a77abebab68a58 100644 --- a/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp +++ b/src/lib/dnssd/Advertiser_ImplMinimalMdns.cpp @@ -849,6 +849,10 @@ FullQName AdvertiserMinMdns::GetCommissioningTxtEntries(const CommissionAdvertis char txtRotatingDeviceId[chip::Dnssd::kKeyRotatingDeviceIdMaxLength + 4]; char txtPairingHint[chip::Dnssd::kKeyPairingInstructionMaxLength + 4]; char txtPairingInstr[chip::Dnssd::kKeyPairingInstructionMaxLength + 4]; + + // the following sub types only apply to commissioner discovery advertisements + char txtCommissionerPasscode[chip::Dnssd::kKeyCommissionerPasscodeMaxLength + 4]; + if (params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissionableNode) { // a discriminator always exists @@ -876,6 +880,14 @@ FullQName AdvertiserMinMdns::GetCommissioningTxtEntries(const CommissionAdvertis txtFields[numTxtFields++] = txtPairingInstr; } } + else + { + if (params.GetCommissionerPasscodeSupported().ValueOr(false)) + { + snprintf(txtCommissionerPasscode, sizeof(txtCommissionerPasscode), "CP=%d", static_cast(1)); + txtFields[numTxtFields++] = txtCommissionerPasscode; + } + } if (numTxtFields == 0) { return allocator->AllocateQNameFromArray(mEmptyTextEntries, 1); diff --git a/src/lib/dnssd/Discovery_ImplPlatform.cpp b/src/lib/dnssd/Discovery_ImplPlatform.cpp index 55debe8eb85e8b..240bb979991038 100644 --- a/src/lib/dnssd/Discovery_ImplPlatform.cpp +++ b/src/lib/dnssd/Discovery_ImplPlatform.cpp @@ -251,6 +251,9 @@ CHIP_ERROR CopyTxtRecord(TxtFieldKey key, char * buffer, size_t bufferLen, const return CopyTextRecordValue(buffer, bufferLen, params.GetPairingHint()); case TxtFieldKey::kCommissioningMode: return CopyTextRecordValue(buffer, bufferLen, params.GetCommissioningMode()); + case TxtFieldKey::kCommissionerPasscode: + return CopyTextRecordValue(buffer, bufferLen, + static_cast(params.GetCommissionerPasscodeSupported().ValueOr(false) ? 1 : 0)); default: return CopyTxtRecord(key, buffer, bufferLen, static_cast>(params)); } @@ -580,6 +583,7 @@ CHIP_ERROR DiscoveryImplPlatform::Advertise(const CommissionAdvertisingParameter if (params.GetCommissionAdvertiseMode() == CommssionAdvertiseMode::kCommissioner) { + ADD_TXT_RECORD(CommissionerPasscode); PUBLISH_RECORDS(Commissioner); return CHIP_NO_ERROR; } diff --git a/src/lib/dnssd/Resolver.h b/src/lib/dnssd/Resolver.h index ae4e95f4341b85..03e68e22df0c4a 100644 --- a/src/lib/dnssd/Resolver.h +++ b/src/lib/dnssd/Resolver.h @@ -177,6 +177,7 @@ struct CommissionNodeData size_t rotatingIdLen = 0; uint16_t pairingHint = 0; char pairingInstruction[kMaxPairingInstructionLen + 1] = {}; + uint8_t commissionerPasscode = 0; CommissionNodeData() {} @@ -230,6 +231,10 @@ struct CommissionNodeData ChipLogDetail(Discovery, "\tInstance Name: %s", instanceName); } ChipLogDetail(Discovery, "\tCommissioning Mode: %u", commissioningMode); + if (commissionerPasscode > 0) + { + ChipLogDetail(Discovery, "\tCommissioner Passcode: %u", commissionerPasscode); + } } }; diff --git a/src/lib/dnssd/TxtFields.cpp b/src/lib/dnssd/TxtFields.cpp index db11983ea869d7..d43650748e53a2 100644 --- a/src/lib/dnssd/TxtFields.cpp +++ b/src/lib/dnssd/TxtFields.cpp @@ -183,6 +183,11 @@ void GetPairingInstruction(const ByteSpan & value, char * pairingInstruction) Platform::CopyString(pairingInstruction, kMaxPairingInstructionLen + 1, value); } +uint8_t GetCommissionerPasscode(const ByteSpan & value) +{ + return MakeU8FromAsciiDecimal(value); +} + Optional GetRetryInterval(const ByteSpan & value) { const auto undefined = std::numeric_limits::max(); @@ -250,6 +255,9 @@ void FillNodeDataFromTxt(const ByteSpan & key, const ByteSpan & val, CommissionN case TxtFieldKey::kPairingHint: nodeData.pairingHint = Internal::GetPairingHint(val); break; + case TxtFieldKey::kCommissionerPasscode: + nodeData.commissionerPasscode = Internal::GetCommissionerPasscode(val); + break; default: break; } diff --git a/src/lib/dnssd/TxtFields.h b/src/lib/dnssd/TxtFields.h index 6e84fa372a8339..c3b8a0d668682c 100644 --- a/src/lib/dnssd/TxtFields.h +++ b/src/lib/dnssd/TxtFields.h @@ -39,14 +39,15 @@ static constexpr size_t kKeyTcpSupportedMaxLength = 1; static constexpr size_t kKeyLongIdleTimeICDMaxLength = 1; // Commissionable/commissioner node TXT entries -static constexpr size_t kKeyLongDiscriminatorMaxLength = 5; -static constexpr size_t kKeyVendorProductMaxLength = 11; -static constexpr size_t kKeyCommissioningModeMaxLength = 1; -static constexpr size_t kKeyDeviceTypeMaxLength = 10; -static constexpr size_t kKeyDeviceNameMaxLength = 32; -static constexpr size_t kKeyRotatingDeviceIdMaxLength = 100; -static constexpr size_t kKeyPairingInstructionMaxLength = 128; -static constexpr size_t kKeyPairingHintMaxLength = 10; +static constexpr size_t kKeyLongDiscriminatorMaxLength = 5; +static constexpr size_t kKeyVendorProductMaxLength = 11; +static constexpr size_t kKeyCommissioningModeMaxLength = 1; +static constexpr size_t kKeyDeviceTypeMaxLength = 10; +static constexpr size_t kKeyDeviceNameMaxLength = 32; +static constexpr size_t kKeyRotatingDeviceIdMaxLength = 100; +static constexpr size_t kKeyPairingInstructionMaxLength = 128; +static constexpr size_t kKeyPairingHintMaxLength = 10; +static constexpr size_t kKeyCommissionerPasscodeMaxLength = 1; enum class TxtKeyUse : uint8_t { @@ -66,6 +67,7 @@ enum class TxtFieldKey : uint8_t kRotatingDeviceId, kPairingInstruction, kPairingHint, + kCommissionerPasscode, kSessionIdleInterval, kSessionActiveInterval, kSessionActiveThreshold, @@ -93,6 +95,7 @@ constexpr const TxtFieldInfo txtFieldInfo[static_cast(TxtFieldKey::kCoun { TxtFieldKey::kRotatingDeviceId, kKeyRotatingDeviceIdMaxLength, "RI", TxtKeyUse::kCommission }, { TxtFieldKey::kPairingInstruction, kKeyPairingInstructionMaxLength, "PI", TxtKeyUse::kCommission }, { TxtFieldKey::kPairingHint, kKeyPairingHintMaxLength, "PH", TxtKeyUse::kCommission }, + { TxtFieldKey::kCommissionerPasscode, kKeyCommissionerPasscodeMaxLength, "CP", TxtKeyUse::kCommission }, { TxtFieldKey::kSessionIdleInterval, kKeySessionIdleIntervalMaxLength, "SII", TxtKeyUse::kCommon }, { TxtFieldKey::kSessionActiveInterval, kKeySessionActiveIntervalMaxLength, "SAI", TxtKeyUse::kCommon }, { TxtFieldKey::kSessionActiveThreshold, kKeySessionActiveThresholdMaxLength, "SAT", TxtKeyUse::kCommon }, @@ -112,6 +115,7 @@ void GetDeviceName(const ByteSpan & value, char * name); void GetRotatingDeviceId(const ByteSpan & value, uint8_t * rotatingId, size_t * len); uint16_t GetPairingHint(const ByteSpan & value); void GetPairingInstruction(const ByteSpan & value, char * pairingInstruction); +uint8_t GetCommissionerPasscode(const ByteSpan & value); #endif } // namespace Internal diff --git a/src/lib/dnssd/tests/TestTxtFields.cpp b/src/lib/dnssd/tests/TestTxtFields.cpp index 9c3f6bd08ae5ba..95f13b5d60c091 100644 --- a/src/lib/dnssd/tests/TestTxtFields.cpp +++ b/src/lib/dnssd/tests/TestTxtFields.cpp @@ -85,6 +85,9 @@ void TestGetTxtFieldKey(nlTestSuite * inSuite, void * inContext) strcpy(key, "XX"); NL_TEST_ASSERT(inSuite, GetTxtFieldKey(GetSpan(key)) == TxtFieldKey::kUnknown); + + strcpy(key, "CP"); + NL_TEST_ASSERT(inSuite, GetTxtFieldKey(GetSpan(key)) == TxtFieldKey::kCommissionerPasscode); } void TestGetTxtFieldKeyCaseInsensitive(nlTestSuite * inSuite, void * inContext) @@ -284,6 +287,20 @@ void TestGetPairingInstruction(nlTestSuite * inSuite, void * inContext) NL_TEST_ASSERT(inSuite, strcmp(ret, data) == 0); } +void TestGetCommissionerPasscode(nlTestSuite * inSuite, void * inContext) +{ + char cm[64]; + strcpy(cm, "0"); + NL_TEST_ASSERT(inSuite, GetCommissionerPasscode(GetSpan(cm)) == 0); + + strcpy(cm, "1"); + NL_TEST_ASSERT(inSuite, GetCommissionerPasscode(GetSpan(cm)) == 1); + + // overflow a uint8 + sprintf(cm, "%u", static_cast(std::numeric_limits::max()) + 1); + NL_TEST_ASSERT(inSuite, GetCommissionerPasscode(GetSpan(cm)) == 0); +} + bool NodeDataIsEmpty(const DiscoveredNodeData & node) { @@ -292,7 +309,7 @@ bool NodeDataIsEmpty(const DiscoveredNodeData & node) node.commissionData.rotatingIdLen != 0 || node.commissionData.pairingHint != 0 || node.resolutionData.mrpRetryIntervalIdle.HasValue() || node.resolutionData.mrpRetryIntervalActive.HasValue() || node.resolutionData.mrpRetryActiveThreshold.HasValue() || node.resolutionData.isICDOperatingAsLIT.HasValue() || - node.resolutionData.supportsTcp) + node.resolutionData.supportsTcp || node.commissionData.commissionerPasscode != 0) { return false; } @@ -343,6 +360,14 @@ void TestFillDiscoveredNodeDataFromTxt(nlTestSuite * inSuite, void * inContext) filled.commissionData.commissioningMode = 0; NL_TEST_ASSERT(inSuite, NodeDataIsEmpty(filled)); + // Commissioning mode + strcpy(key, "CP"); + strcpy(val, "1"); + FillNodeDataFromTxt(GetSpan(key), GetSpan(val), filled.commissionData); + NL_TEST_ASSERT(inSuite, filled.commissionData.commissionerPasscode == 1); + filled.commissionData.commissionerPasscode = 0; + NL_TEST_ASSERT(inSuite, NodeDataIsEmpty(filled)); + // Device type strcpy(key, "DT"); strcpy(val, "1"); @@ -744,6 +769,7 @@ const nlTest sTests[] = { NL_TEST_DEF("TxtFieldRotatingDeviceId", TestGetRotatingDeviceId), // NL_TEST_DEF("TxtFieldPairingHint", TestGetPairingHint), // NL_TEST_DEF("TxtFieldPairingInstruction", TestGetPairingInstruction), // + NL_TEST_DEF("TxtFieldCommissionerPasscode", TestGetCommissionerPasscode), // NL_TEST_DEF("TxtFieldFillDiscoveredNodeDataFromTxt", TestFillDiscoveredNodeDataFromTxt), // NL_TEST_DEF("TxtDiscoveredFieldMrpRetryIntervalIdle", TxtFieldSessionIdleInterval), NL_TEST_DEF("TxtDiscoveredFieldMrpRetryIntervalActive", TxtFieldSessionActiveInterval), diff --git a/src/lib/support/BUILD.gn b/src/lib/support/BUILD.gn index 861cd280cec0d7..b02e4905ff5817 100644 --- a/src/lib/support/BUILD.gn +++ b/src/lib/support/BUILD.gn @@ -196,6 +196,7 @@ static_library("support") { "PrivateHeap.cpp", "PrivateHeap.h", "ReferenceCountedHandle.h", + "Scoped.h", "SerializableIntegerSet.cpp", "SerializableIntegerSet.h", "SetupDiscriminator.h", diff --git a/src/lib/support/Scoped.h b/src/lib/support/Scoped.h new file mode 100644 index 00000000000000..67cc2ea9e96271 --- /dev/null +++ b/src/lib/support/Scoped.h @@ -0,0 +1,81 @@ +/* + * + * 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 + +namespace chip { + +template +class ScopedChange; + +/// Allows a value to only be changed within a scope. +/// +/// Generally used to force determinism for unit test execution. +/// +/// When a variable of this type is used, it should +/// only be changed via `ScopedChange`. +template +class ScopedChangeOnly +{ +public: + explicit ScopedChangeOnly(T initial) : mValue(initial) {} + operator T() const { return mValue; } + +private: + T mValue; + + // Expected to be used only by ScopedChange only + T & InternalMutableValue() { return mValue; } + friend class ScopedChange; +}; + +/// Allows a scoped mutation to occur on a variable. +/// +/// When an instance of this class goes out of scope, the variable +/// will be reset to the default. +/// +/// Example usage +/// +/// int a = 123; +/// ScopedChangeOnly b(234); +/// +/// /* a == 123, b == 234 */ +/// { +/// ScopedChange changeA(a, 321); +/// /* a == 321, b == 234 */ +/// { +/// ScopedChange changeB(b, 10); +/// /* a == 321, b == 10 */ +/// } +/// /* a == 321, b == 234 */ +/// } +/// /* a == 123, b == 234 */ +/// +template +class ScopedChange +{ +public: + ScopedChange(ScopedChangeOnly & what, T value) : mValue(what.InternalMutableValue()), mOriginal(what) { mValue = value; } + ScopedChange(T & what, T value) : mValue(what), mOriginal(what) { mValue = value; } + ~ScopedChange() { mValue = mOriginal; } + +private: + T & mValue; + T mOriginal; +}; + +} // namespace chip diff --git a/src/lib/support/tests/BUILD.gn b/src/lib/support/tests/BUILD.gn index ca647b3dad99cd..7a3b738ef4491a 100644 --- a/src/lib/support/tests/BUILD.gn +++ b/src/lib/support/tests/BUILD.gn @@ -44,6 +44,7 @@ chip_test_suite_using_nltest("tests") { "TestPrivateHeap.cpp", "TestSafeInt.cpp", "TestSafeString.cpp", + "TestScoped.cpp", "TestScopedBuffer.cpp", "TestSerializableIntegerSet.cpp", "TestSpan.cpp", diff --git a/src/lib/support/tests/TestScoped.cpp b/src/lib/support/tests/TestScoped.cpp new file mode 100644 index 00000000000000..90cdd62b0acf4a --- /dev/null +++ b/src/lib/support/tests/TestScoped.cpp @@ -0,0 +1,102 @@ +/* + * + * 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 +#include + +#include +#include + +namespace { + +using namespace chip; + +void TestScopedVariableChange(nlTestSuite * inSuite, void * inContext) +{ + int x = 123; + + { + ScopedChange change1(x, 10); + NL_TEST_ASSERT(inSuite, x == 10); + + x = 15; + { + ScopedChange change2(x, 20); + NL_TEST_ASSERT(inSuite, x == 20); + } + NL_TEST_ASSERT(inSuite, x == 15); + } + NL_TEST_ASSERT(inSuite, x == 123); +} + +void TestScopedChangeOnly(nlTestSuite * inSuite, void * inContext) +{ + ScopedChangeOnly intValue(123); + ScopedChangeOnly strValue("abc"); + + NL_TEST_ASSERT(inSuite, intValue == 123); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "abc") == 0); + + { + ScopedChange change1(intValue, 234); + + NL_TEST_ASSERT(inSuite, intValue == 234); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "abc") == 0); + + ScopedChange change2(strValue, "xyz"); + NL_TEST_ASSERT(inSuite, intValue == 234); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "xyz") == 0); + + { + ScopedChange change3(intValue, 10); + ScopedChange change4(strValue, "test"); + + NL_TEST_ASSERT(inSuite, intValue == 10); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "test") == 0); + } + + NL_TEST_ASSERT(inSuite, intValue == 234); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "xyz") == 0); + } + + NL_TEST_ASSERT(inSuite, intValue == 123); + NL_TEST_ASSERT(inSuite, strcmp(strValue, "abc") == 0); +} + +} // namespace + +#define NL_TEST_DEF_FN(fn) NL_TEST_DEF("Test " #fn, fn) +/** + * Test Suite. It lists all the test functions. + */ +static const nlTest sTests[] = { + NL_TEST_DEF_FN(TestScopedVariableChange), // + NL_TEST_DEF_FN(TestScopedChangeOnly), // + NL_TEST_SENTINEL() // +}; + +int TestScoped() +{ + nlTestSuite theSuite = { "CHIP Scoped tests", &sTests[0], nullptr, nullptr }; + + // Run test suite against one context. + nlTestRunner(&theSuite, nullptr); + return nlTestRunnerStats(&theSuite); +} + +CHIP_REGISTER_TEST_SUITE(TestScoped) diff --git a/src/platform/Linux/BLEManagerImpl.cpp b/src/platform/Linux/BLEManagerImpl.cpp index 10a17be7607735..e46e9c5d21edf2 100644 --- a/src/platform/Linux/BLEManagerImpl.cpp +++ b/src/platform/Linux/BLEManagerImpl.cpp @@ -776,11 +776,14 @@ void BLEManagerImpl::OnDeviceScanned(BluezDevice1 & device, const chip::Ble::Chi mBLEScanConfig.mBleScanState = BleScanState::kConnecting; chip::DeviceLayer::PlatformMgr().LockChipStack(); + // We StartScan in the ChipStack thread. + // StopScan should also be performed in the ChipStack thread. + // At the same time, the scan timer also needs to be canceled in the ChipStack thread. + mDeviceScanner.StopScan(); + // Stop scanning and then start connecting timer DeviceLayer::SystemLayer().StartTimer(kConnectTimeout, HandleConnectTimeout, &mEndpoint); chip::DeviceLayer::PlatformMgr().UnlockChipStack(); - mDeviceScanner.StopScan(); - mEndpoint.ConnectDevice(device); } diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.cpp b/src/platform/Linux/bluez/ChipDeviceScanner.cpp index 1670dfc082bebd..3a3115a9ae4783 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.cpp +++ b/src/platform/Linux/bluez/ChipDeviceScanner.cpp @@ -80,23 +80,17 @@ CHIP_ERROR ChipDeviceScanner::Init(BluezAdapter1 * adapter, ChipDeviceScannerDel }, this)); - mIsInitialized = true; + mScannerState = ChipDeviceScannerState::SCANNER_INITIALIZED; + return CHIP_NO_ERROR; } void ChipDeviceScanner::Shutdown() { - VerifyOrReturn(mIsInitialized); + VerifyOrReturn(mScannerState != ChipDeviceScannerState::SCANNER_UNINITIALIZED); StopScan(); - // mTimerExpired should only be set to true in the TimerExpiredCallback, which means we are in that callback - // right now so there is no need to cancel the timer. - if (!mTimerExpired) - { - chip::DeviceLayer::SystemLayer().CancelTimer(TimerExpiredCallback, this); - } - // Release resources on the glib thread. This is necessary because the D-Bus manager client // object handles D-Bus signals. Otherwise, we might face a race when the manager object is // released during a D-Bus signal being processed. @@ -112,29 +106,32 @@ void ChipDeviceScanner::Shutdown() }, this); - mIsInitialized = false; + mScannerState = ChipDeviceScannerState::SCANNER_UNINITIALIZED; } CHIP_ERROR ChipDeviceScanner::StartScan(System::Clock::Timeout timeout) { assertChipStackLockedByCurrentThread(); - VerifyOrReturnError(mIsInitialized, CHIP_ERROR_INCORRECT_STATE); - VerifyOrReturnError(!mIsScanning, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mScannerState != ChipDeviceScannerState::SCANNER_SCANNING, CHIP_ERROR_INCORRECT_STATE); + VerifyOrReturnError(mTimerState == ScannerTimerState::TIMER_CANCELED, CHIP_ERROR_INCORRECT_STATE); - mIsScanning = true; // optimistic, to allow all callbacks to check this if (PlatformMgrImpl().GLibMatterContextInvokeSync(MainLoopStartScan, this) != CHIP_NO_ERROR) { ChipLogError(Ble, "Failed to schedule BLE scan start."); - mIsScanning = false; - return CHIP_ERROR_INTERNAL; - } - if (!mIsScanning) - { - ChipLogError(Ble, "Failed to start BLE scan."); + ChipDeviceScannerDelegate * delegate = this->mDelegate; + // callback is explicitly allowed to delete the scanner (hence no more + // references to 'self' here) + delegate->OnScanComplete(); + return CHIP_ERROR_INTERNAL; } + // Here need to set the Bluetooth scanning status immediately. + // So that if the timer fails to start in the next step, + // calling StopScan will be effective. + mScannerState = ChipDeviceScannerState::SCANNER_SCANNING; + CHIP_ERROR err = chip::DeviceLayer::SystemLayer().StartTimer(timeout, TimerExpiredCallback, static_cast(this)); if (err != CHIP_NO_ERROR) @@ -143,7 +140,9 @@ CHIP_ERROR ChipDeviceScanner::StartScan(System::Clock::Timeout timeout) StopScan(); return err; } - mTimerExpired = false; + mTimerState = ScannerTimerState::TIMER_STARTED; + + ChipLogDetail(Ble, "ChipDeviceScanner has started scanning!"); return CHIP_NO_ERROR; } @@ -151,37 +150,35 @@ CHIP_ERROR ChipDeviceScanner::StartScan(System::Clock::Timeout timeout) void ChipDeviceScanner::TimerExpiredCallback(chip::System::Layer * layer, void * appState) { ChipDeviceScanner * chipDeviceScanner = static_cast(appState); - chipDeviceScanner->mTimerExpired = true; + chipDeviceScanner->mTimerState = ScannerTimerState::TIMER_EXPIRED; chipDeviceScanner->mDelegate->OnScanError(CHIP_ERROR_TIMEOUT); chipDeviceScanner->StopScan(); } CHIP_ERROR ChipDeviceScanner::StopScan() { - VerifyOrReturnError(mIsScanning, CHIP_NO_ERROR); - VerifyOrReturnError(!mIsStopping, CHIP_NO_ERROR); - - mIsStopping = true; - g_cancellable_cancel(mCancellable); // in case we are currently running a scan + assertChipStackLockedByCurrentThread(); + VerifyOrReturnError(mScannerState == ChipDeviceScannerState::SCANNER_SCANNING, CHIP_NO_ERROR); - if (mObjectAddedSignal) + if (PlatformMgrImpl().GLibMatterContextInvokeSync(MainLoopStopScan, this) != CHIP_NO_ERROR) { - g_signal_handler_disconnect(mManager, mObjectAddedSignal); - mObjectAddedSignal = 0; + ChipLogError(Ble, "Failed to schedule BLE scan stop."); + return CHIP_ERROR_INTERNAL; } - if (mInterfaceChangedSignal) - { - g_signal_handler_disconnect(mManager, mInterfaceChangedSignal); - mInterfaceChangedSignal = 0; - } + // Stop scanning and return to initialization state + mScannerState = ChipDeviceScannerState::SCANNER_INITIALIZED; - if (PlatformMgrImpl().GLibMatterContextInvokeSync(MainLoopStopScan, this) != CHIP_NO_ERROR) + ChipLogDetail(Ble, "ChipDeviceScanner has stopped scanning!"); + + if (mTimerState == ScannerTimerState::TIMER_STARTED) { - ChipLogError(Ble, "Failed to schedule BLE scan stop."); - return CHIP_ERROR_INTERNAL; + chip::DeviceLayer::SystemLayer().CancelTimer(TimerExpiredCallback, this); } + // Reset timer status + mTimerState = ScannerTimerState::TIMER_CANCELED; + ChipDeviceScannerDelegate * delegate = this->mDelegate; // callback is explicitly allowed to delete the scanner (hence no more // references to 'self' here) @@ -194,12 +191,26 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStopScan(ChipDeviceScanner * self) { GAutoPtr error; + g_cancellable_cancel(self->mCancellable); // in case we are currently running a scan + + if (self->mObjectAddedSignal) + { + g_signal_handler_disconnect(self->mManager, self->mObjectAddedSignal); + self->mObjectAddedSignal = 0; + } + + if (self->mInterfaceChangedSignal) + { + g_signal_handler_disconnect(self->mManager, self->mInterfaceChangedSignal); + self->mInterfaceChangedSignal = 0; + } + if (!bluez_adapter1_call_stop_discovery_sync(self->mAdapter, nullptr /* not cancellable */, &MakeUniquePointerReceiver(error).Get())) { ChipLogError(Ble, "Failed to stop discovery %s", error->message); + return CHIP_ERROR_INTERNAL; } - self->mIsScanning = false; return CHIP_NO_ERROR; } @@ -304,9 +315,7 @@ CHIP_ERROR ChipDeviceScanner::MainLoopStartScan(ChipDeviceScanner * self) if (!bluez_adapter1_call_start_discovery_sync(self->mAdapter, self->mCancellable, &MakeUniquePointerReceiver(error).Get())) { ChipLogError(Ble, "Failed to start discovery: %s", error->message); - - self->mIsScanning = false; - self->mDelegate->OnScanComplete(); + return CHIP_ERROR_INTERNAL; } return CHIP_NO_ERROR; diff --git a/src/platform/Linux/bluez/ChipDeviceScanner.h b/src/platform/Linux/bluez/ChipDeviceScanner.h index 16b8c91682650c..4785a737869dda 100644 --- a/src/platform/Linux/bluez/ChipDeviceScanner.h +++ b/src/platform/Linux/bluez/ChipDeviceScanner.h @@ -75,6 +75,20 @@ class ChipDeviceScanner CHIP_ERROR StopScan(); private: + enum ChipDeviceScannerState + { + SCANNER_UNINITIALIZED, + SCANNER_INITIALIZED, + SCANNER_SCANNING + }; + + enum ScannerTimerState + { + TIMER_CANCELED, + TIMER_STARTED, + TIMER_EXPIRED + }; + static void TimerExpiredCallback(chip::System::Layer * layer, void * appState); static CHIP_ERROR MainLoopStartScan(ChipDeviceScanner * self); static CHIP_ERROR MainLoopStopScan(ChipDeviceScanner * self); @@ -96,11 +110,9 @@ class ChipDeviceScanner ChipDeviceScannerDelegate * mDelegate = nullptr; gulong mObjectAddedSignal = 0; gulong mInterfaceChangedSignal = 0; - bool mIsInitialized = false; - bool mIsScanning = false; - bool mIsStopping = false; + ChipDeviceScannerState mScannerState = ChipDeviceScannerState::SCANNER_UNINITIALIZED; /// Used to track if timer has already expired and doesn't need to be canceled. - bool mTimerExpired = false; + ScannerTimerState mTimerState = ScannerTimerState::TIMER_CANCELED; }; } // namespace Internal diff --git a/src/protocols/secure_channel/CASEServer.cpp b/src/protocols/secure_channel/CASEServer.cpp index f8d580fdd9957b..d701d8c568c584 100644 --- a/src/protocols/secure_channel/CASEServer.cpp +++ b/src/protocols/secure_channel/CASEServer.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include using namespace ::chip::Inet; @@ -58,6 +59,7 @@ CHIP_ERROR CASEServer::ListenForSessionEstablishment(Messaging::ExchangeManager CHIP_ERROR CASEServer::InitCASEHandshake(Messaging::ExchangeContext * ec) { + MATTER_TRACE_SCOPE("InitCASEHandshake", "CASEServer"); ReturnErrorCodeIf(ec == nullptr, CHIP_ERROR_INVALID_ARGUMENT); // Hand over the exchange context to the CASE session. @@ -76,6 +78,7 @@ CHIP_ERROR CASEServer::OnUnsolicitedMessageReceived(const PayloadHeader & payloa CHIP_ERROR CASEServer::OnMessageReceived(Messaging::ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && payload) { + MATTER_TRACE_SCOPE("OnMessageReceived", "CASEServer"); if (GetSession().GetState() != CASESession::State::kInitialized) { // We are in the middle of CASE handshake @@ -177,6 +180,7 @@ void CASEServer::PrepareForSessionEstablishment(const ScopedNodeId & previouslyE void CASEServer::OnSessionEstablishmentError(CHIP_ERROR err) { + MATTER_TRACE_SCOPE("OnSessionEstablishmentError", "CASEServer"); ChipLogError(Inet, "CASE Session establishment failed: %" CHIP_ERROR_FORMAT, err.Format()); PrepareForSessionEstablishment(); @@ -184,6 +188,7 @@ void CASEServer::OnSessionEstablishmentError(CHIP_ERROR err) void CASEServer::OnSessionEstablished(const SessionHandle & session) { + MATTER_TRACE_SCOPE("OnSessionEstablished", "CASEServer"); ChipLogProgress(Inet, "CASE Session established to peer: " ChipLogFormatScopedNodeId, ChipLogValueScopedNodeId(session->GetPeer())); PrepareForSessionEstablishment(session->GetPeer()); @@ -191,6 +196,7 @@ void CASEServer::OnSessionEstablished(const SessionHandle & session) CHIP_ERROR CASEServer::SendBusyStatusReport(Messaging::ExchangeContext * ec, System::Clock::Milliseconds16 minimumWaitTime) { + MATTER_TRACE_SCOPE("SendBusyStatusReport", "CASEServer"); ChipLogProgress(Inet, "Already in the middle of CASE handshake, sending busy status report"); System::PacketBufferHandle handle = Protocols::SecureChannel::StatusReport::MakeBusyStatusReportMessage(minimumWaitTime); diff --git a/src/protocols/secure_channel/CASESession.cpp b/src/protocols/secure_channel/CASESession.cpp index 296ba0848150c7..8573d1565686fe 100644 --- a/src/protocols/secure_channel/CASESession.cpp +++ b/src/protocols/secure_channel/CASESession.cpp @@ -386,6 +386,7 @@ void CASESession::OnSessionReleased() void CASESession::Clear() { + MATTER_TRACE_SCOPE("Clear", "CASESession"); // Cancel any outstanding work. if (mSendSigma3Helper) { @@ -436,6 +437,7 @@ void CASESession::InvalidateIfPendingEstablishmentOnFabric(FabricIndex fabricInd CHIP_ERROR CASESession::Init(SessionManager & sessionManager, Credentials::CertificateValidityPolicy * policy, SessionEstablishmentDelegate * delegate, const ScopedNodeId & sessionEvictionHint) { + MATTER_TRACE_SCOPE("Init", "CASESession"); VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(mGroupDataProvider != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(sessionManager.GetSessionKeystore() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -462,6 +464,7 @@ CASESession::PrepareForSessionEstablishment(SessionManager & sessionManager, Fab SessionEstablishmentDelegate * delegate, const ScopedNodeId & previouslyEstablishedPeer, Optional mrpLocalConfig) { + MATTER_TRACE_SCOPE("PrepareForSessionEstablishment", "CASESession"); // Below VerifyOrReturnError is not SuccessOrExit since we only want to goto `exit:` after // Init has been successfully called. VerifyOrReturnError(fabricTable != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -544,6 +547,7 @@ CHIP_ERROR CASESession::EstablishSession(SessionManager & sessionManager, Fabric void CASESession::OnResponseTimeout(ExchangeContext * ec) { + MATTER_TRACE_SCOPE("OnResponseTimeout", "CASESession"); VerifyOrReturn(ec != nullptr, ChipLogError(SecureChannel, "CASESession::OnResponseTimeout was called by null exchange")); VerifyOrReturn(mExchangeCtxt == ec, ChipLogError(SecureChannel, "CASESession::OnResponseTimeout exchange doesn't match")); ChipLogError(SecureChannel, "CASESession timed out while waiting for a response from the peer. Current state was %u", @@ -556,6 +560,7 @@ void CASESession::OnResponseTimeout(ExchangeContext * ec) void CASESession::AbortPendingEstablish(CHIP_ERROR err) { + MATTER_TRACE_SCOPE("AbortPendingEstablish", "CASESession"); // This needs to come before Clear() which will reset mState. SessionEstablishmentStage state = MapCASEStateToSessionEstablishmentStage(mState); Clear(); @@ -751,6 +756,7 @@ CHIP_ERROR CASESession::HandleSigma1_and_SendSigma2(System::PacketBufferHandle & CHIP_ERROR CASESession::FindLocalNodeFromDestinationId(const ByteSpan & destinationId, const ByteSpan & initiatorRandom) { + MATTER_TRACE_SCOPE("FindLocalNodeFromDestinationId", "CASESession"); VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); bool found = false; @@ -805,6 +811,7 @@ CHIP_ERROR CASESession::FindLocalNodeFromDestinationId(const ByteSpan & destinat CHIP_ERROR CASESession::TryResumeSession(SessionResumptionStorage::ConstResumptionIdView resumptionId, ByteSpan resume1MIC, ByteSpan initiatorRandom) { + MATTER_TRACE_SCOPE("TryResumeSession", "CASESession"); VerifyOrReturnError(mSessionResumptionStorage != nullptr, CHIP_ERROR_INCORRECT_STATE); VerifyOrReturnError(mFabricsTable != nullptr, CHIP_ERROR_INCORRECT_STATE); @@ -2095,6 +2102,7 @@ CHIP_ERROR CASESession::ValidateReceivedMessage(ExchangeContext * ec, const Payl CHIP_ERROR CASESession::OnMessageReceived(ExchangeContext * ec, const PayloadHeader & payloadHeader, System::PacketBufferHandle && msg) { + MATTER_TRACE_SCOPE("OnMessageReceived", "CASESession"); CHIP_ERROR err = ValidateReceivedMessage(ec, payloadHeader, msg); Protocols::SecureChannel::MsgType msgType = static_cast(payloadHeader.GetMessageType()); SuccessOrExit(err); diff --git a/src/protocols/secure_channel/PASESession.cpp b/src/protocols/secure_channel/PASESession.cpp index da168fa7c79c95..67da1d103ebf83 100644 --- a/src/protocols/secure_channel/PASESession.cpp +++ b/src/protocols/secure_channel/PASESession.cpp @@ -89,6 +89,7 @@ void PASESession::Finish() void PASESession::Clear() { + MATTER_TRACE_SCOPE("Clear", "PASESession"); // This function zeroes out and resets the memory used by the object. // It's done so that no security related information will be leaked. memset(&mPASEVerifier, 0, sizeof(mPASEVerifier)); @@ -112,6 +113,7 @@ void PASESession::Clear() CHIP_ERROR PASESession::Init(SessionManager & sessionManager, uint32_t setupCode, SessionEstablishmentDelegate * delegate) { + MATTER_TRACE_SCOPE("Init", "PASESession"); VerifyOrReturnError(sessionManager.GetSessionKeystore() != nullptr, CHIP_ERROR_INVALID_ARGUMENT); VerifyOrReturnError(delegate != nullptr, CHIP_ERROR_INVALID_ARGUMENT); @@ -242,6 +244,7 @@ CHIP_ERROR PASESession::Pair(SessionManager & sessionManager, uint32_t peerSetUp void PASESession::OnResponseTimeout(ExchangeContext * ec) { + MATTER_TRACE_SCOPE("OnResponseTimeout", "PASESession"); VerifyOrReturn(ec != nullptr, ChipLogError(SecureChannel, "PASESession::OnResponseTimeout was called by null exchange")); VerifyOrReturn(mExchangeCtxt == nullptr || mExchangeCtxt == ec, ChipLogError(SecureChannel, "PASESession::OnResponseTimeout exchange doesn't match")); @@ -691,7 +694,6 @@ CHIP_ERROR PASESession::HandleMsg2_and_SendMsg3(System::PacketBufferHandle && ms mNextExpectedMsg.SetValue(MsgType::StatusReport); } - ChipLogDetail(SecureChannel, "Sent spake2p msg3"); exit: @@ -814,6 +816,7 @@ CHIP_ERROR PASESession::OnUnsolicitedMessageReceived(const PayloadHeader & paylo CHIP_ERROR PASESession::OnMessageReceived(ExchangeContext * exchange, const PayloadHeader & payloadHeader, System::PacketBufferHandle && msg) { + MATTER_TRACE_SCOPE("OnMessageReceived", "PASESession"); CHIP_ERROR err = ValidateReceivedMessage(exchange, payloadHeader, msg); MsgType msgType = static_cast(payloadHeader.GetMessageType()); SuccessOrExit(err); diff --git a/src/protocols/user_directed_commissioning/UDCClientState.h b/src/protocols/user_directed_commissioning/UDCClientState.h index 944a1e156ad9f2..587b1e3ff2b64c 100644 --- a/src/protocols/user_directed_commissioning/UDCClientState.h +++ b/src/protocols/user_directed_commissioning/UDCClientState.h @@ -118,7 +118,7 @@ class UDCClientState } return false; } - size_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; } + uint8_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; } bool AddTargetAppInfo(TargetAppInfo vid) { @@ -160,27 +160,31 @@ class UDCClientState void SetCancelPasscode(bool newValue) { mCancelPasscode = newValue; }; bool GetCancelPasscode() const { return mCancelPasscode; }; + void SetCachedCommissionerPasscode(uint32_t newValue) { mCachedCommissionerPasscode = newValue; }; + uint32_t GetCachedCommissionerPasscode() const { return mCachedCommissionerPasscode; }; + /** * Reset the connection state to a completely uninitialized status. */ void Reset() { - mPeerAddress = PeerAddress::Uninitialized(); - mLongDiscriminator = 0; - mVendorId = 0; - mProductId = 0; - mRotatingIdLen = 0; - mCdPort = 0; - mDeviceName[0] = '\0'; - mPairingInst[0] = '\0'; - mPairingHint = 0; - mNoPasscode = false; - mCdUponPasscodeDialog = false; - mCommissionerPasscode = false; - mCommissionerPasscodeReady = false; - mCancelPasscode = false; - mExpirationTime = System::Clock::kZero; - mUDCClientProcessingState = UDCClientProcessingState::kNotInitialized; + mPeerAddress = PeerAddress::Uninitialized(); + mLongDiscriminator = 0; + mVendorId = 0; + mProductId = 0; + mRotatingIdLen = 0; + mCdPort = 0; + mDeviceName[0] = '\0'; + mPairingInst[0] = '\0'; + mPairingHint = 0; + mNoPasscode = false; + mCdUponPasscodeDialog = false; + mCommissionerPasscode = false; + mCommissionerPasscodeReady = false; + mCancelPasscode = false; + mExpirationTime = System::Clock::kZero; + mUDCClientProcessingState = UDCClientProcessingState::kNotInitialized; + mCachedCommissionerPasscode = 0; } private: @@ -208,6 +212,8 @@ class UDCClientState UDCClientProcessingState mUDCClientProcessingState; System::Clock::Timestamp mExpirationTime = System::Clock::kZero; + + uint32_t mCachedCommissionerPasscode = 0; }; } // namespace UserDirectedCommissioning diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h index d05a80a857f200..b4b7e90a085611 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioning.h @@ -115,7 +115,7 @@ class DLL_EXPORT IdentificationDeclaration } return false; } - size_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; } + uint8_t GetNumTargetAppInfos() const { return mNumTargetAppInfos; } bool AddTargetAppInfo(TargetAppInfo vid) { @@ -246,7 +246,7 @@ class DLL_EXPORT IdentificationDeclaration } if (mCommissionerPasscodeReady) { - ChipLogDetail(AppServer, "\ttcommissioner passcode ready: true"); + ChipLogDetail(AppServer, "\tcommissioner passcode ready: true"); } if (mCancelPasscode) { @@ -328,7 +328,9 @@ class DLL_EXPORT CommissionerDeclaration kAppInstallConsentPending = 13, kAppInstalling = 14, kAppInstallFailed = 15, - kAppInstalledRetryNeeded = 16 + kAppInstalledRetryNeeded = 16, + kCommissionerPasscodeDisabled = 17, + kUnexpectedCommissionerPasscodeReady = 18 }; constexpr static size_t kUdcTLVDataMaxBytes = 500; diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp index 1d93ae5bb1d75e..3bb69c099612e3 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningClient.cpp @@ -132,27 +132,30 @@ uint32_t IdentificationDeclaration::WritePayload(uint8_t * payloadBuffer, size_t (err = writer.PutBytes(chip::TLV::ContextTag(kRotatingIdTag), mRotatingId, static_cast(mRotatingIdLen))), LogErrorOnFailure(err)); - // AppVendorIdList - VerifyOrExit( - CHIP_NO_ERROR == - (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppListTag), chip::TLV::kTLVType_List, listContainerType)), - LogErrorOnFailure(err)); - for (size_t i = 0; i < mNumTargetAppInfos; i++) + if (mNumTargetAppInfos > 0) { - // start the TargetApp structure + // AppVendorIdList VerifyOrExit(CHIP_NO_ERROR == - (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppTag), chip::TLV::kTLVType_Structure, - outerContainerType)), - LogErrorOnFailure(err)); - // add the vendor Id - VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppVendorIdTag), mTargetAppInfos[i].vendorId)), + (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppListTag), chip::TLV::kTLVType_List, + listContainerType)), LogErrorOnFailure(err)); - VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppProductIdTag), mTargetAppInfos[i].productId)), - LogErrorOnFailure(err)); - // end the TargetApp structure - VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err)); + for (size_t i = 0; i < mNumTargetAppInfos; i++) + { + // start the TargetApp structure + VerifyOrExit(CHIP_NO_ERROR == + (err = writer.StartContainer(chip::TLV::ContextTag(kTargetAppTag), chip::TLV::kTLVType_Structure, + outerContainerType)), + LogErrorOnFailure(err)); + // add the vendor Id + VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppVendorIdTag), mTargetAppInfos[i].vendorId)), + LogErrorOnFailure(err)); + VerifyOrExit(CHIP_NO_ERROR == (err = writer.Put(chip::TLV::ContextTag(kAppProductIdTag), mTargetAppInfos[i].productId)), + LogErrorOnFailure(err)); + // end the TargetApp structure + VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err)); + } + VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(listContainerType)), LogErrorOnFailure(err)); } - VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(listContainerType)), LogErrorOnFailure(err)); VerifyOrExit(CHIP_NO_ERROR == (err = writer.PutBoolean(chip::TLV::ContextTag(kNoPasscodeTag), mNoPasscode)), LogErrorOnFailure(err)); @@ -169,9 +172,10 @@ uint32_t IdentificationDeclaration::WritePayload(uint8_t * payloadBuffer, size_t VerifyOrExit(CHIP_NO_ERROR == (err = writer.EndContainer(outerContainerType)), LogErrorOnFailure(err)); VerifyOrExit(CHIP_NO_ERROR == (err = writer.Finalize()), LogErrorOnFailure(err)); - return writer.GetLengthWritten(); + return writer.GetLengthWritten() + static_cast(sizeof(mInstanceName)); exit: + ChipLogError(AppServer, "IdentificationDeclaration::WritePayload exiting early error %" CHIP_ERROR_FORMAT, err.Format()); return 0; } diff --git a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp index 1a2f125ae5d282..746df853436877 100644 --- a/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp +++ b/src/protocols/user_directed_commissioning/UserDirectedCommissioningServer.cpp @@ -327,6 +327,10 @@ CHIP_ERROR IdentificationDeclaration::ReadPayload(uint8_t * udcPayload, size_t p err = reader.Get(mCancelPasscode); break; } + if (err != CHIP_NO_ERROR) + { + ChipLogError(AppServer, "IdentificationDeclaration::ReadPayload read error %" CHIP_ERROR_FORMAT, err.Format()); + } } if (err == CHIP_END_OF_TLV) @@ -334,6 +338,10 @@ CHIP_ERROR IdentificationDeclaration::ReadPayload(uint8_t * udcPayload, size_t p // Exiting container ReturnErrorOnFailure(reader.ExitContainer(outerContainerType)); } + else + { + ChipLogError(AppServer, "IdentificationDeclaration::ReadPayload exiting early error %" CHIP_ERROR_FORMAT, err.Format()); + } ChipLogProgress(AppServer, "UDC TLV parse complete"); return CHIP_NO_ERROR; diff --git a/src/python_testing/TC_AccessChecker.py b/src/python_testing/TC_AccessChecker.py index 4c6636a29b6611..5533b0e3d91b4d 100644 --- a/src/python_testing/TC_AccessChecker.py +++ b/src/python_testing/TC_AccessChecker.py @@ -137,20 +137,35 @@ async def _run_read_access_test_for_cluster_privilege(self, endpoint_id, cluster async def _run_write_access_test_for_cluster_privilege(self, endpoint_id, cluster_id, cluster, xml_cluster: XmlCluster, privilege: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum, wildcard_read): for attribute_id in checkable_attributes(cluster_id, cluster, xml_cluster): spec_requires = xml_cluster.attributes[attribute_id].write_access - if spec_requires == Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue: - # not writeable - continue + is_optional_write = xml_cluster.attributes[attribute_id].write_optional + attribute = Clusters.ClusterObjects.ALL_ATTRIBUTES[cluster_id][attribute_id] cluster_class = Clusters.ClusterObjects.ALL_CLUSTERS[cluster_id] location = AttributePathLocation(endpoint_id=endpoint_id, cluster_id=cluster_id, attribute_id=attribute_id) test_name = f'Write access checker - {privilege}' + logging.info(f"Testing attribute {attribute} on endpoint {endpoint_id}") + if attribute == Clusters.AccessControl.Attributes.Acl and privilege == Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister: + logging.info("Skipping ACL attribute check for admin privilege as this is known to be writeable and is being used for this test") + continue - print(f"Testing attribute {attribute} on endpoint {endpoint_id}") # Because we read everything with admin, we should have this in the wildcard read # This will only not work if we end up with write-only attributes. We do not currently have any of these. val = wildcard_read.attributes[endpoint_id][cluster_class][attribute] + if isinstance(val, list): + # Use an empty list for writes in case the list is large and does not fit + val = [] + resp = await self.TH2.WriteAttribute(nodeid=self.dut_node_id, attributes=[(endpoint_id, attribute(val))]) - if operation_allowed(spec_requires, privilege): + if spec_requires == Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue: + # not writeable - expect an unsupported write response + if resp[0].Status != Status.UnsupportedWrite: + self.record_error(test_name=test_name, location=location, + problem=f"Unexpected error writing non-writeable attribute - expected Unsupported Write, got {resp[0].Status}") + self.success = False + elif is_optional_write and resp[0].Status == Status.UnsupportedWrite: + # unsupported optional writeable attribute - this is fine, no error + continue + elif operation_allowed(spec_requires, privilege): # Write the default attribute. We don't care if this fails, as long as it fails with a DIFFERENT error than the access # This is OK because access is required to be checked BEFORE any other thing to avoid leaking device information. # For example, because we don't have any range information, we might be writing an out of range value, but this will @@ -166,13 +181,19 @@ async def _run_write_access_test_for_cluster_privilege(self, endpoint_id, cluste problem=f"Unexpected error writing attribute - expected Unsupported Access, got {resp[0].Status}") self.success = False + if resp[0].Status == Status.Success and isinstance(val, list): + # Reset the value to the original if we managed to write an empty list + val = wildcard_read.attributes[endpoint_id][cluster_class][attribute] + await self.TH2.WriteAttribute(nodeid=self.dut_node_id, attributes=[(endpoint_id, attribute(val))]) + async def run_access_test(self, test_type: AccessTestType): # Read all the attributes on TH2 using admin access if test_type == AccessTestType.WRITE: await self._setup_acl(privilege=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kAdminister) wildcard_read = await self.TH2.Read(self.dut_node_id, [()]) - privilege_enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum + enum = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum + privilege_enum = [p for p in enum if p != enum.kUnknownEnumValue] for privilege in privilege_enum: logging.info(f"Testing for {privilege}") await self._setup_acl(privilege=privilege) diff --git a/src/python_testing/TestSpecParsingSupport.py b/src/python_testing/TestSpecParsingSupport.py index d77d634d14312d..ed790fb4bf4629 100644 --- a/src/python_testing/TestSpecParsingSupport.py +++ b/src/python_testing/TestSpecParsingSupport.py @@ -32,7 +32,7 @@ ATTRIBUTE_ID = 0x0000 -def single_attribute_cluster_xml(read_access: str, write_access: str): +def single_attribute_cluster_xml(read_access: str, write_access: str, write_supported: str): xml_cluster = f'' revision_table = ('' '' @@ -41,7 +41,7 @@ def single_attribute_cluster_xml(read_access: str, write_access: str): '') classification = '' read_access_str = f'read="true" readPrivilege="{read_access}"' if read_access is not None else "" - write_access_str = f'write="true" writePrivilege="{write_access}"' if write_access is not None else "" + write_access_str = f'write="{write_supported}" writePrivilege="{write_access}"' if write_access is not None else "" attribute = ('' f'' f'' @@ -82,7 +82,7 @@ def test_spec_parsing_access(self): strs = [None, 'view', 'operate', 'manage', 'admin'] for read in strs: for write in strs: - xml = single_attribute_cluster_xml(read, write) + xml = single_attribute_cluster_xml(read, write, "true") xml_cluster = parse_cluster(xml) asserts.assert_is_not_none(xml_cluster.attributes, "No attributes found in cluster") asserts.assert_is_not_none(xml_cluster.attribute_map, "No attribute map found in cluster") @@ -94,6 +94,18 @@ def test_spec_parsing_access(self): asserts.assert_equal(xml_cluster.attributes[ATTRIBUTE_ID].write_access, get_access_enum_from_string(write), "Unexpected write access") + def test_write_optional(self): + for write_support in ['true', 'optional']: + xml = single_attribute_cluster_xml('view', 'view', write_support) + xml_cluster = parse_cluster(xml) + asserts.assert_is_not_none(xml_cluster.attributes, "No attributes found in cluster") + asserts.assert_is_not_none(xml_cluster.attribute_map, "No attribute map found in cluster") + asserts.assert_equal(len(xml_cluster.attributes), len(GlobalAttributeIds) + 1, "Unexpected number of attributes") + asserts.assert_true(ATTRIBUTE_ID in xml_cluster.attributes.keys(), + "Did not find test attribute in XmlCluster.attributes") + asserts.assert_equal(xml_cluster.attributes[ATTRIBUTE_ID].write_optional, + write_support == 'optional', "Unexpected write_optional value") + if __name__ == "__main__": default_matter_test_main() diff --git a/src/python_testing/spec_parsing_support.py b/src/python_testing/spec_parsing_support.py index 77183a1b464f88..c58f38e9a5ac89 100644 --- a/src/python_testing/spec_parsing_support.py +++ b/src/python_testing/spec_parsing_support.py @@ -61,6 +61,7 @@ class XmlAttribute: conformance: Callable[[uint], ConformanceDecision] read_access: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum write_access: Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum + write_optional: bool def access_string(self): read_marker = "R" if self.read_access is not Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue else "" @@ -228,6 +229,9 @@ def parse_conformance(self, conformance_xml: ElementTree.Element) -> Callable: severity=ProblemSeverity.WARNING, problem=str(ex))) return None + def parse_write_optional(self, element_xml: ElementTree.Element, access_xml: ElementTree.Element) -> bool: + return access_xml.attrib['write'] == 'optional' + def parse_access(self, element_xml: ElementTree.Element, access_xml: ElementTree.Element, conformance: Callable) -> tuple[Optional[Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum], Optional[Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum], Optional[Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum]]: ''' Returns a tuple of access types for read / write / invoke''' def str_to_access_type(privilege_str: str) -> Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum: @@ -301,13 +305,16 @@ def parse_attributes(self) -> dict[uint, XmlAttribute]: # I don't have a good way to relate the ranges to the conformance, but they're both acceptable, so let's just or them. conformance = or_operation([conformance, attributes[code].conformance]) read_access, write_access, _ = self.parse_access(element, access_xml, conformance) + write_optional = False + if write_access not in [None, Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue]: + write_optional = self.parse_write_optional(element, access_xml) attributes[code] = XmlAttribute(name=element.attrib['name'], datatype=datatype, - conformance=conformance, read_access=read_access, write_access=write_access) + conformance=conformance, read_access=read_access, write_access=write_access, write_optional=write_optional) # Add in the global attributes for the base class for id in GlobalAttributeIds: # TODO: Add data type here. Right now it's unused. We should parse this from the spec. attributes[id] = XmlAttribute(name=id.to_name(), datatype="", conformance=mandatory( - ), read_access=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, write_access=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue) + ), read_access=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView, write_access=Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue, write_optional=False) return attributes def parse_commands(self, command_type: CommandType) -> dict[uint, XmlAttribute]: @@ -508,12 +515,12 @@ def remove_problem(location: typing.Union[CommandPathLocation, FeaturePathLocati view = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kView none = Clusters.AccessControl.Enums.AccessControlEntryPrivilegeEnum.kUnknownEnumValue clusters[temp_control_id].attributes = { - 0x00: XmlAttribute(name='TemperatureSetpoint', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none), - 0x01: XmlAttribute(name='MinTemperature', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none), - 0x02: XmlAttribute(name='MaxTemperature', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none), - 0x03: XmlAttribute(name='Step', datatype='temperature', conformance=feature(0x04, 'STEP'), read_access=view, write_access=none), - 0x04: XmlAttribute(name='SelectedTemperatureLevel', datatype='uint8', conformance=feature(0x02, 'TL'), read_access=view, write_access=none), - 0x05: XmlAttribute(name='SupportedTemperatureLevels', datatype='list', conformance=feature(0x02, 'TL'), read_access=view, write_access=none), + 0x00: XmlAttribute(name='TemperatureSetpoint', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none, write_optional=False), + 0x01: XmlAttribute(name='MinTemperature', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none, write_optional=False), + 0x02: XmlAttribute(name='MaxTemperature', datatype='temperature', conformance=feature(0x01, 'TN'), read_access=view, write_access=none, write_optional=False), + 0x03: XmlAttribute(name='Step', datatype='temperature', conformance=feature(0x04, 'STEP'), read_access=view, write_access=none, write_optional=False), + 0x04: XmlAttribute(name='SelectedTemperatureLevel', datatype='uint8', conformance=feature(0x02, 'TL'), read_access=view, write_access=none, write_optional=False), + 0x05: XmlAttribute(name='SupportedTemperatureLevels', datatype='list', conformance=feature(0x02, 'TL'), read_access=view, write_access=none, write_optional=False), } # Workaround for incorrect parsing of access control cluster. diff --git a/src/tracing/esp32_trace/esp32_tracing.cpp b/src/tracing/esp32_trace/esp32_tracing.cpp index 24a7166dde04eb..7a1313089703f2 100644 --- a/src/tracing/esp32_trace/esp32_tracing.cpp +++ b/src/tracing/esp32_trace/esp32_tracing.cpp @@ -29,7 +29,7 @@ namespace Tracing { namespace Insights { namespace { -constexpr size_t kPermitListMaxSize = 10; +constexpr size_t kPermitListMaxSize = 20; using HashValue = uint32_t; // Implements a murmurhash with 0 seed. @@ -66,13 +66,13 @@ uint32_t MurmurHash(const void * key) * are well known permitted entries. */ -HashValue gPermitList[kPermitListMaxSize] = { - MurmurHash("PASESession"), - MurmurHash("CASESession"), - MurmurHash("NetworkCommissioning"), - MurmurHash("GeneralCommissioning"), - MurmurHash("OperationalCredentials"), -}; +HashValue gPermitList[kPermitListMaxSize] = { MurmurHash("PASESession"), + MurmurHash("CASESession"), + MurmurHash("NetworkCommissioning"), + MurmurHash("GeneralCommissioning"), + MurmurHash("OperationalCredentials"), + MurmurHash("CASEServer"), + MurmurHash("Fabric") }; // namespace bool IsPermitted(HashValue hashValue) { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h index fa83804118b175..97ea4eeb3ce0ac 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums-check.h @@ -1641,6 +1641,18 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(DemandResponseLoadContr } } +static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::AdjustmentCauseEnum val) +{ + using EnumType = DeviceEnergyManagement::AdjustmentCauseEnum; + switch (val) + { + case EnumType::kLocalOptimization: + case EnumType::kGridOptimization: + return val; + default: + return static_cast(2); + } +} static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::CauseEnum val) { using EnumType = DeviceEnergyManagement::CauseEnum; @@ -1650,9 +1662,10 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement: case EnumType::kOffline: case EnumType::kFault: case EnumType::kUserOptOut: + case EnumType::kCancelled: return val; default: - return static_cast(4); + return static_cast(5); } } static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::CostTypeEnum val) @@ -1677,12 +1690,11 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement: case EnumType::kOffline: case EnumType::kOnline: case EnumType::kFault: - case EnumType::kUserOptOut: case EnumType::kPowerAdjustActive: case EnumType::kPaused: return val; default: - return static_cast(6); + return static_cast(5); } } static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::ESATypeEnum val) @@ -1710,6 +1722,33 @@ static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement: return static_cast(14); } } +static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::ForecastUpdateReasonEnum val) +{ + using EnumType = DeviceEnergyManagement::ForecastUpdateReasonEnum; + switch (val) + { + case EnumType::kInternalOptimization: + case EnumType::kLocalOptimization: + case EnumType::kGridOptimization: + return val; + default: + return static_cast(3); + } +} +static auto __attribute__((unused)) EnsureKnownEnumValue(DeviceEnergyManagement::OptOutStateEnum val) +{ + using EnumType = DeviceEnergyManagement::OptOutStateEnum; + switch (val) + { + case EnumType::kNoOptOut: + case EnumType::kLocalOptOut: + case EnumType::kGridOptOut: + case EnumType::kOptOut: + return val; + default: + return static_cast(4); + } +} static auto __attribute__((unused)) EnsureKnownEnumValue(EnergyEvse::EnergyTransferStoppedReasonEnum val) { diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h index 49b66ec661f0eb..4dd5c7f4db2735 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-enums.h @@ -2380,6 +2380,18 @@ enum class Feature : uint32_t namespace DeviceEnergyManagement { +// Enum for AdjustmentCauseEnum +enum class AdjustmentCauseEnum : uint8_t +{ + kLocalOptimization = 0x00, + kGridOptimization = 0x01, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 2, +}; + // Enum for CauseEnum enum class CauseEnum : uint8_t { @@ -2387,11 +2399,12 @@ enum class CauseEnum : uint8_t kOffline = 0x01, kFault = 0x02, kUserOptOut = 0x03, + kCancelled = 0x04, // All received enum values that are not listed above will be mapped // to kUnknownEnumValue. This is a helper enum value that should only // be used by code to process how it handles receiving and unknown // enum value. This specific should never be transmitted. - kUnknownEnumValue = 4, + kUnknownEnumValue = 5, }; // Enum for CostTypeEnum @@ -2414,14 +2427,13 @@ enum class ESAStateEnum : uint8_t kOffline = 0x00, kOnline = 0x01, kFault = 0x02, - kUserOptOut = 0x03, - kPowerAdjustActive = 0x04, - kPaused = 0x05, + kPowerAdjustActive = 0x03, + kPaused = 0x04, // All received enum values that are not listed above will be mapped // to kUnknownEnumValue. This is a helper enum value that should only // be used by code to process how it handles receiving and unknown // enum value. This specific should never be transmitted. - kUnknownEnumValue = 6, + kUnknownEnumValue = 5, }; // Enum for ESATypeEnum @@ -2449,13 +2461,43 @@ enum class ESATypeEnum : uint8_t kUnknownEnumValue = 14, }; +// Enum for ForecastUpdateReasonEnum +enum class ForecastUpdateReasonEnum : uint8_t +{ + kInternalOptimization = 0x00, + kLocalOptimization = 0x01, + kGridOptimization = 0x02, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 3, +}; + +// Enum for OptOutStateEnum +enum class OptOutStateEnum : uint8_t +{ + kNoOptOut = 0x00, + kLocalOptOut = 0x01, + kGridOptOut = 0x02, + kOptOut = 0x03, + // All received enum values that are not listed above will be mapped + // to kUnknownEnumValue. This is a helper enum value that should only + // be used by code to process how it handles receiving and unknown + // enum value. This specific should never be transmitted. + kUnknownEnumValue = 4, +}; + // Bitmap for Feature enum class Feature : uint32_t { - kPowerAdjustment = 0x1, - kPowerForecastReporting = 0x2, - kStateForecastReporting = 0x4, - kForecastAdjustment = 0x8, + kPowerAdjustment = 0x1, + kPowerForecastReporting = 0x2, + kStateForecastReporting = 0x4, + kStartTimeAdjustment = 0x8, + kPausable = 0x10, + kForecastAdjustment = 0x20, + kConstraintBasedAdjustment = 0x40, }; } // namespace DeviceEnergyManagement diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp index a0d28f1a74cb05..7d617579e01e93 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.cpp @@ -15262,6 +15262,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const encoder.Encode(to_underlying(Fields::kLatestEndTime), latestEndTime); encoder.Encode(to_underlying(Fields::kIsPauseable), isPauseable); encoder.Encode(to_underlying(Fields::kSlots), slots); + encoder.Encode(to_underlying(Fields::kForecastUpdateReason), forecastUpdateReason); return encoder.Finalize(); } @@ -15311,6 +15312,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, slots); } + else if (__context_tag == to_underlying(Fields::kForecastUpdateReason)) + { + err = DataModel::Decode(reader, forecastUpdateReason); + } else { } @@ -15482,6 +15487,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kPower), power); encoder.Encode(to_underlying(Fields::kDuration), duration); + encoder.Encode(to_underlying(Fields::kCause), cause); return encoder.Finalize(); } @@ -15507,6 +15513,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, duration); } + else if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } else { } @@ -15540,6 +15550,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kRequestedStartTime), requestedStartTime); + encoder.Encode(to_underlying(Fields::kCause), cause); return encoder.Finalize(); } @@ -15561,6 +15572,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, requestedStartTime); } + else if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } else { } @@ -15574,6 +15589,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kDuration), duration); + encoder.Encode(to_underlying(Fields::kCause), cause); return encoder.Finalize(); } @@ -15595,6 +15611,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, duration); } + else if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } else { } @@ -15629,6 +15649,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kForecastId), forecastId); encoder.Encode(to_underlying(Fields::kSlotAdjustments), slotAdjustments); + encoder.Encode(to_underlying(Fields::kCause), cause); return encoder.Finalize(); } @@ -15654,6 +15675,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, slotAdjustments); } + else if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } else { } @@ -15667,6 +15692,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; encoder.Encode(to_underlying(Fields::kConstraints), constraints); + encoder.Encode(to_underlying(Fields::kCause), cause); return encoder.Finalize(); } @@ -15688,6 +15714,10 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { err = DataModel::Decode(reader, constraints); } + else if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } else { } @@ -15696,6 +15726,26 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) } } } // namespace RequestConstraintBasedForecast. +namespace CancelRequest { +CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const +{ + DataModel::WrappedStructEncoder encoder{ aWriter, aTag }; + return encoder.Finalize(); +} + +CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) +{ + detail::StructDecodeIterator __iterator(reader); + while (true) + { + auto __element = __iterator.Next(); + if (std::holds_alternative(__element)) + { + return std::get(__element); + } + } +} +} // namespace CancelRequest. } // namespace Commands namespace Attributes { @@ -15717,6 +15767,8 @@ CHIP_ERROR TypeInfo::DecodableType::Decode(TLV::TLVReader & reader, const Concre return DataModel::Decode(reader, powerAdjustmentCapability); case Attributes::Forecast::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, forecast); + case Attributes::OptOutState::TypeInfo::GetAttributeId(): + return DataModel::Decode(reader, optOutState); case Attributes::GeneratedCommandList::TypeInfo::GetAttributeId(): return DataModel::Decode(reader, generatedCommandList); case Attributes::AcceptedCommandList::TypeInfo::GetAttributeId(): @@ -15828,6 +15880,7 @@ CHIP_ERROR Type::Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const { TLV::TLVType outer; ReturnErrorOnFailure(aWriter.StartContainer(aTag, TLV::kTLVType_Structure, outer)); + ReturnErrorOnFailure(DataModel::Encode(aWriter, TLV::ContextTag(Fields::kCause), cause)); return aWriter.EndContainer(outer); } @@ -15841,6 +15894,19 @@ CHIP_ERROR DecodableType::Decode(TLV::TLVReader & reader) { return std::get(__element); } + + CHIP_ERROR err = CHIP_NO_ERROR; + const uint8_t __context_tag = std::get(__element); + + if (__context_tag == to_underlying(Fields::kCause)) + { + err = DataModel::Decode(reader, cause); + } + else + { + } + + ReturnErrorOnFailure(err); } } } // namespace Resumed. diff --git a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h index f85e0335903656..aa3effd58f758e 100644 --- a/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h +++ b/zzz_generated/app-common/app-common/zap-generated/cluster-objects.h @@ -21346,9 +21346,9 @@ struct Type uint32_t defaultDuration = static_cast(0); uint32_t elapsedSlotTime = static_cast(0); uint32_t remainingSlotTime = static_cast(0); - bool slotIsPauseable = static_cast(0); - uint32_t minPauseDuration = static_cast(0); - uint32_t maxPauseDuration = static_cast(0); + Optional slotIsPauseable; + Optional minPauseDuration; + Optional maxPauseDuration; Optional manufacturerESAState; Optional nominalPower; Optional minPower; @@ -21373,9 +21373,9 @@ struct DecodableType uint32_t defaultDuration = static_cast(0); uint32_t elapsedSlotTime = static_cast(0); uint32_t remainingSlotTime = static_cast(0); - bool slotIsPauseable = static_cast(0); - uint32_t minPauseDuration = static_cast(0); - uint32_t maxPauseDuration = static_cast(0); + Optional slotIsPauseable; + Optional minPauseDuration; + Optional maxPauseDuration; Optional manufacturerESAState; Optional nominalPower; Optional minPower; @@ -21396,14 +21396,15 @@ struct DecodableType namespace ForecastStruct { enum class Fields : uint8_t { - kForecastId = 0, - kActiveSlotNumber = 1, - kStartTime = 2, - kEndTime = 3, - kEarliestStartTime = 4, - kLatestEndTime = 5, - kIsPauseable = 6, - kSlots = 7, + kForecastId = 0, + kActiveSlotNumber = 1, + kStartTime = 2, + kEndTime = 3, + kEarliestStartTime = 4, + kLatestEndTime = 5, + kIsPauseable = 6, + kSlots = 7, + kForecastUpdateReason = 8, }; struct Type @@ -21417,6 +21418,7 @@ struct Type Optional latestEndTime; bool isPauseable = static_cast(0); DataModel::List slots; + ForecastUpdateReasonEnum forecastUpdateReason = static_cast(0); static constexpr bool kIsFabricScoped = false; @@ -21434,6 +21436,7 @@ struct DecodableType Optional latestEndTime; bool isPauseable = static_cast(0); DataModel::DecodableList slots; + ForecastUpdateReasonEnum forecastUpdateReason = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); @@ -21562,6 +21565,11 @@ struct Type; struct DecodableType; } // namespace RequestConstraintBasedForecast +namespace CancelRequest { +struct Type; +struct DecodableType; +} // namespace CancelRequest + } // namespace Commands namespace Commands { @@ -21570,6 +21578,7 @@ enum class Fields : uint8_t { kPower = 0, kDuration = 1, + kCause = 2, }; struct Type @@ -21579,8 +21588,9 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::PowerAdjustRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } - int64_t power = static_cast(0); - uint32_t duration = static_cast(0); + int64_t power = static_cast(0); + uint32_t duration = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -21595,8 +21605,9 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::PowerAdjustRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } - int64_t power = static_cast(0); - uint32_t duration = static_cast(0); + int64_t power = static_cast(0); + uint32_t duration = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace PowerAdjustRequest @@ -21632,6 +21643,7 @@ namespace StartTimeAdjustRequest { enum class Fields : uint8_t { kRequestedStartTime = 0, + kCause = 1, }; struct Type @@ -21642,6 +21654,7 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } uint32_t requestedStartTime = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -21657,6 +21670,7 @@ struct DecodableType static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } uint32_t requestedStartTime = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace StartTimeAdjustRequest @@ -21664,6 +21678,7 @@ namespace PauseRequest { enum class Fields : uint8_t { kDuration = 0, + kCause = 1, }; struct Type @@ -21673,7 +21688,8 @@ struct Type static constexpr CommandId GetCommandId() { return Commands::PauseRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } - uint32_t duration = static_cast(0); + uint32_t duration = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -21688,7 +21704,8 @@ struct DecodableType static constexpr CommandId GetCommandId() { return Commands::PauseRequest::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } - uint32_t duration = static_cast(0); + uint32_t duration = static_cast(0); + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace PauseRequest @@ -21725,6 +21742,7 @@ enum class Fields : uint8_t { kForecastId = 0, kSlotAdjustments = 1, + kCause = 2, }; struct Type @@ -21736,6 +21754,7 @@ struct Type uint32_t forecastId = static_cast(0); DataModel::List slotAdjustments; + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -21752,6 +21771,7 @@ struct DecodableType uint32_t forecastId = static_cast(0); DataModel::DecodableList slotAdjustments; + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace ModifyForecastRequest @@ -21759,6 +21779,7 @@ namespace RequestConstraintBasedForecast { enum class Fields : uint8_t { kConstraints = 0, + kCause = 1, }; struct Type @@ -21769,6 +21790,7 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } DataModel::List constraints; + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; @@ -21784,9 +21806,38 @@ struct DecodableType static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } DataModel::DecodableList constraints; + AdjustmentCauseEnum cause = static_cast(0); CHIP_ERROR Decode(TLV::TLVReader & reader); }; }; // namespace RequestConstraintBasedForecast +namespace CancelRequest { +enum class Fields : uint8_t +{ +}; + +struct Type +{ +public: + // Use GetCommandId instead of commandId directly to avoid naming conflict with CommandIdentification in ExecutionOfACommand + static constexpr CommandId GetCommandId() { return Commands::CancelRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } + + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; + + using ResponseType = DataModel::NullObjectType; + + static constexpr bool MustUseTimedInvoke() { return false; } +}; + +struct DecodableType +{ +public: + static constexpr CommandId GetCommandId() { return Commands::CancelRequest::Id; } + static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } + + CHIP_ERROR Decode(TLV::TLVReader & reader); +}; +}; // namespace CancelRequest } // namespace Commands namespace Attributes { @@ -21880,6 +21931,18 @@ struct TypeInfo static constexpr bool MustUseTimedWrite() { return false; } }; } // namespace Forecast +namespace OptOutState { +struct TypeInfo +{ + using Type = chip::app::Clusters::DeviceEnergyManagement::OptOutStateEnum; + using DecodableType = chip::app::Clusters::DeviceEnergyManagement::OptOutStateEnum; + using DecodableArgType = chip::app::Clusters::DeviceEnergyManagement::OptOutStateEnum; + + static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } + static constexpr AttributeId GetAttributeId() { return Attributes::OptOutState::Id; } + static constexpr bool MustUseTimedWrite() { return false; } +}; +} // namespace OptOutState namespace GeneratedCommandList { struct TypeInfo : public Clusters::Globals::Attributes::GeneratedCommandList::TypeInfo { @@ -21934,6 +21997,8 @@ struct TypeInfo Attributes::AbsMaxPower::TypeInfo::DecodableType absMaxPower = static_cast(0); Attributes::PowerAdjustmentCapability::TypeInfo::DecodableType powerAdjustmentCapability; Attributes::Forecast::TypeInfo::DecodableType forecast; + Attributes::OptOutState::TypeInfo::DecodableType optOutState = + static_cast(0); Attributes::GeneratedCommandList::TypeInfo::DecodableType generatedCommandList; Attributes::AcceptedCommandList::TypeInfo::DecodableType acceptedCommandList; Attributes::EventList::TypeInfo::DecodableType eventList; @@ -22044,6 +22109,7 @@ static constexpr PriorityLevel kPriorityLevel = PriorityLevel::Info; enum class Fields : uint8_t { + kCause = 0, }; struct Type @@ -22054,6 +22120,8 @@ struct Type static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } static constexpr bool kIsFabricScoped = false; + CauseEnum cause = static_cast(0); + CHIP_ERROR Encode(TLV::TLVWriter & aWriter, TLV::Tag aTag) const; }; @@ -22064,6 +22132,8 @@ struct DecodableType static constexpr EventId GetEventId() { return Events::Resumed::Id; } static constexpr ClusterId GetClusterId() { return Clusters::DeviceEnergyManagement::Id; } + CauseEnum cause = static_cast(0); + CHIP_ERROR Decode(TLV::TLVReader & reader); }; } // namespace Resumed diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h index f2ce8f91f96885..1e237a2601cfd8 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Attributes.h @@ -3812,6 +3812,10 @@ namespace Forecast { static constexpr AttributeId Id = 0x00000006; } // namespace Forecast +namespace OptOutState { +static constexpr AttributeId Id = 0x00000007; +} // namespace OptOutState + namespace GeneratedCommandList { static constexpr AttributeId Id = Globals::Attributes::GeneratedCommandList::Id; } // namespace GeneratedCommandList diff --git a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h index 76ed4e215d1092..f5607a6ba0e910 100644 --- a/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h +++ b/zzz_generated/app-common/app-common/zap-generated/ids/Commands.h @@ -1002,6 +1002,10 @@ namespace RequestConstraintBasedForecast { static constexpr CommandId Id = 0x00000006; } // namespace RequestConstraintBasedForecast +namespace CancelRequest { +static constexpr CommandId Id = 0x00000007; +} // namespace CancelRequest + } // namespace Commands } // namespace DeviceEnergyManagement diff --git a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h index 12c9198618fac5..2b03b673a1292a 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/chip-tool/zap-generated/cluster/Commands.h @@ -6896,6 +6896,7 @@ class DemandResponseLoadControlClearLoadControlEventsRequest : public ClusterCom | * ResumeRequest | 0x04 | | * ModifyForecastRequest | 0x05 | | * RequestConstraintBasedForecast | 0x06 | +| * CancelRequest | 0x07 | |------------------------------------------------------------------------------| | Attributes: | | | * ESAType | 0x0000 | @@ -6905,6 +6906,7 @@ class DemandResponseLoadControlClearLoadControlEventsRequest : public ClusterCom | * AbsMaxPower | 0x0004 | | * PowerAdjustmentCapability | 0x0005 | | * Forecast | 0x0006 | +| * OptOutState | 0x0007 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -6930,6 +6932,7 @@ class DeviceEnergyManagementPowerAdjustRequest : public ClusterCommand { AddArgument("Power", INT64_MIN, INT64_MAX, &mRequest.power); AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration); + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); ClusterCommand::AddArguments(); } @@ -7005,6 +7008,7 @@ class DeviceEnergyManagementStartTimeAdjustRequest : public ClusterCommand ClusterCommand("start-time-adjust-request", credsIssuerConfig) { AddArgument("RequestedStartTime", 0, UINT32_MAX, &mRequest.requestedStartTime); + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); ClusterCommand::AddArguments(); } @@ -7043,6 +7047,7 @@ class DeviceEnergyManagementPauseRequest : public ClusterCommand ClusterCommand("pause-request", credsIssuerConfig) { AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration); + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); ClusterCommand::AddArguments(); } @@ -7119,6 +7124,7 @@ class DeviceEnergyManagementModifyForecastRequest : public ClusterCommand { AddArgument("ForecastId", 0, UINT32_MAX, &mRequest.forecastId); AddArgument("SlotAdjustments", &mComplex_SlotAdjustments); + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); ClusterCommand::AddArguments(); } @@ -7160,6 +7166,7 @@ class DeviceEnergyManagementRequestConstraintBasedForecast : public ClusterComma ClusterCommand("request-constraint-based-forecast", credsIssuerConfig), mComplex_Constraints(&mRequest.constraints) { AddArgument("Constraints", &mComplex_Constraints); + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); ClusterCommand::AddArguments(); } @@ -7193,6 +7200,43 @@ class DeviceEnergyManagementRequestConstraintBasedForecast : public ClusterComma mComplex_Constraints; }; +/* + * Command CancelRequest + */ +class DeviceEnergyManagementCancelRequest : public ClusterCommand +{ +public: + DeviceEnergyManagementCancelRequest(CredentialIssuerCommands * credsIssuerConfig) : + ClusterCommand("cancel-request", credsIssuerConfig) + { + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(chip::DeviceProxy * device, std::vector endpointIds) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::DeviceEnergyManagement::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::DeviceEnergyManagement::Commands::CancelRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, + commandId, endpointIds.at(0)); + return ClusterCommand::SendCommand(device, endpointIds.at(0), clusterId, commandId, mRequest); + } + + CHIP_ERROR SendGroupCommand(chip::GroupId groupId, chip::FabricIndex fabricIndex) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::DeviceEnergyManagement::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::DeviceEnergyManagement::Commands::CancelRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on Group %u", clusterId, commandId, + groupId); + + return ClusterCommand::SendGroupCommand(groupId, fabricIndex, clusterId, commandId, mRequest); + } + +private: + chip::app::Clusters::DeviceEnergyManagement::Commands::CancelRequest::Type mRequest; +}; + /*----------------------------------------------------------------------------*\ | Cluster EnergyEvse | 0x0099 | |------------------------------------------------------------------------------| @@ -20135,6 +20179,7 @@ void registerClusterDeviceEnergyManagement(Commands & commands, CredentialIssuer make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // make_unique(credsIssuerConfig), // + make_unique(credsIssuerConfig), // // // Attributes // @@ -20147,6 +20192,7 @@ void registerClusterDeviceEnergyManagement(Commands & commands, CredentialIssuer make_unique(Id, "power-adjustment-capability", Attributes::PowerAdjustmentCapability::Id, credsIssuerConfig), // make_unique(Id, "forecast", Attributes::Forecast::Id, credsIssuerConfig), // + make_unique(Id, "opt-out-state", Attributes::OptOutState::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // @@ -20171,6 +20217,8 @@ void registerClusterDeviceEnergyManagement(Commands & commands, CredentialIssuer make_unique>>( Id, "forecast", Attributes::Forecast::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // + make_unique>( + Id, "opt-out-state", 0, UINT8_MAX, Attributes::OptOutState::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // make_unique>>( Id, "generated-command-list", Attributes::GeneratedCommandList::Id, WriteCommandType::kForceWrite, credsIssuerConfig), // @@ -20193,6 +20241,7 @@ void registerClusterDeviceEnergyManagement(Commands & commands, CredentialIssuer make_unique(Id, "power-adjustment-capability", Attributes::PowerAdjustmentCapability::Id, credsIssuerConfig), // make_unique(Id, "forecast", Attributes::Forecast::Id, credsIssuerConfig), // + make_unique(Id, "opt-out-state", Attributes::OptOutState::Id, credsIssuerConfig), // make_unique(Id, "generated-command-list", Attributes::GeneratedCommandList::Id, credsIssuerConfig), // make_unique(Id, "accepted-command-list", Attributes::AcceptedCommandList::Id, credsIssuerConfig), // make_unique(Id, "event-list", Attributes::EventList::Id, credsIssuerConfig), // diff --git a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp index 2d016ac47c8996..302cafb0a0b37b 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/ComplexArgumentParser.cpp @@ -2853,12 +2853,6 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, value.isMember("elapsedSlotTime"))); ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("SlotStruct.remainingSlotTime", "remainingSlotTime", value.isMember("remainingSlotTime"))); - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("SlotStruct.slotIsPauseable", "slotIsPauseable", - value.isMember("slotIsPauseable"))); - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("SlotStruct.minPauseDuration", "minPauseDuration", - value.isMember("minPauseDuration"))); - ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("SlotStruct.maxPauseDuration", "maxPauseDuration", - value.isMember("maxPauseDuration"))); char labelWithMember[kMaxLabelLength]; snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "minDuration"); @@ -2881,16 +2875,25 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.remainingSlotTime, value["remainingSlotTime"])); valueCopy.removeMember("remainingSlotTime"); - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "slotIsPauseable"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.slotIsPauseable, value["slotIsPauseable"])); + if (value.isMember("slotIsPauseable")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "slotIsPauseable"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.slotIsPauseable, value["slotIsPauseable"])); + } valueCopy.removeMember("slotIsPauseable"); - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "minPauseDuration"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.minPauseDuration, value["minPauseDuration"])); + if (value.isMember("minPauseDuration")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "minPauseDuration"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.minPauseDuration, value["minPauseDuration"])); + } valueCopy.removeMember("minPauseDuration"); - snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "maxPauseDuration"); - ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.maxPauseDuration, value["maxPauseDuration"])); + if (value.isMember("maxPauseDuration")) + { + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "maxPauseDuration"); + ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.maxPauseDuration, value["maxPauseDuration"])); + } valueCopy.removeMember("maxPauseDuration"); if (value.isMember("manufacturerESAState")) @@ -3012,6 +3015,8 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, ReturnErrorOnFailure( ComplexArgumentParser::EnsureMemberExist("ForecastStruct.isPauseable", "isPauseable", value.isMember("isPauseable"))); ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("ForecastStruct.slots", "slots", value.isMember("slots"))); + ReturnErrorOnFailure(ComplexArgumentParser::EnsureMemberExist("ForecastStruct.forecastUpdateReason", "forecastUpdateReason", + value.isMember("forecastUpdateReason"))); char labelWithMember[kMaxLabelLength]; snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "forecastId"); @@ -3052,6 +3057,11 @@ CHIP_ERROR ComplexArgumentParser::Setup(const char * label, ReturnErrorOnFailure(ComplexArgumentParser::Setup(labelWithMember, request.slots, value["slots"])); valueCopy.removeMember("slots"); + snprintf(labelWithMember, sizeof(labelWithMember), "%s.%s", label, "forecastUpdateReason"); + ReturnErrorOnFailure( + ComplexArgumentParser::Setup(labelWithMember, request.forecastUpdateReason, value["forecastUpdateReason"])); + valueCopy.removeMember("forecastUpdateReason"); + return ComplexArgumentParser::EnsureNoMembersRemaining(label, valueCopy); } @@ -3065,6 +3075,7 @@ void ComplexArgumentParser::Finalize(chip::app::Clusters::DeviceEnergyManagement ComplexArgumentParser::Finalize(request.latestEndTime); ComplexArgumentParser::Finalize(request.isPauseable); ComplexArgumentParser::Finalize(request.slots); + ComplexArgumentParser::Finalize(request.forecastUpdateReason); } CHIP_ERROR ComplexArgumentParser::Setup(const char * label, diff --git a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp index 4026dc9e4e0dd3..9967c2f53d4203 100644 --- a/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp +++ b/zzz_generated/chip-tool/zap-generated/cluster/logging/DataModelLogger.cpp @@ -2727,6 +2727,14 @@ DataModelLogger::LogValue(const char * label, size_t indent, return err; } } + { + CHIP_ERROR err = LogValue("ForecastUpdateReason", indent + 1, value.forecastUpdateReason); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Struct truncated due to invalid value for 'ForecastUpdateReason'"); + return err; + } + } DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; @@ -6071,6 +6079,14 @@ CHIP_ERROR DataModelLogger::LogValue(const char * label, size_t indent, const DeviceEnergyManagement::Events::Resumed::DecodableType & value) { DataModelLogger::LogString(label, indent, "{"); + { + CHIP_ERROR err = DataModelLogger::LogValue("Cause", indent + 1, value.cause); + if (err != CHIP_NO_ERROR) + { + DataModelLogger::LogString(indent + 1, "Event truncated due to invalid value for 'Cause'"); + return err; + } + } DataModelLogger::LogString(indent, "}"); return CHIP_NO_ERROR; @@ -12281,6 +12297,11 @@ CHIP_ERROR DataModelLogger::LogAttribute(const chip::app::ConcreteDataAttributeP ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); return DataModelLogger::LogValue("Forecast", 1, value); } + case DeviceEnergyManagement::Attributes::OptOutState::Id: { + chip::app::Clusters::DeviceEnergyManagement::OptOutStateEnum value; + ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); + return DataModelLogger::LogValue("OptOutState", 1, value); + } case DeviceEnergyManagement::Attributes::GeneratedCommandList::Id: { chip::app::DataModel::DecodableList value; ReturnErrorOnFailure(chip::app::DataModel::Decode(*data, value)); diff --git a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h index 85d892b9960f75..8029dc30320e82 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/cluster/Commands.h @@ -79653,6 +79653,7 @@ class SubscribeAttributeDemandResponseLoadControlClusterRevision : public Subscr | * ResumeRequest | 0x04 | | * ModifyForecastRequest | 0x05 | | * RequestConstraintBasedForecast | 0x06 | +| * CancelRequest | 0x07 | |------------------------------------------------------------------------------| | Attributes: | | | * ESAType | 0x0000 | @@ -79662,6 +79663,7 @@ class SubscribeAttributeDemandResponseLoadControlClusterRevision : public Subscr | * AbsMaxPower | 0x0004 | | * PowerAdjustmentCapability | 0x0005 | | * Forecast | 0x0006 | +| * OptOutState | 0x0007 | | * GeneratedCommandList | 0xFFF8 | | * AcceptedCommandList | 0xFFF9 | | * EventList | 0xFFFA | @@ -79690,6 +79692,9 @@ class DeviceEnergyManagementPowerAdjustRequest : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -79710,6 +79715,9 @@ class DeviceEnergyManagementPowerAdjustRequest : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.cause = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.cause)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -79792,6 +79800,9 @@ class DeviceEnergyManagementStartTimeAdjustRequest : public ClusterCommand { { #if MTR_ENABLE_PROVISIONAL AddArgument("RequestedStartTime", 0, UINT32_MAX, &mRequest.requestedStartTime); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -79809,6 +79820,9 @@ class DeviceEnergyManagementStartTimeAdjustRequest : public ClusterCommand { params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; #if MTR_ENABLE_PROVISIONAL params.requestedStartTime = [NSNumber numberWithUnsignedInt:mRequest.requestedStartTime]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.cause = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.cause)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -79845,6 +79859,9 @@ class DeviceEnergyManagementPauseRequest : public ClusterCommand { { #if MTR_ENABLE_PROVISIONAL AddArgument("Duration", 0, UINT32_MAX, &mRequest.duration); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -79862,6 +79879,9 @@ class DeviceEnergyManagementPauseRequest : public ClusterCommand { params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; #if MTR_ENABLE_PROVISIONAL params.duration = [NSNumber numberWithUnsignedInt:mRequest.duration]; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.cause = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.cause)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -79948,6 +79968,9 @@ class DeviceEnergyManagementModifyForecastRequest : public ClusterCommand { #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL AddArgument("SlotAdjustments", &mComplex_SlotAdjustments); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -79979,6 +80002,9 @@ class DeviceEnergyManagementModifyForecastRequest : public ClusterCommand { } params.slotAdjustments = array_0; } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.cause = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.cause)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -80017,6 +80043,9 @@ class DeviceEnergyManagementRequestConstraintBasedForecast : public ClusterComma { #if MTR_ENABLE_PROVISIONAL AddArgument("Constraints", &mComplex_Constraints); +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + AddArgument("Cause", 0, UINT8_MAX, &mRequest.cause); #endif // MTR_ENABLE_PROVISIONAL ClusterCommand::AddArguments(); } @@ -80059,6 +80088,9 @@ class DeviceEnergyManagementRequestConstraintBasedForecast : public ClusterComma } params.constraints = array_0; } +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + params.cause = [NSNumber numberWithUnsignedChar:chip::to_underlying(mRequest.cause)]; #endif // MTR_ENABLE_PROVISIONAL uint16_t repeatCount = mRepeatCount.ValueOr(1); uint16_t __block responsesNeeded = repeatCount; @@ -80084,6 +80116,52 @@ class DeviceEnergyManagementRequestConstraintBasedForecast : public ClusterComma TypedComplexArgument> mComplex_Constraints; }; +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL +/* + * Command CancelRequest + */ +class DeviceEnergyManagementCancelRequest : public ClusterCommand { +public: + DeviceEnergyManagementCancelRequest() + : ClusterCommand("cancel-request") + { + ClusterCommand::AddArguments(); + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::DeviceEnergyManagement::Id; + constexpr chip::CommandId commandId = chip::app::Clusters::DeviceEnergyManagement::Commands::CancelRequest::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") command (0x%08" PRIX32 ") on endpoint %u", clusterId, commandId, endpointId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterDeviceEnergyManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRDeviceEnergyManagementClusterCancelRequestParams alloc] init]; + params.timedInvokeTimeoutMs = mTimedInteractionTimeoutMs.HasValue() ? [NSNumber numberWithUnsignedShort:mTimedInteractionTimeoutMs.Value()] : nil; + uint16_t repeatCount = mRepeatCount.ValueOr(1); + uint16_t __block responsesNeeded = repeatCount; + while (repeatCount--) { + [cluster cancelRequestWithParams:params completion: + ^(NSError * _Nullable error) { + responsesNeeded--; + if (error != nil) { + mError = error; + LogNSError("Error", error); + RemoteDataModelLogger::LogCommandErrorAsJSON(@(endpointId), @(clusterId), @(commandId), error); + } + if (responsesNeeded == 0) { + SetCommandExitStatus(mError); + } + }]; + } + return CHIP_NO_ERROR; + } + +private: +}; + #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL @@ -80683,6 +80761,91 @@ class SubscribeAttributeDeviceEnergyManagementForecast : public SubscribeAttribu #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL +/* + * Attribute OptOutState + */ +class ReadDeviceEnergyManagementOptOutState : public ReadAttribute { +public: + ReadDeviceEnergyManagementOptOutState() + : ReadAttribute("opt-out-state") + { + } + + ~ReadDeviceEnergyManagementOptOutState() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::DeviceEnergyManagement::Id; + constexpr chip::AttributeId attributeId = chip::app::Clusters::DeviceEnergyManagement::Attributes::OptOutState::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReadAttribute (0x%08" PRIX32 ") on endpoint %u", endpointId, clusterId, attributeId); + + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterDeviceEnergyManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + [cluster readAttributeOptOutStateWithCompletion:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"DeviceEnergyManagement.OptOutState response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + LogNSError("DeviceEnergyManagement OptOutState read Error", error); + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + return CHIP_NO_ERROR; + } +}; + +class SubscribeAttributeDeviceEnergyManagementOptOutState : public SubscribeAttribute { +public: + SubscribeAttributeDeviceEnergyManagementOptOutState() + : SubscribeAttribute("opt-out-state") + { + } + + ~SubscribeAttributeDeviceEnergyManagementOptOutState() + { + } + + CHIP_ERROR SendCommand(MTRBaseDevice * device, chip::EndpointId endpointId) override + { + constexpr chip::ClusterId clusterId = chip::app::Clusters::DeviceEnergyManagement::Id; + constexpr chip::CommandId attributeId = chip::app::Clusters::DeviceEnergyManagement::Attributes::OptOutState::Id; + + ChipLogProgress(chipTool, "Sending cluster (0x%08" PRIX32 ") ReportAttribute (0x%08" PRIX32 ") on endpoint %u", clusterId, attributeId, endpointId); + dispatch_queue_t callbackQueue = dispatch_queue_create("com.chip.command", DISPATCH_QUEUE_SERIAL); + __auto_type * cluster = [[MTRBaseClusterDeviceEnergyManagement alloc] initWithDevice:device endpointID:@(endpointId) queue:callbackQueue]; + __auto_type * params = [[MTRSubscribeParams alloc] initWithMinInterval:@(mMinInterval) maxInterval:@(mMaxInterval)]; + if (mKeepSubscriptions.HasValue()) { + params.replaceExistingSubscriptions = !mKeepSubscriptions.Value(); + } + if (mFabricFiltered.HasValue()) { + params.filterByFabric = mFabricFiltered.Value(); + } + if (mAutoResubscribe.HasValue()) { + params.resubscribeAutomatically = mAutoResubscribe.Value(); + } + [cluster subscribeAttributeOptOutStateWithParams:params + subscriptionEstablished:^() { mSubscriptionEstablished = YES; } + reportHandler:^(NSNumber * _Nullable value, NSError * _Nullable error) { + NSLog(@"DeviceEnergyManagement.OptOutState response %@", [value description]); + if (error == nil) { + RemoteDataModelLogger::LogAttributeAsJSON(@(endpointId), @(clusterId), @(attributeId), value); + } else { + RemoteDataModelLogger::LogAttributeErrorAsJSON(@(endpointId), @(clusterId), @(attributeId), error); + } + SetCommandExitStatus(error); + }]; + + return CHIP_NO_ERROR; + } +}; + +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + /* * Attribute GeneratedCommandList */ @@ -181335,6 +181498,9 @@ void registerClusterDeviceEnergyManagement(Commands & commands) #endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // #endif // MTR_ENABLE_PROVISIONAL make_unique(Id), // make_unique(Id), // @@ -181367,6 +181533,10 @@ void registerClusterDeviceEnergyManagement(Commands & commands) make_unique(), // make_unique(), // #endif // MTR_ENABLE_PROVISIONAL +#if MTR_ENABLE_PROVISIONAL + make_unique(), // + make_unique(), // +#endif // MTR_ENABLE_PROVISIONAL #if MTR_ENABLE_PROVISIONAL make_unique(), // make_unique(), //