Build IoT devices
with TypeScript
Write device firmware in TypeScript. Test locally with a simulator. Deploy to real hardware over-the-air. All from one CLI.
import { DeviceEntrypoint } from "@devicesdk/runtime";
import { Pico } from "@devicesdk/core/devices/pico";
export default class Device extends DeviceEntrypoint {
async onDeviceConnect() {
// Configure button on GPIO 14
await this.env.DEVICE.configureGpioInput(14);
// Init I2C display
const display = Pico.i2c({
bus: 0, sda_pin: 0, scl_pin: 1
});
let count = await this.env.DEVICE.kv.get<number>("count") ?? 0;
this.env.logger.info(`Count: ${count}`);
}
async onMessage(message) {
if (message.type === "gpio_state_changed") {
await this.env.DEVICE.setGpioOutput(99, 1);
await this.env.DEVICE.kv.put("count", ++this.count);
}
}
}
How it works
Four steps from idea to running hardware
Write
TypeScript with full type safety and autocomplete
Test
Local simulator with virtual hardware — no device needed
Deploy
One command pushes your code to the cloud
Connect
Flash firmware and your device runs your TypeScript
TypeScript-first hardware
Full type definitions for every hardware API. Autocomplete for GPIO pins, I2C buses, ADC channels. Catch wiring mistakes at compile time, not at 3am.
import { Pico } from "@devicesdk/core/devices/pico";
// Type-safe I2C configuration
const display = Pico.i2c({
bus: 0, // I2C bus 0 or 1
sda_pin: 0, // GPIO 0
scl_pin: 1, // GPIO 1
});
// ^ TypeError: '3' is not
// assignable to I2CBus
$ devicesdk dev
✓ Built device.ts (42ms)
▶ Starting local simulator...
✓ Simulator running at http://localhost:8181
[device] onDeviceConnect called
[device] GPIO 14 configured as input
[device] I2C bus 0 initialized
[device] Count: 0
[device] Waiting for messages..._
Test without hardware
devicesdk dev starts a local simulator with virtual GPIO, I2C, and ADC. Iterate on your code without touching a single wire.
Cloud KV storage
Every device gets a key-value store that persists across reboots and deployments. Store sensor readings, configuration, or device state — accessible from your code and the dashboard.
// Read with type safety
const ledOn = await this.env.DEVICE.kv
.get<boolean>("ledOn");
// Write — persists across reboots
await this.env.DEVICE.kv
.put("ledOn", !ledOn);
// Store sensor data
await this.env.DEVICE.kv
.put("temperature", 23.5);
await this.env.DEVICE.kv
.put("lastReading", Date.now());
// Fluent display API
await this.env.DEVICE.display
.clear()
.drawText(0, 0, `Count: ${count}`)
.drawLine(0, 16, 128, 16)
.drawCircle(64, 40, 12)
.render();
OLED from TypeScript
Draw text, shapes, and graphics on SSD1306 OLED displays with a fluent, chainable API. Preview renders in the local simulator before deploying to hardware.
Pricing
Free for hobbyists.
$3 per million messages.
No uptime charges. No hidden fees. 500 free messages daily.
View full pricing