From ad33d2867dc4ae384d6f062dc3c1224acdf700a9 Mon Sep 17 00:00:00 2001 From: Andrei Litvin Date: Fri, 17 Feb 2023 12:44:32 -0500 Subject: [PATCH] A linux contact sensor app --- examples/common/imgui_ui/windows/BUILD.gn | 15 +++ .../common/imgui_ui/windows/boolean_state.cpp | 61 ++++++++++++ .../common/imgui_ui/windows/boolean_state.h | 52 +++++++++++ examples/contact-sensor-app/linux/.gn | 25 +++++ examples/contact-sensor-app/linux/BUILD.gn | 63 +++++++++++++ examples/contact-sensor-app/linux/args.gni | 27 ++++++ .../contact-sensor-app/linux/build_overrides | 1 + .../linux/include/CHIPProjectAppConfig.h | 46 +++++++++ examples/contact-sensor-app/linux/main.cpp | 93 +++++++++++++++++++ .../linux/third_party/connectedhomeip | 1 + scripts/build/build/targets.py | 1 + scripts/build/builders/host.py | 6 ++ .../build/testdata/all_targets_linux_x64.txt | 2 +- 13 files changed, 392 insertions(+), 1 deletion(-) create mode 100644 examples/common/imgui_ui/windows/boolean_state.cpp create mode 100644 examples/common/imgui_ui/windows/boolean_state.h create mode 100644 examples/contact-sensor-app/linux/.gn create mode 100644 examples/contact-sensor-app/linux/BUILD.gn create mode 100644 examples/contact-sensor-app/linux/args.gni create mode 120000 examples/contact-sensor-app/linux/build_overrides create mode 100644 examples/contact-sensor-app/linux/include/CHIPProjectAppConfig.h create mode 100644 examples/contact-sensor-app/linux/main.cpp create mode 120000 examples/contact-sensor-app/linux/third_party/connectedhomeip diff --git a/examples/common/imgui_ui/windows/BUILD.gn b/examples/common/imgui_ui/windows/BUILD.gn index 925c29865ca23b..e1aa5e132b4970 100644 --- a/examples/common/imgui_ui/windows/BUILD.gn +++ b/examples/common/imgui_ui/windows/BUILD.gn @@ -53,3 +53,18 @@ static_library("light") { public_configs = [ "${chip_root}/src:includes" ] } + +static_library("boolean_state") { + sources = [ + "boolean_state.cpp", + "boolean_state.h", + ] + + deps = [ + ":windows", + "${chip_root}/src/app/common:cluster-objects", + "${chip_root}/third_party/imgui", + ] + + public_configs = [ "${chip_root}/src:includes" ] +} diff --git a/examples/common/imgui_ui/windows/boolean_state.cpp b/examples/common/imgui_ui/windows/boolean_state.cpp new file mode 100644 index 00000000000000..bd3f73fde2e02b --- /dev/null +++ b/examples/common/imgui_ui/windows/boolean_state.cpp @@ -0,0 +1,61 @@ +/* + * + * 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 "boolean_state.h" + +#include + +#include + +#include +#include + +namespace example { +namespace Ui { +namespace Windows { + +using namespace chip::app::Clusters; +using chip::app::DataModel::Nullable; + +void BooleanState::UpdateState() +{ + if (mTargetState.HasValue()) { + chip::app::Clusters::BooleanState::Attributes::StateValue::Set(mEndpointId, mTargetState.Value()); + mTargetState.ClearValue(); + } + + chip::app::Clusters::BooleanState::Attributes::StateValue::Get(mEndpointId, &mState); +} + +void BooleanState::Render() +{ + ImGui::Begin(mTitle.c_str()); + ImGui::Text("On Endpoint %d", mEndpointId); + + bool uiState = mState; + ImGui::Checkbox("State Value", &uiState); + + if (uiState != mState) { + // toggle value on the next 'UpdateState' call + mTargetState.SetValue(uiState); + } + + ImGui::End(); +} + +} // namespace Windows +} // namespace Ui +} // namespace example diff --git a/examples/common/imgui_ui/windows/boolean_state.h b/examples/common/imgui_ui/windows/boolean_state.h new file mode 100644 index 00000000000000..90def2fc509680 --- /dev/null +++ b/examples/common/imgui_ui/windows/boolean_state.h @@ -0,0 +1,52 @@ +/* + * + * Copyright (c) 2023 Project CHIP Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "window.h" + +#include +#include + +#include +#include +#include + +#include + +namespace example { +namespace Ui { +namespace Windows { + +class BooleanState : public Window +{ +public: + BooleanState(chip::EndpointId endpointId, const char *title) : mEndpointId(endpointId), mTitle(title) {} + + void UpdateState() override; + void Render() override; + +private: + const chip::EndpointId mEndpointId; + const std::string mTitle; + + bool mState = false; + chip::Optional mTargetState; +}; + +} // namespace Windows +} // namespace Ui +} // namespace example diff --git a/examples/contact-sensor-app/linux/.gn b/examples/contact-sensor-app/linux/.gn new file mode 100644 index 00000000000000..5d1ce757507582 --- /dev/null +++ b/examples/contact-sensor-app/linux/.gn @@ -0,0 +1,25 @@ +# 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 = { + import("//args.gni") +} diff --git a/examples/contact-sensor-app/linux/BUILD.gn b/examples/contact-sensor-app/linux/BUILD.gn new file mode 100644 index 00000000000000..a905e8d11a8774 --- /dev/null +++ b/examples/contact-sensor-app/linux/BUILD.gn @@ -0,0 +1,63 @@ +# 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}/build/chip/tools.gni") +import("${chip_root}/src/app/common_flags.gni") +import("${chip_root}/third_party/imgui/imgui.gni") + +assert(chip_build_tools) + +config("includes") { + include_dirs = [ + ".", + "include", + ] +} + +executable("contact-sensor-app") { + sources = [ + "include/CHIPProjectAppConfig.h", + "main.cpp", + ] + + deps = [ + "${chip_root}/examples/contact-sensor-app/contact-sensor-common", + "${chip_root}/examples/platform/linux:app-main", + "${chip_root}/src/lib", + ] + + if (chip_examples_enable_imgui_ui) { + deps += [ + "${chip_root}/examples/common/imgui_ui", + "${chip_root}/examples/common/imgui_ui/windows:boolean_state", + "${chip_root}/examples/common/imgui_ui/windows:qrcode", + ] + } + + include_dirs = [ "include" ] + + cflags = [ "-Wconversion" ] + + output_dir = root_out_dir +} + +group("linux") { + deps = [ ":contact-sensor-app" ] +} + +group("default") { + deps = [ ":linux" ] +} diff --git a/examples/contact-sensor-app/linux/args.gni b/examples/contact-sensor-app/linux/args.gni new file mode 100644 index 00000000000000..0d9ddb3d2d5e8d --- /dev/null +++ b/examples/contact-sensor-app/linux/args.gni @@ -0,0 +1,27 @@ +# 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. + +# CHIPProjectConfig.h + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/standalone/args.gni") + +chip_device_project_config_include = "" +chip_project_config_include = "" +chip_system_project_config_include = "" + +chip_project_config_include_dirs = + [ "${chip_root}/examples/contact-sensor-app/linux/include" ] +chip_project_config_include_dirs += [ "${chip_root}/config/standalone" ] diff --git a/examples/contact-sensor-app/linux/build_overrides b/examples/contact-sensor-app/linux/build_overrides new file mode 120000 index 00000000000000..e578e73312ebd1 --- /dev/null +++ b/examples/contact-sensor-app/linux/build_overrides @@ -0,0 +1 @@ +../../build_overrides \ No newline at end of file diff --git a/examples/contact-sensor-app/linux/include/CHIPProjectAppConfig.h b/examples/contact-sensor-app/linux/include/CHIPProjectAppConfig.h new file mode 100644 index 00000000000000..e919666bb9fda5 --- /dev/null +++ b/examples/contact-sensor-app/linux/include/CHIPProjectAppConfig.h @@ -0,0 +1,46 @@ +/* + * + * 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 + +// include the CHIPProjectConfig from config/standalone +#include + +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY 0 + +// Bulbs do not typically use this - enabled so we can use shell to discover commissioners +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONER_DISCOVERY_CLIENT 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_EXTENDED_DISCOVERY 1 + +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_TYPE 1 + +#define CHIP_DEVICE_CONFIG_DEVICE_TYPE 257 // 0x0101 = 257 = Dimmable Bulb + +#define CHIP_DEVICE_CONFIG_ENABLE_COMMISSIONABLE_DEVICE_NAME 1 + +#define CHIP_DEVICE_CONFIG_DEVICE_NAME "Test Bulb" diff --git a/examples/contact-sensor-app/linux/main.cpp b/examples/contact-sensor-app/linux/main.cpp new file mode 100644 index 00000000000000..90e8f32f215634 --- /dev/null +++ b/examples/contact-sensor-app/linux/main.cpp @@ -0,0 +1,93 @@ +/* + * + * 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. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if defined(CHIP_IMGUI_ENABLED) && CHIP_IMGUI_ENABLED +#include +#include +#include + +#endif + +using namespace chip; +using namespace chip::app; +using namespace chip::app::Clusters; + +#if CHIP_DEVICE_CONFIG_ENABLE_WPA +namespace { +DeviceLayer::NetworkCommissioning::LinuxWiFiDriver sLinuxWiFiDriver; +Clusters::NetworkCommissioning::Instance sWiFiNetworkCommissioningInstance(0, &sLinuxWiFiDriver); +} // namespace +#endif + +/** @brief OnOff Cluster Init + * + * This function is called when a specific cluster is initialized. It gives the + * application an opportunity to take care of cluster initialization procedures. + * It is called exactly once for each endpoint where cluster is present. + * + * @param endpoint Ver.: always + * + * TODO Issue #3841 + * emberAfOnOffClusterInitCallback happens before the stack initialize the cluster + * attributes to the default value. + * The logic here expects something similar to the deprecated Plugins callback + * emberAfPluginOnOffClusterServerPostInitCallback. + * + */ +void emberAfOnOffClusterInitCallback(EndpointId endpoint) +{ + // TODO: implement any additional Cluster Server init actions +} + +void ApplicationInit() +{ +#if CHIP_DEVICE_CONFIG_ENABLE_WPA + sWiFiNetworkCommissioningInstance.Init(); +#endif +} + +int main(int argc, char * argv[]) +{ + if (ChipLinuxAppInit(argc, argv) != 0) + { + return -1; + } + +#if defined(CHIP_IMGUI_ENABLED) && CHIP_IMGUI_ENABLED + example::Ui::ImguiUi ui; + + ui.AddWindow(std::make_unique()); + ui.AddWindow(std::make_unique(chip::EndpointId(1), "Contact Sensor")); + + ChipLinuxAppMainLoop(&ui); +#else + ChipLinuxAppMainLoop(); +#endif + + return 0; +} diff --git a/examples/contact-sensor-app/linux/third_party/connectedhomeip b/examples/contact-sensor-app/linux/third_party/connectedhomeip new file mode 120000 index 00000000000000..c866b86874994d --- /dev/null +++ b/examples/contact-sensor-app/linux/third_party/connectedhomeip @@ -0,0 +1 @@ +../../../.. \ No newline at end of file diff --git a/scripts/build/build/targets.py b/scripts/build/build/targets.py index db7053e9fdb301..777dc7d004b260 100755 --- a/scripts/build/build/targets.py +++ b/scripts/build/build/targets.py @@ -118,6 +118,7 @@ def BuildHostTarget(): TargetPart('tests', app=HostApp.TESTS), TargetPart('chip-cert', app=HostApp.CERT_TOOL), TargetPart('address-resolve-tool', app=HostApp.ADDRESS_RESOLVE), + TargetPart('contact-sensor', app=HostApp.CONTACT_SENSOR), ] if (HostBoard.NATIVE.PlatformName() == 'darwin'): diff --git a/scripts/build/builders/host.py b/scripts/build/builders/host.py index b3bfbaa7a326ba..ad9f07cf98da61 100644 --- a/scripts/build/builders/host.py +++ b/scripts/build/builders/host.py @@ -59,6 +59,7 @@ class HostApp(Enum): BRIDGE = auto() DYNAMIC_BRIDGE = auto() JAVA_MATTER_CONTROLLER = auto() + CONTACT_SENSOR = auto() def ExamplePath(self): if self == HostApp.ALL_CLUSTERS: @@ -101,6 +102,8 @@ def ExamplePath(self): return 'dynamic-bridge-app/linux' elif self == HostApp.JAVA_MATTER_CONTROLLER: return 'java-matter-controller' + elif self == HostApp.CONTACT_SENSOR: + return 'contact-sensor-app/linux' else: raise Exception('Unknown app type: %r' % self) @@ -174,6 +177,9 @@ def OutputNames(self): elif self == HostApp.JAVA_MATTER_CONTROLLER: yield 'java-matter-controller' yield 'java-matter-controller.map' + elif self == HostApp.CONTACT_SENSOR: + yield 'contact-sensor-app' + yield 'contact-sensor-app.map' else: raise Exception('Unknown app type: %r' % self) diff --git a/scripts/build/testdata/all_targets_linux_x64.txt b/scripts/build/testdata/all_targets_linux_x64.txt index 77c780e3431b98..3ae80d2684c318 100644 --- a/scripts/build/testdata/all_targets_linux_x64.txt +++ b/scripts/build/testdata/all_targets_linux_x64.txt @@ -8,7 +8,7 @@ efr32-{brd4161a,brd4187c,brd4163a,brd4164a,brd4166a,brd4170a,brd4186a,brd4187a,b 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 linux-fake-tests[-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-coverage][-dmalloc][-clang] -linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool}[-nodeps][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui] +linux-{x64,arm64}-{rpc-console,all-clusters,all-clusters-minimal,chip-tool,thermostat,java-matter-controller,minmdns,light,lock,shell,ota-provider,ota-requestor,python-bindings,tv-app,tv-casting-app,bridge,dynamic-bridge,tests,chip-cert,address-resolve-tool,contact-sensor}[-nodeps][-platform-mdns][-minmdns-verbose][-libnl][-same-event-loop][-no-interactive][-ipv6only][-no-ble][-no-wifi][-no-thread][-mbedtls][-boringssl][-asan][-tsan][-ubsan][-libfuzzer][-coverage][-dmalloc][-clang][-test][-rpc][-with-ui] linux-x64-efr32-test-runner[-clang] imx-{chip-tool,lighting-app,thermostat,all-clusters-app,all-clusters-minimal-app,ota-provider-app}[-release] infineon-psoc6-{lock,light,all-clusters,all-clusters-minimal}[-ota][-updateimage]