rble 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +169 -0
  3. data/LICENSE.txt +21 -0
  4. data/README.md +514 -0
  5. data/exe/rble +14 -0
  6. data/ext/macos_ble/Package.swift +20 -0
  7. data/ext/macos_ble/Sources/RBLEHelper/BLEManager.swift +783 -0
  8. data/ext/macos_ble/Sources/RBLEHelper/Protocol.swift +173 -0
  9. data/ext/macos_ble/Sources/RBLEHelper/main.swift +645 -0
  10. data/ext/macos_ble/extconf.rb +73 -0
  11. data/lib/rble/backend/base.rb +181 -0
  12. data/lib/rble/backend/bluez.rb +1279 -0
  13. data/lib/rble/backend/corebluetooth.rb +653 -0
  14. data/lib/rble/backend.rb +193 -0
  15. data/lib/rble/bluez/adapter.rb +169 -0
  16. data/lib/rble/bluez/async_call.rb +85 -0
  17. data/lib/rble/bluez/async_connection_operations.rb +492 -0
  18. data/lib/rble/bluez/async_gatt_operations.rb +249 -0
  19. data/lib/rble/bluez/async_introspection.rb +151 -0
  20. data/lib/rble/bluez/dbus_connection.rb +64 -0
  21. data/lib/rble/bluez/dbus_session.rb +344 -0
  22. data/lib/rble/bluez/device.rb +86 -0
  23. data/lib/rble/bluez/event_loop.rb +153 -0
  24. data/lib/rble/bluez/gatt_operation_queue.rb +129 -0
  25. data/lib/rble/bluez/pairing_agent.rb +132 -0
  26. data/lib/rble/bluez/pairing_session.rb +212 -0
  27. data/lib/rble/bluez/retry_policy.rb +55 -0
  28. data/lib/rble/bluez.rb +33 -0
  29. data/lib/rble/characteristic.rb +237 -0
  30. data/lib/rble/cli/adapter.rb +88 -0
  31. data/lib/rble/cli/characteristic_helpers.rb +154 -0
  32. data/lib/rble/cli/doctor.rb +309 -0
  33. data/lib/rble/cli/formatters/json.rb +122 -0
  34. data/lib/rble/cli/formatters/text.rb +157 -0
  35. data/lib/rble/cli/hex_dump.rb +48 -0
  36. data/lib/rble/cli/monitor.rb +129 -0
  37. data/lib/rble/cli/pair.rb +103 -0
  38. data/lib/rble/cli/paired.rb +22 -0
  39. data/lib/rble/cli/read.rb +55 -0
  40. data/lib/rble/cli/scan.rb +88 -0
  41. data/lib/rble/cli/show.rb +109 -0
  42. data/lib/rble/cli/status.rb +25 -0
  43. data/lib/rble/cli/unpair.rb +39 -0
  44. data/lib/rble/cli/value_parser.rb +211 -0
  45. data/lib/rble/cli/write.rb +196 -0
  46. data/lib/rble/cli.rb +152 -0
  47. data/lib/rble/company_ids.rb +90 -0
  48. data/lib/rble/connection.rb +539 -0
  49. data/lib/rble/device.rb +54 -0
  50. data/lib/rble/errors.rb +317 -0
  51. data/lib/rble/gatt/uuid_database.rb +395 -0
  52. data/lib/rble/scanner.rb +219 -0
  53. data/lib/rble/service.rb +41 -0
  54. data/lib/rble/tasks/check.rake +154 -0
  55. data/lib/rble/tasks/integration.rake +242 -0
  56. data/lib/rble/tasks.rb +8 -0
  57. data/lib/rble/version.rb +5 -0
  58. data/lib/rble.rb +62 -0
  59. metadata +120 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 90ba04b80efe39ebb30779c0b4fd137e17b5f29bf472055809eecfbe21f3df6c
4
+ data.tar.gz: 8f1e6a6d96be903b4d6a781441e7e2d7d074321a15454a45c26757bcf0223f2d
5
+ SHA512:
6
+ metadata.gz: '07045286c9f44415feb3107897dca6f35a759259e2c30bab0939f93bb671afdef840d2648b0a72bc837c5d461f4e867ea484604bdfc1452a334b23c4eba6dde8'
7
+ data.tar.gz: 2f0568cb218fde698e8e98f5cf8bacf9adf3e5f1438189d9fe0f554c537198bbd9b07743d1cabfe783259a66160cedb01bb662d07a48f989f4c49b268c11fb77
data/CHANGELOG.md ADDED
@@ -0,0 +1,169 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ ## [0.7.0] - 2026-03-17
6
+
7
+ ### Fixed (Critical)
8
+
9
+ - **GATT queue was dead code** (R1) — `gatt_queue` was a private method, so `respond_to?(:gatt_queue)` always returned false and all GATT operations bypassed the serialization queue. Made `gatt_queue` public.
10
+ - **Stale subscriptions on normal disconnect** (R2) — `disconnect_device` did not clear `@subscriptions` for the device on either BlueZ or CoreBluetooth backends. This broke reconnect-resubscribe flows.
11
+
12
+ ### Fixed (High)
13
+
14
+ - **GATT queue stop stranded callers** (R3) — `GattOperationQueue#stop` cleared the queue without notifying threads blocked on `enqueue`. Now drains pending operations and unblocks callers with a `RuntimeError`.
15
+ - **GATT queue race condition** (R5) — `gatt_queue` accessor could create duplicate queues under concurrent access. Now protected by mutex.
16
+ - **`@services` thread safety** (R6) — `@services` reads/writes in `Connection` are now synchronized with `@state_mutex`.
17
+ - **CoreBluetooth busy-poll** (R8) — Replaced `sleep 0.001`/`sleep 0.01` busy-poll in `send_request` with blocking `Queue#pop(timeout:)`.
18
+ - **Value parser bounds checking** (R4) — All binary characteristic parsers now return `"malformed"` for truncated input instead of crashing.
19
+ - **`remaining_timeout` error messages** (R7) — Timeout errors now report the correct operation name instead of always saying "Connect".
20
+
21
+ ### Fixed (Medium)
22
+
23
+ - **`at_exit` connection cleanup** (R9) — Both backends now register `at_exit` hooks to disconnect all tracked connections on process exit, preventing 30s device unreachability.
24
+ - **CoreBluetooth scan state poisoning** (R12) — `start_scan` failure now resets `@scanning` to false, preventing permanent `ScanInProgressError`.
25
+ - **CLI pair security validation** (R13) — Invalid `--security` values are now rejected with a clear error message.
26
+ - **CLI write octal/hex rejection** (R14) — Integer parsing now enforces decimal (base 10) to prevent `010` being treated as octal `8`.
27
+ - **Monitor reconnect sleep** (R15) — Reconnect delay is now interruptible, responding to Ctrl+C within 100ms instead of up to 2s.
28
+
29
+ ### Fixed (Low)
30
+
31
+ - **Text formatter nil RSSI** (R17) — Shows "N/A" instead of fabricating "0 dBm" when RSSI is unknown.
32
+ - **JSON raw bytes format** (R20) — `read_value` now uses `raw_hex` (hex string) matching `monitor_value` format. **Breaking change** for JSON consumers: `raw` (integer array) is now `raw_hex` (hex string).
33
+ - **JSON write verified key** (R24) — `write_result` only includes `verified` key when verify was actually requested.
34
+ - **JSON pair/unpair edge states** (R18) — `already_paired` and `not_paired` states now produce JSON output.
35
+ - **Doctor platform guard** (R19) — Linux-specific checks are skipped on non-Linux platforms. Added `check_ruby_dbus` diagnostic.
36
+ - **32-bit UUID handling** (R21) — `normalize_char_uuid` and `normalize_key` now handle 8-character UUID inputs.
37
+ - **Deduplicated `connect_with_retry`** (R22) — `Show` now uses the shared `CharacteristicHelpers` version.
38
+ - **CoreBluetooth `subscriptions_for_connection`** (R25) — Now correctly filters by the connection's device UUID instead of returning all subscriptions.
39
+
40
+ ### Removed
41
+
42
+ - Dead `GattService` class (R23) — unused code removed.
43
+
44
+ ### Documentation
45
+
46
+ - README: Added Linux section documenting `ruby-dbus` dependency.
47
+
48
+ ### Known Issues (deferred)
49
+
50
+ - R10: `@stop_requested` in Scanner is not thread-safe under JRuby (no current impact under MRI).
51
+ - R11: Post-unsubscribe notification callbacks may still fire due to async D-Bus signal delivery.
52
+ - R16: Each connection creates two D-Bus sessions (connect-session + Connection-session). Architectural change deferred.
53
+
54
+ ## [0.6.3] - 2026-02-06
55
+
56
+ ### Fixed
57
+
58
+ - Eliminate D-Bus `on_signal` deadlock across all call sites — `on_signal` calls synchronous `AddMatch` which blocks forever when an event loop is reading the same socket
59
+ - Scan: replace per-device `subscribe_to_device_properties_for_scan` (called after event loop starts) with a single broad pathless `PropertiesChanged` match rule registered before event loop
60
+ - Connect: replace synchronous `on_signal`/`remove_match` in `async_connect` and `wait_for_services_resolved` with new `async_register_signal_handler` / `async_unregister_signal_handler` methods
61
+ - Subscribe: replace `Thread.new` + `register_signal_handler` workaround in `subscribe_characteristic` with `async_register_signal_handler` (eliminates orphaned threads)
62
+ - Cache invalidation: reorder `setup_cache_invalidation_handler` to run before event loop starts in `start_event_loop`
63
+
64
+ ### Added
65
+
66
+ - `DBusSession#async_register_signal_handler` — splits `on_signal` into local handler registration + async D-Bus `AddMatch` call, safe to call while event loop is running
67
+ - `DBusSession#async_unregister_signal_handler` — same pattern for `RemoveMatch`
68
+
69
+ ### Removed
70
+
71
+ - `subscribe_to_device_properties_for_scan` method (replaced by broad match rule)
72
+
73
+ ## [0.6.2] - 2026-02-06
74
+
75
+ ### Fixed
76
+
77
+ - `Time#iso8601` error on Ruby 3.2/3.3 in JSON monitor output (added missing `require 'time'`)
78
+ - BlueZ adapter test no longer fails in CI when D-Bus socket exists but BlueZ service is not running
79
+ - `rble doctor` no longer crashes on macOS due to unconditional `ruby-dbus` require
80
+ - macOS CI bundle install failure caused by frozen lockfile mismatch (use `install_if` for `ruby-dbus`)
81
+ - `rble adapter` help showed doubled namespace (`rble rble adapter`)
82
+ - Disabled ANSI color in CLI help output for consistent readability
83
+
84
+ ## [0.6.1] - 2026-02-06
85
+
86
+ ### Fixed
87
+
88
+ - `rble doctor` no longer crashes with `uninitialized constant RBLE::BlueZ` (added missing require)
89
+ - `rble doctor` output redesigned: compact OK/FAIL/WARN checklist with detailed errors at bottom
90
+ - `rble help` and `rble tree` show clean command names (`rble scan`, `rble adapter`) instead of internal class paths
91
+ - `rble scan` Ctrl+C reliably stops within 1 second using flag-and-wake pattern (no more potential deadlock)
92
+
93
+ ### Changed
94
+
95
+ - `ruby-dbus` is no longer a hard gemspec dependency; only required at runtime on Linux for BlueZ backend
96
+ - Gemspec metadata completed (documentation_uri, bug_tracker_uri)
97
+ - Gem description updated to be more precise and technical
98
+
99
+ ### Added
100
+
101
+ - GitHub Actions CI workflow (Ruby 3.2/3.3/3.4 on Ubuntu, Ruby 3.4 on macOS)
102
+
103
+ ## [0.6.0] - 2026-02-05
104
+
105
+ ### Added
106
+
107
+ - **CLI Tool** — `rble` command-line executable for BLE operations from the terminal
108
+ - `rble scan` — discover BLE devices with `--timeout`, `--continuous`, `--passive`, `--name`, `--rssi` filters
109
+ - `rble show <mac>` — connect and display GATT service/characteristic tree with human-readable names
110
+ - `rble status` — show Bluetooth adapter info and powered state
111
+ - `rble doctor` — diagnose 8 common Bluetooth problems with actionable fix commands
112
+ - `rble adapter list/power/discoverable/pairable/name` — manage adapter settings
113
+ - `rble pair <mac>` / `rble unpair <mac>` / `rble paired` — BLE device pairing management
114
+ - `rble read <mac> <char>` — read characteristic values with smart formatting
115
+ - `rble write <mac> <char> <value>` — write to characteristics with 8 type encoders (hex, string, uint8/16/32, int8/16/32)
116
+ - `rble monitor <mac> <char>` — subscribe and stream notifications with reconnect support
117
+ - `--json` flag on all commands for structured NDJSON output
118
+ - GATT UUID database with 175 entries (70 services, 90 characteristics, 15 descriptors) at `RBLE::GATT::UUIDDatabase`
119
+ - 15 smart value parsers for known BLE characteristic types (heart rate, battery, temperature, blood pressure, etc.)
120
+ - IEEE 11073 FLOAT/SFLOAT decoding for medical device data
121
+ - Hex dump formatter for unknown characteristic types
122
+ - PairingAgent and PairingSession infrastructure for BlueZ pairing operations
123
+ - Thor ~> 1.3 as CLI framework dependency
124
+
125
+ ## [0.5.0] - 2026-02-05
126
+
127
+ ### Added
128
+
129
+ - Passive scanning mode via `RBLE.scan(active: false)` on both backends
130
+ - `Device#manufacturer_data_bytes(company_id)` convenience method for parsing advertisement data
131
+ - RuuviTag passive scanning example script (`examples/passive_scan.rb`)
132
+ - `RBLE.warnings` flag to suppress user-facing warnings (`RBLE.warnings = false`)
133
+ - `RBLE.rble_warn` centralized warning helper with consistent `[RBLE]` prefix
134
+ - `Backend::Base#subscriptions_for_connection` method on both backends
135
+ - `connection:` parameter on all GATT methods for both backends
136
+ - CoreBluetooth error mapping expanded from 2 to 8 specific RBLE exception classes
137
+ - Platform differences documentation (`docs/PLATFORM_DIFFERENCES.md`)
138
+ - Hardware verification scripts for BLE workflows (`verify/`)
139
+ - Thread safety audit confirming all 15 shared variables are properly protected
140
+
141
+ ### Fixed
142
+
143
+ - Untracked D-Bus signal handlers causing FD leaks on session close
144
+ - CoreBluetooth `address_type` changed from hardcoded `'random'` to `nil` (accurate)
145
+ - CoreBluetooth `discover` regex now handles reversed word order in error messages
146
+
147
+ ### Removed
148
+
149
+ - Dead code: `setup_disconnect_monitoring` and `translate_dbus_error` (63 lines)
150
+
151
+ ### Changed
152
+
153
+ - All `[rble]` prefixes normalized to uppercase `[RBLE]` across all backends and trace output
154
+ - `allow_duplicates:` default changed to `nil` sentinel with conditional resolution based on `active:` parameter
155
+
156
+ ## [0.1.0] - 2026-01-23
157
+
158
+ Initial release.
159
+
160
+ ### Added
161
+
162
+ - BLE device scanning with service UUID filtering
163
+ - GATT connections with service/characteristic discovery
164
+ - Read and write characteristic values
165
+ - Subscribe to characteristic notifications
166
+ - Disconnect detection with callbacks
167
+ - Linux support via BlueZ D-Bus API
168
+ - macOS support via CoreBluetooth (Swift helper)
169
+ - Automatic macOS helper build during gem install
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 rble contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.