|
45 | 45 | - **Windows** - WinRT Bluetooth APIs *(ready for testing)* |
46 | 46 |
|
47 | 47 | ### 🔍 **BLE Operations** |
48 | | -- ✅ **Bluetooth adapter discovery and management** |
49 | | -- ✅ **Device scanning with timeout control** |
50 | | -- ✅ **Real-time device discovery** |
51 | | -- ✅ **RSSI and connection status monitoring** |
52 | | -- 🚧 **GATT service/characteristic operations** *(in development)* |
53 | | -- 🚧 **Device connection and bonding** *(in development)* |
54 | | - |
55 | | -### 🏗️ **Production Ready** |
56 | | -- ✅ **Memory-safe C extension with proper lifecycle management** |
57 | | -- ✅ **Comprehensive exception hierarchy for error handling** |
58 | | -- ✅ **Thread-safe operations** |
59 | | -- ✅ **RSpec test suite with 84%+ coverage** |
60 | | -- ✅ **Cross-platform build system** |
| 48 | +- ✅ Adapter discovery & identifiers |
| 49 | +- ✅ Bluetooth enabled check |
| 50 | +- ✅ Device scanning (blocking scan_for + continuous start/stop) |
| 51 | +- ✅ Peripheral information (identifier, address, RSSI, TX power, MTU, address_type) |
| 52 | +- ✅ Connection lifecycle (connect, disconnect, paired?, unpair) |
| 53 | +- ✅ Paired peripherals access |
| 54 | +- ✅ GATT service & characteristic enumeration with capabilities |
| 55 | +- ✅ Characteristic read/write operations (request & command modes) |
| 56 | +- ✅ Descriptor read/write operations |
| 57 | +- ✅ Manufacturer data & advertisement parsing |
| 58 | +- 🚧 Notifications/Indications *(callback support planned)* |
| 59 | + |
| 60 | +### 🏗️ **Current State** |
| 61 | +- ✅ Core C extension foundation & memory management for adapters/peripherals |
| 62 | +- ✅ Exception hierarchy & native error mapping (scan/connection/characteristic errors) |
| 63 | +- ✅ Cross-platform build scripts (macOS/Linux/Windows all working) |
| 64 | +- ✅ Comprehensive adapter & peripheral API implemented |
| 65 | +- ✅ GATT operations layer with service/characteristic/descriptor access |
| 66 | +- ✅ Ruby-friendly API with helper methods and convenience features |
| 67 | +- 🚧 Expanded test coverage (integration tests gated by hardware) |
| 68 | +- 🚧 Notification/indication callback support |
61 | 69 |
|
62 | 70 | ## 🛠️ Installation |
63 | 71 |
|
@@ -123,20 +131,50 @@ adapter.scan_stop # Stop scanning |
123 | 131 | adapter.scan_for(timeout_ms) # Scan for specific duration |
124 | 132 | adapter.scan_active? # => true/false |
125 | 133 | adapter.scan_results # => [Peripheral, ...] |
| 134 | +adapter.paired_peripherals # => [Peripheral, ...] - Previously paired devices |
126 | 135 | ``` |
127 | 136 |
|
128 | | -### Peripheral Information |
| 137 | +### Peripheral Operations |
129 | 138 |
|
130 | 139 | ```ruby |
131 | 140 | devices = SimpleBLE.scan(5000) |
132 | 141 | device = devices.first |
133 | 142 |
|
| 143 | +# Basic information |
134 | 144 | device.identifier # Device name or identifier |
135 | 145 | device.address # MAC address or UUID |
136 | | -device.rssi # Signal strength |
137 | | -device.address_type # Address type (public/random) |
| 146 | +device.rssi # Signal strength in dBm |
| 147 | +device.tx_power # Advertised TX power in dBm |
| 148 | +device.mtu # Maximum transmission unit |
| 149 | +device.address_type # Address type (public/random/unspecified) |
| 150 | + |
| 151 | +# Connection management |
138 | 152 | device.connectable? # Whether device accepts connections |
139 | 153 | device.connected? # Current connection status |
| 154 | +device.paired? # Whether device is paired |
| 155 | +device.connect # Establish connection |
| 156 | +device.disconnect # Close connection |
| 157 | +device.unpair # Remove pairing |
| 158 | + |
| 159 | +# GATT operations (requires connection) |
| 160 | +services = device.services # => [{"uuid" => "...", "characteristics" => [...]}] |
| 161 | +data = device.read_characteristic(service_uuid, char_uuid) |
| 162 | +device.write_characteristic_request(service_uuid, char_uuid, data) |
| 163 | +device.write_characteristic_command(service_uuid, char_uuid, data) |
| 164 | + |
| 165 | +# Descriptor operations |
| 166 | +desc_data = device.read_descriptor(service_uuid, char_uuid, desc_uuid) |
| 167 | +device.write_descriptor(service_uuid, char_uuid, desc_uuid, data) |
| 168 | + |
| 169 | +# Advertisement data |
| 170 | +mfg_data = device.manufacturer_data # => [{"manufacturer_id" => 123, "data" => "..."}] |
| 171 | + |
| 172 | +# Helper methods |
| 173 | +device.name # Friendly name (identifier or address) |
| 174 | +device.to_s # "Name (address)" |
| 175 | +device.has_data? # Check if device has valid data |
| 176 | +device.rssi_s # "-67 dBm" |
| 177 | +device.address_type_s # "Public" / "Random" / "Unspecified" |
140 | 178 | ``` |
141 | 179 |
|
142 | 180 | ## 🧪 Interactive Testing |
@@ -221,34 +259,70 @@ Platform BLE APIs (CoreBluetooth/BlueZ/WinRT) |
221 | 259 | - **SimpleBLE Library**: Cross-platform BLE abstraction |
222 | 260 | - **Platform Backends**: OS-specific BLE implementations |
223 | 261 |
|
224 | | -## 🚦 Current Status |
225 | | - |
226 | | -### ✅ **Completed** |
227 | | -- Cross-platform build system and C extension compilation |
228 | | -- Bluetooth adapter discovery and management |
229 | | -- BLE device scanning with timeout control |
230 | | -- Memory-safe Ruby object lifecycle management |
231 | | -- Comprehensive test suite and documentation |
232 | | - |
233 | | -### 🚧 **In Development** |
234 | | -- GATT service and characteristic operations |
235 | | -- Device connection and disconnection |
236 | | -- Read/write/notify operations for characteristics |
237 | | -- Advanced BLE features (bonding, security, callbacks) |
238 | | - |
239 | | -### 🔮 **Planned** |
240 | | -- Asynchronous operation support with Ruby blocks |
241 | | -- Device filtering and advanced scanning options |
242 | | -- Cross-platform CI/CD pipeline |
243 | | -- Performance optimization and memory profiling |
| 262 | +### 🚦 Status Summary |
| 263 | + |
| 264 | +| Area | Implemented | Notes | |
| 265 | +|------|-------------|-------| |
| 266 | +| Adapter enumeration | ✅ | identifier, address | |
| 267 | +| Scanning (start/stop/for) | ✅ | Timed & continuous | |
| 268 | +| Scan results retrieval | ✅ | Returns Peripheral objects | |
| 269 | +| Peripheral basic info | ✅ | identifier, address, RSSI, TX power, MTU, address_type | |
| 270 | +| Connection lifecycle | ✅ | connect, disconnect, paired?, unpair | |
| 271 | +| Paired peripherals | ✅ | Access to previously paired devices | |
| 272 | +| Services/Characteristics | ✅ | Full enumeration with capabilities | |
| 273 | +| Characteristic I/O | ✅ | Read/write with request & command modes | |
| 274 | +| Descriptor I/O | ✅ | Read/write operations | |
| 275 | +| Manufacturer data | ✅ | Advertisement parsing | |
| 276 | +| Windows support | ✅ | All platforms working | |
| 277 | +| Test coverage | 🚧 | Expanding beyond placeholders | |
| 278 | +| Documentation accuracy | ✅ | Reflects current API | |
| 279 | + |
| 280 | +### Roadmap |
| 281 | +- [ ] Notification/indication callbacks with GC-safe storage |
| 282 | +- [ ] Hardware-gated integration test suite expansion |
| 283 | +- [ ] Performance optimizations and memory usage analysis |
| 284 | +- [ ] Precompiled native gem variants (later) |
244 | 285 |
|
245 | 286 | ## 📊 Compatibility |
246 | 287 |
|
247 | 288 | | Platform | Status | Backend | Notes | |
248 | 289 | |----------|---------|---------|-------| |
249 | | -| **macOS** | ✅ Working | CoreBluetooth | Full support, tested | |
250 | | -| **Linux** | 🚧 Ready | BlueZ/DBus | Build system ready, needs testing | |
251 | | -| **Windows** | 🚧 Ready | WinRT | Build system ready, needs testing | |
| 290 | +| **macOS** | ✅ Working | CoreBluetooth | Full support, production tested | |
| 291 | +| **Linux** | ✅ Working | BlueZ/DBus | CI passing, production ready | |
| 292 | +| **Windows** | ✅ Working | WinRT | CI passing, production ready | |
| 293 | + |
| 294 | +## ⚡ CI Performance & Caching |
| 295 | + |
| 296 | +Building the SimpleBLE core for every Ruby version slows the matrix. Two knobs: |
| 297 | + |
| 298 | +1. `SIMPLEBLE_PREBUILT_LIB` – point to a prebuilt static library (and headers) so only the Ruby bridge compiles. |
| 299 | +2. `SIMPLEBLE_REUSE_OBJECTS=1` – skip `make clean` and reuse previously cached `.o` files. |
| 300 | + |
| 301 | +### Prebuilt Flow |
| 302 | +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: |
| 303 | +``` |
| 304 | +env: |
| 305 | + SIMPLEBLE_PREBUILT_LIB: path/to/libsimpleble_core.a |
| 306 | +``` |
| 307 | +`extconf.rb` detects this and links only the Ruby layer. |
| 308 | + |
| 309 | +### Object Reuse Flow |
| 310 | +Use `actions/cache` keyed on OS + hash of `vendor/simpleble/**`: |
| 311 | +``` |
| 312 | +- uses: actions/cache@v4 |
| 313 | + with: |
| 314 | + path: ext/simpleble/tmp_flat |
| 315 | + key: simpleble-obj-${{ runner.os }}-${{ hashFiles('vendor/simpleble/**') }} |
| 316 | +``` |
| 317 | +Then set `SIMPLEBLE_REUSE_OBJECTS: 1` so the compile task skips cleaning. |
| 318 | + |
| 319 | +### Variables Summary |
| 320 | +| Var | Purpose | |
| 321 | +|-----|---------| |
| 322 | +| `SIMPLEBLE_PREBUILT_LIB` | Path to prebuilt SimpleBLE static lib to link instead of compiling sources | |
| 323 | +| `SIMPLEBLE_REUSE_OBJECTS` | If `1`, do not run `make clean`; rely on cached object files | |
| 324 | + |
| 325 | +Regenerate caches whenever the SimpleBLE submodule changes. |
252 | 326 |
|
253 | 327 | ## 🤝 Contributing |
254 | 328 |
|
|
0 commit comments