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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +169 -0
- data/LICENSE.txt +21 -0
- data/README.md +514 -0
- data/exe/rble +14 -0
- data/ext/macos_ble/Package.swift +20 -0
- data/ext/macos_ble/Sources/RBLEHelper/BLEManager.swift +783 -0
- data/ext/macos_ble/Sources/RBLEHelper/Protocol.swift +173 -0
- data/ext/macos_ble/Sources/RBLEHelper/main.swift +645 -0
- data/ext/macos_ble/extconf.rb +73 -0
- data/lib/rble/backend/base.rb +181 -0
- data/lib/rble/backend/bluez.rb +1279 -0
- data/lib/rble/backend/corebluetooth.rb +653 -0
- data/lib/rble/backend.rb +193 -0
- data/lib/rble/bluez/adapter.rb +169 -0
- data/lib/rble/bluez/async_call.rb +85 -0
- data/lib/rble/bluez/async_connection_operations.rb +492 -0
- data/lib/rble/bluez/async_gatt_operations.rb +249 -0
- data/lib/rble/bluez/async_introspection.rb +151 -0
- data/lib/rble/bluez/dbus_connection.rb +64 -0
- data/lib/rble/bluez/dbus_session.rb +344 -0
- data/lib/rble/bluez/device.rb +86 -0
- data/lib/rble/bluez/event_loop.rb +153 -0
- data/lib/rble/bluez/gatt_operation_queue.rb +129 -0
- data/lib/rble/bluez/pairing_agent.rb +132 -0
- data/lib/rble/bluez/pairing_session.rb +212 -0
- data/lib/rble/bluez/retry_policy.rb +55 -0
- data/lib/rble/bluez.rb +33 -0
- data/lib/rble/characteristic.rb +237 -0
- data/lib/rble/cli/adapter.rb +88 -0
- data/lib/rble/cli/characteristic_helpers.rb +154 -0
- data/lib/rble/cli/doctor.rb +309 -0
- data/lib/rble/cli/formatters/json.rb +122 -0
- data/lib/rble/cli/formatters/text.rb +157 -0
- data/lib/rble/cli/hex_dump.rb +48 -0
- data/lib/rble/cli/monitor.rb +129 -0
- data/lib/rble/cli/pair.rb +103 -0
- data/lib/rble/cli/paired.rb +22 -0
- data/lib/rble/cli/read.rb +55 -0
- data/lib/rble/cli/scan.rb +88 -0
- data/lib/rble/cli/show.rb +109 -0
- data/lib/rble/cli/status.rb +25 -0
- data/lib/rble/cli/unpair.rb +39 -0
- data/lib/rble/cli/value_parser.rb +211 -0
- data/lib/rble/cli/write.rb +196 -0
- data/lib/rble/cli.rb +152 -0
- data/lib/rble/company_ids.rb +90 -0
- data/lib/rble/connection.rb +539 -0
- data/lib/rble/device.rb +54 -0
- data/lib/rble/errors.rb +317 -0
- data/lib/rble/gatt/uuid_database.rb +395 -0
- data/lib/rble/scanner.rb +219 -0
- data/lib/rble/service.rb +41 -0
- data/lib/rble/tasks/check.rake +154 -0
- data/lib/rble/tasks/integration.rake +242 -0
- data/lib/rble/tasks.rb +8 -0
- data/lib/rble/version.rb +5 -0
- data/lib/rble.rb +62 -0
- metadata +120 -0
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// MARK: - Standard JSON-RPC Error Codes
|
|
4
|
+
enum ErrorCode {
|
|
5
|
+
static let parseError = -32700 // Invalid JSON
|
|
6
|
+
static let invalidRequest = -32600 // Invalid request object
|
|
7
|
+
static let methodNotFound = -32601 // Method not found
|
|
8
|
+
static let invalidParams = -32602 // Invalid method parameters
|
|
9
|
+
static let internalError = -32603 // Internal error
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// MARK: - Request (Ruby -> Swift)
|
|
13
|
+
struct Request: Codable {
|
|
14
|
+
let id: Int
|
|
15
|
+
let method: String
|
|
16
|
+
let params: [String: AnyCodable]?
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// MARK: - Response (Swift -> Ruby)
|
|
20
|
+
struct Response: Codable {
|
|
21
|
+
let id: Int
|
|
22
|
+
let result: [String: AnyCodable]?
|
|
23
|
+
let error: ResponseError?
|
|
24
|
+
|
|
25
|
+
init(id: Int, result: [String: AnyCodable]? = nil, error: ResponseError? = nil) {
|
|
26
|
+
self.id = id
|
|
27
|
+
self.result = result
|
|
28
|
+
self.error = error
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static func success(id: Int, result: [String: AnyCodable]) -> Response {
|
|
32
|
+
Response(id: id, result: result, error: nil)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
static func error(id: Int, code: Int, message: String, data: [String: String]? = nil) -> Response {
|
|
36
|
+
Response(id: id, result: nil, error: ResponseError(code: code, message: message, data: data))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// MARK: - Response Error
|
|
41
|
+
struct ResponseError: Codable {
|
|
42
|
+
let code: Int
|
|
43
|
+
let message: String
|
|
44
|
+
let data: [String: String]?
|
|
45
|
+
|
|
46
|
+
init(code: Int, message: String, data: [String: String]? = nil) {
|
|
47
|
+
self.code = code
|
|
48
|
+
self.message = message
|
|
49
|
+
self.data = data
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// MARK: - Event (Swift -> Ruby, asynchronous notifications)
|
|
54
|
+
struct Event: Codable {
|
|
55
|
+
let method: String
|
|
56
|
+
let params: [String: AnyCodable]
|
|
57
|
+
|
|
58
|
+
init(method: String, params: [String: AnyCodable]) {
|
|
59
|
+
self.method = method
|
|
60
|
+
self.params = params
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// MARK: - AnyCodable Type-Erased Wrapper
|
|
65
|
+
/// A type-erased Codable wrapper that handles common JSON types:
|
|
66
|
+
/// String, Int, Double, Bool, Array, Dictionary, and null
|
|
67
|
+
struct AnyCodable: Codable {
|
|
68
|
+
let value: Any
|
|
69
|
+
|
|
70
|
+
init(_ value: Any) {
|
|
71
|
+
self.value = value
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
init(from decoder: Decoder) throws {
|
|
75
|
+
let container = try decoder.singleValueContainer()
|
|
76
|
+
|
|
77
|
+
if container.decodeNil() {
|
|
78
|
+
value = NSNull()
|
|
79
|
+
} else if let bool = try? container.decode(Bool.self) {
|
|
80
|
+
value = bool
|
|
81
|
+
} else if let int = try? container.decode(Int.self) {
|
|
82
|
+
value = int
|
|
83
|
+
} else if let double = try? container.decode(Double.self) {
|
|
84
|
+
value = double
|
|
85
|
+
} else if let string = try? container.decode(String.self) {
|
|
86
|
+
value = string
|
|
87
|
+
} else if let array = try? container.decode([AnyCodable].self) {
|
|
88
|
+
value = array.map { $0.value }
|
|
89
|
+
} else if let dict = try? container.decode([String: AnyCodable].self) {
|
|
90
|
+
value = dict.mapValues { $0.value }
|
|
91
|
+
} else {
|
|
92
|
+
throw DecodingError.dataCorruptedError(
|
|
93
|
+
in: container,
|
|
94
|
+
debugDescription: "AnyCodable cannot decode value"
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
func encode(to encoder: Encoder) throws {
|
|
100
|
+
var container = encoder.singleValueContainer()
|
|
101
|
+
|
|
102
|
+
if value is NSNull {
|
|
103
|
+
try container.encodeNil()
|
|
104
|
+
} else if let bool = value as? Bool {
|
|
105
|
+
try container.encode(bool)
|
|
106
|
+
} else if let int = value as? Int {
|
|
107
|
+
try container.encode(int)
|
|
108
|
+
} else if let double = value as? Double {
|
|
109
|
+
try container.encode(double)
|
|
110
|
+
} else if let string = value as? String {
|
|
111
|
+
try container.encode(string)
|
|
112
|
+
} else if let array = value as? [Any] {
|
|
113
|
+
try container.encode(array.map { AnyCodable($0) })
|
|
114
|
+
} else if let dict = value as? [String: Any] {
|
|
115
|
+
try container.encode(dict.mapValues { AnyCodable($0) })
|
|
116
|
+
} else {
|
|
117
|
+
throw EncodingError.invalidValue(
|
|
118
|
+
value,
|
|
119
|
+
EncodingError.Context(
|
|
120
|
+
codingPath: encoder.codingPath,
|
|
121
|
+
debugDescription: "AnyCodable cannot encode value of type \(type(of: value))"
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// MARK: - AnyCodable Convenience Extensions
|
|
129
|
+
extension AnyCodable: ExpressibleByStringLiteral {
|
|
130
|
+
init(stringLiteral value: String) {
|
|
131
|
+
self.value = value
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
extension AnyCodable: ExpressibleByIntegerLiteral {
|
|
136
|
+
init(integerLiteral value: Int) {
|
|
137
|
+
self.value = value
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
extension AnyCodable: ExpressibleByFloatLiteral {
|
|
142
|
+
init(floatLiteral value: Double) {
|
|
143
|
+
self.value = value
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
extension AnyCodable: ExpressibleByBooleanLiteral {
|
|
148
|
+
init(booleanLiteral value: Bool) {
|
|
149
|
+
self.value = value
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
extension AnyCodable: ExpressibleByArrayLiteral {
|
|
154
|
+
init(arrayLiteral elements: Any...) {
|
|
155
|
+
self.value = elements
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
extension AnyCodable: ExpressibleByDictionaryLiteral {
|
|
160
|
+
init(dictionaryLiteral elements: (String, Any)...) {
|
|
161
|
+
var dict: [String: Any] = [:]
|
|
162
|
+
for (key, value) in elements {
|
|
163
|
+
dict[key] = value
|
|
164
|
+
}
|
|
165
|
+
self.value = dict
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
extension AnyCodable: ExpressibleByNilLiteral {
|
|
170
|
+
init(nilLiteral: ()) {
|
|
171
|
+
self.value = NSNull()
|
|
172
|
+
}
|
|
173
|
+
}
|