diff --git a/.github/.wordlist.txt b/.github/.wordlist.txt
index 44470a612f42c7..07f3df6b7a9822 100644
--- a/.github/.wordlist.txt
+++ b/.github/.wordlist.txt
@@ -519,8 +519,10 @@ EthyleneOxideConcentrationMeasurement
EvalCode
EvalCodeWithName
EvalFrameDefault
+EV
EVB
evk
+EVSE
exceptfds
ExchangeContext
exe
diff --git a/.github/workflows/examples-qpg.yaml b/.github/workflows/examples-qpg.yaml
index e95e26816dbcc0..b5aadaf11c11bb 100644
--- a/.github/workflows/examples-qpg.yaml
+++ b/.github/workflows/examples-qpg.yaml
@@ -63,6 +63,8 @@ jobs:
--target qpg-qpg6105-light \
--target qpg-qpg6105-shell \
--target qpg-qpg6105-persistent-storage \
+ --target qpg-qpg6105-light-switch \
+ --target qpg-qpg6105-thermostat \
build \
--copy-artifacts-to out/artifacts \
"
diff --git a/config/qpg/toolchain/BUILD.gn b/config/qpg/toolchain/BUILD.gn
index bdf72c9b2ccf5e..65984b186a4f80 100644
--- a/config/qpg/toolchain/BUILD.gn
+++ b/config/qpg/toolchain/BUILD.gn
@@ -31,6 +31,13 @@ arm_toolchain("qpg_lighting_app") {
}
}
+arm_toolchain("qpg_light_switch_app") {
+ toolchain_args = {
+ current_os = "freertos"
+ import("${chip_root}/examples/light-switch-app/qpg/args.gni")
+ }
+}
+
arm_toolchain("qpg_shell_app") {
toolchain_args = {
current_os = "freertos"
diff --git a/config/telink/chip-module/CMakeLists.txt b/config/telink/chip-module/CMakeLists.txt
index f9f4b933cccf5d..418dbc07e0ba0b 100644
--- a/config/telink/chip-module/CMakeLists.txt
+++ b/config/telink/chip-module/CMakeLists.txt
@@ -97,7 +97,6 @@ matter_add_gn_arg_bool ("chip_config_network_layer_ble" CONFIG_BT)
matter_add_gn_arg_bool ("chip_inet_config_enable_ipv4" CONFIG_NET_IPV4)
matter_add_gn_arg_bool ("chip_enable_nfc" CONFIG_CHIP_NFC_COMMISSIONING)
matter_add_gn_arg_bool ("chip_enable_ota_requestor" CONFIG_CHIP_OTA_REQUESTOR)
-matter_add_gn_arg_bool ("chip_enable_bootloader_mcuboot" CONFIG_BOOTLOADER_MCUBOOT)
matter_add_gn_arg_bool ("chip_inet_config_enable_tcp_endpoint" CONFIG_CHIP_BUILD_TESTS)
matter_add_gn_arg_bool ("chip_error_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 1)
matter_add_gn_arg_bool ("chip_progress_logging" CONFIG_MATTER_LOG_LEVEL GREATER_EQUAL 3)
diff --git a/data_model/clusters/Scenes.xml b/data_model/clusters/Scenes.xml
index f82a470ca28eb5..daa9e5da564a41 100644
--- a/data_model/clusters/Scenes.xml
+++ b/data_model/clusters/Scenes.xml
@@ -1,61 +1,61 @@
-
-
+
@@ -528,4 +528,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/ColorDimmerSwitch.xml b/data_model/device_types/ColorDimmerSwitch.xml
index dcd2ac18b1a912..4de98619c1f9fb 100644
--- a/data_model/device_types/ColorDimmerSwitch.xml
+++ b/data_model/device_types/ColorDimmerSwitch.xml
@@ -1,59 +1,59 @@
-
@@ -73,7 +73,7 @@ Davis, CA 95616, USA
-
+
@@ -89,4 +89,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/ColorTemperatureLight.xml b/data_model/device_types/ColorTemperatureLight.xml
index 889f63db0de1f5..2e6db00535d3e3 100644
--- a/data_model/device_types/ColorTemperatureLight.xml
+++ b/data_model/device_types/ColorTemperatureLight.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -155,4 +155,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/ControlBridge.xml b/data_model/device_types/ControlBridge.xml
index 6ed528c0122d96..6c73377045b533 100644
--- a/data_model/device_types/ControlBridge.xml
+++ b/data_model/device_types/ControlBridge.xml
@@ -1,59 +1,59 @@
-
@@ -74,7 +74,7 @@ required."/>
-
+
@@ -96,4 +96,4 @@ required."/>
-
\ No newline at end of file
+
diff --git a/data_model/device_types/DimmableLight.xml b/data_model/device_types/DimmableLight.xml
index 39f193f53e7553..777cf64847884b 100644
--- a/data_model/device_types/DimmableLight.xml
+++ b/data_model/device_types/DimmableLight.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -142,4 +142,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/DimmablePlug-InUnit.xml b/data_model/device_types/DimmablePlug-InUnit.xml
index 012f752c7cc699..9a304fe9d18460 100644
--- a/data_model/device_types/DimmablePlug-InUnit.xml
+++ b/data_model/device_types/DimmablePlug-InUnit.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -142,4 +142,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/DimmerSwitch.xml b/data_model/device_types/DimmerSwitch.xml
index a3bae868a2498b..9922d6fb96dbcf 100644
--- a/data_model/device_types/DimmerSwitch.xml
+++ b/data_model/device_types/DimmerSwitch.xml
@@ -1,59 +1,59 @@
-
@@ -73,7 +73,7 @@ Davis, CA 95616, USA
-
+
@@ -86,4 +86,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/DoorLock.xml b/data_model/device_types/DoorLock.xml
index b322f991c3b6e4..c5eaf911f8f537 100644
--- a/data_model/device_types/DoorLock.xml
+++ b/data_model/device_types/DoorLock.xml
@@ -1,59 +1,59 @@
-
@@ -72,7 +72,7 @@ Davis, CA 95616, USA
-
+
@@ -187,4 +187,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/DoorLockController.xml b/data_model/device_types/DoorLockController.xml
index 413509de632c6e..6e515bc206e04a 100644
--- a/data_model/device_types/DoorLockController.xml
+++ b/data_model/device_types/DoorLockController.xml
@@ -1,59 +1,59 @@
-
@@ -78,7 +78,7 @@ Davis, CA 95616, USA
-
+
@@ -96,4 +96,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/ExtendedColorLight.xml b/data_model/device_types/ExtendedColorLight.xml
index d0ad7936d3629d..839a9c1db7a75b 100644
--- a/data_model/device_types/ExtendedColorLight.xml
+++ b/data_model/device_types/ExtendedColorLight.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -167,4 +167,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/HeatingCoolingUnit.xml b/data_model/device_types/HeatingCoolingUnit.xml
index 244ff14b0a15fa..3bcf0b8e2db0d1 100644
--- a/data_model/device_types/HeatingCoolingUnit.xml
+++ b/data_model/device_types/HeatingCoolingUnit.xml
@@ -1,59 +1,59 @@
-
@@ -70,7 +70,7 @@ Davis, CA 95616, USA
-
+
@@ -92,4 +92,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/OnOffLight.xml b/data_model/device_types/OnOffLight.xml
index 1ce39e8545c84a..6b12217ff10d6f 100644
--- a/data_model/device_types/OnOffLight.xml
+++ b/data_model/device_types/OnOffLight.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -142,4 +142,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/OnOffLightSwitch.xml b/data_model/device_types/OnOffLightSwitch.xml
index c2c324c8ee5d2a..df64178ade52ad 100644
--- a/data_model/device_types/OnOffLightSwitch.xml
+++ b/data_model/device_types/OnOffLightSwitch.xml
@@ -1,59 +1,59 @@
-
@@ -73,7 +73,7 @@ Davis, CA 95616, USA
-
+
@@ -83,4 +83,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/OnOffPlug-inUnit.xml b/data_model/device_types/OnOffPlug-inUnit.xml
index 11bd17151d5e49..83f1c9d0ec15ec 100644
--- a/data_model/device_types/OnOffPlug-inUnit.xml
+++ b/data_model/device_types/OnOffPlug-inUnit.xml
@@ -1,59 +1,59 @@
-
@@ -76,7 +76,7 @@ Davis, CA 95616, USA
-
+
@@ -142,4 +142,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/OnOffSensor.xml b/data_model/device_types/OnOffSensor.xml
index d2c6553fc1140c..d28f76f6130964 100644
--- a/data_model/device_types/OnOffSensor.xml
+++ b/data_model/device_types/OnOffSensor.xml
@@ -1,59 +1,59 @@
-
@@ -74,7 +74,7 @@ required."/>
-
+
@@ -90,4 +90,4 @@ required."/>
-
\ No newline at end of file
+
diff --git a/data_model/device_types/Pump.xml b/data_model/device_types/Pump.xml
index 6f1b1f39aae53c..298bb43cbb02c6 100644
--- a/data_model/device_types/Pump.xml
+++ b/data_model/device_types/Pump.xml
@@ -1,59 +1,59 @@
-
@@ -70,7 +70,7 @@ Davis, CA 95616, USA
-
+
@@ -107,4 +107,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/PumpController.xml b/data_model/device_types/PumpController.xml
index 1eb302399379fe..223915f4525b40 100644
--- a/data_model/device_types/PumpController.xml
+++ b/data_model/device_types/PumpController.xml
@@ -1,59 +1,59 @@
-
@@ -72,7 +72,7 @@ Davis, CA 95616, USA
-
+
@@ -100,4 +100,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/RoomAirConditioner.xml b/data_model/device_types/RoomAirConditioner.xml
index 86240698da6789..8e6a833406637c 100644
--- a/data_model/device_types/RoomAirConditioner.xml
+++ b/data_model/device_types/RoomAirConditioner.xml
@@ -1,59 +1,59 @@
-
@@ -68,7 +68,7 @@ Davis, CA 95616, USA
-
+
@@ -95,4 +95,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/Thermostat.xml b/data_model/device_types/Thermostat.xml
index 117bf36aa8b025..dac8172278b4ad 100644
--- a/data_model/device_types/Thermostat.xml
+++ b/data_model/device_types/Thermostat.xml
@@ -1,59 +1,59 @@
-
@@ -72,7 +72,7 @@ Davis, CA 95616, USA
-
+
@@ -154,4 +154,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/WindowCovering.xml b/data_model/device_types/WindowCovering.xml
index aecac7e3b24052..1f9e4a3a8ec319 100644
--- a/data_model/device_types/WindowCovering.xml
+++ b/data_model/device_types/WindowCovering.xml
@@ -1,59 +1,59 @@
-
@@ -75,7 +75,7 @@ Davis, CA 95616, USA
-
+
@@ -121,4 +121,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/data_model/device_types/WindowCoveringController.xml b/data_model/device_types/WindowCoveringController.xml
index f61f46f5132b4b..8e31eed548e90e 100644
--- a/data_model/device_types/WindowCoveringController.xml
+++ b/data_model/device_types/WindowCoveringController.xml
@@ -1,59 +1,59 @@
-
@@ -78,7 +78,7 @@ Davis, CA 95616, USA
-
+
@@ -98,4 +98,4 @@ Davis, CA 95616, USA
-
\ No newline at end of file
+
diff --git a/docs/clusters.md b/docs/clusters.md
index 1d0453033db586..70f657fd8779ad 100644
--- a/docs/clusters.md
+++ b/docs/clusters.md
@@ -14,7 +14,6 @@ Generally regenerate using one of:
| ---------- | ---------- | ------------------------------------------------------- |
| 3 | 0x03 | Identify |
| 4 | 0x04 | Groups |
-| 5 | 0x05 | Scenes |
| 6 | 0x06 | OnOff |
| 7 | 0x07 | OnOffSwitchConfiguration |
| 8 | 0x08 | LevelControl |
@@ -73,6 +72,7 @@ Generally regenerate using one of:
| 95 | 0x5F | MicrowaveOvenControl |
| 96 | 0x60 | OperationalState |
| 97 | 0x61 | RvcOperationalState |
+| 98 | 0x62 | ScenesManagement |
| 113 | 0x71 | HepaFilterMonitoring |
| 114 | 0x72 | ActivatedCarbonFilterMonitoring |
| 128 | 0x80 | BooleanStateConfiguration |
diff --git a/docs/examples/index.md b/docs/examples/index.md
index e31b434515f11b..0162a25afc149f 100644
--- a/docs/examples/index.md
+++ b/docs/examples/index.md
@@ -131,6 +131,7 @@ lighting-app/qpg/APPLICATION
:maxdepth: 1
light-switch-app/**/README
+light-switch-app/qpg/APPLICATION
```
## Lock example
@@ -282,6 +283,7 @@ temperature-measurement-app/**/README
thermostat/**/README
thermostat/**/Readme
+thermostat/qpg/APPLICATION
```
## TV example
diff --git a/docs/guides/python_chip_controller_building.md b/docs/guides/python_chip_controller_building.md
index 7edbede54057ae..c940f2c92575e7 100644
--- a/docs/guides/python_chip_controller_building.md
+++ b/docs/guides/python_chip_controller_building.md
@@ -539,7 +539,7 @@ OnOff
OperationalCredentials
PumpConfigurationAndControl
RelativeHumidityMeasurement
-Scenes
+ScenesManagement
SoftwareDiagnostics
Switch
Channel
diff --git a/examples/air-quality-sensor-app/telink/CMakeLists.txt b/examples/air-quality-sensor-app/telink/CMakeLists.txt
index 908bea9eb73a98..5ed8c314f1b334 100644
--- a/examples/air-quality-sensor-app/telink/CMakeLists.txt
+++ b/examples/air-quality-sensor-app/telink/CMakeLists.txt
@@ -86,10 +86,6 @@ target_include_directories(app PRIVATE
${TELINK_COMMON}/util/include
${CHIP_ROOT}/examples/air-quality-sensor-app/air-quality-sensor-common/include)
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
src/ZclCallbacks.cpp
@@ -107,3 +103,7 @@ chip_configure_data_model(app
INCLUDE_SERVER
ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../air-quality-sensor-common/air-quality-sensor-app.zap
)
+
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
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 e1dace194762d8..ad7cb56245f2bd 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
@@ -128,199 +128,6 @@ cluster Groups = 4 {
fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5;
}
-/** Attributes and commands for scene configuration and manipulation. */
-provisional cluster Scenes = 5 {
- revision 5;
-
- bitmap CopyModeBitmap : bitmap8 {
- kCopyAllScenes = 0x1;
- }
-
- bitmap Feature : bitmap32 {
- kSceneNames = 0x1;
- kExplicit = 0x2;
- kTableSize = 0x4;
- kFabricScenes = 0x8;
- }
-
- bitmap NameSupportBitmap : bitmap8 {
- kSceneNames = 0x80;
- }
-
- struct AttributeValuePair {
- attrib_id attributeID = 0;
- int32u attributeValue = 1;
- }
-
- struct ExtensionFieldSet {
- cluster_id clusterID = 0;
- AttributeValuePair attributeValueList[] = 1;
- }
-
- fabric_scoped struct SceneInfoStruct {
- int8u sceneCount = 0;
- fabric_sensitive int8u currentScene = 1;
- fabric_sensitive group_id currentGroup = 2;
- fabric_sensitive boolean sceneValid = 3;
- int8u remainingCapacity = 4;
- fabric_idx fabricIndex = 254;
- }
-
- readonly attribute optional int8u sceneCount = 0;
- readonly attribute optional int8u currentScene = 1;
- readonly attribute optional group_id currentGroup = 2;
- readonly attribute optional boolean sceneValid = 3;
- readonly attribute NameSupportBitmap nameSupport = 4;
- readonly attribute optional nullable node_id lastConfiguredBy = 5;
- readonly attribute int16u sceneTableSize = 6;
- readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
- readonly attribute command_id generatedCommandList[] = 65528;
- readonly attribute command_id acceptedCommandList[] = 65529;
- readonly attribute event_id eventList[] = 65530;
- readonly attribute attrib_id attributeList[] = 65531;
- readonly attribute bitmap32 featureMap = 65532;
- readonly attribute int16u clusterRevision = 65533;
-
- request struct AddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct AddSceneResponse = 0 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct ViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct ViewSceneResponse = 1 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct RemoveSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct RemoveSceneResponse = 2 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RemoveAllScenesRequest {
- group_id groupID = 0;
- }
-
- response struct RemoveAllScenesResponse = 3 {
- status status = 0;
- group_id groupID = 1;
- }
-
- request struct StoreSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct StoreSceneResponse = 4 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RecallSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- optional nullable int16u transitionTime = 2;
- }
-
- request struct GetSceneMembershipRequest {
- group_id groupID = 0;
- }
-
- response struct GetSceneMembershipResponse = 6 {
- status status = 0;
- nullable int8u capacity = 1;
- group_id groupID = 2;
- optional int8u sceneList[] = 3;
- }
-
- request struct EnhancedAddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct EnhancedAddSceneResponse = 64 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct EnhancedViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct EnhancedViewSceneResponse = 65 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct CopySceneRequest {
- CopyModeBitmap mode = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- group_id groupIdentifierTo = 3;
- int8u sceneIdentifierTo = 4;
- }
-
- response struct CopySceneResponse = 66 {
- status status = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- }
-
- /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
- fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
- /** Retrieves the requested scene entry from its Scene table. */
- fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
- /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
- /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
- /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
- fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
- /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
- fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
- /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
- fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
- /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
- fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
- /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
- fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
- /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
- fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
-}
-
/** Attributes and commands for switching devices between 'On' and 'Off' states. */
cluster OnOff = 6 {
revision 6;
@@ -3041,6 +2848,7 @@ cluster RvcRunMode = 84 {
enum ModeTag : enum16 {
kIdle = 16384;
kCleaning = 16385;
+ kMapping = 16386;
}
enum StatusCode : enum8 {
@@ -3600,18 +3408,211 @@ cluster RvcOperationalState = 97 {
readonly attribute bitmap32 featureMap = 65532;
readonly attribute int16u clusterRevision = 65533;
- response struct OperationalCommandResponse = 4 {
- ErrorStateStruct commandResponseState = 0;
+ response struct OperationalCommandResponse = 4 {
+ ErrorStateStruct commandResponseState = 0;
+ }
+
+ /** Upon receipt, the device SHALL pause its operation if it is possible based on the current function of the server. */
+ command Pause(): OperationalCommandResponse = 0;
+ /** Upon receipt, the device SHALL stop its operation if it is at a position where it is safe to do so and/or permitted. */
+ command Stop(): OperationalCommandResponse = 1;
+ /** Upon receipt, the device SHALL start its operation if it is safe to do so and the device is in an operational state from which it can be started. */
+ command Start(): OperationalCommandResponse = 2;
+ /** Upon receipt, the device SHALL resume its operation from the point it was at when it received the Pause command, or from the point when it was paused by means outside of this cluster (for example by manual button press). */
+ command Resume(): OperationalCommandResponse = 3;
+}
+
+/** Attributes and commands for scene configuration and manipulation. */
+provisional cluster ScenesManagement = 98 {
+ revision 5;
+
+ bitmap CopyModeBitmap : bitmap8 {
+ kCopyAllScenes = 0x1;
+ }
+
+ bitmap Feature : bitmap32 {
+ kSceneNames = 0x1;
+ kExplicit = 0x2;
+ kTableSize = 0x4;
+ kFabricScenes = 0x8;
+ }
+
+ bitmap NameSupportBitmap : bitmap8 {
+ kSceneNames = 0x80;
+ }
+
+ struct AttributeValuePair {
+ attrib_id attributeID = 0;
+ int32u attributeValue = 1;
+ }
+
+ struct ExtensionFieldSet {
+ cluster_id clusterID = 0;
+ AttributeValuePair attributeValueList[] = 1;
+ }
+
+ fabric_scoped struct SceneInfoStruct {
+ int8u sceneCount = 0;
+ fabric_sensitive int8u currentScene = 1;
+ fabric_sensitive group_id currentGroup = 2;
+ fabric_sensitive boolean sceneValid = 3;
+ int8u remainingCapacity = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ readonly attribute optional int8u sceneCount = 0;
+ readonly attribute optional int8u currentScene = 1;
+ readonly attribute optional group_id currentGroup = 2;
+ readonly attribute optional boolean sceneValid = 3;
+ readonly attribute NameSupportBitmap nameSupport = 4;
+ readonly attribute optional nullable node_id lastConfiguredBy = 5;
+ readonly attribute int16u sceneTableSize = 6;
+ readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
+
+ response struct AddSceneResponse = 0 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct ViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct ViewSceneResponse = 1 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
+
+ request struct RemoveSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct RemoveSceneResponse = 2 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct RemoveAllScenesRequest {
+ group_id groupID = 0;
+ }
+
+ response struct RemoveAllScenesResponse = 3 {
+ status status = 0;
+ group_id groupID = 1;
+ }
+
+ request struct StoreSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct StoreSceneResponse = 4 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct RecallSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ optional nullable int16u transitionTime = 2;
+ }
+
+ request struct GetSceneMembershipRequest {
+ group_id groupID = 0;
+ }
+
+ response struct GetSceneMembershipResponse = 6 {
+ status status = 0;
+ nullable int8u capacity = 1;
+ group_id groupID = 2;
+ optional int8u sceneList[] = 3;
+ }
+
+ request struct EnhancedAddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
+
+ response struct EnhancedAddSceneResponse = 64 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct EnhancedViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct EnhancedViewSceneResponse = 65 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
+
+ request struct CopySceneRequest {
+ CopyModeBitmap mode = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
+ group_id groupIdentifierTo = 3;
+ int8u sceneIdentifierTo = 4;
+ }
+
+ response struct CopySceneResponse = 66 {
+ status status = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
}
- /** Upon receipt, the device SHALL pause its operation if it is possible based on the current function of the server. */
- command Pause(): OperationalCommandResponse = 0;
- /** Upon receipt, the device SHALL stop its operation if it is at a position where it is safe to do so and/or permitted. */
- command Stop(): OperationalCommandResponse = 1;
- /** Upon receipt, the device SHALL start its operation if it is safe to do so and the device is in an operational state from which it can be started. */
- command Start(): OperationalCommandResponse = 2;
- /** Upon receipt, the device SHALL resume its operation from the point it was at when it received the Pause command, or from the point when it was paused by means outside of this cluster (for example by manual button press). */
- command Resume(): OperationalCommandResponse = 3;
+ /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
+ fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
+ /** Retrieves the requested scene entry from its Scene table. */
+ fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
+ /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
+ /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
+ /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
+ fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
+ /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
+ fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
+ /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
+ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
+ /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
+ fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
+ /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
+ fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
+ /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
+ fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
}
/** Attributes and commands for monitoring HEPA filters in a device */
@@ -3919,6 +3920,185 @@ provisional cluster ElectricalEnergyMeasurement = 145 {
readonly attribute int16u clusterRevision = 65533;
}
+/** 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;
+
+ enum CauseEnum : enum8 {
+ kNormalCompletion = 0;
+ kOffline = 1;
+ kFault = 2;
+ kUserOptOut = 3;
+ }
+
+ enum CostTypeEnum : enum8 {
+ kFinancial = 0;
+ kGHGEmissions = 1;
+ kComfort = 2;
+ kTemperature = 3;
+ }
+
+ enum ESAStateEnum : enum8 {
+ kOffline = 0;
+ kOnline = 1;
+ kFault = 2;
+ kUserOptOut = 3;
+ kPowerAdjustActive = 4;
+ kPaused = 5;
+ }
+
+ enum ESATypeEnum : enum8 {
+ kEVSE = 0;
+ kSpaceHeating = 1;
+ kWaterHeating = 2;
+ kSpaceCooling = 3;
+ kSpaceHeatingCooling = 4;
+ kBatteryStorage = 5;
+ kSolarPV = 6;
+ kFridgeFreezer = 7;
+ kWashingMachine = 8;
+ kDishwasher = 9;
+ kCooking = 10;
+ kHomeWaterPump = 11;
+ kIrrigationWaterPump = 12;
+ kPoolPump = 13;
+ kOther = 255;
+ }
+
+ bitmap Feature : bitmap32 {
+ kPowerAdjustment = 0x1;
+ kPowerForecastReporting = 0x2;
+ kStateForecastReporting = 0x4;
+ kForecastAdjustment = 0x8;
+ }
+
+ struct CostStruct {
+ CostTypeEnum costType = 0;
+ int32s value = 1;
+ int8u decimalPoints = 2;
+ optional int16u currency = 3;
+ }
+
+ struct SlotStruct {
+ elapsed_s minDuration = 0;
+ elapsed_s maxDuration = 1;
+ elapsed_s defaultDuration = 2;
+ elapsed_s elapsedSlotTime = 3;
+ elapsed_s remainingSlotTime = 4;
+ boolean slotIsPauseable = 5;
+ elapsed_s minPauseDuration = 6;
+ elapsed_s maxPauseDuration = 7;
+ optional int16u manufacturerESAState = 8;
+ optional power_mw nominalPower = 9;
+ optional power_mw minPower = 10;
+ optional power_mw maxPower = 11;
+ optional energy_mwh nominalEnergy = 12;
+ optional CostStruct costs[] = 13;
+ optional power_mw minPowerAdjustment = 14;
+ optional power_mw maxPowerAdjustment = 15;
+ optional elapsed_s minDurationAdjustment = 16;
+ optional elapsed_s maxDurationAdjustment = 17;
+ }
+
+ struct ForecastStruct {
+ int16u forecastId = 0;
+ nullable int16u activeSlotNumber = 1;
+ epoch_s startTime = 2;
+ epoch_s endTime = 3;
+ optional nullable epoch_s earliestStartTime = 4;
+ optional epoch_s latestEndTime = 5;
+ boolean isPauseable = 6;
+ SlotStruct slots[] = 7;
+ }
+
+ struct ConstraintsStruct {
+ epoch_s startTime = 0;
+ elapsed_s duration = 1;
+ optional power_mw nominalPower = 2;
+ optional energy_mwh maximumEnergy = 3;
+ optional int8s loadControl = 4;
+ }
+
+ struct PowerAdjustStruct {
+ power_mw minPower = 0;
+ power_mw maxPower = 1;
+ elapsed_s minDuration = 2;
+ elapsed_s maxDuration = 3;
+ }
+
+ struct SlotAdjustmentStruct {
+ int8u slotIndex = 0;
+ power_mw nominalPower = 1;
+ elapsed_s duration = 2;
+ }
+
+ info event PowerAdjustStart = 0 {
+ }
+
+ info event PowerAdjustEnd = 1 {
+ CauseEnum cause = 0;
+ elapsed_s duration = 1;
+ energy_mwh energyUse = 2;
+ }
+
+ info event Paused = 2 {
+ }
+
+ info event Resumed = 3 {
+ }
+
+ readonly attribute ESATypeEnum ESAType = 0;
+ readonly attribute boolean ESACanGenerate = 1;
+ readonly attribute ESAStateEnum ESAState = 2;
+ readonly attribute power_mw absMinPower = 3;
+ readonly attribute power_mw absMaxPower = 4;
+ readonly attribute optional nullable PowerAdjustStruct powerAdjustmentCapability[] = 5;
+ readonly attribute optional nullable ForecastStruct forecast = 6;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct PowerAdjustRequestRequest {
+ power_mw power = 0;
+ elapsed_s duration = 1;
+ }
+
+ request struct StartTimeAdjustRequestRequest {
+ epoch_s requestedStartTime = 0;
+ }
+
+ request struct PauseRequestRequest {
+ elapsed_s duration = 0;
+ }
+
+ request struct ModifyForecastRequestRequest {
+ int32u forecastId = 0;
+ SlotAdjustmentStruct slotAdjustments[] = 1;
+ }
+
+ request struct RequestConstraintBasedForecastRequest {
+ ConstraintsStruct constraints[] = 0;
+ }
+
+ /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */
+ command PowerAdjustRequest(PowerAdjustRequestRequest): DefaultSuccess = 0;
+ /** Allows a client to cancel an ongoing PowerAdjustmentRequest operation. */
+ command CancelPowerAdjustRequest(): DefaultSuccess = 1;
+ /** 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). */
+ command StartTimeAdjustRequest(StartTimeAdjustRequestRequest): DefaultSuccess = 2;
+ /** Allows a client to temporarily pause an operation and reduce the ESAs energy demand. */
+ command PauseRequest(PauseRequestRequest): DefaultSuccess = 3;
+ /** Allows a client to cancel the PauseRequest command and enable earlier resumption of operation. */
+ command ResumeRequest(): DefaultSuccess = 4;
+ /** Allows a client to modify a Forecast within the limits allowed by the ESA. */
+ 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;
+}
+
/** 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. */
provisional cluster EnergyEvse = 153 {
revision 2;
@@ -4466,6 +4646,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -4527,6 +4717,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -4536,6 +4730,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -4574,6 +4773,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -4629,6 +4884,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -4660,14 +4929,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
@@ -6752,6 +7052,9 @@ endpoint 0 {
ram attribute lastNetworkingStatus;
ram attribute lastNetworkID;
ram attribute lastConnectErrorValue;
+ callback attribute supportedWiFiBands;
+ callback attribute supportedThreadFeatures;
+ callback attribute threadVersion;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
@@ -7092,39 +7395,6 @@ endpoint 1 {
handle command AddGroupIfIdentifying;
}
- server cluster Scenes {
- ram attribute nameSupport default = 0x80;
- ram attribute lastConfiguredBy;
- ram attribute sceneTableSize default = 16;
- callback attribute fabricSceneInfo;
- callback attribute generatedCommandList;
- callback attribute acceptedCommandList;
- callback attribute eventList;
- callback attribute attributeList;
- ram attribute featureMap default = 15;
- ram attribute clusterRevision default = 5;
-
- handle command AddScene;
- handle command AddSceneResponse;
- handle command ViewScene;
- handle command ViewSceneResponse;
- handle command RemoveScene;
- handle command RemoveSceneResponse;
- handle command RemoveAllScenes;
- handle command RemoveAllScenesResponse;
- handle command StoreScene;
- handle command StoreSceneResponse;
- handle command RecallScene;
- handle command GetSceneMembership;
- handle command GetSceneMembershipResponse;
- handle command EnhancedAddScene;
- handle command EnhancedAddSceneResponse;
- handle command EnhancedViewScene;
- handle command EnhancedViewSceneResponse;
- handle command CopyScene;
- handle command CopySceneResponse;
- }
-
server cluster OnOff {
persist attribute onOff default = 0x00;
ram attribute globalSceneControl default = 0x01;
@@ -7518,6 +7788,39 @@ endpoint 1 {
handle command OperationalCommandResponse;
}
+ server cluster ScenesManagement {
+ ram attribute nameSupport default = 0x80;
+ ram attribute lastConfiguredBy;
+ ram attribute sceneTableSize default = 16;
+ callback attribute fabricSceneInfo;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ ram attribute featureMap default = 15;
+ ram attribute clusterRevision default = 5;
+
+ handle command AddScene;
+ handle command AddSceneResponse;
+ handle command ViewScene;
+ handle command ViewSceneResponse;
+ handle command RemoveScene;
+ handle command RemoveSceneResponse;
+ handle command RemoveAllScenes;
+ handle command RemoveAllScenesResponse;
+ handle command StoreScene;
+ handle command StoreSceneResponse;
+ handle command RecallScene;
+ handle command GetSceneMembership;
+ handle command GetSceneMembershipResponse;
+ handle command EnhancedAddScene;
+ handle command EnhancedAddSceneResponse;
+ handle command EnhancedViewScene;
+ handle command EnhancedViewSceneResponse;
+ handle command CopyScene;
+ handle command CopySceneResponse;
+ }
+
server cluster HepaFilterMonitoring {
callback attribute condition;
callback attribute degradationDirection;
@@ -7613,25 +7916,53 @@ endpoint 1 {
ram attribute clusterRevision default = 1;
}
+ server cluster DeviceEnergyManagement {
+ emits event PowerAdjustStart;
+ emits event PowerAdjustEnd;
+ emits event Paused;
+ emits event Resumed;
+ callback attribute ESAType;
+ callback attribute ESACanGenerate;
+ callback attribute ESAState;
+ callback attribute absMinPower;
+ callback attribute absMaxPower;
+ callback attribute powerAdjustmentCapability;
+ callback attribute forecast;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ callback attribute featureMap;
+ ram attribute clusterRevision default = 2;
+
+ handle command PowerAdjustRequest;
+ handle command CancelPowerAdjustRequest;
+ handle command StartTimeAdjustRequest;
+ handle command PauseRequest;
+ handle command ResumeRequest;
+ handle command ModifyForecastRequest;
+ handle command RequestConstraintBasedForecast;
+ }
+
server cluster EnergyEvse {
- callback attribute state default = 0;
- callback attribute supplyState default = 0;
- callback attribute faultState default = 0;
- callback attribute chargingEnabledUntil default = 0;
- callback attribute dischargingEnabledUntil default = 0;
- callback attribute circuitCapacity default = 0;
- callback attribute minimumChargeCurrent default = 6000;
- callback attribute maximumChargeCurrent default = 0;
- callback attribute maximumDischargeCurrent default = 0;
- callback attribute userMaximumChargeCurrent default = 0;
- callback attribute randomizationDelayWindow default = 600;
+ callback attribute state;
+ callback attribute supplyState;
+ callback attribute faultState;
+ callback attribute chargingEnabledUntil;
+ callback attribute dischargingEnabledUntil;
+ callback attribute circuitCapacity;
+ callback attribute minimumChargeCurrent;
+ callback attribute maximumChargeCurrent;
+ callback attribute maximumDischargeCurrent;
+ callback attribute userMaximumChargeCurrent;
+ callback attribute randomizationDelayWindow;
callback attribute numberOfWeeklyTargets default = 0;
callback attribute numberOfDailyTargets default = 1;
callback attribute nextChargeStartTime;
callback attribute nextChargeTargetTime;
callback attribute nextChargeRequiredEnergy;
callback attribute nextChargeTargetSoC;
- callback attribute approximateEVEfficiency default = 0xFFFF;
+ callback attribute approximateEVEfficiency;
callback attribute stateOfCharge;
callback attribute batteryCapacity;
callback attribute vehicleID;
@@ -7643,7 +7974,7 @@ endpoint 1 {
callback attribute acceptedCommandList;
callback attribute eventList;
callback attribute attributeList;
- ram attribute featureMap default = 0;
+ callback attribute featureMap;
ram attribute clusterRevision default = 2;
handle command GetTargetsResponse;
@@ -7749,6 +8080,19 @@ endpoint 1 {
ram attribute minSetpointDeadBand default = 0x19;
ram attribute controlSequenceOfOperation default = 0x04;
ram attribute systemMode default = 0x01;
+ callback attribute presetTypes;
+ callback attribute scheduleTypes;
+ ram attribute numberOfPresets default = 0;
+ ram attribute numberOfSchedules default = 0;
+ ram attribute numberOfScheduleTransitionPerDay default = 0xFF;
+ ram attribute activePresetHandle;
+ ram attribute activeScheduleHandle;
+ callback attribute presets;
+ callback attribute schedules;
+ ram attribute presetsSchedulesEditable;
+ ram attribute temperatureSetpointHoldPolicy default = 0;
+ ram attribute setpointHoldExpiryTimestamp;
+ callback attribute queuedPreset;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
@@ -7757,6 +8101,13 @@ endpoint 1 {
ram attribute clusterRevision default = 6;
handle command SetpointRaiseLower;
+ handle command SetActiveScheduleRequest;
+ handle command SetActivePresetRequest;
+ handle command StartPresetsSchedulesEditRequest;
+ handle command CancelPresetsSchedulesEditRequest;
+ handle command CommitPresetsSchedulesRequest;
+ handle command CancelSetActivePresetRequest;
+ handle command SetTemperatureSetpointHoldPolicy;
}
server cluster FanControl {
@@ -8314,39 +8665,6 @@ endpoint 2 {
handle command AddGroupIfIdentifying;
}
- server cluster Scenes {
- ram attribute nameSupport default = 0x80;
- ram attribute lastConfiguredBy;
- ram attribute sceneTableSize default = 16;
- callback attribute fabricSceneInfo;
- callback attribute generatedCommandList;
- callback attribute acceptedCommandList;
- callback attribute eventList;
- callback attribute attributeList;
- ram attribute featureMap default = 15;
- ram attribute clusterRevision default = 5;
-
- handle command AddScene;
- handle command AddSceneResponse;
- handle command ViewScene;
- handle command ViewSceneResponse;
- handle command RemoveScene;
- handle command RemoveSceneResponse;
- handle command RemoveAllScenes;
- handle command RemoveAllScenesResponse;
- handle command StoreScene;
- handle command StoreSceneResponse;
- handle command RecallScene;
- handle command GetSceneMembership;
- handle command GetSceneMembershipResponse;
- handle command EnhancedAddScene;
- handle command EnhancedAddSceneResponse;
- handle command EnhancedViewScene;
- handle command EnhancedViewSceneResponse;
- handle command CopyScene;
- handle command CopySceneResponse;
- }
-
server cluster OnOff {
ram attribute onOff default = 0x00;
ram attribute globalSceneControl default = 1;
@@ -8398,6 +8716,39 @@ endpoint 2 {
ram attribute clusterRevision default = 2;
}
+ server cluster ScenesManagement {
+ ram attribute nameSupport default = 0x80;
+ ram attribute lastConfiguredBy;
+ ram attribute sceneTableSize default = 16;
+ callback attribute fabricSceneInfo;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ ram attribute featureMap default = 15;
+ ram attribute clusterRevision default = 5;
+
+ handle command AddScene;
+ handle command AddSceneResponse;
+ handle command ViewScene;
+ handle command ViewSceneResponse;
+ handle command RemoveScene;
+ handle command RemoveSceneResponse;
+ handle command RemoveAllScenes;
+ handle command RemoveAllScenesResponse;
+ handle command StoreScene;
+ handle command StoreSceneResponse;
+ handle command RecallScene;
+ handle command GetSceneMembership;
+ handle command GetSceneMembershipResponse;
+ handle command EnhancedAddScene;
+ handle command EnhancedAddSceneResponse;
+ handle command EnhancedViewScene;
+ handle command EnhancedViewSceneResponse;
+ handle command CopyScene;
+ handle command CopySceneResponse;
+ }
+
server cluster OccupancySensing {
ram attribute occupancy;
ram attribute occupancySensorType;
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 fabe40ca88f598..9013ea3140e6db 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
@@ -2562,6 +2562,54 @@
"maxInterval": 65534,
"reportableChange": 0
},
+ {
+ "name": "SupportedWiFiBands",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportedThreadFeatures",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "ThreadCapabilitiesBitmap",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ThreadVersion",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
{
"name": "GeneratedCommandList",
"code": 65528,
@@ -6464,8 +6512,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "server",
@@ -12593,24 +12641,24 @@
]
},
{
- "name": "Energy EVSE",
- "code": 153,
+ "name": "Device Energy Management",
+ "code": 152,
"mfgCode": null,
- "define": "ENERGY_EVSE_CLUSTER",
+ "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER",
"side": "server",
"enabled": 1,
"apiMaturity": "provisional",
"commands": [
{
- "name": "GetTargetsResponse",
+ "name": "PowerAdjustRequest",
"code": 0,
"mfgCode": null,
- "source": "server",
- "isIncoming": 0,
+ "source": "client",
+ "isIncoming": 1,
"isEnabled": 1
},
{
- "name": "Disable",
+ "name": "CancelPowerAdjustRequest",
"code": 1,
"mfgCode": null,
"source": "client",
@@ -12618,7 +12666,7 @@
"isEnabled": 1
},
{
- "name": "EnableCharging",
+ "name": "StartTimeAdjustRequest",
"code": 2,
"mfgCode": null,
"source": "client",
@@ -12626,7 +12674,7 @@
"isEnabled": 1
},
{
- "name": "EnableDischarging",
+ "name": "PauseRequest",
"code": 3,
"mfgCode": null,
"source": "client",
@@ -12634,7 +12682,7 @@
"isEnabled": 1
},
{
- "name": "StartDiagnostics",
+ "name": "ResumeRequest",
"code": 4,
"mfgCode": null,
"source": "client",
@@ -12642,7 +12690,7 @@
"isEnabled": 1
},
{
- "name": "SetTargets",
+ "name": "ModifyForecastRequest",
"code": 5,
"mfgCode": null,
"source": "client",
@@ -12650,29 +12698,21 @@
"isEnabled": 1
},
{
- "name": "GetTargets",
+ "name": "RequestConstraintBasedForecast",
"code": 6,
"mfgCode": null,
"source": "client",
"isIncoming": 1,
"isEnabled": 1
- },
- {
- "name": "ClearTargets",
- "code": 7,
- "mfgCode": null,
- "source": "client",
- "isIncoming": 1,
- "isEnabled": 1
}
],
"attributes": [
{
- "name": "State",
+ "name": "ESAType",
"code": 0,
"mfgCode": null,
"side": "server",
- "type": "StateEnum",
+ "type": "ESATypeEnum",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12684,11 +12724,11 @@
"reportableChange": 0
},
{
- "name": "SupplyState",
+ "name": "ESACanGenerate",
"code": 1,
"mfgCode": null,
"side": "server",
- "type": "SupplyStateEnum",
+ "type": "boolean",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12700,11 +12740,11 @@
"reportableChange": 0
},
{
- "name": "FaultState",
+ "name": "ESAState",
"code": 2,
"mfgCode": null,
"side": "server",
- "type": "FaultStateEnum",
+ "type": "ESAStateEnum",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12716,11 +12756,11 @@
"reportableChange": 0
},
{
- "name": "ChargingEnabledUntil",
+ "name": "AbsMinPower",
"code": 3,
"mfgCode": null,
"side": "server",
- "type": "epoch_s",
+ "type": "power_mw",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12732,11 +12772,11 @@
"reportableChange": 0
},
{
- "name": "DischargingEnabledUntil",
+ "name": "AbsMaxPower",
"code": 4,
"mfgCode": null,
"side": "server",
- "type": "epoch_s",
+ "type": "power_mw",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12748,107 +12788,107 @@
"reportableChange": 0
},
{
- "name": "CircuitCapacity",
+ "name": "PowerAdjustmentCapability",
"code": 5,
"mfgCode": null,
"side": "server",
- "type": "amperage_ma",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "MinimumChargeCurrent",
+ "name": "Forecast",
"code": 6,
"mfgCode": null,
"side": "server",
- "type": "amperage_ma",
+ "type": "ForecastStruct",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "6000",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "MaximumChargeCurrent",
- "code": 7,
+ "name": "GeneratedCommandList",
+ "code": 65528,
"mfgCode": null,
"side": "server",
- "type": "amperage_ma",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "MaximumDischargeCurrent",
- "code": 8,
+ "name": "AcceptedCommandList",
+ "code": 65529,
"mfgCode": null,
"side": "server",
- "type": "amperage_ma",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "UserMaximumChargeCurrent",
- "code": 9,
+ "name": "EventList",
+ "code": 65530,
"mfgCode": null,
"side": "server",
- "type": "amperage_ma",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "0",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "RandomizationDelayWindow",
- "code": 10,
+ "name": "AttributeList",
+ "code": 65531,
"mfgCode": null,
"side": "server",
- "type": "elapsed_s",
+ "type": "array",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "600",
+ "defaultValue": null,
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "NumberOfWeeklyTargets",
- "code": 33,
+ "name": "FeatureMap",
+ "code": 65532,
"mfgCode": null,
"side": "server",
- "type": "int8u",
+ "type": "bitmap32",
"included": 1,
"storageOption": "External",
"singleton": 0,
@@ -12860,57 +12900,372 @@
"reportableChange": 0
},
{
- "name": "NumberOfDailyTargets",
- "code": 34,
+ "name": "ClusterRevision",
+ "code": 65533,
"mfgCode": null,
"side": "server",
- "type": "int8u",
+ "type": "int16u",
"included": 1,
- "storageOption": "External",
+ "storageOption": "RAM",
"singleton": 0,
"bounded": 0,
- "defaultValue": "1",
+ "defaultValue": "2",
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
+ }
+ ],
+ "events": [
+ {
+ "name": "PowerAdjustStart",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
},
{
- "name": "NextChargeStartTime",
- "code": 35,
+ "name": "PowerAdjustEnd",
+ "code": 1,
"mfgCode": null,
"side": "server",
- "type": "epoch_s",
+ "included": 1
+ },
+ {
+ "name": "Paused",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ },
+ {
+ "name": "Resumed",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ }
+ ]
+ },
+ {
+ "name": "Energy EVSE",
+ "code": 153,
+ "mfgCode": null,
+ "define": "ENERGY_EVSE_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "apiMaturity": "provisional",
+ "commands": [
+ {
+ "name": "GetTargetsResponse",
+ "code": 0,
+ "mfgCode": null,
+ "source": "server",
+ "isIncoming": 0,
+ "isEnabled": 1
+ },
+ {
+ "name": "Disable",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "EnableCharging",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "EnableDischarging",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "StartDiagnostics",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "SetTargets",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "GetTargets",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "ClearTargets",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "State",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "StateEnum",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": "0",
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "NextChargeTargetTime",
- "code": 36,
+ "name": "SupplyState",
+ "code": 1,
"mfgCode": null,
"side": "server",
- "type": "epoch_s",
+ "type": "SupplyStateEnum",
"included": 1,
"storageOption": "External",
"singleton": 0,
"bounded": 0,
- "defaultValue": "",
+ "defaultValue": "0",
"reportable": 1,
"minInterval": 1,
"maxInterval": 65534,
"reportableChange": 0
},
{
- "name": "NextChargeRequiredEnergy",
- "code": 37,
- "mfgCode": null,
+ "name": "FaultState",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "FaultStateEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ChargingEnabledUntil",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "epoch_s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "DischargingEnabledUntil",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "epoch_s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "CircuitCapacity",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "amperage_ma",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MinimumChargeCurrent",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "amperage_ma",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "6000",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaximumChargeCurrent",
+ "code": 7,
+ "mfgCode": null,
+ "side": "server",
+ "type": "amperage_ma",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "MaximumDischargeCurrent",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "amperage_ma",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "UserMaximumChargeCurrent",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "amperage_ma",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "RandomizationDelayWindow",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "elapsed_s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "600",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfWeeklyTargets",
+ "code": 33,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfDailyTargets",
+ "code": 34,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "1",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NextChargeStartTime",
+ "code": 35,
+ "mfgCode": null,
+ "side": "server",
+ "type": "epoch_s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NextChargeTargetTime",
+ "code": 36,
+ "mfgCode": null,
+ "side": "server",
+ "type": "epoch_s",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NextChargeRequiredEnergy",
+ "code": 37,
+ "mfgCode": null,
"side": "server",
"type": "energy_mwh",
"included": 1,
@@ -13138,7 +13493,7 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "0",
@@ -14215,6 +14570,78 @@
"source": "client",
"isIncoming": 1,
"isEnabled": 1
+ },
+ {
+ "name": "GetRelayStatusLogResponse",
+ "code": 1,
+ "mfgCode": null,
+ "source": "server",
+ "isIncoming": 0,
+ "isEnabled": 0
+ },
+ {
+ "name": "GetRelayStatusLog",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "SetActiveScheduleRequest",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "SetActivePresetRequest",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "StartPresetsSchedulesEditRequest",
+ "code": 7,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "CancelPresetsSchedulesEditRequest",
+ "code": 8,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "CommitPresetsSchedulesRequest",
+ "code": 9,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "CancelSetActivePresetRequest",
+ "code": 10,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
+ },
+ {
+ "name": "SetTemperatureSetpointHoldPolicy",
+ "code": 11,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 0
}
],
"attributes": [
@@ -14442,6 +14869,214 @@
"maxInterval": 65344,
"reportableChange": 0
},
+ {
+ "name": "PresetTypes",
+ "code": 72,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ScheduleTypes",
+ "code": 73,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfPresets",
+ "code": 74,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfSchedules",
+ "code": 75,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "NumberOfScheduleTransitionPerDay",
+ "code": 77,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int8u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0xFF",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActivePresetHandle",
+ "code": 78,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ActiveScheduleHandle",
+ "code": 79,
+ "mfgCode": null,
+ "side": "server",
+ "type": "octet_string",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Presets",
+ "code": 80,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Schedules",
+ "code": 81,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PresetsSchedulesEditable",
+ "code": 82,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "TemperatureSetpointHoldPolicy",
+ "code": 83,
+ "mfgCode": null,
+ "side": "server",
+ "type": "TemperatureSetpointHoldPolicyBitmap",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SetpointHoldExpiryTimestamp",
+ "code": 84,
+ "mfgCode": null,
+ "side": "server",
+ "type": "epoch_s",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "QueuedPreset",
+ "code": 85,
+ "mfgCode": null,
+ "side": "server",
+ "type": "QueuedPresetStruct",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
{
"name": "GeneratedCommandList",
"code": 65528,
@@ -21806,8 +22441,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "server",
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
new file mode 100644
index 00000000000000..385c1cfa43c8ee
--- /dev/null
+++ b/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.
+ */
+
+#include
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::DeviceEnergyManagement;
+
+static std::unique_ptr gDelegate;
+static std::unique_ptr gInstance;
+
+void emberAfDeviceEnergyManagementClusterInitCallback(chip::EndpointId endpointId)
+{
+ VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
+ VerifyOrDie(gInstance == nullptr);
+
+ CHIP_ERROR err;
+
+ if (gDelegate || gInstance)
+ {
+ ChipLogError(AppServer, "DEM Instance or Delegate already exist.");
+ return;
+ }
+
+ gDelegate = std::make_unique();
+ if (!gDelegate)
+ {
+ ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate");
+ return;
+ }
+
+ /* Manufacturer may optionally not support all features, commands & attributes */
+ gInstance = std::make_unique(
+ endpointId, *gDelegate,
+ BitMask(
+ DeviceEnergyManagement::Feature::kPowerForecastReporting, DeviceEnergyManagement::Feature::kStateForecastReporting,
+ DeviceEnergyManagement::Feature::kPowerAdjustment, DeviceEnergyManagement::Feature::kForecastAdjustment),
+ BitMask(OptionalCommands::kSupportsModifyForecastRequest,
+ OptionalCommands::kSupportsRequestConstraintBasedForecast));
+
+ if (!gInstance)
+ {
+ ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager");
+ gDelegate.reset();
+ return;
+ }
+
+ err = gInstance->Init(); /* Register Attribute & Command handlers */
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "Init failed on gInstance");
+ gInstance.reset();
+ gDelegate.reset();
+ return;
+ }
+}
diff --git a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp
index a0773de104c187..f9983d47883852 100644
--- a/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp
+++ b/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp
@@ -22,25 +22,26 @@ using namespace chip;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::EnergyEvse;
-static EnergyEvseDelegate * gDelegate = nullptr;
-static EnergyEvseManager * gInstance = nullptr;
+static std::unique_ptr gDelegate;
+static std::unique_ptr gInstance;
void emberAfEnergyEvseClusterInitCallback(chip::EndpointId endpointId)
{
VerifyOrDie(endpointId == 1); // this cluster is only enabled for endpoint 1.
- VerifyOrDie(gInstance == nullptr);
- gDelegate = new EnergyEvseDelegate();
- if (gDelegate != nullptr)
+ VerifyOrDie(!gInstance);
+
+ gDelegate = std::make_unique();
+ if (gDelegate)
{
- gInstance =
- new EnergyEvseManager(endpointId, *gDelegate,
- BitMask(
- EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge,
- EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting, EnergyEvse::Feature::kV2x),
- BitMask(OptionalAttributes::kSupportsUserMaximumChargingCurrent,
- OptionalAttributes::kSupportsRandomizationWindow,
- OptionalAttributes::kSupportsApproximateEvEfficiency),
- BitMask(OptionalCommands::kSupportsStartDiagnostics));
+ gInstance = std::make_unique(
+ endpointId, *gDelegate,
+ BitMask(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge,
+ EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting,
+ EnergyEvse::Feature::kV2x),
+ BitMask(OptionalAttributes::kSupportsUserMaximumChargingCurrent,
+ OptionalAttributes::kSupportsRandomizationWindow,
+ OptionalAttributes::kSupportsApproximateEvEfficiency),
+ BitMask(OptionalCommands::kSupportsStartDiagnostics));
gInstance->Init(); /* Register Attribute & Command handlers */
}
diff --git a/examples/all-clusters-app/ameba/chip_main.cmake b/examples/all-clusters-app/ameba/chip_main.cmake
index e68398afdf625d..66528a9941141a 100755
--- a/examples/all-clusters-app/ameba/chip_main.cmake
+++ b/examples/all-clusters-app/ameba/chip_main.cmake
@@ -156,6 +156,7 @@ list(
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp
+ ${chip_dir}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp
${chip_dir}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp
@@ -175,6 +176,8 @@ list(
${chip_dir}/examples/all-clusters-app/ameba/main/ManualOperationCommand.cpp
${chip_dir}/examples/all-clusters-app/ameba/main/SmokeCOAlarmManager.cpp
+ ${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp
+ ${chip_dir}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp
${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp
${chip_dir}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp
diff --git a/examples/all-clusters-app/asr/BUILD.gn b/examples/all-clusters-app/asr/BUILD.gn
index 1c23617af66262..263bd8cf7734b7 100755
--- a/examples/all-clusters-app/asr/BUILD.gn
+++ b/examples/all-clusters-app/asr/BUILD.gn
@@ -74,6 +74,7 @@ asr_executable("clusters_app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -81,6 +82,8 @@ asr_executable("clusters_app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"${examples_plat_dir}/ButtonHandler.cpp",
diff --git a/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn b/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn
index 26c0f67e389a0c..6ec6202ea21209 100644
--- a/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn
+++ b/examples/all-clusters-app/cc13x2x7_26x2x7/BUILD.gn
@@ -79,6 +79,7 @@ ti_simplelink_executable("all-clusters-app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -86,6 +87,8 @@ ti_simplelink_executable("all-clusters-app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp",
diff --git a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn
index e9492d7a223f42..02dbebf7e6d8c9 100644
--- a/examples/all-clusters-app/cc13x4_26x4/BUILD.gn
+++ b/examples/all-clusters-app/cc13x4_26x4/BUILD.gn
@@ -82,6 +82,7 @@ ti_simplelink_executable("all-clusters-app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -89,6 +90,8 @@ ti_simplelink_executable("all-clusters-app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"${chip_root}/examples/providers/DeviceInfoProviderImpl.cpp",
diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt
index 89ce7c1c872160..623e2ded547abe 100644
--- a/examples/all-clusters-app/esp32/main/CMakeLists.txt
+++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt
@@ -75,6 +75,7 @@ set(SRC_DIRS_LIST
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/icd-management-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server"
+ "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server"
diff --git a/examples/all-clusters-app/infineon/psoc6/BUILD.gn b/examples/all-clusters-app/infineon/psoc6/BUILD.gn
index f4469b9c7bc290..f2b9ab939d6f38 100644
--- a/examples/all-clusters-app/infineon/psoc6/BUILD.gn
+++ b/examples/all-clusters-app/infineon/psoc6/BUILD.gn
@@ -110,6 +110,7 @@ psoc6_executable("clusters_app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -117,6 +118,8 @@ psoc6_executable("clusters_app") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"${examples_plat_dir}/LEDWidget.cpp",
diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn
index b2cc122b5090ab..8b031d769773e4 100644
--- a/examples/all-clusters-app/linux/BUILD.gn
+++ b/examples/all-clusters-app/linux/BUILD.gn
@@ -26,6 +26,7 @@ source_set("chip-all-clusters-common") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/boolcfg-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/dishwasher-alarm-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/dishwasher-mode.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
@@ -42,6 +43,8 @@ source_set("chip-all-clusters-common") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/tcc-mode.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"AllClustersCommandDelegate.cpp",
diff --git a/examples/all-clusters-app/mbed/CMakeLists.txt b/examples/all-clusters-app/mbed/CMakeLists.txt
index 28104e85f0c3b1..f2b6d9f5e88d27 100644
--- a/examples/all-clusters-app/mbed/CMakeLists.txt
+++ b/examples/all-clusters-app/mbed/CMakeLists.txt
@@ -65,6 +65,7 @@ target_sources(${APP_TARGET} PRIVATE
${ALL_CLUSTERS_COMMON}/src/air-quality-instance.cpp
${ALL_CLUSTERS_COMMON}/src/concentration-measurement-instances.cpp
${ALL_CLUSTERS_COMMON}/src/fan-stub.cpp
+ ${ALL_CLUSTERS_COMMON}/src/device-energy-management-stub.cpp
${ALL_CLUSTERS_COMMON}/src/energy-evse-stub.cpp
${ALL_CLUSTERS_COMMON}/src/oven-modes.cpp
${ALL_CLUSTERS_COMMON}/src/resource-monitoring-delegates.cpp
@@ -73,6 +74,9 @@ target_sources(${APP_TARGET} PRIVATE
${ALL_CLUSTERS_COMMON}/src/static-supported-temperature-levels.cpp
${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseDelegateImpl.cpp
${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseManager.cpp
+ ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementDelegateImpl.cpp
+ ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp
+
)
chip_configure_data_model(${APP_TARGET}
diff --git a/examples/all-clusters-app/nrfconnect/CMakeLists.txt b/examples/all-clusters-app/nrfconnect/CMakeLists.txt
index 48499c29712d40..49bf4fb7f95e3a 100644
--- a/examples/all-clusters-app/nrfconnect/CMakeLists.txt
+++ b/examples/all-clusters-app/nrfconnect/CMakeLists.txt
@@ -65,10 +65,13 @@ target_sources(app PRIVATE
${ALL_CLUSTERS_COMMON_DIR}/src/fan-stub.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/oven-modes.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/energy-evse-stub.cpp
+ ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/binding-handler.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/air-quality-instance.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/concentration-measurement-instances.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/resource-monitoring-delegates.cpp
+ ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementDelegateImpl.cpp
+ ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementManager.cpp
${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseDelegateImpl.cpp
${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseManager.cpp
${NRFCONNECT_COMMON}/util/LEDWidget.cpp)
diff --git a/examples/all-clusters-app/nxp/mw320/BUILD.gn b/examples/all-clusters-app/nxp/mw320/BUILD.gn
index 01bba26479a7af..a858c18e87fed2 100644
--- a/examples/all-clusters-app/nxp/mw320/BUILD.gn
+++ b/examples/all-clusters-app/nxp/mw320/BUILD.gn
@@ -78,6 +78,7 @@ mw320_executable("shell_mw320") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/air-quality-instance.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -85,6 +86,8 @@ mw320_executable("shell_mw320") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
"${chip_root}/src/lib/shell/streamer_mw320.cpp",
diff --git a/examples/all-clusters-app/openiotsdk/CMakeLists.txt b/examples/all-clusters-app/openiotsdk/CMakeLists.txt
index 60b5bdddf40740..3b50f286b1683b 100644
--- a/examples/all-clusters-app/openiotsdk/CMakeLists.txt
+++ b/examples/all-clusters-app/openiotsdk/CMakeLists.txt
@@ -60,12 +60,15 @@ target_sources(${APP_TARGET}
${ALL_CLUSTERS_COMMON}/src/concentration-measurement-instances.cpp
${ALL_CLUSTERS_COMMON}/src/fan-stub.cpp
${ALL_CLUSTERS_COMMON}/src/oven-modes.cpp
+ ${ALL_CLUSTERS_COMMON}/src/device-energy-management-stub.cpp
${ALL_CLUSTERS_COMMON}/src/energy-evse-stub.cpp
${ALL_CLUSTERS_COMMON}/src/resource-monitoring-delegates.cpp
${ALL_CLUSTERS_COMMON}/src/static-supported-modes-manager.cpp
${ALL_CLUSTERS_COMMON}/src/binding-handler.cpp
${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseDelegateImpl.cpp
${ENERGY_MANAGEMENT_COMMON}/src/EnergyEvseManager.cpp
+ ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementDelegateImpl.cpp
+ ${ENERGY_MANAGEMENT_COMMON}/src/DeviceEnergyManagementManager.cpp
)
target_link_libraries(${APP_TARGET}
diff --git a/examples/all-clusters-app/telink/CMakeLists.txt b/examples/all-clusters-app/telink/CMakeLists.txt
index 7448fd76c4d91f..ae715a8c41ebfb 100644
--- a/examples/all-clusters-app/telink/CMakeLists.txt
+++ b/examples/all-clusters-app/telink/CMakeLists.txt
@@ -72,10 +72,6 @@ target_include_directories(app PRIVATE
${TELINK_COMMON}/common/include
${TELINK_COMMON}/util/include)
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/smco-stub.cpp
@@ -86,10 +82,13 @@ target_sources(app PRIVATE
${ALL_CLUSTERS_COMMON_DIR}/src/air-quality-instance.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/concentration-measurement-instances.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/fan-stub.cpp
+ ${ALL_CLUSTERS_COMMON_DIR}/src/device-energy-management-stub.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/energy-evse-stub.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/resource-monitoring-delegates.cpp
${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseDelegateImpl.cpp
${ENERGY_MANAGEMENT_COMMON_DIR}/src/EnergyEvseManager.cpp
+ ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementDelegateImpl.cpp
+ ${ENERGY_MANAGEMENT_COMMON_DIR}/src/DeviceEnergyManagementManager.cpp
${TELINK_COMMON}/common/src/mainCommon.cpp
${TELINK_COMMON}/common/src/AppTaskCommon.cpp
${TELINK_COMMON}/util/src/LEDWidget.cpp
@@ -101,3 +100,7 @@ chip_configure_data_model(app
INCLUDE_SERVER
ZAP_FILE ${ALL_CLUSTERS_COMMON_DIR}/all-clusters-app.zap
)
+
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
diff --git a/examples/all-clusters-app/tizen/BUILD.gn b/examples/all-clusters-app/tizen/BUILD.gn
index 202d288f87053c..e9bb7f56e4bfaa 100644
--- a/examples/all-clusters-app/tizen/BUILD.gn
+++ b/examples/all-clusters-app/tizen/BUILD.gn
@@ -27,6 +27,7 @@ source_set("chip-all-clusters-common") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/binding-handler.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/bridged-actions-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/concentration-measurement-instances.cpp",
+ "${chip_root}/examples/all-clusters-app/all-clusters-common/src/device-energy-management-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/energy-evse-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/fan-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/oven-modes.cpp",
@@ -34,6 +35,8 @@ source_set("chip-all-clusters-common") {
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/smco-stub.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-modes-manager.cpp",
"${chip_root}/examples/all-clusters-app/all-clusters-common/src/static-supported-temperature-levels.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
]
diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
index 22ca859b26a104..dd01a2fb356f22 100644
--- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
+++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.matter
@@ -128,199 +128,6 @@ cluster Groups = 4 {
fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5;
}
-/** Attributes and commands for scene configuration and manipulation. */
-provisional cluster Scenes = 5 {
- revision 5;
-
- bitmap CopyModeBitmap : bitmap8 {
- kCopyAllScenes = 0x1;
- }
-
- bitmap Feature : bitmap32 {
- kSceneNames = 0x1;
- kExplicit = 0x2;
- kTableSize = 0x4;
- kFabricScenes = 0x8;
- }
-
- bitmap NameSupportBitmap : bitmap8 {
- kSceneNames = 0x80;
- }
-
- struct AttributeValuePair {
- attrib_id attributeID = 0;
- int32u attributeValue = 1;
- }
-
- struct ExtensionFieldSet {
- cluster_id clusterID = 0;
- AttributeValuePair attributeValueList[] = 1;
- }
-
- fabric_scoped struct SceneInfoStruct {
- int8u sceneCount = 0;
- fabric_sensitive int8u currentScene = 1;
- fabric_sensitive group_id currentGroup = 2;
- fabric_sensitive boolean sceneValid = 3;
- int8u remainingCapacity = 4;
- fabric_idx fabricIndex = 254;
- }
-
- readonly attribute optional int8u sceneCount = 0;
- readonly attribute optional int8u currentScene = 1;
- readonly attribute optional group_id currentGroup = 2;
- readonly attribute optional boolean sceneValid = 3;
- readonly attribute NameSupportBitmap nameSupport = 4;
- readonly attribute optional nullable node_id lastConfiguredBy = 5;
- readonly attribute int16u sceneTableSize = 6;
- readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
- readonly attribute command_id generatedCommandList[] = 65528;
- readonly attribute command_id acceptedCommandList[] = 65529;
- readonly attribute event_id eventList[] = 65530;
- readonly attribute attrib_id attributeList[] = 65531;
- readonly attribute bitmap32 featureMap = 65532;
- readonly attribute int16u clusterRevision = 65533;
-
- request struct AddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct AddSceneResponse = 0 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct ViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct ViewSceneResponse = 1 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct RemoveSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct RemoveSceneResponse = 2 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RemoveAllScenesRequest {
- group_id groupID = 0;
- }
-
- response struct RemoveAllScenesResponse = 3 {
- status status = 0;
- group_id groupID = 1;
- }
-
- request struct StoreSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct StoreSceneResponse = 4 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RecallSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- optional nullable int16u transitionTime = 2;
- }
-
- request struct GetSceneMembershipRequest {
- group_id groupID = 0;
- }
-
- response struct GetSceneMembershipResponse = 6 {
- status status = 0;
- nullable int8u capacity = 1;
- group_id groupID = 2;
- optional int8u sceneList[] = 3;
- }
-
- request struct EnhancedAddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct EnhancedAddSceneResponse = 64 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct EnhancedViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct EnhancedViewSceneResponse = 65 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct CopySceneRequest {
- CopyModeBitmap mode = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- group_id groupIdentifierTo = 3;
- int8u sceneIdentifierTo = 4;
- }
-
- response struct CopySceneResponse = 66 {
- status status = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- }
-
- /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
- fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
- /** Retrieves the requested scene entry from its Scene table. */
- fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
- /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
- /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
- /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
- fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
- /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
- fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
- /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
- fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
- /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
- fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
- /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
- fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
- /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
- fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
-}
-
/** Attributes and commands for switching devices between 'On' and 'Off' states. */
cluster OnOff = 6 {
revision 6;
@@ -2521,72 +2328,265 @@ cluster BooleanState = 69 {
cluster ModeSelect = 80 {
revision 2;
- bitmap Feature : bitmap32 {
- kOnOff = 0x1;
+ bitmap Feature : bitmap32 {
+ kOnOff = 0x1;
+ }
+
+ struct SemanticTagStruct {
+ vendor_id mfgCode = 0;
+ enum16 value = 1;
+ }
+
+ struct ModeOptionStruct {
+ char_string<64> label = 0;
+ int8u mode = 1;
+ SemanticTagStruct semanticTags[] = 2;
+ }
+
+ readonly attribute char_string<64> description = 0;
+ readonly attribute nullable enum16 standardNamespace = 1;
+ readonly attribute ModeOptionStruct supportedModes[] = 2;
+ readonly attribute int8u currentMode = 3;
+ attribute optional nullable int8u startUpMode = 4;
+ attribute optional nullable int8u onMode = 5;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct ChangeToModeRequest {
+ int8u newMode = 0;
+ }
+
+ /** On receipt of this command, if the NewMode field matches the Mode field in an entry of the SupportedModes list, the server SHALL set the CurrentMode attribute to the NewMode value, otherwise, the server SHALL respond with an INVALID_COMMAND status response. */
+ command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0;
+}
+
+/** Attributes and commands for configuring the temperature control, and reporting temperature. */
+cluster TemperatureControl = 86 {
+ revision 1; // NOTE: Default/not specifically set
+
+ bitmap Feature : bitmap32 {
+ kTemperatureNumber = 0x1;
+ kTemperatureLevel = 0x2;
+ kTemperatureStep = 0x4;
+ }
+
+ readonly attribute optional temperature temperatureSetpoint = 0;
+ readonly attribute optional temperature minTemperature = 1;
+ readonly attribute optional temperature maxTemperature = 2;
+ readonly attribute optional temperature step = 3;
+ readonly attribute optional int8u selectedTemperatureLevel = 4;
+ readonly attribute optional char_string supportedTemperatureLevels[] = 5;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct SetTemperatureRequest {
+ optional temperature targetTemperature = 0;
+ optional int8u targetTemperatureLevel = 1;
+ }
+
+ /** Set Temperature */
+ command SetTemperature(SetTemperatureRequest): DefaultSuccess = 0;
+}
+
+/** Attributes and commands for scene configuration and manipulation. */
+provisional cluster ScenesManagement = 98 {
+ revision 5;
+
+ bitmap CopyModeBitmap : bitmap8 {
+ kCopyAllScenes = 0x1;
+ }
+
+ bitmap Feature : bitmap32 {
+ kSceneNames = 0x1;
+ kExplicit = 0x2;
+ kTableSize = 0x4;
+ kFabricScenes = 0x8;
+ }
+
+ bitmap NameSupportBitmap : bitmap8 {
+ kSceneNames = 0x80;
+ }
+
+ struct AttributeValuePair {
+ attrib_id attributeID = 0;
+ int32u attributeValue = 1;
+ }
+
+ struct ExtensionFieldSet {
+ cluster_id clusterID = 0;
+ AttributeValuePair attributeValueList[] = 1;
+ }
+
+ fabric_scoped struct SceneInfoStruct {
+ int8u sceneCount = 0;
+ fabric_sensitive int8u currentScene = 1;
+ fabric_sensitive group_id currentGroup = 2;
+ fabric_sensitive boolean sceneValid = 3;
+ int8u remainingCapacity = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ readonly attribute optional int8u sceneCount = 0;
+ readonly attribute optional int8u currentScene = 1;
+ readonly attribute optional group_id currentGroup = 2;
+ readonly attribute optional boolean sceneValid = 3;
+ readonly attribute NameSupportBitmap nameSupport = 4;
+ readonly attribute optional nullable node_id lastConfiguredBy = 5;
+ readonly attribute int16u sceneTableSize = 6;
+ readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
+
+ response struct AddSceneResponse = 0 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct ViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct ViewSceneResponse = 1 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
+
+ request struct RemoveSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct RemoveSceneResponse = 2 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct RemoveAllScenesRequest {
+ group_id groupID = 0;
+ }
+
+ response struct RemoveAllScenesResponse = 3 {
+ status status = 0;
+ group_id groupID = 1;
+ }
+
+ request struct StoreSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
}
- struct SemanticTagStruct {
- vendor_id mfgCode = 0;
- enum16 value = 1;
+ response struct StoreSceneResponse = 4 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
}
- struct ModeOptionStruct {
- char_string<64> label = 0;
- int8u mode = 1;
- SemanticTagStruct semanticTags[] = 2;
+ request struct RecallSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ optional nullable int16u transitionTime = 2;
}
- readonly attribute char_string<64> description = 0;
- readonly attribute nullable enum16 standardNamespace = 1;
- readonly attribute ModeOptionStruct supportedModes[] = 2;
- readonly attribute int8u currentMode = 3;
- attribute optional nullable int8u startUpMode = 4;
- attribute optional nullable int8u onMode = 5;
- readonly attribute command_id generatedCommandList[] = 65528;
- readonly attribute command_id acceptedCommandList[] = 65529;
- readonly attribute event_id eventList[] = 65530;
- readonly attribute attrib_id attributeList[] = 65531;
- readonly attribute bitmap32 featureMap = 65532;
- readonly attribute int16u clusterRevision = 65533;
+ request struct GetSceneMembershipRequest {
+ group_id groupID = 0;
+ }
- request struct ChangeToModeRequest {
- int8u newMode = 0;
+ response struct GetSceneMembershipResponse = 6 {
+ status status = 0;
+ nullable int8u capacity = 1;
+ group_id groupID = 2;
+ optional int8u sceneList[] = 3;
}
- /** On receipt of this command, if the NewMode field matches the Mode field in an entry of the SupportedModes list, the server SHALL set the CurrentMode attribute to the NewMode value, otherwise, the server SHALL respond with an INVALID_COMMAND status response. */
- command ChangeToMode(ChangeToModeRequest): DefaultSuccess = 0;
-}
+ request struct EnhancedAddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
-/** Attributes and commands for configuring the temperature control, and reporting temperature. */
-cluster TemperatureControl = 86 {
- revision 1; // NOTE: Default/not specifically set
+ response struct EnhancedAddSceneResponse = 64 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
- bitmap Feature : bitmap32 {
- kTemperatureNumber = 0x1;
- kTemperatureLevel = 0x2;
- kTemperatureStep = 0x4;
+ request struct EnhancedViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
}
- readonly attribute optional temperature temperatureSetpoint = 0;
- readonly attribute optional temperature minTemperature = 1;
- readonly attribute optional temperature maxTemperature = 2;
- readonly attribute optional temperature step = 3;
- readonly attribute optional int8u selectedTemperatureLevel = 4;
- readonly attribute optional char_string supportedTemperatureLevels[] = 5;
- readonly attribute command_id generatedCommandList[] = 65528;
- readonly attribute command_id acceptedCommandList[] = 65529;
- readonly attribute event_id eventList[] = 65530;
- readonly attribute attrib_id attributeList[] = 65531;
- readonly attribute bitmap32 featureMap = 65532;
- readonly attribute int16u clusterRevision = 65533;
+ response struct EnhancedViewSceneResponse = 65 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
- request struct SetTemperatureRequest {
- optional temperature targetTemperature = 0;
- optional int8u targetTemperatureLevel = 1;
+ request struct CopySceneRequest {
+ CopyModeBitmap mode = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
+ group_id groupIdentifierTo = 3;
+ int8u sceneIdentifierTo = 4;
}
- /** Set Temperature */
- command SetTemperature(SetTemperatureRequest): DefaultSuccess = 0;
+ response struct CopySceneResponse = 66 {
+ status status = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
+ }
+
+ /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
+ fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
+ /** Retrieves the requested scene entry from its Scene table. */
+ fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
+ /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
+ /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
+ /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
+ fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
+ /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
+ fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
+ /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
+ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
+ /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
+ fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
+ /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
+ fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
+ /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
+ fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
}
/** An interface to a generic way to secure a door */
@@ -3564,6 +3564,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -3625,6 +3635,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -3634,6 +3648,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -3672,6 +3691,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -3727,6 +3802,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -3758,14 +3847,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
@@ -5940,6 +6060,9 @@ endpoint 0 {
ram attribute lastNetworkingStatus;
ram attribute lastNetworkID;
ram attribute lastConnectErrorValue;
+ callback attribute supportedWiFiBands;
+ callback attribute supportedThreadFeatures;
+ callback attribute threadVersion;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
@@ -6158,33 +6281,6 @@ endpoint 1 {
handle command AddGroupIfIdentifying;
}
- server cluster Scenes {
- ram attribute nameSupport default = 0x80;
- ram attribute lastConfiguredBy;
- ram attribute sceneTableSize default = 16;
- callback attribute fabricSceneInfo;
- callback attribute generatedCommandList;
- callback attribute acceptedCommandList;
- callback attribute eventList;
- callback attribute attributeList;
- ram attribute featureMap default = 15;
- ram attribute clusterRevision default = 5;
-
- handle command AddScene;
- handle command AddSceneResponse;
- handle command ViewScene;
- handle command ViewSceneResponse;
- handle command RemoveScene;
- handle command RemoveSceneResponse;
- handle command RemoveAllScenes;
- handle command RemoveAllScenesResponse;
- handle command StoreScene;
- handle command StoreSceneResponse;
- handle command RecallScene;
- handle command GetSceneMembership;
- handle command GetSceneMembershipResponse;
- }
-
server cluster OnOff {
persist attribute onOff default = 0x00;
ram attribute globalSceneControl default = 0x01;
@@ -6315,6 +6411,33 @@ endpoint 1 {
handle command SetTemperature;
}
+ server cluster ScenesManagement {
+ ram attribute nameSupport default = 0x80;
+ ram attribute lastConfiguredBy;
+ ram attribute sceneTableSize default = 16;
+ callback attribute fabricSceneInfo;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ ram attribute featureMap default = 15;
+ ram attribute clusterRevision default = 5;
+
+ handle command AddScene;
+ handle command AddSceneResponse;
+ handle command ViewScene;
+ handle command ViewSceneResponse;
+ handle command RemoveScene;
+ handle command RemoveSceneResponse;
+ handle command RemoveAllScenes;
+ handle command RemoveAllScenesResponse;
+ handle command StoreScene;
+ handle command StoreSceneResponse;
+ handle command RecallScene;
+ handle command GetSceneMembership;
+ handle command GetSceneMembershipResponse;
+ }
+
server cluster DoorLock {
emits event DoorLockAlarm;
emits event LockOperation;
@@ -6718,32 +6841,6 @@ endpoint 2 {
handle command AddGroupIfIdentifying;
}
- server cluster Scenes {
- ram attribute nameSupport default = 0x80;
- ram attribute sceneTableSize default = 16;
- callback attribute fabricSceneInfo;
- callback attribute generatedCommandList;
- callback attribute acceptedCommandList;
- callback attribute eventList;
- callback attribute attributeList;
- ram attribute featureMap default = 15;
- ram attribute clusterRevision default = 5;
-
- handle command AddScene;
- handle command AddSceneResponse;
- handle command ViewScene;
- handle command ViewSceneResponse;
- handle command RemoveScene;
- handle command RemoveSceneResponse;
- handle command RemoveAllScenes;
- handle command RemoveAllScenesResponse;
- handle command StoreScene;
- handle command StoreSceneResponse;
- handle command RecallScene;
- handle command GetSceneMembership;
- handle command GetSceneMembershipResponse;
- }
-
server cluster OnOff {
ram attribute onOff default = 0x00;
ram attribute globalSceneControl default = 1;
@@ -6791,6 +6888,32 @@ endpoint 2 {
ram attribute clusterRevision default = 2;
}
+ server cluster ScenesManagement {
+ ram attribute nameSupport default = 0x80;
+ ram attribute sceneTableSize default = 16;
+ callback attribute fabricSceneInfo;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ ram attribute featureMap default = 15;
+ ram attribute clusterRevision default = 5;
+
+ handle command AddScene;
+ handle command AddSceneResponse;
+ handle command ViewScene;
+ handle command ViewSceneResponse;
+ handle command RemoveScene;
+ handle command RemoveSceneResponse;
+ handle command RemoveAllScenes;
+ handle command RemoveAllScenesResponse;
+ handle command StoreScene;
+ handle command StoreSceneResponse;
+ handle command RecallScene;
+ handle command GetSceneMembership;
+ handle command GetSceneMembershipResponse;
+ }
+
server cluster OccupancySensing {
ram attribute occupancy;
ram attribute occupancySensorType;
diff --git a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
index 2ca83ff224c938..5aff52c41cca6b 100644
--- a/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
+++ b/examples/all-clusters-minimal-app/all-clusters-common/all-clusters-minimal-app.zap
@@ -2235,6 +2235,54 @@
"maxInterval": 65534,
"reportableChange": 0
},
+ {
+ "name": "SupportedWiFiBands",
+ "code": 8,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "SupportedThreadFeatures",
+ "code": 9,
+ "mfgCode": null,
+ "side": "server",
+ "type": "ThreadCapabilitiesBitmap",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ThreadVersion",
+ "code": 10,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
{
"name": "GeneratedCommandList",
"code": 65528,
@@ -4551,8 +4599,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "server",
@@ -6851,7 +6899,7 @@
"code": 0,
"mfgCode": null,
"side": "server",
- "type": "int16s",
+ "type": "temperature",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
@@ -6899,7 +6947,7 @@
"code": 28,
"mfgCode": null,
"side": "server",
- "type": "enum8",
+ "type": "SystemModeEnum",
"included": 1,
"storageOption": "RAM",
"singleton": 0,
@@ -10787,8 +10835,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "server",
diff --git a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
index cb38515a1a8770..cae8b64315a232 100644
--- a/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
+++ b/examples/all-clusters-minimal-app/esp32/main/CMakeLists.txt
@@ -81,6 +81,7 @@ set(SRC_DIRS_LIST
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/diagnostic-logs-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/door-lock-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/occupancy-sensor-server"
+ "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/device-energy-management-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/energy-evse-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/ethernet-network-diagnostics-server"
"${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/localization-configuration-server"
diff --git a/examples/all-clusters-minimal-app/telink/CMakeLists.txt b/examples/all-clusters-minimal-app/telink/CMakeLists.txt
index a7bb51ba0e67fe..a68471e379a842 100644
--- a/examples/all-clusters-minimal-app/telink/CMakeLists.txt
+++ b/examples/all-clusters-minimal-app/telink/CMakeLists.txt
@@ -70,10 +70,6 @@ target_include_directories(app PRIVATE
${TELINK_COMMON}/common/include
${TELINK_COMMON}/util/include)
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
${ALL_CLUSTERS_COMMON_DIR}/src/smco-stub.cpp
@@ -90,3 +86,7 @@ chip_configure_data_model(app
INCLUDE_SERVER
ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../all-clusters-common/all-clusters-minimal-app.zap
)
+
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
diff --git a/examples/bridge-app/telink/CMakeLists.txt b/examples/bridge-app/telink/CMakeLists.txt
index 1b65dc3bf543e7..f4da959953def8 100644
--- a/examples/bridge-app/telink/CMakeLists.txt
+++ b/examples/bridge-app/telink/CMakeLists.txt
@@ -69,11 +69,6 @@ target_include_directories(app PRIVATE
${TELINK_COMMON}/util/include
${TELINK_COMMON}/app/include)
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
- -DCHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT=16
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
src/ZclCallbacks.cpp
@@ -90,3 +85,7 @@ chip_configure_data_model(app
INCLUDE_SERVER
ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../bridge-common/bridge-app.zap
)
+
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
diff --git a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter
index 6066dc34eedb2e..df276f6ab3fce3 100644
--- a/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter
+++ b/examples/chef/devices/rootnode_airpurifier_airqualitysensor_temperaturesensor_humiditysensor_thermostat_56de3d5f45.matter
@@ -1177,6 +1177,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -1238,6 +1248,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -1247,6 +1261,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -1285,6 +1304,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -1340,6 +1415,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -1371,14 +1460,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
diff --git a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
index 741d7b25fef7db..ed16842ca4a281 100644
--- a/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
+++ b/examples/chef/devices/rootnode_heatingcoolingunit_ncdGai1E5a.matter
@@ -1534,6 +1534,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -1595,6 +1605,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -1604,6 +1618,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -1642,6 +1661,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -1697,6 +1772,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -1728,14 +1817,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
diff --git a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter
index fb79f75aa6244a..cea46e31fad3fc 100644
--- a/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter
+++ b/examples/chef/devices/rootnode_roboticvacuumcleaner_1807ff0c49.matter
@@ -1005,6 +1005,7 @@ cluster RvcRunMode = 84 {
enum ModeTag : enum16 {
kIdle = 16384;
kCleaning = 16385;
+ kMapping = 16386;
}
enum StatusCode : enum8 {
diff --git a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter
index af70a8875073c9..6797456a6b6091 100644
--- a/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter
+++ b/examples/chef/devices/rootnode_roomairconditioner_9cf3607804.matter
@@ -1117,6 +1117,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -1178,6 +1188,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -1187,6 +1201,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -1225,6 +1244,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -1280,6 +1355,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -1311,14 +1400,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
diff --git a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
index 26bd437442d209..30163a05f14a9a 100644
--- a/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
+++ b/examples/chef/devices/rootnode_thermostat_bm3fb8dhYi.matter
@@ -1337,6 +1337,16 @@ cluster Thermostat = 513 {
kCoolingAndHeatingWithReheat = 5;
}
+ enum PresetScenarioEnum : enum8 {
+ kUnspecified = 0;
+ kOccupied = 1;
+ kUnoccupied = 2;
+ kSleep = 3;
+ kWake = 4;
+ kVacation = 5;
+ kUserDefined = 6;
+ }
+
enum SetpointChangeSourceEnum : enum8 {
kManual = 0;
kSchedule = 1;
@@ -1398,6 +1408,10 @@ cluster Thermostat = 513 {
kSetback = 0x10;
kAutoMode = 0x20;
kLocalTemperatureNotExposed = 0x40;
+ kMatterScheduleConfiguration = 0x80;
+ kPresets = 0x100;
+ kSetpoints = 0x200;
+ kQueuedPresetsSupported = 0x400;
}
bitmap HVACSystemTypeBitmap : bitmap8 {
@@ -1407,6 +1421,11 @@ cluster Thermostat = 513 {
kHeatingUsesFuel = 0x20;
}
+ bitmap PresetTypeFeaturesBitmap : bitmap16 {
+ kAutomatic = 0x1;
+ kSupportsNames = 0x2;
+ }
+
bitmap ProgrammingOperationModeBitmap : bitmap8 {
kScheduleActive = 0x1;
kAutoRecovery = 0x2;
@@ -1445,6 +1464,62 @@ cluster Thermostat = 513 {
kCoolSetpointPresent = 0x2;
}
+ bitmap ScheduleTypeFeaturesBitmap : bitmap16 {
+ kSupportsPresets = 0x1;
+ kSupportsSetpoints = 0x2;
+ kSupportsNames = 0x4;
+ kSupportsOff = 0x8;
+ }
+
+ bitmap TemperatureSetpointHoldPolicyBitmap : bitmap8 {
+ kHoldDurationElapsed = 0x1;
+ kHoldDurationElapsedOrPresetChanged = 0x2;
+ }
+
+ struct ScheduleTransitionStruct {
+ ScheduleDayOfWeekBitmap dayOfWeek = 0;
+ int16u transitionTime = 1;
+ optional octet_string<16> presetHandle = 2;
+ optional SystemModeEnum systemMode = 3;
+ optional temperature coolingSetpoint = 4;
+ optional temperature heatingSetpoint = 5;
+ }
+
+ struct ScheduleStruct {
+ nullable octet_string<16> scheduleHandle = 0;
+ SystemModeEnum systemMode = 1;
+ optional char_string<64> name = 2;
+ optional octet_string<16> presetHandle = 3;
+ ScheduleTransitionStruct transitions[] = 4;
+ optional nullable boolean builtIn = 5;
+ }
+
+ struct PresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ PresetScenarioEnum presetScenario = 1;
+ optional nullable char_string<64> name = 2;
+ optional temperature coolingSetpoint = 3;
+ optional temperature heatingSetpoint = 4;
+ nullable boolean builtIn = 5;
+ }
+
+ struct PresetTypeStruct {
+ PresetScenarioEnum presetScenario = 0;
+ int8u numberOfPresets = 1;
+ PresetTypeFeaturesBitmap presetTypeFeatures = 2;
+ }
+
+ struct QueuedPresetStruct {
+ nullable octet_string<16> presetHandle = 0;
+ nullable epoch_s transitionTimestamp = 1;
+ }
+
+ struct ScheduleTypeStruct {
+ SystemModeEnum systemMode = 0;
+ int8u numberOfSchedules = 1;
+ ScheduleTypeFeaturesBitmap scheduleTypeFeatures = 2;
+ }
+
struct WeeklyScheduleTransitionStruct {
int16u transitionTime = 0;
nullable temperature heatSetpoint = 1;
@@ -1500,6 +1575,20 @@ cluster Thermostat = 513 {
attribute access(write: manage) optional ACLouverPositionEnum ACLouverPosition = 69;
readonly attribute optional nullable temperature ACCoilTemperature = 70;
attribute access(write: manage) optional ACCapacityFormatEnum ACCapacityformat = 71;
+ readonly attribute optional PresetTypeStruct presetTypes[] = 72;
+ readonly attribute optional ScheduleTypeStruct scheduleTypes[] = 73;
+ readonly attribute optional int8u numberOfPresets = 74;
+ readonly attribute optional int8u numberOfSchedules = 75;
+ readonly attribute optional int8u numberOfScheduleTransitions = 76;
+ readonly attribute optional nullable int8u numberOfScheduleTransitionPerDay = 77;
+ readonly attribute optional nullable octet_string<16> activePresetHandle = 78;
+ readonly attribute optional nullable octet_string<16> activeScheduleHandle = 79;
+ attribute access(write: manage) optional PresetStruct presets[] = 80;
+ attribute access(write: manage) optional ScheduleStruct schedules[] = 81;
+ readonly attribute optional boolean presetsSchedulesEditable = 82;
+ readonly attribute optional TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 83;
+ readonly attribute optional nullable epoch_s setpointHoldExpiryTimestamp = 84;
+ readonly attribute optional nullable QueuedPresetStruct queuedPreset = 85;
readonly attribute command_id generatedCommandList[] = 65528;
readonly attribute command_id acceptedCommandList[] = 65529;
readonly attribute event_id eventList[] = 65530;
@@ -1531,14 +1620,45 @@ cluster Thermostat = 513 {
ScheduleModeBitmap modeToReturn = 1;
}
+ request struct SetActiveScheduleRequestRequest {
+ octet_string<16> scheduleHandle = 0;
+ }
+
+ request struct SetActivePresetRequestRequest {
+ octet_string<16> presetHandle = 0;
+ optional int16u delayMinutes = 1;
+ }
+
+ request struct StartPresetsSchedulesEditRequestRequest {
+ int16u timeoutSeconds = 0;
+ }
+
+ request struct SetTemperatureSetpointHoldPolicyRequest {
+ TemperatureSetpointHoldPolicyBitmap temperatureSetpointHoldPolicy = 0;
+ }
+
/** Command description for SetpointRaiseLower */
command SetpointRaiseLower(SetpointRaiseLowerRequest): DefaultSuccess = 0;
/** Command description for SetWeeklySchedule */
command access(invoke: manage) SetWeeklySchedule(SetWeeklyScheduleRequest): DefaultSuccess = 1;
/** Command description for GetWeeklySchedule */
command GetWeeklySchedule(GetWeeklyScheduleRequest): GetWeeklyScheduleResponse = 2;
- /** The Clear Weekly Schedule command is used to clear the weekly schedule. */
+ /** This command is used to clear the weekly schedule. The ClearWeeklySchedule command has no payload. */
command access(invoke: manage) ClearWeeklySchedule(): DefaultSuccess = 3;
+ /** This command is used to set the active schedule. */
+ command SetActiveScheduleRequest(SetActiveScheduleRequestRequest): DefaultSuccess = 5;
+ /** This command is used to set the active preset. */
+ command SetActivePresetRequest(SetActivePresetRequestRequest): DefaultSuccess = 6;
+ /** This command is used to start editing the presets and schedules. */
+ command access(invoke: manage) StartPresetsSchedulesEditRequest(StartPresetsSchedulesEditRequestRequest): DefaultSuccess = 7;
+ /** This command is used to cancel editing presets and schedules. */
+ command access(invoke: manage) CancelPresetsSchedulesEditRequest(): DefaultSuccess = 8;
+ /** This command is used to notify the server that all edits are done and should be committed. */
+ command access(invoke: manage) CommitPresetsSchedulesRequest(): DefaultSuccess = 9;
+ /** This command is sent to cancel a queued preset. */
+ command access(invoke: manage) CancelSetActivePresetRequest(): DefaultSuccess = 10;
+ /** This command sets the set point hold policy. */
+ command SetTemperatureSetpointHoldPolicy(SetTemperatureSetpointHoldPolicyRequest): DefaultSuccess = 11;
}
/** An interface for controlling a fan in a heating/cooling system. */
diff --git a/examples/chef/devices/template.zap b/examples/chef/devices/template.zap
index c53936a568b663..7987c79179e375 100644
--- a/examples/chef/devices/template.zap
+++ b/examples/chef/devices/template.zap
@@ -2276,8 +2276,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "server",
diff --git a/examples/chef/telink/CMakeLists.txt b/examples/chef/telink/CMakeLists.txt
index 7722f26a11d96e..5d30d424ea3dfd 100755
--- a/examples/chef/telink/CMakeLists.txt
+++ b/examples/chef/telink/CMakeLists.txt
@@ -92,10 +92,6 @@ if (CONFIG_CHIP_LIB_SHELL)
)
endif()
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
${TELINK_COMMON}/common/src/mainCommon.cpp
@@ -113,6 +109,10 @@ chip_configure_data_model(app
ZAP_FILE ${CHEF}/devices/${SAMPLE_NAME}.zap
)
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
+
if (CONFIG_CHIP_PW_RPC)
# Make all targets created below depend on zephyr_interface to inherit MCU-related compilation flags
diff --git a/examples/contact-sensor-app/telink/CMakeLists.txt b/examples/contact-sensor-app/telink/CMakeLists.txt
index 128d7afbf89744..c29ef949914036 100755
--- a/examples/contact-sensor-app/telink/CMakeLists.txt
+++ b/examples/contact-sensor-app/telink/CMakeLists.txt
@@ -68,10 +68,6 @@ target_include_directories(app PRIVATE
${TELINK_COMMON}/common/include
${TELINK_COMMON}/util/include)
-add_definitions(
- "-DCHIP_ADDRESS_RESOLVE_IMPL_INCLUDE_HEADER="
-)
-
target_sources(app PRIVATE
src/AppTask.cpp
src/ContactSensorManager.cpp
@@ -87,3 +83,7 @@ chip_configure_data_model(app
INCLUDE_SERVER
ZAP_FILE ${CMAKE_CURRENT_SOURCE_DIR}/../contact-sensor-common/contact-sensor-app.zap
)
+
+if(CONFIG_BOOTLOADER_MCUBOOT)
+ target_sources(app PRIVATE ${TELINK_COMMON}/util/src/OTAUtil.cpp)
+endif()
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 d48a22c42cc51e..753c428234a038 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
@@ -900,6 +900,185 @@ cluster GroupKeyManagement = 63 {
fabric command access(invoke: administer) KeySetReadAllIndices(): KeySetReadAllIndicesResponse = 4;
}
+/** 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;
+
+ enum CauseEnum : enum8 {
+ kNormalCompletion = 0;
+ kOffline = 1;
+ kFault = 2;
+ kUserOptOut = 3;
+ }
+
+ enum CostTypeEnum : enum8 {
+ kFinancial = 0;
+ kGHGEmissions = 1;
+ kComfort = 2;
+ kTemperature = 3;
+ }
+
+ enum ESAStateEnum : enum8 {
+ kOffline = 0;
+ kOnline = 1;
+ kFault = 2;
+ kUserOptOut = 3;
+ kPowerAdjustActive = 4;
+ kPaused = 5;
+ }
+
+ enum ESATypeEnum : enum8 {
+ kEVSE = 0;
+ kSpaceHeating = 1;
+ kWaterHeating = 2;
+ kSpaceCooling = 3;
+ kSpaceHeatingCooling = 4;
+ kBatteryStorage = 5;
+ kSolarPV = 6;
+ kFridgeFreezer = 7;
+ kWashingMachine = 8;
+ kDishwasher = 9;
+ kCooking = 10;
+ kHomeWaterPump = 11;
+ kIrrigationWaterPump = 12;
+ kPoolPump = 13;
+ kOther = 255;
+ }
+
+ bitmap Feature : bitmap32 {
+ kPowerAdjustment = 0x1;
+ kPowerForecastReporting = 0x2;
+ kStateForecastReporting = 0x4;
+ kForecastAdjustment = 0x8;
+ }
+
+ struct CostStruct {
+ CostTypeEnum costType = 0;
+ int32s value = 1;
+ int8u decimalPoints = 2;
+ optional int16u currency = 3;
+ }
+
+ struct SlotStruct {
+ elapsed_s minDuration = 0;
+ elapsed_s maxDuration = 1;
+ elapsed_s defaultDuration = 2;
+ elapsed_s elapsedSlotTime = 3;
+ elapsed_s remainingSlotTime = 4;
+ boolean slotIsPauseable = 5;
+ elapsed_s minPauseDuration = 6;
+ elapsed_s maxPauseDuration = 7;
+ optional int16u manufacturerESAState = 8;
+ optional power_mw nominalPower = 9;
+ optional power_mw minPower = 10;
+ optional power_mw maxPower = 11;
+ optional energy_mwh nominalEnergy = 12;
+ optional CostStruct costs[] = 13;
+ optional power_mw minPowerAdjustment = 14;
+ optional power_mw maxPowerAdjustment = 15;
+ optional elapsed_s minDurationAdjustment = 16;
+ optional elapsed_s maxDurationAdjustment = 17;
+ }
+
+ struct ForecastStruct {
+ int16u forecastId = 0;
+ nullable int16u activeSlotNumber = 1;
+ epoch_s startTime = 2;
+ epoch_s endTime = 3;
+ optional nullable epoch_s earliestStartTime = 4;
+ optional epoch_s latestEndTime = 5;
+ boolean isPauseable = 6;
+ SlotStruct slots[] = 7;
+ }
+
+ struct ConstraintsStruct {
+ epoch_s startTime = 0;
+ elapsed_s duration = 1;
+ optional power_mw nominalPower = 2;
+ optional energy_mwh maximumEnergy = 3;
+ optional int8s loadControl = 4;
+ }
+
+ struct PowerAdjustStruct {
+ power_mw minPower = 0;
+ power_mw maxPower = 1;
+ elapsed_s minDuration = 2;
+ elapsed_s maxDuration = 3;
+ }
+
+ struct SlotAdjustmentStruct {
+ int8u slotIndex = 0;
+ power_mw nominalPower = 1;
+ elapsed_s duration = 2;
+ }
+
+ info event PowerAdjustStart = 0 {
+ }
+
+ info event PowerAdjustEnd = 1 {
+ CauseEnum cause = 0;
+ elapsed_s duration = 1;
+ energy_mwh energyUse = 2;
+ }
+
+ info event Paused = 2 {
+ }
+
+ info event Resumed = 3 {
+ }
+
+ readonly attribute ESATypeEnum ESAType = 0;
+ readonly attribute boolean ESACanGenerate = 1;
+ readonly attribute ESAStateEnum ESAState = 2;
+ readonly attribute power_mw absMinPower = 3;
+ readonly attribute power_mw absMaxPower = 4;
+ readonly attribute optional nullable PowerAdjustStruct powerAdjustmentCapability[] = 5;
+ readonly attribute optional nullable ForecastStruct forecast = 6;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct PowerAdjustRequestRequest {
+ power_mw power = 0;
+ elapsed_s duration = 1;
+ }
+
+ request struct StartTimeAdjustRequestRequest {
+ epoch_s requestedStartTime = 0;
+ }
+
+ request struct PauseRequestRequest {
+ elapsed_s duration = 0;
+ }
+
+ request struct ModifyForecastRequestRequest {
+ int32u forecastId = 0;
+ SlotAdjustmentStruct slotAdjustments[] = 1;
+ }
+
+ request struct RequestConstraintBasedForecastRequest {
+ ConstraintsStruct constraints[] = 0;
+ }
+
+ /** Allows a client to request an adjustment in the power consumption of an ESA for a specified duration. */
+ command PowerAdjustRequest(PowerAdjustRequestRequest): DefaultSuccess = 0;
+ /** Allows a client to cancel an ongoing PowerAdjustmentRequest operation. */
+ command CancelPowerAdjustRequest(): DefaultSuccess = 1;
+ /** 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). */
+ command StartTimeAdjustRequest(StartTimeAdjustRequestRequest): DefaultSuccess = 2;
+ /** Allows a client to temporarily pause an operation and reduce the ESAs energy demand. */
+ command PauseRequest(PauseRequestRequest): DefaultSuccess = 3;
+ /** Allows a client to cancel the PauseRequest command and enable earlier resumption of operation. */
+ command ResumeRequest(): DefaultSuccess = 4;
+ /** Allows a client to modify a Forecast within the limits allowed by the ESA. */
+ 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;
+}
+
/** 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. */
provisional cluster EnergyEvse = 153 {
revision 2;
@@ -1290,6 +1469,34 @@ endpoint 1 {
callback attribute clusterRevision;
}
+ server cluster DeviceEnergyManagement {
+ emits event PowerAdjustStart;
+ emits event PowerAdjustEnd;
+ emits event Paused;
+ emits event Resumed;
+ callback attribute ESAType;
+ callback attribute ESACanGenerate;
+ callback attribute ESAState;
+ callback attribute absMinPower;
+ callback attribute absMaxPower;
+ callback attribute powerAdjustmentCapability;
+ callback attribute forecast;
+ callback attribute generatedCommandList;
+ callback attribute acceptedCommandList;
+ callback attribute eventList;
+ callback attribute attributeList;
+ callback attribute featureMap;
+ ram attribute clusterRevision default = 2;
+
+ handle command PowerAdjustRequest;
+ handle command CancelPowerAdjustRequest;
+ handle command StartTimeAdjustRequest;
+ handle command PauseRequest;
+ handle command ResumeRequest;
+ handle command ModifyForecastRequest;
+ handle command RequestConstraintBasedForecast;
+ }
+
server cluster EnergyEvse {
emits event EVConnected;
emits event EVNotDetected;
@@ -1300,33 +1507,33 @@ endpoint 1 {
callback attribute state;
callback attribute supplyState;
callback attribute faultState;
- callback attribute chargingEnabledUntil default = 0;
- callback attribute dischargingEnabledUntil default = 0;
- callback attribute circuitCapacity default = 0;
- callback attribute minimumChargeCurrent default = 6000;
- callback attribute maximumChargeCurrent default = 0;
- callback attribute maximumDischargeCurrent default = 0;
- callback attribute userMaximumChargeCurrent default = 0;
- callback attribute randomizationDelayWindow default = 600;
+ callback attribute chargingEnabledUntil;
+ callback attribute dischargingEnabledUntil;
+ callback attribute circuitCapacity;
+ callback attribute minimumChargeCurrent;
+ callback attribute maximumChargeCurrent;
+ callback attribute maximumDischargeCurrent;
+ callback attribute userMaximumChargeCurrent;
+ callback attribute randomizationDelayWindow;
callback attribute numberOfWeeklyTargets default = 0;
callback attribute numberOfDailyTargets default = 1;
callback attribute nextChargeStartTime;
callback attribute nextChargeTargetTime;
callback attribute nextChargeRequiredEnergy;
callback attribute nextChargeTargetSoC;
- callback attribute approximateEVEfficiency default = 0xFFFF;
+ callback attribute approximateEVEfficiency;
callback attribute stateOfCharge;
callback attribute batteryCapacity;
callback attribute vehicleID;
- callback attribute sessionID default = 0;
- callback attribute sessionDuration default = 0;
- callback attribute sessionEnergyCharged default = 0;
- callback attribute sessionEnergyDischarged default = 0;
+ callback attribute sessionID;
+ callback attribute sessionDuration;
+ callback attribute sessionEnergyCharged;
+ callback attribute sessionEnergyDischarged;
callback attribute generatedCommandList;
callback attribute acceptedCommandList;
callback attribute eventList;
callback attribute attributeList;
- ram attribute featureMap default = 1;
+ callback attribute featureMap;
ram attribute clusterRevision default = 2;
handle command GetTargetsResponse;
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 55d62101227dab..8ed4aa6e2167d7 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
@@ -2517,6 +2517,313 @@
}
]
},
+ {
+ "name": "Device Energy Management",
+ "code": 152,
+ "mfgCode": null,
+ "define": "DEVICE_ENERGY_MANAGEMENT_CLUSTER",
+ "side": "server",
+ "enabled": 1,
+ "apiMaturity": "provisional",
+ "commands": [
+ {
+ "name": "PowerAdjustRequest",
+ "code": 0,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "CancelPowerAdjustRequest",
+ "code": 1,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "StartTimeAdjustRequest",
+ "code": 2,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "PauseRequest",
+ "code": 3,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "ResumeRequest",
+ "code": 4,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "ModifyForecastRequest",
+ "code": 5,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ },
+ {
+ "name": "RequestConstraintBasedForecast",
+ "code": 6,
+ "mfgCode": null,
+ "source": "client",
+ "isIncoming": 1,
+ "isEnabled": 1
+ }
+ ],
+ "attributes": [
+ {
+ "name": "ESAType",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "type": "ESATypeEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ESACanGenerate",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "type": "boolean",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ESAState",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "type": "ESAStateEnum",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AbsMinPower",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "type": "power_mw",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AbsMaxPower",
+ "code": 4,
+ "mfgCode": null,
+ "side": "server",
+ "type": "power_mw",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "PowerAdjustmentCapability",
+ "code": 5,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "Forecast",
+ "code": 6,
+ "mfgCode": null,
+ "side": "server",
+ "type": "ForecastStruct",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "GeneratedCommandList",
+ "code": 65528,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AcceptedCommandList",
+ "code": 65529,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "EventList",
+ "code": 65530,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "AttributeList",
+ "code": 65531,
+ "mfgCode": null,
+ "side": "server",
+ "type": "array",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": null,
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "FeatureMap",
+ "code": 65532,
+ "mfgCode": null,
+ "side": "server",
+ "type": "bitmap32",
+ "included": 1,
+ "storageOption": "External",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "0",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ },
+ {
+ "name": "ClusterRevision",
+ "code": 65533,
+ "mfgCode": null,
+ "side": "server",
+ "type": "int16u",
+ "included": 1,
+ "storageOption": "RAM",
+ "singleton": 0,
+ "bounded": 0,
+ "defaultValue": "2",
+ "reportable": 1,
+ "minInterval": 1,
+ "maxInterval": 65534,
+ "reportableChange": 0
+ }
+ ],
+ "events": [
+ {
+ "name": "PowerAdjustStart",
+ "code": 0,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ },
+ {
+ "name": "PowerAdjustEnd",
+ "code": 1,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ },
+ {
+ "name": "Paused",
+ "code": 2,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ },
+ {
+ "name": "Resumed",
+ "code": 3,
+ "mfgCode": null,
+ "side": "server",
+ "included": 1
+ }
+ ]
+ },
{
"name": "Energy EVSE",
"code": 153,
@@ -3063,7 +3370,7 @@
"side": "server",
"type": "bitmap32",
"included": 1,
- "storageOption": "RAM",
+ "storageOption": "External",
"singleton": 0,
"bounded": 0,
"defaultValue": "1",
diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h
new file mode 100644
index 00000000000000..464a683510b3d7
--- /dev/null
+++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementDelegateImpl.h
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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 "app/clusters/device-energy-management-server/device-energy-management-server.h"
+
+#include
+#include
+#include
+
+using chip::Protocols::InteractionModel::Status;
+namespace chip {
+namespace app {
+namespace Clusters {
+namespace DeviceEnergyManagement {
+
+/**
+ * The application delegate.
+ */
+class DeviceEnergyManagementDelegate : public DeviceEnergyManagement::Delegate
+{
+public:
+ virtual Status PowerAdjustRequest(const int64_t power, const uint32_t duration) override;
+ virtual Status CancelPowerAdjustRequest() override;
+ virtual Status StartTimeAdjustRequest(const uint32_t requestedStartTime) override;
+ virtual Status PauseRequest(const uint32_t duration) 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;
+
+ // ------------------------------------------------------------------
+ // Get attribute methods
+ virtual ESATypeEnum GetESAType() override;
+ virtual bool GetESACanGenerate() override;
+ virtual ESAStateEnum GetESAState() override;
+ virtual int64_t GetAbsMinPower() override;
+ virtual int64_t GetAbsMaxPower() override;
+ virtual Attributes::PowerAdjustmentCapability::TypeInfo::Type GetPowerAdjustmentCapability() override;
+ virtual DataModel::Nullable GetForecast() override;
+
+ // ------------------------------------------------------------------
+ // Set attribute methods
+ virtual CHIP_ERROR SetESAType(ESATypeEnum) override;
+ virtual CHIP_ERROR SetESACanGenerate(bool) override;
+ virtual CHIP_ERROR SetESAState(ESAStateEnum) override;
+ virtual CHIP_ERROR SetAbsMinPower(int64_t) override;
+ virtual CHIP_ERROR SetAbsMaxPower(int64_t) override;
+ virtual CHIP_ERROR SetPowerAdjustmentCapability(Attributes::PowerAdjustmentCapability::TypeInfo::Type) override;
+ virtual CHIP_ERROR SetForecast(DataModel::Nullable) override;
+
+private:
+ ESATypeEnum mEsaType;
+ bool mEsaCanGenerate;
+ ESAStateEnum mEsaState;
+ int64_t mAbsMinPower;
+ int64_t mAbsMaxPower;
+ Attributes::PowerAdjustmentCapability::TypeInfo::Type mPowerAdjustmentCapability;
+ DataModel::Nullable mForecast;
+};
+
+} // namespace DeviceEnergyManagement
+} // namespace Clusters
+} // namespace app
+} // namespace chip
diff --git a/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h
new file mode 100644
index 00000000000000..6d131dd4ae90fa
--- /dev/null
+++ b/examples/energy-management-app/energy-management-common/include/DeviceEnergyManagementManager.h
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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
+#include
+
+namespace chip {
+namespace app {
+namespace Clusters {
+
+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)
+ {
+ mDelegate = &aDelegate;
+ }
+
+ // Delete copy constructor and assignment operator.
+ DeviceEnergyManagementManager(const DeviceEnergyManagementManager &) = delete;
+ DeviceEnergyManagementManager(const DeviceEnergyManagementManager &&) = delete;
+ DeviceEnergyManagementManager & operator=(const DeviceEnergyManagementManager &) = delete;
+
+ CHIP_ERROR Init();
+ void Shutdown();
+
+ DeviceEnergyManagementDelegate * GetDelegate() { return mDelegate; };
+
+private:
+ DeviceEnergyManagementDelegate * mDelegate;
+};
+
+} // namespace Clusters
+} // namespace app
+} // namespace chip
diff --git a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h
index 5bdac2f8e853d6..7d288809952ee3 100644
--- a/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h
+++ b/examples/energy-management-app/energy-management-common/include/EVSECallbacks.h
@@ -30,26 +30,41 @@ using namespace chip::app::Clusters::EnergyEvse;
* This is not specific to the EnergyEVSE cluster, but includes DeviceEnergyManagement
* and potential future clusters.
*/
-enum EVSECallbackType
+enum class EVSECallbackType : uint8_t
{
/*
* The State has changed (e.g. from Disabled to Charging, or vice-versa)
*/
StateChanged,
/*
- * ChargeCurrent has changed
+ * ChargeCurrent has changed (e.g. maxChargingCurrent so requires an
+ update to advertise a different charging current to the EV)
*/
ChargeCurrentChanged,
/*
* Charging Preferences have changed
+ * The daily charging target time, SoC / Added Energy schedules have changed
+ * and may require the local optimiser to re-run.
*/
ChargingPreferencesChanged,
/*
- * DeviceEnergyManagement has changed
+ * Energy Meter Reading requested from the hardware, e.g. so that the session
+ * information can be updated.
+ */
+ EnergyMeterReadingRequested,
+ /*
+ * The associated DeviceEnergyManagement cluster has changed. This may mean
+ * that the start time, or power profile or power levels have been adjusted
*/
DeviceEnergyManagementChanged,
};
+enum class ChargingDischargingType : uint8_t
+{
+ kCharging,
+ kDischarging
+};
+
struct EVSECbInfo
{
EVSECallbackType type;
@@ -68,6 +83,13 @@ struct EVSECbInfo
{
int64_t maximumChargeCurrent;
} ChargingCurrent;
+
+ /* for type = EnergyMeterReadingRequested */
+ struct
+ {
+ ChargingDischargingType meterType;
+ int64_t * energyMeterValuePtr;
+ } EnergyMeterReadingRequest;
};
};
diff --git a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h
index 4ff45e925674aa..df757f7374e672 100644
--- a/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h
+++ b/examples/energy-management-app/energy-management-common/include/EVSEManufacturerImpl.h
@@ -18,6 +18,7 @@
#pragma once
+#include
#include
using chip::Protocols::InteractionModel::Status;
@@ -33,15 +34,26 @@ namespace EnergyEvse {
class EVSEManufacturer
{
public:
+ EVSEManufacturer(EnergyEvseManager * aInstance) { mInstance = aInstance; }
+ EnergyEvseManager * GetInstance() { return mInstance; }
+ EnergyEvseDelegate * GetDelegate()
+ {
+ if (mInstance)
+ {
+ return mInstance->GetDelegate();
+ }
+ return nullptr;
+ }
+
/**
* @brief Called at start up to apply hardware settings
*/
- CHIP_ERROR Init(EnergyEvseManager * aInstance);
+ CHIP_ERROR Init();
/**
* @brief Called at shutdown
*/
- CHIP_ERROR Shutdown(EnergyEvseManager * aInstance);
+ CHIP_ERROR Shutdown();
/**
* @brief Main Callback handler from delegate to user code
@@ -49,8 +61,23 @@ class EVSEManufacturer
static void ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg);
private:
+ EnergyEvseManager * mInstance;
+
+ int64_t mLastChargingEnergyMeter = 0;
+ int64_t mLastDischargingEnergyMeter = 0;
};
+/** @brief Helper function to return the singleton EVSEManufacturer instance
+ *
+ * This is needed by the EVSEManufacturer class to support TestEventTriggers
+ * which are called outside of any class context. This allows the EVSEManufacturer
+ * class to return the relevant Delegate instance in which to invoke the test
+ * events on.
+ *
+ * This function is typically found in main.cpp or wherever the singleton is created.
+ */
+EVSEManufacturer * GetEvseManufacturer();
+
} // namespace EnergyEvse
} // namespace Clusters
} // namespace app
diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h
index f3c003d081fc6e..d27f35ee63201c 100644
--- a/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h
+++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseDelegateImpl.h
@@ -31,6 +31,68 @@ namespace app {
namespace Clusters {
namespace EnergyEvse {
+/* Local state machine Events to allow simpler handling of state transitions */
+enum EVSEStateMachineEvent
+{
+ EVPluggedInEvent, /* EV has been plugged in */
+ EVNotDetectedEvent, /* EV has been unplugged or detected as not connected */
+ EVNoDemandEvent, /* EV has stopped asking for demand */
+ EVDemandEvent, /* EV has asked for demand*/
+ ChargingEnabledEvent, /* Charging has been enabled */
+ DischargingEnabledEvent, /* Discharging has been enabled */
+ DisabledEvent, /* EVSE has been disabled */
+ FaultRaised, /* Fault has been raised */
+ FaultCleared, /* Fault has been cleared */
+};
+
+/**
+ * Helper class to handle all of the session related info
+ */
+class EvseSession
+{
+public:
+ EvseSession(EndpointId aEndpoint) { mEndpointId = aEndpoint; }
+ /**
+ * @brief This function records the start time and provided energy meter values as part of the new session.
+ *
+ * @param chargingMeterValue - The current value of the energy meter (charging) in mWh
+ * @param dischargingMeterValue - The current value of the energy meter (discharging) in mWh
+ */
+ void StartSession(int64_t chargingMeterValue, int64_t dischargingMeterValue);
+
+ /**
+ * @brief This function updates the session Duration to allow read attributes to return latest values
+ */
+ void RecalculateSessionDuration();
+
+ /**
+ * @brief This function updates the EnergyCharged meter value
+ *
+ * @param chargingMeterValue - The value of the energy meter (charging) in mWh
+ */
+ void UpdateEnergyCharged(int64_t chargingMeterValue);
+
+ /**
+ * @brief This function updates the EnergyDischarged meter value
+ *
+ * @param dischargingMeterValue - The value of the energy meter (discharging) in mWh
+ */
+ void UpdateEnergyDischarged(int64_t dischargingMeterValue);
+
+ /* Public members - represent attributes in the cluster */
+ DataModel::Nullable mSessionID;
+ DataModel::Nullable mSessionDuration;
+ DataModel::Nullable mSessionEnergyCharged;
+ DataModel::Nullable mSessionEnergyDischarged;
+
+private:
+ EndpointId mEndpointId = 0;
+
+ uint32_t mStartTime = 0; // Epoch_s - 0 means it hasn't started yet
+ int64_t mSessionEnergyChargedAtStart = 0; // in mWh - 0 means it hasn't been set yet
+ int64_t mSessionEnergyDischargedAtStart = 0; // in mWh - 0 means it hasn't been set yet
+};
+
/**
* The application delegate.
*/
@@ -74,15 +136,41 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
*/
Status HwRegisterEvseCallbackHandler(EVSECallbackFunc handler, intptr_t arg);
+ /**
+ * @brief Decides if a timer is needed based on EVSE state and sets a callback if needed
+ *
+ * In order to ensure the EVSE restarts charging (if enabled) after power loss
+ * this should be called after the EVSE is initialised
+ * (e.g. HwSetMaxHardwareCurrentLimit and HwSetCircuitCapacity have been called)
+ * and the persisted attributes have been loaded, and time has been synchronised.
+ *
+ * If time isn't sync'd yet it will call itself back periodically (if required)
+ * until time is sync'd.
+ *
+ * It is also called when a EnableCharging or EnableDischarging command
+ * is recv'd to schedule when the EVSE should be automatically disabled based
+ * on ChargingEnabledUntil / DischargingEnabledUntil expiring.
+ */
+ Status ScheduleCheckOnEnabledTimeout();
+
// -----------------------------------------------------------------
// Internal API to allow an EVSE to change its internal state etc
Status HwSetMaxHardwareCurrentLimit(int64_t currentmA);
+ int64_t HwGetMaxHardwareCurrentLimit() { return mMaxHardwareCurrentLimit; }
Status HwSetCircuitCapacity(int64_t currentmA);
Status HwSetCableAssemblyLimit(int64_t currentmA);
+ int64_t HwGetCableAssemblyLimit() { return mCableAssemblyCurrentLimit; }
Status HwSetState(StateEnum state);
+ StateEnum HwGetState() { return mHwState; };
Status HwSetFault(FaultStateEnum fault);
Status HwSetRFID(ByteSpan uid);
Status HwSetVehicleID(const CharSpan & vehID);
+ Status HwDiagnosticsComplete();
+ Status SendEVConnectedEvent();
+ Status SendEVNotDetectedEvent();
+ Status SendEnergyTransferStartedEvent();
+ Status SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum reason);
+ Status SendFaultEvent(FaultStateEnum newFaultState);
// ------------------------------------------------------------------
// Get attribute methods
@@ -96,10 +184,10 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
CHIP_ERROR SetFaultState(FaultStateEnum);
DataModel::Nullable GetChargingEnabledUntil() override;
- CHIP_ERROR SetChargingEnabledUntil(uint32_t);
+ CHIP_ERROR SetChargingEnabledUntil(DataModel::Nullable);
DataModel::Nullable GetDischargingEnabledUntil() override;
- CHIP_ERROR SetDischargingEnabledUntil(uint32_t);
+ CHIP_ERROR SetDischargingEnabledUntil(DataModel::Nullable);
int64_t GetCircuitCapacity() override;
CHIP_ERROR SetCircuitCapacity(int64_t);
@@ -128,7 +216,7 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
DataModel::Nullable GetNextChargeTargetSoC() override;
DataModel::Nullable GetApproximateEVEfficiency() override;
- CHIP_ERROR SetApproximateEVEfficiency(uint16_t) override;
+ CHIP_ERROR SetApproximateEVEfficiency(DataModel::Nullable) override;
/* SOC attributes */
DataModel::Nullable GetStateOfCharge() override;
@@ -143,10 +231,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
private:
/* Constants */
- static constexpr int DEFAULT_MIN_CHARGE_CURRENT = 6000; /* 6A */
- static constexpr int DEFAULT_USER_MAXIMUM_CHARGE_CURRENT = kMaximumChargeCurrent; /* 80A */
- static constexpr int DEFAULT_RANDOMIZATION_DELAY_WINDOW = 600; /* 600s */
- static constexpr int kMaxVehicleIDBufSize = 32;
+ static constexpr int kDefaultMinChargeCurrent = 6000; /* 6A */
+ static constexpr int kDefaultUserMaximumChargeCurrent = kMaximumChargeCurrent; /* 80A */
+ static constexpr int kDefaultRandomizationDelayWindow = 600; /* 600s */
+ static constexpr int kMaxVehicleIDBufSize = 32;
+ static constexpr int kPeriodicCheckIntervalRealTimeClockNotSynced = 30;
/* private variables for controlling the hardware - these are not attributes */
int64_t mMaxHardwareCurrentLimit = 0; /* Hardware current limit in mA */
@@ -155,16 +244,42 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
int64_t mActualChargingCurrentLimit = 0;
StateEnum mHwState = StateEnum::kNotPluggedIn; /* Hardware state */
+ /* Variables to hold State and SupplyState in case a fault is raised */
+ StateEnum mStateBeforeFault = StateEnum::kUnknownEnumValue;
+ SupplyStateEnum mSupplyStateBeforeFault = SupplyStateEnum::kUnknownEnumValue;
+
/* Callback related */
EVSECallbackWrapper mCallbacks = { .handler = nullptr, .arg = 0 }; /* Wrapper to allow callbacks to be registered */
Status NotifyApplicationCurrentLimitChange(int64_t maximumChargeCurrent);
Status NotifyApplicationStateChange();
+ Status GetEVSEEnergyMeterValue(ChargingDischargingType meterType, int64_t & aMeterValue);
+
+ /* Local State machine handling */
+ Status CheckFaultOrDiagnostic();
+ Status HandleStateMachineEvent(EVSEStateMachineEvent event);
+ Status HandleEVPluggedInEvent();
+ Status HandleEVNotDetectedEvent();
+ Status HandleEVNoDemandEvent();
+ Status HandleEVDemandEvent();
+ Status HandleChargingEnabledEvent();
+ Status HandleDischargingEnabledEvent();
+ Status HandleDisabledEvent();
+ Status HandleFaultRaised();
+ Status HandleFaultCleared();
/**
* @brief Helper function to work out the charge limit based on conditions and settings
*/
Status ComputeMaxChargeCurrentLimit();
+ /**
+ * @brief This checks if the charging or discharging needs to be disabled
+ *
+ * @params pointer to SystemLayer
+ * @params pointer to EnergyEvseDelegate
+ */
+ static void EvseCheckTimerExpiry(System::Layer * systemLayer, void * delegate);
+
/* Attributes */
StateEnum mState = StateEnum::kNotPluggedIn;
SupplyStateEnum mSupplyState = SupplyStateEnum::kDisabled;
@@ -172,11 +287,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
DataModel::Nullable mChargingEnabledUntil; // TODO Default to 0 to indicate disabled
DataModel::Nullable mDischargingEnabledUntil; // TODO Default to 0 to indicate disabled
int64_t mCircuitCapacity = 0;
- int64_t mMinimumChargeCurrent = DEFAULT_MIN_CHARGE_CURRENT;
+ int64_t mMinimumChargeCurrent = kDefaultMinChargeCurrent;
int64_t mMaximumChargeCurrent = 0;
int64_t mMaximumDischargeCurrent = 0;
- int64_t mUserMaximumChargeCurrent = DEFAULT_USER_MAXIMUM_CHARGE_CURRENT; // TODO update spec
- uint32_t mRandomizationDelayWindow = DEFAULT_RANDOMIZATION_DELAY_WINDOW;
+ int64_t mUserMaximumChargeCurrent = kDefaultUserMaximumChargeCurrent; // TODO update spec
+ uint32_t mRandomizationDelayWindow = kDefaultRandomizationDelayWindow;
/* PREF attributes */
uint8_t mNumberOfWeeklyTargets = 0;
uint8_t mNumberOfDailyTargets = 1;
@@ -193,11 +308,11 @@ class EnergyEvseDelegate : public EnergyEvse::Delegate
/* PNC attributes*/
DataModel::Nullable mVehicleID;
- /* Session SESS attributes */
- DataModel::Nullable mSessionID;
- DataModel::Nullable mSessionDuration;
- DataModel::Nullable mSessionEnergyCharged;
- DataModel::Nullable mSessionEnergyDischarged;
+ /* Session Object */
+ EvseSession mSession = EvseSession(mEndpointId);
+
+ /* Helper variable to hold meter val since last EnergyTransferStarted event */
+ int64_t mMeterValueAtEnergyTransferStart;
};
} // namespace EnergyEvse
diff --git a/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h b/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h
index 9875c397990ef2..fc0d41b9259643 100644
--- a/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h
+++ b/examples/energy-management-app/energy-management-common/include/EnergyEvseManager.h
@@ -26,8 +26,8 @@
namespace chip {
namespace app {
namespace Clusters {
+namespace EnergyEvse {
-using namespace chip::app::Clusters::EnergyEvse;
class EnergyEvseManager : public Instance
{
public:
@@ -46,12 +46,15 @@ class EnergyEvseManager : public Instance
CHIP_ERROR Init();
void Shutdown();
+ CHIP_ERROR LoadPersistentAttributes();
+
EnergyEvseDelegate * GetDelegate() { return mDelegate; };
private:
EnergyEvseDelegate * mDelegate;
};
+} // namespace EnergyEvse
} // namespace Clusters
} // namespace app
} // namespace chip
diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp
new file mode 100644
index 00000000000000..4d4d9bf05bbdbb
--- /dev/null
+++ b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp
@@ -0,0 +1,344 @@
+/*
+ *
+ * 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.
+ */
+
+#include "DeviceEnergyManagementDelegateImpl.h"
+
+#include
+#include
+#include
+
+using namespace chip;
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::DeviceEnergyManagement;
+using namespace chip::app::Clusters::DeviceEnergyManagement::Attributes;
+
+using chip::Optional;
+using namespace chip::app;
+using CostsList = DataModel::List;
+
+/**
+ * @brief Delegate handler for PowerAdjustRequest
+ *
+ * Note: checking of the validity of the PowerAdjustRequest has been done by the lower layer
+ *
+ * This function needs to notify the appliance that it should apply a new power setting.
+ * It should:
+ * 1) notify the appliance - if the appliance hardware cannot be adjusted, then return Failure
+ * 2) start a timer (or restart the existing PowerAdjust timer) for duration seconds
+ * 3) generate a PowerAdjustStart event (if there is not an existing PowerAdjustRequest running)
+ * 4) if appropriate, update the forecast with the new expected end time
+ *
+ * and when the timer expires:
+ * 5) notify the appliance's that it can resume its intended power setting (or go idle)
+ * 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 status = Status::UnsupportedCommand; // Status::Success;
+
+ // TODO: implement
+ mEsaState = ESAStateEnum::kPowerAdjustActive;
+
+ // TODO: Generate a PowerAdjustStart Event, then begins to adjust its power
+ // When done, raise PowerAdjustEnd & ESAState set to kOnline.
+
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAState::Id);
+
+ return status;
+}
+/**
+ * @brief Delegate handler for CancelPowerAdjustRequest
+ *
+ * Note: checking of the validity of the CancelPowerAdjustRequest has been done by the lower layer
+ *
+ * This function needs to notify the appliance that it should resume its intended power setting (or go idle).
+
+ * It should:
+ * 1) notify the appliance's that it can resume its intended power setting (or go idle)
+ * 2) generate a PowerAdjustEnd event with cause code Cancelled
+ * 3) if necessary, update the forecast with new expected end time
+ */
+Status DeviceEnergyManagementDelegate::CancelPowerAdjustRequest()
+{
+ Status status = Status::UnsupportedCommand; // Status::Success;
+
+ // TODO: implement
+ /* TODO: If the command is accepted, the ESA SHALL generate an PowerAdjustEnd Event. */
+ mEsaState = ESAStateEnum::kOnline;
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAState::Id);
+
+ return status;
+}
+
+/**
+ * @brief Delegate handler for StartTimeAdjustRequest
+ *
+ * Note: checking of the validity of the StartTimeAdjustRequest has been done by the lower layer
+ *
+ * This function needs to notify the appliance that the forecast has been updated by a client.
+ *
+ * It should:
+ * 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)
+{
+ DataModel::Nullable forecast = GetForecast();
+
+ if (forecast.IsNull())
+ {
+ return Status::Failure;
+ }
+
+ uint32_t duration = forecast.Value().endTime - forecast.Value().startTime; // the current entire forecast duration
+
+ /* Modify start time and end time */
+ forecast.Value().startTime = requestedStartTime;
+ forecast.Value().endTime = requestedStartTime + duration;
+
+ SetForecast(forecast); // This will increment forecast ID
+
+ // TODO: callback to the appliance to notify it of a new start time
+
+ return Status::Success;
+}
+/**
+ * @brief Delegate handler for Pause Request
+ *
+ * Note: checking of the validity of the Pause Request has been done by the lower layer
+ *
+ * This function needs to notify the appliance that it should now pause.
+ * It should:
+ * 1) pause the appliance - if the appliance hardware cannot be paused, then return Failure
+ * 2) start a timer for duration seconds
+ * 3) generate a Paused event
+ * 4) update the forecast with the new expected end time
+ *
+ * and when the timer expires:
+ * 5) restore the appliance's operational state
+ * 6) generate a Resumed event
+ * 7) if necessary, update the forecast with new expected end time
+ */
+Status DeviceEnergyManagementDelegate::PauseRequest(const uint32_t duration)
+{
+ Status status = Status::UnsupportedCommand; // Status::Success;
+ // TODO: implement the behaviour above
+ return status;
+}
+
+/**
+ * @brief Delegate handler for ResumeRequest
+ *
+ * Note: checking of the validity of the ResumeRequest has been done by the lower layer
+ *
+ * This function needs to notify the appliance that it should now resume operation
+ *
+ * It should:
+ * 1) restore the appliance's operational state
+ * 2) generate a Resumed event
+ * 3) update the forecast with new expected end time (given that the pause duration was shorter than originally requested)
+ *
+ */
+Status DeviceEnergyManagementDelegate::ResumeRequest()
+{
+ Status status = Status::UnsupportedCommand; // Status::Success;
+
+ // TODO: implement the behaviour above
+ SetESAState(ESAStateEnum::kOnline);
+
+ return status;
+}
+
+/**
+ * @brief Delegate handler for ModifyForecastRequest
+ *
+ * Note: Only basic checking of the validity of the ModifyForecastRequest has been
+ * done by the lower layer. This is a more complex use-case and requires higher-level
+ * work by the delegate.
+ *
+ * It should:
+ * 1) determine if the new forecast adjustments are acceptable to the appliance
+ * - if not return Failure. For example, if it may cause the home to be too hot
+ * or too cold, or a battery to be insufficiently charged
+ * 2) if the slot adjustments are acceptable, then update the forecast
+ * 3) notify the appliance to follow the revised schedule
+ */
+Status DeviceEnergyManagementDelegate::ModifyForecastRequest(
+ const uint32_t forecastId, const DataModel::DecodableList & slotAdjustments)
+{
+ Status status = Status::UnsupportedCommand; // Status::Success;
+
+ // TODO: implement the behaviour above
+ return status;
+}
+
+/**
+ * @brief Delegate handler for RequestConstraintBasedForecast
+ *
+ * Note: Only basic checking of the validity of the RequestConstraintBasedForecast has been
+ * done by the lower layer. This is a more complex use-case and requires higher-level
+ * work by the delegate.
+ *
+ * It should:
+ * 1) perform a higher level optimization (e.g. using tariff information, and user preferences)
+ * 2) if a solution can be found, then update the forecast, else return Failure
+ * 3) notify the appliance to follow the revised schedule
+ */
+Status DeviceEnergyManagementDelegate::RequestConstraintBasedForecast(
+ const DataModel::DecodableList & constraints)
+{
+ Status status = Status::UnsupportedCommand; // Status::Success;
+ // TODO: implement the behaviour above
+ return status;
+}
+
+// ------------------------------------------------------------------
+// Get attribute methods
+ESATypeEnum DeviceEnergyManagementDelegate::GetESAType()
+{
+ return mEsaType;
+}
+
+bool DeviceEnergyManagementDelegate::GetESACanGenerate()
+{
+ return mEsaCanGenerate;
+}
+
+ESAStateEnum DeviceEnergyManagementDelegate::GetESAState()
+{
+ return mEsaState;
+}
+
+int64_t DeviceEnergyManagementDelegate::GetAbsMinPower()
+{
+ return mAbsMinPower;
+}
+
+int64_t DeviceEnergyManagementDelegate::GetAbsMaxPower()
+{
+ return mAbsMaxPower;
+}
+
+PowerAdjustmentCapability::TypeInfo::Type DeviceEnergyManagementDelegate::GetPowerAdjustmentCapability()
+{
+ return mPowerAdjustmentCapability;
+}
+
+DataModel::Nullable DeviceEnergyManagementDelegate::GetForecast()
+{
+ return mForecast;
+}
+
+// ------------------------------------------------------------------
+// Set attribute methods
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetESAType(ESATypeEnum newValue)
+{
+ ESATypeEnum oldValue = mEsaType;
+
+ if (newValue >= ESATypeEnum::kUnknownEnumValue)
+ {
+ return CHIP_IM_GLOBAL_STATUS(ConstraintError);
+ }
+
+ mEsaType = newValue;
+ if (oldValue != newValue)
+ {
+ ChipLogDetail(AppServer, "mEsaType updated to %d", static_cast(mEsaType));
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAType::Id);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetESACanGenerate(bool newValue)
+{
+ bool oldValue = mEsaCanGenerate;
+
+ mEsaCanGenerate = newValue;
+ if (oldValue != newValue)
+ {
+ ChipLogDetail(AppServer, "mEsaCanGenerate updated to %d", static_cast(mEsaCanGenerate));
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESACanGenerate::Id);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetESAState(ESAStateEnum newValue)
+{
+ ESAStateEnum oldValue = mEsaState;
+
+ if (newValue >= ESAStateEnum::kUnknownEnumValue)
+ {
+ return CHIP_IM_GLOBAL_STATUS(ConstraintError);
+ }
+
+ mEsaState = newValue;
+ if (oldValue != newValue)
+ {
+ ChipLogDetail(AppServer, "mEsaState updated to %d", static_cast(mEsaState));
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, ESAState::Id);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMinPower(int64_t newValue)
+{
+ int64_t oldValue = mAbsMinPower;
+
+ mAbsMinPower = newValue;
+ if (oldValue != newValue)
+ {
+ ChipLogDetail(AppServer, "mAbsMinPower updated to %d", static_cast(mAbsMinPower));
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, AbsMinPower::Id);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetAbsMaxPower(int64_t newValue)
+{
+ int64_t oldValue = mAbsMaxPower;
+
+ mAbsMaxPower = newValue;
+ if (oldValue != newValue)
+ {
+ ChipLogDetail(AppServer, "mAbsMaxPower updated to %d", static_cast(mAbsMaxPower));
+ MatterReportingAttributeChangeCallback(mEndpointId, DeviceEnergyManagement::Id, AbsMaxPower::Id);
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR
+DeviceEnergyManagementDelegate::SetPowerAdjustmentCapability(PowerAdjustmentCapability::TypeInfo::Type powerAdjustmentCapability)
+{
+ // TODO see Issue #31147
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementDelegate::SetForecast(DataModel::Nullable forecast)
+{
+ // TODO see Issue #31147
+
+ return CHIP_NO_ERROR;
+}
diff --git a/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp
new file mode 100644
index 00000000000000..c31e0624e4c743
--- /dev/null
+++ b/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp
@@ -0,0 +1,33 @@
+/*
+ *
+ * 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.
+ */
+
+#include
+
+using namespace chip::app;
+using namespace chip::app::Clusters;
+using namespace chip::app::Clusters::DeviceEnergyManagement;
+
+CHIP_ERROR DeviceEnergyManagementManager::Init()
+{
+ return Instance::Init();
+}
+
+void DeviceEnergyManagementManager::Shutdown()
+{
+ Instance::Shutdown();
+}
diff --git a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp
index 8daf1781103831..fe51c9da664b6d 100644
--- a/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp
+++ b/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp
@@ -18,53 +18,74 @@
#include
#include
+#include
+using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::EnergyEvse;
-CHIP_ERROR EVSEManufacturer::Init(EnergyEvseManager * aInstance)
+CHIP_ERROR EVSEManufacturer::Init()
{
/* Manufacturers should modify this to do any custom initialisation */
/* Register callbacks */
- EnergyEvseDelegate * dg = aInstance->GetDelegate();
+ EnergyEvseDelegate * dg = GetEvseManufacturer()->GetDelegate();
if (dg == nullptr)
{
- ChipLogError(AppServer, "Delegate is not initialized");
+ ChipLogError(AppServer, "EVSE Delegate is not initialized");
return CHIP_ERROR_UNINITIALIZED;
}
- dg->HwRegisterEvseCallbackHandler(ApplicationCallbackHandler, reinterpret_cast(nullptr));
+ dg->HwRegisterEvseCallbackHandler(ApplicationCallbackHandler, reinterpret_cast(this));
- /* Set the EVSE Hardware Maximum current limit */
- // For Manufacturer to specify the hardware capability in mA
- dg->HwSetMaxHardwareCurrentLimit(32000);
-
- // For Manufacturer to specify the CircuitCapacity (e.g. from DIP switches)
- dg->HwSetCircuitCapacity(20000);
-
- /* For now let's pretend the EV is plugged in, and asking for demand */
- dg->HwSetState(StateEnum::kPluggedInDemand);
- dg->HwSetCableAssemblyLimit(63000);
-
- /* For now let's pretend the vehicle ID is set */
- dg->HwSetVehicleID(CharSpan::fromCharString("TEST_VEHICLE_123456789"));
- dg->HwSetVehicleID(CharSpan::fromCharString("TEST_VEHICLE_9876543210"));
+ /*
+ * This is an example implementation for manufacturers to consider
+ *
+ * For Manufacturer to specify the hardware capability in mA:
+ * dg->HwSetMaxHardwareCurrentLimit(32000); // 32A
+ *
+ * For Manufacturer to specify the CircuitCapacity in mA (e.g. from DIP switches)
+ * dg->HwSetCircuitCapacity(20000); // 20A
+ *
+ */
- /* This next one will fail because it is too long */
- dg->HwSetVehicleID(CharSpan::fromCharString("TEST_VEHICLE_9876543210TOOOOOOOOOOOOOOOOOOO"));
-
- /* For now let's pretend the RFID sensor was triggered - send an event */
- uint8_t uid[10] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE };
- dg->HwSetRFID(ByteSpan(uid));
+ /* Once the system is initialised then check to see if the state was restored
+ * (e.g. after a power outage), and if the Enable timer check needs to be started
+ */
+ dg->ScheduleCheckOnEnabledTimeout();
return CHIP_NO_ERROR;
}
-CHIP_ERROR EVSEManufacturer::Shutdown(EnergyEvseManager * aInstance)
-{
+/*
+ * When the EV is plugged in, and asking for demand change the state
+ * and set the CableAssembly current limit
+ *
+ * EnergyEvseDelegate * dg = GetEvseManufacturer()->GetDelegate();
+ * if (dg == nullptr)
+ * {
+ * ChipLogError(AppServer, "Delegate is not initialized");
+ * return CHIP_ERROR_UNINITIALIZED;
+ * }
+ *
+ * dg->HwSetState(StateEnum::kPluggedInDemand);
+ * dg->HwSetCableAssemblyLimit(63000); // 63A = 63000mA
+ *
+ *
+ * If the vehicle ID can be retrieved (e.g. over Powerline)
+ * dg->HwSetVehicleID(CharSpan::fromCharString("TEST_VEHICLE_123456789"));
+ *
+ *
+ * If the EVSE has an RFID sensor, the RFID value read can cause an event to be sent
+ * (e.g. can be used to indicate if a user as tried to activate the charging)
+ *
+ * uint8_t uid[10] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE };
+ * dg->HwSetRFID(ByteSpan(uid));
+ */
+CHIP_ERROR EVSEManufacturer::Shutdown()
+{
return CHIP_NO_ERROR;
}
@@ -78,6 +99,8 @@ CHIP_ERROR EVSEManufacturer::Shutdown(EnergyEvseManager * aInstance)
*/
void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_t arg)
{
+ EVSEManufacturer * pClass = reinterpret_cast(arg);
+
switch (cb->type)
{
case EVSECallbackType::StateChanged:
@@ -87,7 +110,177 @@ void EVSEManufacturer::ApplicationCallbackHandler(const EVSECbInfo * cb, intptr_
ChipLogProgress(AppServer, "EVSE callback - maxChargeCurrent changed to %ld",
static_cast(cb->ChargingCurrent.maximumChargeCurrent));
break;
+ case EVSECallbackType::EnergyMeterReadingRequested:
+ ChipLogProgress(AppServer, "EVSE callback - EnergyMeterReadingRequested");
+ if (cb->EnergyMeterReadingRequest.meterType == ChargingDischargingType::kCharging)
+ {
+ *(cb->EnergyMeterReadingRequest.energyMeterValuePtr) = pClass->mLastChargingEnergyMeter;
+ }
+ else
+ {
+ *(cb->EnergyMeterReadingRequest.energyMeterValuePtr) = pClass->mLastDischargingEnergyMeter;
+ }
+ break;
+
+ default:
+ ChipLogError(AppServer, "Unhandled EVSE Callback type %d", static_cast(cb->type));
+ }
+}
+
+struct EVSETestEventSaveData
+{
+ int64_t mOldMaxHardwareCurrentLimit;
+ int64_t mOldCircuitCapacity;
+ int64_t mOldUserMaximumChargeCurrent;
+ int64_t mOldCableAssemblyLimit;
+ StateEnum mOldHwStateBasic; /* For storing hwState before Basic Func event */
+ StateEnum mOldHwStatePluggedIn; /* For storing hwState before PluggedIn event */
+ StateEnum mOldHwStatePluggedInDemand; /* For storing hwState before PluggedInDemand event */
+};
+
+static EVSETestEventSaveData sEVSETestEventSaveData;
+
+EnergyEvseDelegate * GetEvseDelegate()
+{
+ EVSEManufacturer * mn = GetEvseManufacturer();
+ VerifyOrDieWithMsg(mn != nullptr, AppServer, "EVSEManufacturer is null");
+ EnergyEvseDelegate * dg = mn->GetDelegate();
+ VerifyOrDieWithMsg(dg != nullptr, AppServer, "EVSE Delegate is null");
+
+ return dg;
+}
+
+void SetTestEventTrigger_BasicFunctionality()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit = dg->HwGetMaxHardwareCurrentLimit();
+ sEVSETestEventSaveData.mOldCircuitCapacity = dg->GetCircuitCapacity();
+ sEVSETestEventSaveData.mOldUserMaximumChargeCurrent = dg->GetUserMaximumChargeCurrent();
+ sEVSETestEventSaveData.mOldHwStateBasic = dg->HwGetState();
+
+ dg->HwSetMaxHardwareCurrentLimit(32000);
+ dg->HwSetCircuitCapacity(32000);
+ dg->SetUserMaximumChargeCurrent(32000);
+ dg->HwSetState(StateEnum::kNotPluggedIn);
+}
+void SetTestEventTrigger_BasicFunctionalityClear()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwSetMaxHardwareCurrentLimit(sEVSETestEventSaveData.mOldMaxHardwareCurrentLimit);
+ dg->HwSetCircuitCapacity(sEVSETestEventSaveData.mOldCircuitCapacity);
+ dg->SetUserMaximumChargeCurrent(sEVSETestEventSaveData.mOldUserMaximumChargeCurrent);
+ dg->HwSetState(sEVSETestEventSaveData.mOldHwStateBasic);
+}
+void SetTestEventTrigger_EVPluggedIn()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ sEVSETestEventSaveData.mOldCableAssemblyLimit = dg->HwGetCableAssemblyLimit();
+ sEVSETestEventSaveData.mOldHwStatePluggedIn = dg->HwGetState();
+
+ dg->HwSetCableAssemblyLimit(63000);
+ dg->HwSetState(StateEnum::kPluggedInNoDemand);
+}
+void SetTestEventTrigger_EVPluggedInClear()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+ dg->HwSetCableAssemblyLimit(sEVSETestEventSaveData.mOldCableAssemblyLimit);
+ dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedIn);
+}
+
+void SetTestEventTrigger_EVChargeDemand()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ sEVSETestEventSaveData.mOldHwStatePluggedInDemand = dg->HwGetState();
+ dg->HwSetState(StateEnum::kPluggedInDemand);
+}
+void SetTestEventTrigger_EVChargeDemandClear()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwSetState(sEVSETestEventSaveData.mOldHwStatePluggedInDemand);
+}
+void SetTestEventTrigger_EVSEGroundFault()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwSetFault(FaultStateEnum::kGroundFault);
+}
+
+void SetTestEventTrigger_EVSEOverTemperatureFault()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwSetFault(FaultStateEnum::kOverTemperature);
+}
+
+void SetTestEventTrigger_EVSEFaultClear()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwSetFault(FaultStateEnum::kNoError);
+}
+
+void SetTestEventTrigger_EVSEDiagnosticsComplete()
+{
+ EnergyEvseDelegate * dg = GetEvseDelegate();
+
+ dg->HwDiagnosticsComplete();
+}
+
+bool HandleEnergyEvseTestEventTrigger(uint64_t eventTrigger)
+{
+ EnergyEvseTrigger trigger = static_cast(eventTrigger);
+
+ switch (trigger)
+ {
+ case EnergyEvseTrigger::kBasicFunctionality:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality install");
+ SetTestEventTrigger_BasicFunctionality();
+ break;
+ case EnergyEvseTrigger::kBasicFunctionalityClear:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => Basic Functionality clear");
+ SetTestEventTrigger_BasicFunctionalityClear();
+ break;
+ case EnergyEvseTrigger::kEVPluggedIn:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV plugged in");
+ SetTestEventTrigger_EVPluggedIn();
+ break;
+ case EnergyEvseTrigger::kEVPluggedInClear:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV unplugged");
+ SetTestEventTrigger_EVPluggedInClear();
+ break;
+ case EnergyEvseTrigger::kEVChargeDemand:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge Demand");
+ SetTestEventTrigger_EVChargeDemand();
+ break;
+ case EnergyEvseTrigger::kEVChargeDemandClear:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EV Charge NoDemand");
+ SetTestEventTrigger_EVChargeDemandClear();
+ break;
+ case EnergyEvseTrigger::kEVSEGroundFault:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a GroundFault fault");
+ SetTestEventTrigger_EVSEGroundFault();
+ break;
+ case EnergyEvseTrigger::kEVSEOverTemperatureFault:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE has a OverTemperature fault");
+ SetTestEventTrigger_EVSEOverTemperatureFault();
+ break;
+ case EnergyEvseTrigger::kEVSEFaultClear:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE faults have cleared");
+ SetTestEventTrigger_EVSEFaultClear();
+ break;
+ case EnergyEvseTrigger::kEVSEDiagnosticsComplete:
+ ChipLogProgress(Support, "[EnergyEVSE-Test-Event] => EVSE Diagnostics Completed");
+ SetTestEventTrigger_EVSEDiagnosticsComplete();
+ break;
+
default:
- ChipLogError(AppServer, "Unhandler EVSE Callback type %d", static_cast(cb->type));
+ return false;
}
+
+ return true;
}
diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp
index 4cc83eaaf8a835..2b4a6e44f5fcea 100644
--- a/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp
+++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp
@@ -20,6 +20,7 @@
#include
#include
#include
+#include
using namespace chip;
using namespace chip::app;
@@ -41,6 +42,13 @@ EnergyEvseDelegate::~EnergyEvseDelegate()
}
}
+/**
+ * @brief Helper function to get current timestamp in Epoch format
+ *
+ * @param chipEpoch reference to hold return timestamp
+ */
+CHIP_ERROR GetEpochTS(uint32_t & chipEpoch);
+
/**
* @brief Called when EVSE cluster receives Disable command
*/
@@ -48,33 +56,10 @@ Status EnergyEvseDelegate::Disable()
{
ChipLogProgress(AppServer, "EnergyEvseDelegate::Disable()");
- /* Update State */
- switch (mHwState)
- {
- case StateEnum::kNotPluggedIn:
- SetState(StateEnum::kNotPluggedIn);
- break;
-
- case StateEnum::kPluggedInNoDemand:
- SetState(StateEnum::kPluggedInNoDemand);
- break;
-
- case StateEnum::kPluggedInDemand:
- SetState(StateEnum::kPluggedInDemand);
- break;
-
- default:
- ChipLogError(AppServer, "Unexpected EVSE hardware state");
- SetState(StateEnum::kFault);
- break;
- }
-
- /* update SupplyState */
- SetSupplyState(SupplyStateEnum::kDisabled);
-
+ DataModel::Nullable disableTime(0);
/* update ChargingEnabledUntil & DischargingEnabledUntil to show 0 */
- SetChargingEnabledUntil(0);
- SetDischargingEnabledUntil(0);
+ SetChargingEnabledUntil(disableTime);
+ SetDischargingEnabledUntil(disableTime);
/* update MinimumChargeCurrent & MaximumChargeCurrent to 0 */
SetMinimumChargeCurrent(0);
@@ -83,10 +68,7 @@ Status EnergyEvseDelegate::Disable()
/* update MaximumDischargeCurrent to 0 */
SetMaximumDischargeCurrent(0);
- NotifyApplicationStateChange();
- // TODO: Generate events
-
- return Status::Success;
+ return HandleStateMachineEvent(EVSEStateMachineEvent::DisabledEvent);
}
/**
@@ -123,95 +105,131 @@ Status EnergyEvseDelegate::EnableCharging(const DataModel::Nullable &
{
/* Charging enabled indefinitely */
ChipLogError(AppServer, "Charging enabled indefinitely");
+ SetChargingEnabledUntil(chargingEnabledUntil);
}
else
{
/* check chargingEnabledUntil is in the future */
ChipLogError(AppServer, "Charging enabled until: %lu", static_cast(chargingEnabledUntil.Value()));
- // TODO
- // if (checkChargingEnabled)
+ SetChargingEnabledUntil(chargingEnabledUntil);
}
- /* Check current state isn't already enabled */
-
- /* If charging is already enabled, check that the parameters may have
- changed, these may override an existing charging command */
- switch (mHwState)
- {
- case StateEnum::kNotPluggedIn:
- // TODO handle errors here
- SetState(StateEnum::kNotPluggedIn);
- break;
-
- case StateEnum::kPluggedInNoDemand:
- // TODO handle errors here
- // TODO REFACTOR per Andrei's comment in PR30857 - can we collapse this switch statement?
- SetState(StateEnum::kPluggedInNoDemand);
- break;
-
- case StateEnum::kPluggedInDemand:
- /* If the EVSE is asking for demand then enable charging */
- SetState(StateEnum::kPluggedInCharging);
- break;
-
- default:
- ChipLogError(AppServer, "Unexpected EVSE hardware state");
- SetState(StateEnum::kFault);
- break;
- }
-
- /* update SupplyState to say that charging is now enabled */
- SetSupplyState(SupplyStateEnum::kChargingEnabled);
-
/* If it looks ok, store the min & max charging current */
mMaximumChargingCurrentLimitFromCommand = maximumChargeCurrent;
SetMinimumChargeCurrent(minimumChargeCurrent);
// TODO persist these to KVS
- // TODO: Generate events
+ ComputeMaxChargeCurrentLimit();
- NotifyApplicationStateChange();
-
- return this->ComputeMaxChargeCurrentLimit();
+ return HandleStateMachineEvent(EVSEStateMachineEvent::ChargingEnabledEvent);
}
/**
* @brief Called when EVSE cluster receives EnableDischarging command
*
* @param dischargingEnabledUntil (can be null to indefinite discharging)
- * @param maximumChargeCurrent (in mA)
+ * @param maximumDischargeCurrent (in mA)
*/
Status EnergyEvseDelegate::EnableDischarging(const DataModel::Nullable & dischargingEnabledUntil,
const int64_t & maximumDischargeCurrent)
{
ChipLogProgress(AppServer, "EnergyEvseDelegate::EnableDischarging() called.");
- /* update SupplyState */
- SetSupplyState(SupplyStateEnum::kDischargingEnabled);
+ // TODO save the maxDischarging Current
+ // TODO Do something with timestamp
- // TODO: Generate events
+ return HandleStateMachineEvent(EVSEStateMachineEvent::DischargingEnabledEvent);
+}
- NotifyApplicationStateChange();
+/**
+ * @brief Routine to help schedule a timer callback to check if the EVSE should go disabled
+ *
+ * If the clock is sync'd we can work out when to call back to check when to disable the EVSE
+ * automatically. If the clock isn't sync'd the we just set a timer to check once every 30s.
+ *
+ * We first check the SupplyState to check if it is EnabledCharging or EnabledDischarging
+ * Then if the EnabledCharging/DischargingUntil is not Null, then we compute a delay to come
+ * back and check.
+ */
+Status EnergyEvseDelegate::ScheduleCheckOnEnabledTimeout()
+{
+
+ uint32_t chipEpoch = 0;
+ DataModel::Nullable enabledUntilTime;
+ if (mSupplyState == SupplyStateEnum::kChargingEnabled)
+ {
+ enabledUntilTime = GetChargingEnabledUntil();
+ }
+ else if (mSupplyState == SupplyStateEnum::kDischargingEnabled)
+ {
+ enabledUntilTime = GetDischargingEnabledUntil();
+ }
+ else
+ {
+ // In all other states the EVSE is disabled
+ return Status::Success;
+ }
+
+ if (enabledUntilTime.IsNull())
+ {
+ /* This is enabled indefinitely so don't schedule a callback */
+ return Status::Success;
+ }
+
+ CHIP_ERROR err = GetEpochTS(chipEpoch);
+ if (err == CHIP_NO_ERROR)
+ {
+ /* time is sync'd */
+ int32_t delta = static_cast(enabledUntilTime.Value() - chipEpoch);
+ if (delta > 0)
+ {
+ /* The timer hasn't expired yet - set a timer to check in the future */
+ ChipLogDetail(AppServer, "Setting EVSE Enable check timer for %ld seconds", static_cast(delta));
+ DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(delta), EvseCheckTimerExpiry, this);
+ }
+ else
+ {
+ /* we have gone past the enabledUntilTime - so we need to disable */
+ ChipLogDetail(AppServer, "EVSE enable time expired, disabling charging");
+ Disable();
+ }
+ }
+ else if (err == CHIP_ERROR_REAL_TIME_NOT_SYNCED)
+ {
+ /* Real time isn't sync'd -lets check again in 30 seconds - otherwise keep the charger enabled */
+ DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds32(kPeriodicCheckIntervalRealTimeClockNotSynced),
+ EvseCheckTimerExpiry, this);
+ }
return Status::Success;
}
+void EnergyEvseDelegate::EvseCheckTimerExpiry(System::Layer * systemLayer, void * delegate)
+{
+ EnergyEvseDelegate * dg = reinterpret_cast(delegate);
+
+ dg->ScheduleCheckOnEnabledTimeout();
+}
+
/**
* @brief Called when EVSE cluster receives StartDiagnostics command
+ *
+ * NOTE: Application code needs to call HwDiagnosticsComplete
+ * once diagnostics have been completed.
*/
Status EnergyEvseDelegate::StartDiagnostics()
{
/* For EVSE manufacturers to customize */
ChipLogProgress(AppServer, "EnergyEvseDelegate::StartDiagnostics()");
- /* update SupplyState to indicate we are now in Diagnostics mode */
- SetSupplyState(SupplyStateEnum::kDisabledDiagnostics);
-
- // TODO: Generate events
-
- // TODO: Notify Application to implement Diagnostics
+ if (mSupplyState != SupplyStateEnum::kDisabled)
+ {
+ ChipLogError(AppServer, "EVSE: cannot be put into diagnostics mode if it is not Disabled!");
+ return Status::Failure;
+ }
- NotifyApplicationStateChange();
+ // Update the SupplyState - this will automatically callback the Application StateChanged callback
+ SetSupplyState(SupplyStateEnum::kDisabledDiagnostics);
return Status::Success;
}
@@ -259,7 +277,7 @@ Status EnergyEvseDelegate::HwSetMaxHardwareCurrentLimit(int64_t currentmA)
/* there is no attribute to store this so store in private variable */
mMaxHardwareCurrentLimit = currentmA;
- return this->ComputeMaxChargeCurrentLimit();
+ return ComputeMaxChargeCurrentLimit();
}
/**
@@ -281,7 +299,7 @@ Status EnergyEvseDelegate::HwSetCircuitCapacity(int64_t currentmA)
mCircuitCapacity = currentmA;
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, CircuitCapacity::Id);
- return this->ComputeMaxChargeCurrentLimit();
+ return ComputeMaxChargeCurrentLimit();
}
/**
@@ -306,40 +324,99 @@ Status EnergyEvseDelegate::HwSetCableAssemblyLimit(int64_t currentmA)
/* there is no attribute to store this so store in private variable */
mCableAssemblyCurrentLimit = currentmA;
- return this->ComputeMaxChargeCurrentLimit();
+ return ComputeMaxChargeCurrentLimit();
}
/**
* @brief Called by EVSE Hardware to indicate if EV is detected
*
- * The only allowed states that the EVSE hardware can set are:
+ * The only allowed states that the EVSE hardware can tell us about are:
* kNotPluggedIn
* kPluggedInNoDemand
* kPluggedInDemand
*
+ * The actual overall state is more complex and includes faults,
+ * enable & disable charging or discharging etc.
+ *
* @param StateEnum - the state of the EV being plugged in and asking for demand etc
*/
-Status EnergyEvseDelegate::HwSetState(StateEnum state)
+Status EnergyEvseDelegate::HwSetState(StateEnum newState)
{
- switch (state)
+ switch (newState)
{
case StateEnum::kNotPluggedIn:
- // TODO - work out logic here
- mHwState = state;
+ switch (mHwState)
+ {
+ case StateEnum::kNotPluggedIn:
+ // No change
+ break;
+ case StateEnum::kPluggedInNoDemand:
+ case StateEnum::kPluggedInDemand:
+ /* EVSE has been unplugged now */
+ mHwState = newState;
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVNotDetectedEvent);
+ break;
+
+ default:
+ // invalid value for mHwState
+ ChipLogError(AppServer, "HwSetState newstate(kNotPluggedIn) - Invalid value for mHwState");
+ mHwState = newState; // set it to the new state anyway
+ break;
+ }
break;
+
case StateEnum::kPluggedInNoDemand:
- // TODO - work out logic here
- mHwState = state;
+ switch (mHwState)
+ {
+ case StateEnum::kNotPluggedIn:
+ /* EV was unplugged, now is plugged in */
+ mHwState = newState;
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVPluggedInEvent);
+ break;
+ case StateEnum::kPluggedInNoDemand:
+ // No change
+ break;
+ case StateEnum::kPluggedInDemand:
+ /* EV was plugged in and wanted demand, now doesn't want demand */
+ mHwState = newState;
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVNoDemandEvent);
+ break;
+ default:
+ // invalid value for mHwState
+ ChipLogError(AppServer, "HwSetState newstate(kPluggedInNoDemand) - Invalid value for mHwState");
+ mHwState = newState; // set it to the new state anyway
+ break;
+ }
break;
case StateEnum::kPluggedInDemand:
- // TODO - work out logic here
- mHwState = state;
+ switch (mHwState)
+ {
+ case StateEnum::kNotPluggedIn:
+ /* EV was unplugged, now is plugged in and wants demand */
+ mHwState = newState;
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVPluggedInEvent);
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVDemandEvent);
+ break;
+ case StateEnum::kPluggedInNoDemand:
+ /* EV was plugged in and didn't want demand, now does want demand */
+ mHwState = newState;
+ HandleStateMachineEvent(EVSEStateMachineEvent::EVDemandEvent);
+ break;
+ case StateEnum::kPluggedInDemand:
+ // No change
+ break;
+ default:
+ // invalid value for mHwState
+ ChipLogError(AppServer, "HwSetState newstate(kPluggedInDemand) - Invalid value for mHwState");
+ mHwState = newState; // set it to the new state anyway
+ break;
+ }
break;
default:
/* All other states should be managed by the Delegate */
- // TODO (assert?)
- break;
+ ChipLogError(AppServer, "HwSetState received invalid enum from caller");
+ return Status::Failure;
}
return Status::Success;
@@ -350,29 +427,35 @@ Status EnergyEvseDelegate::HwSetState(StateEnum state)
*
* @param FaultStateEnum - the fault condition detected
*/
-Status EnergyEvseDelegate::HwSetFault(FaultStateEnum fault)
+Status EnergyEvseDelegate::HwSetFault(FaultStateEnum newFaultState)
{
ChipLogProgress(AppServer, "EnergyEvseDelegate::Fault()");
- if (fault == FaultStateEnum::kNoError)
+ if (mFaultState == newFaultState)
{
- /* Update State to previous state */
- // TODO: need to work out the logic here!
+ ChipLogError(AppServer, "No change in fault state, ignoring call");
+ return Status::Failure;
+ }
+
+ /** Before we do anything we log the fault
+ * any change in FaultState reports previous fault and new fault
+ * and the state prior to the fault being raised */
+ SendFaultEvent(newFaultState);
+
+ /* Updated FaultState before we call into the handlers */
+ SetFaultState(newFaultState);
- /* Update SupplyState to previous state */
+ if (newFaultState == FaultStateEnum::kNoError)
+ {
+ /* Fault has been cleared */
+ HandleStateMachineEvent(EVSEStateMachineEvent::FaultCleared);
}
else
{
- /* Update State & SupplyState */
- SetState(StateEnum::kFault);
- SetSupplyState(SupplyStateEnum::kDisabledError);
+ /* a new Fault has been raised */
+ HandleStateMachineEvent(EVSEStateMachineEvent::FaultRaised);
}
- /* Update FaultState */
- SetFaultState(fault);
-
- // TODO: Generate events
-
return Status::Success;
}
@@ -436,10 +519,329 @@ Status EnergyEvseDelegate::HwSetVehicleID(const CharSpan & newValue)
return Status::Success;
}
+/**
+ * @brief Called by EVSE Hardware to indicate that it has finished its diagnostics test
+ */
+Status EnergyEvseDelegate::HwDiagnosticsComplete()
+{
+ if (mSupplyState != SupplyStateEnum::kDisabledDiagnostics)
+ {
+ ChipLogError(AppServer, "Incorrect state to be completing diagnostics");
+ return Status::Failure;
+ }
+
+ /* Restore the SupplyState to Disabled (per spec) - client will need to
+ * re-enable charging or discharging to get out of this state */
+ SetSupplyState(SupplyStateEnum::kDisabled);
+
+ return Status::Success;
+}
/* ---------------------------------------------------------------------------
* Functions below are private helper functions internal to the delegate
*/
+/**
+ * @brief Main EVSE state machine
+ *
+ * This routine handles state transition events to determine behaviour
+ *
+ *
+ */
+Status EnergyEvseDelegate::HandleStateMachineEvent(EVSEStateMachineEvent event)
+{
+ switch (event)
+ {
+ case EVSEStateMachineEvent::EVPluggedInEvent:
+ ChipLogDetail(AppServer, "EVSE: EV PluggedIn event");
+ return HandleEVPluggedInEvent();
+ break;
+ case EVSEStateMachineEvent::EVNotDetectedEvent:
+ ChipLogDetail(AppServer, "EVSE: EV NotDetected event");
+ return HandleEVNotDetectedEvent();
+ break;
+ case EVSEStateMachineEvent::EVNoDemandEvent:
+ ChipLogDetail(AppServer, "EVSE: EV NoDemand event");
+ return HandleEVNoDemandEvent();
+ break;
+ case EVSEStateMachineEvent::EVDemandEvent:
+ ChipLogDetail(AppServer, "EVSE: EV Demand event");
+ return HandleEVDemandEvent();
+ break;
+ case EVSEStateMachineEvent::ChargingEnabledEvent:
+ ChipLogDetail(AppServer, "EVSE: ChargingEnabled event");
+ return HandleChargingEnabledEvent();
+ break;
+ case EVSEStateMachineEvent::DischargingEnabledEvent:
+ ChipLogDetail(AppServer, "EVSE: DischargingEnabled event");
+ return HandleDischargingEnabledEvent();
+ break;
+ case EVSEStateMachineEvent::DisabledEvent:
+ ChipLogDetail(AppServer, "EVSE: Disabled event");
+ return HandleDisabledEvent();
+ break;
+ case EVSEStateMachineEvent::FaultRaised:
+ ChipLogDetail(AppServer, "EVSE: FaultRaised event");
+ return HandleFaultRaised();
+ break;
+ case EVSEStateMachineEvent::FaultCleared:
+ ChipLogDetail(AppServer, "EVSE: FaultCleared event");
+ return HandleFaultCleared();
+ break;
+ default:
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::HandleEVPluggedInEvent()
+{
+ /* check if we are already plugged in or not */
+ if (mState == StateEnum::kNotPluggedIn)
+ {
+ /* EV was not plugged in - start a new session */
+ // TODO get energy meter readings
+ mSession.StartSession(0, 0);
+ SendEVConnectedEvent();
+
+ /* Set the state to either PluggedInNoDemand or PluggedInDemand as indicated by mHwState */
+ SetState(mHwState);
+ }
+ // else we are already plugged in - ignore
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::HandleEVNotDetectedEvent()
+{
+ if (mState == StateEnum::kPluggedInCharging || mState == StateEnum::kPluggedInDischarging)
+ {
+ /*
+ * EV was transferring current - unusual to get to this case without
+ * first having the state set to kPluggedInNoDemand or kPluggedInDemand
+ */
+ SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kOther);
+ }
+
+ SendEVNotDetectedEvent();
+ SetState(StateEnum::kNotPluggedIn);
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::HandleEVNoDemandEvent()
+{
+ if (mState == StateEnum::kPluggedInCharging || mState == StateEnum::kPluggedInDischarging)
+ {
+ /*
+ * EV was transferring current - EV decided to stop
+ */
+ mSession.RecalculateSessionDuration();
+ SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVStopped);
+ }
+ /* We must still be plugged in to get here - so no need to check if we are plugged in! */
+ SetState(StateEnum::kPluggedInNoDemand);
+ return Status::Success;
+}
+Status EnergyEvseDelegate::HandleEVDemandEvent()
+{
+ /* Check to see if the supply is enabled for charging / discharging*/
+ switch (mSupplyState)
+ {
+ case SupplyStateEnum::kChargingEnabled:
+ ComputeMaxChargeCurrentLimit();
+ SetState(StateEnum::kPluggedInCharging);
+ SendEnergyTransferStartedEvent();
+ break;
+ case SupplyStateEnum::kDischargingEnabled:
+ // TODO ComputeMaxDischargeCurrentLimit() - Needs to be implemented
+ SetState(StateEnum::kPluggedInDischarging);
+ SendEnergyTransferStartedEvent();
+ break;
+ case SupplyStateEnum::kDisabled:
+ case SupplyStateEnum::kDisabledError:
+ case SupplyStateEnum::kDisabledDiagnostics:
+ /* We must be plugged in, and the event is asking for demand
+ * but we can't charge or discharge now - leave it as kPluggedInDemand */
+ SetState(StateEnum::kPluggedInDemand);
+ break;
+ default:
+ break;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::CheckFaultOrDiagnostic()
+{
+ if (mFaultState != FaultStateEnum::kNoError)
+ {
+ ChipLogError(AppServer, "EVSE: Trying to handle command when fault is present");
+ return Status::Failure;
+ }
+
+ if (mSupplyState == SupplyStateEnum::kDisabledDiagnostics)
+ {
+ ChipLogError(AppServer, "EVSE: Trying to handle command when in diagnostics mode");
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::HandleChargingEnabledEvent()
+{
+ /* Check there is no Fault or Diagnostics condition */
+ Status status = CheckFaultOrDiagnostic();
+ if (status != Status::Success)
+ {
+ return status;
+ }
+
+ /* update SupplyState to say that charging is now enabled */
+ SetSupplyState(SupplyStateEnum::kChargingEnabled);
+
+ switch (mState)
+ {
+ case StateEnum::kNotPluggedIn:
+ case StateEnum::kPluggedInNoDemand:
+ break;
+ case StateEnum::kPluggedInDemand:
+ ComputeMaxChargeCurrentLimit();
+ SetState(StateEnum::kPluggedInCharging);
+ SendEnergyTransferStartedEvent();
+ break;
+ case StateEnum::kPluggedInCharging:
+ break;
+ case StateEnum::kPluggedInDischarging:
+ /* Switched from discharging to charging */
+ SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVSEStopped);
+
+ ComputeMaxChargeCurrentLimit();
+ SetState(StateEnum::kPluggedInCharging);
+ SendEnergyTransferStartedEvent();
+ break;
+ default:
+ break;
+ }
+
+ ScheduleCheckOnEnabledTimeout();
+
+ return Status::Success;
+}
+Status EnergyEvseDelegate::HandleDischargingEnabledEvent()
+{
+ /* Check there is no Fault or Diagnostics condition */
+ Status status = CheckFaultOrDiagnostic();
+ if (status != Status::Success)
+ {
+ return status;
+ }
+ /* update SupplyState to say that charging is now enabled */
+ SetSupplyState(SupplyStateEnum::kDischargingEnabled);
+
+ switch (mState)
+ {
+ case StateEnum::kNotPluggedIn:
+ case StateEnum::kPluggedInNoDemand:
+ break;
+ case StateEnum::kPluggedInDemand:
+ // TODO call ComputeMaxDischargeCurrentLimit()
+ SetState(StateEnum::kPluggedInDischarging);
+ SendEnergyTransferStartedEvent();
+ break;
+ case StateEnum::kPluggedInCharging:
+ /* Switched from charging to discharging */
+ SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVSEStopped);
+
+ // TODO call ComputeMaxDischargeCurrentLimit()
+ SetState(StateEnum::kPluggedInDischarging);
+ SendEnergyTransferStartedEvent();
+ break;
+ case StateEnum::kPluggedInDischarging:
+ default:
+ break;
+ }
+
+ ScheduleCheckOnEnabledTimeout();
+
+ return Status::Success;
+}
+Status EnergyEvseDelegate::HandleDisabledEvent()
+{
+ /* Check there is no Fault or Diagnostics condition */
+ Status status = CheckFaultOrDiagnostic();
+ if (status != Status::Success)
+ {
+ return status;
+ }
+
+ /* update SupplyState to say that charging is now enabled */
+ SetSupplyState(SupplyStateEnum::kDisabled);
+
+ switch (mState)
+ {
+ case StateEnum::kNotPluggedIn:
+ case StateEnum::kPluggedInNoDemand:
+ case StateEnum::kPluggedInDemand:
+ break;
+ case StateEnum::kPluggedInCharging:
+ case StateEnum::kPluggedInDischarging:
+ SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum::kEVSEStopped);
+ SetState(mHwState);
+ break;
+ default:
+ break;
+ }
+
+ return Status::Success;
+}
+
+/**
+ * @brief This handles the new fault
+ *
+ * Note that if multiple faults happen and this is called repeatedly
+ * We only save the previous State and SupplyState if its the first raising
+ * of the fault, so we can restore the state back once all faults have cleared
+)*/
+Status EnergyEvseDelegate::HandleFaultRaised()
+{
+ /* Save the current State and SupplyState so we can restore them if the fault clears */
+ if (mStateBeforeFault == StateEnum::kUnknownEnumValue)
+ {
+ /* No existing fault - save this value to restore it later if it clears */
+ mStateBeforeFault = mState;
+ }
+
+ if (mSupplyStateBeforeFault == SupplyStateEnum::kUnknownEnumValue)
+ {
+ /* No existing fault */
+ mSupplyStateBeforeFault = mSupplyState;
+ }
+
+ /* Update State & SupplyState */
+ SetState(StateEnum::kFault);
+ SetSupplyState(SupplyStateEnum::kDisabledError);
+
+ return Status::Success;
+}
+Status EnergyEvseDelegate::HandleFaultCleared()
+{
+ /* Check that something strange hasn't happened */
+ if ((mStateBeforeFault == StateEnum::kUnknownEnumValue) || (mSupplyStateBeforeFault == SupplyStateEnum::kUnknownEnumValue))
+ {
+ ChipLogError(AppServer, "EVSE: Something wrong trying to clear fault");
+ return Status::Failure;
+ }
+
+ /* Restore the State and SupplyState back to old values once all the faults have cleared
+ * Changing the State should notify the application, so it can continue charging etc
+ */
+ SetState(mStateBeforeFault);
+ SetSupplyState(mSupplyStateBeforeFault);
+
+ /* put back the sentinel to catch new faults if more are raised */
+ mStateBeforeFault = StateEnum::kUnknownEnumValue;
+ mSupplyStateBeforeFault = SupplyStateEnum::kUnknownEnumValue;
+
+ return Status::Success;
+}
+
/**
* @brief Called to compute the safe charging current limit
*
@@ -507,6 +909,172 @@ Status EnergyEvseDelegate::NotifyApplicationStateChange()
return Status::Success;
}
+Status EnergyEvseDelegate::GetEVSEEnergyMeterValue(ChargingDischargingType meterType, int64_t & aMeterValue)
+{
+ EVSECbInfo cbInfo;
+
+ cbInfo.type = EVSECallbackType::EnergyMeterReadingRequested;
+
+ cbInfo.EnergyMeterReadingRequest.meterType = meterType;
+ cbInfo.EnergyMeterReadingRequest.energyMeterValuePtr = &aMeterValue;
+
+ if (mCallbacks.handler != nullptr)
+ {
+ mCallbacks.handler(&cbInfo, mCallbacks.arg);
+ }
+
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::SendEVConnectedEvent()
+{
+ Events::EVConnected::Type event;
+ EventNumber eventNumber;
+
+ if (mSession.mSessionID.IsNull())
+ {
+ ChipLogError(AppServer, "SessionID is Null");
+ return Status::Failure;
+ }
+
+ event.sessionID = mSession.mSessionID.Value();
+
+ CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber);
+ if (CHIP_NO_ERROR != err)
+ {
+ ChipLogError(AppServer, "Unable to send notify event: %" CHIP_ERROR_FORMAT, err.Format());
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::SendEVNotDetectedEvent()
+{
+ Events::EVNotDetected::Type event;
+ EventNumber eventNumber;
+
+ if (mSession.mSessionID.IsNull())
+ {
+ ChipLogError(AppServer, "SessionID is Null");
+ return Status::Failure;
+ }
+
+ event.sessionID = mSession.mSessionID.Value();
+ event.state = mState;
+ event.sessionDuration = mSession.mSessionDuration.Value();
+ event.sessionEnergyCharged = mSession.mSessionEnergyCharged.Value();
+ event.sessionEnergyDischarged = MakeOptional(mSession.mSessionEnergyDischarged.Value());
+
+ CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber);
+ if (CHIP_NO_ERROR != err)
+ {
+ ChipLogError(AppServer, "Unable to send notify event: %" CHIP_ERROR_FORMAT, err.Format());
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::SendEnergyTransferStartedEvent()
+{
+ Events::EnergyTransferStarted::Type event;
+ EventNumber eventNumber;
+
+ if (mSession.mSessionID.IsNull())
+ {
+ ChipLogError(AppServer, "SessionID is Null");
+ return Status::Failure;
+ }
+
+ event.sessionID = mSession.mSessionID.Value();
+ event.state = mState;
+ /**
+ * A positive value indicates the EV has been enabled for charging and the value is
+ * taken directly from the MaximumChargeCurrent attribute.
+ * A negative value indicates that the EV has been enabled for discharging and the value can be taken
+ * from the MaximumDischargeCurrent attribute with its sign inverted.
+ */
+
+ if (mState == StateEnum::kPluggedInCharging)
+ {
+ /* Sample the energy meter for charging */
+ GetEVSEEnergyMeterValue(ChargingDischargingType::kCharging, mMeterValueAtEnergyTransferStart);
+ event.maximumCurrent = mMaximumChargeCurrent;
+ }
+ else if (mState == StateEnum::kPluggedInDischarging)
+ {
+ /* Sample the energy meter for discharging */
+ GetEVSEEnergyMeterValue(ChargingDischargingType::kDischarging, mMeterValueAtEnergyTransferStart);
+
+ /* discharging should have a negative current */
+ event.maximumCurrent = -mMaximumDischargeCurrent;
+ }
+
+ CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber);
+ if (CHIP_NO_ERROR != err)
+ {
+ ChipLogError(AppServer, "Unable to send notify event: %" CHIP_ERROR_FORMAT, err.Format());
+ return Status::Failure;
+ }
+
+ return Status::Success;
+}
+Status EnergyEvseDelegate::SendEnergyTransferStoppedEvent(EnergyTransferStoppedReasonEnum reason)
+{
+ Events::EnergyTransferStopped::Type event;
+ EventNumber eventNumber;
+
+ if (mSession.mSessionID.IsNull())
+ {
+ ChipLogError(AppServer, "SessionID is Null");
+ return Status::Failure;
+ }
+
+ event.sessionID = mSession.mSessionID.Value();
+ event.state = mState;
+ event.reason = reason;
+ int64_t meterValueNow = 0;
+
+ if (mState == StateEnum::kPluggedInCharging)
+ {
+ GetEVSEEnergyMeterValue(ChargingDischargingType::kCharging, meterValueNow);
+ event.energyTransferred = meterValueNow - mMeterValueAtEnergyTransferStart;
+ }
+ else if (mState == StateEnum::kPluggedInDischarging)
+ {
+ GetEVSEEnergyMeterValue(ChargingDischargingType::kDischarging, meterValueNow);
+
+ /* discharging should have a negative value */
+ event.energyTransferred = mMeterValueAtEnergyTransferStart - meterValueNow;
+ }
+
+ CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber);
+ if (CHIP_NO_ERROR != err)
+ {
+ ChipLogError(AppServer, "Unable to send notify event: %" CHIP_ERROR_FORMAT, err.Format());
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
+Status EnergyEvseDelegate::SendFaultEvent(FaultStateEnum newFaultState)
+{
+ Events::Fault::Type event;
+ EventNumber eventNumber;
+
+ event.sessionID = mSession.mSessionID; // Note here the event sessionID can be Null!
+ event.state = mState; // This is the state prior to the fault being raised
+ event.faultStatePreviousState = mFaultState;
+ event.faultStateCurrentState = newFaultState;
+
+ CHIP_ERROR err = LogEvent(event, mEndpointId, eventNumber);
+ if (CHIP_NO_ERROR != err)
+ {
+ ChipLogError(AppServer, "Unable to send notify event: %" CHIP_ERROR_FORMAT, err.Format());
+ return Status::Failure;
+ }
+ return Status::Success;
+}
+
/**
* Attribute methods
*/
@@ -529,6 +1097,7 @@ CHIP_ERROR EnergyEvseDelegate::SetState(StateEnum newValue)
{
ChipLogDetail(AppServer, "State updated to %d", static_cast(mState));
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, State::Id);
+ NotifyApplicationStateChange();
}
return CHIP_NO_ERROR;
@@ -554,6 +1123,7 @@ CHIP_ERROR EnergyEvseDelegate::SetSupplyState(SupplyStateEnum newValue)
{
ChipLogDetail(AppServer, "SupplyState updated to %d", static_cast(mSupplyState));
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SupplyState::Id);
+ NotifyApplicationStateChange();
}
return CHIP_NO_ERROR;
}
@@ -588,17 +1158,30 @@ DataModel::Nullable EnergyEvseDelegate::GetChargingEnabledUntil()
return mChargingEnabledUntil;
}
-CHIP_ERROR EnergyEvseDelegate::SetChargingEnabledUntil(uint32_t newValue)
+CHIP_ERROR EnergyEvseDelegate::SetChargingEnabledUntil(DataModel::Nullable newValue)
{
DataModel::Nullable oldValue = mChargingEnabledUntil;
- mChargingEnabledUntil = MakeNullable(newValue);
- if ((oldValue.IsNull()) || (oldValue.Value() != newValue))
+ mChargingEnabledUntil = newValue;
+ if (oldValue != newValue)
{
- ChipLogDetail(AppServer, "ChargingEnabledUntil updated to %lu",
- static_cast(mChargingEnabledUntil.Value()));
+ if (newValue.IsNull())
+ {
+ ChipLogDetail(AppServer, "ChargingEnabledUntil updated to Null");
+ }
+ else
+ {
+ ChipLogDetail(AppServer, "ChargingEnabledUntil updated to %lu",
+ static_cast(mChargingEnabledUntil.Value()));
+ }
+
+ // Write new value to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, ChargingEnabledUntil::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mChargingEnabledUntil);
+
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, ChargingEnabledUntil::Id);
}
+
return CHIP_NO_ERROR;
}
@@ -608,17 +1191,29 @@ DataModel::Nullable EnergyEvseDelegate::GetDischargingEnabledUntil()
return mDischargingEnabledUntil;
}
-CHIP_ERROR EnergyEvseDelegate::SetDischargingEnabledUntil(uint32_t newValue)
+CHIP_ERROR EnergyEvseDelegate::SetDischargingEnabledUntil(DataModel::Nullable newValue)
{
DataModel::Nullable oldValue = mDischargingEnabledUntil;
- mDischargingEnabledUntil = MakeNullable(newValue);
- if ((oldValue.IsNull()) || (oldValue.Value() != newValue))
+ mDischargingEnabledUntil = newValue;
+ if (oldValue != newValue)
{
- ChipLogDetail(AppServer, "DischargingEnabledUntil updated to %lu",
- static_cast(mDischargingEnabledUntil.Value()));
+ if (newValue.IsNull())
+ {
+ ChipLogDetail(AppServer, "DischargingEnabledUntil updated to Null");
+ }
+ else
+ {
+ ChipLogDetail(AppServer, "DischargingEnabledUntil updated to %lu",
+ static_cast(mDischargingEnabledUntil.Value()));
+ }
+ // Write new value to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, DischargingEnabledUntil::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mDischargingEnabledUntil);
+
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, DischargingEnabledUntil::Id);
}
+
return CHIP_NO_ERROR;
}
@@ -736,6 +1331,13 @@ CHIP_ERROR EnergyEvseDelegate::SetUserMaximumChargeCurrent(int64_t newValue)
if (oldValue != newValue)
{
ChipLogDetail(AppServer, "UserMaximumChargeCurrent updated to %ld", static_cast(mUserMaximumChargeCurrent));
+
+ ComputeMaxChargeCurrentLimit();
+
+ // Write new value to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, UserMaximumChargeCurrent::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mUserMaximumChargeCurrent);
+
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, UserMaximumChargeCurrent::Id);
}
@@ -761,6 +1363,11 @@ CHIP_ERROR EnergyEvseDelegate::SetRandomizationDelayWindow(uint32_t newValue)
{
ChipLogDetail(AppServer, "RandomizationDelayWindow updated to %lu",
static_cast(mRandomizationDelayWindow));
+
+ // Write new value to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, RandomizationDelayWindow::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mRandomizationDelayWindow);
+
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, RandomizationDelayWindow::Id);
}
return CHIP_NO_ERROR;
@@ -798,14 +1405,25 @@ DataModel::Nullable EnergyEvseDelegate::GetApproximateEVEfficiency()
return mApproximateEVEfficiency;
}
-CHIP_ERROR EnergyEvseDelegate::SetApproximateEVEfficiency(uint16_t newValue)
+CHIP_ERROR EnergyEvseDelegate::SetApproximateEVEfficiency(DataModel::Nullable newValue)
{
DataModel::Nullable oldValue = mApproximateEVEfficiency;
- mApproximateEVEfficiency = MakeNullable(newValue);
- if ((oldValue.IsNull()) || (oldValue.Value() != newValue))
+ mApproximateEVEfficiency = newValue;
+ if ((oldValue != newValue))
{
- ChipLogDetail(AppServer, "ApproximateEVEfficiency updated to %d", mApproximateEVEfficiency.Value());
+ if (newValue.IsNull())
+ {
+ ChipLogDetail(AppServer, "ApproximateEVEfficiency updated to Null");
+ }
+ else
+ {
+ ChipLogDetail(AppServer, "ApproximateEVEfficiency updated to %d", mApproximateEVEfficiency.Value());
+ }
+ // Write new value to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, ApproximateEVEfficiency::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mApproximateEVEfficiency);
+
MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, ApproximateEVEfficiency::Id);
}
@@ -831,17 +1449,149 @@ DataModel::Nullable EnergyEvseDelegate::GetVehicleID()
/* Session SESS attributes */
DataModel::Nullable EnergyEvseDelegate::GetSessionID()
{
- return mSessionID;
+ return mSession.mSessionID;
}
DataModel::Nullable EnergyEvseDelegate::GetSessionDuration()
{
- return mSessionDuration;
+ mSession.RecalculateSessionDuration();
+ return mSession.mSessionDuration;
}
DataModel::Nullable EnergyEvseDelegate::GetSessionEnergyCharged()
{
- return mSessionEnergyCharged;
+ return mSession.mSessionEnergyCharged;
}
DataModel::Nullable EnergyEvseDelegate::GetSessionEnergyDischarged()
{
- return mSessionEnergyDischarged;
+ return mSession.mSessionEnergyDischarged;
+}
+
+/**
+ * @brief Helper function to get current timestamp in Epoch format
+ *
+ * @param chipEpoch reference to hold return timestamp
+ */
+CHIP_ERROR GetEpochTS(uint32_t & chipEpoch)
+{
+ chipEpoch = 0;
+
+ System::Clock::Milliseconds64 cTMs;
+ CHIP_ERROR err = System::SystemClock().GetClock_RealTimeMS(cTMs);
+
+ /* If the GetClock_RealTimeMS returns CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE, then
+ * This platform cannot ever report real time !
+ * This should not be certifiable since getting time is a Mandatory
+ * feature of EVSE Cluster
+ */
+ VerifyOrDie(err != CHIP_ERROR_UNSUPPORTED_CHIP_FEATURE);
+
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(Zcl, "EVSE: Unable to get current time - err:%" CHIP_ERROR_FORMAT, err.Format());
+ return err;
+ }
+
+ auto unixEpoch = std::chrono::duration_cast(cTMs).count();
+ if (!UnixEpochToChipEpochTime(unixEpoch, chipEpoch))
+ {
+ ChipLogError(Zcl, "EVSE: unable to convert Unix Epoch time to Matter Epoch Time");
+ return err;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+/**
+ * @brief This function samples the start-time, and energy meter to hold the session info
+ *
+ * @param chargingMeterValue - The current value of the energy meter (charging) in mWh
+ * @param dischargingMeterValue - The current value of the energy meter (discharging) in mWh
+ */
+void EvseSession::StartSession(int64_t chargingMeterValue, int64_t dischargingMeterValue)
+{
+ /* Get Timestamp */
+ uint32_t chipEpoch = 0;
+ CHIP_ERROR err = GetEpochTS(chipEpoch);
+ if (err != CHIP_NO_ERROR)
+ {
+ /* Note that the error will be also be logged inside GetErrorTS() -
+ * adding context here to help debugging */
+ ChipLogError(AppServer, "EVSE: Unable to get current time when starting session - err:%" CHIP_ERROR_FORMAT, err.Format());
+ return;
+ }
+ mStartTime = chipEpoch;
+
+ mSessionEnergyChargedAtStart = chargingMeterValue;
+ mSessionEnergyDischargedAtStart = dischargingMeterValue;
+
+ if (mSessionID.IsNull())
+ {
+ mSessionID = MakeNullable(static_cast(0));
+ }
+ else
+ {
+ uint32_t sessionID = mSessionID.Value() + 1;
+ mSessionID = MakeNullable(sessionID);
+ }
+
+ /* Reset other session values */
+ mSessionDuration = MakeNullable(static_cast(0));
+ mSessionEnergyCharged = MakeNullable(static_cast(0));
+ mSessionEnergyDischarged = MakeNullable(static_cast(0));
+
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionID::Id);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionDuration::Id);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionEnergyCharged::Id);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionEnergyDischarged::Id);
+
+ // Write values to persistent storage.
+ ConcreteAttributePath path = ConcreteAttributePath(mEndpointId, EnergyEvse::Id, SessionID::Id);
+ GetSafeAttributePersistenceProvider()->WriteScalarValue(path, mSessionID);
+
+ // TODO persist mStartTime
+ // TODO persist mSessionEnergyChargedAtStart
+ // TODO persist mSessionEnergyDischargedAtStart
+}
+
+/**
+ * @brief This function updates the session attrs to allow read attributes to return latest values
+ */
+void EvseSession::RecalculateSessionDuration()
+{
+ /* Get Timestamp */
+ uint32_t chipEpoch = 0;
+ CHIP_ERROR err = GetEpochTS(chipEpoch);
+ if (err != CHIP_NO_ERROR)
+ {
+ /* Note that the error will be also be logged inside GetErrorTS() -
+ * adding context here to help debugging */
+ ChipLogError(AppServer, "EVSE: Unable to get current time when updating session duration - err:%" CHIP_ERROR_FORMAT,
+ err.Format());
+ return;
+ }
+
+ uint32_t duration = chipEpoch - mStartTime;
+ mSessionDuration = MakeNullable(duration);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionDuration::Id);
+}
+
+/**
+ * @brief This function updates the EnergyCharged meter value
+ *
+ * @param chargingMeterValue - The value of the energy meter (charging) in mWh
+ */
+void EvseSession::UpdateEnergyCharged(int64_t chargingMeterValue)
+{
+ mSessionEnergyCharged = MakeNullable(chargingMeterValue - mSessionEnergyChargedAtStart);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionEnergyCharged::Id);
+}
+
+/**
+ * @brief This function updates the EnergyDischarged meter value
+ *
+ * @param dischargingMeterValue - The value of the energy meter (discharging) in mWh
+ */
+void EvseSession::UpdateEnergyDischarged(int64_t dischargingMeterValue)
+{
+ mSessionEnergyDischarged = MakeNullable(dischargingMeterValue - mSessionEnergyDischargedAtStart);
+ MatterReportingAttributeChangeCallback(mEndpointId, EnergyEvse::Id, SessionEnergyDischarged::Id);
}
diff --git a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp
index 0d84d8856212e0..710b13f9d342b8 100644
--- a/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp
+++ b/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp
@@ -17,14 +17,96 @@
*/
#include
+#include
using namespace chip::app;
using namespace chip::app::Clusters;
using namespace chip::app::Clusters::EnergyEvse;
+CHIP_ERROR EnergyEvseManager::LoadPersistentAttributes()
+{
+
+ SafeAttributePersistenceProvider * aProvider = GetSafeAttributePersistenceProvider();
+ EndpointId aEndpointId = mDelegate->GetEndpointId();
+ CHIP_ERROR err;
+
+ // Restore ChargingEnabledUntil value
+ DataModel::Nullable tempChargingEnabledUntil;
+ err = aProvider->ReadScalarValue(ConcreteAttributePath(aEndpointId, EnergyEvse::Id, Attributes::ChargingEnabledUntil::Id),
+ tempChargingEnabledUntil);
+ if (err == CHIP_NO_ERROR)
+ {
+ ChipLogDetail(AppServer, "EVSE: successfully loaded ChargingEnabledUntil from NVM");
+ mDelegate->SetChargingEnabledUntil(tempChargingEnabledUntil);
+ }
+ else
+ {
+ ChipLogError(AppServer, "EVSE: Unable to restore persisted ChargingEnabledUntil value");
+ }
+
+ // Restore DischargingEnabledUntil value
+ DataModel::Nullable tempDischargingEnabledUntil;
+ err = aProvider->ReadScalarValue(ConcreteAttributePath(aEndpointId, EnergyEvse::Id, Attributes::DischargingEnabledUntil::Id),
+ tempDischargingEnabledUntil);
+ if (err == CHIP_NO_ERROR)
+ {
+ ChipLogDetail(AppServer, "EVSE: successfully loaded DischargingEnabledUntil from NVM");
+ mDelegate->SetDischargingEnabledUntil(tempDischargingEnabledUntil);
+ }
+ else
+ {
+ ChipLogError(AppServer, "EVSE: Unable to restore persisted DischargingEnabledUntil value");
+ }
+
+ // Restore UserMaximumChargeCurrent value
+ int64_t tempUserMaximumChargeCurrent;
+ err = aProvider->ReadScalarValue(ConcreteAttributePath(aEndpointId, EnergyEvse::Id, Attributes::UserMaximumChargeCurrent::Id),
+ tempUserMaximumChargeCurrent);
+ if (err == CHIP_NO_ERROR)
+ {
+ ChipLogDetail(AppServer, "EVSE: successfully loaded UserMaximumChargeCurrent from NVM");
+ mDelegate->SetUserMaximumChargeCurrent(tempUserMaximumChargeCurrent);
+ }
+ else
+ {
+ ChipLogError(AppServer, "EVSE: Unable to restore persisted UserMaximumChargeCurrent value");
+ }
+
+ // Restore RandomizationDelayWindow value
+ uint32_t tempRandomizationDelayWindow;
+ err = aProvider->ReadScalarValue(ConcreteAttributePath(aEndpointId, EnergyEvse::Id, Attributes::RandomizationDelayWindow::Id),
+ tempRandomizationDelayWindow);
+ if (err == CHIP_NO_ERROR)
+ {
+ ChipLogDetail(AppServer, "EVSE: successfully loaded RandomizationDelayWindow from NVM");
+ mDelegate->SetRandomizationDelayWindow(tempRandomizationDelayWindow);
+ }
+ else
+ {
+ ChipLogError(AppServer, "EVSE: Unable to restore persisted RandomizationDelayWindow value");
+ }
+
+ // Restore ApproximateEVEfficiency value
+ DataModel::Nullable tempApproxEVEfficiency;
+ err = aProvider->ReadScalarValue(ConcreteAttributePath(aEndpointId, EnergyEvse::Id, Attributes::ApproximateEVEfficiency::Id),
+ tempApproxEVEfficiency);
+ if (err == CHIP_NO_ERROR)
+ {
+ ChipLogDetail(AppServer, "EVSE: successfully loaded ApproximateEVEfficiency from NVM");
+ mDelegate->SetApproximateEVEfficiency(tempApproxEVEfficiency);
+ }
+ else
+ {
+ ChipLogError(AppServer, "EVSE: Unable to restore persisted ApproximateEVEfficiency value");
+ }
+
+ return CHIP_NO_ERROR; // It is ok to have no value loaded here
+}
+
CHIP_ERROR EnergyEvseManager::Init()
{
- return Instance::Init();
+ ReturnErrorOnFailure(Instance::Init());
+ return LoadPersistentAttributes();
}
void EnergyEvseManager::Shutdown()
diff --git a/examples/energy-management-app/linux/BUILD.gn b/examples/energy-management-app/linux/BUILD.gn
index 8597caabfc35b9..8fb53878129c60 100644
--- a/examples/energy-management-app/linux/BUILD.gn
+++ b/examples/energy-management-app/linux/BUILD.gn
@@ -36,6 +36,8 @@ config("includes") {
executable("chip-energy-management-app") {
sources = [
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementDelegateImpl.cpp",
+ "${chip_root}/examples/energy-management-app/energy-management-common/src/DeviceEnergyManagementManager.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EVSEManufacturerImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseDelegateImpl.cpp",
"${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp",
diff --git a/examples/energy-management-app/linux/README.md b/examples/energy-management-app/linux/README.md
index 9671ab073b12a8..d316dd807c13e2 100644
--- a/examples/energy-management-app/linux/README.md
+++ b/examples/energy-management-app/linux/README.md
@@ -13,10 +13,17 @@ To cross-compile this example on x64 host and run on **NXP i.MX 8M Mini**
- [CHIP Linux Energy Management Example](#chip-linux-energy-management-example)
- [Building](#building)
- - [Commandline Arguments](#commandline-arguments)
+ - [Commandline arguments](#commandline-arguments)
- [Running the Complete Example on Raspberry Pi 4](#running-the-complete-example-on-raspberry-pi-4)
- - [Running RPC console](#running-rpc-console)
+ - [Running RPC Console](#running-rpc-console)
- [Device Tracing](#device-tracing)
+ - [Python Test Cases](#python-test-cases)
+ - [Running the test cases:](#running-the-test-cases)
+ - [CHIP-REPL Interaction](#chip-repl-interaction)
+ - [Building chip-repl:](#building-chip-repl)
+ - [Activating python virtual env](#activating-python-virtual-env)
+ - [Interacting with CHIP-REPL and the example app](#interacting-with-chip-repl-and-the-example-app)
+ - [Using chip-repl to Fake a charging session](#using-chip-repl-to-fake-a-charging-session)
@@ -141,3 +148,361 @@ Obtain tracing json file.
$ ./{PIGWEED_REPO}/pw_trace_tokenized/py/pw_trace_tokenized/get_trace.py -s localhost:33000 \
-o {OUTPUT_FILE} -t {ELF_FILE} {PIGWEED_REPO}/pw_trace_tokenized/pw_trace_protos/trace_rpc.proto
```
+
+## Python Test Cases
+
+When you want to test this cluster you can use chip-repl or chip-tool by hand.
+CHIP-REPL is slightly easier to interact with when dealing with some of the
+complex structures.
+
+There are several test scripts provided for EVSE (in
+[src/python_testing](src/python_testing)):
+
+- `TC_EEVSE_2_2`: This validates the primary functionality
+- `TC_EEVSE_2_3`: This validates Get/Set/Clear target commands
+- `TC_EEVSE_2_4`: This validates Faults
+- `TC_EEVSE_2_5`: This validates EVSE diagnostic command (optional)
+
+These scripts require the use of Test Event Triggers via the GeneralDiagnostics
+cluster on Endpoint 0. This requires an `enableKey` (16 bytes) and a set of
+reserved int64_t test event trigger codes.
+
+By default the test event support is not enabled, and when compiling the example
+app you need to add `chip_enable_energy_evse_trigger=true` to the gn args.
+
+ $ gn gen out/debug --args='chip_enable_energy_evse_trigger=true'
+ $ ninja -C out/debug
+
+Once the application is built you also need to tell it at runtime what the
+chosen enable key is using the `--enable-key` command line option.
+
+ $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f
+
+### Running the test cases:
+
+From the top-level of the connectedhomeip repo type:
+
+```bash
+ $ python src/python_testing/TC_EEVSE_2_2.py --endpoint 1 -m on-network -n 1234 -p 20202021 -d 3840 --hex-arg enableKey:000102030405060708090a0b0c0d0e0f
+```
+
+- Note that the `--endpoint 1` must be used with the example, since the EVSE
+ cluster is on endpoint 1. The `--hex-arg enableKey:` value must match
+ the `--enable-key ` used on chip-energy-management-app args.
+
+## CHIP-REPL Interaction
+
+- See chip-repl documentation in
+ [Matter_REPL_Intro](../../../docs/guides/repl/Matter_REPL_Intro.ipynb)
+
+### Building chip-repl:
+
+```bash
+ $ ./build_python.sh -i
+```
+
+### Activating python virtual env
+
+- You need to repeat this step each time you start a new shell.
+
+```bash
+ $ source /bin/activate
+```
+
+### Interacting with CHIP-REPL and the example app
+
+- Step 1: Launch the example app
+
+```bash
+ $ ./chip-energy-management-app --enable-key 000102030405060708090a0b0c0d0e0f
+```
+
+- Step 2: Launch CHIP-REPL
+
+```bash
+ $ chip-repl
+```
+
+- Step 3: (In chip-repl) Commissioning OnNetwork
+
+```python
+ devCtrl.CommissionOnNetwork(1234,20202021) # Commission with NodeID 1234
+Established secure session with Device
+Commissioning complete
+Out[2]:
+```
+
+- Step 4: (In chip-repl) Read EVSE attributes
+
+```python
+ # Read from NodeID 1234, Endpoint 1, all attributes on EnergyEvse cluster
+ await devCtrl.ReadAttribute(1234,[(1, chip.clusters.EnergyEvse)])
+```
+
+```
+{
+│ 1: {
+│ │ : {
+│ │ │ : 3790455237,
+│ │ │ : Null,
+│ │ │ : ,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : 0,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : [
+... │ │ ],
+│ │ │ : 6000,
+│ │ │ : Null,
+│ │ │ : 758415333,
+│ │ │ : 0,
+│ │ │ : 1,
+│ │ │ : [
+...
+│ │ │ ],
+│ │ │ : ,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : Null,
+│ │ │ : [
+... │ │ ],
+│ │ │ : Null,
+│ │ │ : 0,
+│ │ │ : Null,
+│ │ │ : ,
+│ │ │ : 600,
+│ │ │ : 0,
+│ │ │ : 1,
+│ │ │ : 80000,
+│ │ │ : 2
+│ │ }
+│ }
+}
+
+```
+
+- Step 5: Setting up a subscription so that attributes updates are sent
+ automatically
+
+```python
+ reportingTimingParams = (3, 60) # MinInterval = 3s, MaxInterval = 60s
+ subscription = await devCtrl.ReadAttribute(1234,[(1, chip.clusters.EnergyEvse)], reportInterval=reportingTimingParams)
+```
+
+- Step 6: Send an `EnableCharging` command which lasts for 60 seconds The
+ `EnableCharging` takes an optional `chargingEnabledUntil` parameter which
+ allows the charger to automatically disable itself at some preset time in
+ the future. Note that it uses Epoch_s (which is from Jan 1 2000) which is a
+ uint32_t in seconds.
+
+```python
+ from datetime import datetime, timezone, timedelta
+ epoch_end = int((datetime.now(tz=timezone.utc) + timedelta(seconds=60) - datetime(2000, 1, 1, 0, 0, 0, 0, timezone.utc)).total_seconds())
+
+ await devCtrl.SendCommand(1234, 1, chip.clusters.EnergyEvse.Commands.EnableCharging(chargingEnabledUntil=epoch_end,minimumChargeCurrent=2000,maximumChargeCurrent=25000),timedRequestTimeoutMs=3000)
+```
+
+The output should look like:
+
+```
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value':
+}
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value': 2000
+}
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value': 758416066
+}
+```
+
+After 60 seconds the charging should automatically become disabled:
+
+```
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value':
+}
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value': 0
+}
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value': 0
+}
+Attribute Changed:
+{
+│ 'Endpoint': 1,
+│ 'Attribute': ,
+│ 'Value': 0
+}
+```
+
+Note that you can omit the `chargingEnabledUntil` argument and it will charge
+indefinitely.
+
+### Using chip-repl to Fake a charging session
+
+If you haven't implemented a real EVSE but want to simulate plugging in an EV
+then you can use a few of the test event triggers to simulate these scenarios.
+
+The test event triggers values can be found in:
+[EnergyEvseTestEventTriggerDelegate.h](../../../src/app/clusters/energy-evse-server/EnergyEvseTestEventTriggerDelegate.h)
+
+- 0x0099000000000000 - Simulates the EVSE being installed on a 32A supply
+- 0x0099000000000002 - Simulates the EVSE being plugged in (this should
+ generate an `EVConnected` event)
+- 0x0099000000000004 - Simulates the EVSE requesting power
+
+To send a test event trigger to the app, use the following commands (in
+chip-repl):
+
+```python
+ # send 1st event trigger to 'install' the EVSE on a 32A supply
+ await devCtrl.SendCommand(1234, 0, chip.clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=bytes([b for b in range(16)]), eventTrigger=0x0099000000000000))
+
+ # send 2nd event trigger to plug the EV in
+ await devCtrl.SendCommand(1234, 0, chip.clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=bytes([b for b in range(16)]), eventTrigger=0x0099000000000002))
+
+```
+
+Now send the enable charging command (omit the `chargingEnabledUntil` arg this
+time):
+
+```python
+ await devCtrl.SendCommand(1234, 1, chip.clusters.EnergyEvse.Commands.EnableCharging(minimumChargeCurrent=2000,maximumChargeCurrent=25000),timedRequestTimeoutMs=3000)
+```
+
+Now send the test event trigger to simulate the EV asking for demand:
+
+```python
+ # send 2nd event trigger to plug the EV in
+ await devCtrl.SendCommand(1234, 0, chip.clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=bytes([b for b in range(16)]), eventTrigger=0x0099000000000004))
+
+ # Read the events
+ await devCtrl.ReadEvent(1234,[(1, chip.clusters.EnergyEvse,1)])
+```
+
+```
+[
+│ EventReadResult(
+│ │ Header=EventHeader(
+│ │ │ EndpointId=1,
+│ │ │ ClusterId=153,
+│ │ │ EventId=0,
+│ │ │ EventNumber=65538,
+│ │ │ Priority=,
+│ │ │ Timestamp=1705102500069,
+│ │ │ TimestampType=
+│ │ ),
+│ │ Status=,
+│ │ Data=EVConnected(
+│ │ │ sessionID=0
+│ │ )
+│ ),
+│ EventReadResult(
+│ │ Header=EventHeader(
+│ │ │ EndpointId=1,
+│ │ │ ClusterId=153,
+│ │ │ EventId=2,
+│ │ │ EventNumber=65539,
+│ │ │ Priority=,
+│ │ │ Timestamp=1705102801764,
+│ │ │ TimestampType=
+│ │ ),
+│ │ Status=,
+│ │ Data=EnergyTransferStarted(
+│ │ │ sessionID=0,
+│ │ │ state=,
+│ │ │ maximumCurrent=25000
+│ │ )
+│ )
+]
+```
+
+- We can see that the `EventNumber 65538` was sent when the vehicle was
+ plugged in, and a new `sessionID=0` was created.
+- We can also see that the `EnergyTransferStarted` was sent in
+ `EventNumber 65539`
+
+What happens when we unplug the vehicle?
+
+```python
+ await devCtrl.SendCommand(1234, 0, chip.clusters.GeneralDiagnostics.Commands.TestEventTrigger(enableKey=bytes([b for b in range(16)]), eventTrigger=0x0099000000000001))
+```
+
+When we re-read the events:
+
+```
+[
+│ EventReadResult(
+│ │ Header=EventHeader(
+│ │ │ EndpointId=1,
+│ │ │ ClusterId=153,
+│ │ │ EventId=3,
+│ │ │ EventNumber=65540,
+│ │ │ Priority=,
+│ │ │ Timestamp=1705102996749,
+│ │ │ TimestampType=
+│ │ ),
+│ │ Status=,
+│ │ Data=EnergyTransferStopped(
+│ │ │ sessionID=0,
+│ │ │ state=,
+│ │ │ reason=,
+│ │ │ energyTransferred=0
+│ │ )
+│ ),
+│ EventReadResult(
+│ │ Header=EventHeader(
+│ │ │ EndpointId=1,
+│ │ │ ClusterId=153,
+│ │ │ EventId=1,
+│ │ │ EventNumber=65541,
+│ │ │ Priority=,
+│ │ │ Timestamp=1705102996749,
+│ │ │ TimestampType=
+│ │ ),
+│ │ Status=,
+│ │ Data=EVNotDetected(
+│ │ │ sessionID=0,
+│ │ │ state=,
+│ │ │ sessionDuration=0,
+│ │ │ sessionEnergyCharged=0,
+│ │ │ sessionEnergyDischarged=0
+│ │ )
+│ )
+]
+
+```
+
+- In `EventNumber 65540` we had an `EnergyTransferStopped` event with reason
+ `kOther`.
+
+ This was a rather abrupt end to a charging session (normally we would see
+ the EVSE or EV decide to stop charging), but this demonstrates the cable
+ being pulled out without a graceful charging shutdown.
+
+- In `EventNumber 65541` we had an `EvNotDetected` event showing that the
+ state was `kPluggedInCharging` prior to the EV being not detected (normally
+ in a graceful shutdown this would be `kPluggedInNoDemand` or
+ `kPluggedInDemand`).
diff --git a/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h b/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h
index f22628d0f69def..e091fa9cf7c91c 100644
--- a/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h
+++ b/examples/energy-management-app/linux/include/CHIPProjectAppConfig.h
@@ -32,15 +32,13 @@
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY 0
-// Bulbs do not typically use this - enabled so we can use shell to discover commissioners
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT 1
#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE 1
-// TODO We don’t have one yet - but we’d need to change this
-#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 257 // 0x0101 = 257 = Dimmable Bulb
+#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 0x050C // Energy EVSE
#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_NAME 1
diff --git a/examples/energy-management-app/linux/main.cpp b/examples/energy-management-app/linux/main.cpp
index dddc6f53d76b20..23ec97e267f45d 100644
--- a/examples/energy-management-app/linux/main.cpp
+++ b/examples/energy-management-app/linux/main.cpp
@@ -17,6 +17,7 @@
*/
#include
+#include
#include
#include
#include
@@ -35,80 +36,227 @@ using namespace chip;
using namespace chip::app;
using namespace chip::app::Clusters;
-static EnergyEvseDelegate * gDelegate = nullptr;
-static EnergyEvseManager * gInstance = nullptr;
-static EVSEManufacturer * gEvseManufacturer = nullptr;
+static std::unique_ptr gEvseDelegate;
+static std::unique_ptr gEvseInstance;
+static std::unique_ptr gDEMDelegate;
+static std::unique_ptr gDEMInstance;
+static std::unique_ptr gEvseManufacturer;
-void ApplicationInit()
+EVSEManufacturer * EnergyEvse::GetEvseManufacturer()
+{
+ return gEvseManufacturer.get();
+}
+
+/*
+ * @brief Creates a Delegate and Instance for DEM
+ *
+ * The Instance is a container around the Delegate, so
+ * create the Delegate first, then wrap it in the Instance
+ * Then call the Instance->Init() to register the attribute and command handlers
+ */
+CHIP_ERROR DeviceEnergyManagementInit()
+{
+ if (gDEMDelegate || gDEMInstance)
+ {
+ ChipLogError(AppServer, "DEM Instance or Delegate already exist.");
+ return CHIP_ERROR_INCORRECT_STATE;
+ }
+
+ gDEMDelegate = std::make_unique();
+ if (!gDEMDelegate)
+ {
+ ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementDelegate");
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ /* Manufacturer may optionally not support all features, commands & attributes */
+ 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));
+
+ if (!gDEMInstance)
+ {
+ ChipLogError(AppServer, "Failed to allocate memory for DeviceEnergyManagementManager");
+ gDEMDelegate.reset();
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ CHIP_ERROR err = gDEMInstance->Init(); /* Register Attribute & Command handlers */
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(AppServer, "Init failed on gDEMInstance");
+ gDEMInstance.reset();
+ gDEMDelegate.reset();
+ return err;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR DeviceEnergyManagementShutdown()
+{
+ /* Do this in the order Instance first, then delegate
+ * Ensure we call the Instance->Shutdown to free attribute & command handlers first
+ */
+ if (gDEMInstance)
+ {
+ /* deregister attribute & command handlers */
+ gDEMInstance->Shutdown();
+ gDEMInstance.reset();
+ }
+ if (gDEMDelegate)
+ {
+ gDEMDelegate.reset();
+ }
+ return CHIP_NO_ERROR;
+}
+
+/*
+ * @brief Creates a Delegate and Instance for EVSE cluster
+ *
+ * The Instance is a container around the Delegate, so
+ * create the Delegate first, then wrap it in the Instance
+ * Then call the Instance->Init() to register the attribute and command handlers
+ */
+CHIP_ERROR EnergyEvseInit()
{
CHIP_ERROR err;
- if ((gDelegate != nullptr) || (gInstance != nullptr) || (gEvseManufacturer != nullptr))
+ if (gEvseDelegate || gEvseInstance)
{
- ChipLogError(AppServer, "EVSE Instance or Delegate, EvseManufacturer already exist.");
- return;
+ ChipLogError(AppServer, "EVSE Instance or Delegate already exist.");
+ return CHIP_ERROR_INCORRECT_STATE;
}
- gDelegate = new EnergyEvseDelegate();
- if (gDelegate == nullptr)
+ gEvseDelegate = std::make_unique();
+ if (!gEvseDelegate)
{
ChipLogError(AppServer, "Failed to allocate memory for EnergyEvseDelegate");
- return;
+ return CHIP_ERROR_NO_MEMORY;
}
/* Manufacturer may optionally not support all features, commands & attributes */
- gInstance =
- new EnergyEvseManager(EndpointId(ENERGY_EVSE_ENDPOINT), *gDelegate,
- BitMask(
- EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge,
- EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting, EnergyEvse::Feature::kV2x),
- BitMask(OptionalAttributes::kSupportsUserMaximumChargingCurrent,
- OptionalAttributes::kSupportsRandomizationWindow,
- OptionalAttributes::kSupportsApproximateEvEfficiency),
- BitMask(OptionalCommands::kSupportsStartDiagnostics));
-
- if (gInstance == nullptr)
+ gEvseInstance = std::make_unique(
+ EndpointId(ENERGY_EVSE_ENDPOINT), *gEvseDelegate,
+ BitMask(EnergyEvse::Feature::kChargingPreferences, EnergyEvse::Feature::kPlugAndCharge,
+ EnergyEvse::Feature::kRfid, EnergyEvse::Feature::kSoCReporting,
+ EnergyEvse::Feature::kV2x),
+ BitMask(EnergyEvse::OptionalAttributes::kSupportsUserMaximumChargingCurrent,
+ EnergyEvse::OptionalAttributes::kSupportsRandomizationWindow,
+ EnergyEvse::OptionalAttributes::kSupportsApproximateEvEfficiency),
+ BitMask(EnergyEvse::OptionalCommands::kSupportsStartDiagnostics));
+
+ if (!gEvseInstance)
{
ChipLogError(AppServer, "Failed to allocate memory for EnergyEvseManager");
- delete gDelegate;
- gDelegate = nullptr;
- return;
+ gEvseDelegate.reset();
+ return CHIP_ERROR_NO_MEMORY;
}
- err = gInstance->Init(); /* Register Attribute & Command handlers */
+ err = gEvseInstance->Init(); /* Register Attribute & Command handlers */
if (err != CHIP_NO_ERROR)
{
- ChipLogError(AppServer, "Init failed on gInstance");
- delete gInstance;
- delete gDelegate;
- gInstance = nullptr;
- gDelegate = nullptr;
- return;
+ ChipLogError(AppServer, "Init failed on gEvseInstance");
+ gEvseInstance.reset();
+ gEvseDelegate.reset();
+ return err;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EnergyEvseShutdown()
+{
+ /* Do this in the order Instance first, then delegate
+ * Ensure we call the Instance->Shutdown to free attribute & command handlers first
+ */
+ if (gEvseInstance)
+ {
+ /* deregister attribute & command handlers */
+ gEvseInstance->Shutdown();
+ gEvseInstance.reset();
}
- /* Now create EVSEManufacturer*/
- gEvseManufacturer = new EVSEManufacturer();
- if (gEvseManufacturer == nullptr)
+ if (gEvseDelegate)
+ {
+ gEvseDelegate.reset();
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+/*
+ * @brief Creates a EVSEManufacturer class to hold the EVSE & DEM clusters
+ *
+ * The Instance is a container around the Delegate, so
+ * create the Delegate first, then wrap it in the Instance
+ * Then call the Instance->Init() to register the attribute and command handlers
+ */
+CHIP_ERROR EVSEManufacturerInit()
+{
+ CHIP_ERROR err;
+
+ if (gEvseManufacturer)
+ {
+ ChipLogError(AppServer, "EvseManufacturer already exist.");
+ return CHIP_ERROR_INCORRECT_STATE;
+ }
+
+ /* Now create EVSEManufacturer */
+ // TODO this takes just the EVSE Instance for now, but will need the DEM adding
+ gEvseManufacturer = std::make_unique(gEvseInstance.get());
+ if (!gEvseManufacturer)
{
ChipLogError(AppServer, "Failed to allocate memory for EvseManufacturer");
- delete gInstance;
- delete gDelegate;
- gInstance = nullptr;
- gDelegate = nullptr;
- return;
+ return CHIP_ERROR_NO_MEMORY;
}
/* Call Manufacturer specific init */
- err = gEvseManufacturer->Init(gInstance);
+ err = gEvseManufacturer->Init();
if (err != CHIP_NO_ERROR)
{
ChipLogError(AppServer, "Init failed on gEvseManufacturer");
- delete gEvseManufacturer;
- delete gInstance;
- delete gDelegate;
- gEvseManufacturer = nullptr;
- gInstance = nullptr;
- gDelegate = nullptr;
+ gEvseManufacturer.reset();
+ return err;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+CHIP_ERROR EVSEManufacturerShutdown()
+{
+ if (gEvseManufacturer)
+ {
+ /* Shutdown the EVSEManufacturer */
+ gEvseManufacturer->Shutdown();
+ gEvseManufacturer.reset();
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void ApplicationInit()
+{
+ if (DeviceEnergyManagementInit() != CHIP_NO_ERROR)
+ {
+ return;
+ }
+
+ if (EnergyEvseInit() != CHIP_NO_ERROR)
+ {
+ DeviceEnergyManagementShutdown();
+ return;
+ }
+
+ if (EVSEManufacturerInit() != CHIP_NO_ERROR)
+ {
+ DeviceEnergyManagementShutdown();
+ EnergyEvseShutdown();
return;
}
}
@@ -117,18 +265,10 @@ void ApplicationShutdown()
{
ChipLogDetail(AppServer, "Energy Management App: ApplicationShutdown()");
- /* Shutdown the EVSEManufacturer*/
- gEvseManufacturer->Shutdown(gInstance);
-
- /* Shutdown the Instance - deregister attribute & command handler */
- gInstance->Shutdown();
-
- delete gEvseManufacturer;
- delete gInstance;
- delete gDelegate;
- gEvseManufacturer = nullptr;
- gInstance = nullptr;
- gDelegate = nullptr;
+ /* Shutdown in reverse order that they were created */
+ EVSEManufacturerShutdown(); /* Free the EVSEManufacturer */
+ EnergyEvseShutdown(); /* Free the EnergyEvse */
+ DeviceEnergyManagementShutdown(); /* Free the DEM */
}
int main(int argc, char * argv[])
diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.matter b/examples/light-switch-app/light-switch-common/light-switch-app.matter
index 19c9f5231f5e22..6aed1fec4b48ad 100644
--- a/examples/light-switch-app/light-switch-common/light-switch-app.matter
+++ b/examples/light-switch-app/light-switch-common/light-switch-app.matter
@@ -178,199 +178,6 @@ cluster Groups = 4 {
fabric command access(invoke: manage) AddGroupIfIdentifying(AddGroupIfIdentifyingRequest): DefaultSuccess = 5;
}
-/** Attributes and commands for scene configuration and manipulation. */
-provisional cluster Scenes = 5 {
- revision 5;
-
- bitmap CopyModeBitmap : bitmap8 {
- kCopyAllScenes = 0x1;
- }
-
- bitmap Feature : bitmap32 {
- kSceneNames = 0x1;
- kExplicit = 0x2;
- kTableSize = 0x4;
- kFabricScenes = 0x8;
- }
-
- bitmap NameSupportBitmap : bitmap8 {
- kSceneNames = 0x80;
- }
-
- struct AttributeValuePair {
- attrib_id attributeID = 0;
- int32u attributeValue = 1;
- }
-
- struct ExtensionFieldSet {
- cluster_id clusterID = 0;
- AttributeValuePair attributeValueList[] = 1;
- }
-
- fabric_scoped struct SceneInfoStruct {
- int8u sceneCount = 0;
- fabric_sensitive int8u currentScene = 1;
- fabric_sensitive group_id currentGroup = 2;
- fabric_sensitive boolean sceneValid = 3;
- int8u remainingCapacity = 4;
- fabric_idx fabricIndex = 254;
- }
-
- readonly attribute optional int8u sceneCount = 0;
- readonly attribute optional int8u currentScene = 1;
- readonly attribute optional group_id currentGroup = 2;
- readonly attribute optional boolean sceneValid = 3;
- readonly attribute NameSupportBitmap nameSupport = 4;
- readonly attribute optional nullable node_id lastConfiguredBy = 5;
- readonly attribute int16u sceneTableSize = 6;
- readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
- readonly attribute command_id generatedCommandList[] = 65528;
- readonly attribute command_id acceptedCommandList[] = 65529;
- readonly attribute event_id eventList[] = 65530;
- readonly attribute attrib_id attributeList[] = 65531;
- readonly attribute bitmap32 featureMap = 65532;
- readonly attribute int16u clusterRevision = 65533;
-
- request struct AddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct AddSceneResponse = 0 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct ViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct ViewSceneResponse = 1 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct RemoveSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct RemoveSceneResponse = 2 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RemoveAllScenesRequest {
- group_id groupID = 0;
- }
-
- response struct RemoveAllScenesResponse = 3 {
- status status = 0;
- group_id groupID = 1;
- }
-
- request struct StoreSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct StoreSceneResponse = 4 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct RecallSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- optional nullable int16u transitionTime = 2;
- }
-
- request struct GetSceneMembershipRequest {
- group_id groupID = 0;
- }
-
- response struct GetSceneMembershipResponse = 6 {
- status status = 0;
- nullable int8u capacity = 1;
- group_id groupID = 2;
- optional int8u sceneList[] = 3;
- }
-
- request struct EnhancedAddSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- int16u transitionTime = 2;
- char_string sceneName = 3;
- ExtensionFieldSet extensionFieldSets[] = 4;
- }
-
- response struct EnhancedAddSceneResponse = 64 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- }
-
- request struct EnhancedViewSceneRequest {
- group_id groupID = 0;
- int8u sceneID = 1;
- }
-
- response struct EnhancedViewSceneResponse = 65 {
- status status = 0;
- group_id groupID = 1;
- int8u sceneID = 2;
- optional int16u transitionTime = 3;
- optional char_string sceneName = 4;
- optional ExtensionFieldSet extensionFieldSets[] = 5;
- }
-
- request struct CopySceneRequest {
- CopyModeBitmap mode = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- group_id groupIdentifierTo = 3;
- int8u sceneIdentifierTo = 4;
- }
-
- response struct CopySceneResponse = 66 {
- status status = 0;
- group_id groupIdentifierFrom = 1;
- int8u sceneIdentifierFrom = 2;
- }
-
- /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
- fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
- /** Retrieves the requested scene entry from its Scene table. */
- fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
- /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
- /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
- fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
- /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
- fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
- /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
- fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
- /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
- fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
- /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
- fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
- /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
- fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
- /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
- fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
-}
-
/** Attributes and commands for switching devices between 'On' and 'Off' states. */
cluster OnOff = 6 {
revision 6;
@@ -2199,6 +2006,199 @@ cluster IcdManagement = 70 {
command access(invoke: manage) StayActiveRequest(): StayActiveResponse = 3;
}
+/** Attributes and commands for scene configuration and manipulation. */
+provisional cluster ScenesManagement = 98 {
+ revision 5;
+
+ bitmap CopyModeBitmap : bitmap8 {
+ kCopyAllScenes = 0x1;
+ }
+
+ bitmap Feature : bitmap32 {
+ kSceneNames = 0x1;
+ kExplicit = 0x2;
+ kTableSize = 0x4;
+ kFabricScenes = 0x8;
+ }
+
+ bitmap NameSupportBitmap : bitmap8 {
+ kSceneNames = 0x80;
+ }
+
+ struct AttributeValuePair {
+ attrib_id attributeID = 0;
+ int32u attributeValue = 1;
+ }
+
+ struct ExtensionFieldSet {
+ cluster_id clusterID = 0;
+ AttributeValuePair attributeValueList[] = 1;
+ }
+
+ fabric_scoped struct SceneInfoStruct {
+ int8u sceneCount = 0;
+ fabric_sensitive int8u currentScene = 1;
+ fabric_sensitive group_id currentGroup = 2;
+ fabric_sensitive boolean sceneValid = 3;
+ int8u remainingCapacity = 4;
+ fabric_idx fabricIndex = 254;
+ }
+
+ readonly attribute optional int8u sceneCount = 0;
+ readonly attribute optional int8u currentScene = 1;
+ readonly attribute optional group_id currentGroup = 2;
+ readonly attribute optional boolean sceneValid = 3;
+ readonly attribute NameSupportBitmap nameSupport = 4;
+ readonly attribute optional nullable node_id lastConfiguredBy = 5;
+ readonly attribute int16u sceneTableSize = 6;
+ readonly attribute SceneInfoStruct fabricSceneInfo[] = 7;
+ readonly attribute command_id generatedCommandList[] = 65528;
+ readonly attribute command_id acceptedCommandList[] = 65529;
+ readonly attribute event_id eventList[] = 65530;
+ readonly attribute attrib_id attributeList[] = 65531;
+ readonly attribute bitmap32 featureMap = 65532;
+ readonly attribute int16u clusterRevision = 65533;
+
+ request struct AddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
+
+ response struct AddSceneResponse = 0 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct ViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct ViewSceneResponse = 1 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
+
+ request struct RemoveSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct RemoveSceneResponse = 2 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct RemoveAllScenesRequest {
+ group_id groupID = 0;
+ }
+
+ response struct RemoveAllScenesResponse = 3 {
+ status status = 0;
+ group_id groupID = 1;
+ }
+
+ request struct StoreSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct StoreSceneResponse = 4 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct RecallSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ optional nullable int16u transitionTime = 2;
+ }
+
+ request struct GetSceneMembershipRequest {
+ group_id groupID = 0;
+ }
+
+ response struct GetSceneMembershipResponse = 6 {
+ status status = 0;
+ nullable int8u capacity = 1;
+ group_id groupID = 2;
+ optional int8u sceneList[] = 3;
+ }
+
+ request struct EnhancedAddSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ int16u transitionTime = 2;
+ char_string sceneName = 3;
+ ExtensionFieldSet extensionFieldSets[] = 4;
+ }
+
+ response struct EnhancedAddSceneResponse = 64 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ }
+
+ request struct EnhancedViewSceneRequest {
+ group_id groupID = 0;
+ int8u sceneID = 1;
+ }
+
+ response struct EnhancedViewSceneResponse = 65 {
+ status status = 0;
+ group_id groupID = 1;
+ int8u sceneID = 2;
+ optional int16u transitionTime = 3;
+ optional char_string sceneName = 4;
+ optional ExtensionFieldSet extensionFieldSets[] = 5;
+ }
+
+ request struct CopySceneRequest {
+ CopyModeBitmap mode = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
+ group_id groupIdentifierTo = 3;
+ int8u sceneIdentifierTo = 4;
+ }
+
+ response struct CopySceneResponse = 66 {
+ status status = 0;
+ group_id groupIdentifierFrom = 1;
+ int8u sceneIdentifierFrom = 2;
+ }
+
+ /** Add a scene to the scene table. Extension field sets are supported, and are inputed as '{"ClusterID": VALUE, "AttributeValueList":[{"AttributeId": VALUE, "AttributeValue": VALUE}]}' */
+ fabric command access(invoke: manage) AddScene(AddSceneRequest): AddSceneResponse = 0;
+ /** Retrieves the requested scene entry from its Scene table. */
+ fabric command ViewScene(ViewSceneRequest): ViewSceneResponse = 1;
+ /** Removes the requested scene entry, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveScene(RemoveSceneRequest): RemoveSceneResponse = 2;
+ /** Remove all scenes, corresponding to the value of the GroupID field, from its Scene Table */
+ fabric command access(invoke: manage) RemoveAllScenes(RemoveAllScenesRequest): RemoveAllScenesResponse = 3;
+ /** Adds the scene entry into its Scene Table along with all extension field sets corresponding to the current state of other clusters on the same endpoint */
+ fabric command access(invoke: manage) StoreScene(StoreSceneRequest): StoreSceneResponse = 4;
+ /** Set the attributes and corresponding state for each other cluster implemented on the endpoint accordingly to the resquested scene entry in the Scene Table */
+ fabric command RecallScene(RecallSceneRequest): DefaultSuccess = 5;
+ /** Get an unused scene identifier when no commissioning tool is in the network, or for a commissioning tool to get the used scene identifiers within a certain group */
+ fabric command GetSceneMembership(GetSceneMembershipRequest): GetSceneMembershipResponse = 6;
+ /** Allows a scene to be added using a finer scene transition time than the AddScene command. */
+ fabric command EnhancedAddScene(EnhancedAddSceneRequest): EnhancedAddSceneResponse = 64;
+ /** Allows a scene to be retrieved using a finer scene transition time than the ViewScene command */
+ fabric command EnhancedViewScene(EnhancedViewSceneRequest): EnhancedViewSceneResponse = 65;
+ /** Allows a client to efficiently copy scenes from one group/scene identifier pair to another group/scene identifier pair. */
+ fabric command CopyScene(CopySceneRequest): CopySceneResponse = 66;
+}
+
/** Attributes and commands for controlling the color properties of a color-capable light. */
cluster ColorControl = 768 {
revision 6;
@@ -2904,8 +2904,8 @@ endpoint 1 {
device type ma_onofflightswitch = 259, version 1;
binding cluster Identify;
- binding cluster Scenes;
binding cluster OnOff;
+ binding cluster ScenesManagement;
binding cluster ColorControl;
server cluster Identify {
diff --git a/examples/light-switch-app/light-switch-common/light-switch-app.zap b/examples/light-switch-app/light-switch-common/light-switch-app.zap
index 354ba583cf0b41..e652272b3b3664 100644
--- a/examples/light-switch-app/light-switch-common/light-switch-app.zap
+++ b/examples/light-switch-app/light-switch-common/light-switch-app.zap
@@ -4881,8 +4881,8 @@
]
},
{
- "name": "Scenes",
- "code": 5,
+ "name": "Scenes Management",
+ "code": 98,
"mfgCode": null,
"define": "SCENES_CLUSTER",
"side": "client",
diff --git a/examples/light-switch-app/qpg/.gn b/examples/light-switch-app/qpg/.gn
new file mode 100644
index 00000000000000..3d48789e30ab3d
--- /dev/null
+++ b/examples/light-switch-app/qpg/.gn
@@ -0,0 +1,28 @@
+# 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.
+
+import("//build_overrides/build.gni")
+
+# The location of the build configuration file.
+buildconfig = "${build_root}/config/BUILDCONFIG.gn"
+
+# CHIP uses angle bracket includes.
+check_system_includes = true
+
+default_args = {
+ target_cpu = "arm"
+ target_os = "freertos"
+
+ import("//args.gni")
+}
diff --git a/examples/light-switch-app/qpg/APPLICATION.md b/examples/light-switch-app/qpg/APPLICATION.md
new file mode 100644
index 00000000000000..487a8cbab22ed1
--- /dev/null
+++ b/examples/light-switch-app/qpg/APPLICATION.md
@@ -0,0 +1,17 @@
+# Matter QPG6105 Light Switch Example Application
+
+## Light-switch-app
+
+A light switch example application showing the use of
+[Matter](https://github.com/project-chip/connectedhomeip) on the Qorvo QPG6105
+can be found in this folder.
+
+## Qorvo SDK
+
+More detailed information on the Qorvo SDK can be found in the
+[Qorvo Matter SDK](https://github.com/Qorvo/QMatter).
+
+## More information
+
+For more information on our product line and support options, please visit
+[www.qorvo.com](https://www.qorvo.com) or contact us at
diff --git a/examples/light-switch-app/qpg/BUILD.gn b/examples/light-switch-app/qpg/BUILD.gn
new file mode 100644
index 00000000000000..a5488d27b33dbc
--- /dev/null
+++ b/examples/light-switch-app/qpg/BUILD.gn
@@ -0,0 +1,154 @@
+# Copyright(c) 2021 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.
+
+import("//build_overrides/build.gni")
+import("//build_overrides/chip.gni")
+import("//build_overrides/openthread.gni")
+import("//build_overrides/qpg_sdk.gni")
+
+import("${build_root}/config/defaults.gni")
+import("${chip_root}/src/platform/device.gni")
+import("${qpg_sdk_build_root}/qpg_executable.gni")
+import("${qpg_sdk_build_root}/qpg_sdk.gni")
+
+# declares chip_build_libshell = false
+import("${chip_root}/src/lib/lib.gni")
+
+# declares chip_enable_pw_rpc = false
+import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni")
+if (chip_enable_pw_rpc) {
+ import("//build_overrides/pigweed.gni")
+ import("$dir_pw_build/target_types.gni")
+}
+
+assert(current_os == "freertos")
+
+qpg_project_dir = "${chip_root}/examples/light-switch-app/qpg"
+examples_plat_dir = "${chip_root}/examples/platform/qpg"
+
+qpg_sdk("sdk") {
+ include_dirs = [
+ "${chip_root}/src/platform/qpg",
+ "${examples_plat_dir}",
+ "${qpg_project_dir}/include",
+ ]
+
+ defines = [ "PW_RPC_ENABLED=${chip_enable_pw_rpc}" ]
+}
+
+qpg_executable("light_switch_app") {
+ output_name = "chip-${qpg_target_ic}-light-switch-example.out"
+
+ sources = [
+ "${chip_root}/src/app/clusters/general-diagnostics-server/GenericFaultTestEventTriggerDelegate.cpp",
+ "${examples_plat_dir}/app/main.cpp",
+ "${examples_plat_dir}/ota/ota.cpp",
+ "src/AppTask.cpp",
+ "src/SwitchManager.cpp",
+ "src/ZclCallbacks.cpp",
+ "src/binding-handler.cpp",
+ ]
+
+ deps = [
+ ":sdk",
+ "${chip_root}/examples/light-switch-app/qpg/zap/",
+ "${chip_root}/examples/providers:device_info_provider",
+ "${chip_root}/src/lib",
+ "${chip_root}/src/setup_payload",
+ "${chip_root}/third_party/openthread/platforms:libopenthread-platform",
+ "${chip_root}/third_party/openthread/platforms:libopenthread-platform-utils",
+ "${chip_root}/third_party/qpg_sdk:qpg_switch_factorydata_lib",
+ "${chip_root}/third_party/qpg_sdk:qpg_switch_firmwaredata_lib",
+ ]
+
+ if (chip_openthread_ftd) {
+ deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-ftd" ]
+ } else {
+ deps += [ "${chip_root}/third_party/openthread/repo:libopenthread-mtd" ]
+ }
+
+ include_dirs = [
+ "include",
+ "${examples_plat_dir}/ota",
+ ]
+
+ defines = []
+
+ if (chip_enable_pw_rpc) {
+ defines += [
+ "PW_RPC_ATTRIBUTE_SERVICE=1",
+ "PW_RPC_BUTTON_SERVICE=1",
+ "PW_RPC_DEVICE_SERVICE=1",
+ "PW_RPC_LOCKING_SERVICE=1",
+ ]
+
+ sources += [
+ "${chip_root}/examples/common/pigweed/RpcService.cpp",
+ "${chip_root}/examples/common/pigweed/qpg/PigweedLoggerMutex.cpp",
+ "${examples_plat_dir}/PigweedLogger.cpp",
+ "${examples_plat_dir}/Rpc.cpp",
+ "${examples_plat_dir}/uart.c",
+ ]
+
+ deps += [
+ "$dir_pw_hdlc:rpc_channel_output",
+ "$dir_pw_stream:sys_io_stream",
+ "${chip_root}/config/qpg/lib/pw_rpc:pw_rpc",
+ "${chip_root}/examples/common/pigweed:attributes_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:button_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:device_service.nanopb_rpc",
+ "${chip_root}/examples/common/pigweed:locking_service.nanopb_rpc",
+ "${examples_plat_dir}/pw_sys_io:pw_sys_io_qpg",
+ ]
+
+ deps += pw_build_LINK_DEPS
+
+ include_dirs += [
+ "${chip_root}/examples/common",
+ "${chip_root}/examples/common/pigweed/qpg",
+ ]
+ } else {
+ # The below gives compiler erros in pigweed, therefore it is only enabled
+ # when rpc is not
+ cflags = [ "-Wconversion" ]
+ }
+
+ if (chip_build_libshell) {
+ deps += [ "${examples_plat_dir}:qpg-matter-shell" ]
+ } else {
+ if (chip_openthread_ftd) {
+ deps +=
+ [ "${chip_root}/third_party/openthread/repo:libopenthread-cli-ftd" ]
+ } else {
+ deps +=
+ [ "${chip_root}/third_party/openthread/repo:libopenthread-cli-mtd" ]
+ }
+ }
+
+ ldscript = "${qpg_sdk_root}/Libraries/Qorvo/QorvoStack/gen/QorvoStack_${qpg_target_ic}/QorvoStack_${qpg_target_ic}.ld"
+
+ inputs = [ ldscript ]
+
+ ldflags = [ "-T" + rebase_path(ldscript, root_build_dir) ]
+
+ output_dir = root_out_dir
+}
+
+group("qpg") {
+ deps = [ ":light_switch_app" ]
+}
+
+group("default") {
+ deps = [ ":qpg" ]
+}
diff --git a/examples/light-switch-app/qpg/README.md b/examples/light-switch-app/qpg/README.md
new file mode 100644
index 00000000000000..d8e070848f540c
--- /dev/null
+++ b/examples/light-switch-app/qpg/README.md
@@ -0,0 +1,15 @@
+---
+orphan: true
+---
+
+# Matter QPG6105 SDK
+
+## Qorvo SDK
+
+More detailed information on the Qorvo SDK can be found in the
+[Qorvo Matter SDK](https://github.com/Qorvo/QMatter).
+
+## More information
+
+For more information on our product line and support options, please visit
+[www.qorvo.com](https://www.qorvo.com) or contact us at
diff --git a/examples/light-switch-app/qpg/args.gni b/examples/light-switch-app/qpg/args.gni
new file mode 100644
index 00000000000000..d5dcdfe217c635
--- /dev/null
+++ b/examples/light-switch-app/qpg/args.gni
@@ -0,0 +1,35 @@
+# 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.
+
+import("//build_overrides/chip.gni")
+import("//build_overrides/pigweed.gni")
+import("${chip_root}/config/standalone/args.gni")
+import("${chip_root}/examples/platform/qpg/args.gni")
+
+qpg_sdk_target = get_label_info(":sdk", "label_no_toolchain")
+
+chip_enable_ota_requestor = true
+chip_openthread_ftd = false
+enable_sleepy_device = true
+chip_enable_icd_server = true
+
+# Disable lock tracking, since our FreeRTOS configuration does not set
+# INCLUDE_xSemaphoreGetMutexHolder
+chip_stack_lock_tracking = "none"
+
+matter_device_vid = "0xFFF1"
+matter_device_pid = "0x8006"
+
+pw_log_BACKEND = "${chip_root}/src/lib/support/pw_log_chip"
+pw_assert_BACKEND = "$dir_pw_assert_log:check_backend"
diff --git a/examples/light-switch-app/qpg/build_overrides b/examples/light-switch-app/qpg/build_overrides
new file mode 120000
index 00000000000000..e578e73312ebd1
--- /dev/null
+++ b/examples/light-switch-app/qpg/build_overrides
@@ -0,0 +1 @@
+../../build_overrides
\ No newline at end of file
diff --git a/examples/light-switch-app/qpg/include/AppConfig.h b/examples/light-switch-app/qpg/include/AppConfig.h
new file mode 100644
index 00000000000000..dfe8b494ea548c
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/AppConfig.h
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef APP_CONFIG_H
+#define APP_CONFIG_H
+
+#define APP_TASK_NAME "APP"
+
+// Mapping of Functional buttons
+#define APP_FUNCTION1_BUTTON BTN_SW1
+#define APP_FUNCTION2_SWITCH BTN_SW2
+#define APP_FUNCTION3_BUTTON BTN_SW3
+#define APP_FUNCTION4_BUTTON BTN_SW4
+#define APP_FUNCTION5_BUTTON BTN_SW5
+
+// Mapping of LEDs
+#define SYSTEM_STATE_LED LED_GREEN
+
+#endif // APP_CONFIG_H
diff --git a/examples/light-switch-app/qpg/include/AppEvent.h b/examples/light-switch-app/qpg/include/AppEvent.h
new file mode 100644
index 00000000000000..92f5b0ae5a1933
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/AppEvent.h
@@ -0,0 +1,51 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef APP_EVENT_H
+#define APP_EVENT_H
+
+struct AppEvent;
+typedef void (*EventHandler)(AppEvent *);
+
+struct AppEvent
+{
+ enum AppEventTypes
+ {
+ kEventType_Button = 0,
+ kEventType_Timer,
+ };
+
+ uint16_t Type;
+
+ union
+ {
+ struct
+ {
+ uint8_t ButtonIdx;
+ uint8_t Action;
+ } ButtonEvent;
+ struct
+ {
+ void * Context;
+ } TimerEvent;
+ };
+
+ EventHandler Handler;
+};
+
+#endif // APP_EVENT_H
diff --git a/examples/light-switch-app/qpg/include/AppTask.h b/examples/light-switch-app/qpg/include/AppTask.h
new file mode 100644
index 00000000000000..9284e068ab8509
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/AppTask.h
@@ -0,0 +1,89 @@
+/*
+ *
+ * Copyright (c) 2020 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.
+ */
+
+#ifndef APP_TASK_H
+#define APP_TASK_H
+
+#include
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "SwitchManager.h"
+#include "timers.h" // provides FreeRTOS timer support
+#include
+
+#include
+
+#define APP_NAME "Light-Switch-app"
+
+class AppTask
+{
+public:
+ CHIP_ERROR Init();
+ CHIP_ERROR StartAppTask();
+ static void AppTaskMain(void * pvParameter);
+
+ void PostEvent(const AppEvent * event);
+
+ void UpdateClusterState();
+
+ static void ButtonEventHandler(uint8_t btnIdx, bool btnPressed);
+
+private:
+ friend AppTask & GetAppTask(void);
+
+ static void InitServer(intptr_t arg);
+ static void OpenCommissioning(intptr_t arg);
+
+ void DispatchEvent(AppEvent * event);
+
+ static void FunctionTimerEventHandler(AppEvent * aEvent);
+ static void FunctionHandler(AppEvent * aEvent);
+
+ static void TimerEventHandler(chip::System::Layer * aLayer, void * aAppState);
+
+ static void MatterEventHandler(const chip::DeviceLayer::ChipDeviceEvent * event, intptr_t arg);
+ static void UpdateLEDs(void);
+
+ void StartTimer(uint32_t aTimeoutMs);
+ void CancelTimer(void);
+
+ enum Function_t
+ {
+ kFunction_NoneSelected = 0,
+ kFunction_SoftwareUpdate = 1,
+ kFunction_FactoryReset = 2,
+ kFunction_Invalid
+ } Function;
+
+ Function_t mFunction;
+ bool mFunctionTimerActive;
+
+ chip::DeviceLayer::FactoryDataProvider mFactoryDataProvider;
+
+ static AppTask sAppTask;
+};
+
+inline AppTask & GetAppTask(void)
+{
+ return AppTask::sAppTask;
+}
+
+#endif // APP_TASK_H
diff --git a/examples/light-switch-app/qpg/include/CHIPProjectConfig.h b/examples/light-switch-app/qpg/include/CHIPProjectConfig.h
new file mode 100644
index 00000000000000..0cce04bad354c0
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/CHIPProjectConfig.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * Copyright (c) 2020 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file
+ * Example project configuration file for CHIP.
+ *
+ * This is a place to put application or project-specific overrides
+ * to the default configuration values for general CHIP features.
+ *
+ */
+
+#pragma once
+
+// For convenience, enable Chip Security Test Mode and disable the requirement for
+// authentication in various protocols.
+//
+// WARNING: These options make it possible to circumvent basic Chip security functionality,
+// including message encryption. Because of this they MUST NEVER BE ENABLED IN PRODUCTION BUILDS.
+//
+#define CHIP_CONFIG_SECURITY_TEST_MODE 0
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+ *
+ * A uint32_t identifying the software version running on the device.
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0003 // Can't be removed, needed for OTA file generation.
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+ *
+ * A string identifying the software version running on the device.
+ * CHIP service currently expects the software version to be in the format
+ * {MAJOR_VERSION}.0d{MINOR_VERSION}
+ */
+#ifndef CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING
+#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "1.1" // Can't be removed, needed for OTA file generation.
+#endif
+
+/**
+ * CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE
+ *
+ * Enable support for Chip-over-BLE (CHIPoBLE).
+ */
+#define CHIP_DEVICE_CONFIG_ENABLE_CHIPOBLE 1
+
+/**
+ * @name Interaction Model object pool configuration.
+ *
+ * @brief
+ * The following definitions sets the maximum number of corresponding interaction model object pool size.
+ *
+ * * #CHIP_IM_MAX_NUM_COMMAND_HANDLER
+ * * #CHIP_IM_MAX_REPORTS_IN_FLIGHT
+ * * #CHIP_IM_MAX_NUM_WRITE_HANDLER
+ * * #CHIP_IM_MAX_NUM_WRITE_CLIENT
+ *
+ * @{
+ */
+
+/**
+ * @def CHIP_IM_MAX_NUM_COMMAND_HANDLER
+ *
+ * @brief Defines the maximum number of CommandHandler, limits the number of active commands transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_COMMAND_HANDLER 2
+
+/**
+ * @def CHIP_IM_MAX_REPORTS_IN_FLIGHT
+ *
+ * @brief Defines the maximum number of Reports, limits the traffic of read and subscription transactions.
+ */
+#define CHIP_IM_MAX_REPORTS_IN_FLIGHT 2
+
+/**
+ * @def CHIP_IM_MAX_NUM_WRITE_HANDLER
+ *
+ * @brief Defines the maximum number of WriteHandler, limits the number of active write transactions on server.
+ */
+#define CHIP_IM_MAX_NUM_WRITE_HANDLER 2
+
+/**
+ * @def CHIP_IM_MAX_NUM_WRITE_CLIENT
+ *
+ * @brief Defines the maximum number of WriteClient, limits the number of active write transactions on client.
+ */
+#define CHIP_IM_MAX_NUM_WRITE_CLIENT 2
+
+#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1
+
+/**
+ * @def CHIP_DEVICE_CONFIG_ENABLE_SED
+ *
+ * @brief Defines if a matter device is acting as a Sleepy End Device(SED)
+ */
+#ifndef CHIP_DEVICE_CONFIG_ENABLE_SED
+#define CHIP_DEVICE_CONFIG_ENABLE_SED 1
+#endif
+
+#ifndef CHIP_DEVICE_CONFIG_THREAD_FTD
+#define CHIP_DEVICE_CONFIG_THREAD_FTD 0
+#endif
diff --git a/examples/light-switch-app/qpg/include/SwitchManager.h b/examples/light-switch-app/qpg/include/SwitchManager.h
new file mode 100644
index 00000000000000..3f429f0c79a54e
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/SwitchManager.h
@@ -0,0 +1,72 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include
+#include
+
+#include
+
+#include "AppEvent.h"
+
+#include "FreeRTOS.h"
+#include "timers.h" // provides FreeRTOS timer support
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#define SWITCH_ENDPOINT_ID 1
+#define GENERICSWITCH_ENDPOINT_ID 2
+
+class SwitchManager
+{
+public:
+ enum Level_t
+ {
+ MIN_LEVEL = 0x40,
+ MAX_LEVEL = 0xfe,
+ };
+
+ enum Color_t
+ {
+ COLOR_AMBER = 1,
+ COLOR_GREEN,
+ };
+
+ void Init(void);
+ static void GenericSwitchInitialPress(void);
+ static void GenericSwitchReleasePress(void);
+ static void ToggleHandler(AppEvent * aEvent);
+ static void LevelHandler(AppEvent * aEvent);
+ static void ColorHandler(AppEvent * aEvent);
+
+private:
+ friend SwitchManager & SwitchMgr(void);
+
+ static SwitchManager sSwitch;
+};
+
+inline SwitchManager & SwitchMgr(void)
+{
+ return SwitchManager::sSwitch;
+}
diff --git a/examples/light-switch-app/qpg/include/binding-handler.h b/examples/light-switch-app/qpg/include/binding-handler.h
new file mode 100644
index 00000000000000..30a40701092959
--- /dev/null
+++ b/examples/light-switch-app/qpg/include/binding-handler.h
@@ -0,0 +1,42 @@
+/*
+ *
+ * Copyright (c) 2022 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.
+ */
+
+#pragma once
+
+#include
+
+void InitBindingManager(intptr_t context);
+void SwitchWorkerFunction(intptr_t context);
+
+typedef struct ColorXYData
+{
+ uint16_t x;
+ uint16_t y;
+} colorXYData_s;
+
+struct BindingCommandData
+{
+ chip::EndpointId localEndpointId = 1;
+ chip::CommandId commandId;
+ chip::ClusterId clusterId;
+ bool isGroup = false;
+ union
+ {
+ uint8_t level;
+ colorXYData_s colorXY;
+ };
+};
diff --git a/examples/light-switch-app/qpg/src/AppTask.cpp b/examples/light-switch-app/qpg/src/AppTask.cpp
new file mode 100644
index 00000000000000..9f6662206f2e74
--- /dev/null
+++ b/examples/light-switch-app/qpg/src/AppTask.cpp
@@ -0,0 +1,571 @@
+/*
+ *
+ * Copyright (c) 2021 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.
+ */
+
+// TODO - Intentionally grouped together
+#include "binding-handler.h"
+#include
+using namespace ::chip;
+
+#include "gpSched.h"
+#include "qvIO.h"
+
+#include "AppConfig.h"
+#include "AppEvent.h"
+#include "AppTask.h"
+#include "ota.h"
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+
+using namespace ::chip;
+using namespace ::chip::app;
+using namespace ::chip::TLV;
+using namespace ::chip::Credentials;
+using namespace ::chip::DeviceLayer;
+
+#include
+
+#define FACTORY_RESET_TRIGGER_TIMEOUT 3000
+#define FACTORY_RESET_CANCEL_WINDOW_TIMEOUT 3000
+#define APP_TASK_STACK_SIZE (2 * 1024)
+#define APP_TASK_PRIORITY 2
+#define APP_EVENT_QUEUE_SIZE 10
+
+namespace {
+TaskHandle_t sAppTaskHandle;
+QueueHandle_t sAppEventQueue;
+
+bool sIsThreadProvisioned = false;
+bool sIsThreadEnabled = false;
+bool sHaveBLEConnections = false;
+bool sIsBLEAdvertisingEnabled = false;
+
+// NOTE! This key is for test/certification only and should not be available in production devices!
+uint8_t sTestEventTriggerEnableKey[TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
+ 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff };
+
+uint8_t sAppEventQueueBuffer[APP_EVENT_QUEUE_SIZE * sizeof(AppEvent)];
+
+StaticQueue_t sAppEventQueueStruct;
+
+StackType_t appStack[APP_TASK_STACK_SIZE / sizeof(StackType_t)];
+StaticTask_t appTaskStruct;
+
+chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider;
+} // namespace
+
+AppTask AppTask::sAppTask;
+
+namespace {
+constexpr int extDiscTimeoutSecs = 20;
+}
+
+Clusters::Identify::EffectIdentifierEnum sIdentifyEffect = Clusters::Identify::EffectIdentifierEnum::kStopEffect;
+
+/**********************************************************
+ * Identify Callbacks
+ *********************************************************/
+
+namespace {
+void OnTriggerIdentifyEffectCompleted(chip::System::Layer * systemLayer, void * appState)
+{
+ sIdentifyEffect = Clusters::Identify::EffectIdentifierEnum::kStopEffect;
+}
+} // namespace
+
+void OnTriggerIdentifyEffect(Identify * identify)
+{
+ sIdentifyEffect = identify->mCurrentEffectIdentifier;
+
+ if (identify->mEffectVariant != Clusters::Identify::EffectVariantEnum::kDefault)
+ {
+ ChipLogDetail(AppServer, "Identify Effect Variant unsupported. Using default");
+ }
+
+ switch (sIdentifyEffect)
+ {
+ case Clusters::Identify::EffectIdentifierEnum::kBlink:
+ case Clusters::Identify::EffectIdentifierEnum::kBreathe:
+ case Clusters::Identify::EffectIdentifierEnum::kOkay:
+ case Clusters::Identify::EffectIdentifierEnum::kChannelChange:
+ SystemLayer().ScheduleLambda([identify] {
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(5), OnTriggerIdentifyEffectCompleted,
+ identify);
+ });
+ break;
+ case Clusters::Identify::EffectIdentifierEnum::kFinishEffect:
+ SystemLayer().ScheduleLambda([identify] {
+ (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify);
+ (void) chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Seconds16(1), OnTriggerIdentifyEffectCompleted,
+ identify);
+ });
+ break;
+ case Clusters::Identify::EffectIdentifierEnum::kStopEffect:
+ SystemLayer().ScheduleLambda(
+ [identify] { (void) chip::DeviceLayer::SystemLayer().CancelTimer(OnTriggerIdentifyEffectCompleted, identify); });
+ sIdentifyEffect = Clusters::Identify::EffectIdentifierEnum::kStopEffect;
+ break;
+ default:
+ ChipLogProgress(Zcl, "No identifier effect");
+ }
+}
+
+Identify gIdentify = {
+ chip::EndpointId{ 1 },
+ [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); },
+ [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); },
+ Clusters::Identify::IdentifyTypeEnum::kVisibleIndicator,
+ OnTriggerIdentifyEffect,
+};
+
+void LockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().LockThreadStack();
+}
+
+void UnlockOpenThreadTask(void)
+{
+ chip::DeviceLayer::ThreadStackMgr().UnlockThreadStack();
+}
+
+CHIP_ERROR AppTask::StartAppTask()
+{
+ sAppEventQueue = xQueueCreateStatic(APP_EVENT_QUEUE_SIZE, sizeof(AppEvent), sAppEventQueueBuffer, &sAppEventQueueStruct);
+ if (sAppEventQueue == nullptr)
+ {
+ ChipLogError(NotSpecified, "Failed to allocate app event queue");
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ // Start App task.
+ sAppTaskHandle = xTaskCreateStatic(AppTaskMain, APP_TASK_NAME, ArraySize(appStack), nullptr, 1, appStack, &appTaskStruct);
+ if (sAppTaskHandle == nullptr)
+ {
+ return CHIP_ERROR_NO_MEMORY;
+ }
+
+ return CHIP_NO_ERROR;
+}
+
+void AppTask::InitServer(intptr_t arg)
+{
+ static chip::CommonCaseDeviceServerInitParams initParams;
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+
+ gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate);
+ chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider);
+
+ chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams;
+ nativeParams.lockCb = LockOpenThreadTask;
+ nativeParams.unlockCb = UnlockOpenThreadTask;
+ nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance();
+ initParams.endpointNativeParams = static_cast(&nativeParams);
+
+ // Use GenericFaultTestEventTriggerDelegate to inject faults
+ static GenericFaultTestEventTriggerDelegate testEventTriggerDelegate{ ByteSpan(sTestEventTriggerEnableKey) };
+ (void) initParams.InitializeStaticResourcesBeforeServerInit();
+ initParams.testEventTriggerDelegate = &testEventTriggerDelegate;
+
+ chip::Server::GetInstance().Init(initParams);
+
+#if CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY
+ chip::app::DnssdServer::Instance().SetExtendedDiscoveryTimeoutSecs(extDiscTimeoutSecs);
+#endif
+
+ // Open commissioning after boot if no fabric was available
+ if (chip::Server::GetInstance().GetFabricTable().FabricCount() == 0)
+ {
+ PlatformMgr().ScheduleWork(OpenCommissioning, 0);
+ }
+}
+
+void AppTask::OpenCommissioning(intptr_t arg)
+{
+ // Enable BLE advertisements
+ chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow();
+ ChipLogProgress(NotSpecified, "BLE advertising started. Waiting for Pairing.");
+}
+
+CHIP_ERROR AppTask::Init()
+{
+ CHIP_ERROR err = CHIP_NO_ERROR;
+
+ PlatformMgr().AddEventHandler(MatterEventHandler, 0);
+
+ ChipLogProgress(NotSpecified, "Current Software Version: %s", CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING);
+
+ // Init ZCL Data Model and start server
+ PlatformMgr().ScheduleWork(InitServer, 0);
+
+ ReturnErrorOnFailure(mFactoryDataProvider.Init());
+ SetDeviceInstanceInfoProvider(&mFactoryDataProvider);
+ SetCommissionableDataProvider(&mFactoryDataProvider);
+
+ SetDeviceAttestationCredentialsProvider(&mFactoryDataProvider);
+
+ SwitchMgr().Init();
+ UpdateClusterState();
+
+ // Setup button handler
+ qvIO_SetBtnCallback(ButtonEventHandler);
+
+ DeviceLayer::PlatformMgr().ScheduleWork(InitBindingManager);
+
+ // Log device configuration
+ ConfigurationMgr().LogDeviceConfig();
+ PrintOnboardingCodes(chip::RendezvousInformationFlags(chip::RendezvousInformationFlag::kBLE));
+
+ sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned();
+ sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled();
+ sHaveBLEConnections = (ConnectivityMgr().NumBLEConnections() != 0);
+ sIsBLEAdvertisingEnabled = ConnectivityMgr().IsBLEAdvertisingEnabled();
+ UpdateLEDs();
+
+ return err;
+}
+
+void AppTask::AppTaskMain(void * pvParameter)
+{
+ AppEvent event;
+
+ while (true)
+ {
+ BaseType_t eventReceived = xQueueReceive(sAppEventQueue, &event, portMAX_DELAY);
+ while (eventReceived == pdTRUE)
+ {
+ sAppTask.DispatchEvent(&event);
+ eventReceived = xQueueReceive(sAppEventQueue, &event, 0);
+ }
+ }
+}
+
+void AppTask::ButtonEventHandler(uint8_t btnIdx, bool btnPressed)
+{
+ ChipLogProgress(NotSpecified, "ButtonEventHandler %d, %d", btnIdx, btnPressed);
+
+ AppEvent button_event = {};
+ button_event.Type = AppEvent::kEventType_Button;
+ button_event.ButtonEvent.ButtonIdx = btnIdx;
+ button_event.ButtonEvent.Action = btnPressed;
+
+ switch (btnIdx)
+ {
+ case APP_FUNCTION1_BUTTON: {
+ if (!btnPressed)
+ {
+ return;
+ }
+
+ ChipLogProgress(NotSpecified, "Level Button pressed");
+ button_event.Handler = SwitchMgr().LevelHandler;
+ break;
+ }
+ case APP_FUNCTION2_SWITCH: {
+ if (!btnPressed)
+ {
+ ChipLogProgress(NotSpecified, "Switch initial press");
+ SwitchMgr().GenericSwitchInitialPress();
+ }
+ else
+ {
+ ChipLogProgress(NotSpecified, "Switch release press");
+ SwitchMgr().GenericSwitchReleasePress();
+ }
+ break;
+ }
+ case APP_FUNCTION3_BUTTON: {
+ if (!btnPressed)
+ {
+ return;
+ }
+ ChipLogProgress(NotSpecified, "Color button pressed");
+ button_event.Handler = SwitchMgr().ColorHandler;
+ break;
+ }
+ case APP_FUNCTION4_BUTTON: {
+ if (!btnPressed)
+ {
+ return;
+ }
+
+ ChipLogProgress(NotSpecified, "Toggle Button pressed");
+ button_event.Handler = SwitchMgr().ToggleHandler;
+ break;
+ }
+ case APP_FUNCTION5_BUTTON: {
+ button_event.Handler = FunctionHandler;
+ break;
+ }
+ default: {
+ // invalid button
+ return;
+ }
+ }
+
+ sAppTask.PostEvent(&button_event);
+}
+
+void AppTask::TimerEventHandler(chip::System::Layer * aLayer, void * aAppState)
+{
+ AppEvent event;
+ event.Type = AppEvent::kEventType_Timer;
+ event.TimerEvent.Context = aAppState;
+ event.Handler = FunctionTimerEventHandler;
+ sAppTask.PostEvent(&event);
+}
+
+void AppTask::FunctionTimerEventHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Timer)
+ {
+ return;
+ }
+
+ // If we reached here, the button was held past FACTORY_RESET_TRIGGER_TIMEOUT,
+ // initiate factory reset
+ if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+ {
+ ChipLogProgress(NotSpecified, "[BTN] Factory Reset selected. Release within %us to cancel.",
+ FACTORY_RESET_CANCEL_WINDOW_TIMEOUT / 1000);
+
+ // Start timer for FACTORY_RESET_CANCEL_WINDOW_TIMEOUT to allow user to
+ // cancel, if required.
+ sAppTask.StartTimer(FACTORY_RESET_CANCEL_WINDOW_TIMEOUT);
+
+ sAppTask.mFunction = kFunction_FactoryReset;
+
+ // Turn off all LEDs before starting blink to make sure blink is
+ // co-ordinated.
+ qvIO_LedSet(SYSTEM_STATE_LED, false);
+
+ qvIO_LedBlink(SYSTEM_STATE_LED, 500, 500);
+ }
+ else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+ {
+ // Actually trigger Factory Reset
+ sAppTask.mFunction = kFunction_NoneSelected;
+ chip::Server::GetInstance().ScheduleFactoryReset();
+ }
+}
+
+void AppTask::FunctionHandler(AppEvent * aEvent)
+{
+ if (aEvent->ButtonEvent.ButtonIdx != APP_FUNCTION5_BUTTON)
+ {
+ return;
+ }
+
+ // To trigger software update: press the APP_FUNCTION_BUTTON button briefly (<
+ // FACTORY_RESET_TRIGGER_TIMEOUT) To initiate factory reset: press the
+ // APP_FUNCTION_BUTTON for FACTORY_RESET_TRIGGER_TIMEOUT +
+ // FACTORY_RESET_CANCEL_WINDOW_TIMEOUT All LEDs start blinking after
+ // FACTORY_RESET_TRIGGER_TIMEOUT to signal factory reset has been initiated.
+ // To cancel factory reset: release the APP_FUNCTION_BUTTON once all LEDs
+ // start blinking within the FACTORY_RESET_CANCEL_WINDOW_TIMEOUT
+ if (aEvent->ButtonEvent.Action == true)
+ {
+ if (!sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_NoneSelected)
+ {
+ ChipLogProgress(NotSpecified, "[BTN] Hold to select function:");
+ ChipLogProgress(NotSpecified, "[BTN] - Trigger OTA (0-3s)");
+ ChipLogProgress(NotSpecified, "[BTN] - Factory Reset (>6s)");
+
+ sAppTask.StartTimer(FACTORY_RESET_TRIGGER_TIMEOUT);
+
+ sAppTask.mFunction = kFunction_SoftwareUpdate;
+ }
+ }
+ else
+ {
+ // If the button was released before factory reset got initiated, trigger a
+ // software update.
+ if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_SoftwareUpdate)
+ {
+ sAppTask.CancelTimer();
+
+ sAppTask.mFunction = kFunction_NoneSelected;
+
+ ChipLogProgress(NotSpecified, "[BTN] Triggering OTA Query");
+
+ TriggerOTAQuery();
+ }
+ else if (sAppTask.mFunctionTimerActive && sAppTask.mFunction == kFunction_FactoryReset)
+ {
+ sAppTask.CancelTimer();
+
+ // Change the function to none selected since factory reset has been
+ // canceled.
+ sAppTask.mFunction = kFunction_NoneSelected;
+
+ ChipLogProgress(NotSpecified, "[BTN] Factory Reset has been Canceled");
+ }
+ }
+}
+
+void AppTask::CancelTimer()
+{
+ chip::DeviceLayer::SystemLayer().CancelTimer(TimerEventHandler, this);
+ mFunctionTimerActive = false;
+}
+
+void AppTask::StartTimer(uint32_t aTimeoutInMs)
+{
+ CHIP_ERROR err;
+
+ chip::DeviceLayer::SystemLayer().CancelTimer(TimerEventHandler, this);
+ err = chip::DeviceLayer::SystemLayer().StartTimer(chip::System::Clock::Milliseconds32(aTimeoutInMs), TimerEventHandler, this);
+ SuccessOrExit(err);
+
+ mFunctionTimerActive = true;
+exit:
+ if (err != CHIP_NO_ERROR)
+ {
+ ChipLogError(NotSpecified, "StartTimer failed %s: ", chip::ErrorStr(err));
+ }
+}
+
+void AppTask::PostEvent(const AppEvent * aEvent)
+{
+ if (sAppEventQueue != nullptr)
+ {
+ if (!xQueueSend(sAppEventQueue, aEvent, 1))
+ {
+ ChipLogError(NotSpecified, "Failed to post event to app task event queue");
+ }
+ }
+ else
+ {
+ ChipLogError(NotSpecified, "Event Queue is nullptr should never happen");
+ }
+}
+
+void AppTask::DispatchEvent(AppEvent * aEvent)
+{
+ if (aEvent->Handler)
+ {
+ aEvent->Handler(aEvent);
+ }
+ else
+ {
+ ChipLogError(NotSpecified, "Event received with no handler. Dropping event.");
+ }
+}
+
+/**
+ * Update cluster status after application level changes
+ */
+void AppTask::UpdateClusterState(void)
+{
+ ChipLogProgress(NotSpecified, "UpdateClusterState");
+
+ /* write the new attribute value based on attribute setter API.
+ example API usage of on-off attribute:
+
+ EmberAfStatus status = Clusters::OnOff::Attributes::OnOff::Set(QPG_LIGHT_ENDPOINT_ID, LightingMgr().IsTurnedOn());
+
+ if (status != EMBER_ZCL_STATUS_SUCCESS)
+ {
+ ChipLogError(NotSpecified, "ERR: updating on/off %x", status);
+ }
+ */
+}
+
+void AppTask::UpdateLEDs(void)
+{
+ // If system has "full connectivity", keep the LED On constantly.
+ //
+ // If thread and service provisioned, but not attached to the thread network
+ // yet OR no connectivity to the service OR subscriptions are not fully
+ // established THEN blink the LED Off for a short period of time.
+ //
+ // If the system has ble connection(s) uptill the stage above, THEN blink
+ // the LEDs at an even rate of 100ms.
+ //
+ // Otherwise, blink the LED ON for a very short time.
+ if (sIsThreadProvisioned && sIsThreadEnabled)
+ {
+ qvIO_LedSet(SYSTEM_STATE_LED, true);
+ }
+ else if (sHaveBLEConnections)
+ {
+ qvIO_LedBlink(SYSTEM_STATE_LED, 100, 100);
+ }
+ else if (sIsBLEAdvertisingEnabled)
+ {
+ qvIO_LedBlink(SYSTEM_STATE_LED, 50, 50);
+ }
+ else
+ {
+ // not commissioned yet
+ qvIO_LedBlink(SYSTEM_STATE_LED, 50, 950);
+ }
+}
+
+void AppTask::MatterEventHandler(const ChipDeviceEvent * event, intptr_t)
+{
+ switch (event->Type)
+ {
+ case DeviceEventType::kServiceProvisioningChange: {
+ sIsThreadProvisioned = event->ServiceProvisioningChange.IsServiceProvisioned;
+ UpdateLEDs();
+ break;
+ }
+
+ case DeviceEventType::kThreadConnectivityChange: {
+ sIsThreadEnabled = (event->ThreadConnectivityChange.Result == kConnectivity_Established);
+ UpdateLEDs();
+ break;
+ }
+
+ case DeviceEventType::kCHIPoBLEConnectionEstablished: {
+ sHaveBLEConnections = true;
+ UpdateLEDs();
+ break;
+ }
+
+ case DeviceEventType::kCHIPoBLEConnectionClosed: {
+ sHaveBLEConnections = false;
+ UpdateLEDs();
+ break;
+ }
+
+ case DeviceEventType::kCHIPoBLEAdvertisingChange: {
+ sIsBLEAdvertisingEnabled = (event->CHIPoBLEAdvertisingChange.Result == kActivity_Started);
+ UpdateLEDs();
+ break;
+ }
+
+ default:
+ break;
+ }
+}
diff --git a/examples/light-switch-app/qpg/src/SwitchManager.cpp b/examples/light-switch-app/qpg/src/SwitchManager.cpp
new file mode 100644
index 00000000000000..45d7079b578598
--- /dev/null
+++ b/examples/light-switch-app/qpg/src/SwitchManager.cpp
@@ -0,0 +1,126 @@
+/*
+ *
+ * Copyright (c) 2021 Project CHIP Authors
+ * Copyright (c) 2019 Google LLC.
+ * 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 "SwitchManager.h"
+#include "binding-handler.h"
+#include "qvIO.h"
+#include
+#include
+
+SwitchManager SwitchManager::sSwitch;
+using namespace ::chip;
+using namespace chip::DeviceLayer;
+
+void SwitchManager::Init(void)
+{
+ // init - TODO
+}
+
+void SwitchManager::ToggleHandler(AppEvent * aEvent)
+{
+ if (aEvent->Type != AppEvent::kEventType_Button)
+ {
+ ChipLogError(NotSpecified, "Event type not supported!");
+ return;
+ }
+
+ BindingCommandData * data = Platform::New();
+ VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "CHIP_ERROR_NO_MEMORY"));
+
+ data->localEndpointId = SWITCH_ENDPOINT_ID;
+ data->clusterId = chip::app::Clusters::OnOff::Id;
+ data->commandId = chip::app::Clusters::OnOff::Commands::Toggle::Id;
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+}
+
+void SwitchManager::LevelHandler(AppEvent * aEvent)
+{
+ static uint8_t sLevel;
+
+ if (aEvent->Type != AppEvent::kEventType_Button)
+ {
+ ChipLogError(NotSpecified, "Event type not supported!");
+ return;
+ }
+
+ BindingCommandData * data = Platform::New();
+ VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "CHIP_ERROR_NO_MEMORY"));
+
+ data->localEndpointId = SWITCH_ENDPOINT_ID;
+ data->clusterId = chip::app::Clusters::LevelControl::Id;
+ data->commandId = chip::app::Clusters::LevelControl::Commands::MoveToLevel::Id;
+ data->level = (sLevel == MIN_LEVEL) ? MAX_LEVEL : MIN_LEVEL;
+ sLevel = data->level;
+
+ ChipLogProgress(NotSpecified, "Level - %d", sLevel);
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+}
+
+void SwitchManager::ColorHandler(AppEvent * aEvent)
+{
+ static uint8_t color;
+
+ if (aEvent->Type != AppEvent::kEventType_Button)
+ {
+ ChipLogError(NotSpecified, "Event type not supported!");
+ return;
+ }
+
+ BindingCommandData * data = Platform::New();
+ VerifyOrReturn(data != nullptr, ChipLogError(NotSpecified, "CHIP_ERROR_NO_MEMORY"));
+
+ data->localEndpointId = SWITCH_ENDPOINT_ID;
+ data->clusterId = chip::app::Clusters::ColorControl::Id;
+ data->commandId = chip::app::Clusters::ColorControl::Commands::MoveToColor::Id;
+ if (color == COLOR_AMBER)
+ {
+ color = COLOR_GREEN;
+ data->colorXY.x = 36044;
+ data->colorXY.y = 29490;
+ ChipLogProgress(NotSpecified, "Color - AMBER");
+ }
+ else
+ {
+ color = COLOR_AMBER;
+ data->colorXY.x = 7536;
+ data->colorXY.y = 54131;
+ ChipLogProgress(NotSpecified, "Color - GREEN");
+ }
+
+ DeviceLayer::PlatformMgr().ScheduleWork(SwitchWorkerFunction, reinterpret_cast(data));
+}
+
+void SwitchManager::GenericSwitchInitialPress(void)
+{
+ // Press moves Position from 0 (idle) to 1 (press)
+ uint8_t newPosition = 1;
+
+ SystemLayer().ScheduleLambda(
+ [newPosition] { chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition); });
+}
+
+void SwitchManager::GenericSwitchReleasePress(void)
+{
+ // Release moves Position from 1 (press) to 0
+ uint8_t newPosition = 0;
+
+ SystemLayer().ScheduleLambda(
+ [newPosition] { chip::app::Clusters::Switch::Attributes::CurrentPosition::Set(GENERICSWITCH_ENDPOINT_ID, newPosition); });
+}
diff --git a/examples/light-switch-app/qpg/src/ZclCallbacks.cpp b/examples/light-switch-app/qpg/src/ZclCallbacks.cpp
new file mode 100644
index 00000000000000..373932454cc972
--- /dev/null
+++ b/examples/light-switch-app/qpg/src/ZclCallbacks.cpp
@@ -0,0 +1,38 @@
+/*
+ *
+ * Copyright (c) 2021 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 "AppTask.h"
+
+#include