Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions Sources/HAP/Base/Accessory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ struct AIDGenerator: Sequence, IteratorProtocol, Codable {

open class Accessory: JSONSerializable {
public weak var device: Device?
public weak var delegate: AccessoryDelegate?

internal var aid: InstanceID = 0
public let type: AccessoryType
public let info: Service.Info
Expand Down Expand Up @@ -103,11 +105,12 @@ open class Accessory: JSONSerializable {

/// Characteristic's value was changed by controller. Used for bubbling up
/// to the device, which will notify the delegate.
open func characteristic<T>(_ characteristic: GenericCharacteristic<T>,
internal func characteristic<T>(_ characteristic: GenericCharacteristic<T>,
ofService service: Service,
didChangeValue newValue: T?) {
device?.characteristic(characteristic, ofService: service, ofAccessory: self, didChangeValue: newValue)
}
delegate?.characteristic(characteristic, ofService: service, didChangeValue: newValue)
}

public func serialized() -> [String: JSONValueType] {
[
Expand All @@ -116,3 +119,39 @@ open class Accessory: JSONSerializable {
]
}
}

/// A HAP `Characteristic` calls the methods of this delegate to report
/// set/gets from a HAP controller.
///
/// Implement this protocol in an accessory-specific object (such as a subclass
/// of a given accessory) in order to make the accessory react accordingly.
/// For example, you might want to update the value of certain characteristics
/// if the HAP controller is showing interest or makes a change.
///
public protocol AccessoryDelegate: AnyObject {
/// Characteristic's value was changed by controller. Used for notifying
func characteristic<T>(
_ characteristic: GenericCharacteristic<T>,
ofService: Service,
didChangeValue: T?)
/// Characteristic's value was observed by controller. Used for lazy updating
func characteristic<T>(
_ characteristic: GenericCharacteristic<T>,
ofService: Service,
didGetValue: T?)

/// Tells the delegate that identification of the device was requested.
///
/// When the user configures a device, there might be multiple similar
/// devices. In order to identify the individual device, HAP
/// accommodates for an identification event. When possible, you should
/// make the physical device emit sound and/or light for the user to be
/// able to identify the device.
func didRequestIdentification()

}

public extension AccessoryDelegate {
// Default implementation ignores the request
func didRequestIdentification() { }
}
27 changes: 24 additions & 3 deletions Sources/HAP/Base/Characteristic.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ protocol Characteristic: class, JSONSerializable {
var iid: InstanceID { get set }
var type: CharacteristicType { get }
var permissions: [CharacteristicPermission] { get }
func getValue() -> JSONValueType?
func jsonValue() -> JSONValueType?
func getValue(fromChannel: Channel?) -> JSONValueType?
func setValue(_: Any?, fromChannel: Channel?) throws
var description: String? { get }
var format: CharacteristicFormat? { get }
Expand All @@ -41,7 +42,7 @@ extension Characteristic {

if permissions.contains(.read) {
// TODO: fixit
serialized["value"] = getValue() ?? 0 //NSNull()
serialized["value"] = jsonValue() ?? 0 //NSNull()
}

if let description = description { serialized["description"] = description }
Expand Down Expand Up @@ -89,13 +90,33 @@ public class GenericCharacteristic<T: CharacteristicValueType>: Characteristic,
if let device = service?.accessory?.device {
device.fireCharacteristicChangeEvent(self)
}
if let service = self.service,
let accessory = service.accessory,
let device = accessory.device {
device.characteristic(self,
ofService: service,
ofAccessory: accessory,
didChangeValue: _value)
}
}
}

func getValue() -> JSONValueType? {
func jsonValue() -> JSONValueType? {
value?.jsonValueType
}

// Get Value for HAP controller
func getValue(fromChannel channel: Channel?) -> JSONValueType? {
let currentValue = _value
DispatchQueue.main.async { [weak self] in
if let self = self, let service = self.service {
service.accessory?.delegate?.characteristic(self, ofService: service, didGetValue: currentValue)
}
}
return jsonValue()
}

// Set Value by HAP controller
func setValue(_ newValue: Any?, fromChannel channel: Channel?) throws {
switch newValue {
case let some?:
Expand Down
1 change: 1 addition & 0 deletions Sources/HAP/Base/Info.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ extension Service {
if characteristic === identify {
if let accessory = accessory {
accessory.device?.delegate?.didRequestIdentificationOf(accessory)
accessory.delegate?.didRequestIdentification()
}
}
super.characteristic(characteristic, didChangeValue: newValue)
Expand Down
2 changes: 1 addition & 1 deletion Sources/HAP/Endpoints/characteristics().swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func characteristics(device: Device, channel: Channel, request: HTTPRequest) ->
}

var value: Protocol.Value?
switch characteristic.getValue() {
switch characteristic.getValue(fromChannel: channel) {
case let _value as Double: value = .double(_value)
case let _value as Float: value = .double(Double(_value))
case let _value as UInt8: value = .int(Int(_value))
Expand Down
2 changes: 1 addition & 1 deletion Sources/HAP/Utils/Event.swift
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ struct Event {
guard let aid = char.service?.accessory?.aid else {
throw Error.characteristicWithoutAccessory
}
payload.append(["aid": aid, "iid": char.iid, "value": char.getValue() ?? NSNull()])
payload.append(["aid": aid, "iid": char.iid, "value": char.jsonValue() ?? NSNull()])
}
let serialized = ["characteristics": payload]
guard let body = try? JSONSerialization.data(withJSONObject: serialized, options: []) else {
Expand Down
4 changes: 2 additions & 2 deletions Tests/HAPTests/CharacteristicTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class CharacteristicTests: XCTestCase {

func testReadOptionalValueType() {
let characteristic = GenericCharacteristic<Bool?>(type: .identify, value: false)
guard let value = characteristic.getValue() as? Bool? else {
guard let value = characteristic.getValue(fromChannel: nil) as? Bool? else {
XCTFail("Could not get value")
return
}
Expand All @@ -36,7 +36,7 @@ class CharacteristicTests: XCTestCase {
} catch {
XCTFail("Could not set value: \(error)")
}
guard let value = characteristic.getValue() as? Bool? else {
guard let value = characteristic.getValue(fromChannel: nil) as? Bool? else {
XCTFail("Could not get value")
return
}
Expand Down
Binary file added libsodium.23.dylib
Binary file not shown.