Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,18 @@ title: Device-to-Device communication with Device Connect
minutes_to_complete: 25


who_is_this_for: This is an introductory topic for developers wiring up heterogeneous edge fleets, where devices need a shared way to find each other and a shared way to be controlled by agents. Device Connect provides this communication protocol between agents and devices, and standardizes how devices from different vendors advertise themselves and exchange structured messages, so both peer devices and AI agents can discover and invoke them through the same driver model. You'll use it to stand up peer-to-peer communication between two devices, with no broker or cloud service in between.
who_is_this_for: This is an introductory topic for developers wiring up heterogeneous edge fleets, where devices need a shared way to find each other and a shared way to be controlled by agents. Device Connect provides this communication protocol between agents and devices, and standardizes how devices from different vendors advertise themselves and exchange structured messages, so both peer devices and AI agents can discover and invoke them through the same driver model. You'll use a Raspberry Pi 5 as the example primary edge device, but the same flow works with another device or with your development machine acting as a simulated device.

learning_objectives:
- Understand Device Connect Edge SDK primitives
- Set up a Python environment for Device Connect with no hardware required
- Build two simulated devices
- Set up a Python environment for Device Connect on an example edge device and a development machine
- Build two device runtimes, with the primary sensor runtime shown on a Raspberry Pi 5
- Use the Device Connect agent tools to discover both devices on the mesh and invoke their RPCs

prerequisites:
- Basic familiarity with Python and the command line
- A Raspberry Pi 5, another Linux device, or your development machine to use as the example primary device
- A development machine on the same local network if you run the example across two machines

author:
- Kavya Sri Chennoju
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ layout: learningpathall

Arm processors sit at the heart of a remarkable range of systems, from Cortex-M microcontrollers in industrial sensors, to Cortex-A boards driving robots and appliances, to Neoverse servers in the cloud. Many edge applications need these devices to cooperate: a sensor publishes a reading, a supervisor reacts, a controller adjusts an actuator. The obvious way to wire that up is through a central broker or a cloud service, but both add latency, operational overhead, and a single point of failure you may not want in a lab, a vehicle, or a factory cell.

Direct device-to-device (D2D) communication sidesteps that. Devices on the same local network discover each other, exchange typed events, and call each other's functions directly, with no broker, no registry, and no cloud round-trip. It is a good fit for:
Direct device-to-device (D2D) communication sidesteps that. Devices on the same local network discover each other, exchange typed events, and call each other's functions directly, with no broker, no registry, and no cloud round-trip. This Learning Path uses a Raspberry Pi 5 as the example primary device because it is an Arm-based Linux system that can run the same Python runtime and Device Connect SDK used by larger edge devices. D2D is a good fit for:

- prototyping sensor networks and local automation flows
- small fleets (roughly 50-100 devices) on a shared network
Expand All @@ -33,7 +33,7 @@ In D2D mode, every participant is a peer. Each device runtime joins the same pub

```
┌──────────────────────────────────────────────┐
Sensor device
Raspberry Pi 5 sensor device
│ - device_id: sensor-001 │
│ - @rpc get_reading │
│ - @emit reading_ready ─┐ │
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,25 @@ weight: 4
layout: learningpathall
---

In this section you'll build two simulated devices on the same mesh:
In this section you'll build two device runtimes on the same mesh, with the Raspberry Pi 5 as the primary edge device:

- a **sensor** that publishes temperature and humidity readings on a schedule
- a **threshold monitor** that subscribes to those readings and raises an alert when the temperature crosses a configurable threshold
- a **sensor** that runs on the Raspberry Pi 5 and publishes temperature and humidity readings on a schedule
- a **threshold monitor** that runs on your development machine, subscribes to those readings, and raises an alert when the temperature crosses a configurable threshold

This mirrors a real edge scenario, a room supervisor watching environmental sensors for out-of-bounds conditions, and exercises every Device Connect primitive across two cooperating devices.

{{% notice Note %}}
This Learning Path uses a Raspberry Pi 5 as the example primary device. You can use any device that can run the Device Connect Python packages, and you can also use your development machine as a simulated device by running the sensor and monitor in separate terminals.
{{% /notice %}}

## Install uv

This walkthrough uses [uv](https://docs.astral.sh/uv/) to manage the project and its Python dependencies. uv will resolve a compatible Python interpreter, create a virtual environment, and install packages for you, so no manual `venv` or `pip` steps are needed.
This walkthrough uses [uv](https://docs.astral.sh/uv/) to manage the project and its Python dependencies. Install uv on both machines:

- the Raspberry Pi 5 or other device that runs the sensor runtime
- your development machine, which runs the monitor and the agent-tools client

uv will resolve a compatible Python interpreter, create a virtual environment, and install packages for you, so no manual `venv` or `pip` steps are needed.

{{< tabpane code=true >}}
{{< tab header="macOS or Linux" language="shell">}}
Expand All @@ -34,7 +43,7 @@ uv --version

## Create the project

Create a new project and add the Device Connect packages:
Create the same project on the sensor device and your development machine, and add the Device Connect packages:

```bash
mkdir ~/device-connect-d2d
Expand All @@ -45,9 +54,11 @@ uv add device-connect-edge device-connect-agent-tools

The [`device-connect-edge`](https://pypi.org/project/device-connect-edge/) package is the device runtime SDK. It is what turns a Python class into a live peer on the messaging mesh. The [`device-connect-agent-tools`](https://pypi.org/project/device-connect-agent-tools/) package is the client side: it lets an agent or script discover devices and invoke their RPCs. In production you might consume devices from a different client, but for this walkthrough it is the fastest way to confirm that discovery and RPC are working.

## Write a simulated sensor device
Keep both runtimes on the same local network. D2D discovery uses local network discovery, so VPNs, guest Wi-Fi isolation, or firewall rules that block local traffic can prevent devices from seeing each other. If you run everything on your development machine, open separate terminals for the sensor, monitor, and agent-tools client.

Create a file called `sensor.py`:
## Write the sensor device

On the Raspberry Pi 5, another device, or your development machine, create a file called `sensor.py`:

```python
import argparse
Expand All @@ -72,12 +83,12 @@ class SimulatedSensor(DeviceDriver):
device_type="simulated_sensor",
manufacturer="Device Connect",
model="SIM-TH-100",
description="Simulated temperature and humidity sensor",
description="Raspberry Pi 5 temperature and humidity sensor example",
)

@property
def status(self) -> DeviceStatus:
return DeviceStatus(availability="available", location="simulator")
return DeviceStatus(availability="available", location="raspberry-pi-5")

@rpc()
async def get_reading(self) -> dict:
Expand Down Expand Up @@ -120,11 +131,13 @@ This driver uses three of the decorators introduced in the overview:
- `@emit` declares `reading_ready` as an event the device publishes to the mesh
- `@periodic` runs `publish_reading` every five seconds so the sensor produces fresh data on its own

The `identity` and `status` properties are what other peers see during discovery. They are how this device advertises itself as a `simulated_sensor` with a known manufacturer, model, and availability.
The `identity` and `status` properties are what other peers see during discovery. They are how the sensor runtime advertises itself as a `simulated_sensor` with a known manufacturer, model, and availability. The readings are generated so you can focus on Device Connect behavior first; you can replace `publish_reading()` with a real sensor read later without changing the runtime structure.

If you are not using a Raspberry Pi 5, update the `description` and `location` values to match your device, for example `location="development-machine"` when you run the sensor locally.

## Write a threshold monitor device

Now create a second device that consumes the sensor's data. Create a file called `monitor.py`:
Now create a second device that consumes the sensor's data. On your development machine, create a file called `monitor.py`:

```python
import argparse
Expand Down Expand Up @@ -155,7 +168,7 @@ class ThresholdMonitor(DeviceDriver):

@property
def status(self) -> DeviceStatus:
return DeviceStatus(availability="available", location="simulator")
return DeviceStatus(availability="available", location="development-machine")

@on(event_name="reading_ready")
async def on_reading(self, device_id: str, event_name: str, payload: dict):
Expand Down Expand Up @@ -202,25 +215,25 @@ The monitor adds one primitive you haven't seen yet:

## Run the sensor and the monitor

Open two terminals in the project directory (`~/device-connect-d2d`). In terminal 1, start the sensor:
Open a terminal on the Raspberry Pi 5, another device, or your development machine in the project directory (`~/device-connect-d2d`). Start the sensor:

```bash
uv run python sensor.py --device-id sensor-001
```

In terminal 2, start the monitor with a threshold below the sensor's typical temperature range so you see alerts quickly:
On your development machine, open a terminal in the project directory (`~/device-connect-d2d`). Start the monitor with a threshold below the sensor's typical temperature range so you see alerts quickly:

```bash
uv run python monitor.py --device-id monitor-001 --threshold 27.0
```

`uv run` executes the command inside the project's managed environment, so you do not need to activate a virtual environment manually.

Within a few seconds, the monitor terminal should start printing `received ... from sensor-001` lines, and an `ALERT:` line each time the simulated temperature rises above 27.0 °C. This is the sensor invoking the monitor across the mesh through its emitted event, and you did not configure any address or pairing between them.
Within a few seconds, the monitor terminal should start printing `received ... from sensor-001` lines, and an `ALERT:` line each time the temperature rises above 27.0 degrees C. This is the sensor invoking the monitor across the mesh through its emitted event, and you did not configure any address or pairing between them.

## Query the monitor from agent tools

Open a third terminal in the project directory and run:
Open a second terminal on your development machine in the project directory and run:

```bash
uv run python - <<'PY'
Expand Down Expand Up @@ -264,4 +277,4 @@ The sensor and monitor did not know about each other before they started. They f

## Outcome

You now have a working D2D deployment where two simulated devices cooperate on the same mesh: a sensor that publishes data and a monitor that reacts to it and exposes its own state. This same driver pattern (a class, a handful of decorators, and a runtime) is how you would describe a real sensor, actuator, or monitor on the network.
You now have a working D2D deployment where an example primary device cooperates with a monitor on the same mesh: the sensor publishes data, and the monitor reacts to it and exposes its own state. This same driver pattern (a class, a handful of decorators, and a runtime) is how you would describe a real sensor, actuator, or monitor on the network.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The [`device-connect-edge`](https://pypi.org/project/device-connect-edge/) packa

You describe a device by subclassing `DeviceDriver` from `device_connect_edge.drivers`, then annotating methods and properties with primitives. The runtime wires them into discovery, pub/sub, and RPC for you.

In this Learning Path you'll use these primitives to write two cooperating drivers: a **sensor** runtime that publishes temperature and humidity readings on a schedule, and a **threshold monitor** runtime that reacts to those readings and raises alerts when a threshold is crossed. The subsections below walk through the identity, decorators, and runtime you'll use to build them, and the agent tools package you'll use to invoke them from a separate client.
In this Learning Path you'll use these primitives to write two cooperating drivers: a **sensor** runtime that publishes temperature and humidity readings from an example device on a schedule, and a **threshold monitor** runtime that reacts to those readings and raises alerts when a threshold is crossed. The instructions use a Raspberry Pi 5 for the sensor runtime, but the same code can run on another device or on your development machine. The subsections below walk through the identity, decorators, and runtime you'll use to build them, and the agent tools package you'll use to invoke them from a separate client.

### Identity and status

Expand Down Expand Up @@ -44,12 +44,12 @@ Any Python process that imports this package can find and drive devices without

## What you'll build

In the next section you will create two cooperating simulated devices on the same local network:
In the next section you will create two cooperating devices on the same local network:

- a **sensor** driver that publishes temperature and humidity readings on a schedule using `@rpc`, `@emit`, and `@periodic`
- a **threshold monitor** driver that uses `@on` to subscribe to the sensor's readings, emits its own `alert_raised` event when a reading crosses a threshold, and exposes the alert history through an `@rpc` method
- a **sensor** driver that runs on a Raspberry Pi 5, another device, or your development machine and publishes temperature and humidity readings on a schedule using `@rpc`, `@emit`, and `@periodic`
- a **threshold monitor** driver that runs on your development machine, uses `@on` to subscribe to the sensor's readings, emits its own `alert_raised` event when a reading crosses a threshold, and exposes the alert history through an `@rpc` method

You will run both devices as independent runtimes on one machine and watch the monitor react to the sensor in real time. Finally, you will use the agent tools package to discover both devices and query their RPCs from a separate terminal.
You can run the devices as independent runtimes on separate machines and watch the monitor react to the Raspberry Pi 5 sensor in real time. If you do not have a Raspberry Pi 5 available, run the sensor runtime in another terminal on your development machine. Finally, you will use the agent tools package to discover both devices and query their RPCs from a separate terminal.

By the end, you will have a working D2D deployment where two devices find each other automatically and communicate through typed events and RPCs. This is the same pattern you would use to model a real sensor and a real supervisor on an edge network.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
---
title: Deploy multi-network device meshes using Device Connect server and NATS

description: Connect devices and AI agents across networks using Device Connect server. Learn to provision NATS credentials, commission devices, manage persistent registry, and orchestrate multi-network IoT fleets with secure authentication.
description: Connect an example edge device, secondary devices, and AI agents across networks using Device Connect server. Learn to provision NATS credentials, commission devices, manage persistent registry, and orchestrate multi-network IoT fleets with secure authentication.
minutes_to_complete: 30

who_is_this_for: This Learning Path is for developers who have completed the Device-to-device Learning Path and want to add a server layer to their Device Connect mesh. You'll learn to use persistent registry, distributed state, and security features (commissioning, ACLs) to operate a multi-network fleet. If you're new to Device Connect, start with the device-to-device Learning Path first.

learning_objectives:
- Understand what the Device Connect server adds on top of the edge SDK and when you'd reach for it
- Provision a hosted tenant on the Device Connect portal and download per-device NATS credentials
- Commission two simulated devices against your tenant using the credentials the portal issues
- Commission an example primary device and a secondary device against your tenant using the credentials the portal issues
- Discover and invoke commissioned devices from a Python client using `device-connect-agent-tools`
- Connect a Strands AI agent to the same tenant

prerequisites:
- Complete the [Device-to-device Learning Path](/learning-paths/embedded-and-microcontrollers/device-connect-d2d/) to understand Device Connect edge SDK basics
- An account on the [Device Connect portal](https://portal.deviceconnect.dev/)
- A Raspberry Pi 5, another Linux device, or your development machine to use as the example primary device
- A development machine for the secondary device and Python client
- Basic familiarity with Python and the command line

author:
Expand Down
Loading
Loading