Build Bluetooth once. Ship it everywhere.
SimpleDelphiBLE brings SimpleBLE to Delphi and Free Pascal on Windows, macOS, and Linux. Discover and connect Bluetooth peripherals, read and write GATT values, subscribe to notifications, and host local GATT services through one API, with events that reach your VCL, FMX, or Lazarus forms on the main thread.
- One cross-platform API: Keep your Bluetooth client and hosting logic the same on Windows, macOS, and Linux, in Delphi and in Lazarus.
- Native underneath: Use WinRT, CoreBluetooth, and BlueZ through one maintained stack.
- Built for real products: Act as a central or a peripheral on every supported platform.
- Commercially supported: Ship proprietary applications with commercial licensing and direct technical support from the team that builds SimpleBLE.
- Documentation: The usage guide and examples cover every API.
- Commercial support: Visit simpleble.org or email us about licensing and professional services.
- Community: Ask questions and share projects in GitHub Discussions.
- Dongl: Prototype and ship with the official SimpleBLE USB adapter.
- Contribute: Send changes to simpleble/simpleble; the development guide covers builds and tests.
Use Delphi 11 or newer, or Free Pascal 3.2.2 or newer. Install with Boss:
boss install github.com/simpleble/simpledelphibleor download a release
and add its source folder to your search path. Both include the native
SimpleBLE library for every supported platform, prebuilt in lib; ship the one
for your target next to your executable. SimpleDelphiBLE loads it on first use,
and TSimpleDelphiBLE.LibraryPath points it elsewhere.
Scan for five seconds and print what was found:
program scan;
{$APPTYPE CONSOLE}
uses
SimpleDelphiBLE;
type
TPrinter = class
procedure ScanFound(Sender: TBleAdapter; Peripheral: TBlePeripheral);
end;
procedure TPrinter.ScanFound(Sender: TBleAdapter; Peripheral: TBlePeripheral);
begin
WriteLn(Peripheral.Identifier, ' [', Peripheral.Address, '] ', Peripheral.Rssi, ' dBm');
end;
var
Adapter: TBleAdapter;
Printer: TPrinter;
begin
Adapter := TBleAdapter.GetAdapters[0];
Printer := TPrinter.Create;
Adapter.OnScanFound := Printer.ScanFound;
Adapter.ScanFor(5000);
end.An adapter has the events OnScanStart, OnScanStop, OnScanFound,
OnScanUpdated, OnPowerOn, and OnPowerOff; a peripheral has OnConnected
and OnDisconnected. In VCL, FMX, and Lazarus applications, handlers run on
the main thread, so they can update your forms directly. In console programs,
they run in order on SimpleDelphiBLE's event thread.
Use ScanStart and ScanStop when your application controls scan timing, and
ScanGetResults for the peripherals seen by the last scan. An adapter always
gives you the same TBlePeripheral object for the same device, whether it came
from an event or from a list. SimpleDelphiBLE owns adapters and peripherals, so
you never free them.
Read the battery level of a peripheral and follow its notifications:
const
BatteryService = '0000180f-0000-1000-8000-00805f9b34fb';
BatteryLevel = '00002a19-0000-1000-8000-00805f9b34fb';
procedure TBatteryMonitor.Follow(Peripheral: TBlePeripheral);
begin
Peripheral.OnDisconnected := PeripheralDisconnected;
Peripheral.Connect;
WriteLn('Battery: ', Peripheral.Read(BatteryService, BatteryLevel)[0], '%');
Peripheral.Notify(BatteryService, BatteryLevel, BatteryChanged);
end;
procedure TBatteryMonitor.BatteryChanged(Sender: TBlePeripheral; const Service, Characteristic: string;
const Data: TBytes);
begin
WriteLn('Battery: ', Data[0], '%');
end;Services lists the services, characteristics, capabilities, and descriptors
of a connected peripheral. Read, WriteRequest, and WriteCommand access
characteristic values; ReadDescriptor and WriteDescriptor access
descriptors. Notify and Indicate call your handler with each value as
TBytes, and Unsubscribe stops them. Calls like Connect and Read wait for
the device. In GUI applications, use their Async versions, such as
ConnectAsync and ReadAsync: they run the call on a worker thread and report
the result to your OnDone handler on the main thread. Failures raise an
EBleError subclass, such as EBleNotConnected, with SimpleBLE's error code
in Code, or reach OnDone as its Error.
Create a local peripheral from an adapter, add services and characteristics, then start advertising:
Host := Adapter.CreateLocalPeripheral;
Host.AddAdvertisedService(BatteryService);
Battery := Host.AddService(BatteryService).AddCharacteristic(BatteryLevel, [lcRead, lcNotify]);
Battery.SetValue(TBytes.Create(100));
Host.OnClientConnected := ClientConnected;
Host.Start;SetValue updates the stored value and publishes it to subscribers.
Characteristics have the events OnWrite, OnSubscribed, and
OnUnsubscribed, and OnReadRequest supplies a value for each read. Configure
services before Start; call Stop before changing them. Your application
owns the local peripheral: stop it, then free it.
A Dongl is a USB Bluetooth adapter made for SimpleBLE. Its backend is on by default; use the adapters of the Dongl backend:
Adapter := TBleBackend.GetDongl.GetAdapters[0];TBleConfig holds the Dongl, BlueZ, and WinRT backend settings; set them
before the first call that reaches a backend. Pairing through a Dongl happens
without the operating system: assign OnPasskeyRequest, OnPasskeyDisplay, or
OnNumericComparison on the peripheral before Connect. On Linux, a BlueZ
adapter has the same handlers plus OnPairingAuthorization, each with the
peer's address, and TBleConfig.SimpleBluez.InteractivePairing sends passkey
and numeric comparison requests to them.
On macOS and Linux, list cthreads first in your program's uses clause. Your
code can use any mode. In Lazarus's default {$mode objfpc}{$H+}, assign
handlers with @ and declare their string parameters as UnicodeString, the
type SimpleDelphiBLE uses for strings:
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}cthreads,{$ENDIF}
SimpleDelphiBLE;
procedure TBatteryMonitor.BatteryChanged(Sender: TBlePeripheral;
const Service, Characteristic: UnicodeString; const Data: TBytes);{$MODE DELPHIUNICODE} lets you write the code as in Delphi instead.
In Lazarus, use the SimpleDelphiBLEPackage.lpk runtime package that comes
with Boss and with each release. Open it with Package > Open Package File
(.lpk) and choose Use > Add to Project, or build it with
lazbuild SimpleDelphiBLEPackage.lpk and add SimpleDelphiBLEPackage as a
New Requirement in the Project Inspector. The package supplies the units,
so your project needs no search paths.
| Platform | Architectures | Compilers | Requirements |
|---|---|---|---|
| Windows 10 or newer | x86, x64 | Delphi, Free Pascal | |
| macOS 15.0 or newer | x64, arm64 | Delphi, Free Pascal | Bluetooth permission for your app |
| Linux | x64 | Delphi Enterprise or Architect, Free Pascal | BlueZ and the D-Bus library |
| Linux | arm64 | Free Pascal | BlueZ and the D-Bus library |
See Bluetooth permissions for the setup each platform needs.
SimpleDelphiBLE follows SimpleBLE's release versions. Stable releases use
X.Y.Z, and development builds of the main branch are published as
X.Y.Z-dev.N.
SimpleDelphiBLE follows the SimpleBLE license, the Business Source License 1.1 (BUSL-1.1). It is free for non-commercial use, and commercial use needs a commercial license. We offer free commercial licenses for small projects and early-stage companies: email us or leave us a message to discuss your use case. Commercial licenses carry no royalties or revenue sharing; see the licensing page for terms.
SimpleBLE is a project powered by The California Open Source Company.