---
title: "How do I make two devices talk to each other?"
description: "Use this.env.DEVICES[\"other\"].method() - typed RPC mediated by the runtime"
---

> Documentation Index
> Fetch the complete documentation index at: https://docs.devicesdk.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How do I make two devices talk to each other?

A sensor in one room reads the temperature; a controller in another room turns a fan on or off. Both are DeviceSDK devices in the same project. They talk to each other via the runtime - never directly over the network.

## `devicesdk.ts`

```typescript
import { defineConfig } from "@devicesdk/cli";

export default defineConfig({
  projectId: "two-room-climate",
  devices: {
sensor: {
  className: "Sensor",
  main: "./src/devices/sensor.ts",
  deviceType: "pico-w",
  wifi: { ssid: "YOUR_WIFI_SSID", password: "YOUR_WIFI_PASSWORD" },
},
controller: {
  className: "Controller",
  main: "./src/devices/controller.ts",
  deviceType: "pico-w",
  wifi: { ssid: "YOUR_WIFI_SSID", password: "YOUR_WIFI_PASSWORD" },
},
  },
});
```

After editing the `devices` block, run `devicesdk build` so `devicesdk-env.d.ts` regenerates - that's where the inter-device RPC types come from.

## `src/devices/sensor.ts`

```typescript
import { DeviceEntrypoint, type DeviceResponse } from "@devicesdk/core";

export class Sensor extends DeviceEntrypoint {
  crons = { sample: "*/1 * * * *" };

  async onCron() {
await this.env.DEVICE.getTemperature();
  }

  async onMessage(message: DeviceResponse) {
if (message.type !== "temperature_result") return;
// RPC call - typed against the controller's public methods.
await this.env.DEVICES["controller"].handleTemperature(message.payload.celsius);
  }
}
```

## `src/devices/controller.ts`

```typescript
import { DeviceEntrypoint, OnboardLED, type DeviceResponse } from "@devicesdk/core";

export class Controller extends DeviceEntrypoint {
  /**
   * Public method - callable from other devices via
   *   await this.env.DEVICES["controller"].handleTemperature(c);
   * Lifecycle hooks (onDeviceConnect, etc.) and `env`/`ctx` are *not* exposed
   * on the RPC surface; only your own public methods are.
   */
  async handleTemperature(celsius: number) {
if (celsius > 25) {
  // Turn the fan on (here represented by the onboard LED).
  await this.env.DEVICE.setGpioState(OnboardLED, "high");
  console.log(`fan on @ ${celsius}°C`);
} else if (celsius < 23) {
  await this.env.DEVICE.setGpioState(OnboardLED, "low");
  console.log(`fan off @ ${celsius}°C`);
}
  }

  async onMessage(_message: DeviceResponse) {
// The controller's own hardware events would be handled here.
  }
}
```

## What this demonstrates

- `this.env.DEVICES["other-slug"].method(arg)` is the canonical inter-device RPC.
- The slug (`"controller"`) matches the key in your `devicesdk.ts` `devices` block.
- The RPC types come from `devicesdk-env.d.ts`, regenerated by `devicesdk build`.
- The RPC is **runtime-mediated** - the sensor never opens a direct network connection to the controller. This means it works whether the two devices are on the same WiFi or on opposite sides of the planet.
- Lifecycle hooks (`onDeviceConnect`, `onMessage`, …) and the `env`/`ctx` properties are deliberately stripped from the RPC surface. Only the methods *you* define on the class are callable.

## What to do when the controller is offline

`this.env.DEVICES["controller"].handleTemperature(...)` returns a Promise that rejects if the controller is offline. Handle it explicitly - otherwise the rejection is logged but the sensor keeps trying every minute regardless.

```typescript
try {
  await this.env.DEVICES["controller"].handleTemperature(c);
} catch (err) {
  console.warn(`controller unreachable, skipping this tick: ${err instanceof Error ? err.message : err}`);
}
```

## Going further

- Add a third device - a display in a third room - that listens via `emitState` and updates an OLED.
- Persist the last-seen temperature on the controller so it can recover after a reboot.

Source: https://docs.devicesdk.com/recipes/two-devices-rpc/index.mdx
