Device API reference
Every method on this.env.DEVICE — GPIO, PWM, I2C, SPI, UART, KV, watchdog
This is a single-page reference of every method on this.env.DEVICE. The same surface is documented in JSDoc on node_modules/@devicesdk/core/dist/index.d.ts — your editor will surface it on hover and in completions. Use this page when you want a flat overview rather than chasing types.
Pin numbering: every supported board exposes a virtual pin 99 mapped to the onboard LED. Use it instead of chip-specific GPIOs to keep your code portable.
GPIO
await this.env.DEVICE.setGpioState(pin: number, state: "high" | "low"): Promise<void>
Drive a GPIO output. Use 99 for the onboard LED. Pico W GPIOs are 0–22, 26–28; ESP32 ranges depend on chip — see the Pico pinout and ESP32 hardware pages.
await this.env.DEVICE.getPinState(pin: number, mode: "analog" | "digital"): Promise<DeviceResponse>
Read once. Resolves with a pin_state_update event whose payload.value is "high" | "low" for digital reads or a number 0..4095 for analog (Pico ADC).
await this.env.DEVICE.configureGpioInputMonitoring(
pin: number,
enable: boolean,
pull?: "up" | "down" | "none"
): Promise<void>
Subscribe to GPIO transitions. Each transition fires a gpio_state_changed event (handled in onMessage).
PWM
await this.env.DEVICE.setPwmState(pin: number, frequency: number, dutyCycle: number): Promise<void>
dutyCycle is 0..1, not 0..100. Typical frequencies: 1000–25000 Hz for LEDs, 50 Hz for hobby servos.
I2C
await this.env.DEVICE.i2cConfigure(bus, sdaPin, sclPin, frequency?): Promise<void>
await this.env.DEVICE.i2cScan(bus: number): Promise<DeviceResponse> // → i2c_scan_result
await this.env.DEVICE.i2cWrite(bus, address, data: string[]): Promise<void>
await this.env.DEVICE.i2cRead(bus, address, bytesToRead, registerToRead?): Promise<DeviceResponse>
// → i2c_read_result
Addresses are hex strings ("0x3C"); data is an array of single-byte hex strings (["0xAE", "0xD5"]). See the I2C guide for batch writes and patterns.
SPI
await this.env.DEVICE.spiConfigure(
bus, clkPin, mosiPin, misoPin, csPin, frequency, mode: 0 | 1 | 2 | 3
): Promise<void>
await this.env.DEVICE.spiTransfer(bus, data: string[]): Promise<DeviceResponse> // full-duplex
await this.env.DEVICE.spiWrite(bus, data: string[]): Promise<void>
await this.env.DEVICE.spiRead(bus, bytesToRead): Promise<DeviceResponse>
See the SPI guide.
UART
await this.env.DEVICE.uartConfigure(
port, txPin, rxPin, baudRate,
dataBits?: 5|6|7|8, stopBits?: 1|2, parity?: "none" | "even" | "odd"
): Promise<void>
await this.env.DEVICE.uartWrite(port, data: string[]): Promise<void>
await this.env.DEVICE.uartRead(port, bytesToRead, timeoutMs?): Promise<DeviceResponse>
See the UART guide.
Addressable LEDs (WS2812 / NeoPixel — Pico)
await this.env.DEVICE.pioWs2812Configure(pin: number, numLeds: number): Promise<void>
await this.env.DEVICE.pioWs2812Update(pixels: [number, number, number][]): Promise<void>
One [r, g, b] triplet per LED. Each channel is 0–255. See the Addressable LEDs guide.
Watchdog
await this.env.DEVICE.watchdogConfigure(timeoutMs: number, enable: boolean): Promise<void>
await this.env.DEVICE.watchdogFeed(): Promise<void>
Once enabled, the watchdog cannot be disabled until reboot. Call watchdogFeed within timeoutMs or the chip hard-resets.
Onboard temperature
await this.env.DEVICE.getTemperature(): Promise<DeviceResponse> // → temperature_result
Reads the chip’s built-in sensor. Less accurate than an external sensor (BME280, DS18B20). The Discord temperature recipe uses it.
KV state
this.env.DEVICE.kv.get<T>(key: string): Promise<T | undefined>
this.env.DEVICE.kv.put<T>(key: string, value: T): Promise<void>
this.env.DEVICE.kv.delete(key: string): Promise<boolean>
Per-device key/value storage. Persists across reconnects, deploys, and reboots. Values are JSON-serialised. See the KV recipe.
Logs and state events
this.env.DEVICE.persistLog(level: string, message: string): Promise<void>
this.env.DEVICE.emitState(entityId: string, value: unknown): Promise<void>
persistLog writes a structured log entry visible in devicesdk logs --tail and the dashboard — but console.log/info/warn/error are captured automatically, so prefer those. emitState publishes telemetry to dashboard watchers and (if declared in devicesdk.ts) Home Assistant. See Emit state.
Reboot
await this.env.DEVICE.reboot(): Promise<void>
Soft-reboot the device. Don’t chain commands after this — they queue and fire on reconnect.
Lower-level escape hatches
When a typed wrapper doesn’t yet exist, you can emit raw commands:
await this.env.DEVICE.sendCommand(command: Omit<DeviceCommand, "id">): Promise<void>
await this.env.DEVICE.sendCommandAndWait<T>(command: Omit<T, "id">): Promise<DeviceResponse>
Prefer the typed methods above whenever possible.
Related
- Device entrypoints — how methods on
DeviceEntrypointconnect to this surface. - Cookbook — task-shaped recipes that use these methods.
- Error reference — what runtime errors look like.