Skip to content
Shiny Controls v1.0 - The Ultra Control Suite for .NET MAUI & BlazorO...M...G!

Getting Started

GitHub GitHub stars for shinyorg/obd
Downloads NuGet downloads for Shiny.Obd
Operating Systems
Android
iOS
Windows

Shiny.Obd is a .NET library for communicating with vehicles through OBD-II (On-Board Diagnostics) adapters. It uses a command-object pattern with generic return types, pluggable transports, and adapter auto-detection.

  • Command-object pattern — OBD commands are objects, not methods. Pass built-in commands or create your own for custom PIDs.
  • Generic return types — each command declares its return type (int, double, string, TimeSpan, etc.) with compile-time safety.
  • Pluggable transportsIObdTransport abstracts the communication channel. BLE, WiFi and serial (USB/UART) ship in the box; add anything else with one interface.
  • WiFi works everywhere — a WiFi adapter is a plain TCP socket, so Shiny.Obd.Wifi behaves identically on iOS, Android, Windows, Linux and macOS. No platform package, no pairing, no BLE stack.
  • Device discoveryIObdDeviceScanner finds available adapters before connecting, over any transport that supports it. BLE, WiFi and serial scanners included.
  • Adapter auto-detection — detects ELM327 vs OBDLink (STN) adapters via ATI and runs the appropriate initialization sequence.
  • Task-based async — fully async/await throughout, no Reactive Extensions required in consuming code.
  • 30+ standard commands included — speed, RPM, temperatures, pressures, throttle and pedal position, fuel level, trims, rate and system status, timing advance, engine load, odometer, distances and timers, VIN, calibration IDs, hybrid battery life and more.
  • Supported-PID discoverySupportedPidsCommand reads the mode 01 bitmask blocks so you only ever query readings the vehicle in front of you actually reports.
  • Oxygen sensors, narrowband and wideband — the measurement behind the fuel trim, with the bank/sensor layout decoded so a reading is never labelled from the wrong one.
  • EGR and EVAP — commanded position and error, purge command, and all three vapour-pressure encodings kept distinct.
  • Torque and powerEnginePower turns the percentage PIDs into newton-metres, kilowatts and horsepower.
  • Mode 06 on-board test results — the measurement each monitor took and the limits it was judged against, fully scaled, with BandPosition showing how close a passing test is to failing.
  • Diagnostic trouble codes — read stored, pending and permanent codes (modes 03/07/0A) as SAE J2012 strings, and clear them (mode 04). CAN and pre-CAN response framing are both handled.
  • Emissions monitor readiness — the full mode 01 PID 01/41 bit layout decoded for both spark and compression ignition, with IsReadyForInspection answering the question an emissions test actually asks.
  • Freeze framesAsFreezeFrame() on any mode 01 command reads the same PID out of the snapshot the ECU stored when a code was set, so you get the conditions at the moment of the fault rather than the conditions now.
  • Test without a carShiny.Obd.Emulator is an adapter. It hosts an ELM327-compatible OBD-II bus over TCP (and BLE, with one more package), with every PID, trouble code and readiness flag settable, eight vehicles whose VINs decode for real, and a looping city, highway or commute scenario to drive them — headless in a test, or behind the sample app’s UI.
Package Target Description
Shiny.Obd net10.0 Core library — commands, connection, transport abstraction
Shiny.Obd.Ble net10.0 BLE transport using Shiny.BluetoothLE
Shiny.Obd.Wifi net10.0 WiFi (TCP) transport — every platform, including iOS and Android
Shiny.Obd.Serial net10.0 Serial (USB/UART) transport — Windows, Linux, macOS, Mac Catalyst
Shiny.Obd.Emulator net10.0 Adapter emulator — be a vehicle instead of reading one, over TCP
Shiny.Obd.Emulator.Ble net10.0 BLE peripheral front-end for the emulator
Shiny.ObdNuGet package Shiny.Obd
Shiny.Obd.BleNuGet package Shiny.Obd.Ble
Shiny.Obd.SerialNuGet package Shiny.Obd.Serial
Shiny.Obd.WifiNuGet package Shiny.Obd.Wifi
Shiny.Hosting.MauiNuGet package Shiny.Hosting.Maui
using Shiny.Obd;
using Shiny.Obd.Ble;
using Shiny.Obd.Commands;
// Scan for an adapter
var scanner = new BleObdDeviceScanner(bleManager, new BleObdConfiguration
{
DeviceNameFilter = "OBDLink"
});
var cts = new CancellationTokenSource();
ObdDiscoveredDevice? selected = null;
await scanner.Scan(device =>
{
selected = device;
cts.Cancel();
}, cts.Token);
// Connect using the discovered device
var transport = new BleObdTransport(selected!, new BleObdConfiguration());
var connection = new ObdConnection(transport);
await connection.Connect();
// Execute commands
var speed = await connection.Execute(StandardCommands.VehicleSpeed); // int (km/h)
var rpm = await connection.Execute(StandardCommands.EngineRpm); // int
var vin = await connection.Execute(StandardCommands.Vin); // string
claude plugin marketplace add shinyorg/skills
claude plugin install shiny@shiny

One plugin installs all 35 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.

copilot plugin marketplace add https://github.com/shinyorg/skills
copilot plugin install shiny@shiny

One plugin installs all 35 Shiny skills. Your agent loads only the skill relevant to what you're building, so there's no cost to having them all available.

View shiny-obd Skill
┌─────────────────────────────────────────────────┐
│ Your App │
│ await connection.Execute(StandardCommands.*) │
└──────────────────────┬──────────────────────────┘
┌──────────────────────▼──────────────────────────┐
│ ObdConnection │
│ • Adapter detection (ATI probe) │
│ • Profile-based initialization │
│ • ELM327 response parsing (hex → bytes) │
│ • Error handling (NO DATA, UNABLE TO CONNECT) │
└──────────────────────┬──────────────────────────┘
┌──────────────────────▼──────────────────────────┐
│ IObdDeviceScanner ──▶ IObdTransport │
│ Discover adapters Pluggable transport layer │
│ ┌────────────────┐ ┌──────────┐ ┌──────────┐ │
│ │ BleObdTransport│ │ WifiObd │ │SerialObd │ │
│ │ (Shiny BLE) │ │ (TCP) │ │(USB/UART)│ │
│ └────────────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────┘