|
|
@@ -19,6 +19,7 @@ extension CBUUIDRawValue where RawValue == String {
|
|
|
|
|
|
enum RileyLinkServiceUUID: String, CBUUIDRawValue {
|
|
|
case main = "0235733B-99C5-4197-B856-69219C2A3845"
|
|
|
+ case battery = "180F"
|
|
|
}
|
|
|
|
|
|
enum MainServiceCharacteristicUUID: String, CBUUIDRawValue {
|
|
|
@@ -30,6 +31,12 @@ enum MainServiceCharacteristicUUID: String, CBUUIDRawValue {
|
|
|
case ledMode = "C6D84241-F1A7-4F9C-A25F-FCE16732F14E"
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+enum BatteryServiceCharacteristicUUID: String, CBUUIDRawValue {
|
|
|
+ case battery_level = "2A19"
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
enum RileyLinkLEDMode: UInt8 {
|
|
|
case off = 0x00
|
|
|
case on = 0x01
|
|
|
@@ -48,6 +55,9 @@ extension PeripheralManager.Configuration {
|
|
|
MainServiceCharacteristicUUID.timerTick.cbUUID,
|
|
|
MainServiceCharacteristicUUID.firmwareVersion.cbUUID,
|
|
|
MainServiceCharacteristicUUID.ledMode.cbUUID
|
|
|
+ ],
|
|
|
+ RileyLinkServiceUUID.battery.cbUUID: [
|
|
|
+ BatteryServiceCharacteristicUUID.battery_level.cbUUID
|
|
|
]
|
|
|
],
|
|
|
notifyingCharacteristics: [
|
|
|
@@ -82,6 +92,18 @@ fileprivate extension CBPeripheral {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+fileprivate extension CBPeripheral {
|
|
|
+ func getBatteryCharacteristic(_ uuid: BatteryServiceCharacteristicUUID, serviceUUID: RileyLinkServiceUUID = .battery) -> CBCharacteristic? {
|
|
|
+ guard let service = services?.itemWithUUID(serviceUUID.cbUUID) else {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ return service.characteristics?.itemWithUUID(uuid.cbUUID)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
|
|
|
extension CBCentralManager {
|
|
|
func scanForPeripherals(withOptions options: [String: Any]? = nil) {
|
|
|
@@ -90,6 +112,8 @@ extension CBCentralManager {
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
extension Command {
|
|
|
/// Encodes a command's data by validating and prepending its length
|
|
|
///
|
|
|
@@ -290,9 +314,30 @@ extension PeripheralManager {
|
|
|
throw RileyLinkDeviceError.peripheralManagerError(error)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ func readBatteryLevel(timeout: TimeInterval) throws -> String {
|
|
|
+ guard let characteristic = peripheral.getBatteryCharacteristic(.battery_level) else {
|
|
|
+ throw RileyLinkDeviceError.peripheralManagerError(.unknownCharacteristic)
|
|
|
+ }
|
|
|
+
|
|
|
+ do {
|
|
|
+ guard let data = try readValue(for: characteristic, timeout: timeout) else {
|
|
|
+ // TODO: This is an "unknown value" issue, not a timeout
|
|
|
+ throw RileyLinkDeviceError.peripheralManagerError(.timeout)
|
|
|
+ }
|
|
|
+
|
|
|
+ let battery_level = "\(data[0])"
|
|
|
+
|
|
|
+ return battery_level
|
|
|
+ } catch let error as PeripheralManagerError {
|
|
|
+ throw RileyLinkDeviceError.peripheralManagerError(error)
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
|
|
|
+
|
|
|
+
|
|
|
// MARK: - Lower-level helper operations
|
|
|
extension PeripheralManager {
|
|
|
|