SimpleBLE Ruby
A Ruby gem providing enterprise-grade, cross-platform Bluetooth Low Energy (BLE) functionality through Ruby bindings for the SimpleBLE C++ library. Delivers production-ready BLE scanning, device connection, and GATT operations.
๐ Quick Start
gem install simpleble
require 'simpleble'
# Check if Bluetooth is available
SimpleBLE.bluetooth_enabled? # => true
# Get available Bluetooth adapters
adapters = SimpleBLE.adapters
adapter = adapters.first
puts adapter.identifier # => "Default Adapter [uuid]"
# Quick scan for BLE devices (5 second timeout)
devices = SimpleBLE.scan(5000)
puts "Found #{devices.length} BLE devices!"
# Advanced scanning with adapter control
adapter.scan_for(3000) # Scan for 3 seconds
peripherals = adapter.scan_results
peripherals.each do |device|
puts "Device: #{device.identifier} (#{device.address})"
end
โจ Features
๐ Cross-Platform Support
- macOS - CoreBluetooth framework integration
- Linux - DBus/BlueZ backend support
- Windows - WinRT Bluetooth APIs (ready for testing)
๐ BLE Operations
- โ Adapter discovery & identifiers
- โ Bluetooth enabled check
- โ Device scanning (blocking scan_for + continuous start/stop)
- โ Peripheral information (identifier, address, RSSI, TX power, MTU, address_type)
- โ Connection lifecycle (connect, disconnect, paired?, unpair)
- โ Paired peripherals access
- โ GATT service & characteristic enumeration with capabilities
- โ Characteristic read/write operations (request & command modes)
- โ Descriptor read/write operations
- โ Manufacturer data & advertisement parsing
- ๐ง Notifications/Indications (callback support planned)
๐๏ธ Current State
- โ Core C extension foundation & memory management for adapters/peripherals
- โ Exception hierarchy & native error mapping (scan/connection/characteristic errors)
- โ Cross-platform build scripts (macOS/Linux/Windows all working)
- โ Comprehensive adapter & peripheral API implemented
- โ GATT operations layer with service/characteristic/descriptor access
- โ Ruby-friendly API with helper methods and convenience features
- ๐ง Expanded test coverage (integration tests gated by hardware)
- ๐ง Notification/indication callback support
๐ ๏ธ Installation
Prerequisites
macOS:
- Xcode command line tools:
xcode-select --install
Linux:
# Ubuntu/Debian
sudo apt-get install build-essential libdbus-1-dev cmake
# Red Hat/CentOS
sudo yum install gcc-c++ dbus-devel cmake
Windows:
- Visual Studio Build Tools
- Windows SDK
- CMake
Install the Gem
gem install simpleble
Or add to your Gemfile:
gem 'simpleble'
๐ API Documentation
Module-Level Methods
# Check Bluetooth availability
SimpleBLE.bluetooth_enabled? # => true/false
# Get all adapters (convenience method)
SimpleBLE.adapters # => [Adapter, ...]
# Quick scan with first available adapter
SimpleBLE.scan(timeout_ms) # => [Peripheral, ...]
Adapter Management
# Get all available Bluetooth adapters
adapters = SimpleBLE::Adapter.get_adapters
adapter = adapters.first
# Adapter information
adapter.identifier # => "Default Adapter [uuid]"
adapter.address # => "XX:XX:XX:XX:XX:XX" (or UUID on macOS)
# Scanning operations
adapter.scan_start # Start continuous scan
adapter.scan_stop # Stop scanning
adapter.scan_for(timeout_ms) # Scan for specific duration
adapter.scan_active? # => true/false
adapter.scan_results # => [Peripheral, ...]
adapter.paired_peripherals # => [Peripheral, ...] - Previously paired devices
Peripheral Operations
devices = SimpleBLE.scan(5000)
device = devices.first
# Basic information
device.identifier # Device name or identifier
device.address # MAC address or UUID
device.rssi # Signal strength in dBm
device.tx_power # Advertised TX power in dBm
device.mtu # Maximum transmission unit
device.address_type # Address type (public/random/unspecified)
# Connection management
device.connectable? # Whether device accepts connections
device.connected? # Current connection status
device.paired? # Whether device is paired
device.connect # Establish connection
device.disconnect # Close connection
device.unpair # Remove pairing
# GATT operations (requires connection)
services = device.services # => [{"uuid" => "...", "characteristics" => [...]}]
data = device.read_characteristic(service_uuid, char_uuid)
device.write_characteristic_request(service_uuid, char_uuid, data)
device.write_characteristic_command(service_uuid, char_uuid, data)
# Descriptor operations
desc_data = device.read_descriptor(service_uuid, char_uuid, desc_uuid)
device.write_descriptor(service_uuid, char_uuid, desc_uuid, data)
# Advertisement data
mfg_data = device.manufacturer_data # => [{"manufacturer_id" => 123, "data" => "..."}]
# Helper methods
device.name # Friendly name (identifier or address)
device.to_s # "Name (address)"
device.has_data? # Check if device has valid data
device.rssi_s # "-67 dBm"
device.address_type_s # "Public" / "Random" / "Unspecified"
๐งช Interactive Testing
Launch an interactive Ruby session with SimpleBLE loaded:
ruby -rsimpleble -e "
adapters = SimpleBLE.adapters
adapter = adapters.first
puts 'Try: SimpleBLE.scan(3000)'
require 'irb'; IRB.start
"
๐ง Development
Building from Source
# Clone repository with submodules
git clone --recurse-submodules https://github.com/twilightcoders/ruby-simpleble.git
cd ruby-simpleble
# Or if you already cloned without submodules:
git submodule update --init --recursive
# Install dependencies
bundle install
# Compile the C extension
rake compile
# Run tests
rake test
Updating SimpleBLE Vendor Library
# Update to latest SimpleBLE upstream
git submodule update --remote vendor/simpleble
# Verify the update
git submodule status
Running Tests
# Run all tests
bundle exec rspec
# Run with coverage
bundle exec rspec --format documentation
# Test specific functionality
bundle exec rspec spec/simpleble_spec.rb
๐๏ธ Architecture
SimpleBLE Ruby uses a layered architecture:
Ruby Application
โ
SimpleBLE Ruby Wrapper (lib/simpleble.rb)
โ
C Extension Layer (ext/simpleble/)
โ
SimpleBLE C++ Library (vendor/simpleble/)
โ
Platform BLE APIs (CoreBluetooth/BlueZ/WinRT)
Key Components
- Ruby API Layer: Clean, idiomatic Ruby interface
- C Extension: Memory-safe Ruby โ C++ bridge
- C++ Wrapper: Type-safe interface to SimpleBLE library
- SimpleBLE Library: Cross-platform BLE abstraction
- Platform Backends: OS-specific BLE implementations
๐ฆ Status Summary
Area | Implemented | Notes |
---|---|---|
Adapter enumeration | โ | identifier, address |
Scanning (start/stop/for) | โ | Timed & continuous |
Scan results retrieval | โ | Returns Peripheral objects |
Peripheral basic info | โ | identifier, address, RSSI, TX power, MTU, address_type |
Connection lifecycle | โ | connect, disconnect, paired?, unpair |
Paired peripherals | โ | Access to previously paired devices |
Services/Characteristics | โ | Full enumeration with capabilities |
Characteristic I/O | โ | Read/write with request & command modes |
| Descriptor I/O | โ | Read/write operations | | Manufacturer data | โ | Advertisement parsing | | Windows support | โ | All platforms working | | Test coverage | ๐ง | Expanding beyond placeholders | | Documentation accuracy | โ | Reflects current API |
Roadmap
- Notification/indication callbacks with GC-safe storage
- Hardware-gated integration test suite expansion
- Performance optimizations and memory usage analysis
- Precompiled native gem variants (later)
๐ Compatibility
Platform | Status | Backend | Notes |
---|---|---|---|
macOS | โ Working | CoreBluetooth | Full support, production tested |
Linux | โ Working | BlueZ/DBus | CI passing, production ready |
Windows | โ Working | WinRT | CI passing, production ready |
โก CI Performance & Caching
Building the SimpleBLE core for every Ruby version slows the matrix. Two knobs:
-
SIMPLEBLE_PREBUILT_LIB
โ point to a prebuilt static library (and headers) so only the Ruby bridge compiles. -
SIMPLEBLE_REUSE_OBJECTS=1
โ skipmake clean
and reuse previously cached.o
files.
Prebuilt Flow
Create a warmup job that builds once, packages tmp_flat/*.o
(or a consolidated libsimpleble_core.a
you produce via ar
), uploads as an artifact, then matrix jobs download and set:
env:
SIMPLEBLE_PREBUILT_LIB: path/to/libsimpleble_core.a
extconf.rb
detects this and links only the Ruby layer.
Object Reuse Flow
Use actions/cache
keyed on OS + hash of vendor/simpleble/**
:
- uses: actions/cache@v4
with:
path: ext/simpleble/tmp_flat
key: simpleble-obj-${{ runner.os }}-${{ hashFiles('vendor/simpleble/**') }}
Then set SIMPLEBLE_REUSE_OBJECTS: 1
so the compile task skips cleaning.
Variables Summary
Var | Purpose |
---|---|
SIMPLEBLE_PREBUILT_LIB |
Path to prebuilt SimpleBLE static lib to link instead of compiling sources |
SIMPLEBLE_REUSE_OBJECTS |
If 1 , do not run make clean ; rely on cached object files |
Regenerate caches whenever the SimpleBLE submodule changes.
๐ค Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Run tests:
bundle exec rspec
- Commit your changes (
git commit -am 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
๐ License
This project is licensed under the MIT License - see the LICENSE.txt file for details.
๐ Acknowledgments
- SimpleBLE Library - The excellent cross-platform BLE library this gem wraps
- OpenBluetoothToolbox - For creating and maintaining SimpleBLE