Multiplatform IoT Dashboard for Live Telemetry Monitoring
Built with Compose Multiplatform, Clean Architecture, and MQTT
- Dashboard — Device list with live status, connection chips, signal trace
- Device Detail — Sensor readout, connection log, signal quality
- Empty State — Initial state before any device publishes
┌─────────────────────────────────────────────┐
│ Feature Layer │
│ Screen ← ViewModel ← UseCase │
├─────────────────────────────────────────────┤
│ Domain Layer │
│ Repository Interface ← Domain Models │
├─────────────────────────────────────────────┤
│ Data Layer │
│ Repository Impl → DataSource → MQTT │
└─────────────────────────────────────────────┘
- MVI — Unidirectional data flow with
StateFlow - Package by feature — Dashboard, DeviceDetail
- Clean separation — No framework leaks between layers
| Category | Library |
|---|---|
| UI | Compose Multiplatform + Material 3 |
| ViewModel | AndroidX ViewModel (KMP) |
| DI | Koin |
| Networking | Ktor (MQTT over WebSocket) |
| Database | Room (KMP) |
| Navigation | Navigation 3 |
Device Pulse — A graphite instrument panel designed for long monitoring sessions
- Signal Amber (
#FFB238) — Live, attention-worthy - Signal Cyan (
#45D6C4) — Stable, nominal - Fault Red (
#FF5C5C) — Errors, faults - IBM Plex Mono — Data readouts, timestamps, topic strings
See the full spec at
specs/device-pulse-design-system.html
The dashboard connects to a public MQTT broker and subscribes to a single topic. You can send test data using MQTTX, a cross-platform MQTT client.
| Field | Value |
|---|---|
| Host | test.mosquitto.org |
| Port | 8081 |
| Protocol | WebSocket |
| Path | /mqtt |
/esteki/devices
Each message is a single sensor reading. All fields except unit and timestamp are required.
{"deviceId":"a1b2c3d4-e5f6-7890-abcd-ef1234567890","name":"Ward B — bed 4","sensorType":"temperature","value":24.6,"unit":"°C","timestamp":1720000000000,"status":"live"}
| Field | Type | Required | Description |
|---|---|---|---|
deviceId |
string | yes | Stable UUID grouping sensors under one device |
name |
string | yes | Human-readable display name |
sensorType |
string | yes | temperature, pressure, or humidity |
value |
number | yes | The numeric reading |
unit |
string | no | Override unit (defaults: °C, hPa, %RH) |
timestamp |
integer | no | Epoch ms (defaults to receive time) |
status |
string | yes | live, reconnecting, or offline |
- Open MQTTX and create a new connection
- Enter the broker settings above
- Connect, then open the Publish tab
- Set topic to
/esteki/devices - Paste a JSON payload and hit Publish
The full JSON Schema is at
specs/telemetry-payload.schema.json.
iPulse/
├── shared/ # KMP module — all UI, ViewModels, repositories
├── androidApp/ # Android entry point
├── desktopApp/ # Desktop entry point (JVM)
├── webApp/ # Web entry point (Wasm + JS)
├── iosApp/ # iOS entry point (SwiftUI)
├── publisher/ # Test MQTT publisher
└── specs/ # Design system specification
# Android
./gradlew :androidApp:assembleDebug
# Desktop
./gradlew :desktopApp:run
# Web (Wasm)
./gradlew :webApp:wasmJsBrowserDevelopmentRun
# iOS — open iosApp/ in Xcode./gradlew :shared:allTestsApache 2.0
