Skip to content

Commit 3f5a154

Browse files
committed
AccessoryDelegate to handle HAP controller Characteristic get/sets by Accessory implementations
Separate functions to obtain the value of a characteristic for a HAP server and to just get a jason formatted value. Notify device delegate when an accessory changes it's value
1 parent 83fbb3f commit 3f5a154

File tree

6 files changed

+54
-9
lines changed

6 files changed

+54
-9
lines changed

Sources/HAP/Base/Accessory.swift

+26-2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ struct AIDGenerator: Sequence, IteratorProtocol, Codable {
2727

2828
open class Accessory: JSONSerializable {
2929
public weak var device: Device?
30+
public weak var delegate: AccessoryDelegate?
31+
3032
internal var aid: InstanceID = 0
3133
public let type: AccessoryType
3234
public let info: Service.Info
@@ -103,11 +105,12 @@ open class Accessory: JSONSerializable {
103105

104106
/// Characteristic's value was changed by controller. Used for bubbling up
105107
/// to the device, which will notify the delegate.
106-
open func characteristic<T>(_ characteristic: GenericCharacteristic<T>,
108+
internal func characteristic<T>(_ characteristic: GenericCharacteristic<T>,
107109
ofService service: Service,
108110
didChangeValue newValue: T?) {
109111
device?.characteristic(characteristic, ofService: service, ofAccessory: self, didChangeValue: newValue)
110-
}
112+
delegate?.characteristic(characteristic, ofService: service, didChangeValue: newValue)
113+
}
111114

112115
public func serialized() -> [String: JSONValueType] {
113116
[
@@ -116,3 +119,24 @@ open class Accessory: JSONSerializable {
116119
]
117120
}
118121
}
122+
123+
/// A HAP `Characteristic` calls the methods of this delegate to report
124+
/// set/gets from a HAP controller.
125+
///
126+
/// Implement this protocol in an accessory-specific object (such as a subclass
127+
/// of a given accessory) in order to make the accessory react accordingly.
128+
/// For example, you might want to update the value of certain characteristics
129+
/// if the HAP controller is showing interest or makes a change.
130+
///
131+
public protocol AccessoryDelegate: class {
132+
/// Characteristic's value was changed by controller. Used for notifying
133+
func characteristic<T>(
134+
_ characteristic: GenericCharacteristic<T>,
135+
ofService: Service,
136+
didChangeValue: T?)
137+
/// Characteristic's value was observed by controller. Used for lazy updating
138+
func characteristic<T>(
139+
_ characteristic: GenericCharacteristic<T>,
140+
ofService: Service,
141+
didGetValue: T?)
142+
}

Sources/HAP/Base/Characteristic.swift

+24-3
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ protocol Characteristic: class, JSONSerializable {
1818
var iid: InstanceID { get set }
1919
var type: CharacteristicType { get }
2020
var permissions: [CharacteristicPermission] { get }
21-
func getValue() -> JSONValueType?
21+
func jsonValue() -> JSONValueType?
22+
func getValue(fromChannel: Channel?) -> JSONValueType?
2223
func setValue(_: Any?, fromChannel: Channel?) throws
2324
var description: String? { get }
2425
var format: CharacteristicFormat? { get }
@@ -41,7 +42,7 @@ extension Characteristic {
4142

4243
if permissions.contains(.read) {
4344
// TODO: fixit
44-
serialized["value"] = getValue() ?? 0 //NSNull()
45+
serialized["value"] = jsonValue() ?? 0 //NSNull()
4546
}
4647

4748
if let description = description { serialized["description"] = description }
@@ -89,13 +90,33 @@ public class GenericCharacteristic<T: CharacteristicValueType>: Characteristic,
8990
if let device = service?.accessory?.device {
9091
device.fireCharacteristicChangeEvent(self)
9192
}
93+
if let service = self.service,
94+
let accessory = service.accessory,
95+
let device = accessory.device {
96+
device.characteristic(self,
97+
ofService: service,
98+
ofAccessory: accessory,
99+
didChangeValue: _value)
100+
}
92101
}
93102
}
94103

95-
func getValue() -> JSONValueType? {
104+
func jsonValue() -> JSONValueType? {
96105
value?.jsonValueType
97106
}
98107

108+
// Get Value for HAP controller
109+
func getValue(fromChannel channel: Channel?) -> JSONValueType? {
110+
let currentValue = _value
111+
DispatchQueue.main.async { [weak self] in
112+
if let this = self, let service = this.service {
113+
service.accessory?.delegate?.characteristic(this, ofService: service, didGetValue: currentValue)
114+
}
115+
}
116+
return jsonValue()
117+
}
118+
119+
// Set Value by HAP controller
99120
func setValue(_ newValue: Any?, fromChannel channel: Channel?) throws {
100121
switch newValue {
101122
case let some?:

Sources/HAP/Endpoints/characteristics().swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func characteristics(device: Device, channel: Channel, request: HTTPRequest) ->
5656
}
5757

5858
var value: Protocol.Value?
59-
switch characteristic.getValue() {
59+
switch characteristic.getValue(fromChannel: channel) {
6060
case let _value as Double: value = .double(_value)
6161
case let _value as Float: value = .double(Double(_value))
6262
case let _value as UInt8: value = .int(Int(_value))

Sources/HAP/Utils/Event.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ struct Event {
6262
guard let aid = char.service?.accessory?.aid else {
6363
throw Error.characteristicWithoutAccessory
6464
}
65-
payload.append(["aid": aid, "iid": char.iid, "value": char.getValue() ?? NSNull()])
65+
payload.append(["aid": aid, "iid": char.iid, "value": char.jsonValue() ?? NSNull()])
6666
}
6767
let serialized = ["characteristics": payload]
6868
guard let body = try? JSONSerialization.data(withJSONObject: serialized, options: []) else {

Tests/HAPTests/CharacteristicTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class CharacteristicTests: XCTestCase {
1313

1414
func testReadOptionalValueType() {
1515
let characteristic = GenericCharacteristic<Bool?>(type: .identify, value: false)
16-
guard let value = characteristic.getValue() as? Bool? else {
16+
guard let value = characteristic.getValue(fromChannel: nil) as? Bool? else {
1717
XCTFail("Could not get value")
1818
return
1919
}
@@ -36,7 +36,7 @@ class CharacteristicTests: XCTestCase {
3636
} catch {
3737
XCTFail("Could not set value: \(error)")
3838
}
39-
guard let value = characteristic.getValue() as? Bool? else {
39+
guard let value = characteristic.getValue(fromChannel: nil) as? Bool? else {
4040
XCTFail("Could not get value")
4141
return
4242
}

libsodium.23.dylib

494 KB
Binary file not shown.

0 commit comments

Comments
 (0)