一键导入
shiny-obd
Generate code using Shiny.Obd, an OBD-II vehicle communication library for .NET with command-object pattern, adapter auto-detection, and BLE transport
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Generate code using Shiny.Obd, an OBD-II vehicle communication library for .NET with command-object pattern, adapter auto-detection, and BLE transport
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Guide for implementing Firebase Cloud Messaging push notifications in .NET MAUI apps using Shiny.Push.FirebaseMessaging on iOS and Android.
Generate code using Shiny.DocumentDb.Firestore.Mobile, an on-device (native) Firebase Firestore provider for Shiny.DocumentDb on iOS and Android — offline-first persistence, real-time snapshot listeners, LINQ queries, and managed Firebase Auth identity.
Generate code using Shiny.Extensions.Push, a server-side push notification dispatch library for .NET with a provider-agnostic core and transports for APNs (.p8/ES256), FCM (HTTP v1), Web Push (VAPID + RFC 8291) and WNS (Windows App SDK / Entra auth), plus Shiny.DocumentDb persistence, structured targeting, topics, interceptors, dead-token pruning, multi-app keyed registration, runtime static/dynamic (multi-tenant) configuration via IPushConfigurationProvider, and System.Diagnostics.Metrics + tracing — fully AOT/trim-safe.
Generate code using Shiny.Speech for cross-platform speech-to-text, text-to-speech, audio capture, and audio playback with pluggable cloud providers
Shiny BluetoothLE client/central operations for scanning, connecting, and communicating with BLE peripherals
Generate code for Shiny.AiConversation - a centralized AI service library for .NET MAUI apps with chat client abstraction, wake word detection, speech-to-text/text-to-speech, acknowledgement modes (None/AudioBlip/LessWordy/Full), persistent message store, optional AI chat history lookup tool, and configurable sound effects
| name | shiny-obd |
| description | Generate code using Shiny.Obd, an OBD-II vehicle communication library for .NET with command-object pattern, adapter auto-detection, and BLE transport |
| auto_invoke | true |
| triggers | ["obd","obd-ii","obd2","vehicle diagnostics","elm327","obdlink","IObdCommand","IObdConnection","IObdTransport","IObdDeviceScanner","ObdDiscoveredDevice","BleObdDeviceScanner","ObdCommand","ObdConnection","StandardCommands","vehicle speed","engine rpm","coolant temperature","throttle position","vin command","obd ble","BleObdTransport","obd adapter","obd scan","device scanner","adapter profile","Shiny.Obd","AddShinyObdBluetoothLE"] |
You are an expert in Shiny.Obd, a .NET library for communicating with vehicles through OBD-II adapters. It uses a command-object pattern with generic return types, pluggable transports (BLE first), and adapter auto-detection for ELM327 and OBDLink (STN) adapters.
Invoke this skill when the user wants to:
Shiny.Obd, Shiny.Obd.Ble, Shiny.Obd.CommandsShiny.Obd (core), Shiny.Obd.Ble (BLE transport)net10.0 (core), net10.0 (BLE)Every OBD command implements this. T is the parsed result type.
public interface IObdCommand<T>
{
string RawCommand { get; }
T Parse(byte[] data);
}
Validates mode+PID response header, strips it, and delegates to ParseData.
public abstract class ObdCommand<T> : IObdCommand<T>
{
protected ObdCommand(byte mode, byte pid);
public byte Mode { get; }
public byte Pid { get; }
public virtual string RawCommand { get; } // "{Mode:X2}{Pid:X2}"
protected abstract T ParseData(byte[] data); // data after header
}
public interface IObdConnection : IAsyncDisposable
{
bool IsConnected { get; }
Task Connect(CancellationToken ct = default);
Task Disconnect();
Task<T> Execute<T>(IObdCommand<T> command, CancellationToken ct = default);
Task<string> SendRaw(string command, CancellationToken ct = default);
}
public interface IObdTransport : IAsyncDisposable
{
bool IsConnected { get; }
Task Connect(CancellationToken ct = default);
Task Disconnect();
Task<string> Send(string command, CancellationToken ct = default);
}
public interface IObdDeviceScanner
{
Task Scan(Action<ObdDiscoveredDevice> onDeviceFound, CancellationToken ct = default);
}
Cancel the token to stop scanning. Each discovered device invokes the callback.
public class ObdDiscoveredDevice
{
public string Name { get; } // e.g. "OBDLink MX+"
public string Id { get; } // unique identifier (BLE UUID, IP, etc.)
public object NativeDevice { get; } // IPeripheral for BLE, IPEndPoint for WiFi, etc.
}
Two constructors:
ObdConnection(IObdTransport transport) — auto-detects adapter via ATIObdConnection(IObdTransport transport, IObdAdapterProfile profile) — uses explicit profile, skips detectionProperties:
DetectedAdapter — ObdAdapterInfo? with RawIdentifier (string) and Type (ObdAdapterType enum: Unknown, Elm327, ObdLink). Null when explicit profile used.Handles:
public interface IObdAdapterProfile
{
string Name { get; }
Task Initialize(IObdConnection connection, CancellationToken ct = default);
}
Built-in profiles:
Elm327AdapterProfile — ATZ, ATE0, ATL0, ATS1, ATH0, ATSP0ObdLinkAdapterProfile — extends Elm327 with STFAC, ATCAF1| Property | Type | Command | Return | Parse Formula |
|---|---|---|---|---|
VehicleSpeed | VehicleSpeedCommand | 010D | int (km/h) | A |
EngineRpm | EngineRpmCommand | 010C | int (RPM) | ((A*256)+B)/4 |
CoolantTemperature | CoolantTemperatureCommand | 0105 | int (°C) | A-40 |
ThrottlePosition | ThrottlePositionCommand | 0111 | double (%) | (A*100)/255 |
FuelLevel | FuelLevelCommand | 012F | double (%) | (A*100)/255 |
CalculatedEngineLoad | CalculatedEngineLoadCommand | 0104 | double (%) | (A*100)/255 |
IntakeAirTemperature | IntakeAirTemperatureCommand | 010F | int (°C) | A-40 |
RuntimeSinceStart | RuntimeSinceStartCommand | 011F | TimeSpan | (A*256)+B seconds |
Vin | VinCommand | 0902 | string | skip count byte, ASCII decode |
public class BleObdConfiguration
{
public string ServiceUuid { get; set; } = "FFF0";
public string ReadCharacteristicUuid { get; set; } = "FFF1";
public string WriteCharacteristicUuid { get; set; } = "FFF2";
public string? DeviceNameFilter { get; set; }
public TimeSpan CommandTimeout { get; set; } = TimeSpan.FromSeconds(10);
}
Three constructors:
BleObdTransport(IBleManager bleManager, BleObdConfiguration config) — scans for adapterBleObdTransport(IPeripheral peripheral, BleObdConfiguration config) — uses pre-discovered peripheralBleObdTransport(ObdDiscoveredDevice device, BleObdConfiguration config) — uses device from scannerUses Shiny.BluetoothLE v4 APIs:
ConnectAsync for task-based connectionNotifyCharacteristic for RX notificationsWriteCharacteristicAsync for TX writes> prompt, returns complete responsepublic class BarometricPressureCommand : ObdCommand<int>
{
public BarometricPressureCommand() : base(0x01, 0x33) { }
protected override int ParseData(byte[] data) => data[0];
}
public class ManufacturerCommand : IObdCommand<string>
{
public string RawCommand => "2101";
public string Parse(byte[] data) => BitConverter.ToString(data);
}
var transport = new BleObdTransport(bleManager, new BleObdConfiguration
{
DeviceNameFilter = "OBDLink"
});
var connection = new ObdConnection(transport);
await connection.Connect();
var speed = await connection.Execute(StandardCommands.VehicleSpeed);
var rpm = await connection.Execute(StandardCommands.EngineRpm);
var vin = await connection.Execute(StandardCommands.Vin);
var scanner = new BleObdDeviceScanner(bleManager);
var cts = new CancellationTokenSource();
ObdDiscoveredDevice? selected = null;
await scanner.Scan(device =>
{
selected = device;
cts.Cancel(); // stop after first device
}, cts.Token);
var transport = new BleObdTransport(selected!, new BleObdConfiguration());
var connection = new ObdConnection(transport);
await connection.Connect();
// In MauiProgram.cs
builder.Services.AddBluetoothLE(); // Shiny BLE v4 — namespace: Shiny
builder.Services.AddShinyObdBluetoothLE(new BleObdConfiguration
{
DeviceNameFilter = "OBD"
});
AddShinyObdBluetoothLE registers BleObdConfiguration and IObdDeviceScanner (BleObdDeviceScanner). Call AddBluetoothLE() separately for platform BLE support.
var connection = new ObdConnection(transport, new ObdLinkAdapterProfile());
await connection.Connect();
public class MyAdapterProfile : IObdAdapterProfile
{
public string Name => "MyAdapter";
public async Task Initialize(IObdConnection connection, CancellationToken ct = default)
{
await connection.SendRaw("ATZ", ct);
await Task.Delay(500, ct);
await connection.SendRaw("ATE0", ct);
await connection.SendRaw("ATSP6", ct); // force CAN 11-bit 500kbaud
}
}
public class WifiObdTransport : IObdTransport
{
public bool IsConnected { get; private set; }
public async Task Connect(CancellationToken ct = default) { /* TCP connect */ }
public Task Disconnect() { /* close socket */ }
public async Task<string> Send(string command, CancellationToken ct = default)
{
// Write command, read until '>' prompt, return response without '>'
}
public ValueTask DisposeAsync() { /* cleanup */ }
}
Async suffix (e.g. Connect, Execute, SendRaw).ObdCommand<T>.ParseData receives bytes AFTER the 2-byte mode+PID header is stripped.IObdCommand<T>.Parse receives ALL response bytes including mode+PID header.ObdConnection appends \r to all commands sent via SendRaw before passing to transport.SemaphoreSlim to serialize commands (one at a time)."41 0D 50") and multi-frame CAN ("0: 49 02 01 57 42\r1: 41 30...") formats.BleObdDeviceScanner deduplicates by peripheral UUID — each device is reported once.builder.Services.AddBluetoothLE() (namespace Shiny, no UseShiny needed in v4), then call builder.Services.AddShinyObdBluetoothLE() to register OBD BLE services.AddShinyObdBluetoothLE registers BleObdConfiguration and IObdDeviceScanner (BleObdDeviceScanner).samples/Sample.Maui/ with scan → select → dashboard flow.