[Fabric-Sync] Add the IPC support between Fabric_Admin and Fabric_Bridge (#33603)

* Add the RPC support between Fabric_Admin and Fabric_Bridge

* Add bridge_enable_pw_rpc build flag

* Address review comments

* Add RpcClientProcessor

* Update API comments
diff --git a/examples/common/pigweed/BUILD.gn b/examples/common/pigweed/BUILD.gn
index c0178e4..e523bea 100644
--- a/examples/common/pigweed/BUILD.gn
+++ b/examples/common/pigweed/BUILD.gn
@@ -80,6 +80,20 @@
   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 0000000..e52fd29
--- /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 0000000..5bd4f8e
--- /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 a03dc98..db9f22f 100644
--- a/examples/common/pigweed/rpc_console/py/BUILD.gn
+++ b/examples/common/pigweed/rpc_console/py/BUILD.gn
@@ -46,6 +46,8 @@
     "${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 1591722..50f0b03 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 @@
                 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 0000000..5254b9e
--- /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 <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <platform/PlatformManager.h>
+
+namespace chip {
+namespace rpc {
+
+class FabricAdmin : public pw_rpc::nanopb::FabricAdmin::Service<FabricAdmin>
+{
+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 0000000..bce32eb
--- /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 <app-common/zap-generated/attributes/Accessors.h>
+#include <app-common/zap-generated/ids/Attributes.h>
+#include <app-common/zap-generated/ids/Clusters.h>
+#include <platform/PlatformManager.h>
+
+namespace chip {
+namespace rpc {
+
+class FabricBridge : public pw_rpc::nanopb::FabricBridge::Service<FabricBridge>
+{
+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 ddaa334..ad7eb21 100644
--- a/examples/fabric-admin/BUILD.gn
+++ b/examples/fabric-admin/BUILD.gn
@@ -22,10 +22,18 @@
 
 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 = [
     ".",
     "${chip_root}/examples/common",
+    "${chip_root}/examples/platform/linux",
     "${chip_root}/zzz_generated/app-common/app-common",
     "${chip_root}/zzz_generated/chip-tool",
     "${chip_root}/src/lib",
@@ -39,6 +47,10 @@
   }
 
   cflags = [ "-Wconversion" ]
+
+  if (chip_enable_pw_rpc) {
+    defines += [ "PW_RPC_ENABLED" ]
+  }
 }
 
 static_library("fabric-admin-utils") {
@@ -59,6 +71,7 @@
     "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 +108,40 @@
 
   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/RpcClientProcessor.cpp",
+      "${chip_root}/examples/platform/linux/RpcClientProcessor.h",
+      "${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
+  }
+
   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 0000000..f2be577
--- /dev/null
+++ b/examples/fabric-admin/commands/fabric-sync/Commands.h
@@ -0,0 +1,33 @@
+/*
+ *   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 <commands/common/Commands.h>
+#include <commands/fabric-sync/FabricSyncCommand.h>
+
+void registerCommandsFabricSync(Commands & commands, CredentialIssuerCommands * credsIssuerConfig)
+{
+    const char * clusterName = "FabricSync";
+
+    commands_list clusterCommands = {
+        make_unique<FabricSyncAddDeviceCommand>(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 0000000..c2a1b5d
--- /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 <commands/common/RemoteDataModelLogger.h>
+#include <thread>
+#include <unistd.h>
+
+#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 <rpc/RpcClient.h>
+#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 0000000..cf739cc
--- /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 <commands/common/CHIPCommand.h>
+
+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(1); }
+
+private:
+    chip::NodeId mNodeId;
+
+    CHIP_ERROR RunCommand(NodeId remoteId);
+};
diff --git a/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp b/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp
index aaf3c36..c5c8442 100644
--- a/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp
+++ b/examples/fabric-admin/commands/interactive/InteractiveCommands.cpp
@@ -28,11 +28,18 @@
 #include <string>
 #include <vector>
 
+#if defined(PW_RPC_ENABLED)
+#include <rpc/RpcClient.h>
+#endif
+
+using namespace chip;
+
+namespace {
+
 constexpr char kInteractiveModePrompt[]          = ">>> ";
 constexpr char kInteractiveModeHistoryFileName[] = "chip_tool_history";
 constexpr char kInteractiveModeStopCommand[]     = "quit()";
-
-namespace {
+constexpr uint16_t kRetryIntervalS               = 5;
 
 // File pointer for the log file
 FILE * sLogFile = nullptr;
@@ -67,7 +74,7 @@
         return;
     }
 
-    uint64_t timeMs       = chip::System::SystemClock().GetMonotonicMilliseconds64().count();
+    uint64_t timeMs       = System::SystemClock().GetMonotonicMilliseconds64().count();
     uint64_t seconds      = timeMs / 1000;
     uint64_t milliseconds = timeMs % 1000;
 
@@ -82,6 +89,26 @@
     funlockfile(sLogFile);
 }
 
+#if defined(PW_RPC_ENABLED)
+void AttemptRpcClientConnect(System::Layer * systemLayer, void * appState)
+{
+    if (InitRpcClient(kFabricBridgeServerPort) == CHIP_NO_ERROR)
+    {
+        ChipLogProgress(NotSpecified, "Connected to Fabric-Bridge");
+    }
+    else
+    {
+        ChipLogError(NotSpecified, "Failed to connect to Fabric-Bridge, retry in %d seconds....", kRetryIntervalS);
+        systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, nullptr);
+    }
+}
+
+void ExecuteDeferredConnect(intptr_t ignored)
+{
+    AttemptRpcClientConnect(&DeviceLayer::SystemLayer(), nullptr);
+}
+#endif
+
 } // namespace
 
 char * InteractiveStartCommand::GetCommand(char * command)
@@ -134,9 +161,13 @@
         OpenLogFile(mLogFilePath.Value());
 
         // Redirect logs to the custom logging callback
-        chip::Logging::SetLogRedirectCallback(LoggingCallback);
+        Logging::SetLogRedirectCallback(LoggingCallback);
     }
 
+#if defined(PW_RPC_ENABLED)
+    DeviceLayer::PlatformMgr().ScheduleWork(ExecuteDeferredConnect, 0);
+#endif
+
     char * command = nullptr;
     int status;
     while (true)
@@ -167,7 +198,7 @@
         // If scheduling the cleanup fails, there is not much we can do.
         // But if something went wrong while the application is leaving it could be because things have
         // not been cleaned up properly, so it is still useful to log the failure.
-        LogErrorOnFailure(chip::DeviceLayer::PlatformMgr().ScheduleWork(ExecuteDeferredCleanups, 0));
+        LogErrorOnFailure(DeviceLayer::PlatformMgr().ScheduleWork(ExecuteDeferredCleanups, 0));
         return false;
     }
 
diff --git a/examples/fabric-admin/main.cpp b/examples/fabric-admin/main.cpp
index a1002d8..f5f98cc 100644
--- a/examples/fabric-admin/main.cpp
+++ b/examples/fabric-admin/main.cpp
@@ -18,6 +18,7 @@
 
 #include <commands/clusters/SubscriptionsCommands.h>
 #include <commands/common/Commands.h>
+#include <commands/fabric-sync/Commands.h>
 #include <commands/interactive/Commands.h>
 #include <commands/pairing/Commands.h>
 #include <zap-generated/cluster/Commands.h>
@@ -26,6 +27,20 @@
 #include <string>
 #include <vector>
 
+#if defined(PW_RPC_ENABLED)
+#include <rpc/RpcServer.h>
+#endif
+
+using namespace chip;
+
+void ApplicationInit()
+{
+#if defined(PW_RPC_ENABLED)
+    InitRpcServer(kFabricAdminServerPort);
+    ChipLogProgress(NotSpecified, "PW_RPC initialized.");
+#endif
+}
+
 // ================================================================================
 // Main Code
 // ================================================================================
@@ -45,6 +60,7 @@
     ExampleCredentialIssuerCommands credIssuerCommands;
     Commands commands;
 
+    registerCommandsFabricSync(commands, &credIssuerCommands);
     registerCommandsInteractive(commands, &credIssuerCommands);
     registerCommandsPairing(commands, &credIssuerCommands);
     registerClusters(commands, &credIssuerCommands);
@@ -56,5 +72,7 @@
         c_args.push_back(const_cast<char *>(arg.c_str()));
     }
 
+    ApplicationInit();
+
     return commands.Run(static_cast<int>(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 0000000..a1a34d3
--- /dev/null
+++ b/examples/fabric-admin/rpc/RpcClient.cpp
@@ -0,0 +1,89 @@
+/*
+ *
+ *    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 "RpcClientProcessor.h"
+
+#include <string>
+#include <thread>
+#include <unistd.h>
+
+#include "fabric_bridge_service/fabric_bridge_service.rpc.pb.h"
+#include "pw_assert/check.h"
+#include "pw_function/function.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"
+
+using namespace chip;
+
+namespace {
+
+// Constants
+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;
+
+// Callback function to be called when the RPC response is received
+void OnAddDeviceResponseCompleted(const pw_protobuf_Empty & response, pw::Status status)
+{
+    if (status.ok())
+    {
+        ChipLogProgress(NotSpecified, "AddSynchronizedDevice RPC call succeeded!");
+    }
+    else
+    {
+        ChipLogProgress(NotSpecified, "AddSynchronizedDevice RPC call failed with status: %d\n", status.code());
+    }
+}
+
+} // namespace
+
+CHIP_ERROR InitRpcClient(uint16_t rpcServerPort)
+{
+    rpc::client::SetRpcServerPort(rpcServerPort);
+    return rpc::client::StartPacketProcessing();
+}
+
+CHIP_ERROR AddSynchronizedDevice(chip::NodeId nodeId)
+{
+    ChipLogProgress(NotSpecified, "AddSynchronizedDevice");
+
+    if (addSynchronizedDeviceCall.active())
+    {
+        ChipLogError(NotSpecified, "OpenCommissioningWindow is in progress\n");
+        return CHIP_ERROR_BUSY;
+    }
+
+    chip_rpc_SynchronizedDevice device;
+    device.node_id = nodeId;
+
+    // The RPC will remain active as long as `addSynchronizedDeviceCall` is alive.
+    addSynchronizedDeviceCall = fabricBridgeClient.AddSynchronizedDevice(device, OnAddDeviceResponseCompleted);
+
+    if (!addSynchronizedDeviceCall.active())
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
diff --git a/examples/fabric-admin/rpc/RpcClient.h b/examples/fabric-admin/rpc/RpcClient.h
new file mode 100644
index 0000000..efe3c24
--- /dev/null
+++ b/examples/fabric-admin/rpc/RpcClient.h
@@ -0,0 +1,48 @@
+/*
+ *
+ *    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 <platform/CHIPDeviceLayer.h>
+
+constexpr uint16_t kFabricBridgeServerPort = 33002;
+
+/**
+ * @brief Initializes the RPC client with the specified server port.
+ *
+ * This function sets the RPC server port and starts packet processing for the RPC client.
+ *
+ * @param rpcServerPort The port number on which the RPC server is running.
+ * @return CHIP_NO_ERROR on successful initialization, or an appropriate CHIP_ERROR on failure.
+ */
+CHIP_ERROR InitRpcClient(uint16_t rpcServerPort);
+
+/**
+ * @brief Adds a synchronized device to the RPC client.
+ *
+ * This function attempts to add a device identified by its `nodeId` to the synchronized device list.
+ * It logs the progress and checks if an `OpenCommissioningWindow` 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 added.
+ * @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 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 0000000..b3cbdce
--- /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 <system/SystemClock.h>
+#include <thread>
+
+#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;
+        ChipLogProgress(NotSpecified, "Received OpenCommissioningWindow request: 0x%lx", 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 0000000..bc03bc0
--- /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 0000000..abb9ac6
--- /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 ea7e6e0..3e82f04 100644
--- a/examples/fabric-bridge-app/linux/BUILD.gn
+++ b/examples/fabric-bridge-app/linux/BUILD.gn
@@ -16,8 +16,20 @@
 
 import("${chip_root}/build/chip/tools.gni")
 
+import("//with_pw_rpc.gni")
+
 assert(chip_build_tools)
 
+declare_args() {
+  bridge_enable_pw_rpc = false
+}
+
+if (bridge_enable_pw_rpc) {
+  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",
@@ -38,6 +50,45 @@
 
   include_dirs = [ "include" ]
 
+  if (bridge_enable_pw_rpc) {
+    defines = [
+      "PW_RPC_FABRIC_ADMIN_SERVICE=1",
+      "PW_RPC_FABRIC_BRIDGE_SERVICE=1",
+    ]
+
+    sources += [
+      "${chip_root}/examples/platform/linux/RpcClientProcessor.cpp",
+      "${chip_root}/examples/platform/linux/RpcClientProcessor.h",
+      "${chip_root}/examples/platform/linux/system_rpc_server.cc",
+      "RpcClient.cpp",
+      "RpcServer.cpp",
+      "include/RpcClient.h",
+      "include/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
+
+    include_dirs += [
+      "${chip_root}/examples/common",
+      "${chip_root}/examples/platform/linux",
+    ]
+  }
+
   output_dir = root_out_dir
 }
 
diff --git a/examples/fabric-bridge-app/linux/RpcClient.cpp b/examples/fabric-bridge-app/linux/RpcClient.cpp
new file mode 100644
index 0000000..c09a447
--- /dev/null
+++ b/examples/fabric-bridge-app/linux/RpcClient.cpp
@@ -0,0 +1,88 @@
+/*
+ *
+ *    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 "RpcClientProcessor.h"
+
+#include <string>
+#include <thread>
+#include <unistd.h>
+
+#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"
+
+using namespace chip;
+
+namespace {
+
+// Constants
+constexpr uint32_t kDefaultChannelId = 1;
+
+// Fabric Admin Client
+rpc::pw_rpc::nanopb::FabricAdmin::Client fabricAdminClient(rpc::client::GetDefaultRpcClient(), kDefaultChannelId);
+pw::rpc::NanopbUnaryReceiver<::chip_rpc_OperationStatus> openCommissioningWindowCall;
+
+// Callback function to be called when the RPC response is received
+void OnOpenCommissioningWindowCompleted(const chip_rpc_OperationStatus & response, pw::Status status)
+{
+    if (status.ok())
+    {
+        ChipLogProgress(NotSpecified, "OpenCommissioningWindow received operation status: %d", response.success);
+    }
+    else
+    {
+        ChipLogProgress(NotSpecified, "OpenCommissioningWindow RPC call failed with status: %d\n", status.code());
+    }
+}
+
+} // namespace
+
+CHIP_ERROR InitRpcClient(uint16_t rpcServerPort)
+{
+    rpc::client::SetRpcServerPort(rpcServerPort);
+    return rpc::client::StartPacketProcessing();
+}
+
+CHIP_ERROR OpenCommissioningWindow(NodeId nodeId)
+{
+    ChipLogProgress(NotSpecified, "OpenCommissioningWindow\n");
+
+    if (openCommissioningWindowCall.active())
+    {
+        ChipLogError(NotSpecified, "OpenCommissioningWindow is in progress\n");
+        return CHIP_ERROR_BUSY;
+    }
+
+    chip_rpc_DeviceInfo device;
+    device.node_id = nodeId;
+
+    // The RPC will remain active as long as `openCommissioningWindowCall` is alive.
+    openCommissioningWindowCall = fabricAdminClient.OpenCommissioningWindow(device, OnOpenCommissioningWindowCompleted);
+
+    if (!openCommissioningWindowCall.active())
+    {
+        return CHIP_ERROR_INTERNAL;
+    }
+
+    return CHIP_NO_ERROR;
+}
diff --git a/examples/fabric-bridge-app/linux/RpcServer.cpp b/examples/fabric-bridge-app/linux/RpcServer.cpp
new file mode 100644
index 0000000..c971811
--- /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 <system/SystemClock.h>
+#include <thread>
+
+#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 0000000..bd424e9
--- /dev/null
+++ b/examples/fabric-bridge-app/linux/include/RpcClient.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 <platform/CHIPDeviceLayer.h>
+
+constexpr uint16_t kFabricAdminServerPort = 33001;
+
+/**
+ * Initializes the RPC client by setting the server port and starting packet processing.
+ *
+ * @param rpcServerPort The port number of the RPC server.
+ * @return CHIP_ERROR An error code indicating the success or failure of the initialization process.
+ * - CHIP_NO_ERROR: Initialization was successful.
+ * - Other error codes indicating specific failure reasons.
+ */
+CHIP_ERROR InitRpcClient(uint16_t rpcServerPort);
+
+/**
+ * Opens a commissioning window for a specified node.
+ *
+ * @param nodeId The identifier of the node for which the commissioning window should be opened.
+ * @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 commissioning window is currently in progress.
+ * - CHIP_ERROR_INTERNAL: An internal error occurred.
+ */
+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 0000000..f86858b
--- /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 600d4a2..4767056 100644
--- a/examples/fabric-bridge-app/linux/main.cpp
+++ b/examples/fabric-bridge-app/linux/main.cpp
@@ -25,19 +25,26 @@
 #include <app/AttributeAccessInterfaceRegistry.h>
 #include <lib/support/ZclString.h>
 
+#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
+#include "RpcClient.h"
+#include "RpcServer.h"
+#endif
+
 #include <string>
 #include <sys/ioctl.h>
 #include <thread>
 
 using namespace chip;
 
-#define POLL_INTERVAL_MS (100)
 #define ZCL_DESCRIPTOR_CLUSTER_REVISION (1u)
 #define ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_CLUSTER_REVISION (2u)
 #define ZCL_BRIDGED_DEVICE_BASIC_INFORMATION_FEATURE_MAP (0u)
 
 namespace {
 
+constexpr uint16_t kPollIntervalMs = 100;
+constexpr uint16_t kRetryIntervalS = 3;
+
 bool KeyboardHit()
 {
     int bytesWaiting;
@@ -57,20 +64,50 @@
                 ChipLogProgress(NotSpecified, "Exiting.....");
                 exit(0);
             }
+#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
+            else if (ch == 'o')
+            {
+                CHIP_ERROR err = OpenCommissioningWindow(0x1234);
+                if (err != CHIP_NO_ERROR)
+                {
+                    ChipLogError(NotSpecified, "Failed to call OpenCommissioningWindow RPC: %" CHIP_ERROR_FORMAT, err.Format());
+                }
+            }
+#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
             continue;
         }
 
         // Sleep to avoid tight loop reading commands
-        usleep(POLL_INTERVAL_MS * 1000);
+        usleep(kPollIntervalMs * 1000);
     }
 }
 
+#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
+void AttemptRpcClientConnect(System::Layer * systemLayer, void * appState)
+{
+    if (InitRpcClient(kFabricAdminServerPort) == CHIP_NO_ERROR)
+    {
+        ChipLogProgress(NotSpecified, "Connected to Fabric-Admin");
+    }
+    else
+    {
+        ChipLogError(NotSpecified, "Failed to connect to Fabric-Admin, retry in %d seconds....", kRetryIntervalS);
+        systemLayer->StartTimer(System::Clock::Seconds16(kRetryIntervalS), AttemptRpcClientConnect, nullptr);
+    }
+}
+#endif // defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
+
 DeviceManager gDeviceManager;
 
 } // namespace
 
 void ApplicationInit()
 {
+#if defined(PW_RPC_FABRIC_BRIDGE_SERVICE) && PW_RPC_FABRIC_BRIDGE_SERVICE
+    InitRpcServer(kFabricBridgeServerPort);
+    AttemptRpcClientConnect(&DeviceLayer::SystemLayer(), nullptr);
+#endif
+
     // 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 0000000..e1bd567
--- /dev/null
+++ b/examples/fabric-bridge-app/linux/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_use_pw_logging = true
+bridge_enable_pw_rpc = true
diff --git a/examples/platform/linux/RpcClientProcessor.cpp b/examples/platform/linux/RpcClientProcessor.cpp
new file mode 100644
index 0000000..a2cbe56
--- /dev/null
+++ b/examples/platform/linux/RpcClientProcessor.cpp
@@ -0,0 +1,124 @@
+/*
+ *
+ *    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 "RpcClientProcessor.h"
+
+#include <string>
+#include <thread>
+
+#include "pw_hdlc/decoder.h"
+#include "pw_hdlc/default_addresses.h"
+#include "pw_hdlc/rpc_channel.h"
+#include "pw_stream/socket_stream.h"
+
+namespace chip {
+namespace rpc {
+namespace client {
+namespace {
+
+// Constants
+constexpr size_t kMaxTransmissionUnit = 256;
+constexpr uint32_t kDefaultChannelId  = 1;
+const char * kDefaultRpcServerAddress = "127.0.0.1";
+
+// RPC Stream and Channel Setup
+pw::stream::SocketStream rpcSocketStream;
+pw::hdlc::RpcChannelOutput hdlcChannelOutput(rpcSocketStream, pw::hdlc::kDefaultRpcAddress, "HDLC channel");
+pw::rpc::Channel channels[] = { pw::rpc::Channel::Create<1>(&hdlcChannelOutput) };
+pw::rpc::Client rpcClient(channels);
+
+// RPC Stream and Channel Setup
+uint16_t rpcServerPort        = 0;
+const char * rpcServerAddress = kDefaultRpcServerAddress;
+
+// Function to process incoming packets
+void ProcessPackets()
+{
+    std::array<std::byte, kMaxTransmissionUnit> inputBuf;
+    pw::hdlc::Decoder decoder(inputBuf);
+
+    while (true)
+    {
+        std::array<std::byte, kMaxTransmissionUnit> 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;
+            }
+
+            rpcClient.ProcessPacket(frame.data()).IgnoreError();
+        }
+    }
+}
+
+} // namespace
+
+void SetRpcServerAddress(const char * address)
+{
+    rpcServerAddress = address;
+}
+
+void SetRpcServerPort(uint16_t port)
+{
+    rpcServerPort = port;
+}
+
+pw::rpc::Client & GetDefaultRpcClient()
+{
+    return rpcClient;
+}
+
+CHIP_ERROR StartPacketProcessing()
+{
+    if (rpcSocketStream.Connect(rpcServerAddress, rpcServerPort) != PW_STATUS_OK)
+    {
+        // Handle connection error
+        return CHIP_ERROR_NOT_CONNECTED;
+    }
+
+    // Start a thread to process incoming packets
+    std::thread packet_processor(ProcessPackets);
+    packet_processor.detach();
+
+    return CHIP_NO_ERROR;
+}
+
+} // namespace client
+} // namespace rpc
+} // namespace chip
diff --git a/examples/platform/linux/RpcClientProcessor.h b/examples/platform/linux/RpcClientProcessor.h
new file mode 100644
index 0000000..f2305df
--- /dev/null
+++ b/examples/platform/linux/RpcClientProcessor.h
@@ -0,0 +1,36 @@
+/*
+ *
+ *    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 "pw_rpc/client.h"
+#include <platform/CHIPDeviceLayer.h>
+#include <unistd.h>
+
+namespace chip {
+namespace rpc {
+namespace client {
+
+void SetRpcServerAddress(const char * address);
+void SetRpcServerPort(uint16_t port);
+pw::rpc::Client & GetDefaultRpcClient();
+CHIP_ERROR StartPacketProcessing();
+
+} // namespace client
+} // namespace rpc
+} // namespace chip