From d046d917f42b32896f622aaf48e817b2e838f069 Mon Sep 17 00:00:00 2001 From: Yufeng Wang Date: Fri, 24 May 2024 14:36:25 -0700 Subject: [PATCH] Add the RPC support between Fabric_Admin and Fabric_Bridge --- examples/common/pigweed/BUILD.gn | 14 ++ .../pigweed/protos/fabric_admin_service.proto | 20 +++ .../protos/fabric_bridge_service.proto | 15 ++ .../common/pigweed/rpc_console/py/BUILD.gn | 2 + .../rpc_console/py/chip_rpc/console.py | 4 + .../common/pigweed/rpc_services/FabricAdmin.h | 44 +++++ .../pigweed/rpc_services/FabricBridge.h | 44 +++++ examples/fabric-admin/BUILD.gn | 48 ++++- .../commands/fabric-sync/Commands.h | 33 ++++ .../fabric-sync/FabricSyncCommand.cpp | 45 +++++ .../commands/fabric-sync/FabricSyncCommand.h | 40 +++++ examples/fabric-admin/main.cpp | 32 ++++ examples/fabric-admin/rpc/RpcClient.cpp | 168 +++++++++++++++++ examples/fabric-admin/rpc/RpcClient.h | 27 +++ examples/fabric-admin/rpc/RpcServer.cpp | 70 ++++++++ examples/fabric-admin/rpc/RpcServer.h | 23 +++ examples/fabric-admin/with_pw_rpc.gni | 42 +++++ examples/fabric-bridge-app/linux/BUILD.gn | 34 ++++ examples/fabric-bridge-app/linux/Device.cpp | 6 +- .../fabric-bridge-app/linux/RpcClient.cpp | 169 ++++++++++++++++++ .../fabric-bridge-app/linux/RpcServer.cpp | 68 +++++++ .../linux/include/RpcClient.h | 27 +++ .../linux/include/RpcServer.h | 23 +++ examples/fabric-bridge-app/linux/main.cpp | 39 +++- .../fabric-bridge-app/linux/with_pw_rpc.gni | 41 +++++ 25 files changed, 1067 insertions(+), 11 deletions(-) create mode 100644 examples/common/pigweed/protos/fabric_admin_service.proto create mode 100644 examples/common/pigweed/protos/fabric_bridge_service.proto create mode 100644 examples/common/pigweed/rpc_services/FabricAdmin.h create mode 100644 examples/common/pigweed/rpc_services/FabricBridge.h create mode 100644 examples/fabric-admin/commands/fabric-sync/Commands.h create mode 100644 examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp create mode 100644 examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h create mode 100644 examples/fabric-admin/rpc/RpcClient.cpp create mode 100644 examples/fabric-admin/rpc/RpcClient.h create mode 100644 examples/fabric-admin/rpc/RpcServer.cpp create mode 100644 examples/fabric-admin/rpc/RpcServer.h create mode 100644 examples/fabric-admin/with_pw_rpc.gni create mode 100644 examples/fabric-bridge-app/linux/RpcClient.cpp create mode 100644 examples/fabric-bridge-app/linux/RpcServer.cpp create mode 100644 examples/fabric-bridge-app/linux/include/RpcClient.h create mode 100644 examples/fabric-bridge-app/linux/include/RpcServer.h create mode 100644 examples/fabric-bridge-app/linux/with_pw_rpc.gni diff --git a/examples/common/pigweed/BUILD.gn b/examples/common/pigweed/BUILD.gn index c0178e419a1d5d..e523bea380c03f 100644 --- a/examples/common/pigweed/BUILD.gn +++ b/examples/common/pigweed/BUILD.gn @@ -80,6 +80,20 @@ pw_proto_library("button_service") { prefix = "button_service" } +pw_proto_library("fabric_admin_service") { + sources = [ "protos/fabric_admin_service.proto" ] + deps = [ "$dir_pw_protobuf:common_protos" ] + strip_prefix = "protos" + prefix = "fabric_admin_service" +} + +pw_proto_library("fabric_bridge_service") { + sources = [ "protos/fabric_bridge_service.proto" ] + deps = [ "$dir_pw_protobuf:common_protos" ] + strip_prefix = "protos" + prefix = "fabric_bridge_service" +} + pw_proto_library("lighting_service") { sources = [ "protos/lighting_service.proto" ] deps = [ "$dir_pw_protobuf:common_protos" ] diff --git a/examples/common/pigweed/protos/fabric_admin_service.proto b/examples/common/pigweed/protos/fabric_admin_service.proto new file mode 100644 index 00000000000000..e52fd2951ac0d7 --- /dev/null +++ b/examples/common/pigweed/protos/fabric_admin_service.proto @@ -0,0 +1,20 @@ +syntax = "proto3"; + +import 'pw_protobuf_protos/common.proto'; + +package chip.rpc; + +// Define the message for a synchronized end device with necessary fields +message DeviceInfo { + uint64 node_id = 1; +} + +// Define the response message to convey the status of the operation +message OperationStatus { + bool success = 1; +} + +service FabricAdmin { + rpc OpenCommissioningWindow(DeviceInfo) returns (OperationStatus){} +} + diff --git a/examples/common/pigweed/protos/fabric_bridge_service.proto b/examples/common/pigweed/protos/fabric_bridge_service.proto new file mode 100644 index 00000000000000..5bd4f8efd779e7 --- /dev/null +++ b/examples/common/pigweed/protos/fabric_bridge_service.proto @@ -0,0 +1,15 @@ +syntax = "proto3"; + +import 'pw_protobuf_protos/common.proto'; + +package chip.rpc; + +// Define the message for a synchronized end device with necessary fields +message SynchronizedDevice { + uint64 node_id = 1; +} + +service FabricBridge { + rpc AddSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} +} + diff --git a/examples/common/pigweed/rpc_console/py/BUILD.gn b/examples/common/pigweed/rpc_console/py/BUILD.gn index a03dc980872739..db9f22fe45fff9 100644 --- a/examples/common/pigweed/rpc_console/py/BUILD.gn +++ b/examples/common/pigweed/rpc_console/py/BUILD.gn @@ -46,6 +46,8 @@ pw_python_package("chip_rpc") { "${chip_root}/examples/common/pigweed:descriptor_service.python", "${chip_root}/examples/common/pigweed:device_service.python", "${chip_root}/examples/common/pigweed:echo_service.python", + "${chip_root}/examples/common/pigweed:fabric_admin_service.python", + "${chip_root}/examples/common/pigweed:fabric_bridge_service.python", "${chip_root}/examples/common/pigweed:lighting_service.python", "${chip_root}/examples/common/pigweed:locking_service.python", "${chip_root}/examples/common/pigweed:ot_cli_service.python", diff --git a/examples/common/pigweed/rpc_console/py/chip_rpc/console.py b/examples/common/pigweed/rpc_console/py/chip_rpc/console.py index 1591722bfdbeab..7aea568c288b16 100644 --- a/examples/common/pigweed/rpc_console/py/chip_rpc/console.py +++ b/examples/common/pigweed/rpc_console/py/chip_rpc/console.py @@ -53,6 +53,8 @@ from descriptor_service import descriptor_service_pb2 from device_service import device_service_pb2 from echo_service import echo_pb2 +from fabric_admin_service import fabric_admin_service_pb2 +from fabric_bridge_service import fabric_bridge_service_pb2 from lighting_service import lighting_service_pb2 from locking_service import locking_service_pb2 from ot_cli_service import ot_cli_service_pb2 @@ -136,6 +138,8 @@ def show_console(device: str, baudrate: int, descriptor_service_pb2, device_service_pb2, echo_pb2, + fabric_admin_service_pb2, + fabric_bridge_service_pb2, lighting_service_pb2, locking_service_pb2, ot_cli_service_pb2, diff --git a/examples/common/pigweed/rpc_services/FabricAdmin.h b/examples/common/pigweed/rpc_services/FabricAdmin.h new file mode 100644 index 00000000000000..5254b9e9054a0c --- /dev/null +++ b/examples/common/pigweed/rpc_services/FabricAdmin.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "app/util/attribute-storage.h" +#include "fabric_admin_service/fabric_admin_service.rpc.pb.h" +#include "pigweed/rpc_services/internal/StatusUtils.h" +#include +#include +#include +#include + +namespace chip { +namespace rpc { + +class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service +{ +public: + virtual ~FabricAdmin() = default; + + virtual pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) + { + return pw::Status::Unimplemented(); + } +}; + +} // namespace rpc +} // namespace chip diff --git a/examples/common/pigweed/rpc_services/FabricBridge.h b/examples/common/pigweed/rpc_services/FabricBridge.h new file mode 100644 index 00000000000000..bce32ebd3d99b2 --- /dev/null +++ b/examples/common/pigweed/rpc_services/FabricBridge.h @@ -0,0 +1,44 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include "app/util/attribute-storage.h" +#include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h" +#include "pigweed/rpc_services/internal/StatusUtils.h" +#include +#include +#include +#include + +namespace chip { +namespace rpc { + +class FabricBridge : public pw_rpc::nanopb::FabricBridge::Service +{ +public: + virtual ~FabricBridge() = default; + + virtual pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) + { + return pw::Status::Unimplemented(); + } +}; + +} // namespace rpc +} // namespace chip diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index ddaa33483257b1..c8a95a3c3925be 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -22,6 +22,13 @@ import("${chip_root}/src/lib/core/core.gni") assert(chip_build_tools) +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + +if (chip_enable_pw_rpc) { + import("//build_overrides/pigweed.gni") + import("$dir_pw_build/target_types.gni") +} + config("config") { include_dirs = [ ".", @@ -38,7 +45,9 @@ config("config") { defines += [ "CONFIG_USE_LOCAL_STORAGE" ] } - cflags = [ "-Wconversion" ] + if (chip_enable_pw_rpc) { + defines += [ "PW_RPC_ENABLED" ] + } } static_library("fabric-admin-utils") { @@ -59,6 +68,7 @@ static_library("fabric-admin-utils") { "commands/common/HexConversion.h", "commands/common/RemoteDataModelLogger.cpp", "commands/common/RemoteDataModelLogger.h", + "commands/fabric-sync/FabricSyncCommand.cpp", "commands/pairing/OpenCommissioningWindowCommand.cpp", "commands/pairing/OpenCommissioningWindowCommand.h", "commands/pairing/PairingCommand.cpp", @@ -95,6 +105,42 @@ static_library("fabric-admin-utils") { public_configs = [ ":config" ] + if (chip_enable_pw_rpc) { + defines = [ + "PW_RPC_FABRIC_ADMIN_SERVICE=1", + "PW_RPC_FABRIC_BRIDGE_SERVICE=1", + ] + + sources += [ + "${chip_root}/examples/platform/linux/system_rpc_server.cc", + "rpc/RpcClient.cpp", + "rpc/RpcClient.h", + "rpc/RpcServer.cpp", + "rpc/RpcServer.h", + ] + + deps += [ + "$dir_pw_hdlc:default_addresses", + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_log", + "$dir_pw_rpc:server", + "$dir_pw_rpc/system_server:facade", + "$dir_pw_rpc/system_server:socket", + "$dir_pw_stream:socket_stream", + "$dir_pw_sync:mutex", + "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:fabric_admin_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:fabric_bridge_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:rpc_services", + ] + + deps += pw_build_LINK_DEPS + } else { + # The system_rpc_server.cc file is in pigweed and doesn't compile with + # -Wconversion, remove check for RPC build only. + cflags = [ "-Wconversion" ] + } + if (chip_enable_transport_trace) { public_deps += [ "${chip_root}/examples/common/tracing:trace_handlers_decoder" ] diff --git a/examples/fabric-admin/commands/fabric-sync/Commands.h b/examples/fabric-admin/commands/fabric-sync/Commands.h new file mode 100644 index 00000000000000..7c15416c560e60 --- /dev/null +++ b/examples/fabric-admin/commands/fabric-sync/Commands.h @@ -0,0 +1,33 @@ +/* + * 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 + +void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands * credsIssuerConfig) +{ + const char * clusterName = "FabricSync"; + + commands_list clusterCommands = { + make_unique(credsIssuerConfig), + }; + + commands.RegisterCommandSet(clusterName, clusterCommands, "Commands for fabric synchronization."); +} diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp new file mode 100644 index 00000000000000..c2a1b5df8fb80e --- /dev/null +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#include "FabricSyncCommand.h" +#include +#include +#include + +#if defined(PW_RPC_ENABLED) +#include "pw_assert/check.h" +#include "pw_hdlc/decoder.h" +#include "pw_hdlc/default_addresses.h" +#include "pw_hdlc/rpc_channel.h" +#include "pw_rpc/client.h" +#include "pw_stream/socket_stream.h" + +#include +#endif + +using namespace ::chip; + +CHIP_ERROR FabricSyncAddDeviceCommand::RunCommand(NodeId remoteId) +{ +#if defined(PW_RPC_ENABLED) + AddSynchronizedDevice(remoteId); + return CHIP_NO_ERROR; +#else + return CHIP_ERROR_NOT_IMPLEMENTED; +#endif +} diff --git a/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h new file mode 100644 index 00000000000000..3b57e891db7723 --- /dev/null +++ b/examples/fabric-admin/commands/fabric-sync/FabricSyncCommand.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +#pragma once + +#include + +class FabricSyncAddDeviceCommand : public CHIPCommand +{ +public: + FabricSyncAddDeviceCommand(CredentialIssuerCommands * credIssuerCommands) : CHIPCommand("add-device", credIssuerCommands) + { + AddArgument("nodeid", 0, UINT64_MAX, &mNodeId); + } + + /////////// CHIPCommand Interface ///////// + CHIP_ERROR RunCommand() override { return RunCommand(mNodeId); } + + chip::System::Clock::Timeout GetWaitDuration() const override { return chip::System::Clock::Seconds16(30); } + +private: + chip::NodeId mNodeId; + + CHIP_ERROR RunCommand(NodeId remoteId); +}; diff --git a/examples/fabric-admin/main.cpp b/examples/fabric-admin/main.cpp index a1002d83170d5b..450586cb5f86db 100644 --- a/examples/fabric-admin/main.cpp +++ b/examples/fabric-admin/main.cpp @@ -18,14 +18,43 @@ #include #include +#include #include #include #include #include #include +#include #include +#if defined(PW_RPC_ENABLED) +#include +#include +#endif + +#define RETRY_INTERVAL_S (3) + +void ApplicationInit() +{ +#if defined(PW_RPC_ENABLED) + InitRpcServer(kFabricAdminServerPort); + ChipLogProgress(NotSpecified, "PW_RPC initialized."); + + while (true) + { + if (InitRpcClient(kFabricBridgeServerPort) == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Connected to Fabric-Bridge"); + break; + } + + ChipLogError(NotSpecified, "Failed to connect to Fabric-Bridge, retry in %d seconds....", RETRY_INTERVAL_S); + std::this_thread::sleep_for(std::chrono::seconds(RETRY_INTERVAL_S)); + } +#endif +} + // ================================================================================ // Main Code // ================================================================================ @@ -45,6 +74,7 @@ int main(int argc, char * argv[]) ExampleCredentialIssuerCommands credIssuerCommands; Commands commands; + registerCommandsFabricSync(commands, &credIssuerCommands); registerCommandsInteractive(commands, &credIssuerCommands); registerCommandsPairing(commands, &credIssuerCommands); registerClusters(commands, &credIssuerCommands); @@ -56,5 +86,7 @@ int main(int argc, char * argv[]) c_args.push_back(const_cast(arg.c_str())); } + ApplicationInit(); + return commands.Run(static_cast(c_args.size()), c_args.data()); } diff --git a/examples/fabric-admin/rpc/RpcClient.cpp b/examples/fabric-admin/rpc/RpcClient.cpp new file mode 100644 index 00000000000000..0be1668f2daeac --- /dev/null +++ b/examples/fabric-admin/rpc/RpcClient.cpp @@ -0,0 +1,168 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RpcClient.h" + +#include +#include +#include + +#include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h" +#include "pw_assert/check.h" +#include "pw_hdlc/decoder.h" +#include "pw_hdlc/default_addresses.h" +#include "pw_hdlc/rpc_channel.h" +#include "pw_rpc/client.h" +#include "pw_stream/socket_stream.h" + +namespace { + +constexpr size_t kMaxTransmissionUnit = 256; +constexpr uint32_t kRpcTimeoutMs = 1000; +const char * rpcServerAddress = "127.0.0.1"; + +pw::stream::SocketStream rpcSocketStream; + +// Set up the output channel for the pw_rpc client to use. +pw::hdlc::RpcChannelOutput hdlc_channel_output(rpcSocketStream, pw::hdlc::kDefaultRpcAddress, "HDLC channel"); + +// An array of RPC channels (channels) is created, each associated with an HDLC channel output. +// This sets up the communication channels for RPC calls. +pw::rpc::Channel channels[] = { pw::rpc::Channel::Create<1>(&hdlc_channel_output) }; + +// Initialize the RPC client with the channels. +pw::rpc::Client client(channels); + +// Generated clients are namespaced with their proto library. +using FabricBridgeClient = chip::rpc::pw_rpc::nanopb::FabricBridge::Client; + +// RPC channel ID on which to make client calls. RPC calls cannot be made on +// channel 0 (Channel::kUnassignedChannelId). +constexpr uint32_t kDefaultChannelId = 1; + +// Function to process incoming packets +void ProcessPackets() +{ + std::array inputBuf; + pw::hdlc::Decoder decoder(inputBuf); + + while (true) + { + std::array data; + auto ret = rpcSocketStream.Read(data); + if (!ret.ok()) + { + if (ret.status() == pw::Status::OutOfRange()) + { + // Handle remote disconnect + rpcSocketStream.Close(); + return; + } + continue; + } + + for (std::byte byte : ret.value()) + { + auto result = decoder.Process(byte); + if (!result.ok()) + { + // Wait for more bytes that form a complete packet + continue; + } + pw::hdlc::Frame & frame = result.value(); + if (frame.address() != pw::hdlc::kDefaultRpcAddress) + { + // Wrong address; ignore the packet + continue; + } + + client.ProcessPacket(frame.data()).IgnoreError(); + } + } +} + +template +CHIP_ERROR WaitForResponse(CallType & call) +{ + if (!call.active()) + { + return CHIP_ERROR_INTERNAL; + } + + // Wait for the response or timeout + uint32_t elapsedTimeMs = 0; + const uint32_t sleepTimeMs = 100; + + while (call.active() && elapsedTimeMs < kRpcTimeoutMs) + { + usleep(sleepTimeMs * 1000); + elapsedTimeMs += sleepTimeMs; + } + + if (elapsedTimeMs >= kRpcTimeoutMs) + { + fprintf(stderr, "RPC Response timed out!"); + return CHIP_ERROR_TIMEOUT; + } + + return CHIP_NO_ERROR; +} + +void AddDeviceResponse(const pw_protobuf_Empty & response, pw::Status status) +{ + if (status.ok()) + { + printf("RPC call succeeded\n"); + } + else + { + printf("RPC call failed with status: %d\n", status.code()); + } +} + +} // namespace + +CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) +{ + if (rpcSocketStream.Connect(rpcServerAddress, rpcServerPort) != PW_STATUS_OK) + { + ChipLogError(NotSpecified, "Failed to connect the Fabric-Admin"); + return CHIP_ERROR_NOT_CONNECTED; + } + + ChipLogProgress(NotSpecified, "Connectted to the Fabric-Admin\n"); + + // Start a thread to process incoming packets + std::thread packet_processor(ProcessPackets); + packet_processor.detach(); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId) +{ + ChipLogProgress(NotSpecified, "AddSynchronizedDevice"); + + FabricBridgeClient fabric_bridge_client(client, kDefaultChannelId); + chip_rpc_SynchronizedDevice device; + device.node_id = nodeId; + + // The RPC will remain active as long as `call` is alive. + auto call = fabric_bridge_client.AddSynchronizedDevice(device, AddDeviceResponse); + return WaitForResponse(call); +} diff --git a/examples/fabric-admin/rpc/RpcClient.h b/examples/fabric-admin/rpc/RpcClient.h new file mode 100644 index 00000000000000..46c1e9497c53aa --- /dev/null +++ b/examples/fabric-admin/rpc/RpcClient.h @@ -0,0 +1,27 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +constexpr uint16_t kFabricBridgeServerPort = 33002; + +CHIP_ERROR InitRpcClient(uint16_t rpcServerPort); + +CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId); diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp new file mode 100644 index 00000000000000..ed3e6b0d59e077 --- /dev/null +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -0,0 +1,70 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pw_rpc/server.h" +#include "pw_rpc_system_server/rpc_server.h" +#include "pw_rpc_system_server/socket.h" + +#include +#include + +#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE +#include "pigweed/rpc_services/FabricAdmin.h" +#endif + +namespace { + +#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE +class FabricAdmin final : public chip::rpc::FabricAdmin +{ +public: + pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) override + { + chip::NodeId nodeId = request.node_id; + printf("Received OpenCommissioningWindow request: 0x%" PRIx64 "\n", nodeId); + response.success = false; + + return pw::OkStatus(); + } +}; + +FabricAdmin fabric_admin_service; +#endif // defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE + +void RegisterServices(pw::rpc::Server & server) +{ +#if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE + server.RegisterService(fabric_admin_service); +#endif +} + +} // namespace + +void RunRpcService() +{ + pw::rpc::system_server::Init(); + RegisterServices(pw::rpc::system_server::Server()); + pw::rpc::system_server::Start(); +} + +void InitRpcServer(uint16_t rpcServerPort) +{ + pw::rpc::system_server::set_socket_port(rpcServerPort); + std::thread rpc_service(RunRpcService); + rpc_service.detach(); +} diff --git a/examples/fabric-admin/rpc/RpcServer.h b/examples/fabric-admin/rpc/RpcServer.h new file mode 100644 index 00000000000000..bc03bc0ac4abd3 --- /dev/null +++ b/examples/fabric-admin/rpc/RpcServer.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +constexpr uint16_t kFabricAdminServerPort = 33001; + +void InitRpcServer(uint16_t rpcServerPort); diff --git a/examples/fabric-admin/with_pw_rpc.gni b/examples/fabric-admin/with_pw_rpc.gni new file mode 100644 index 00000000000000..abb9ac65f27e78 --- /dev/null +++ b/examples/fabric-admin/with_pw_rpc.gni @@ -0,0 +1,42 @@ +# Copyright (c) 2024 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. + +# add this gni as import in your build args to use pigweed in the example +# 'import("//with_pw_rpc.gni")' + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/standalone/args.gni") + +import("//build_overrides/pigweed.gni") + +pw_log_BACKEND = "$dir_pw_log_basic" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" +pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" +pw_trace_BACKEND = "$dir_pw_trace_tokenized" +pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" +pw_rpc_system_server_BACKEND = "${chip_root}/config/linux/lib/pw_rpc:pw_rpc" +dir_pw_third_party_nanopb = "${chip_root}/third_party/nanopb/repo" +pw_chrono_SYSTEM_CLOCK_BACKEND = "$dir_pw_chrono_stl:system_clock" +pw_sync_MUTEX_BACKEND = "$dir_pw_sync_stl:mutex_backend" +pw_thread_YIELD_BACKEND = "$dir_pw_thread_stl:yield" +pw_thread_SLEEP_BACKEND = "$dir_pw_thread_stl:sleep" + +pw_build_LINK_DEPS = [ + "$dir_pw_assert:impl", + "$dir_pw_log:impl", +] + +chip_enable_pw_rpc = true +chip_use_pw_logging = true diff --git a/examples/fabric-bridge-app/linux/BUILD.gn b/examples/fabric-bridge-app/linux/BUILD.gn index 21c93344416b62..60617f2c3b6728 100644 --- a/examples/fabric-bridge-app/linux/BUILD.gn +++ b/examples/fabric-bridge-app/linux/BUILD.gn @@ -18,11 +18,19 @@ import("${chip_root}/build/chip/tools.gni") assert(chip_build_tools) +import("//build_overrides/pigweed.gni") +import("$dir_pw_build/target_types.gni") +import("${chip_root}/examples/common/pigweed/pigweed_rpcs.gni") + executable("fabric-bridge-app") { sources = [ "${chip_root}/examples/fabric-bridge-app/fabric-bridge-common/include/CHIPProjectAppConfig.h", "Device.cpp", + "RpcClient.cpp", + "RpcServer.cpp", "include/Device.h", + "include/RpcClient.h", + "include/RpcServer.h", "main.cpp", ] @@ -36,6 +44,32 @@ executable("fabric-bridge-app") { include_dirs = [ "include" ] + defines = [ + "PW_RPC_FABRIC_ADMIN_SERVICE=1", + "PW_RPC_FABRIC_BRIDGE_SERVICE=1", + ] + + sources += [ "${chip_root}/examples/platform/linux/system_rpc_server.cc" ] + + deps += [ + "$dir_pw_hdlc:default_addresses", + "$dir_pw_hdlc:rpc_channel_output", + "$dir_pw_log", + "$dir_pw_rpc:server", + "$dir_pw_rpc/system_server:facade", + "$dir_pw_rpc/system_server:socket", + "$dir_pw_stream:socket_stream", + "$dir_pw_sync:mutex", + "${chip_root}/config/linux/lib/pw_rpc:pw_rpc", + "${chip_root}/examples/common/pigweed:fabric_admin_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:fabric_bridge_service.nanopb_rpc", + "${chip_root}/examples/common/pigweed:rpc_services", + ] + + deps += pw_build_LINK_DEPS + + include_dirs += [ "${chip_root}/examples/common" ] + output_dir = root_out_dir } diff --git a/examples/fabric-bridge-app/linux/Device.cpp b/examples/fabric-bridge-app/linux/Device.cpp index 40cd8c007e8baa..4cf72a281113b6 100644 --- a/examples/fabric-bridge-app/linux/Device.cpp +++ b/examples/fabric-bridge-app/linux/Device.cpp @@ -46,11 +46,11 @@ void Device::SetReachable(bool aReachable) if (aReachable) { - ChipLogProgress(DeviceLayer, "Device[%s]: ONLINE", mName); + ChipLogProgress(NotSpecified, "Device[%s]: ONLINE", mName); } else { - ChipLogProgress(DeviceLayer, "Device[%s]: OFFLINE", mName); + ChipLogProgress(NotSpecified, "Device[%s]: OFFLINE", mName); } if (changed) @@ -63,7 +63,7 @@ void Device::SetName(const char * szName) { bool changed = (strncmp(mName, szName, sizeof(mName)) != 0); - ChipLogProgress(DeviceLayer, "Device[%s]: New Name=\"%s\"", mName, szName); + ChipLogProgress(NotSpecified, "Device[%s]: New Name=\"%s\"", mName, szName); chip::Platform::CopyString(mName, szName); diff --git a/examples/fabric-bridge-app/linux/RpcClient.cpp b/examples/fabric-bridge-app/linux/RpcClient.cpp new file mode 100644 index 00000000000000..57cfcb23a82e9b --- /dev/null +++ b/examples/fabric-bridge-app/linux/RpcClient.cpp @@ -0,0 +1,169 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "RpcClient.h" + +#include +#include +#include + +#include "fabric_admin_service/fabric_admin_service.rpc.pb.h" +#include "pw_assert/check.h" +#include "pw_hdlc/decoder.h" +#include "pw_hdlc/default_addresses.h" +#include "pw_hdlc/rpc_channel.h" +#include "pw_rpc/client.h" +#include "pw_stream/socket_stream.h" + +namespace { + +constexpr size_t kMaxTransmissionUnit = 256; +constexpr uint32_t kRpcTimeoutMs = 1000; +const char * rpcServerAddress = "127.0.0.1"; + +pw::stream::SocketStream rpcSocketStream; + +// Set up the output channel for the pw_rpc client to use. +pw::hdlc::RpcChannelOutput hdlc_channel_output(rpcSocketStream, pw::hdlc::kDefaultRpcAddress, "HDLC channel"); + +// An array of RPC channels (channels) is created, each associated with an HDLC channel output. +// This sets up the communication channels for RPC calls. +pw::rpc::Channel channels[] = { pw::rpc::Channel::Create<1>(&hdlc_channel_output) }; + +// Initialize the RPC client with the channels. +pw::rpc::Client client(channels); + +// Generated clients are namespaced with their proto library. +using FabricAdminClient = chip::rpc::pw_rpc::nanopb::FabricAdmin::Client; + +// RPC channel ID on which to make client calls. RPC calls cannot be made on +// channel 0 (Channel::kUnassignedChannelId). +constexpr uint32_t kDefaultChannelId = 1; + +// Function to process incoming packets +void ProcessPackets() +{ + std::array inputBuf; + pw::hdlc::Decoder decoder(inputBuf); + + while (true) + { + std::array data; + auto ret = rpcSocketStream.Read(data); + if (!ret.ok()) + { + if (ret.status() == pw::Status::OutOfRange()) + { + // Handle remote disconnect + rpcSocketStream.Close(); + return; + } + continue; + } + + for (std::byte byte : ret.value()) + { + auto result = decoder.Process(byte); + if (!result.ok()) + { + // Wait for more bytes that form a complete packet + continue; + } + pw::hdlc::Frame & frame = result.value(); + if (frame.address() != pw::hdlc::kDefaultRpcAddress) + { + // Wrong address; ignore the packet + continue; + } + + client.ProcessPacket(frame.data()).IgnoreError(); + } + } +} + +template +CHIP_ERROR WaitForResponse(CallType & call) +{ + if (!call.active()) + { + return CHIP_ERROR_INTERNAL; + } + + // Wait for the response or timeout + uint32_t elapsedTimeMs = 0; + const uint32_t sleepTimeMs = 100; + + while (call.active() && elapsedTimeMs < kRpcTimeoutMs) + { + usleep(sleepTimeMs * 1000); + elapsedTimeMs += sleepTimeMs; + } + + if (elapsedTimeMs >= kRpcTimeoutMs) + { + ChipLogError(NotSpecified, "RPC Response timed out!"); + return CHIP_ERROR_TIMEOUT; + } + + return CHIP_NO_ERROR; +} + +void OperationStatusResponse(const chip_rpc_OperationStatus & response, pw::Status status) +{ + if (status.ok()) + { + ChipLogProgress(NotSpecified, "Received operation status: %d", response.success); + } + else + { + ChipLogProgress(NotSpecified, "RPC call failed with status: %d\n", status.code()); + } +} + +} // namespace + +CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) +{ + if (rpcSocketStream.Connect(rpcServerAddress, rpcServerPort) != PW_STATUS_OK) + { + ChipLogError(NotSpecified, "Failed to connect the Fabric-Admin"); + return CHIP_ERROR_NOT_CONNECTED; + } + + ChipLogProgress(NotSpecified, "Connectted to the Fabric-Admin\n"); + + // Start a thread to process incoming packets + std::thread packet_processor(ProcessPackets); + packet_processor.detach(); + + return CHIP_NO_ERROR; +} + +CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId) +{ + ChipLogProgress(NotSpecified, "OpenCommissioningWindow\n"); + + FabricAdminClient fabric_admin_client(client, kDefaultChannelId); + chip_rpc_DeviceInfo device; + + device.node_id = nodeId; + + // The RPC will remain active as long as `call` is alive. + auto call = fabric_admin_client.OpenCommissioningWindow(device, OperationStatusResponse); + return WaitForResponse(call); +} diff --git a/examples/fabric-bridge-app/linux/RpcServer.cpp b/examples/fabric-bridge-app/linux/RpcServer.cpp new file mode 100644 index 00000000000000..c971811b193016 --- /dev/null +++ b/examples/fabric-bridge-app/linux/RpcServer.cpp @@ -0,0 +1,68 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "pw_rpc/server.h" +#include "pw_rpc_system_server/rpc_server.h" +#include "pw_rpc_system_server/socket.h" + +#include +#include + +#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE +#include "pigweed/rpc_services/FabricBridge.h" +#endif + +namespace { + +#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE +class FabricBridge final : public chip::rpc::FabricBridge +{ +public: + pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override + { + chip::NodeId nodeId = request.node_id; + ChipLogProgress(NotSpecified, "Received AddSynchronizedDevice: " ChipLogFormatX64, ChipLogValueX64(nodeId)); + return pw::OkStatus(); + } +}; + +FabricBridge fabric_bridge_service; +#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE + +void RegisterServices(pw::rpc::Server & server) +{ +#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE + server.RegisterService(fabric_bridge_service); +#endif +} + +} // namespace + +void RunRpcService() +{ + pw::rpc::system_server::Init(); + RegisterServices(pw::rpc::system_server::Server()); + pw::rpc::system_server::Start(); +} + +void InitRpcServer(uint16_t rpcServerPort) +{ + pw::rpc::system_server::set_socket_port(rpcServerPort); + std::thread rpc_service(RunRpcService); + rpc_service.detach(); +} diff --git a/examples/fabric-bridge-app/linux/include/RpcClient.h b/examples/fabric-bridge-app/linux/include/RpcClient.h new file mode 100644 index 00000000000000..8baa8231f63cb4 --- /dev/null +++ b/examples/fabric-bridge-app/linux/include/RpcClient.h @@ -0,0 +1,27 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include + +constexpr uint16_t kFabricAdminServerPort = 33001; + +CHIP_ERROR InitRpcClient(uint16_t rpcServerPort); + +CHIP_ERROR OpenCommissioningWindow(chip::NodeId nodeId); diff --git a/examples/fabric-bridge-app/linux/include/RpcServer.h b/examples/fabric-bridge-app/linux/include/RpcServer.h new file mode 100644 index 00000000000000..f86858b19bdfe3 --- /dev/null +++ b/examples/fabric-bridge-app/linux/include/RpcServer.h @@ -0,0 +1,23 @@ +/* + * + * Copyright (c) 2024 Project CHIP Authors + * All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +constexpr uint16_t kFabricBridgeServerPort = 33002; + +void InitRpcServer(uint16_t rpcServerPort); diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp index d639cea1ca0697..7ac1e2b5052c50 100644 --- a/examples/fabric-bridge-app/linux/main.cpp +++ b/examples/fabric-bridge-app/linux/main.cpp @@ -42,8 +42,11 @@ #include "CommissionableInit.h" #include "Device.h" +#include "RpcClient.h" +#include "RpcServer.h" #include +#include #include #include #include @@ -58,6 +61,7 @@ using namespace chip::DeviceLayer; using namespace chip::app::Clusters; #define POLL_INTERVAL_MS (100) +#define RETRY_INTERVAL_S (3) namespace { @@ -81,9 +85,16 @@ void BridgePollingThread() int ch = getchar(); if (ch == 'e') { - ChipLogProgress(DeviceLayer, "Exiting....."); + ChipLogProgress(NotSpecified, "Exiting....."); exit(0); } + else if (ch == 'o') + { + if (OpenCommissioningWindow(0x1234) != CHIP_NO_ERROR) + { + ChipLogError(NotSpecified, "Failed to call OpenCommissioningWindow RPC"); + } + } continue; } @@ -124,7 +135,7 @@ int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const SpanGetName(), + ChipLogProgress(NotSpecified, "Added device %s to dynamic endpoint %d (index=%d)", dev->GetName(), gCurrentEndpointId, index); return index; } @@ -139,12 +150,12 @@ int AddDeviceEndpoint(Device * dev, EmberAfEndpointType * ep, const SpanGetName(), ep, index); + ChipLogProgress(NotSpecified, "Removed device %s from dynamic endpoint %d (index=%d)", dev->GetName(), ep, index); return index; } index++; @@ -201,7 +212,7 @@ Protocols::InteractionModel::Status HandleReadBridgedDeviceBasicAttribute(Device { using namespace BridgedDeviceBasicInformation::Attributes; - ChipLogProgress(DeviceLayer, "HandleReadBridgedDeviceBasicAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength); + ChipLogProgress(NotSpecified, "HandleReadBridgedDeviceBasicAttribute: attrId=%d, maxReadLength=%d", attributeId, maxReadLength); if ((attributeId == Reachable::Id) && (maxReadLength == 1)) { @@ -265,7 +276,7 @@ Protocols::InteractionModel::Status emberAfExternalAttributeWriteCallback(Endpoi if (dev->IsReachable()) { - ChipLogProgress(DeviceLayer, "emberAfExternalAttributeWriteCallback: ep=%d, clusterId=%d", endpoint, clusterId); + ChipLogProgress(NotSpecified, "emberAfExternalAttributeWriteCallback: ep=%d, clusterId=%d", endpoint, clusterId); ret = Protocols::InteractionModel::Status::Success; } } @@ -284,6 +295,20 @@ void ApplicationInit() static_cast(emberAfEndpointFromIndex(static_cast(emberAfFixedEndpointCount() - 1))) + 1); gCurrentEndpointId = gFirstDynamicEndpointId; + InitRpcServer(kFabricBridgeServerPort); + + while (true) + { + if (InitRpcClient(kFabricAdminServerPort) == CHIP_NO_ERROR) + { + ChipLogProgress(NotSpecified, "Connected to Fabric-Admin"); + break; + } + + ChipLogError(NotSpecified, "Failed to connect to Fabric-Admin, retry in %d seconds....", RETRY_INTERVAL_S); + std::this_thread::sleep_for(std::chrono::seconds(RETRY_INTERVAL_S)); + } + // Start a thread for bridge polling std::thread pollingThread(BridgePollingThread); pollingThread.detach(); diff --git a/examples/fabric-bridge-app/linux/with_pw_rpc.gni b/examples/fabric-bridge-app/linux/with_pw_rpc.gni new file mode 100644 index 00000000000000..054640f9ddae61 --- /dev/null +++ b/examples/fabric-bridge-app/linux/with_pw_rpc.gni @@ -0,0 +1,41 @@ +# Copyright (c) 2024 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. + +# add this gni as import in your build args to use pigweed in the example +# 'import("//with_pw_rpc.gni")' + +import("//build_overrides/chip.gni") + +import("${chip_root}/config/standalone/args.gni") + +import("//build_overrides/pigweed.gni") + +pw_log_BACKEND = "$dir_pw_log_basic" +pw_assert_BACKEND = "$dir_pw_assert_log:check_backend" +pw_sys_io_BACKEND = "$dir_pw_sys_io_stdio" +pw_trace_BACKEND = "$dir_pw_trace_tokenized" +pw_unit_test_MAIN = "$dir_pw_unit_test:logging_main" +pw_rpc_system_server_BACKEND = "${chip_root}/config/linux/lib/pw_rpc:pw_rpc" +dir_pw_third_party_nanopb = "${chip_root}/third_party/nanopb/repo" +pw_chrono_SYSTEM_CLOCK_BACKEND = "$dir_pw_chrono_stl:system_clock" +pw_sync_MUTEX_BACKEND = "$dir_pw_sync_stl:mutex_backend" +pw_thread_YIELD_BACKEND = "$dir_pw_thread_stl:yield" +pw_thread_SLEEP_BACKEND = "$dir_pw_thread_stl:sleep" + +pw_build_LINK_DEPS = [ + "$dir_pw_assert:impl", + "$dir_pw_log:impl", +] + +chip_use_pw_logging = true