KOEBELT
All projects
Projects

koebelt/dash

An open-source app for drones, planes, rovers, boats, legged robots, robot arms and test benches, in seven languages, and the library that connects a board to it, released on desktop, Android, iPhone and iPad. Python scripts and AI assistants can drive the machines, with the operator in charge.

Personal projectOpen sourceFlutterEmbedded systems
One Flutter codebase: desktop, tablet and phoneReplay, sequences, arm control, the sensor wall and the phone viewsThe same app on the desktop, a tablet and a phone, built from one Flutter codebase: a recorded flight replayed with its point cloud, a survey sequence, a robot arm jogged joint by joint, the sensor wall, and the phone’s live view, controls and test bench.
RoleSole designer and engineer
StackFlutter · Dart · C++ (Arduino) · Python · Rust · ROS 2 · MAVLink · Bluetooth LE · GitHub Actions
DownloadVersion 1.4.0 · November 9, 2026
macOS.dmg · macOS 12+
Windows.exe · Windows 10+, x64
Linux.tar.gz · x64, GTK 3
Linux.tar.gz · ARM64, GTK 3
Android.apk · Android 7+
iPhone, iPadApp Store · iOS 15+

Free and open source, and it updates itself in one click from then on. The Windows installer is not code-signed yet, so SmartScreen asks once; iPhone and iPad get it from the App Store, which updates it, and Google Play comes later.

Release notes
The problem

My quadcopter, its controller and the robotic arm each needed their own way to send telemetry, take commands and stop safely, and each time I wrote it again. koebelt/dash does it once: a small library on the device describes what it is and what it measures, and one app builds the screens, the controls and the safety around it, for whatever the board turns out to be.

Constraints
  • One protocol over Wi-Fi, Bluetooth LE, USB serial and long-range radios, including LoRa links that only carry telemetry
  • The same library for Arduino boards (C++), Python, Rust with no_std, and ROS 2, checked against one set of shared test vectors
  • The device stays safe without the app: it holds, returns or lands on its own after 1.8 s without a control packet
  • One Flutter codebase for iOS, Android, macOS, Windows and Linux, with up to 8 devices connected at once
  • Flight controllers that cannot run the library (ArduPilot, PX4, Betaflight) connect as they are, over MAVLink and MSP
Decisions

Put the failsafe on the device

A phone can crash, sleep or walk out of range, so the app is never what keeps a machine safe. It sends the sticks as a steady heartbeat; the device switches to its own safe mode when the heartbeat stops, and STOP is sent three times so one lost packet cannot cancel it. A test in the app withholds the heartbeat on purpose, so the failsafe is checked before it is needed.

Let the device describe itself

On connection the device says what it is, which sensors it has, which parameters it exposes and where its camera streams are. The app shows tiles only for the channels that arrive and builds the tuning screen from the firmware's own table, so adding a sensor is one line in the firmware and no app update.

Store sequences on the device

A mission run step by step from the phone stops the moment the link drops. The app uploads the sequence instead, and the device runs it through the same handlers it uses for live control, checking its own telemetry between steps. It keeps going without the link, and the app picks up the progress when it reconnects.

Test against the real thing

Every snippet in the in-app guides is compiled against the libraries in CI, the real ArduPilot and PX4 autopilots fly sequences in simulation, and the simulated devices in the app speak the same protocol as hardware. That is how a clash between the Arduino examples and a newer ESP32 core was caught before the first release instead of by the first user.

How it works

One library on the device, one app for every machine

Your deviceYOUR CODESensors, motors, your handlerskoebelt/linkArduino · Python · Rust · ROS 2Failsafe, sequences, parametersHELLO · TELEMETRY 30 HZ · VIDEOWI-FIBLEUSBRADIOCONTROL 20 HZ, THE HEARTBEAT · STOP ×3PARAMETERS · SEQUENCES · MODESkoebelt/dashLive: HUD, 3D, map, cameraControl: sticks, jog, throttleProgram: sequencesTune: parametersReplay: recordingsiOS · Android · macOS · Windows · LinuxArduPilot · PX4 · Betaflight · TelloNo library needed: MAVLink, MSP, Tello SDK
Your code calls koebelt/link, which talks to the app over whichever link the board has. Telemetry and video go to the app; control, STOP and sequences come back. Flight controllers that cannot run the library connect as they are.

The device describes itself, the app builds the screens

WHAT THE DEVICE SENDS ON CONNECTING{"t":"hello", "kind":"drone","sensors":["GPS","IMU","BARO"],"video":[{"label":"Front"}],"seq":32}{"t":"chan","ch":[{"id":"motor_temp","axes":["M1","M2","M3","M4"]}]}{"t":"params","p":[["MAX_TILT",35,10,60]]}THE APP BUILDSKIND · DRONESticks, take-off, landSENSORS · GPSMap, track and homeSENSORS · IMUAttitude and 3D poseSENSORS · BAROAltitude chartVIDEO · FRONTCamera behind the HUDCHAN · MOTOR_TEMPA line per motorPARAMSTune screen, live chartSEQ · 32Sequences run on board
On connecting, the device says what it is, which sensors and cameras it has, which parameters it exposes and how many sequence steps it stores. The app shows only what arrives, so a new sensor is one line in the firmware and no app update.

When the link drops

LINK LOSTFLYING LIVECONTROL PACKETS · 20 HZPilot in controlFailsafe: HOLD / RTH / LANDPilot again1.8 S WITHOUT CONTROLLINK BACKSTORED SEQUENCETake offFly toFly toWaitLandAPP BACK: STEP 4 OF 5THE DEVICE RUNS EVERY STEP ITSELF; THE FAILSAFE WAITS UNTIL THE END0 S1 S2 S3 S4 S5 S6 S7 S8 S
The app sends control 20 times a second, also when the sticks are still, so silence means the link is gone. After 1.8 s of it the device switches to its own failsafe; the pilot gets control back with the link and a new mode. A sequence stored on the device keeps running through the gap, and the app shows where it got to when it reconnects.
Screens