diff --git a/.github/workflows/examples-linux-standalone.yaml b/.github/workflows/examples-linux-standalone.yaml index eb97e63235e714..53728d33eac42a 100644 --- a/.github/workflows/examples-linux-standalone.yaml +++ b/.github/workflows/examples-linux-standalone.yaml @@ -202,21 +202,21 @@ jobs: run: | ./scripts/run_in_build_env.sh \ "./scripts/build/build_examples.py \ - --target linux-x64-fabric-admin \ + --target linux-x64-fabric-admin-rpc \ build" .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ linux debug fabric-admin \ - out/linux-x64-fabric-admin/fabric-admin \ + out/linux-x64-fabric-admin-rpc/fabric-admin \ /tmp/bloat_reports/ - name: Build example Fabric Bridge App run: | ./scripts/run_in_build_env.sh \ "./scripts/build/build_examples.py \ - --target linux-x64-fabric-bridge \ + --target linux-x64-fabric-bridge-no-ble-rpc \ build" .environment/pigweed-venv/bin/python3 scripts/tools/memory/gh_sizes.py \ linux debug fabric-bridge-app \ - out/linux-x64-fabric-bridge/fabric-bridge-app \ + out/linux-x64-fabric-bridge-no-ble-rpc/fabric-bridge-app \ /tmp/bloat_reports/ - name: Uploading Size Reports uses: ./.github/actions/upload-size-reports diff --git a/examples/common/pigweed/protos/fabric_bridge_service.proto b/examples/common/pigweed/protos/fabric_bridge_service.proto index 5bd4f8efd779e7..10e5ccf888583d 100644 --- a/examples/common/pigweed/protos/fabric_bridge_service.proto +++ b/examples/common/pigweed/protos/fabric_bridge_service.proto @@ -11,5 +11,6 @@ message SynchronizedDevice { service FabricBridge { rpc AddSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} + rpc RemoveSynchronizedDevice(SynchronizedDevice) returns (pw.protobuf.Empty){} } diff --git a/examples/common/pigweed/rpc_services/FabricBridge.h b/examples/common/pigweed/rpc_services/FabricBridge.h index bce32ebd3d99b2..4b9c4d93f1eb51 100644 --- a/examples/common/pigweed/rpc_services/FabricBridge.h +++ b/examples/common/pigweed/rpc_services/FabricBridge.h @@ -38,6 +38,11 @@ class FabricBridge : public pw_rpc::nanopb::FabricBridge::Service<FabricBridge> { return pw::Status::Unimplemented(); } + + virtual pw::Status RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) + { + return pw::Status::Unimplemented(); + } }; } // namespace rpc diff --git a/examples/fabric-admin/BUILD.gn b/examples/fabric-admin/BUILD.gn index 9ab444d5f8dc9c..485c14afbbfe80 100644 --- a/examples/fabric-admin/BUILD.gn +++ b/examples/fabric-admin/BUILD.gn @@ -46,8 +46,6 @@ config("config") { defines += [ "CONFIG_USE_LOCAL_STORAGE" ] } - cflags = [ "-Wconversion" ] - if (chip_enable_pw_rpc) { defines += [ "PW_RPC_ENABLED" ] } @@ -142,6 +140,10 @@ static_library("fabric-admin-utils") { ] 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) { diff --git a/examples/fabric-admin/args.gni b/examples/fabric-admin/args.gni index 83300d797ed08a..63c91c70c209cd 100644 --- a/examples/fabric-admin/args.gni +++ b/examples/fabric-admin/args.gni @@ -32,3 +32,4 @@ matter_log_json_payload_decode_full = true # make fabric-admin very strict by default chip_tlv_validate_char_string_on_read = true chip_tlv_validate_char_string_on_write = true +chip_enable_ble = true diff --git a/examples/fabric-admin/rpc/RpcClient.cpp b/examples/fabric-admin/rpc/RpcClient.cpp index 96a39e91f23b02..f03c4f3f699838 100644 --- a/examples/fabric-admin/rpc/RpcClient.cpp +++ b/examples/fabric-admin/rpc/RpcClient.cpp @@ -41,6 +41,7 @@ constexpr uint32_t kDefaultChannelId = 1; // Fabric Bridge Client rpc::pw_rpc::nanopb::FabricBridge::Client fabricBridgeClient(rpc::client::GetDefaultRpcClient(), kDefaultChannelId); pw::rpc::NanopbUnaryReceiver<::pw_protobuf_Empty> addSynchronizedDeviceCall; +pw::rpc::NanopbUnaryReceiver<::pw_protobuf_Empty> removeSynchronizedDeviceCall; // Callback function to be called when the RPC response is received void OnAddDeviceResponseCompleted(const pw_protobuf_Empty & response, pw::Status status) @@ -55,6 +56,19 @@ void OnAddDeviceResponseCompleted(const pw_protobuf_Empty & response, pw::Status } } +// Callback function to be called when the RPC response is received +void OnRemoveDeviceResponseCompleted(const pw_protobuf_Empty & response, pw::Status status) +{ + if (status.ok()) + { + ChipLogProgress(NotSpecified, "RemoveSynchronizedDevice RPC call succeeded!"); + } + else + { + ChipLogProgress(NotSpecified, "RemoveSynchronizedDevice RPC call failed with status: %d", status.code()); + } +} + } // namespace CHIP_ERROR InitRpcClient(uint16_t rpcServerPort) @@ -76,11 +90,41 @@ CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId) chip_rpc_SynchronizedDevice device; device.node_id = nodeId; - // The RPC will remain active as long as `addSynchronizedDeviceCall` is alive. + // By assigning the returned call to the global 'addSynchronizedDeviceCall', the RPC + // call is kept alive until it completes. When a response is received, it + // will be logged by the handler function and the call will complete. addSynchronizedDeviceCall = fabricBridgeClient.AddSynchronizedDevice(device, OnAddDeviceResponseCompleted); if (!addSynchronizedDeviceCall.active()) { + // The RPC call was not sent. This could occur due to, for example, an invalid channel ID. Handle if necessary. + return CHIP_ERROR_INTERNAL; + } + + return CHIP_NO_ERROR; +} + +CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId) +{ + ChipLogProgress(NotSpecified, "RemoveSynchronizedDevice"); + + if (removeSynchronizedDeviceCall.active()) + { + ChipLogError(NotSpecified, "Remove Synchronized Device operation is in progress\n"); + return CHIP_ERROR_BUSY; + } + + chip_rpc_SynchronizedDevice device; + device.node_id = nodeId; + + // By assigning the returned call to the global 'removeSynchronizedDeviceCall', the RPC + // call is kept alive until it completes. When a response is received, it + // will be logged by the handler function and the call will complete. + removeSynchronizedDeviceCall = fabricBridgeClient.RemoveSynchronizedDevice(device, OnRemoveDeviceResponseCompleted); + + if (!removeSynchronizedDeviceCall.active()) + { + // The RPC call was not sent. This could occur due to, for example, an invalid channel ID. Handle if necessary. return CHIP_ERROR_INTERNAL; } diff --git a/examples/fabric-admin/rpc/RpcClient.h b/examples/fabric-admin/rpc/RpcClient.h index f6ce805d607ce0..eb28c19bee7d3e 100644 --- a/examples/fabric-admin/rpc/RpcClient.h +++ b/examples/fabric-admin/rpc/RpcClient.h @@ -46,3 +46,18 @@ CHIP_ERROR InitRpcClient(uint16_t rpcServerPort); * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. */ CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId); + +/** + * @brief Removes a synchronized device from the RPC client. + * + * This function attempts to remove a device identified by its `nodeId` from the synchronized device list. + * It logs the progress and checks if a `RemoveSynchronizedDevice` operation is already in progress. + * If an operation is in progress, it returns `CHIP_ERROR_BUSY`. + * + * @param nodeId The Node ID of the device to be removed. + * @return CHIP_ERROR An error code indicating the success or failure of the operation. + * - CHIP_NO_ERROR: The RPC command was successfully sent. + * - CHIP_ERROR_BUSY: Another operation is currently in progress. + * - CHIP_ERROR_INTERNAL: An internal error occurred while activating the RPC call. + */ +CHIP_ERROR RemoveSynchronizedDevice(chip::NodeId nodeId); diff --git a/examples/fabric-admin/rpc/RpcServer.cpp b/examples/fabric-admin/rpc/RpcServer.cpp index b3cbdcea05409a..638e76dddcf292 100644 --- a/examples/fabric-admin/rpc/RpcServer.cpp +++ b/examples/fabric-admin/rpc/RpcServer.cpp @@ -27,15 +27,17 @@ #include "pigweed/rpc_services/FabricAdmin.h" #endif +using namespace ::chip; + namespace { #if defined(PW_RPC_FABRIC_ADMIN_SERVICE) && PW_RPC_FABRIC_ADMIN_SERVICE -class FabricAdmin final : public chip::rpc::FabricAdmin +class FabricAdmin final : public rpc::FabricAdmin { public: pw::Status OpenCommissioningWindow(const chip_rpc_DeviceInfo & request, chip_rpc_OperationStatus & response) override { - chip::NodeId nodeId = request.node_id; + NodeId nodeId = request.node_id; ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", nodeId); response.success = false; diff --git a/examples/fabric-bridge-app/linux/BUILD.gn b/examples/fabric-bridge-app/linux/BUILD.gn index 3e82f044c047f9..2b408d52625fea 100644 --- a/examples/fabric-bridge-app/linux/BUILD.gn +++ b/examples/fabric-bridge-app/linux/BUILD.gn @@ -46,8 +46,6 @@ executable("fabric-bridge-app") { "${chip_root}/src/lib", ] - cflags = [ "-Wconversion" ] - include_dirs = [ "include" ] if (bridge_enable_pw_rpc) { @@ -87,6 +85,10 @@ executable("fabric-bridge-app") { "${chip_root}/examples/common", "${chip_root}/examples/platform/linux", ] + } else { + # The system_rpc_server.cc file is in pigweed and doesn't compile with + # -Wconversion, remove check for RPC build only. + cflags = [ "-Wconversion" ] } output_dir = root_out_dir diff --git a/examples/fabric-bridge-app/linux/RpcServer.cpp b/examples/fabric-bridge-app/linux/RpcServer.cpp index 088fc9a50a38b8..d4044f043468d3 100644 --- a/examples/fabric-bridge-app/linux/RpcServer.cpp +++ b/examples/fabric-bridge-app/linux/RpcServer.cpp @@ -43,6 +43,7 @@ class FabricBridge final : public chip::rpc::FabricBridge { public: pw::Status AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override; + pw::Status RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) override; }; pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) @@ -64,6 +65,21 @@ pw::Status FabricBridge::AddSynchronizedDevice(const chip_rpc_SynchronizedDevice return pw::OkStatus(); } +pw::Status FabricBridge::RemoveSynchronizedDevice(const chip_rpc_SynchronizedDevice & request, pw_protobuf_Empty & response) +{ + NodeId nodeId = request.node_id; + ChipLogProgress(NotSpecified, "Received RemoveSynchronizedDevice: " ChipLogFormatX64, ChipLogValueX64(nodeId)); + + int removed_idx = DeviceMgr().RemoveDeviceByNodeId(nodeId); + if (removed_idx < 0) + { + ChipLogError(NotSpecified, "Failed to remove device with nodeId=0x" ChipLogFormatX64, ChipLogValueX64(nodeId)); + return pw::Status::NotFound(); + } + + return pw::OkStatus(); +} + FabricBridge fabric_bridge_service; #endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE diff --git a/examples/fabric-bridge-app/linux/main.cpp b/examples/fabric-bridge-app/linux/main.cpp index f4217a14868972..2047e15877ee4c 100644 --- a/examples/fabric-bridge-app/linux/main.cpp +++ b/examples/fabric-bridge-app/linux/main.cpp @@ -47,7 +47,10 @@ using namespace chip::app::Clusters::AdministratorCommissioning; namespace { constexpr uint16_t kPollIntervalMs = 100; + +#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE constexpr uint16_t kRetryIntervalS = 3; +#endif bool KeyboardHit() {