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 9c3e474946addf..a63bd698b5f656 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 @@ -3716,6 +3716,72 @@ cluster ActivatedCarbonFilterMonitoring = 114 { command ResetCondition(): DefaultSuccess = 0; } +/** This cluster is used to configure a valve. */ +provisional cluster ValveConfigurationAndControl = 129 { + revision 1; + + enum StatusCodeEnum : enum8 { + kFailureDueToFault = 2; + } + + enum ValveStateEnum : enum8 { + kClosed = 0; + kOpen = 1; + kTransitioning = 2; + } + + bitmap Feature : bitmap32 { + kTimeSync = 0x1; + kLevel = 0x2; + } + + bitmap ValveFaultBitmap : bitmap16 { + kGeneralFault = 0x1; + kBlocked = 0x2; + kLeaking = 0x4; + kNotConnected = 0x8; + kShortCircuit = 0x10; + kCurrentExceeded = 0x20; + } + + info event ValveStateChanged = 0 { + ValveStateEnum valveState = 0; + optional percent valveLevel = 1; + } + + info event ValveFault = 1 { + ValveFaultBitmap valveFault = 0; + } + + readonly attribute nullable elapsed_s openDuration = 0; + attribute nullable elapsed_s defaultOpenDuration = 1; + readonly attribute optional nullable epoch_us autoCloseTime = 2; + readonly attribute nullable elapsed_s remainingDuration = 3; + readonly attribute nullable ValveStateEnum currentState = 4; + readonly attribute nullable ValveStateEnum targetState = 5; + readonly attribute optional nullable percent currentLevel = 6; + readonly attribute optional nullable percent targetLevel = 7; + attribute optional percent defaultOpenLevel = 8; + readonly attribute optional ValveFaultBitmap valveFault = 9; + readonly attribute optional int8u levelStep = 10; + 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 OpenRequest { + optional nullable elapsed_s openDuration = 0; + optional percent targetLevel = 1; + } + + /** This command is used to set the valve to its open position. */ + command Open(OpenRequest): DefaultSuccess = 0; + /** This command is used to set the valve to its closed position. */ + command Close(): DefaultSuccess = 1; +} + /** This cluster provides a mechanism for querying data about the electrical energy imported or provided by the server. */ provisional cluster ElectricalEnergyMeasurement = 145 { revision 1; @@ -7426,6 +7492,31 @@ endpoint 1 { handle command ResetCondition; } + server cluster ValveConfigurationAndControl { + emits event ValveStateChanged; + emits event ValveFault; + ram attribute openDuration; + persist attribute defaultOpenDuration; + ram attribute autoCloseTime; + callback attribute remainingDuration; + ram attribute currentState; + ram attribute targetState; + ram attribute currentLevel; + ram attribute targetLevel; + persist attribute defaultOpenLevel default = 100; + ram attribute valveFault default = 0; + ram attribute levelStep default = 1; + callback attribute generatedCommandList; + callback attribute acceptedCommandList; + callback attribute eventList; + callback attribute attributeList; + ram attribute featureMap default = 3; + ram attribute clusterRevision default = 1; + + handle command Open; + handle command Close; + } + server cluster ElectricalEnergyMeasurement { emits event CumulativeEnergyMeasured; emits event PeriodicEnergyMeasured; 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 0c14d72717e091..c69cbe4cd4c4bf 100644 --- a/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap +++ b/examples/all-clusters-app/all-clusters-common/all-clusters-app.zap @@ -17,12 +17,6 @@ } ], "package": [ - { - "pathRelativity": "relativeToZap", - "path": "../../../src/app/zap-templates/app-templates.json", - "type": "gen-templates-json", - "version": "chip-v1" - }, { "pathRelativity": "relativeToZap", "path": "../../../src/app/zap-templates/zcl/zcl-with-test-extensions.json", @@ -30,6 +24,12 @@ "category": "matter", "version": 1, "description": "Matter SDK ZCL data with some extensions" + }, + { + "pathRelativity": "relativeToZap", + "path": "../../../src/app/zap-templates/app-templates.json", + "type": "gen-templates-json", + "version": "chip-v1" } ], "endpointTypes": [ @@ -8427,7 +8427,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -8459,7 +8459,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -8475,7 +8475,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -8491,7 +8491,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -8507,7 +8507,7 @@ "storageOption": "External", "singleton": 0, "bounded": 0, - "defaultValue": "", + "defaultValue": null, "reportable": 1, "minInterval": 1, "maxInterval": 65534, @@ -11803,6 +11803,323 @@ } ] }, + { + "name": "Valve Configuration and Control", + "code": 129, + "mfgCode": null, + "define": "VALVE_CONFIGURATION_AND_CONTROL_CLUSTER", + "side": "server", + "enabled": 1, + "apiMaturity": "provisional", + "commands": [ + { + "name": "Open", + "code": 0, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + }, + { + "name": "Close", + "code": 1, + "mfgCode": null, + "source": "client", + "isIncoming": 1, + "isEnabled": 1 + } + ], + "attributes": [ + { + "name": "OpenDuration", + "code": 0, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultOpenDuration", + "code": 1, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "AutoCloseTime", + "code": 2, + "mfgCode": null, + "side": "server", + "type": "epoch_us", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "RemainingDuration", + "code": 3, + "mfgCode": null, + "side": "server", + "type": "elapsed_s", + "included": 1, + "storageOption": "External", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentState", + "code": 4, + "mfgCode": null, + "side": "server", + "type": "ValveStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetState", + "code": 5, + "mfgCode": null, + "side": "server", + "type": "ValveStateEnum", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "CurrentLevel", + "code": 6, + "mfgCode": null, + "side": "server", + "type": "percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "TargetLevel", + "code": 7, + "mfgCode": null, + "side": "server", + "type": "percent", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": null, + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "DefaultOpenLevel", + "code": 8, + "mfgCode": null, + "side": "server", + "type": "percent", + "included": 1, + "storageOption": "NVM", + "singleton": 0, + "bounded": 0, + "defaultValue": "100", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "ValveFault", + "code": 9, + "mfgCode": null, + "side": "server", + "type": "ValveFaultBitmap", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "0", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + }, + { + "name": "LevelStep", + "code": 10, + "mfgCode": null, + "side": "server", + "type": "int8u", + "included": 1, + "storageOption": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "1", + "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": "RAM", + "singleton": 0, + "bounded": 0, + "defaultValue": "3", + "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": "1", + "reportable": 1, + "minInterval": 1, + "maxInterval": 65534, + "reportableChange": 0 + } + ], + "events": [ + { + "name": "ValveStateChanged", + "code": 0, + "mfgCode": null, + "side": "server", + "included": 1 + }, + { + "name": "ValveFault", + "code": 1, + "mfgCode": null, + "side": "server", + "included": 1 + } + ] + }, { "name": "Electrical Energy Measurement", "code": 145, diff --git a/examples/all-clusters-app/esp32/main/CMakeLists.txt b/examples/all-clusters-app/esp32/main/CMakeLists.txt index c5d40048308c2d..08f0673223b34a 100644 --- a/examples/all-clusters-app/esp32/main/CMakeLists.txt +++ b/examples/all-clusters-app/esp32/main/CMakeLists.txt @@ -86,6 +86,7 @@ set(SRC_DIRS_LIST "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/resource-monitoring-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/temperature-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/time-synchronization-server" + "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/valve-configuration-and-control-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/dishwasher-alarm-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-washer-controls-server" "${CMAKE_SOURCE_DIR}/third_party/connectedhomeip/src/app/clusters/laundry-dryer-controls-server" diff --git a/examples/all-clusters-app/linux/BUILD.gn b/examples/all-clusters-app/linux/BUILD.gn index 343372676bd8fc..43a3e94506784a 100644 --- a/examples/all-clusters-app/linux/BUILD.gn +++ b/examples/all-clusters-app/linux/BUILD.gn @@ -45,6 +45,7 @@ source_set("chip-all-clusters-common") { "${chip_root}/examples/energy-management-app/energy-management-common/src/EnergyEvseManager.cpp", "AllClustersCommandDelegate.cpp", "AppOptions.cpp", + "ValveControlDelegate.cpp", "WindowCoveringManager.cpp", "include/tv-callbacks.cpp", "include/tv-callbacks.h", diff --git a/examples/all-clusters-app/linux/ValveControlDelegate.cpp b/examples/all-clusters-app/linux/ValveControlDelegate.cpp new file mode 100644 index 00000000000000..9c51aff63101f5 --- /dev/null +++ b/examples/all-clusters-app/linux/ValveControlDelegate.cpp @@ -0,0 +1,76 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "ValveControlDelegate.h" +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters::ValveConfigurationAndControl; +using namespace chip::app::Clusters::TimeSynchronization; + +static chip::Percent sLevel = 1; +static uint32_t sLastOpenDuration = 0; +static constexpr EndpointId kValveEndpoint = 1; + +DataModel::Nullable ValveControlDelegate::HandleOpenValve(DataModel::Nullable level) +{ + chip::Percent currentLevel = sLevel; + sLevel = level.IsNull() ? 100 : level.Value(); + sLastOpenDuration = 0; + ChipLogProgress(NotSpecified, "Valve openinig from level: %d to %d", currentLevel, sLevel); + + // In this demo application, the trasition is considered instant, + // so current level is set to the requested level and current state is set to kOpen. + currentLevel = sLevel; + Attributes::CurrentState::Set(kValveEndpoint, ValveConfigurationAndControl::ValveStateEnum::kOpen); + + return DataModel::Nullable(currentLevel); +} + +CHIP_ERROR ValveControlDelegate::HandleCloseValve() +{ + sLastOpenDuration = 0; + sLevel = 0; + ReturnErrorOnFailure(ValveConfigurationAndControl::UpdateCurrentLevel(kValveEndpoint, sLevel)); + ReturnErrorOnFailure( + ValveConfigurationAndControl::UpdateCurrentState(kValveEndpoint, ValveConfigurationAndControl::ValveStateEnum::kClosed)); + ChipLogProgress(NotSpecified, "Valve closed"); + return CHIP_NO_ERROR; +} + +void ValveControlDelegate::HandleRemainingDurationTick(uint32_t duration) +{ + ChipLogProgress(NotSpecified, "Valve remaining duration ticking: %dsec level: %d duration %d", duration, sLevel, + sLastOpenDuration); + if (sLastOpenDuration == 0) + { + VerifyOrReturn(CHIP_NO_ERROR == ValveConfigurationAndControl::UpdateCurrentLevel(kValveEndpoint, sLevel), + ChipLogError(NotSpecified, "Updating current level failed")); + VerifyOrReturn(CHIP_NO_ERROR == + ValveConfigurationAndControl::UpdateCurrentState(kValveEndpoint, + ValveConfigurationAndControl::ValveStateEnum::kOpen), + ChipLogError(NotSpecified, "Updating current state failed")); + } + sLastOpenDuration = duration; +} + +void ExtendedTimeSyncDelegate::UTCTimeChanged(uint64_t time) +{ + ValveConfigurationAndControl::UpdateAutoCloseTime(time); +} diff --git a/examples/all-clusters-app/linux/ValveControlDelegate.h b/examples/all-clusters-app/linux/ValveControlDelegate.h new file mode 100644 index 00000000000000..76f0f17a8fdfd1 --- /dev/null +++ b/examples/all-clusters-app/linux/ValveControlDelegate.h @@ -0,0 +1,49 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ValveConfigurationAndControl { + +class ValveControlDelegate : public Delegate +{ +public: + DataModel::Nullable HandleOpenValve(DataModel::Nullable level) override; + CHIP_ERROR HandleCloseValve() override; + void HandleRemainingDurationTick(uint32_t duration) override; +}; + +} // namespace ValveConfigurationAndControl + +namespace TimeSynchronization { + +class ExtendedTimeSyncDelegate : public DefaultTimeSyncDelegate +{ +public: + void UTCTimeChanged(uint64_t time) override; +}; + +} // namespace TimeSynchronization +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/examples/all-clusters-app/linux/main-common.cpp b/examples/all-clusters-app/linux/main-common.cpp index 05435df44e81b8..49ee513ca33f95 100644 --- a/examples/all-clusters-app/linux/main-common.cpp +++ b/examples/all-clusters-app/linux/main-common.cpp @@ -17,6 +17,7 @@ */ #include "AllClustersCommandDelegate.h" +#include "ValveControlDelegate.h" #include "WindowCoveringManager.h" #include "air-quality-instance.h" #include "dishwasher-mode.h" @@ -38,6 +39,8 @@ #include #include #include +#include +#include #include #include #include @@ -64,6 +67,8 @@ AllClustersCommandDelegate sAllClustersCommandDelegate; Clusters::WindowCovering::WindowCoveringManager sWindowCoveringManager; Clusters::TemperatureControl::AppSupportedTemperatureLevelsDelegate sAppSupportedTemperatureLevelsDelegate; +Clusters::ValveConfigurationAndControl::ValveControlDelegate sValveDelegate; +Clusters::TimeSynchronization::ExtendedTimeSyncDelegate sTimeSyncDelegate; // Please refer to https://github.com/CHIP-Specifications/connectedhomeip-spec/blob/master/src/namespaces constexpr const uint8_t kNamespaceCommon = 7; @@ -218,6 +223,9 @@ void ApplicationInit() #endif Clusters::TemperatureControl::SetInstance(&sAppSupportedTemperatureLevelsDelegate); + Clusters::ValveConfigurationAndControl::SetDefaultDelegate(chip::EndpointId(1), &sValveDelegate); + Clusters::TimeSynchronization::SetDefaultDelegate(&sTimeSyncDelegate); + SetTagList(/* endpoint= */ 0, Span(gEp0TagList)); SetTagList(/* endpoint= */ 1, Span(gEp1TagList)); SetTagList(/* endpoint= */ 2, Span(gEp2TagList)); diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter index 6065ce3b36efc0..6023f53fa18bba 100644 --- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter +++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.matter @@ -1631,7 +1631,7 @@ cluster OccupancySensing = 1030 { } endpoint 0 { - device type ma_rootdevice = 22, version 1; + device type ma_rootdevice = 22, version 2; binding cluster OtaSoftwareUpdateProvider; diff --git a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap index b37968d2d15978..8c58d93a8a6b41 100644 --- a/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap +++ b/examples/contact-sensor-app/contact-sensor-common/contact-sensor-app.zap @@ -51,7 +51,7 @@ } ], "deviceVersions": [ - 1 + 2 ], "deviceIdentifiers": [ 22 @@ -4748,4 +4748,4 @@ } ], "log": [] -} \ No newline at end of file +} diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn index 36f52d917f22db..cc87b4fc1532d6 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/BUILD.gn @@ -93,10 +93,7 @@ k32w0_executable("contact_sensor_app") { "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", ] - defines = [ - "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", - "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", - ] + defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ] } deps = [ diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md index f616ddfeeca4f9..27ae15b672eb05 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/README.md +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/README.md @@ -177,56 +177,58 @@ contact status. In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). -- Start building the application either with Secure Element or without, SDK is - downloaded with west tool. +Activate the Matter environment: - - without Secure Element +```bash +user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh +``` - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh +To bring the SDK in the environment, the user can: + +- download it with west tool, in which case it will be handled automatically + by gn: + + ```bash user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update ``` - In case there are local modification to the already installed git NXP SDK: - Use the below west `forall` command instead of the west init command to - reset the west workspace. Warning: all local changes will be lost after + In case there are local modification to the already installed github NXP + SDK, use the below `west forall` command instead of the `west init` command + to reset the west workspace. Warning: all local changes will be lost after running this command. ```bash user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo - user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a ``` - Build the application - - Prior to building, the user can specify a custom `SDK` path by setting - `NXP_K32W0_SDK_ROOT`: +- set up a custom path to the SDK, in which case + `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen` + command: ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core + user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK ``` - If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default - to the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`. +Start building the application: - ``` - user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0 - user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" - user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug - ``` +```bash +user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/contact-sensor-app/nxp/k32w/k32w0 +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" +user@ubuntu:~/Desktop/git/connectedhomeip/examples/contact-sensor-app/nxp/k32w/k32w0$ ninja -C out/debug +``` - - with Secure element Exactly the same steps as above but set - chip_with_se05x=1 in the gn command and add argument - chip_enable_ota_requestor=false +To build with Secure Element, follow the same steps as above but set +`chip_with_se05x=1 chip_enable_ota_requestor=false` in the `gn gen` command. -Note that option chip_enable_ota_requestor=false are required for building with -Secure Element. These can be changed if building without Secure Element +Note that option `chip_enable_ota_requestor=false` is required for building with +Secure Element due to flash constraints. - K32W041AM flavor - Exactly the same steps as above but set argument build_for_k32w041am=1 in + Exactly the same steps as above but set argument `build_for_k32w041am=1` in the gn command. Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index b48b97c55e6f94..72f94878cf328f 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -48,13 +48,6 @@ #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 #endif -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER -#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS -// Set to 3: default number of custom Ids from CustomFactoryDataProvider example -#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 -#endif -#endif - // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp index 484ddce1b7ce1b..5c942db19b3af5 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -85,7 +85,10 @@ using namespace chip::app; AppTask AppTask::sAppTask; #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static AppTask::FactoryDataProvider sFactoryDataProvider; +static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider; +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider; +#endif #endif static Identify gIdentify = { chip::EndpointId{ 1 }, AppTask::OnIdentifyStart, AppTask::OnIdentifyStop, @@ -199,6 +202,9 @@ CHIP_ERROR AppTask::Init() SetDeviceInstanceInfoProvider(&sFactoryDataProvider); SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); SetCommissionableDataProvider(&sFactoryDataProvider); +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + sCustomFactoryDataProvider.ParseFunctionExample(); +#endif #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); diff --git a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h index 58effbdba14162..867a496de1e56d 100644 --- a/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/contact-sensor-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -49,15 +49,6 @@ class AppTask { -public: -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; -#else - using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl; -#endif -#endif - public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); diff --git a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn index a71bf63dc6d4e0..93bf1dc363f9dd 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w0/BUILD.gn @@ -95,10 +95,7 @@ k32w0_executable("light_app") { "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", ] - defines = [ - "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", - "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", - ] + defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ] } deps = [ diff --git a/examples/lighting-app/nxp/k32w/k32w0/README.md b/examples/lighting-app/nxp/k32w/k32w0/README.md index b43a08622eb330..3194d71b39b889 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/README.md +++ b/examples/lighting-app/nxp/k32w/k32w0/README.md @@ -192,58 +192,58 @@ effects: In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). -- Start building the application either with Secure Element or without, SDK is - downloaded with west tool. - - without Secure Element +Activate the Matter environment: -``` +```bash user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh -user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update ``` -In case there are local modification to the already installed git NXP SDK: Use -the below west `forall` command instead of the west init command to reset the -west workspace. Warning: all local changes will be lost after running this -command. +To bring the SDK in the environment, the user can: -```bash -user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a -``` +- download it with west tool, in which case it will be handled automatically + by gn: -Build the application + ```bash + user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update + ``` -Prior to building, the user can specify a custom `SDK` path by setting -`NXP_K32W0_SDK_ROOT`: + In case there are local modification to the already installed github NXP + SDK, use the below `west forall` command instead of the `west init` command + to reset the west workspace. Warning: all local changes will be lost after + running this command. -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core -``` + ```bash + user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a + ``` + +- set up a custom path to the SDK, in which case + `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen` + command: -If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default to -the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`. + ``` + user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK + ``` -``` +Start building the application: + +```bash user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lighting-app/nxp/k32w/k32w0 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" user@ubuntu:~/Desktop/git/connectedhomeip/examples/lighting-app/nxp/k32w/k32w0$ ninja -C out/debug ``` - - with Secure element - -``` - Exactly the same steps as above but set chip_with_se05x=1 in the gn command - and add argument chip_enable_ota_requestor=false -``` +To build with Secure Element, follow the same steps as above but set +`chip_with_se05x=1 chip_enable_ota_requestor=false` in the `gn gen` command. -Note that option chip_enable_ota_requestor=false are required for building with -Secure Element. These can be changed if building without Secure Element +Note that option `chip_enable_ota_requestor=false` is required for building with +Secure Element due to flash constraints. - K32W041AM flavor - Exactly the same steps as above but set argument build_for_k32w041am=1 in + Exactly the same steps as above but set argument `build_for_k32w041am=1` in the gn command. Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the diff --git a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index 10019a4268cad2..946d457622e467 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/lighting-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -48,13 +48,6 @@ #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 #endif -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER -#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS -// Set to 3: default number of custom Ids from CustomFactoryDataProvider example -#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 -#endif -#endif - // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp index e63c35a1489ee0..557293f6bac2aa 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lighting-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -85,7 +85,10 @@ using namespace chip::app; AppTask AppTask::sAppTask; #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static AppTask::FactoryDataProvider sFactoryDataProvider; +static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider; +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider; +#endif #endif // This key is for testing/certification only and should not be used in production devices. @@ -190,6 +193,9 @@ CHIP_ERROR AppTask::Init() SetDeviceInstanceInfoProvider(&sFactoryDataProvider); SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); SetCommissionableDataProvider(&sFactoryDataProvider); +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + sCustomFactoryDataProvider.ParseFunctionExample(); +#endif #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); diff --git a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h index 83dfd33da2abd9..9590734521d5e1 100644 --- a/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/lighting-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -49,15 +49,6 @@ class AppTask { -public: -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; -#else - using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl; -#endif -#endif - public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); diff --git a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn index fd095a2cb197c5..a7643a9f847931 100644 --- a/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn +++ b/examples/lighting-app/nxp/k32w/k32w1/BUILD.gn @@ -82,6 +82,8 @@ k32w1_executable("light_app") { "main/main.cpp", ] + public = [ "${chip_root}/src/platform/nxp/k32w/k32w1/DefaultTestEventTriggerDelegate.h" ] + deps = [ ":sdk", "${chip_root}/examples/common/QRCode", diff --git a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn index 0b752583604a89..c755514d66a175 100644 --- a/examples/lock-app/nxp/k32w/k32w0/BUILD.gn +++ b/examples/lock-app/nxp/k32w/k32w0/BUILD.gn @@ -92,10 +92,7 @@ k32w0_executable("lock_app") { "${k32w0_platform_dir}/common/CustomFactoryDataProvider.h", ] - defines = [ - "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", - "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3", - ] + defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1" ] } deps = [ diff --git a/examples/lock-app/nxp/k32w/k32w0/README.md b/examples/lock-app/nxp/k32w/k32w0/README.md index b5fec55268371c..49920906819b0f 100644 --- a/examples/lock-app/nxp/k32w/k32w0/README.md +++ b/examples/lock-app/nxp/k32w/k32w0/README.md @@ -173,59 +173,67 @@ will be initiated. In order to build the Project CHIP example, we recommend using a Linux distribution (the demo-application was compiled on Ubuntu 20.04). -- Start building the application either with Secure Element or without, SDK is - downloaded with west tool. +Activate the Matter environment: - - without Secure Element - -``` +```bash user@ubuntu:~/Desktop/git/connectedhomeip$ source ./scripts/activate.sh -user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update ``` -In case there are local modification to the already installed git NXP SDK: Use -the below west `forall` command instead of the west init command to reset the -west workspace. Warning: all local changes will be lost after running this -command. +To bring the SDK in the environment, the user can: -```bash -user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo -user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$west forall -c "git reset --hard && git clean -xdf" -a -``` +- download it with west tool, in which case it will be handled automatically + by gn: -Build the application + ```bash + user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west init -l manifest --mf west.yml + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west update + ``` -Prior to building, the user can specify a custom `SDK` path by setting -`NXP_K32W0_SDK_ROOT`: + In case there are local modification to the already installed github NXP + SDK, use the below `west forall` command instead of the `west init` command + to reset the west workspace. Warning: all local changes will be lost after + running this command. -``` -user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=$(pwd)/third_party/nxp/k32w0_sdk/repo/core -``` + ```bash + user@ubuntu:~/Desktop/git/connectedhomeip$ cd third_party/nxp/k32w0_sdk/repo + user@ubuntu:~/Desktop/git/connectedhomeip/third_party/nxp/k32w0_sdk/repo$ west forall -c "git reset --hard && git clean -xdf" -a + ``` -If the environment variable `NXP_K32W0_SDK_ROOT` is not set, it will default to -the `SDK` found in `third_party/nxp/k32w0_sdk/repo/core`. +- set up a custom path to the SDK, in which case + `k32w0_sdk_root=\"${NXP_K32W0_SDK_ROOT}\"` must be added to the `gn gen` + command: -``` + ``` + user@ubuntu:~/Desktop/git/connectedhomeip$ export NXP_K32W0_SDK_ROOT=/custom/path/to/SDK + ``` + +Start building the application: + +```bash user@ubuntu:~/Desktop/git/connectedhomeip$ cd examples/lock-app/nxp/k32w/k32w0 user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ gn gen out/debug --args="chip_with_OM15082=1 chip_with_ot_cli=0 is_debug=false chip_crypto=\"platform\" chip_with_se05x=0 chip_pw_tokenizer_logging=true" user@ubuntu:~/Desktop/git/connectedhomeip/examples/lock-app/nxp/k32w/k32w0$ ninja -C out/debug ``` - - with Secure element - Exactly the same steps as above but set chip_with_se05x=1 in the gn command. +To build with Secure Element, follow the same steps as above but set +`chip_with_se05x=1` in the `gn gen` command. + +- K32W041AM flavor + + Exactly the same steps as above but set argument `build_for_k32w041am=1` in + the gn command. Also, in case the OM15082 Expansion Board is not attached to the DK6 board, the -build argument (chip_with_OM15082) inside the gn build instruction should be set -to zero. The argument chip_with_OM15082 is set to zero by default. +build argument (`chip_with_OM15082`) inside the gn build instruction should be +set to zero. The argument `chip_with_OM15082` is set to zero by default. -In case that Openthread CLI is needed, chip_with_ot_cli build argument must be +In case that Openthread CLI is needed, `chip_with_ot_cli` build argument must be set to 1. In case the board doesn't have 32KHz crystal fitted, one can use the 32KHz free -running oscillator as a clock source. In this case one must set the use_fro_32k -argument to 1. +running oscillator as a clock source. In this case one must set the +`use_fro_32k` argument to 1. In case signing errors are encountered when running the "sign_images.sh" script (run automatically) install the recommanded packages (python version > 3, pip3, diff --git a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h index c74714bded920f..43598870fb7533 100644 --- a/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h +++ b/examples/lock-app/nxp/k32w/k32w0/include/CHIPProjectConfig.h @@ -48,13 +48,6 @@ #define CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER 0 #endif -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER -#ifndef CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS -// Set to 3: default number of custom Ids from CustomFactoryDataProvider example -#define CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS 3 -#endif -#endif - // VID/PID for product => will be used by Basic Information Cluster #define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0x1037 #define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0xA220 diff --git a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp index fff749b311678e..130569791e2e8e 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp +++ b/examples/lock-app/nxp/k32w/k32w0/main/AppTask.cpp @@ -71,7 +71,10 @@ using namespace ::chip::DeviceLayer; AppTask AppTask::sAppTask; #if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -static AppTask::FactoryDataProvider sFactoryDataProvider; +static chip::DeviceLayer::FactoryDataProviderImpl sFactoryDataProvider; +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER +static chip::DeviceLayer::CustomFactoryDataProvider sCustomFactoryDataProvider; +#endif #endif CHIP_ERROR AppTask::StartAppTask() @@ -102,6 +105,9 @@ CHIP_ERROR AppTask::Init() SetDeviceInstanceInfoProvider(&sFactoryDataProvider); SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); SetCommissionableDataProvider(&sFactoryDataProvider); +#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER + sCustomFactoryDataProvider.ParseFunctionExample(); +#endif #else #ifdef ENABLE_HSM_DEVICE_ATTESTATION SetDeviceAttestationCredentialsProvider(Examples::GetExampleSe05xDACProvider()); diff --git a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h index cbaa5757374497..1addd9236c4bcf 100644 --- a/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h +++ b/examples/lock-app/nxp/k32w/k32w0/main/include/AppTask.h @@ -40,15 +40,6 @@ class AppTask { -public: -#if CONFIG_CHIP_LOAD_REAL_FACTORY_DATA -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - using FactoryDataProvider = chip::DeviceLayer::CustomFactoryDataProvider; -#else - using FactoryDataProvider = chip::DeviceLayer::FactoryDataProviderImpl; -#endif -#endif - public: CHIP_ERROR StartAppTask(); static void AppTaskMain(void * pvParameter); diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp index 18e809509fc803..7f2f6d9bc0cad0 100644 --- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp +++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.cpp @@ -24,21 +24,10 @@ static constexpr size_t kMaxLengthCustomId1 = 10; static constexpr size_t kMaxLengthCustomId2 = 50; static constexpr size_t kMaxLengthCustomId3 = 100; -CustomFactoryDataProvider & CustomFactoryDataProvider::GetDefaultInstance() +CustomFactoryDataProvider::CustomFactoryDataProvider() { - static CustomFactoryDataProvider sInstance; - return sInstance; -} - -CHIP_ERROR CustomFactoryDataProvider::SetCustomIds() -{ - static_assert(CustomFactoryIds::kCustomMaxId == FactoryDataProvider::kNumberOfIds, - "kNumberOfIds is computed based on CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS."); - maxLengths[CustomFactoryIds::kCustomId1] = kMaxLengthCustomId1; - maxLengths[CustomFactoryIds::kCustomId2] = kMaxLengthCustomId2; - maxLengths[CustomFactoryIds::kCustomId3] = kMaxLengthCustomId3; - - return CHIP_NO_ERROR; + // Custom ids should be from a range that does not overlap with the standard factory data range. + static_assert((uint16_t) CustomFactoryIds::kCustomId1 >= (uint16_t) FactoryDataProvider::FactoryDataId::kMaxId); } CHIP_ERROR CustomFactoryDataProvider::ParseFunctionExample() @@ -49,7 +38,9 @@ CHIP_ERROR CustomFactoryDataProvider::ParseFunctionExample() uint16_t userDataSize = 0; // A user can use FactoryDataProvider::SearchForId to read an id from internal // flash factory data section. - ReturnErrorOnFailure(SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize)); + auto * provider = static_cast(DeviceLayer::GetDeviceInstanceInfoProvider()); + ReturnErrorOnFailure((provider != nullptr) ? CHIP_NO_ERROR : CHIP_ERROR_INVALID_ADDRESS); + ReturnErrorOnFailure(provider->SearchForId(CustomFactoryIds::kCustomId1, buffer.data(), buffer.size(), userDataSize)); // Data should now be ready for custom parsing. diff --git a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h index 9edd603b4677c8..dfb722d67fdc11 100644 --- a/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h +++ b/examples/platform/nxp/k32w/k32w0/common/CustomFactoryDataProvider.h @@ -27,26 +27,21 @@ namespace DeviceLayer { * provider based on this example. */ -class CustomFactoryDataProvider : public FactoryDataProviderImpl +class CustomFactoryDataProvider { public: - /* Custom IDs should start from FactoryDataId::kMaxId, which is + /* Custom IDs should start from at least FactoryDataId::kMaxId, which is * the next available valid ID. Last default ID is kMaxId - 1. */ enum CustomFactoryIds { - kCustomId1 = FactoryDataId::kMaxId, + kCustomId1 = 200, // Random id that is greater than FactoryDataId::kMaxId. kCustomId2, kCustomId3, kCustomMaxId }; - static CustomFactoryDataProvider & GetDefaultInstance(); - - CustomFactoryDataProvider() {} - - /* SetCustomIds() must be implemented in order to define custom IDs. */ - CHIP_ERROR SetCustomIds() override; + CustomFactoryDataProvider(); /* Declare here custom functions to be implemented. */ CHIP_ERROR ParseFunctionExample(); diff --git a/examples/platform/nxp/k32w/k32w0/common/README.md b/examples/platform/nxp/k32w/k32w0/common/README.md index 459f62f049e337..59347d6bfd205d 100644 --- a/examples/platform/nxp/k32w/k32w0/common/README.md +++ b/examples/platform/nxp/k32w/k32w0/common/README.md @@ -12,10 +12,11 @@ following interfaces: - DeviceAttestationCredentialsProvider - DeviceInstanceInfoProvider -A user can inherit `FactoryDataProviderImpl` to provide additional functionality -(such as parsing custom factory data fields) that is customer specific. +A user can use `FactoryDataProvider::SearchForId` API to extract information +about custom factory data ids. -What **shall** be done to enable usage of a custom factory provider: +What **shall** be done to enable usage of a custom factory provider in the +reference app: - Set `use_custom_factory_provider=1`. This option is only available when factory data is used (`chip_with_factory_data=1`). An assert will be raised @@ -33,28 +34,15 @@ What **shall** be done to enable usage of a custom factory provider: defines = [ "CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER=1", - "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS=3" ] } ``` - Note that new flags were introduced: - - - `CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER`: select between using - `FactoryDataProviderImpl` or `CustomFactoryDataProvider` when - registering the provider. - - `CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS`: set the number of - custom IDs (which are different than the default IDs). If this macro is - not correctly set, compilation should fail. - -- The default IDs are validated directly in `SearchForId`, but custom IDs - should set their maximum lengths through `SetCustomIds` method. -- `FactoryDataProvider::kNumberOfIds` is computed at compile time and should - represent the number of IDs (custom + default). Custom IDs should start from - `FactoryDataId::kMaxId`, which is the next valid ID. IDs - `[1, FactoryDataId::kMaxId - 1]` are reserved for default factory data IDs. - -Please refer to `CustomFactoryDataProvider` for a minimal example of a custom -factory data provider and note that its implementation is just an example of how -to integrate a custom provider into the application, while still using the -default implementation provided by `FactoryDataProviderImpl`. +Note that new flags were introduced: + +- `CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER`: add custom factory data related + code in reference app. + +Please refer to `CustomFactoryDataProvider` for a minimal example of leveraging +the standard factory data provider to parse custom factory data information. +Real applications could use the public API of `FactoryDataProvider` directly. diff --git a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/parsing.py b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/parsing.py index 624bcb56b9dc01..608e526f619cc0 100644 --- a/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/parsing.py +++ b/scripts/py_matter_idl/matter_idl/data_model_xml/handlers/parsing.py @@ -102,6 +102,13 @@ def NormalizeDataType(t: str) -> str: } +# Handle odd casing and naming +_CASE_RENAMES_MAPPING = { + "power_mW": "power_mw", + "energy_mWh": "energy_mwh" +} + + def ParseType(t: str) -> ParsedType: """Parse a data type entry. @@ -123,6 +130,9 @@ def ParseType(t: str) -> ParsedType: if t in _REF_NAME_MAPPING: t = _REF_NAME_MAPPING[t] + if t in _CASE_RENAMES_MAPPING: + t = _CASE_RENAMES_MAPPING[t] + return ParsedType(name=NormalizeDataType(t), is_list=is_list) diff --git a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py index 647a275ea8d547..6bdb530f7cc9fc 100755 --- a/scripts/py_matter_idl/matter_idl/test_data_model_xml.py +++ b/scripts/py_matter_idl/matter_idl/test_data_model_xml.py @@ -415,6 +415,19 @@ def testXmlNameWorkarounds(self): + + + + + + + + + + + + + @@ -443,11 +456,14 @@ def testXmlNameWorkarounds(self): char_string id = 0; int8u items[] = 1; endpoint_no endpoints[] = 2; + optional power_mw nominalPower = 3; + optional energy_mwh maximumEnergy = 4; } readonly attribute OutputInfoStruct outputList[] = 0; readonly attribute optional enum8 testConform = 1; + readonly attribute attrib_id attributeList[] = 65531; readonly attribute event_id eventList[] = 65530; readonly attribute command_id acceptedCommandList[] = 65529; diff --git a/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.cpp b/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.cpp index 82164afc2427b2..3f97c57a7171fe 100644 --- a/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.cpp +++ b/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.cpp @@ -73,3 +73,8 @@ CHIP_ERROR DefaultTimeSyncDelegate::UpdateTimeUsingNTPFallback(const CharSpan & { return CHIP_ERROR_NOT_IMPLEMENTED; } + +void DefaultTimeSyncDelegate::UTCTimeChanged(uint64_t time) +{ + // placeholder implementation +} diff --git a/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.h b/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.h index a954f51954cb3c..826f1d22d82707 100644 --- a/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.h +++ b/src/app/clusters/time-synchronization-server/DefaultTimeSyncDelegate.h @@ -36,6 +36,7 @@ class DefaultTimeSyncDelegate : public Delegate CHIP_ERROR UpdateTimeFromPlatformSource(chip::Callback::Callback * callback) override; CHIP_ERROR UpdateTimeUsingNTPFallback(const CharSpan & fallbackNTP, chip::Callback::Callback * callback) override; + void UTCTimeChanged(uint64_t time) override; }; } // namespace TimeSynchronization diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-delegate.h b/src/app/clusters/time-synchronization-server/time-synchronization-delegate.h index a80b3207aff992..1f424e31798c44 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-delegate.h +++ b/src/app/clusters/time-synchronization-server/time-synchronization-delegate.h @@ -105,6 +105,11 @@ class Delegate virtual CHIP_ERROR UpdateTimeUsingNTPFallback(const CharSpan & fallbackNTP, chip::Callback::Callback * callback) = 0; + /** + * @brief Signals application that UTCTime has changed through the timesync cluster. + */ + virtual void UTCTimeChanged(uint64_t time) = 0; + virtual ~Delegate() = default; private: diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp b/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp index 8b285c4a1ad402..fae9565ef21599 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp +++ b/src/app/clusters/time-synchronization-server/time-synchronization-server.cpp @@ -776,6 +776,7 @@ CHIP_ERROR TimeSynchronizationServer::SetUTCTime(EndpointId ep, uint64_t utcTime ChipLogError(Zcl, "Error setting UTC time on the device"); return err; } + GetDelegate()->UTCTimeChanged(utcTime); mGranularity = granularity; EmberAfStatus status = TimeSource::Set(ep, source); if (!(status == EMBER_ZCL_STATUS_SUCCESS || status == EMBER_ZCL_STATUS_UNSUPPORTED_ATTRIBUTE)) diff --git a/src/app/clusters/time-synchronization-server/time-synchronization-server.h b/src/app/clusters/time-synchronization-server/time-synchronization-server.h index 200714d3cf7def..5eee8e52b000b8 100644 --- a/src/app/clusters/time-synchronization-server/time-synchronization-server.h +++ b/src/app/clusters/time-synchronization-server/time-synchronization-server.h @@ -69,6 +69,9 @@ enum class TimeSyncEventFlag : uint8_t kMissingTTSource = 16, }; +void SetDefaultDelegate(Delegate * delegate); +Delegate * GetDefaultDelegate(); + class TimeSynchronizationServer : public FabricTable::Delegate #if TIME_SYNC_ENABLE_TSC_FEATURE , diff --git a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-delegate.h b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-delegate.h new file mode 100644 index 00000000000000..b0d3e5fd14a90d --- /dev/null +++ b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-delegate.h @@ -0,0 +1,50 @@ +/* + * + * 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 { +namespace ValveConfigurationAndControl { + +/** @brief + * Defines methods for implementing application-specific logic for the Valve Configuration and Control Cluster. + */ +class Delegate +{ +public: + Delegate(){}; + + // shall return current level if supported, otherwise null + virtual DataModel::Nullable HandleOpenValve(DataModel::Nullable level) = 0; + virtual CHIP_ERROR HandleCloseValve() = 0; + virtual void HandleRemainingDurationTick(uint32_t duration) = 0; + + virtual ~Delegate() = default; +}; + +} // namespace ValveConfigurationAndControl +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp new file mode 100644 index 00000000000000..0f6968f98e5826 --- /dev/null +++ b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.cpp @@ -0,0 +1,521 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "valve-configuration-and-control-server.h" + +#include +#ifdef ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER +// Need the `nogncheck` because it's inter-cluster dependency and this +// breaks GN deps checks since that doesn't know how to deal with #ifdef'd includes :(. +#include "app/clusters/time-synchronization-server/time-synchronization-server.h" // nogncheck + +#endif // ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; +using namespace chip::app::Clusters::ValveConfigurationAndControl::Attributes; +using chip::app::Clusters::ValveConfigurationAndControl::Delegate; +using chip::Protocols::InteractionModel::Status; + +static constexpr size_t kValveConfigurationAndControlDelegateTableSize = + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT + CHIP_DEVICE_CONFIG_DYNAMIC_ENDPOINT_COUNT; + +static_assert(kValveConfigurationAndControlDelegateTableSize <= kEmberInvalidEndpointIndex, + "ValveConfigurationAndControl Delegate table size error"); + +namespace { + +struct RemainingDurationTable +{ + EndpointId endpoint; + DataModel::Nullable remainingDuration; +}; + +RemainingDurationTable gRemainingDuration[kValveConfigurationAndControlDelegateTableSize]; +Delegate * gDelegateTable[kValveConfigurationAndControlDelegateTableSize] = { nullptr }; + +bool GetRemainingDuration(EndpointId endpoint, DataModel::Nullable & duration) +{ + uint16_t epIdx = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + VerifyOrReturnValue(epIdx < kValveConfigurationAndControlDelegateTableSize, false); + duration = gRemainingDuration[epIdx].remainingDuration; + return true; +} + +void SetRemainingDuration(EndpointId endpoint, DataModel::Nullable duration) +{ + uint16_t epIdx = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + if (epIdx < kValveConfigurationAndControlDelegateTableSize) + { + gRemainingDuration[epIdx].endpoint = endpoint; + gRemainingDuration[epIdx].remainingDuration = duration; + } +} + +void SetRemainingDurationNull(EndpointId endpoint) +{ + uint16_t epIdx = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + if (epIdx < kValveConfigurationAndControlDelegateTableSize) + { + if (!gRemainingDuration[epIdx].remainingDuration.IsNull()) + { + MatterReportingAttributeChangeCallback(endpoint, ValveConfigurationAndControl::Id, RemainingDuration::Id); + } + gRemainingDuration[epIdx].remainingDuration.SetNull(); + } +} + +RemainingDurationTable * GetRemainingDurationItem(EndpointId endpoint) +{ + uint16_t epIdx = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + if (epIdx < kValveConfigurationAndControlDelegateTableSize) + { + return &gRemainingDuration[epIdx]; + } + return nullptr; +} + +Delegate * GetDelegate(EndpointId endpoint) +{ + uint16_t epIdx = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + return (epIdx >= kValveConfigurationAndControlDelegateTableSize ? nullptr : gDelegateTable[epIdx]); +} + +bool isDelegateNull(Delegate * delegate) +{ + if (delegate == nullptr) + { + return true; + } + return false; +} + +class ValveConfigAndControlAttrAccess : public AttributeAccessInterface +{ +public: + ValveConfigAndControlAttrAccess() : AttributeAccessInterface(Optional::Missing(), ValveConfigurationAndControl::Id) + {} + + CHIP_ERROR Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) override; + +private: + CHIP_ERROR ReadRemainingDuration(EndpointId endpoint, AttributeValueEncoder & aEncoder); +}; + +ValveConfigAndControlAttrAccess gAttrAccess; + +CHIP_ERROR ValveConfigAndControlAttrAccess::ReadRemainingDuration(EndpointId endpoint, AttributeValueEncoder & aEncoder) +{ + DataModel::Nullable rDuration; + VerifyOrReturnError(GetRemainingDuration(endpoint, rDuration), CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute)); + + return aEncoder.Encode(rDuration); +} + +CHIP_ERROR ValveConfigAndControlAttrAccess::Read(const ConcreteReadAttributePath & aPath, AttributeValueEncoder & aEncoder) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if (aPath.mClusterId != ValveConfigurationAndControl::Id) + { + return CHIP_ERROR_INVALID_PATH_LIST; + } + + switch (aPath.mAttributeId) + { + case RemainingDuration::Id: { + return ReadRemainingDuration(aPath.mEndpointId, aEncoder); + } + default: { + break; + } + } + + return err; +} +} // namespace + +static void startRemainingDurationTick(EndpointId ep); + +static bool emitValveStateChangedEvent(EndpointId ep, ValveConfigurationAndControl::ValveStateEnum state) +{ + ValveConfigurationAndControl::Events::ValveStateChanged::Type event; + EventNumber eventNumber; + event.valveState = state; + + CHIP_ERROR error = LogEvent(event, ep, eventNumber); + + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "Unable to emit ValveStateChanged event [ep=%d]", ep); + return false; + } + + ChipLogProgress(Zcl, "Emit ValveStateChanged event [ep=%d] %d", ep, to_underlying(state)); + return true; +} + +static CHIP_ERROR emitValveFaultEvent(EndpointId ep, BitMask fault) +{ + ValveConfigurationAndControl::Events::ValveFault::Type event; + EventNumber eventNumber; + event.valveFault = fault; + + CHIP_ERROR error = LogEvent(event, ep, eventNumber); + + if (CHIP_NO_ERROR != error) + { + ChipLogError(Zcl, "Unable to emit ValveFault event [ep=%d]", ep); + return error; + } + + ChipLogProgress(Zcl, "Emit ValveFault event [ep=%d]", ep); + return CHIP_NO_ERROR; +} + +static void onValveConfigurationAndControlTick(System::Layer * systemLayer, void * data) +{ + RemainingDurationTable * item = reinterpret_cast(data); + VerifyOrReturn(item != nullptr, ChipLogError(Zcl, "Error retrieving RemainingDuration item")); + + DataModel::Nullable rDuration = item->remainingDuration; + VerifyOrReturn(!rDuration.IsNull()); + + EndpointId ep = item->endpoint; + + if (rDuration.Value() > 0) + { + SetRemainingDuration(ep, DataModel::MakeNullable(--rDuration.Value())); + startRemainingDurationTick(ep); + } + else + { + SetRemainingDurationNull(ep); + } +} + +void startRemainingDurationTick(EndpointId ep) +{ + RemainingDurationTable * item = GetRemainingDurationItem(ep); + VerifyOrReturn(item != nullptr, ChipLogError(Zcl, "Error retrieving RemainingDuration item")); + + DataModel::Nullable rDuration = item->remainingDuration; + VerifyOrReturn(!rDuration.IsNull()); + Delegate * delegate = GetDelegate(item->endpoint); + VerifyOrReturn(!isDelegateNull(delegate)); + + delegate->HandleRemainingDurationTick(rDuration.Value()); + if (rDuration.Value() > 0) + { + (void) DeviceLayer::SystemLayer().StartTimer(System::Clock::Seconds16(1), onValveConfigurationAndControlTick, item); + } + else + { + ValveConfigurationAndControl::CloseValve(ep); + (void) DeviceLayer::SystemLayer().CancelTimer(onValveConfigurationAndControlTick, item); + } +} + +namespace chip { +namespace app { +namespace Clusters { +namespace ValveConfigurationAndControl { + +void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate) +{ + uint16_t ep = emberAfGetClusterServerEndpointIndex(endpoint, ValveConfigurationAndControl::Id, + EMBER_AF_VALVE_CONFIGURATION_AND_CONTROL_CLUSTER_SERVER_ENDPOINT_COUNT); + // if endpoint is found + if (ep < kValveConfigurationAndControlDelegateTableSize) + { + gDelegateTable[ep] = delegate; + } +} + +Delegate * GetDefaultDelegate(EndpointId endpoint) +{ + return GetDelegate(endpoint); +} + +CHIP_ERROR CloseValve(EndpointId ep) +{ + Delegate * delegate = GetDelegate(ep); + DataModel::Nullable rDuration; + CHIP_ERROR attribute_error = CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == TargetState::Set(ep, ValveConfigurationAndControl::ValveStateEnum::kClosed), + attribute_error); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == + CurrentState::Set(ep, ValveConfigurationAndControl::ValveStateEnum::kTransitioning), + attribute_error); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == OpenDuration::SetNull(ep), attribute_error); + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == TargetLevel::Set(ep, 0), attribute_error); + } + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kTimeSync)) + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == AutoCloseTime::SetNull(ep), attribute_error); + } + SetRemainingDurationNull(ep); + RemainingDurationTable * item = GetRemainingDurationItem(ep); + (void) DeviceLayer::SystemLayer().CancelTimer(onValveConfigurationAndControlTick, item); + + emitValveStateChangedEvent(ep, ValveConfigurationAndControl::ValveStateEnum::kTransitioning); + if (!isDelegateNull(delegate)) + { + delegate->HandleCloseValve(); + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR SetValveLevel(EndpointId ep, DataModel::Nullable level, DataModel::Nullable openDuration) +{ + Delegate * delegate = GetDelegate(ep); + Optional status = Optional::Missing(); + DataModel::Nullable openLevel; + DataModel::Nullable autoCloseTime; + CHIP_ERROR attribute_error = CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); + + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kTimeSync)) + { +#ifdef ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER + if (!openDuration.IsNull() && + TimeSynchronization::TimeSynchronizationServer::Instance().GetGranularity() != + TimeSynchronization::GranularityEnum::kNoTimeGranularity) + { + System::Clock::Microseconds64 utcTime; + uint64_t chipEpochTime; + ReturnErrorOnFailure(System::SystemClock().GetClock_RealTime(utcTime)); + VerifyOrReturnError(UnixEpochToChipEpochMicros(utcTime.count(), chipEpochTime), CHIP_ERROR_INVALID_TIME); + + uint64_t time = openDuration.Value() * chip::kMicrosecondsPerSecond; + autoCloseTime.SetNonNull(chipEpochTime + time); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == AutoCloseTime::Set(ep, autoCloseTime), attribute_error); + } + else + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == AutoCloseTime::SetNull(ep), attribute_error); + } +#else + return CHIP_FAILURE; +#endif // ZCL_USING_TIME_SYNCHRONIZATION_CLUSTER_SERVER + } + + // level can only be null if LVL feature is not supported + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel) && !level.IsNull()) + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == TargetLevel::Set(ep, level), attribute_error); + } + + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == OpenDuration::Set(ep, openDuration), attribute_error); + + SetRemainingDuration(ep, openDuration); + // Trigger report for remainingduration + MatterReportingAttributeChangeCallback(ep, ValveConfigurationAndControl::Id, RemainingDuration::Id); + // set targetstate to open + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == TargetState::Set(ep, ValveConfigurationAndControl::ValveStateEnum::kOpen), + attribute_error); + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == + CurrentState::Set(ep, ValveConfigurationAndControl::ValveStateEnum::kTransitioning), + attribute_error); + + // start movement towards target + emitValveStateChangedEvent(ep, ValveConfigurationAndControl::ValveStateEnum::kTransitioning); + if (!isDelegateNull(delegate)) + { + DataModel::Nullable cLevel = delegate->HandleOpenValve(level); + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == CurrentLevel::Set(ep, cLevel), attribute_error); + } + } + // start countdown + startRemainingDurationTick(ep); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR UpdateCurrentLevel(EndpointId ep, Percent currentLevel) +{ + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) + { + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == CurrentLevel::Set(ep, currentLevel), + CHIP_IM_GLOBAL_STATUS(ConstraintError)); + return CHIP_NO_ERROR; + } + return CHIP_IM_GLOBAL_STATUS(UnsupportedAttribute); +} + +CHIP_ERROR UpdateCurrentState(EndpointId ep, ValveConfigurationAndControl::ValveStateEnum currentState) +{ + VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == CurrentState::Set(ep, currentState), CHIP_IM_GLOBAL_STATUS(ConstraintError)); + emitValveStateChangedEvent(ep, currentState); + return CHIP_NO_ERROR; +} + +CHIP_ERROR EmitValveFault(EndpointId ep, BitMask fault) +{ + ReturnErrorOnFailure(emitValveFaultEvent(ep, fault)); + return CHIP_NO_ERROR; +} + +void UpdateAutoCloseTime(uint64_t time) +{ + for (auto & t : gRemainingDuration) + { + const auto & d = t.remainingDuration; + if (!d.IsNull() && d.Value() != 0) + { + uint64_t closingTime = d.Value() * chip::kMicrosecondsPerSecond + time; + if (EMBER_ZCL_STATUS_SUCCESS != AutoCloseTime::Set(t.endpoint, closingTime)) + { + ChipLogError(Zcl, "Unable to update AutoCloseTime"); + } + } + } +} +} // namespace ValveConfigurationAndControl +} // namespace Clusters +} // namespace app +} // namespace chip + +bool emberAfValveConfigurationAndControlClusterOpenCallback( + CommandHandler * commandObj, const ConcreteCommandPath & commandPath, + const ValveConfigurationAndControl::Commands::Open::DecodableType & commandData) +{ + const auto & openDuration = commandData.openDuration; + const auto & targetLevel = commandData.targetLevel; + const auto & ep = commandPath.mEndpointId; + DataModel::Nullable level; + DataModel::Nullable duration; + BitMask fault(0); + Optional status = Optional::Missing(); + + // if fault is registered return FailureDueToFault + if (EMBER_ZCL_STATUS_SUCCESS == ValveFault::Get(ep, &fault) && fault.HasAny()) + { + commandObj->AddClusterSpecificFailure(commandPath, + to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); + return true; + } + + // verify min 1 requirement + VerifyOrExit(targetLevel.HasValue() ? targetLevel.Value() > 0 : true, status.Emplace(Status::ConstraintError)); + if (openDuration.HasValue()) + { + bool validOpenDuration = openDuration.Value().IsNull() ? true : openDuration.Value().Value() > 0; + // verify min 1 requirement + VerifyOrExit(validOpenDuration, status.Emplace(Status::ConstraintError)); + + duration = openDuration.Value(); + } + else + { + VerifyOrExit(EMBER_ZCL_STATUS_SUCCESS == DefaultOpenDuration::Get(ep, duration), status.Emplace(Status::Failure)); + } + + if (HasFeature(ep, ValveConfigurationAndControl::Feature::kLevel)) + { + Percent defOpenLevel; + if (targetLevel.HasValue()) + { + level.SetNonNull(targetLevel.Value()); + } + else if (EMBER_ZCL_STATUS_SUCCESS == DefaultOpenLevel::Get(ep, &defOpenLevel)) + { + level.SetNonNull(defOpenLevel); + } + else + { + level.SetNonNull(Percent(100)); + } + } + + VerifyOrExit(CHIP_NO_ERROR == ValveConfigurationAndControl::SetValveLevel(ep, level, duration), + status.Emplace(Status::Failure)); + +exit: + if (status.HasValue()) + { + BitMask gFault( + ValveConfigurationAndControl::ValveFaultBitmap::kGeneralFault); + emitValveFaultEvent(ep, gFault); + commandObj->AddStatus(commandPath, status.Value()); + } + else + { + commandObj->AddStatus(commandPath, Status::Success); + } + + return true; +} + +bool emberAfValveConfigurationAndControlClusterCloseCallback( + CommandHandler * commandObj, const ConcreteCommandPath & commandPath, + const ValveConfigurationAndControl::Commands::Close::DecodableType & commandData) +{ + const auto & ep = commandPath.mEndpointId; + BitMask fault(0); + + // if fault is registered return FailureDueToFault + if (EMBER_ZCL_STATUS_SUCCESS == ValveFault::Get(ep, &fault) && fault.HasAny()) + { + commandObj->AddClusterSpecificFailure(commandPath, + to_underlying(ValveConfigurationAndControl::StatusCodeEnum::kFailureDueToFault)); + return true; + } + + if (CHIP_NO_ERROR == ValveConfigurationAndControl::CloseValve(ep)) + { + commandObj->AddStatus(commandPath, Status::Success); + } + else + { + commandObj->AddStatus(commandPath, Status::Failure); + } + + return true; +} + +void MatterValveConfigurationAndControlPluginServerInitCallback() +{ + registerAttributeAccessOverride(&gAttrAccess); +} diff --git a/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.h b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.h new file mode 100644 index 00000000000000..6f46e8cc6356e4 --- /dev/null +++ b/src/app/clusters/valve-configuration-and-control-server/valve-configuration-and-control-server.h @@ -0,0 +1,59 @@ +/** + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file API declarations for valve configuration and control cluster. + */ + +#pragma once + +#include "valve-configuration-and-control-delegate.h" + +#include +#include +#include +#include +#include +#include +#include + +namespace chip { +namespace app { +namespace Clusters { +namespace ValveConfigurationAndControl { + +void SetDefaultDelegate(EndpointId endpoint, Delegate * delegate); +Delegate * GetDefaultDelegate(EndpointId endpoint); + +CHIP_ERROR CloseValve(chip::EndpointId ep); +CHIP_ERROR SetValveLevel(chip::EndpointId ep, chip::Percent level, DataModel::Nullable openDuration); +CHIP_ERROR UpdateCurrentLevel(chip::EndpointId ep, chip::Percent currentLevel); +CHIP_ERROR UpdateCurrentState(chip::EndpointId ep, ValveConfigurationAndControl::ValveStateEnum currentState); +CHIP_ERROR EmitValveFault(chip::EndpointId ep, chip::BitMask fault); +void UpdateAutoCloseTime(uint64_t time); + +inline bool HasFeature(EndpointId ep, Feature feature) +{ + uint32_t map; + bool success = (Attributes::FeatureMap::Get(ep, &map) == EMBER_ZCL_STATUS_SUCCESS); + return success ? (map & to_underlying(feature)) : false; +} + +} // namespace ValveConfigurationAndControl +} // namespace Clusters +} // namespace app +} // namespace chip diff --git a/src/app/tests/BUILD.gn b/src/app/tests/BUILD.gn index 1c48851aa07b95..d0f9a73178ccb0 100644 --- a/src/app/tests/BUILD.gn +++ b/src/app/tests/BUILD.gn @@ -18,6 +18,7 @@ import("//build_overrides/nlunit_test.gni") import("${chip_root}/build/chip/chip_test_suite.gni") import("${chip_root}/src/app/icd/icd.gni") +import("${chip_root}/src/crypto/crypto.gni") import("${chip_root}/src/platform/device.gni") static_library("helpers") { @@ -162,7 +163,11 @@ chip_test_suite_using_nltest("tests") { } test_sources += [ "TestAclAttribute.cpp" ] - test_sources += [ "TestDefaultICDClientStorage.cpp" ] + + # DefaultICDClientStorage assumes that raw AES key is used by the application + if (chip_crypto != "psa") { + test_sources += [ "TestDefaultICDClientStorage.cpp" ] + } # # On NRF platforms, the allocation of a large number of pbufs in this test diff --git a/src/app/tests/suites/certification/Test_TC_DGWIFI_2_1.yaml b/src/app/tests/suites/certification/Test_TC_DGWIFI_2_1.yaml index a95db84e1785fb..7ed81db6ac7c94 100644 --- a/src/app/tests/suites/certification/Test_TC_DGWIFI_2_1.yaml +++ b/src/app/tests/suites/certification/Test_TC_DGWIFI_2_1.yaml @@ -56,7 +56,7 @@ tests: constraints: type: enum8 minValue: 0 - maxValue: 5 + maxValue: 6 - label: "Step 5: TH reads ChannelNumber attribute constraints" PICS: DGWIFI.S.A0003 diff --git a/src/app/util/util.cpp b/src/app/util/util.cpp index 98c475d608864e..2f43df991a345c 100644 --- a/src/app/util/util.cpp +++ b/src/app/util/util.cpp @@ -160,7 +160,6 @@ void MatterRvcOperationalStatePluginServerInitCallback() {} void MatterOvenModePluginServerInitCallback() {} void MatterDishwasherAlarmPluginServerInitCallback() {} void MatterBooleanStateConfigurationPluginServerInitCallback() {} -void MatterValveConfigurationAndControlPluginServerInitCallback() {} void MatterMicrowaveOvenModePluginServerInitCallback() {} // **************************************** // Print out information about each cluster diff --git a/src/app/zap-templates/zcl/zcl-with-test-extensions.json b/src/app/zap-templates/zcl/zcl-with-test-extensions.json index 634f66606f6a60..83b541897d7abc 100644 --- a/src/app/zap-templates/zcl/zcl-with-test-extensions.json +++ b/src/app/zap-templates/zcl/zcl-with-test-extensions.json @@ -559,7 +559,8 @@ "CumulativeEnergyExported", "PeriodicEnergyImported", "PeriodicEnergyExported" - ] + ], + "Valve Configuration and Control": ["RemainingDuration"] }, "defaultReportingPolicy": "mandatory", "ZCLDataTypes": ["ARRAY", "BITMAP", "ENUM", "NUMBER", "STRING", "STRUCT"], diff --git a/src/app/zap-templates/zcl/zcl.json b/src/app/zap-templates/zcl/zcl.json index a0556e6da7ebb2..0e0e0f925f7885 100644 --- a/src/app/zap-templates/zcl/zcl.json +++ b/src/app/zap-templates/zcl/zcl.json @@ -557,7 +557,8 @@ "CumulativeEnergyExported", "PeriodicEnergyImported", "PeriodicEnergyExported" - ] + ], + "Valve Configuration and Control": ["RemainingDuration"] }, "defaultReportingPolicy": "mandatory", "ZCLDataTypes": ["ARRAY", "BITMAP", "ENUM", "NUMBER", "STRING", "STRUCT"], diff --git a/src/app/zap_cluster_list.json b/src/app/zap_cluster_list.json index a7f1c8e58dca6f..021cc8aa466f4d 100644 --- a/src/app/zap_cluster_list.json +++ b/src/app/zap_cluster_list.json @@ -285,7 +285,9 @@ "UNIT_LOCALIZATION_CLUSTER": [], "UNIT_TESTING_CLUSTER": ["test-cluster-server"], "USER_LABEL_CLUSTER": ["user-label-server"], - "VALVE_CONFIGURATION_AND_CONTROL_CLUSTER": [], + "VALVE_CONFIGURATION_AND_CONTROL_CLUSTER": [ + "valve-configuration-and-control-server" + ], "WAKE_ON_LAN_CLUSTER": ["wake-on-lan-server"], "LAUNDRY_WASHER_CONTROLS_CLUSTER": ["laundry-washer-controls-server"], "LAUNDRY_DRYER_CONTROLS_CLUSTER": ["laundry-dryer-controls-server"], diff --git a/src/controller/python/chip/clusters/Attribute.py b/src/controller/python/chip/clusters/Attribute.py index 25691bb826cf55..96a66f5706f174 100644 --- a/src/controller/python/chip/clusters/Attribute.py +++ b/src/controller/python/chip/clusters/Attribute.py @@ -24,7 +24,7 @@ import logging import sys from asyncio.futures import Future -from ctypes import CFUNCTYPE, c_size_t, c_uint8, c_uint16, c_uint32, c_uint64, c_void_p, py_object +from ctypes import CFUNCTYPE, POINTER, c_size_t, c_uint8, c_uint16, c_uint32, c_uint64, c_void_p, cast, py_object from dataclasses import dataclass, field from enum import Enum, unique from typing import Any, Callable, Dict, List, Optional, Tuple, Union @@ -34,6 +34,7 @@ import chip.interaction_model import chip.tlv import construct +from chip.interaction_model import PyWriteAttributeData from chip.native import ErrorSDKPart, PyChipError from rich.pretty import pprint @@ -955,22 +956,22 @@ def WriteAttributes(future: Future, eventLoop, device, interactionTimeoutMs: Union[None, int] = None, busyWaitMs: Union[None, int] = None) -> PyChipError: handle = chip.native.GetLibraryHandle() - writeargs = [] - for attr in attributes: + numberOfAttributes = len(attributes) + pyWriteAttributesArrayType = PyWriteAttributeData * numberOfAttributes + pyWriteAttributes = pyWriteAttributesArrayType() + for idx, attr in enumerate(attributes): if attr.Attribute.must_use_timed_write and timedRequestTimeoutMs is None or timedRequestTimeoutMs == 0: raise chip.interaction_model.InteractionModelError(chip.interaction_model.Status.NeedsTimedInteraction) - path = chip.interaction_model.AttributePathIBstruct.parse( - b'\x00' * chip.interaction_model.AttributePathIBstruct.sizeof()) - path.EndpointId = attr.EndpointId - path.ClusterId = attr.Attribute.cluster_id - path.AttributeId = attr.Attribute.attribute_id - path.DataVersion = attr.DataVersion - path.HasDataVersion = attr.HasDataVersion - path = chip.interaction_model.AttributePathIBstruct.build(path) + tlv = attr.Attribute.ToTLV(None, attr.Data) - writeargs.append(ctypes.c_char_p(path)) - writeargs.append(ctypes.c_char_p(bytes(tlv))) - writeargs.append(ctypes.c_int(len(tlv))) + + pyWriteAttributes[idx].attributePath.endpointId = c_uint16(attr.EndpointId) + pyWriteAttributes[idx].attributePath.clusterId = c_uint32(attr.Attribute.cluster_id) + pyWriteAttributes[idx].attributePath.attributeId = c_uint32(attr.Attribute.attribute_id) + pyWriteAttributes[idx].attributePath.dataVersion = c_uint32(attr.DataVersion) + pyWriteAttributes[idx].attributePath.hasDataVersion = c_uint8(attr.HasDataVersion) + pyWriteAttributes[idx].tlvData = cast(ctypes.c_char_p(bytes(tlv)), c_void_p) + pyWriteAttributes[idx].tlvLength = c_size_t(len(tlv)) transaction = AsyncWriteTransaction(future, eventLoop) ctypes.pythonapi.Py_IncRef(ctypes.py_object(transaction)) @@ -980,7 +981,7 @@ def WriteAttributes(future: Future, eventLoop, device, ctypes.c_size_t(0 if timedRequestTimeoutMs is None else timedRequestTimeoutMs), ctypes.c_size_t(0 if interactionTimeoutMs is None else interactionTimeoutMs), ctypes.c_size_t(0 if busyWaitMs is None else busyWaitMs), - ctypes.c_size_t(len(attributes)), *writeargs) + pyWriteAttributes, ctypes.c_size_t(numberOfAttributes)) ) if not res.is_success: ctypes.pythonapi.Py_DecRef(ctypes.py_object(transaction)) @@ -990,26 +991,26 @@ def WriteAttributes(future: Future, eventLoop, device, def WriteGroupAttributes(groupId: int, devCtrl: c_void_p, attributes: List[AttributeWriteRequest], busyWaitMs: Union[None, int] = None) -> PyChipError: handle = chip.native.GetLibraryHandle() - writeargs = [] - for attr in attributes: - path = chip.interaction_model.AttributePathIBstruct.parse( - b'\x00' * chip.interaction_model.AttributePathIBstruct.sizeof()) - path.EndpointId = attr.EndpointId - path.ClusterId = attr.Attribute.cluster_id - path.AttributeId = attr.Attribute.attribute_id - path.DataVersion = attr.DataVersion - path.HasDataVersion = attr.HasDataVersion - path = chip.interaction_model.AttributePathIBstruct.build(path) + numberOfAttributes = len(attributes) + pyWriteAttributesArrayType = PyWriteAttributeData * numberOfAttributes + pyWriteAttributes = pyWriteAttributesArrayType() + for idx, attr in enumerate(attributes): + tlv = attr.Attribute.ToTLV(None, attr.Data) - writeargs.append(ctypes.c_char_p(path)) - writeargs.append(ctypes.c_char_p(bytes(tlv))) - writeargs.append(ctypes.c_int(len(tlv))) + + pyWriteAttributes[idx].attributePath.endpointId = c_uint16(attr.EndpointId) + pyWriteAttributes[idx].attributePath.clusterId = c_uint32(attr.Attribute.cluster_id) + pyWriteAttributes[idx].attributePath.attributeId = c_uint32(attr.Attribute.attribute_id) + pyWriteAttributes[idx].attributePath.dataVersion = c_uint32(attr.DataVersion) + pyWriteAttributes[idx].attributePath.hasDataVersion = c_uint8(attr.HasDataVersion) + pyWriteAttributes[idx].tlvData = cast(ctypes.c_char_p(bytes(tlv)), c_void_p) + pyWriteAttributes[idx].tlvLength = c_size_t(len(tlv)) return builtins.chipStack.Call( lambda: handle.pychip_WriteClient_WriteGroupAttributes( ctypes.c_size_t(groupId), devCtrl, ctypes.c_size_t(0 if busyWaitMs is None else busyWaitMs), - ctypes.c_size_t(len(attributes)), *writeargs) + pyWriteAttributes, ctypes.c_size_t(numberOfAttributes)) ) @@ -1037,10 +1038,12 @@ def Read(future: Future, eventLoop, device, devCtrl, transaction = AsyncReadTransaction( future, eventLoop, devCtrl, returnClusterObject) - readargs = [] - + attributePathsForCffi = None if attributes is not None: - for attr in attributes: + numberOfAttributePaths = len(attributes) + attributePathsForCffiArrayType = c_void_p * numberOfAttributePaths + attributePathsForCffi = attributePathsForCffiArrayType() + for idx, attr in enumerate(attributes): path = chip.interaction_model.AttributePathIBstruct.parse( b'\xff' * chip.interaction_model.AttributePathIBstruct.sizeof()) if attr.EndpointId is not None: @@ -1050,10 +1053,14 @@ def Read(future: Future, eventLoop, device, devCtrl, if attr.AttributeId is not None: path.AttributeId = attr.AttributeId path = chip.interaction_model.AttributePathIBstruct.build(path) - readargs.append(ctypes.c_char_p(path)) + attributePathsForCffi[idx] = cast(ctypes.c_char_p(path), c_void_p) + dataVersionFiltersForCffi = None if dataVersionFilters is not None: - for f in dataVersionFilters: + numberOfDataVersionFilters = len(dataVersionFilters) + dataVersionFiltersForCffiArrayType = c_void_p * numberOfDataVersionFilters + dataVersionFiltersForCffi = dataVersionFiltersForCffiArrayType() + for idx, f in enumerate(dataVersionFilters): filter = chip.interaction_model.DataVersionFilterIBstruct.parse( b'\xff' * chip.interaction_model.DataVersionFilterIBstruct.sizeof()) if f.EndpointId is not None: @@ -1073,10 +1080,14 @@ def Read(future: Future, eventLoop, device, devCtrl, "DataVersionFilter must provide DataVersion.") filter = chip.interaction_model.DataVersionFilterIBstruct.build( filter) - readargs.append(ctypes.c_char_p(filter)) + dataVersionFiltersForCffi[idx] = cast(ctypes.c_char_p(filter), c_void_p) + eventPathsForCffi = None if events is not None: - for event in events: + numberOfEvents = len(events) + eventPathsForCffiArrayType = c_void_p * numberOfEvents + eventPathsForCffi = eventPathsForCffiArrayType() + for idx, event in enumerate(events): path = chip.interaction_model.EventPathIBstruct.parse( b'\xff' * chip.interaction_model.EventPathIBstruct.sizeof()) if event.EndpointId is not None: @@ -1090,7 +1101,7 @@ def Read(future: Future, eventLoop, device, devCtrl, else: path.Urgent = 0 path = chip.interaction_model.EventPathIBstruct.build(path) - readargs.append(ctypes.c_char_p(path)) + eventPathsForCffi[idx] = cast(ctypes.c_char_p(path), c_void_p) readClientObj = ctypes.POINTER(c_void_p)() readCallbackObj = ctypes.POINTER(c_void_p)() @@ -1116,12 +1127,14 @@ def Read(future: Future, eventLoop, device, devCtrl, ctypes.byref(readCallbackObj), device, ctypes.c_char_p(params), + attributePathsForCffi, ctypes.c_size_t(0 if attributes is None else len(attributes)), + dataVersionFiltersForCffi, ctypes.c_size_t( 0 if dataVersionFilters is None else len(dataVersionFilters)), + eventPathsForCffi, ctypes.c_size_t(0 if events is None else len(events)), - eventNumberFilterPtr, - *readargs)) + eventNumberFilterPtr)) transaction.SetClientObjPointers(readClientObj, readCallbackObj) @@ -1168,8 +1181,10 @@ def Init(): # attribute information we want written using a vector. This possibility was not implemented at the # time where simply specified the argtypes, because of time constraints. This solution was quicker # to fix the crash on ARM64 Apple platforms without a refactor. - handle.pychip_WriteClient_WriteAttributes.argtypes = [py_object, c_void_p, c_size_t, c_size_t, c_size_t, c_size_t] - handle.pychip_WriteClient_WriteGroupAttributes.argtypes = [c_size_t, c_void_p, c_size_t, c_size_t] + handle.pychip_WriteClient_WriteAttributes.argtypes = [py_object, c_void_p, + c_size_t, c_size_t, c_size_t, POINTER(PyWriteAttributeData), c_size_t] + handle.pychip_WriteClient_WriteGroupAttributes.argtypes = [ + c_size_t, c_void_p, c_size_t, POINTER(PyWriteAttributeData), c_size_t] setter.Set('pychip_WriteClient_InitCallbacks', None, [ _OnWriteResponseCallbackFunct, _OnWriteErrorCallbackFunct, _OnWriteDoneCallbackFunct]) diff --git a/src/controller/python/chip/clusters/Command.py b/src/controller/python/chip/clusters/Command.py index d3dcc5bba913ff..6e25a76d50230f 100644 --- a/src/controller/python/chip/clusters/Command.py +++ b/src/controller/python/chip/clusters/Command.py @@ -21,12 +21,13 @@ import logging import sys from asyncio.futures import Future -from ctypes import CFUNCTYPE, c_bool, c_char_p, c_size_t, c_uint8, c_uint16, c_uint32, c_void_p, py_object +from ctypes import CFUNCTYPE, POINTER, c_bool, c_char_p, c_size_t, c_uint8, c_uint16, c_uint32, c_void_p, cast, py_object from dataclasses import dataclass from typing import List, Optional, Type, Union import chip.exceptions import chip.interaction_model +from chip.interaction_model import PyInvokeRequestData from chip.native import PyChipError from .ClusterObjects import ClusterCommand @@ -313,8 +314,10 @@ def SendBatchCommands(future: Future, eventLoop, device, commands: List[InvokeRe handle = chip.native.GetLibraryHandle() responseTypes = [] - commandargs = [] - for command in commands: + numberOfCommands = len(commands) + pyBatchCommandsDataArrayType = PyInvokeRequestData * numberOfCommands + pyBatchCommandsData = pyBatchCommandsDataArrayType() + for idx, command in enumerate(commands): clusterCommand = command.Command responseType = command.ResponseType if (responseType is not None) and (not issubclass(responseType, ClusterCommand)): @@ -322,15 +325,13 @@ def SendBatchCommands(future: Future, eventLoop, device, commands: List[InvokeRe if clusterCommand.must_use_timed_invoke and timedRequestTimeoutMs is None or timedRequestTimeoutMs == 0: raise chip.interaction_model.InteractionModelError(chip.interaction_model.Status.NeedsTimedInteraction) - commandPath = chip.interaction_model.CommandPathIBStruct.build({ - "EndpointId": command.EndpointId, - "ClusterId": clusterCommand.cluster_id, - "CommandId": clusterCommand.command_id}) payloadTLV = clusterCommand.ToTLV() - commandargs.append(c_char_p(commandPath)) - commandargs.append(c_char_p(bytes(payloadTLV))) - commandargs.append(c_size_t(len(payloadTLV))) + pyBatchCommandsData[idx].commandPath.endpointId = c_uint16(command.EndpointId) + pyBatchCommandsData[idx].commandPath.clusterId = c_uint32(clusterCommand.cluster_id) + pyBatchCommandsData[idx].commandPath.commandId = c_uint32(clusterCommand.command_id) + pyBatchCommandsData[idx].tlvData = cast(c_char_p(bytes(payloadTLV)), c_void_p) + pyBatchCommandsData[idx].tlvLength = c_size_t(len(payloadTLV)) responseTypes.append(responseType) @@ -344,7 +345,7 @@ def SendBatchCommands(future: Future, eventLoop, device, commands: List[InvokeRe c_uint16(0 if interactionTimeoutMs is None else interactionTimeoutMs), c_uint16(0 if busyWaitMs is None else busyWaitMs), c_bool(False if suppressResponse is None else suppressResponse), - c_size_t(len(commands)), *commandargs) + pyBatchCommandsData, c_size_t(numberOfCommands)) ) @@ -375,7 +376,7 @@ def Init(): setter.Set('pychip_CommandSender_SendCommand', PyChipError, [py_object, c_void_p, c_uint16, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool]) setter.Set('pychip_CommandSender_SendBatchCommands', - PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, c_size_t]) + PyChipError, [py_object, c_void_p, c_uint16, c_uint16, c_uint16, c_bool, POINTER(PyInvokeRequestData), c_size_t]) setter.Set('pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke', PyChipError, [py_object, c_void_p, c_uint32, c_uint32, c_char_p, c_size_t, c_uint16, c_bool]) setter.Set('pychip_CommandSender_SendGroupCommand', diff --git a/src/controller/python/chip/clusters/attribute.cpp b/src/controller/python/chip/clusters/attribute.cpp index d85d132b36bf8a..8abaaab18e1ed9 100644 --- a/src/controller/python/chip/clusters/attribute.cpp +++ b/src/controller/python/chip/clusters/attribute.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -256,13 +257,14 @@ struct __attribute__((packed)) PyReadAttributeParams bool autoResubscribe; }; -// Encodes n attribute write requests, follows 3 * n arguments, in the (AttributeWritePath*=void *, uint8_t*, size_t) order. PyChipError pychip_WriteClient_WriteAttributes(void * appContext, DeviceProxy * device, size_t timedWriteTimeoutMsSizeT, - size_t interactionTimeoutMsSizeT, size_t busyWaitMsSizeT, size_t n, ...); + size_t interactionTimeoutMsSizeT, size_t busyWaitMsSizeT, + chip::python::PyWriteAttributeData * writeAttributesData, + size_t attributeDataLength); PyChipError pychip_WriteClient_WriteGroupAttributes(size_t groupIdSizeT, chip::Controller::DeviceCommissioner * devCtrl, - size_t busyWaitMsSizeT, size_t n, ...); -PyChipError pychip_ReadClient_ReadAttributes(void * appContext, ReadClient ** pReadClient, ReadClientCallback ** pCallback, - DeviceProxy * device, uint8_t * readParamsBuf, size_t n, size_t total, ...); + size_t busyWaitMsSizeT, + chip::python::PyWriteAttributeData * writeAttributesData, + size_t attributeDataLength); } using OnWriteResponseCallback = void (*)(PyObject * appContext, chip::EndpointId endpointId, chip::ClusterId clusterId, @@ -337,7 +339,8 @@ void pychip_ReadClient_InitCallbacks(OnReadAttributeDataCallback onReadAttribute } PyChipError pychip_WriteClient_WriteAttributes(void * appContext, DeviceProxy * device, size_t timedWriteTimeoutMsSizeT, - size_t interactionTimeoutMsSizeT, size_t busyWaitMsSizeT, size_t n, ...) + size_t interactionTimeoutMsSizeT, size_t busyWaitMsSizeT, + python::PyWriteAttributeData * writeAttributesData, size_t attributeDataLength) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -352,35 +355,27 @@ PyChipError pychip_WriteClient_WriteAttributes(void * appContext, DeviceProxy * app::InteractionModelEngine::GetInstance()->GetExchangeManager(), callback->GetChunkedCallback(), timedWriteTimeoutMs != 0 ? Optional(timedWriteTimeoutMs) : Optional::Missing()); - va_list args; - va_start(args, n); - VerifyOrExit(device != nullptr && device->GetSecureSession().HasValue(), err = CHIP_ERROR_MISSING_SECURE_SESSION); + for (size_t i = 0; i < attributeDataLength; i++) { - for (size_t i = 0; i < n; i++) + python::PyAttributePath path = writeAttributesData[i].attributePath; + void * tlv = writeAttributesData[i].tlvData; + size_t length = writeAttributesData[i].tlvLength; + + uint8_t * tlvBuffer = reinterpret_cast(tlv); + + TLV::TLVReader reader; + reader.Init(tlvBuffer, static_cast(length)); + reader.Next(); + Optional dataVersion; + if (path.hasDataVersion == 1) { - void * path = va_arg(args, void *); - void * tlv = va_arg(args, void *); - int length = va_arg(args, int); - - python::AttributePath pathObj; - memcpy(&pathObj, path, sizeof(python::AttributePath)); - uint8_t * tlvBuffer = reinterpret_cast(tlv); - - TLV::TLVReader reader; - reader.Init(tlvBuffer, static_cast(length)); - reader.Next(); - Optional dataVersion; - if (pathObj.hasDataVersion == 1) - { - dataVersion.SetValue(pathObj.dataVersion); - } - SuccessOrExit( - err = client->PutPreencodedAttribute( - chip::app::ConcreteDataAttributePath(pathObj.endpointId, pathObj.clusterId, pathObj.attributeId, dataVersion), - reader)); + dataVersion.SetValue(path.dataVersion); } + SuccessOrExit( + err = client->PutPreencodedAttribute( + chip::app::ConcreteDataAttributePath(path.endpointId, path.clusterId, path.attributeId, dataVersion), reader)); } SuccessOrExit(err = client->SendWriteRequest(device->GetSecureSession().Value(), @@ -396,12 +391,12 @@ PyChipError pychip_WriteClient_WriteAttributes(void * appContext, DeviceProxy * } exit: - va_end(args); return ToPyChipError(err); } PyChipError pychip_WriteClient_WriteGroupAttributes(size_t groupIdSizeT, chip::Controller::DeviceCommissioner * devCtrl, - size_t busyWaitMsSizeT, size_t n, ...) + size_t busyWaitMsSizeT, python::PyWriteAttributeData * writeAttributesData, + size_t attributeDataLength) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -417,34 +412,26 @@ PyChipError pychip_WriteClient_WriteGroupAttributes(size_t groupIdSizeT, chip::C std::unique_ptr client = std::make_unique( app::InteractionModelEngine::GetInstance()->GetExchangeManager(), nullptr /* callback */, Optional::Missing()); - va_list args; - va_start(args, n); - + for (size_t i = 0; i < attributeDataLength; i++) { - for (size_t i = 0; i < n; i++) + python::PyAttributePath path = writeAttributesData[i].attributePath; + void * tlv = writeAttributesData[i].tlvData; + size_t length = writeAttributesData[i].tlvLength; + + uint8_t * tlvBuffer = reinterpret_cast(tlv); + + TLV::TLVReader reader; + reader.Init(tlvBuffer, static_cast(length)); + reader.Next(); + Optional dataVersion; + if (path.hasDataVersion == 1) { - void * path = va_arg(args, void *); - void * tlv = va_arg(args, void *); - int length = va_arg(args, int); - - python::AttributePath pathObj; - memcpy(&pathObj, path, sizeof(python::AttributePath)); - uint8_t * tlvBuffer = reinterpret_cast(tlv); - - TLV::TLVReader reader; - reader.Init(tlvBuffer, static_cast(length)); - reader.Next(); - Optional dataVersion; - if (pathObj.hasDataVersion == 1) - { - dataVersion.SetValue(pathObj.dataVersion); - } - // Using kInvalidEndpointId as that used when sending group write requests. - SuccessOrExit( - err = client->PutPreencodedAttribute( - chip::app::ConcreteDataAttributePath(kInvalidEndpointId, pathObj.clusterId, pathObj.attributeId, dataVersion), - reader)); + dataVersion.SetValue(path.dataVersion); } + // Using kInvalidEndpointId as that used when sending group write requests. + SuccessOrExit( + err = client->PutPreencodedAttribute( + chip::app::ConcreteDataAttributePath(kInvalidEndpointId, path.clusterId, path.attributeId, dataVersion), reader)); } { @@ -460,7 +447,6 @@ PyChipError pychip_WriteClient_WriteGroupAttributes(size_t groupIdSizeT, chip::C } exit: - va_end(args); return ToPyChipError(err); } @@ -487,8 +473,9 @@ PyChipError pychip_ReadClient_GetReportingIntervals(ReadClient * pReadClient, ui } PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, ReadClientCallback ** pCallback, - DeviceProxy * device, uint8_t * readParamsBuf, size_t numAttributePaths, - size_t numDataversionFilters, size_t numEventPaths, uint64_t * eventNumberFilter, ...) + DeviceProxy * device, uint8_t * readParamsBuf, void ** attributePathsFromPython, + size_t numAttributePaths, void ** dataversionFiltersFromPython, size_t numDataversionFilters, + void ** eventPathsFromPython, size_t numEventPaths, uint64_t * eventNumberFilter) { CHIP_ERROR err = CHIP_NO_ERROR; PyReadAttributeParams pyParams = {}; @@ -497,9 +484,6 @@ PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, std::unique_ptr callback = std::make_unique(appContext); - va_list args; - va_start(args, eventNumberFilter); - std::unique_ptr attributePaths(new AttributePathParams[numAttributePaths]); std::unique_ptr dataVersionFilters(new chip::app::DataVersionFilter[numDataversionFilters]); std::unique_ptr eventPaths(new EventPathParams[numEventPaths]); @@ -507,7 +491,7 @@ PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, for (size_t i = 0; i < numAttributePaths; i++) { - void * path = va_arg(args, void *); + void * path = attributePathsFromPython[i]; python::AttributePath pathObj; memcpy(&pathObj, path, sizeof(python::AttributePath)); @@ -517,7 +501,7 @@ PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, for (size_t i = 0; i < numDataversionFilters; i++) { - void * filter = va_arg(args, void *); + void * filter = dataversionFiltersFromPython[i]; python::DataVersionFilter filterObj; memcpy(&filterObj, filter, sizeof(python::DataVersionFilter)); @@ -527,7 +511,7 @@ PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, for (size_t i = 0; i < numEventPaths; i++) { - void * path = va_arg(args, void *); + void * path = eventPathsFromPython[i]; python::EventPath pathObj; memcpy(&pathObj, path, sizeof(python::EventPath)); @@ -599,7 +583,6 @@ PyChipError pychip_ReadClient_Read(void * appContext, ReadClient ** pReadClient, callback.release(); exit: - va_end(args); return ToPyChipError(err); } } diff --git a/src/controller/python/chip/clusters/command.cpp b/src/controller/python/chip/clusters/command.cpp index c920a82c53fb54..7195cefe16eba1 100644 --- a/src/controller/python/chip/clusters/command.cpp +++ b/src/controller/python/chip/clusters/command.cpp @@ -41,7 +41,7 @@ PyChipError pychip_CommandSender_SendCommand(void * appContext, DeviceProxy * de PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs, uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse, - size_t n, ...); + chip::python::PyInvokeRequestData * batchCommandData, size_t length); PyChipError pychip_CommandSender_TestOnlySendCommandTimedRequestNoTimedInvoke( void * appContext, DeviceProxy * device, chip::EndpointId endpointId, chip::ClusterId clusterId, chip::CommandId commandId, @@ -68,13 +68,6 @@ OnCommandSenderResponseCallback gOnCommandSenderResponseCallback = nullptr; OnCommandSenderErrorCallback gOnCommandSenderErrorCallback = nullptr; OnCommandSenderDoneCallback gOnCommandSenderDoneCallback = nullptr; -struct __attribute__((packed)) CommandPath -{ - chip::EndpointId endpointId; - chip::ClusterId clusterId; - chip::CommandId commandId; -}; - class CommandSenderCallback : public CommandSender::ExtendableCallback { public: @@ -256,7 +249,7 @@ PyChipError pychip_CommandSender_SendCommand(void * appContext, DeviceProxy * de PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProxy * device, uint16_t timedRequestTimeoutMs, uint16_t interactionTimeoutMs, uint16_t busyWaitMs, bool suppressResponse, - size_t n, ...) + python::PyInvokeRequestData * batchCommandData, size_t length) { CHIP_ERROR err = CHIP_NO_ERROR; @@ -279,47 +272,41 @@ PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProx std::make_unique(callback.get(), device->GetExchangeManager(), /* is timed request */ timedRequestTimeoutMs != 0, suppressResponse); - // TODO(#30986): Move away from passing these command through variadic arguments. - va_list args; - va_start(args, n); - SuccessOrExit(err = sender->SetCommandSenderConfig(config)); + for (size_t i = 0; i < length; i++) { - for (size_t i = 0; i < n; i++) - { - void * commandPath = va_arg(args, void *); - void * tlv = va_arg(args, void *); - int length = va_arg(args, int); + chip::EndpointId endpointId = batchCommandData[i].commandPath.endpointId; + chip::ClusterId clusterId = batchCommandData[i].commandPath.clusterId; + chip::CommandId commandId = batchCommandData[i].commandPath.commandId; + void * tlv = batchCommandData[i].tlvData; + size_t tlvLength = batchCommandData[i].tlvLength; - python::CommandPath invokeRequestInfoObj; - memcpy(&invokeRequestInfoObj, commandPath, sizeof(python::CommandPath)); - const uint8_t * tlvBuffer = reinterpret_cast(tlv); + const uint8_t * tlvBuffer = reinterpret_cast(tlv); - app::CommandPathParams cmdParams = { invokeRequestInfoObj.endpointId, /* group id */ 0, invokeRequestInfoObj.clusterId, - invokeRequestInfoObj.commandId, (app::CommandPathFlags::kEndpointIdValid) }; + app::CommandPathParams cmdParams = { endpointId, /* group id */ 0, clusterId, commandId, + (app::CommandPathFlags::kEndpointIdValid) }; - CommandSender::AdditionalCommandParameters additionalParams; + CommandSender::AdditionalCommandParameters additionalParams; - SuccessOrExit(err = sender->PrepareCommand(cmdParams, additionalParams)); - { - auto writer = sender->GetCommandDataIBTLVWriter(); - VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE); - TLV::TLVReader reader; - reader.Init(tlvBuffer, static_cast(length)); - reader.Next(); - SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader)); - } + SuccessOrExit(err = sender->PrepareCommand(cmdParams, additionalParams)); + { + auto writer = sender->GetCommandDataIBTLVWriter(); + VerifyOrExit(writer != nullptr, err = CHIP_ERROR_INCORRECT_STATE); + TLV::TLVReader reader; + reader.Init(tlvBuffer, static_cast(tlvLength)); + reader.Next(); + SuccessOrExit(err = writer->CopyContainer(TLV::ContextTag(CommandDataIB::Tag::kFields), reader)); + } - SuccessOrExit(err = sender->FinishCommand(timedRequestTimeoutMs != 0 ? Optional(timedRequestTimeoutMs) - : Optional::Missing(), - additionalParams)); + SuccessOrExit(err = sender->FinishCommand(timedRequestTimeoutMs != 0 ? Optional(timedRequestTimeoutMs) + : Optional::Missing(), + additionalParams)); - // CommandSender provides us with the CommandReference for this associated command. In order to match responses - // we have to add CommandRef to index lookup. - VerifyOrExit(additionalParams.commandRef.HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); - SuccessOrExit(err = callback->AddCommandRefToIndexLookup(additionalParams.commandRef.Value(), i)); - } + // CommandSender provides us with the CommandReference for this associated command. In order to match responses + // we have to add CommandRef to index lookup. + VerifyOrExit(additionalParams.commandRef.HasValue(), err = CHIP_ERROR_INVALID_ARGUMENT); + SuccessOrExit(err = callback->AddCommandRefToIndexLookup(additionalParams.commandRef.Value(), i)); } SuccessOrExit(err = sender->SendCommandRequest(device->GetSecureSession().Value(), @@ -338,7 +325,6 @@ PyChipError pychip_CommandSender_SendBatchCommands(void * appContext, DeviceProx } exit: - va_end(args); return ToPyChipError(err); } diff --git a/src/controller/python/chip/interaction_model/Delegate.h b/src/controller/python/chip/interaction_model/Delegate.h index c92d0d042459c7..f11f4931fc4c1d 100644 --- a/src/controller/python/chip/interaction_model/Delegate.h +++ b/src/controller/python/chip/interaction_model/Delegate.h @@ -23,8 +23,45 @@ namespace chip { namespace python { + static constexpr ClusterStatus kUndefinedClusterStatus = 0xFF; -} + +// This needs to match the python definition that uses the same name. +struct PyCommandPath +{ + chip::EndpointId endpointId; + chip::ClusterId clusterId; + chip::CommandId commandId; +}; + +// This needs to match the python definition that uses the same name. +struct PyInvokeRequestData +{ + PyCommandPath commandPath; + void * tlvData; + size_t tlvLength; +}; + +// This needs to match the python definition that uses the same name. +struct PyAttributePath +{ + chip::EndpointId endpointId; + chip::ClusterId clusterId; + chip::AttributeId attributeId; + chip::DataVersion dataVersion; + uint8_t hasDataVersion; +}; + +// This needs to match the python definition that uses the same name. +struct PyWriteAttributeData +{ + PyAttributePath attributePath; + void * tlvData; + size_t tlvLength; +}; + +} // namespace python + namespace Controller { // The command status will be used for python script. diff --git a/src/controller/python/chip/interaction_model/__init__.py b/src/controller/python/chip/interaction_model/__init__.py index 97c185bdcd96e5..78568563a73475 100644 --- a/src/controller/python/chip/interaction_model/__init__.py +++ b/src/controller/python/chip/interaction_model/__init__.py @@ -26,12 +26,12 @@ from chip.exceptions import ChipStackException -from .delegate import (AttributePath, AttributePathIBstruct, CommandPathIBStruct, DataVersionFilterIBstruct, EventPath, - EventPathIBstruct, SessionParameters, SessionParametersStruct) +from .delegate import (AttributePath, AttributePathIBstruct, DataVersionFilterIBstruct, EventPath, EventPathIBstruct, + PyInvokeRequestData, PyWriteAttributeData, SessionParameters, SessionParametersStruct) -__all__ = ["AttributePath", "AttributePathIBstruct", "CommandPathIBStruct", - "DataVersionFilterIBstruct", "EventPath", "EventPathIBstruct", - "InteractionModelError", "SessionParameters", "SessionParametersStruct", "Status"] +__all__ = ["AttributePath", "AttributePathIBstruct", "DataVersionFilterIBstruct", + "EventPath", "EventPathIBstruct", "InteractionModelError", "PyInvokeRequestData", + "PyWriteAttributeData", "SessionParameters", "SessionParametersStruct", "Status"] # defined src/controller/python/chip/interaction_model/Delegate.h diff --git a/src/controller/python/chip/interaction_model/delegate.py b/src/controller/python/chip/interaction_model/delegate.py index 6ce577b94580de..a9a9c04c4365a9 100644 --- a/src/controller/python/chip/interaction_model/delegate.py +++ b/src/controller/python/chip/interaction_model/delegate.py @@ -46,12 +46,6 @@ "AttributeId" / Int32ul, ) -CommandPathIBStruct = Struct( - "EndpointId" / Int16ul, - "ClusterId" / Int32ul, - "CommandId" / Int32ul, -) - # AttributePath should not contain padding AttributePathIBstruct = Struct( "EndpointId" / Int16ul, @@ -134,6 +128,77 @@ class SessionParameters: maxPathsPerInvoke: int +class PyCommandPath(ctypes.Structure): + ''' InvokeRequest Path struct that has c++ counterpart for CFFI. + + We are using the following struct for passing the information of InvokeRequest between Python and C++: + + ```c + struct PyCommandPath + { + chip::EndpointId endpointId; + chip::ClusterId clusterId; + chip::CommandId commandId; + }; + ``` + ''' + _fields_ = [('endpointId', ctypes.c_uint16), ('clusterId', ctypes.c_uint32), ('commandId', ctypes.c_uint32)] + + +class PyInvokeRequestData(ctypes.Structure): + ''' InvokeRequest struct that has c++ counterpart for CFFI. + + We are using the following struct for passing the information of InvokeRequest between Python and C++: + + ```c + struct PyInvokeRequestData + { + PyCommandPath commandPath; + void * tlvData; + size_t tlvLength; + }; + ``` + ''' + _fields_ = [('commandPath', PyCommandPath), ('tlvData', ctypes.c_void_p), ('tlvLength', ctypes.c_size_t)] + + +class PyAttributePath(ctypes.Structure): + ''' Attributed Path struct that has c++ counterpart for CFFI. + + We are using the following struct for passing the information of WriteAttributes between Python and C++: + + ```c + struct PyAttributePath + { + chip::EndpointId endpointId; + chip::ClusterId clusterId; + chip::AttributeId attributeId; + chip::DataVersion dataVersion; + uint8_t hasDataVersion; + }; + ``` + ''' + _fields_ = [('endpointId', ctypes.c_uint16), ('clusterId', ctypes.c_uint32), ('attributeId', + ctypes.c_uint32), ('dataVersion', ctypes.c_uint32), ('hasDataVersion', ctypes.c_uint8)] + + +class PyWriteAttributeData(ctypes.Structure): + ''' WriteAttribute struct that has c++ counterpart for CFFI. + + We are using the following struct for passing the information of WriteAttributes between Python and C++: + + ```c + struct PyWriteAttributeData + { + PyAttributePath attributePath; + void * tlvData; + size_t tlvLength; + }; + ``` + ''' + _fields_ = [('attributePath', PyAttributePath), ('tlvData', ctypes.c_void_p), ('tlvLength', ctypes.c_size_t)] + + # typedef void (*PythonInteractionModelDelegate_OnCommandResponseStatusCodeReceivedFunct)(uint64_t commandSenderPtr, # void * commandStatusBuf); # typedef void (*PythonInteractionModelDelegate_OnCommandResponseProtocolErrorFunct)(uint64_t commandSenderPtr, diff --git a/src/crypto/tests/CHIPCryptoPALTest.cpp b/src/crypto/tests/CHIPCryptoPALTest.cpp index 74b339abad9877..4a3af662853172 100644 --- a/src/crypto/tests/CHIPCryptoPALTest.cpp +++ b/src/crypto/tests/CHIPCryptoPALTest.cpp @@ -52,10 +52,6 @@ #include -#if CHIP_CRYPTO_MBEDTLS -#include -#endif - #include #include #include @@ -71,6 +67,10 @@ #include #include +#if CHIP_CRYPTO_MBEDTLS || CHIP_CRYPTO_PSA +#include +#endif + #if CHIP_CRYPTO_PSA #include #endif @@ -88,7 +88,7 @@ using TestHKDF_sha = HKDF_sha; using TestHMAC_sha = HMAC_sha; // Helper class to verify that all mbedTLS heap objects are released at the end of a test. -#if CHIP_CRYPTO_MBEDTLS && defined(MBEDTLS_MEMORY_DEBUG) +#if defined(MBEDTLS_MEMORY_DEBUG) class HeapChecker { public: diff --git a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp index 5d20035aa99940..d6aa5f2e939251 100644 --- a/src/platform/nxp/k32w/common/BLEManagerCommon.cpp +++ b/src/platform/nxp/k32w/common/BLEManagerCommon.cpp @@ -1174,9 +1174,14 @@ void BLEManagerCommon::blekw_gap_connection_cb(deviceId_t deviceId, gapConnectio if (pConnectionEvent->eventType == gConnEvtConnected_c) { +#if CHIP_DEVICE_K32W1 #if defined(chip_with_low_power) && (chip_with_low_power == 1) + /* Disallow must be called here for K32W1, otherwise an assert will be reached. + * Disclaimer: this is a workaround until a better cross platform solution is found. */ PWR_DisallowDeviceToSleep(); #endif +#endif + #if CHIP_DEVICE_CONFIG_BLE_SET_PHY_2M_REQ ChipLogProgress(DeviceLayer, "BLE K32W: Trying to set the PHY to 2M"); diff --git a/src/platform/nxp/k32w/common/FactoryDataProvider.cpp b/src/platform/nxp/k32w/common/FactoryDataProvider.cpp index 315811cbf32442..1770cf22c659f0 100644 --- a/src/platform/nxp/k32w/common/FactoryDataProvider.cpp +++ b/src/platform/nxp/k32w/common/FactoryDataProvider.cpp @@ -44,31 +44,6 @@ uint32_t FactoryDataProvider::kFactoryDataStart = (uint32_t) __MATTER_FAC uint32_t FactoryDataProvider::kFactoryDataSize = (uint32_t) __MATTER_FACTORY_DATA_SIZE; uint32_t FactoryDataProvider::kFactoryDataPayloadStart = kFactoryDataStart + sizeof(FactoryDataProvider::Header); -FactoryDataProvider::FactoryDataProvider() -{ - maxLengths[FactoryDataId::kVerifierId] = kSpake2pSerializedVerifier_MaxBase64Len; - maxLengths[FactoryDataId::kSaltId] = kSpake2pSalt_MaxBase64Len; - maxLengths[FactoryDataId::kIcId] = sizeof(uint32_t); - maxLengths[FactoryDataId::kDacPrivateKeyId] = Crypto::kP256_PrivateKey_Length; - maxLengths[FactoryDataId::kDacCertificateId] = Credentials::kMaxDERCertLength; - maxLengths[FactoryDataId::kPaiCertificateId] = Credentials::kMaxDERCertLength; - maxLengths[FactoryDataId::kDiscriminatorId] = sizeof(uint32_t); - maxLengths[FactoryDataId::kSetupPasscodeId] = sizeof(uint32_t); - maxLengths[FactoryDataId::kVidId] = sizeof(uint16_t); - maxLengths[FactoryDataId::kPidId] = sizeof(uint16_t); - maxLengths[FactoryDataId::kCertDeclarationId] = Credentials::kMaxCMSSignedCDMessage; - maxLengths[FactoryDataId::kVendorNameId] = ConfigurationManager::kMaxVendorNameLength; - maxLengths[FactoryDataId::kProductNameId] = ConfigurationManager::kMaxProductNameLength; - maxLengths[FactoryDataId::kSerialNumberId] = ConfigurationManager::kMaxSerialNumberLength; - maxLengths[FactoryDataId::kManufacturingDateId] = ConfigurationManager::kMaxManufacturingDateLength; - maxLengths[FactoryDataId::kHardwareVersionId] = sizeof(uint16_t); - maxLengths[FactoryDataId::kHardwareVersionStrId] = ConfigurationManager::kMaxHardwareVersionStringLength; - maxLengths[FactoryDataId::kUniqueId] = ConfigurationManager::kMaxUniqueIDLength; - maxLengths[FactoryDataId::kPartNumber] = ConfigurationManager::kMaxPartNumberLength; - maxLengths[FactoryDataId::kProductURL] = ConfigurationManager::kMaxProductURLLength; - maxLengths[FactoryDataId::kProductLabel] = ConfigurationManager::kMaxProductLabelLength; -} - FactoryDataProvider::~FactoryDataProvider() {} CHIP_ERROR FactoryDataProvider::Validate() @@ -97,12 +72,6 @@ CHIP_ERROR FactoryDataProvider::SearchForId(uint8_t searchedType, uint8_t * pBuf if (searchedType == type) { - if ((type >= FactoryDataProvider::kNumberOfIds) || (length > maxLengths[type])) - { - ChipLogError(DeviceLayer, "Failed validity check for factory data with: id=%d, length=%d", type, length); - break; - } - ReturnErrorCodeIf(bufLength < length, CHIP_ERROR_BUFFER_TOO_SMALL); memcpy(pBuf, (void *) (addr + kValueOffset), length); @@ -367,5 +336,29 @@ CHIP_ERROR FactoryDataProvider::GetRotatingDeviceIdUniqueId(MutableByteSpan & un return err; } +CHIP_ERROR FactoryDataProvider::GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) +{ + uint8_t productFinish; + uint16_t length = 0; + auto err = SearchForId(FactoryDataId::kProductFinish, &productFinish, sizeof(productFinish), length); + ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED); + + *finish = static_cast(productFinish); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR FactoryDataProvider::GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) +{ + uint8_t color; + uint16_t length = 0; + auto err = SearchForId(FactoryDataId::kProductPrimaryColor, &color, sizeof(color), length); + ReturnErrorCodeIf(err != CHIP_NO_ERROR, CHIP_ERROR_NOT_IMPLEMENTED); + + *primaryColor = static_cast(color); + + return CHIP_NO_ERROR; +} + } // namespace DeviceLayer } // namespace chip diff --git a/src/platform/nxp/k32w/common/FactoryDataProvider.h b/src/platform/nxp/k32w/common/FactoryDataProvider.h index 99b9a1e039cf34..2bad3e7934482f 100644 --- a/src/platform/nxp/k32w/common/FactoryDataProvider.h +++ b/src/platform/nxp/k32w/common/FactoryDataProvider.h @@ -88,17 +88,11 @@ class FactoryDataProvider : public DeviceInstanceInfoProvider, kPartNumber, kProductURL, kProductLabel, + kProductFinish, + kProductPrimaryColor, kMaxId }; -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER -#if !CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS -#error "CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS must be > 0 if custom provider is enabled." -#endif - static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId + CHIP_DEVICE_CONFIG_CUSTOM_PROVIDER_NUMBER_IDS; -#else - static constexpr uint16_t kNumberOfIds = FactoryDataId::kMaxId; -#endif static uint32_t kFactoryDataStart; static uint32_t kFactoryDataSize; static uint32_t kFactoryDataPayloadStart; @@ -107,11 +101,13 @@ class FactoryDataProvider : public DeviceInstanceInfoProvider, static constexpr uint32_t kHashLen = 4; static constexpr size_t kHashId = 0xCE47BA5E; - FactoryDataProvider(); virtual ~FactoryDataProvider(); virtual CHIP_ERROR Init() = 0; virtual CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) = 0; + CHIP_ERROR Validate(); + + CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * offset = nullptr); // ===== Members functions that implement the CommissionableDataProvider CHIP_ERROR GetSetupDiscriminator(uint16_t & setupDiscriminator) override; @@ -142,12 +138,10 @@ class FactoryDataProvider : public DeviceInstanceInfoProvider, CHIP_ERROR GetManufacturingDate(uint16_t & year, uint8_t & month, uint8_t & day) override; CHIP_ERROR GetHardwareVersion(uint16_t & hardwareVersion) override; CHIP_ERROR GetRotatingDeviceIdUniqueId(MutableByteSpan & uniqueIdSpan) override; + CHIP_ERROR GetProductFinish(app::Clusters::BasicInformation::ProductFinishEnum * finish) override; + CHIP_ERROR GetProductPrimaryColor(app::Clusters::BasicInformation::ColorEnum * primaryColor) override; protected: - CHIP_ERROR Validate(); - CHIP_ERROR SearchForId(uint8_t searchedType, uint8_t * pBuf, size_t bufLength, uint16_t & length, uint32_t * offset = nullptr); - - uint16_t maxLengths[kNumberOfIds]; Header mHeader; }; diff --git a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp index c80bf64eaa357b..946c0c37f83d87 100644 --- a/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp +++ b/src/platform/nxp/k32w/common/OTAImageProcessorImpl.cpp @@ -148,6 +148,16 @@ CHIP_ERROR OTAImageProcessorImpl::ProcessPayload(ByteSpan & block) mAccumulator.Init(sizeof(OTATlvHeader)); mCurrentProcessor = nullptr; + + // If the block size is 0, it means that the processed data was a multiple of + // received BDX block size (e.g. 8 blocks of 1024 bytes were transferred). + // After state for selecting next processor is reset, a request for fetching next + // data must be sent. + if (block.size() == 0) + { + status = CHIP_NO_ERROR; + break; + } } else { @@ -380,7 +390,11 @@ void OTAImageProcessorImpl::HandleApply(intptr_t context) // queued actions, e.g. sending events to a subscription SystemLayer().StartTimer( chip::System::Clock::Milliseconds32(CHIP_DEVICE_LAYER_OTA_REBOOT_DELAY), - [](chip::System::Layer *, void *) { OtaHookReset(); }, nullptr); + [](chip::System::Layer *, void *) { + PlatformMgr().HandleServerShuttingDown(); + OtaHookReset(); + }, + nullptr); } CHIP_ERROR OTAImageProcessorImpl::ReleaseBlock() diff --git a/src/platform/nxp/k32w/common/OTATlvProcessor.cpp b/src/platform/nxp/k32w/common/OTATlvProcessor.cpp index 7571e693728c00..d9d2ccba6f28e3 100644 --- a/src/platform/nxp/k32w/common/OTATlvProcessor.cpp +++ b/src/platform/nxp/k32w/common/OTATlvProcessor.cpp @@ -45,7 +45,7 @@ CHIP_ERROR OTATlvProcessor::Process(ByteSpan & block) if (mProcessedLength == mLength) { status = ExitAction(); - if (!IsError(status) && (block.size() > 0)) + if (!IsError(status)) { // If current block was processed fully and the block still contains data, it // means that the block contains another TLV's data and the current processor @@ -106,7 +106,7 @@ CHIP_ERROR OTADataAccumulator::Accumulate(ByteSpan & block) CHIP_ERROR OTATlvProcessor::vOtaProcessInternalEncryption(MutableByteSpan & block) { uint8_t iv[16]; - uint8_t key[16]; + uint8_t key[kOTAEncryptionKeyLength]; uint8_t dataOut[16] = { 0 }; uint32_t u32IVCount; uint32_t Offset = 0; @@ -124,18 +124,13 @@ CHIP_ERROR OTATlvProcessor::vOtaProcessInternalEncryption(MutableByteSpan & bloc iv[14] = (uint8_t) ((u32IVCount >> 8) & 0xff); iv[15] = (uint8_t) (u32IVCount & 0xff); - size_t len = strlen(OTA_ENCRYPTION_KEY); - - if (len != 32) + if (Encoding::HexToBytes(OTA_ENCRYPTION_KEY, strlen(OTA_ENCRYPTION_KEY), key, kOTAEncryptionKeyLength) != + kOTAEncryptionKeyLength) { - return CHIP_ERROR_INVALID_ARGUMENT; + // Failed to convert the OTAEncryptionKey string to octstr type value + return CHIP_ERROR_INVALID_STRING_LENGTH; } - for (size_t i = 0; i < len; i += 2) - { - char hex[3] = { OTA_ENCRYPTION_KEY[i], OTA_ENCRYPTION_KEY[i + 1], '\0' }; - key[i / 2] = (uint8_t) strtol(hex, NULL, 16); - } ByteSpan KEY = ByteSpan(key); Encoding::LittleEndian::Reader reader_key(KEY.data(), KEY.size()); ReturnErrorOnFailure(reader_key.Read32(&sKey.u32register0) diff --git a/src/platform/nxp/k32w/common/OTATlvProcessor.h b/src/platform/nxp/k32w/common/OTATlvProcessor.h index e412e1cdd1c5fa..13a2df115d90d9 100644 --- a/src/platform/nxp/k32w/common/OTATlvProcessor.h +++ b/src/platform/nxp/k32w/common/OTATlvProcessor.h @@ -127,6 +127,8 @@ class OTATlvProcessor #if OTA_ENCRYPTION_ENABLE /*ota decryption*/ uint32_t mIVOffset = 0; + /* Expected byte size of the OTAEncryptionKeyLength */ + static constexpr size_t kOTAEncryptionKeyLength = 16; #endif uint32_t mLength = 0; uint32_t mProcessedLength = 0; diff --git a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h index 2f582b28171996..830024033fc0e7 100644 --- a/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h +++ b/src/platform/nxp/k32w/k32w0/CHIPPlatformConfig.h @@ -79,13 +79,13 @@ #if NXP_ICD_ENABLED -#ifndef CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC -#define CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC NXP_IDLE_MODE_INTERVAL -#endif // CHIP_CONFIG_ICD_IDLE_MODE_INTERVAL_SEC +#ifndef CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC +#define CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC NXP_IDLE_MODE_INTERVAL +#endif // CHIP_CONFIG_ICD_IDLE_MODE_DURATION_SEC -#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS -#define CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS NXP_ACTIVE_MODE_INTERVAL -#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_INTERVAL_MS +#ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS +#define CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS NXP_ACTIVE_MODE_INTERVAL +#endif // CHIP_CONFIG_ICD_ACTIVE_MODE_DURATION_MS #ifndef CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS #define CHIP_CONFIG_ICD_ACTIVE_MODE_THRESHOLD_MS NXP_ACTIVE_MODE_THRESHOLD diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp index df51c774712281..c595bf9cf31033 100644 --- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp +++ b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.cpp @@ -39,22 +39,6 @@ FactoryDataProviderImpl::FactoryDataProviderImpl() CHIP_ERROR FactoryDataProviderImpl::Init() { CHIP_ERROR error = CHIP_NO_ERROR; - uint32_t sum = 0; - -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - ReturnErrorOnFailure(SetCustomIds()); -#endif - - for (uint8_t i = 1; i < FactoryDataProvider::kNumberOfIds; i++) - { - sum += maxLengths[i]; - } - - if (sum > kFactoryDataSize) - { - ChipLogError(DeviceLayer, "Max size of factory data: %lu is bigger than reserved factory data size: %lu", sum, - kFactoryDataSize); - } #if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR error = ValidateWithRestore(); diff --git a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h index f8d51573f6c488..b359a6d3f196cd 100644 --- a/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h +++ b/src/platform/nxp/k32w/k32w0/FactoryDataProviderImpl.h @@ -24,7 +24,6 @@ namespace DeviceLayer { /** * This class provides K32W0 specific factory data features. - * CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - application defined factory data provider * CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR - enables factory data OTA */ @@ -36,13 +35,6 @@ class FactoryDataProviderImpl : public FactoryDataProvider CHIP_ERROR Init() override; CHIP_ERROR SignWithDacKey(const ByteSpan & messageToSign, MutableByteSpan & outSignBuffer) override; -#if CHIP_DEVICE_CONFIG_USE_CUSTOM_PROVIDER - virtual ~FactoryDataProviderImpl() {} - // Custom factory data providers must implement this method in order to define - // their own custom IDs. - virtual CHIP_ERROR SetCustomIds() = 0; -#endif - #if CONFIG_CHIP_K32W0_OTA_FACTORY_DATA_PROCESSOR using RestoreMechanism = CHIP_ERROR (*)(void); diff --git a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp index 5d98fc1f0c6b67..b01854c964296d 100644 --- a/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp +++ b/src/platform/nxp/k32w/k32w0/LowPowerHooks.cpp @@ -34,9 +34,6 @@ #include "app_dual_mode_low_power.h" #include "app_dual_mode_switch.h" #include "k32w0-chip-mbedtls-config.h" -#include // nogncheck - -#include "app_config.h" using namespace ::chip; using namespace ::chip::Inet; @@ -107,22 +104,6 @@ uint32_t dm_switch_get15_4InitWakeUpTime(void) return dualModeStates.threadWarmBootInitTime; } -extern "C" bleResult_t App_PostCallbackMessage(appCallbackHandler_t handler, appCallbackParam_t param) -{ - AppEvent event; - event.Type = AppEvent::kEventType_Lp; - event.Handler = handler; - event.param = param; - -#if ENABLE_LOW_POWER_LOGS - K32W_LOG("App_PostCallbackMessage %d", (uint32_t) param); -#endif - - GetAppTask().PostEvent(&event); - - return gBleSuccess_c; -} - WEAK void dm_switch_wakeupCallBack(void) { BOARD_SetClockForWakeup(); diff --git a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp b/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp index 438623dbc97d2f..d40d2ae3c17f5a 100644 --- a/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp +++ b/src/platform/nxp/k32w/k32w0/OTAFactoryDataProcessor.cpp @@ -73,7 +73,8 @@ CHIP_ERROR OTAFactoryDataProcessor::ProcessInternal(ByteSpan & block) CHIP_ERROR OTAFactoryDataProcessor::ApplyAction() { - CHIP_ERROR error = CHIP_NO_ERROR; + CHIP_ERROR error = CHIP_NO_ERROR; + FactoryProvider * provider = nullptr; ReturnErrorOnFailure(Read()); ReturnErrorOnFailure(Backup()); @@ -83,7 +84,16 @@ CHIP_ERROR OTAFactoryDataProcessor::ApplyAction() SuccessOrExit(error = Update((uint8_t) Tags::kPaiCertificateId, mPayload.mCertPai)); SuccessOrExit(error = Update((uint8_t) Tags::kCertDeclarationId, mPayload.mCertDeclaration)); - error = FactoryProviderImpl::UpdateData(mFactoryData); + SuccessOrExit(error = FactoryProviderImpl::UpdateData(mFactoryData)); + + /* Check integrity of freshly copied data. If validation fails, OTA will be aborted + * and factory data will be restored to the previous version. Use device instance info + * provider getter to access the factory data provider instance. The instance is created + * by the application, so it's easier to access it this way.*/ + provider = static_cast(DeviceLayer::GetDeviceInstanceInfoProvider()); + SuccessOrExit(error = ((provider != nullptr) ? CHIP_NO_ERROR : CHIP_ERROR_INVALID_ADDRESS)); + + error = provider->Validate(); exit: if (error != CHIP_NO_ERROR) diff --git a/src/platform/nxp/k32w/k32w1/BUILD.gn b/src/platform/nxp/k32w/k32w1/BUILD.gn index 187a7360cd27d2..8ad11928178bb7 100644 --- a/src/platform/nxp/k32w/k32w1/BUILD.gn +++ b/src/platform/nxp/k32w/k32w1/BUILD.gn @@ -58,6 +58,8 @@ static_library("k32w1") { "ram_storage.h", ] + public = [ "${chip_root}/src/platform/nxp/k32w/k32w1/BLEManagerImpl.h" ] + public_deps = [ "${chip_root}/src/platform:platform_base" ] if (chip_with_low_power != 0) { @@ -65,6 +67,8 @@ static_library("k32w1") { } if (chip_enable_ota_requestor) { + public += [ "../common/OTAImageProcessorImpl.h" ] + sources += [ "../common/OTAImageProcessorImpl.cpp", "../common/OTAImageProcessorImpl.h", diff --git a/src/test_driver/nrfconnect/main/include/app_mbedtls_config.h b/src/test_driver/nrfconnect/main/include/app_mbedtls_config.h index c676d725837aea..b28420c41828e8 100644 --- a/src/test_driver/nrfconnect/main/include/app_mbedtls_config.h +++ b/src/test_driver/nrfconnect/main/include/app_mbedtls_config.h @@ -17,24 +17,7 @@ */ // Enable cryptographic functions needed by CHIP which can't be enabled via Kconfig -#define MBEDTLS_ECP_C -#define MBEDTLS_ECDH_C #define MBEDTLS_HKDF_C -#define MBEDTLS_BIGNUM_C -#define MBEDTLS_PKCS5_C -#define MBEDTLS_PK_WRITE_C #define MBEDTLS_X509_CREATE_C #define MBEDTLS_X509_CSR_PARSE_C #define MBEDTLS_X509_CSR_WRITE_C -#define MBEDTLS_BASE64_C -#define MBEDTLS_PEM_WRITE_C - -// Define mbedtls_error() -#define MBEDTLS_ERROR_C - -// Use /dev/urandom as entropy generator -#undef MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES -#undef MBEDTLS_NO_PLATFORM_ENTROPY - -// Configure heap usage monitoring -#define MBEDTLS_MEMORY_DEBUG diff --git a/src/test_driver/nrfconnect/prj.conf b/src/test_driver/nrfconnect/prj.conf index 4a49d837a1d56a..8c9c4433d56086 100644 --- a/src/test_driver/nrfconnect/prj.conf +++ b/src/test_driver/nrfconnect/prj.conf @@ -17,60 +17,46 @@ # Application stack size CONFIG_MAIN_STACK_SIZE=8704 -# Turn on the logger +# Logging configuration CONFIG_LOG=y CONFIG_LOG_MODE_IMMEDIATE=y -# Set up IPv4/6 networking over BSD socket API -CONFIG_NETWORKING=y -CONFIG_NET_IPV6=y -CONFIG_NET_UDP=y -CONFIG_NET_SOCKETS=y +# Zephyr networking configuration CONFIG_NET_SOCKETS_POSIX_NAMES=n - CONFIG_NET_IPV4=y -CONFIG_NET_CONFIG_NEED_IPV6=y -CONFIG_NET_CONFIG_NEED_IPV4=y - CONFIG_ETH_NATIVE_POSIX=y - -# disable certain parts of Zephyr IPv6 stack -CONFIG_NET_IPV6_NBR_CACHE=n -CONFIG_NET_IPV6_MLD=n - -# Configure settings -CONFIG_FLASH_SIMULATOR=y - -# Network buffers CONFIG_NET_PKT_RX_COUNT=16 CONFIG_NET_PKT_TX_COUNT=16 CONFIG_NET_BUF_RX_COUNT=80 CONFIG_NET_BUF_TX_COUNT=80 CONFIG_NET_CONTEXT_NET_PKT_POOL=y - -# Thread by default registers quite a lot addresses. CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=6 CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=8 -CONFIG_NET_MAX_CONTEXTS=10 -# mbedTLS tweaks +# Configure settings +CONFIG_FLASH_SIMULATOR=y + +# mbedTLS configuration CONFIG_MBEDTLS=y CONFIG_MBEDTLS_ENABLE_HEAP=y -CONFIG_MBEDTLS_BUILTIN=y -CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=768 CONFIG_MBEDTLS_HEAP_SIZE=65536 +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=768 +CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y +CONFIG_MBEDTLS_USER_CONFIG_FILE="app_mbedtls_config.h" +CONFIG_MBEDTLS_ZEPHYR_ENTROPY=y CONFIG_MBEDTLS_ENTROPY_ENABLED=y CONFIG_MBEDTLS_CTR_DRBG_ENABLED=y -CONFIG_MBEDTLS_CIPHER_MODE_CTR_ENABLED=y +CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y -CONFIG_MBEDTLS_CFG_FILE="config-tls-generic.h" -CONFIG_MBEDTLS_USER_CONFIG_ENABLE=y -CONFIG_MBEDTLS_USER_CONFIG_FILE="app_mbedtls_config.h" CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=y CONFIG_MBEDTLS_ECDH_C=y CONFIG_MBEDTLS_ECDSA_C=y CONFIG_MBEDTLS_ECP_C=y -CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y +CONFIG_MBEDTLS_PK_WRITE_C=y +CONFIG_MBEDTLS_PKCS5_C=y +CONFIG_MBEDTLS_PSA_CRYPTO_C=y +CONFIG_MBEDTLS_MEMORY_DEBUG=y +CONFIG_MBEDTLS_DEBUG=y # Enable entropy CONFIG_ENTROPY_GENERATOR=y @@ -83,16 +69,14 @@ CONFIG_THREAD_NAME=y CONFIG_INIT_STACKS=y CONFIG_REBOOT=n -# Build as C++14 +# Build as C++17 CONFIG_STD_CPP17=y # CHIP configuration CONFIG_CHIP=y +CONFIG_CHIP_CRYPTO_PSA=y CONFIG_CHIP_BUILD_TESTS=y -CONFIG_CHIP_ENABLE_DNSSD_SRP=n +CONFIG_CHIP_ENABLE_READ_CLIENT=y CONFIG_CHIP_DEVICE_VENDOR_ID=65521 CONFIG_CHIP_DEVICE_PRODUCT_ID=32768 CONFIG_CHIP_PROJECT_CONFIG="main/include/CHIPProjectConfig.h" - -# Enable the Read Client -CONFIG_CHIP_ENABLE_READ_CLIENT=y diff --git a/third_party/libwebsockets/repo b/third_party/libwebsockets/repo index f18fc2316f9743..49bfef2ecd51b8 160000 --- a/third_party/libwebsockets/repo +++ b/third_party/libwebsockets/repo @@ -1 +1 @@ -Subproject commit f18fc2316f9743624ced9ba934595f7b9ba8cd05 +Subproject commit 49bfef2ecd51b854b63e35d913849b6bb518a7f6 diff --git a/third_party/mbedtls/repo b/third_party/mbedtls/repo index ffb18d2012909c..56fd26cee97531 160000 --- a/third_party/mbedtls/repo +++ b/third_party/mbedtls/repo @@ -1 +1 @@ -Subproject commit ffb18d2012909c05277a1e16dc6ba23dc8ba2854 +Subproject commit 56fd26cee97531f223071b91ed108dc1e22e7a85 diff --git a/third_party/nanopb/repo b/third_party/nanopb/repo index cf26d28b88010d..423c03b626a861 160000 --- a/third_party/nanopb/repo +++ b/third_party/nanopb/repo @@ -1 +1 @@ -Subproject commit cf26d28b88010dd3ac94e0cba64d4a71522154bc +Subproject commit 423c03b626a861a7b3a08a2d411e23aefd58827b diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp index bb8bea1d96e7f9..ee8e52fb08d776 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.cpp @@ -9792,59 +9792,6 @@ EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullabl } // namespace AutoCloseTime -namespace RemainingDuration { - -EmberAfStatus Get(chip::EndpointId endpoint, DataModel::Nullable & value) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType temp; - uint8_t * readable = Traits::ToAttributeStoreRepresentation(temp); - EmberAfStatus status = emberAfReadAttribute(endpoint, Clusters::ValveConfigurationAndControl::Id, Id, readable, sizeof(temp)); - VerifyOrReturnError(EMBER_ZCL_STATUS_SUCCESS == status, status); - if (Traits::IsNullValue(temp)) - { - value.SetNull(); - } - else - { - value.SetNonNull() = Traits::StorageToWorking(temp); - } - return status; -} -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value) -{ - using Traits = NumericAttributeTraits; - if (!Traits::CanRepresentValue(/* isNullable = */ true, value)) - { - return EMBER_ZCL_STATUS_CONSTRAINT_ERROR; - } - Traits::StorageType storageValue; - Traits::WorkingToStorage(value, storageValue); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(storageValue); - return emberAfWriteAttribute(endpoint, Clusters::ValveConfigurationAndControl::Id, Id, writable, ZCL_ELAPSED_S_ATTRIBUTE_TYPE); -} - -EmberAfStatus SetNull(chip::EndpointId endpoint) -{ - using Traits = NumericAttributeTraits; - Traits::StorageType value; - Traits::SetNull(value); - uint8_t * writable = Traits::ToAttributeStoreRepresentation(value); - return emberAfWriteAttribute(endpoint, Clusters::ValveConfigurationAndControl::Id, Id, writable, ZCL_ELAPSED_S_ATTRIBUTE_TYPE); -} - -EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value) -{ - if (value.IsNull()) - { - return SetNull(endpoint); - } - - return Set(endpoint, value.Value()); -} - -} // namespace RemainingDuration - namespace CurrentState { EmberAfStatus Get(chip::EndpointId endpoint, diff --git a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h index 8eac5af1be7ff0..e9969a14e8ed00 100644 --- a/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h +++ b/zzz_generated/app-common/app-common/zap-generated/attributes/Accessors.h @@ -1910,13 +1910,6 @@ EmberAfStatus SetNull(chip::EndpointId endpoint); EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value); } // namespace AutoCloseTime -namespace RemainingDuration { -EmberAfStatus Get(chip::EndpointId endpoint, DataModel::Nullable & value); // elapsed_s -EmberAfStatus Set(chip::EndpointId endpoint, uint32_t value); -EmberAfStatus SetNull(chip::EndpointId endpoint); -EmberAfStatus Set(chip::EndpointId endpoint, const chip::app::DataModel::Nullable & value); -} // namespace RemainingDuration - namespace CurrentState { EmberAfStatus Get(chip::EndpointId endpoint, DataModel::Nullable & value); // ValveStateEnum diff --git a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h index 4ba0ce8966b107..a69442a3e058a9 100644 --- a/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h +++ b/zzz_generated/darwin-framework-tool/zap-generated/test/Commands.h @@ -112151,7 +112151,7 @@ class Test_TC_DGWIFI_2_1 : public TestCommandBridge { VerifyOrReturn(CheckConstraintType("wiFiVersion", "enum8", "enum8")); VerifyOrReturn(CheckConstraintMinValue("wiFiVersion", [value unsignedCharValue], 0U)); - VerifyOrReturn(CheckConstraintMaxValue("wiFiVersion", [value unsignedCharValue], 5U)); + VerifyOrReturn(CheckConstraintMaxValue("wiFiVersion", [value unsignedCharValue], 6U)); } NextTest();