diff --git a/.github/workflows/examples-infineon.yaml b/.github/workflows/examples-infineon.yaml index b3f3e946e53b49..262f2fcc7cd42f 100644 --- a/.github/workflows/examples-infineon.yaml +++ b/.github/workflows/examples-infineon.yaml @@ -141,7 +141,8 @@ jobs: "./scripts/build/build_examples.py \ --target cyw30739-cyw930739m2evb_01-light \ --target cyw30739-cyw930739m2evb_01-lock \ - --target cyw30739-cyw930739m2evb_01-ota-requestor-no-progress-logging \ + --target cyw30739-cyw930739m2evb_01-ota-requestor \ + --target cyw30739-cyw930739m2evb_01-switch \ build \ --copy-artifacts-to out/artifacts \ " @@ -163,8 +164,15 @@ jobs: timeout-minutes: 5 run: | .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ - cyw30739 cyw930739m2evb_01 ota-requestor-no-progress-logging \ - out/artifacts/cyw30739-cyw930739m2evb_01-ota-requestor-no-progress-logging/chip-cyw30739-ota-requestor-example.elf \ + cyw30739 cyw930739m2evb_01 ota-requestor \ + out/artifacts/cyw30739-cyw930739m2evb_01-ota-requestor/chip-cyw30739-ota-requestor-example.elf \ + /tmp/bloat_reports/ + - name: Get switch size stats + timeout-minutes: 5 + run: | + .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ + cyw30739 cyw930739m2evb_01 switch \ + out/artifacts/cyw30739-cyw930739m2evb_01-switch/chip-cyw30739-light-switch-example.elf \ /tmp/bloat_reports/ - name: Uploading Size Reports uses: actions/upload-artifact@v3 diff --git a/examples/light-switch-app/infineon/cyw30739/.gn b/examples/light-switch-app/infineon/cyw30739/.gn new file mode 100644 index 00000000000000..90115e4209947e --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/.gn @@ -0,0 +1,28 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") + +# The location of the build configuration file. +buildconfig = "${build_root}/config/BUILDCONFIG.gn" + +# CHIP uses angle bracket includes. +check_system_includes = true + +default_args = { + target_cpu = "arm" + target_os = "cyw30739" + + import("//args.gni") +} diff --git a/examples/light-switch-app/infineon/cyw30739/BUILD.gn b/examples/light-switch-app/infineon/cyw30739/BUILD.gn new file mode 100644 index 00000000000000..0a594386bc9206 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/BUILD.gn @@ -0,0 +1,82 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/build.gni") +import("//build_overrides/chip.gni") +import("//build_overrides/cyw30739_sdk.gni") + +import("${cyw30739_sdk_build_root}/cyw30739_executable.gni") +import("${cyw30739_sdk_build_root}/cyw30739_sdk.gni") + +cyw30739_project_dir = + "${chip_root}/examples/light-switch-app/infineon/cyw30739" +examples_plat_dir = "${chip_root}/examples/platform/infineon/cyw30739" + +declare_args() { + setupPinCode = 20202021 + setupDiscriminator = 3840 +} + +cyw30739_sdk("sdk") { + sources = [ "${cyw30739_project_dir}/include/CHIPProjectConfig.h" ] + + include_dirs = [ + "${cyw30739_project_dir}/include", + "${examples_plat_dir}", + ] + + defines = [ + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_PIN_CODE=${setupPinCode}", + "CHIP_DEVICE_CONFIG_USE_TEST_SETUP_DISCRIMINATOR=${setupDiscriminator}", + ] +} + +cyw30739_executable("light_switch_app") { + output_name = "chip-cyw30739-light-switch-example.elf" + + sources = [ + "src/AppShellCommands.cpp", + "src/BindingHandler.cpp", + "src/ButtonHandler.cpp", + "src/LightSwitch.cpp", + "src/LightingManager.cpp", + "src/ZclCallbacks.cpp", + "src/main.cpp", + ] + + deps = [ + ":sdk", + "${chip_root}/examples/light-switch-app/light-switch-common", + "${chip_root}/examples/providers:device_info_provider", + "${chip_root}/examples/shell/shell_common:shell_common", + "${chip_root}/src/lib", + ] + + include_dirs = [ "include" ] + + if (chip_enable_ota_requestor) { + sources += [ + "${examples_plat_dir}/OTAConfig.cpp", + "${examples_plat_dir}/OTAConfig.h", + ] + } +} + +group("cyw30739") { + deps = [ ":light_switch_app" ] +} + +group("default") { + deps = [ ":cyw30739" ] +} diff --git a/examples/light-switch-app/infineon/cyw30739/README.md b/examples/light-switch-app/infineon/cyw30739/README.md new file mode 100644 index 00000000000000..fc45a42a42f9f4 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/README.md @@ -0,0 +1,216 @@ +# Matter CYW30739 Light Switch Example + +An example showing the use of Matter on the Infineon CYW30739 platform. + +--- + +## Table of Contents + +- [Matter CYW30739 Light Switch Example](#matter-cyw30739-light-switch-example) + - [Table of Contents](#table-of-contents) + - [Introduction](#introduction) + - [Building](#building) + - [Building Options](#building-options) + - [DAC / DAC Key / PAI Certificate / Certificate Declaration](#dac--dac-key--pai-certificate--certificate-declaration) + - [Flashing the Application](#flashing-the-application) + - [Enter Recovery Mode](#enter-recovery-mode) + - [Run Flash Script](#run-flash-script) + - [Running the Complete Example](#running-the-complete-example) + +## Introduction + +The CYW30739 light switch example provides a baseline demonstration of a on-off +light switch device, built using Matter and the Infineon Modustoolbox SDK. It +can be controlled by a Matter controller over Openthread network. + +The CYW30739 device can be commissioned over Bluetooth Low Energy where the +device and the Matter controller will exchange security information with the +Rendez-vous procedure. Target Thread Network information including the active +dataset and CASE credentials are then provided. + +## Building + +- Build the example application: + + ```bash + $ cd ~/connectedhomeip + $ git submodule update --init + $ ./scripts/examples/gn_build_example.sh examples/light-switch-app/infineon/cyw30739 out/light-switch-app + ``` + +- To delete generated executable, libraries and object files use: + + ```bash + $ cd ~/connectedhomeip + $ rm -rf ./out/ + ``` + +- OR use GN/Ninja directly + + ```bash + $ cd ~/connectedhomeip/examples/light-switch-app/infineon/cyw30739 + $ git submodule update --init + $ source third_party/connectedhomeip/scripts/activate.sh + $ gn gen out/debug + $ ninja -C out/debug + ``` + +- To delete generated executable, libraries and object files use: + + ```bash + $ cd ~/connectedhomeip/examples/light-switch-app/infineon/cyw30739 + $ rm -rf out/ + ``` + +## Building Options + +### DAC / DAC Key / PAI Certificate / Certificate Declaration + +Infineon CYW30739 examples use test certifications, keys, and CD by default. For +a production build, manufacturers can provision certifications, keys, and CD by +the following arguments: + +- `matter_dac`, `matter_dac_key`, `matter_pai`, `matter_cd` + + ```bash + $ ./scripts/examples/gn_build_example.sh examples/light-switch-app/infineon/cyw30739 out/light-switch-app \ + 'matter_dac="/path/to/dac.der"' \ + 'matter_dac_key="/path/to/dac_key.der"' \ + 'matter_pai="/path/to/pai.der"' \ + 'matter_cd="/path/to/cd.der"' + ``` + +## Flashing the Application + +### Enter Recovery Mode + +Put the CYW30739 in to the recovery mode before running the flash script. + +1. Press and hold the `RECOVERY` button on the board. +2. Press and hold the `RESET` button on the board. +3. Release the `RESET` button. +4. After one second, release the `RECOVERY` button. + +### Run Flash Script + +- On the command line: + + ```bash + $ cd ~/connectedhomeip/examples/light-switch-app/infineon/cyw30739 + $ python3 out/debug/chip-cyw30739-light-switch-example.flash.py + ``` + +## Running the Complete Example + +- It is assumed here that you already have an OpenThread border router + configured and running. If not see the following guide + [Openthread_border_router](https://github.com/project-chip/connectedhomeip/blob/master/docs/guides/openthread_border_router_pi.md) + for more information on how to setup a border router on a raspberryPi. + +- For this example to work, it is necessary to have a second CYW30739 device + running the lighting app example commissioned on the same OpenThread network + +- If the CYW30739 device is running the light switch example, then + + **Push USER Button** - Sends a Toggle command to bound light app. + + **LED1** - Indicates the current button state. + + **_OnOff Cluster_** - As following commands are app shell commands. + + - 'switch local on' : Lights On LED1 of light-switch device + - 'switch local off' : Lights Off LED1 of light-switch device + - 'switch local toggle' : Makes Toggle LED1 of light-switch device + + - 'switch onoff on' : Sends unicast On command to bound device + - 'switch onoff off' : Sends unicast Off command to bound device + - 'switch onoff toggle' : Sends unicast Toggle command to bound device + + - 'switch groups onoff on' : Sends On group command to bound group + - 'switch groups onoff off' : Sends On group command to bound group + - 'switch groups onoff toggle' : Sends On group command to bound group + +- Here is an example with the CHIPTool for unicast commands only: + + ```bash + chip-tool pairing ble-thread 1 hex: 20202021 3840 + + chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [], "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 2, "subjects": [], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}]}]' 0 + + chip-tool binding write binding '[{"fabricIndex": 1, "node": , "endpoint": 1, "cluster": 6}]' 1 + ``` + + Example: After pairing successfully [lighting-node-id : 1, + light-switch-node-id : 2] + + ```bash + chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": [112233], "targets": null}, {"fabricIndex": 1, + "privilege": 3, "authMode": 2, "subjects": [2], "targets": [{"cluster": 6, "endpoint": 1, "deviceType": null}]}]' 1 0 + + chip-tool binding write binding '[{"fabricIndex": 1, "node": 1, "endpoint": 1, "cluster": 6}]' 2 1 + ``` + +- Here is an example with the CHIPTool for groups commands only: + + Pairing the device + + ```bash + chip-tool pairing ble-thread 1 hex: 20202021 3840 + ``` + + You can use a series of commands after pairing successfully. Here is a + lighting device (node 1) and a light-switch device (node 2) for connection + demonstration. + + ```bash + chip-tool groupkeymanagement key-set-write '{"groupKeySetID": 417, "groupKeySecurityPolicy": 0, "epochKey0":"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "epochStartTime0": 1110000,"epochKey1":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf", "epochStartTime1":1110001,"epochKey2":"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", "epochStartTime2": 1110002 }' 1 0 + + chip-tool groupkeymanagement write group-key-map '[{"groupId": 257, "groupKeySetID": 417, "fabricIndex": 1}]' 1 0 + + chip-tool groups add-group 257 demo 1 1 + + chip-tool accesscontrol write acl '[{"fabricIndex": 1, "privilege": 5, "authMode": 2, "subjects": null, "targets": null}, {"fabricIndex": 1, "privilege": 3, "authMode": 3, "subjects": [257], "targets": null}]' 1 0 + + chip-tool groupkeymanagement key-set-write '{"groupKeySetID": 417, "groupKeySecurityPolicy": 0, "epochKey0":"a0a1a2a3a4a5a6a7a8a9aaabacadaeaf", "epochStartTime0": 1110000,"epochKey1":"b0b1b2b3b4b5b6b7b8b9babbbcbdbebf", "epochStartTime1":1110001,"epochKey2":"c0c1c2c3c4c5c6c7c8c9cacbcccdcecf", "epochStartTime2": 1110002 }' 2 0 + + chip-tool groupkeymanagement write group-key-map '[{"groupId": 257, "groupKeySetID": 417, "fabricIndex": 1}]' 2 0 + + chip-tool groups add-group 257 demo 2 1 + + chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' 2 1 + ``` + + Or you can use TestGroupDemoConfig after pairing successfully + + ```bash + chip-tool tests TestGroupDemoConfig --nodeId + + chip-tool tests TestGroupDemoConfig --nodeId + + chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' 1 + ``` + + Example: After pairing successfully [lighting-node-id : 1, + light-switch-node-id : 2] + + ```bash + chip-tool tests TestGroupDemoConfig --nodeId 2 + + chip-tool tests TestGroupDemoConfig --nodeId 1 + + chip-tool binding write binding '[{"fabricIndex": 1, "group": 257}]' 2 1 + ``` + + To run the example with unicast and groups commands, run the group + configuration commands and replace the last one with binding this command + + ```bash + chip-tool binding write binding '[{"fabricIndex": 1, "group": 257},{"fabricIndex": 1, "node": , "endpoint": 1, "cluster":6} ]' 1 + ``` + + To acquire the chip-tool node id, read the acl table right after + commissioning + + ```bash + chip-tool accesscontrol read acl 0 + ``` diff --git a/examples/light-switch-app/infineon/cyw30739/args.gni b/examples/light-switch-app/infineon/cyw30739/args.gni new file mode 100644 index 00000000000000..0f3c578940d0ce --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/args.gni @@ -0,0 +1,29 @@ +# Copyright (c) 2020 Project CHIP Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import("//build_overrides/chip.gni") +import("${chip_root}/config/standalone/args.gni") +import("${chip_root}/src/platform/Infineon/CYW30739/args.gni") + +cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") + +chip_openthread_ftd = false +enable_sleepy_device = true + +chip_enable_ota_requestor = true + +chip_error_logging = false +chip_progress_logging = false +chip_detail_logging = false +chip_automation_logging = false diff --git a/examples/light-switch-app/infineon/cyw30739/build_overrides b/examples/light-switch-app/infineon/cyw30739/build_overrides new file mode 120000 index 00000000000000..ee19c065d619a2 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/build_overrides @@ -0,0 +1 @@ +../../../build_overrides/ \ No newline at end of file diff --git a/examples/light-switch-app/infineon/cyw30739/include/App.h b/examples/light-switch-app/infineon/cyw30739/include/App.h new file mode 100644 index 00000000000000..2811595e99d143 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/App.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 2022 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 + +CHIP_ERROR StartBLEAdvertisingHandler(); +CHIP_ERROR StopBLEAdvertisingHandler(); diff --git a/examples/light-switch-app/infineon/cyw30739/include/AppShellCommands.h b/examples/light-switch-app/infineon/cyw30739/include/AppShellCommands.h new file mode 100644 index 00000000000000..a139b9fb293003 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/AppShellCommands.h @@ -0,0 +1,21 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +void RegisterAppShellCommands(); diff --git a/examples/light-switch-app/infineon/cyw30739/include/BindingHandler.h b/examples/light-switch-app/infineon/cyw30739/include/BindingHandler.h new file mode 100644 index 00000000000000..ef330c7da2c1ea --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/BindingHandler.h @@ -0,0 +1,64 @@ +/* + * + * Copyright (c) 2022 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 +#include +#include + +class BindingHandler +{ +public: + struct BindingData + { + chip::AttributeId attributeId; + chip::EndpointId EndpointId = 1; + chip::CommandId CommandId; + chip::ClusterId ClusterId; + uint8_t Value; + bool IsGroup{ false }; + bool isReadAttribute = false; + }; + + void Init(); + void PrintBindingTable(); + bool IsGroupBound(); + + static void SwitchWorkerHandler(intptr_t); + static void BindingWorkerHandler(intptr_t); + static void OnInvokeCommandFailure(BindingData & aBindingData, CHIP_ERROR aError); + + static BindingHandler & GetInstance() + { + static BindingHandler sBindingHandler; + return sBindingHandler; + } + +private: + static void OnOffProcessCommand(chip::CommandId, const EmberBindingTableEntry &, chip::OperationalDeviceProxy *, void *); + static void LevelControlProcessCommand(chip::CommandId, const EmberBindingTableEntry &, chip::OperationalDeviceProxy *, void *); + static void LightSwitchChangedHandler(const EmberBindingTableEntry &, chip::OperationalDeviceProxy *, void *); + static void LightSwitchContextReleaseHandler(void * context); + static void InitInternal(intptr_t); + + bool mCaseSessionRecovered = false; +}; diff --git a/examples/light-switch-app/infineon/cyw30739/include/ButtonHandler.h b/examples/light-switch-app/infineon/cyw30739/include/ButtonHandler.h new file mode 100644 index 00000000000000..c6a5999f96f8d7 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/ButtonHandler.h @@ -0,0 +1,28 @@ +/* + * + * Copyright (c) 2022 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 + +typedef enum +{ + ON_OFF_BUTTON, + APP_MAX_BUTTON, +} application_button_t; + +wiced_result_t app_button_init(void); diff --git a/examples/light-switch-app/infineon/cyw30739/include/CHIPProjectConfig.h b/examples/light-switch-app/infineon/cyw30739/include/CHIPProjectConfig.h new file mode 100644 index 00000000000000..522e40755f8bca --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/CHIPProjectConfig.h @@ -0,0 +1,66 @@ +/* + * + * Copyright (c) 2020 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @file + * Example project configuration file for CHIP. + * + * This is a place to put application or project-specific overrides + * to the default configuration values for general CHIP features. + * + */ + +#pragma once + +/*********************************************************************************** + * Device Identification Configuration + ***********************************************************************************/ +/* The VendorName attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_NAME "Infineon" + +/* The VendorID attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_VENDOR_ID 0xFFF2 + +/* The ProductName attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_NAME "CYW30739 Light-Switch App" + +/* The ProductID attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_PRODUCT_ID 0x8002 + +/* The HardwareVersionString attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION_STRING "30739" + +/* The HardwareVersion attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEFAULT_DEVICE_HARDWARE_VERSION 30739 + +/* The SoftwareVersionString attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION_STRING "TE7.5" + +/* The SoftwareVersion attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_DEVICE_SOFTWARE_VERSION 0x0705 + +/* The SerialNumber attribute of the Basic cluster. */ +#define CHIP_DEVICE_CONFIG_TEST_SERIAL_NUMBER "TEST_SN" + +// -------------------- Test Configuration -------------------- +#define CHIP_DEVICE_CONFIG_ENABLE_TEST_DEVICE_IDENTITY 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 + +// ------------------------- Debug use ------------------------- +#define CHIP_DEVICE_CONFIG_ENABLE_LOCAL_LEDSTATUS_DEBUG 1 diff --git a/examples/light-switch-app/infineon/cyw30739/include/LightSwitch.h b/examples/light-switch-app/infineon/cyw30739/include/LightSwitch.h new file mode 100644 index 00000000000000..244c1bcb7b6452 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/LightSwitch.h @@ -0,0 +1,58 @@ +/* + * + * Copyright (c) 2022 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 + +class LightSwitch +{ +public: + enum class Action : uint8_t + { + Toggle, // Switch state on lighting-app device + On, // Turn on light on lighting-app device + Off // Turn off light on lighting-app device + }; + + enum class Status : uint8_t + { + Toggle = 0, + On, + Off, + Unknown + }; + + void Init(chip::EndpointId aLightDimmerSwitchEndpoint); + void InitiateActionSwitch(Action); + Status GetSwitchStatus(); + void DimmerChangeBrightness(uint16_t kValue); + + chip::EndpointId GetLightSwitchEndpointId() { return mLightSwitchEndpoint; } + + static LightSwitch & GetInstance() + { + static LightSwitch sLightSwitch; + return sLightSwitch; + } + +private: + Status mStatus = Status::Unknown; + chip::EndpointId mLightSwitchEndpoint; +}; diff --git a/examples/light-switch-app/infineon/cyw30739/include/LightingManager.h b/examples/light-switch-app/infineon/cyw30739/include/LightingManager.h new file mode 100644 index 00000000000000..21a3b3871b05d1 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/include/LightingManager.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include + +class LightingManager +{ +public: + wiced_result_t Init(); + void Set(bool state, uint8_t pin); + void Blink(wiced_led_t led_pin, uint32_t on_period_ms, uint32_t off_period_ms); + bool IsLightOn(); + +private: + void DoSetLEDOnOff(bool state, uint8_t pin); + + friend LightingManager & LightMgr(void); + + bool usr_LED1_OnOffStatus; + + static LightingManager sLight; +}; + +inline LightingManager & LightMgr(void) +{ + return LightingManager::sLight; +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/AppShellCommands.cpp b/examples/light-switch-app/infineon/cyw30739/src/AppShellCommands.cpp new file mode 100644 index 00000000000000..477ce99fa44c0b --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/AppShellCommands.cpp @@ -0,0 +1,475 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace chip; +using namespace chip::app; +using namespace chip::Shell; + +using Shell::Engine; +using Shell::shell_command_t; +using Shell::streamer_get; +using Shell::streamer_printf; + +static Engine AppCmdSubCommands; +static Engine AppCmdLocalSubCommands; +static Engine AppCmdOnOffSubCommands; +static Engine AppCmdGroupsSubCommands; +static Engine AppCmdGroupsOnOffSubCommands; +static Engine AppCmdDebugSubCommands; +static Engine AppCmdIdentifySubCommands; +static Engine AppCmdIdentifyReadSubCommands; + +static CHIP_ERROR AppCmdHelpHandler(int argc, char ** argv) +{ + AppCmdSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR AppCmdCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return AppCmdHelpHandler(argc, argv); + } + + return AppCmdSubCommands.ExecCommand(argc, argv); +} + +namespace Local { + +static CHIP_ERROR OnOffHelpHandler(int argc, char ** argv) +{ + AppCmdLocalSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR AppCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return OnOffHelpHandler(argc, argv); + } + + return AppCmdLocalSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR OnCommandHandler(int argc, char ** argv) +{ + streamer_printf(streamer_get(), "Turning the light on ...\n"); + LightMgr().Set(true, PLATFORM_LED_1); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OffCommandHandler(int argc, char ** argv) +{ + streamer_printf(streamer_get(), "Turning the light off ...\n"); + LightMgr().Set(false, PLATFORM_LED_1); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR ToggleCommandHandler(int argc, char ** argv) +{ + streamer_printf(streamer_get(), "Toggling the light ...\n"); + if (LightMgr().IsLightOn()) + { + LightMgr().Set(false, PLATFORM_LED_1); + } + else + { + LightMgr().Set(true, PLATFORM_LED_1); + } + + return CHIP_NO_ERROR; +} + +} // namespace Local + +CHIP_ERROR AssignUnicastData(LightSwitch::Status mStatus) +{ + BindingHandler::BindingData * data = Platform::New(); + data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId(); + switch (mStatus) + { + case LightSwitch::Status::Toggle: + data->CommandId = Clusters::OnOff::Commands::Toggle::Id; + break; + case LightSwitch::Status::On: + data->CommandId = Clusters::OnOff::Commands::On::Id; + break; + case LightSwitch::Status::Off: + data->CommandId = Clusters::OnOff::Commands::Off::Id; + break; + default: + data->CommandId = Clusters::OnOff::Commands::Off::Id; + printf("[unicast] default -> Clusters::OnOff::Commands::Off\n"); + break; + } + data->ClusterId = Clusters::OnOff::Id; + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +namespace Unicast { + +static CHIP_ERROR OnOffHelpHandler(int argc, char ** argv) +{ + AppCmdOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR AppCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return OnOffHelpHandler(argc, argv); + } + + return AppCmdOnOffSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR OnCommandHandler(int argc, char ** argv) +{ + return AssignUnicastData(LightSwitch::Status::On); +} + +CHIP_ERROR OffCommandHandler(int argc, char ** argv) +{ + return AssignUnicastData(LightSwitch::Status::Off); +} + +CHIP_ERROR ToggleCommandHandler(int argc, char ** argv) +{ + return AssignUnicastData(LightSwitch::Status::Toggle); +} + +} // namespace Unicast + +CHIP_ERROR AssignGroupData(LightSwitch::Status mStatus) +{ + BindingHandler::BindingData * data = Platform::New(); + data->EndpointId = LightSwitch::GetInstance().GetLightSwitchEndpointId(); + switch (mStatus) + { + case LightSwitch::Status::Toggle: + data->CommandId = Clusters::OnOff::Commands::Toggle::Id; + break; + case LightSwitch::Status::On: + data->CommandId = Clusters::OnOff::Commands::On::Id; + break; + case LightSwitch::Status::Off: + data->CommandId = Clusters::OnOff::Commands::Off::Id; + break; + default: + data->CommandId = Clusters::OnOff::Commands::Off::Id; + printf("[group] default -> Clusters::OnOff::Commands::Off\n"); + break; + } + data->ClusterId = Clusters::OnOff::Id; + data->IsGroup = true; + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +namespace Group { + +static CHIP_ERROR AppSwitchHelpHandler(int argc, char ** argv) +{ + AppCmdGroupsSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR AppCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return AppSwitchHelpHandler(argc, argv); + } + + return AppCmdGroupsSubCommands.ExecCommand(argc, argv); +} + +static CHIP_ERROR OnOffHelpHandler(int argc, char ** argv) +{ + AppCmdGroupsOnOffSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR OnOffCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return OnOffHelpHandler(argc, argv); + } + + return AppCmdGroupsOnOffSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR OnCommandHandler(int argc, char ** argv) +{ + return AssignGroupData(LightSwitch::Status::On); +} + +CHIP_ERROR OffCommandHandler(int argc, char ** argv) +{ + return AssignGroupData(LightSwitch::Status::Off); +} + +CHIP_ERROR ToggleCommandHandler(int argc, char ** argv) +{ + return AssignGroupData(LightSwitch::Status::Toggle); +} + +} // namespace Group + +namespace Identify { + +CHIP_ERROR IdentifyHelpHandler(int argc, char ** argv) +{ + AppCmdIdentifySubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR AppCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return IdentifyHelpHandler(argc, argv); + } + + return AppCmdIdentifySubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR ReadHelpHandler(int argc, char ** argv) +{ + AppCmdIdentifyReadSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +CHIP_ERROR Read(int argc, char ** argv) +{ + if (argc == 0) + { + return ReadHelpHandler(argc, argv); + } + + return AppCmdIdentifyReadSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR ReadAttributeList(int argc, char ** argv) +{ + BindingHandler::BindingData * data = Platform::New(); + data->attributeId = Clusters::Identify::Attributes::AttributeList::Id; + data->ClusterId = Clusters::Identify::Id; + data->isReadAttribute = true; + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +CHIP_ERROR ReadFeatureMap(int argc, char ** argv) +{ + BindingHandler::BindingData * data = Platform::New(); + data->attributeId = Clusters::Identify::Attributes::FeatureMap::Id; + data->ClusterId = Clusters::Identify::Id; + data->isReadAttribute = true; + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + return CHIP_NO_ERROR; +} + +} // namespace Identify + +namespace Debug { + +static CHIP_ERROR DebugHelpHandler(int argc, char ** argv) +{ + AppCmdDebugSubCommands.ForEachCommand(Shell::PrintCommandHelp, nullptr); + return CHIP_NO_ERROR; +} + +static CHIP_ERROR AppCommandHandler(int argc, char ** argv) +{ + if (argc == 0) + { + return DebugHelpHandler(argc, argv); + } + + return AppCmdDebugSubCommands.ExecCommand(argc, argv); +} + +CHIP_ERROR StartBLEAdvertisingDebugCommandHandler(int argc, char * argv[]) +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + if ((argc > 0) && (strcmp(argv[0], "start") == 0)) + { + printf("Start BLE advertising ...\n"); + err = StartBLEAdvertisingHandler(); + } + else if ((argc > 0) && (strcmp(argv[0], "stop") == 0)) + { + printf("Stop BLE advertising ...\n"); + err = StopBLEAdvertisingHandler(); + } + else + { + return CHIP_ERROR_INVALID_ARGUMENT; + } + + return err; +} + +static CHIP_ERROR TableDebugCommandHandler(int argc, char ** argv) +{ + BindingHandler::GetInstance().PrintBindingTable(); + return CHIP_NO_ERROR; +} + +/* + * Usage: switch debug bind_group [fabric index] [group id] [cluster id] + */ +CHIP_ERROR GroupBindCommandHandler(int argc, char ** argv) +{ + VerifyOrReturnError(argc == 3, CHIP_ERROR_INVALID_ARGUMENT); + + EmberBindingTableEntry * entry = Platform::New(); + entry->type = EMBER_MULTICAST_BINDING; + entry->local = 1; // Hardcoded to endpoint 1 for now + entry->fabricIndex = atoi(argv[0]); + entry->groupId = atoi(argv[1]); + entry->clusterId.SetValue(atoi(argv[3])); + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::BindingWorkerHandler, reinterpret_cast(entry)); + return CHIP_NO_ERROR; +} + +/* + * Usage: switch debug bind_unicast [fabric index] [node id] [endpoint] [cluster id] + */ +CHIP_ERROR UnicastBindCommandHandler(int argc, char ** argv) +{ + VerifyOrReturnError(argc == 4, CHIP_ERROR_INVALID_ARGUMENT); + + EmberBindingTableEntry * entry = Platform::New(); + entry->type = EMBER_UNICAST_BINDING; + entry->local = 1; // Hardcoded to endpoint 1 for now + entry->fabricIndex = atoi(argv[0]); + entry->nodeId = atoi(argv[1]); + entry->remote = atoi(argv[2]); + entry->clusterId.SetValue(atoi(argv[3])); + + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::BindingWorkerHandler, reinterpret_cast(entry)); + return CHIP_NO_ERROR; +} + +/* + * Usage: switch debug brightness [brightness value] + */ +CHIP_ERROR ChangeBrightnessCommandHandler(int argc, char ** argv) +{ + LightSwitch::GetInstance().DimmerChangeBrightness(atoi(argv[0])); + return CHIP_NO_ERROR; +} + +} // namespace Debug + +void RegisterAppShellCommands() +{ + static const shell_command_t ifxAppCmdSubCommands[] = { + { &AppCmdHelpHandler, "help", "Switch commands" }, + { &Local::AppCommandHandler, "local", "Light-switch on/off local device." }, + { &Unicast::AppCommandHandler, "onoff", "Lightbulb on/off remote device by unicast." }, + { &Group::AppCommandHandler, "groups", "Lightbulb on/off remote device by group." }, + { &Debug::AppCommandHandler, "debug", "Extend the debug command." }, + { &Identify::AppCommandHandler, "identify", "identify read attribute" }, + }; + + static const shell_command_t ifxAppCmdLocalSubCommands[] = { { &Local::OnOffHelpHandler, "help", + "Usage: switch local [on|off|toggle]" }, + { &Local::OnCommandHandler, "on", "Make light on" }, + { &Local::OffCommandHandler, "off", "Make light off" }, + { &Local::ToggleCommandHandler, "toggle", "Toggle the light" } }; + + static const shell_command_t ifxAppCmdOnOffSubCommands[] = { + { &Unicast::OnOffHelpHandler, "help", "Usage: switch onoff [on|off|toggle]" }, + { &Unicast::OnCommandHandler, "on", "Sends on command to bound Lightbulb" }, + { &Unicast::OffCommandHandler, "off", "Sends off command to bound Lightbulb" }, + { &Unicast::ToggleCommandHandler, "toggle", "Sends toggle command to bound Lightbulb" }, + }; + + static const shell_command_t ifxAppCmdGroupsSubCommands[] = { + { &Group::AppSwitchHelpHandler, "help", "Switch a group of bounded Lightbulbs" }, + { &Group::OnOffCommandHandler, "onoff", "Usage: switch groups onoff [on|off|toggle]" }, + }; + + static const shell_command_t ifxAppCmdGroupsOnOffSubCommands[] = { + { &Group::OnOffHelpHandler, "help", "Usage: switch groups onoff [on|off|toggle]" }, + { &Group::OnCommandHandler, "on", "Sends on command to bound Group" }, + { &Group::OffCommandHandler, "off", "Sends off command to bound Group" }, + { &Group::ToggleCommandHandler, "toggle", "Sends toggle command to bound Group" }, + }; + + static const shell_command_t ifxAppCmdDebugSubCommands[] = { + { &Debug::DebugHelpHandler, "help", "Debug use commands " }, + { &Debug::StartBLEAdvertisingDebugCommandHandler, "bleadv", "Usage: switch debug bleadv [start|stop]" }, + { &Debug::TableDebugCommandHandler, "table", "Print a binding table. Usage: switch debug table" }, + { &Debug::GroupBindCommandHandler, "bind_group", "Usage: switch debug bind_group [fabric index] [group id] [cluster id]" }, + { &Debug::UnicastBindCommandHandler, "bind_unicast", + "Usage: switch debug bind_unicast [fabric index] [node id] [endpoint] [cluster id]" }, + { &Debug::ChangeBrightnessCommandHandler, "brightness", + "Change the brightness and range is 0-254. Usage: switch debug brightness [brightness value]" }, + }; + + static const shell_command_t ifxAppCmdIdentifySubCommands[] = { + { &Identify::Read, "read", "Usage: switch identify read " }, + }; + + static const shell_command_t ifxAppCmdIdentifyReadSubCommands[] = { + { &Identify::ReadHelpHandler, "help", "Usage: switch identify read " }, + { &Identify::ReadAttributeList, "attlist", "attribute list attribute" }, + { &Identify::ReadFeatureMap, "featureMap", "featureMap attribute" }, + }; + + static const shell_command_t AppLightSwitchCommand = { + &AppCmdCommandHandler, "switch", "Light switch commands. Usage: switch [local|onoff|groups|debug][identify]" + }; + + AppCmdSubCommands.RegisterCommands(ifxAppCmdSubCommands, ArraySize(ifxAppCmdSubCommands)); + AppCmdLocalSubCommands.RegisterCommands(ifxAppCmdLocalSubCommands, ArraySize(ifxAppCmdLocalSubCommands)); + AppCmdOnOffSubCommands.RegisterCommands(ifxAppCmdOnOffSubCommands, ArraySize(ifxAppCmdOnOffSubCommands)); + AppCmdGroupsSubCommands.RegisterCommands(ifxAppCmdGroupsSubCommands, ArraySize(ifxAppCmdGroupsSubCommands)); + AppCmdGroupsOnOffSubCommands.RegisterCommands(ifxAppCmdGroupsOnOffSubCommands, ArraySize(ifxAppCmdGroupsOnOffSubCommands)); + AppCmdDebugSubCommands.RegisterCommands(ifxAppCmdDebugSubCommands, ArraySize(ifxAppCmdDebugSubCommands)); + AppCmdIdentifySubCommands.RegisterCommands(ifxAppCmdIdentifySubCommands, ArraySize(ifxAppCmdIdentifySubCommands)); + AppCmdIdentifyReadSubCommands.RegisterCommands(ifxAppCmdIdentifyReadSubCommands, ArraySize(ifxAppCmdIdentifyReadSubCommands)); + + Engine::Root().RegisterCommands(&AppLightSwitchCommand, 1); +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp b/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp new file mode 100644 index 00000000000000..bcf66efb2dd81a --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/BindingHandler.cpp @@ -0,0 +1,347 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "controller/ReadInteraction.h" +#include +#include +#include + +using namespace chip; +using namespace chip::app; + +void BindingHandler::Init() +{ + DeviceLayer::PlatformMgr().ScheduleWork(InitInternal); +} + +void BindingHandler::OnInvokeCommandFailure(BindingData & aBindingData, CHIP_ERROR aError) +{ + CHIP_ERROR error; + + if (aError == CHIP_ERROR_TIMEOUT && !BindingHandler::GetInstance().mCaseSessionRecovered) + { + printf("Response timeout for invoked command, trying to recover CASE session.\n"); + + // Set flag to not try recover session multiple times. + BindingHandler::GetInstance().mCaseSessionRecovered = true; + // Allocate new object to make sure its life time will be appropriate. + BindingHandler::BindingData * data = Platform::New(); + *data = aBindingData; + // Establish new CASE session and retrasmit command that was not applied. + error = chip::BindingManager::GetInstance().NotifyBoundClusterChanged(aBindingData.EndpointId, aBindingData.ClusterId, + static_cast(data)); + + if (CHIP_NO_ERROR != error) + { + printf("NotifyBoundClusterChanged failed due to: %" CHIP_ERROR_FORMAT, error.Format()); + return; + } + } + else + { + printf("Binding command was not applied! Reason: %" CHIP_ERROR_FORMAT, aError.Format()); + } +} + +void ProcessIdentifyUnicastBindingRead(BindingHandler::BindingData * data, const EmberBindingTableEntry & binding, + OperationalDeviceProxy * peer_device) +{ + auto onSuccess = [](const ConcreteDataAttributePath & attributePath, const auto & dataResponse) { + ChipLogProgress(NotSpecified, "Read Identify attribute succeeds"); + }; + + auto onFailure = [](const ConcreteDataAttributePath * attributePath, CHIP_ERROR error) { + ChipLogError(NotSpecified, "Read Identify attribute failed: %" CHIP_ERROR_FORMAT, error.Format()); + }; + + VerifyOrDie(peer_device != nullptr && peer_device->ConnectionReady()); + + switch (data->attributeId) + { + case Clusters::Identify::Attributes::AttributeList::Id: + Controller::ReadAttribute( + peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); + break; + case Clusters::Identify::Attributes::FeatureMap::Id: + Controller::ReadAttribute( + peer_device->GetExchangeManager(), peer_device->GetSecureSession().Value(), binding.remote, onSuccess, onFailure); + break; + } +} + +void BindingHandler::OnOffProcessCommand(CommandId aCommandId, const EmberBindingTableEntry & aBinding, + OperationalDeviceProxy * aDevice, void * aContext) +{ + CHIP_ERROR ret = CHIP_NO_ERROR; + BindingData * data = reinterpret_cast(aContext); + + auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { + printf("Binding command applied successfully!\n"); + // If session was recovered and communication works, reset flag to the initial state. + if (BindingHandler::GetInstance().mCaseSessionRecovered) + BindingHandler::GetInstance().mCaseSessionRecovered = false; + }; + + auto onFailure = [dataRef = *data](CHIP_ERROR aError) mutable { BindingHandler::OnInvokeCommandFailure(dataRef, aError); }; + + if (aDevice) + { + // We are validating connection is ready once here instead of multiple times in each case statement below. + VerifyOrDie(aDevice->ConnectionReady()); + } + + switch (aCommandId) + { + case Clusters::OnOff::Commands::Toggle::Id: + Clusters::OnOff::Commands::Toggle::Type toggleCommand; + if (aDevice) + { + ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(), + aBinding.remote, toggleCommand, onSuccess, onFailure); + } + else + { + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, toggleCommand); + } + break; + + case Clusters::OnOff::Commands::On::Id: + Clusters::OnOff::Commands::On::Type onCommand; + if (aDevice) + { + ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(), + aBinding.remote, onCommand, onSuccess, onFailure); + } + else + { + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, onCommand); + } + break; + + case Clusters::OnOff::Commands::Off::Id: + Clusters::OnOff::Commands::Off::Type offCommand; + if (aDevice) + { + ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(), + aBinding.remote, offCommand, onSuccess, onFailure); + } + else + { + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, offCommand); + } + break; + default: + printf("Invalid binding command data - commandId is not supported\n"); + break; + } + if (CHIP_NO_ERROR != ret) + { + printf("Invoke OnOff Command Request ERROR: %s\n", ErrorStr(ret)); + } +} + +void BindingHandler::LevelControlProcessCommand(CommandId aCommandId, const EmberBindingTableEntry & aBinding, + OperationalDeviceProxy * aDevice, void * aContext) +{ + BindingData * data = reinterpret_cast(aContext); + + auto onSuccess = [](const ConcreteCommandPath & commandPath, const StatusIB & status, const auto & dataResponse) { + printf("Binding command applied successfully!\n"); + // If session was recovered and communication works, reset flag to the initial state. + if (BindingHandler::GetInstance().mCaseSessionRecovered) + BindingHandler::GetInstance().mCaseSessionRecovered = false; + }; + + auto onFailure = [dataRef = *data](CHIP_ERROR aError) mutable { BindingHandler::OnInvokeCommandFailure(dataRef, aError); }; + + CHIP_ERROR ret = CHIP_NO_ERROR; + + if (aDevice) + { + // We are validating connection is ready once here instead of multiple times in each case statement below. + VerifyOrDie(aDevice->ConnectionReady()); + } + + switch (aCommandId) + { + case Clusters::LevelControl::Commands::MoveToLevel::Id: { + Clusters::LevelControl::Commands::MoveToLevel::Type moveToLevelCommand; + moveToLevelCommand.level = data->Value; + if (aDevice) + { + ret = Controller::InvokeCommandRequest(aDevice->GetExchangeManager(), aDevice->GetSecureSession().Value(), + aBinding.remote, moveToLevelCommand, onSuccess, onFailure); + } + else + { + Messaging::ExchangeManager & exchangeMgr = Server::GetInstance().GetExchangeManager(); + ret = Controller::InvokeGroupCommandRequest(&exchangeMgr, aBinding.fabricIndex, aBinding.groupId, moveToLevelCommand); + } + } + break; + default: + printf("Invalid binding command data - commandId is not supported\n"); + break; + } + if (CHIP_NO_ERROR != ret) + { + printf("Invoke Group Command Request ERROR: %s\n", ErrorStr(ret)); + } +} + +void BindingHandler::LightSwitchChangedHandler(const EmberBindingTableEntry & binding, OperationalDeviceProxy * deviceProxy, + void * context) +{ + VerifyOrReturn(context != nullptr, printf("Invalid context for Light switch handler\n");); + BindingData * data = static_cast(context); + + if (binding.type == EMBER_MULTICAST_BINDING && data->IsGroup) + { + switch (data->ClusterId) + { + case Clusters::OnOff::Id: + OnOffProcessCommand(data->CommandId, binding, nullptr, context); + break; + case Clusters::LevelControl::Id: + LevelControlProcessCommand(data->CommandId, binding, nullptr, context); + break; + default: + ChipLogError(NotSpecified, "Invalid binding group command data"); + break; + } + } + else if (binding.type == EMBER_UNICAST_BINDING && !data->IsGroup) + { + switch (data->ClusterId) + { + case Clusters::OnOff::Id: + OnOffProcessCommand(data->CommandId, binding, deviceProxy, context); + break; + case Clusters::LevelControl::Id: + LevelControlProcessCommand(data->CommandId, binding, deviceProxy, context); + break; + case Clusters::Identify::Id: + ProcessIdentifyUnicastBindingRead(data, binding, deviceProxy); + break; + default: + ChipLogError(NotSpecified, "Invalid binding unicast command data"); + break; + } + } +} + +void BindingHandler::LightSwitchContextReleaseHandler(void * context) +{ + VerifyOrReturn(context != nullptr, printf("Invalid context for Light switch context release handler\n");); + + Platform::Delete(static_cast(context)); +} + +void BindingHandler::InitInternal(intptr_t aArg) +{ + CHIP_ERROR ret = CHIP_NO_ERROR; + auto & server = Server::GetInstance(); + + ret = BindingManager::GetInstance().Init( + { &server.GetFabricTable(), server.GetCASESessionManager(), &server.GetPersistentStorage() }); + if (CHIP_NO_ERROR != ret) + { + printf("BindingHandler::InitInternal() run fail, err_code: 0x%" CHIP_ERROR_FORMAT, ret.Format()); + printf("\n"); + } + else + { + BindingManager::GetInstance().RegisterBoundDeviceChangedHandler(LightSwitchChangedHandler); + BindingManager::GetInstance().RegisterBoundDeviceContextReleaseHandler(LightSwitchContextReleaseHandler); + BindingHandler::GetInstance().PrintBindingTable(); + } +} + +bool BindingHandler::IsGroupBound() +{ + BindingTable & bindingTable = BindingTable::GetInstance(); + + for (auto & entry : bindingTable) + { + if (EMBER_MULTICAST_BINDING == entry.type) + { + return true; + } + } + return false; +} + +void BindingHandler::PrintBindingTable() +{ + BindingTable & bindingTable = BindingTable::GetInstance(); + + printf("Binding Table size: [%d]:\n", bindingTable.Size()); + uint8_t i = 0; + for (auto & entry : bindingTable) + { + switch (entry.type) + { + case EMBER_UNICAST_BINDING: + printf("[%d] UNICAST:", i++); + printf("\t\t+ Fabric: %d\n \ + \t+ LocalEndpoint %d \n \ + \t+ ClusterId %d \n \ + \t+ RemoteEndpointId %d \n \ + \t+ NodeId %d \n", + (int) entry.fabricIndex, (int) entry.local, (int) entry.clusterId.Value(), (int) entry.remote, + (int) entry.nodeId); + break; + case EMBER_MULTICAST_BINDING: + printf("[%d] GROUP:", i++); + printf("\t\t+ Fabric: %d\n \ + \t+ LocalEndpoint %d \n \ + \t+ RemoteEndpointId %d \n \ + \t+ GroupId %d \n", + (int) entry.fabricIndex, (int) entry.local, (int) entry.remote, (int) entry.groupId); + break; + case EMBER_UNUSED_BINDING: + printf("[%d] UNUSED", i++); + break; + default: + break; + } + } +} + +void BindingHandler::SwitchWorkerHandler(intptr_t context) +{ + VerifyOrReturn(context != 0, printf("BindingHandler::Invalid switch work data\n")); + + BindingHandler::BindingData * data = reinterpret_cast(context); + printf("Notify Bounded Cluster | endpoint: %d cluster: %ld\n", data->EndpointId, data->ClusterId); + BindingManager::GetInstance().NotifyBoundClusterChanged(data->EndpointId, data->ClusterId, static_cast(data)); + + Platform::Delete(data); +} + +void BindingHandler::BindingWorkerHandler(intptr_t context) +{ + VerifyOrReturn(context != 0, ChipLogError(NotSpecified, "BindingHandler::Invalid binding work data\n")); + EmberBindingTableEntry * entry = reinterpret_cast(context); + AddBindingEntry(*entry); + + Platform::Delete(entry); +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/ButtonHandler.cpp b/examples/light-switch-app/infineon/cyw30739/src/ButtonHandler.cpp new file mode 100644 index 00000000000000..5be809bf53e88e --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/ButtonHandler.cpp @@ -0,0 +1,79 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define APP_MAX_BUTTON_DEF 1 + +void app_button_event_handler(const button_manager_button_t * button_mgr, button_manager_event_t event, + button_manager_button_state_t state); + +using namespace chip::app::Clusters; + +static wiced_button_manager_configuration_t app_button_manager_configuration = { + .short_hold_duration = 500, /* msec */ + .medium_hold_duration = 700, + .long_hold_duration = 1500, + .very_long_hold_duration = 2500, + .debounce_duration = 150, /* typically a click takes around ~150-200 ms */ + .double_click_interval = 250, + .continuous_hold_detect = WICED_TRUE, + .event_handler = app_button_event_handler, +}; + +static wiced_button_configuration_t app_button_configurations[APP_MAX_BUTTON_DEF]; +static button_manager_button_t app_buttons[APP_MAX_BUTTON_DEF]; +static button_manager_t app_button_manager; + +wiced_result_t app_button_init(void) +{ + wiced_result_t result = WICED_ERROR; + + memset(app_button_configurations, 0, (sizeof(wiced_button_configuration_t) * APP_MAX_BUTTON_DEF)); + memset(app_buttons, 0, (sizeof(button_manager_button_t) * APP_MAX_BUTTON_DEF)); + + app_button_configurations[ON_OFF_BUTTON].button = PLATFORM_BUTTON_1; + app_button_configurations[ON_OFF_BUTTON].button_event_mask = BUTTON_CLICK_EVENT | BUTTON_HOLDING_EVENT; + app_buttons[ON_OFF_BUTTON].configuration = &app_button_configurations[ON_OFF_BUTTON]; + + result = wiced_button_manager_init(&app_button_manager, &app_button_manager_configuration, app_buttons, 1); + + if (result != WICED_SUCCESS) + { + printf("button_manager_init failed (%d)\n", result); + } + return result; +} + +void app_button_event_handler(const button_manager_button_t * button_mgr, button_manager_event_t event, + button_manager_button_state_t state) +{ + if (button_mgr[0].configuration->button == PLATFORM_BUTTON_1) + { + if (event == BUTTON_CLICK_EVENT && state == BUTTON_STATE_RELEASED) + { + LightSwitch::GetInstance().InitiateActionSwitch(LightSwitch::Action::Toggle); + } + } +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/LightSwitch.cpp b/examples/light-switch-app/infineon/cyw30739/src/LightSwitch.cpp new file mode 100644 index 00000000000000..e3e178456e94f5 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/LightSwitch.cpp @@ -0,0 +1,89 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include +#include +#include + +#define CHIP_DEVICE_CONFIG_BRIGHTNESS_MAXIMUM 254 + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; + +void LightSwitch::Init(chip::EndpointId aLightDimmerSwitchEndpoint) +{ + BindingHandler::GetInstance().Init(); + mLightSwitchEndpoint = aLightDimmerSwitchEndpoint; +} + +void LightSwitch::InitiateActionSwitch(Action mAction) +{ + BindingHandler::BindingData * data = Platform::New(); + if (data) + { + data->EndpointId = mLightSwitchEndpoint; + data->ClusterId = Clusters::OnOff::Id; + switch (mAction) + { + case Action::Toggle: + data->CommandId = Clusters::OnOff::Commands::Toggle::Id; + mStatus = LightSwitch::Status::Toggle; + break; + case Action::On: + data->CommandId = Clusters::OnOff::Commands::On::Id; + mStatus = LightSwitch::Status::On; + break; + case Action::Off: + data->CommandId = Clusters::OnOff::Commands::Off::Id; + mStatus = LightSwitch::Status::Off; + break; + default: + Platform::Delete(data); + mStatus = LightSwitch::Status::Unknown; + return; + } + data->IsGroup = BindingHandler::GetInstance().IsGroupBound(); + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + } +} + +LightSwitch::Status LightSwitch::GetSwitchStatus() +{ + return mStatus; +} + +void LightSwitch::DimmerChangeBrightness(uint16_t kValue) +{ + static uint16_t sBrightness; + BindingHandler::BindingData * data = Platform::New(); + if (data) + { + data->EndpointId = mLightSwitchEndpoint; + data->CommandId = Clusters::LevelControl::Commands::MoveToLevel::Id; + data->ClusterId = Clusters::LevelControl::Id; + // add to brightness vluse to change brightness after call dimmer change. + sBrightness = kValue; + data->Value = + (uint8_t)(sBrightness > CHIP_DEVICE_CONFIG_BRIGHTNESS_MAXIMUM ? CHIP_DEVICE_CONFIG_BRIGHTNESS_MAXIMUM : sBrightness); + data->IsGroup = BindingHandler::GetInstance().IsGroupBound(); + DeviceLayer::PlatformMgr().ScheduleWork(BindingHandler::SwitchWorkerHandler, reinterpret_cast(data)); + } +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/LightingManager.cpp b/examples/light-switch-app/infineon/cyw30739/src/LightingManager.cpp new file mode 100644 index 00000000000000..497efd24900daf --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/LightingManager.cpp @@ -0,0 +1,97 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#include + +using namespace chip; + +LightingManager LightingManager::sLight; +bool usr_LED1_OnOffStatus = false; + +/* config LED 1 */ +static wiced_led_config_t chip_lighting_led_config_1 = { + .led = PLATFORM_LED_1, + .bright = 50, +}; +/* config LED 2 */ +static wiced_led_config_t chip_lighting_led_config_2 = { + .led = PLATFORM_LED_2, + .bright = 50, +}; + +wiced_result_t LightingManager::Init() +{ + wiced_result_t result; + result = wiced_led_manager_init(&chip_lighting_led_config_1); + if (result != WICED_SUCCESS) + printf("Init LED1 fail (%d)\n", result); + + result = wiced_led_manager_init(&chip_lighting_led_config_2); + if (result != WICED_SUCCESS) + printf("Init LED2 fail (%d)\n", result); + + return result; +} + +void LightingManager::Set(bool state, uint8_t pin) +{ + DoSetLEDOnOff(state, pin); +} + +void LightingManager::Blink(wiced_led_t led_pin, uint32_t on_period_ms, uint32_t off_period_ms) +{ + wiced_led_manager_blink_led(led_pin, on_period_ms, off_period_ms); +} + +bool LightingManager::IsLightOn(void) +{ + return usr_LED1_OnOffStatus; +} + +void LightingManager::DoSetLEDOnOff(bool state, uint8_t pin) +{ + if (pin == PLATFORM_LED_1) + { + usr_LED1_OnOffStatus = state; + if (state) + { + wiced_led_manager_enable_led(PLATFORM_LED_1); + } + else + { + wiced_led_manager_disable_led(PLATFORM_LED_1); + } + } + else if (pin == PLATFORM_LED_2) + { + if (state) + { + wiced_led_manager_enable_led(PLATFORM_LED_2); + } + else + { + wiced_led_manager_disable_led(PLATFORM_LED_2); + } + } + else + { + printf("Invalid pin number\n"); + } +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/ZclCallbacks.cpp b/examples/light-switch-app/infineon/cyw30739/src/ZclCallbacks.cpp new file mode 100644 index 00000000000000..84ca0d61fb8895 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/ZclCallbacks.cpp @@ -0,0 +1,67 @@ +/* + * + * Copyright (c) 2021 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include + +using namespace chip; +using namespace chip::app::Clusters; +using namespace chip::DeviceLayer; + +void emberAfBasicInformationClusterInitCallback(EndpointId endpoint) +{ + uint16_t year; + uint8_t month; + uint8_t dayOfMonth; + char cString[16] = "00000000"; + + if (GetDeviceInstanceInfoProvider()->GetManufacturingDate(year, month, dayOfMonth) == CHIP_NO_ERROR) + { + snprintf(cString, sizeof(cString), "%04u%02u%02u", year, month, dayOfMonth); + } + BasicInformation::Attributes::ManufacturingDate::Set(endpoint, CharSpan(cString)); +} + +void MatterPostAttributeChangeCallback(const app::ConcreteAttributePath & attributePath, uint8_t type, uint16_t size, + uint8_t * value) +{ + switch (attributePath.mClusterId) + { + case Identify::Id: + if (attributePath.mAttributeId == Identify::Attributes::IdentifyTime::Id) + { + uint16_t identifyTime; + if (EMBER_ZCL_STATUS_SUCCESS == Identify::Attributes::IdentifyTime::Get(attributePath.mEndpointId, &identifyTime)) + { + ChipLogProgress(Zcl, "IdentifyTime %u", identifyTime); + return; + } + } + break; + case OnOffSwitchConfiguration::Id: + printf("OnOff Switch Configuration attribute ID: " ChipLogFormatMEI " Type: %u Value: %u, length %u\n", + ChipLogValueMEI(attributePath.mAttributeId), type, *value, size); + return; + default: + printf("Unhandled cluster ID: 0x%04lx\n", attributePath.mClusterId); + return; + } + + printf("ERROR clusterId: 0x%04lx, unknown attribute ID: 0x%04lx\n", attributePath.mClusterId, attributePath.mAttributeId); +} diff --git a/examples/light-switch-app/infineon/cyw30739/src/main.cpp b/examples/light-switch-app/infineon/cyw30739/src/main.cpp new file mode 100644 index 00000000000000..c828788574a40a --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/src/main.cpp @@ -0,0 +1,323 @@ +/* + * + * Copyright (c) 2022 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include + +#include +#include +#include +#include +#include +#include +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace ::chip::Credentials; +using namespace ::chip::DeviceLayer; +using namespace ::chip::Shell; + +constexpr chip::EndpointId kLightDimmerSwitchEndpointId = 1; + +static chip::DeviceLayer::DeviceInfoProviderImpl gExampleDeviceInfoProvider; +static FactoryDataProvider sFactoryDataProvider; +static bool sIsThreadProvisioned = false; +static bool sIsThreadEnabled = false; +static bool sIsThreadBLEAdvertising = false; +static bool sHaveBLEConnections = false; + +static void InitApp(intptr_t args); +static void ChipEventHandler(const chip::DeviceLayer::ChipDeviceEvent *, intptr_t); + +// NOTE! This key is for test/certification only and should not be available in production devices! +uint8_t sTestEventTriggerEnableKey[chip::TestEventTriggerDelegate::kEnableKeyLength] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, + 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, + 0xcc, 0xdd, 0xee, 0xff }; + +/********************************************************** + * Identify Callbacks + *********************************************************/ + +void OnIdentifyTriggerEffect(Identify * identify) +{ + switch (identify->mCurrentEffectIdentifier) + { + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BLINK"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_BREATHE"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_OKAY"); + break; + case EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE: + ChipLogProgress(Zcl, "EMBER_ZCL_IDENTIFY_EFFECT_IDENTIFIER_CHANNEL_CHANGE"); + break; + default: + ChipLogProgress(Zcl, "No identifier effect"); + break; + } + return; +} + +static Identify gIdentify = { + chip::EndpointId{ 1 }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStart"); }, + [](Identify *) { ChipLogProgress(Zcl, "onIdentifyStop"); }, + EMBER_ZCL_IDENTIFY_IDENTIFY_TYPE_NONE, + OnIdentifyTriggerEffect, +}; + +APPLICATION_START() +{ + CHIP_ERROR err; + wiced_result_t result; + + printf("\nChip Light-Switch App starting\n"); + + mbedtls_platform_set_calloc_free(CHIPPlatformMemoryCalloc, CHIPPlatformMemoryFree); + + err = chip::Platform::MemoryInit(); + if (err != CHIP_NO_ERROR) + { + printf("ERROR MemoryInit %ld\n", err.AsInteger()); + } + + result = app_button_init(); + if (result != WICED_SUCCESS) + { + printf("ERROR app_button_init %d\n", result); + } + + /* Init. LED Manager. */ + LightMgr().Init(); + + printf("Initializing CHIP\n"); + err = PlatformMgr().InitChipStack(); + if (err != CHIP_NO_ERROR) + { + printf("ERROR InitChipStack %ld\n", err.AsInteger()); + } + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + printf("Initializing OpenThread stack\n"); + err = ThreadStackMgr().InitThreadStack(); + if (err != CHIP_NO_ERROR) + { + printf("ERROR InitThreadStack %ld\n", err.AsInteger()); + } +#endif + +#if CHIP_DEVICE_CONFIG_THREAD_FTD + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); +#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#if CHIP_DEVICE_CONFIG_ENABLE_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); +#else /* !CHIP_DEVICE_CONFIG_ENABLE_SED */ + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_SED */ +#endif // CHIP_DEVICE_CONFIG_THREAD_FTD + if (err != CHIP_NO_ERROR) + { + printf("ERROR SetThreadDeviceType %ld\n", err.AsInteger()); + } + + PlatformMgr().AddEventHandler(ChipEventHandler, 0); + + printf("Starting event loop task\n"); + err = PlatformMgr().StartEventLoopTask(); + if (err != CHIP_NO_ERROR) + { + printf("ERROR StartEventLoopTask %ld\n", err.AsInteger()); + } + +#if CHIP_DEVICE_CONFIG_ENABLE_THREAD + printf("Starting thread task\n"); + err = ThreadStackMgr().StartThreadTask(); + if (err != CHIP_NO_ERROR) + { + printf("ERROR StartThreadTask %ld\n", err.AsInteger()); + } +#endif + + PlatformMgr().ScheduleWork(InitApp, 0); + + const int ret = Engine::Root().Init(); + if (!chip::ChipError::IsSuccess(ret)) + { + printf("ERROR Shell Init %d\n", ret); + } + RegisterAppShellCommands(); + Engine::Root().RunMainLoop(); + + assert(!wiced_rtos_check_for_stack_overflow()); +} + +void InitApp(intptr_t args) +{ + ConfigurationMgr().LogDeviceConfig(); + + // Print QR Code URL + PrintOnboardingCodes(chip::RendezvousInformationFlag(chip::RendezvousInformationFlag::kBLE)); + /* Start CHIP datamodel server */ + static chip::OTATestEventTriggerDelegate testEventTriggerDelegate{ chip::ByteSpan(sTestEventTriggerEnableKey) }; + static chip::CommonCaseDeviceServerInitParams initParams; + (void) initParams.InitializeStaticResourcesBeforeServerInit(); + initParams.testEventTriggerDelegate = &testEventTriggerDelegate; + gExampleDeviceInfoProvider.SetStorageDelegate(initParams.persistentStorageDelegate); + chip::DeviceLayer::SetDeviceInfoProvider(&gExampleDeviceInfoProvider); + chip::Inet::EndPointStateOpenThread::OpenThreadEndpointInitParam nativeParams; + nativeParams.lockCb = [] { ThreadStackMgr().LockThreadStack(); }; + nativeParams.unlockCb = [] { ThreadStackMgr().UnlockThreadStack(); }; + nativeParams.openThreadInstancePtr = chip::DeviceLayer::ThreadStackMgrImpl().OTInstance(); + initParams.endpointNativeParams = static_cast(&nativeParams); + chip::Server::GetInstance().Init(initParams); + + SetDeviceAttestationCredentialsProvider(&sFactoryDataProvider); + + LightSwitch::GetInstance().Init(kLightDimmerSwitchEndpointId); + +#if CHIP_DEVICE_CONFIG_ENABLE_OTA_REQUESTOR + OTAConfig::Init(); +#endif +} + +void UpdateStatusLED() +{ + LightMgr().Set(false, PLATFORM_LED_2); + // Status LED indicates: + // - blinking 1 s - advertising, ready to commission + // - blinking 200 ms - commissioning in progress + // - constant lightning means commissioned with Thread network + if (sIsThreadBLEAdvertising && !sHaveBLEConnections) + { + LightMgr().Blink(PLATFORM_LED_2, 50, 950); + } + else if (sIsThreadProvisioned && sIsThreadEnabled) + { + LightMgr().Set(true, PLATFORM_LED_2); + } + else if (sHaveBLEConnections) + { + LightMgr().Blink(PLATFORM_LED_2, 50, 150); + } + else + { + /* back to default status */ + LightMgr().Set(false, PLATFORM_LED_2); + } +} + +void ChipEventHandler(const ChipDeviceEvent * aEvent, intptr_t arg) +{ +#if CHIP_DEVICE_CONFIG_ENABLE_LOCAL_LEDSTATUS_DEBUG + switch (aEvent->Type) + { + case DeviceEventType::kCHIPoBLEAdvertisingChange: + sIsThreadBLEAdvertising = true; + sHaveBLEConnections = ConnectivityMgr().NumBLEConnections() != 0; + UpdateStatusLED(); + break; + case DeviceEventType::kThreadStateChange: + sIsThreadProvisioned = ConnectivityMgr().IsThreadProvisioned(); + sIsThreadEnabled = ConnectivityMgr().IsThreadEnabled(); + UpdateStatusLED(); + break; + case DeviceEventType::kThreadConnectivityChange: + if (aEvent->ThreadConnectivityChange.Result == kConnectivity_Established) + sHaveBLEConnections = true; + break; + default: + if ((ConnectivityMgr().NumBLEConnections() == 0) && (!sIsThreadProvisioned || !sIsThreadEnabled)) + { + printf("[Event] Commissioning with a Thread network has not been done. An error occurred\n"); + sIsThreadBLEAdvertising = false; + sHaveBLEConnections = false; + UpdateStatusLED(); + } + break; + } +#endif /* CHIP_DEVICE_CONFIG_ENABLE_LOCAL_LEDSTATUS_DEBUG */ +} + +CHIP_ERROR StartBLEAdvertisingHandler() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + /// Don't allow on starting Matter service BLE advertising after Thread provisioning. + if (chip::Server::GetInstance().GetFabricTable().FabricCount() != 0) + { + printf("Matter service BLE advertising not started - device is already commissioned\n"); + return err; + } + + if (ConnectivityMgr().IsBLEAdvertisingEnabled()) + { + printf("BLE advertising is already enabled\n"); + return err; + } + else + { + printf("Start BLE advertising...\n"); + err = ConnectivityMgr().SetBLEAdvertisingEnabled(true); + if (err != CHIP_NO_ERROR) + { + printf("Enable BLE advertising failed\n"); + return err; + } + } + + printf("Enabling BLE advertising...\n"); + /* Check Commissioning Window*/ + if (chip::Server::GetInstance().GetCommissioningWindowManager().OpenBasicCommissioningWindow() != CHIP_NO_ERROR) + { + printf("OpenBasicCommissioningWindow() failed\n"); + err = CHIP_ERROR_UNEXPECTED_EVENT; + } + + return err; +} + +CHIP_ERROR StopBLEAdvertisingHandler() +{ + CHIP_ERROR err = CHIP_NO_ERROR; + + printf("Stop BLE advertising...\n"); + err = ConnectivityMgr().SetBLEAdvertisingEnabled(false); + if (err != CHIP_NO_ERROR) + { + printf("Disable BLE advertising failed\n"); + return err; + } + return err; +} diff --git a/examples/light-switch-app/infineon/cyw30739/third_party/connectedhomeip b/examples/light-switch-app/infineon/cyw30739/third_party/connectedhomeip new file mode 120000 index 00000000000000..3efed95be5dbe9 --- /dev/null +++ b/examples/light-switch-app/infineon/cyw30739/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../../../ \ No newline at end of file diff --git a/examples/lighting-app/infineon/cyw30739/args.gni b/examples/lighting-app/infineon/cyw30739/args.gni index c19de1f1304321..770d2675cd9176 100644 --- a/examples/lighting-app/infineon/cyw30739/args.gni +++ b/examples/lighting-app/infineon/cyw30739/args.gni @@ -19,6 +19,7 @@ import("${chip_root}/src/platform/Infineon/CYW30739/args.gni") cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_openthread_ftd = false +enable_sleepy_device = false chip_enable_ota_requestor = true diff --git a/examples/lighting-app/infineon/cyw30739/src/main.cpp b/examples/lighting-app/infineon/cyw30739/src/main.cpp index 74ff57aa959763..f1b28060f5d73f 100644 --- a/examples/lighting-app/infineon/cyw30739/src/main.cpp +++ b/examples/lighting-app/infineon/cyw30739/src/main.cpp @@ -1,6 +1,6 @@ /* * - * Copyright (c) 2021 Project CHIP Authors + * Copyright (c) 2022 Project CHIP Authors * Copyright (c) 2019 Google LLC. * All rights reserved. * @@ -142,8 +142,12 @@ APPLICATION_START() #if CHIP_DEVICE_CONFIG_THREAD_FTD err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); -#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#if CHIP_DEVICE_CONFIG_ENABLE_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); +#else /* !CHIP_DEVICE_CONFIG_ENABLE_SED */ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_SED */ #endif // CHIP_DEVICE_CONFIG_THREAD_FTD if (err != CHIP_NO_ERROR) { diff --git a/examples/lock-app/infineon/cyw30739/args.gni b/examples/lock-app/infineon/cyw30739/args.gni index c19de1f1304321..770d2675cd9176 100644 --- a/examples/lock-app/infineon/cyw30739/args.gni +++ b/examples/lock-app/infineon/cyw30739/args.gni @@ -19,6 +19,7 @@ import("${chip_root}/src/platform/Infineon/CYW30739/args.gni") cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_openthread_ftd = false +enable_sleepy_device = false chip_enable_ota_requestor = true diff --git a/examples/lock-app/infineon/cyw30739/src/main.cpp b/examples/lock-app/infineon/cyw30739/src/main.cpp index be32b550205bf4..551fc31e2e3052 100644 --- a/examples/lock-app/infineon/cyw30739/src/main.cpp +++ b/examples/lock-app/infineon/cyw30739/src/main.cpp @@ -141,10 +141,18 @@ APPLICATION_START() } #endif +#if CHIP_DEVICE_CONFIG_THREAD_FTD err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); +#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#if CHIP_DEVICE_CONFIG_ENABLE_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); +#else /* !CHIP_DEVICE_CONFIG_ENABLE_SED */ + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_SED */ +#endif // CHIP_DEVICE_CONFIG_THREAD_FTD if (err != CHIP_NO_ERROR) { - ChipLogError(Zcl, "ERROR SetThreadDeviceType %ld", err.AsInteger()); + printf("ERROR SetThreadDeviceType %ld\n", err.AsInteger()); } ChipLogProgress(Zcl, "Starting event loop task"); diff --git a/examples/ota-requestor-app/infineon/cyw30739/args.gni b/examples/ota-requestor-app/infineon/cyw30739/args.gni index e6ec7f5d3636a6..6f4645ad4beb71 100644 --- a/examples/ota-requestor-app/infineon/cyw30739/args.gni +++ b/examples/ota-requestor-app/infineon/cyw30739/args.gni @@ -19,5 +19,6 @@ import("${chip_root}/src/platform/Infineon/CYW30739/args.gni") cyw30739_sdk_target = get_label_info(":sdk", "label_no_toolchain") chip_openthread_ftd = false +enable_sleepy_device = false chip_enable_ota_requestor = true diff --git a/examples/ota-requestor-app/infineon/cyw30739/src/main.cpp b/examples/ota-requestor-app/infineon/cyw30739/src/main.cpp index d68f4c70eb0c7f..14ce58809f68dc 100644 --- a/examples/ota-requestor-app/infineon/cyw30739/src/main.cpp +++ b/examples/ota-requestor-app/infineon/cyw30739/src/main.cpp @@ -76,8 +76,12 @@ APPLICATION_START() #if CHIP_DEVICE_CONFIG_THREAD_FTD err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_Router); -#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#else // !CHIP_DEVICE_CONFIG_THREAD_FTD +#if CHIP_DEVICE_CONFIG_ENABLE_SED + err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_SleepyEndDevice); +#else /* !CHIP_DEVICE_CONFIG_ENABLE_SED */ err = ConnectivityMgr().SetThreadDeviceType(ConnectivityManager::kThreadDeviceType_MinimalEndDevice); +#endif /* CHIP_DEVICE_CONFIG_ENABLE_SED */ #endif // CHIP_DEVICE_CONFIG_THREAD_FTD if (err != CHIP_NO_ERROR) { diff --git a/integrations/cloudbuild/build-all.yaml b/integrations/cloudbuild/build-all.yaml index f6fefd0703e314..4c2a4259c19ca1 100644 --- a/integrations/cloudbuild/build-all.yaml +++ b/integrations/cloudbuild/build-all.yaml @@ -39,7 +39,7 @@ steps: --target cc13x2x7_26x2x7-lock-ftd --target cc13x2x7_26x2x7-lock-mtd --target cc13x2x7_26x2x7-shell - --target cyw30739-cyw930739m2evb_01-ota-requestor-no-progress-logging + --target cyw30739-cyw930739m2evb_01-ota-requestor --target efr32-brd4161a-light-rpc --target efr32-brd4161a-lock --target efr32-brd4161a-switch diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index 8c2a1cd15ef722..b078416f01b01f 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -432,12 +432,11 @@ def BuildCyw30739Target(): # apps target.AppendFixedTargets([ TargetPart('light', app=Cyw30739App.LIGHT), - TargetPart('lock', app=Cyw30739App.LOCK), - TargetPart('ota-requestor', app=Cyw30739App.OTA_REQUESTOR), + TargetPart('lock', app=Cyw30739App.LOCK), + TargetPart('ota-requestor', app=Cyw30739App.OTA_REQUESTOR), + TargetPart('switch', app=Cyw30739App.SWITCH), ]) - target.AppendModifier(name="no-progress-logging", progress_logging=False) - return target diff --git a/scripts/build/builders/cyw30739.py b/scripts/build/builders/cyw30739.py index b0347750c6593a..722a07578fa0b1 100644 --- a/scripts/build/builders/cyw30739.py +++ b/scripts/build/builders/cyw30739.py @@ -22,6 +22,7 @@ class Cyw30739App(Enum): LIGHT = auto() LOCK = auto() OTA_REQUESTOR = auto() + SWITCH = auto() def ExampleName(self): if self == Cyw30739App.LIGHT: @@ -30,6 +31,8 @@ def ExampleName(self): return "lock-app" elif self == Cyw30739App.OTA_REQUESTOR: return "ota-requestor-app" + elif self == Cyw30739App.SWITCH: + return "light-switch-app" else: raise Exception("Unknown app type: %r" % self) @@ -40,6 +43,8 @@ def AppNamePrefix(self): return "chip-cyw30739-lock-example" elif self == Cyw30739App.OTA_REQUESTOR: return "chip-cyw30739-ota-requestor-example" + elif self == Cyw30739App.SWITCH: + return "chip-cyw30739-light-switch-example" else: raise Exception("Unknown app type: %r" % self) @@ -65,21 +70,16 @@ def __init__( app: Cyw30739App = Cyw30739App.LIGHT, board: Cyw30739Board = Cyw30739Board.CYW930739M2EVB_01, release: bool = False, - progress_logging: bool = True ): super(Cyw30739Builder, self).__init__( root=app.BuildRoot(root), runner=runner) self.app = app self.board = board self.release = release - self.progress_logging = progress_logging def GnBuildArgs(self): args = [] - if not self.progress_logging: - args.append('chip_progress_logging=false') - if self.release: args.append('is_debug=false') diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index fb7005b2a3c818..5488d53d05a8f5 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -3,7 +3,7 @@ android-{arm,arm64,x86,x64,androidstudio-arm,androidstudio-arm64,androidstudio-x bouffalolab-{bl602-iot-matter-v1,bl602-iot-dvk-3s,bl602-night-light,xt-zb6-devkit,bl706-iot-dvk,bl706-night-light}-light[-shell][-115200][-rpc][-cdc] cc13x2x7_26x2x7-{all-clusters,all-clusters-minimal,lock,pump,pump-controller,shell}[-ftd][-mtd] cc32xx-lock -cyw30739-cyw930739m2evb_01-{light,lock,ota-requestor}[-no-progress-logging] +cyw30739-cyw930739m2evb_01-{light,lock,ota-requestor,switch} efr32-{brd4161a,brd4187c,brd4186c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,brd4304a}-{window-covering,switch,unit-test,light,lock,thermostat}[-rpc][-with-ota-requestor][-sed][-low-power][-shell][-no_logging][-openthread_mtd][-enable_heap_monitoring][-no_openthread_cli][-show_qr_code][-wifi][-rs911x][-wf200][-wifi_ipv4][-additional_data_advertising][-use_ot_lib][-use_ot_coap_lib][-no-version] esp32-{m5stack,c3devkit,devkitc,qemu}-{all-clusters,all-clusters-minimal,ota-provider,ota-requestor,shell,light,lock,bridge,temperature-measurement,ota-requestor,tests}[-rpc][-ipv6only] genio-lighting-app diff --git a/third_party/infineon/cyw30739_sdk/cyw30739_sdk.gni b/third_party/infineon/cyw30739_sdk/cyw30739_sdk.gni index 4e560cf89f26c4..8bb9a47e53d727 100644 --- a/third_party/infineon/cyw30739_sdk/cyw30739_sdk.gni +++ b/third_party/infineon/cyw30739_sdk/cyw30739_sdk.gni @@ -19,6 +19,9 @@ import("//build_overrides/cyw30739_sdk.gni") import("${chip_root}/src/platform/device.gni") declare_args() { + # Enable sleepy end device + enable_sleepy_device = false + # Location of the CYW30739 SDK. cyw30739_sdk_root = "${cyw30739_sdk_build_root}/repos" cyw30739_sdk_verbose = false @@ -128,6 +131,10 @@ template("cyw30739_sdk") { if (defined(invoker.defines)) { defines += invoker.defines } + if (enable_sleepy_device) { + assert(!chip_openthread_ftd, "OpenThread SED must run with FTD disabled.") + defines += [ "CHIP_DEVICE_CONFIG_ENABLE_SED=1" ] + } include_dirs += [ "${cyw30739_sdk_baselib_dir}/WICED/common", @@ -239,7 +246,10 @@ template("cyw30739_sdk_pre_build") { script_file, ] - sources = [ cyw30739_sdk_btp_file ] + sources = [ + cyw30739_sdk_btp_file, + cyw30739_sdk_patch_sym_file, + ] outputs = [ invoker.ldscript_file ]