Working on tests.
This commit is contained in:
@@ -43,8 +43,55 @@ enum MQTTError: Error {
|
||||
case relay(reason: String, error: Error?)
|
||||
}
|
||||
|
||||
protocol FetchableTopic {
|
||||
associatedtype Value: BufferInitalizable
|
||||
var topic: String { get }
|
||||
}
|
||||
|
||||
extension Double: BufferInitalizable {
|
||||
|
||||
init?(buffer: inout ByteBuffer) {
|
||||
guard let string = buffer.readString(length: buffer.readableBytes) else {
|
||||
return nil
|
||||
}
|
||||
self.init(string)
|
||||
}
|
||||
}
|
||||
|
||||
//extension SetPoint: FetchableTopic {
|
||||
// typealias Value = Double
|
||||
//}
|
||||
|
||||
extension Sensor: FetchableTopic where Reading: BufferInitalizable {
|
||||
typealias Value = Reading
|
||||
}
|
||||
|
||||
extension MQTTNIO.MQTTClient {
|
||||
|
||||
func mqttSubscription(topic: String, qos: MQTTQoS = .atLeastOnce, retainAsPublished: Bool = true, retainHandling: MQTTSubscribeInfoV5.RetainHandling = .sendAlways) -> MQTTSubscribeInfoV5 {
|
||||
.init(topicFilter: topic, qos: qos, retainAsPublished: retainAsPublished, retainHandling: retainHandling)
|
||||
}
|
||||
|
||||
func fetch<Value>(
|
||||
_ subscription: MQTTSubscribeInfoV5
|
||||
) -> EventLoopFuture<Value> where Value: BufferInitalizable {
|
||||
logger.debug("Fetching data for: \(subscription.topicFilter)")
|
||||
return v5.subscribe(to: [subscription])
|
||||
.flatMap { _ in
|
||||
let promise = self.eventLoopGroup.next().makePromise(of: Value.self)
|
||||
self.addPublishListener(named: subscription.topicFilter + "-listener") { result in
|
||||
|
||||
result.mapBuffer(to: Value.self)
|
||||
.unwrap(or: MQTTError.sensor(reason: "Invalid sensor reading", error: nil))
|
||||
.fullfill(promise: promise)
|
||||
|
||||
self.logger.debug("Done fetching data for: \(subscription.topicFilter)")
|
||||
}
|
||||
|
||||
return promise.futureResult
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch a sensor state and convert it appropriately, when the sensor type is ``BufferInitializable``.
|
||||
///
|
||||
/// - Parameters:
|
||||
@@ -52,32 +99,17 @@ extension MQTTNIO.MQTTClient {
|
||||
func fetch<S>(
|
||||
sensor: Sensor<S>
|
||||
) -> EventLoopFuture<S> where S: BufferInitalizable {
|
||||
logger.debug("Fetching data for sensor: \(sensor.topic)")
|
||||
let subscription = MQTTSubscribeInfoV5.init(
|
||||
topicFilter: sensor.topic,
|
||||
qos: .atLeastOnce,
|
||||
retainAsPublished: false,
|
||||
retainHandling: .sendAlways
|
||||
)
|
||||
return v5.subscribe(to: [subscription])
|
||||
.flatMap { _ in
|
||||
let promise = self.eventLoopGroup.next().makePromise(of: S.self)
|
||||
self.addPublishListener(named: sensor.topic) { result in
|
||||
|
||||
result.mapBuffer(to: S.self)
|
||||
.unwrap(or: MQTTError.sensor(reason: "Invalid sensor reading", error: nil))
|
||||
.fullfill(promise: promise)
|
||||
|
||||
self.logger.debug("Done fetching data for sensor: \(sensor.topic)")
|
||||
}
|
||||
|
||||
return promise.futureResult
|
||||
}
|
||||
return fetch(mqttSubscription(topic: sensor.topic))
|
||||
}
|
||||
|
||||
func `set`(relay: Relay, to state: Relay.State, qos: MQTTQoS = .atLeastOnce) -> EventLoopFuture<Void> {
|
||||
func fetch(setPoint: KeyPath<Topics.SetPoints, String>, setPoints: Topics.SetPoints) -> EventLoopFuture<Double> {
|
||||
// logger.debug("Fetching data for set point: \(setPoint.topic)")
|
||||
return fetch(mqttSubscription(topic: setPoints[keyPath: setPoint]))
|
||||
}
|
||||
|
||||
func `set`(relay relayTopic: String, to state: Relay.State, qos: MQTTQoS = .atLeastOnce) -> EventLoopFuture<Void> {
|
||||
publish(
|
||||
to: relay.topic,
|
||||
to: relayTopic,
|
||||
payload: ByteBufferAllocator().buffer(string: state.rawValue),
|
||||
qos: qos
|
||||
)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import Foundation
|
||||
import Client
|
||||
@_exported import Client
|
||||
import CoreUnitTypes
|
||||
import Models
|
||||
import MQTTNIO
|
||||
@@ -11,20 +11,24 @@ extension Client.MQTTClient {
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - client: The ``MQTTNIO.MQTTClient`` used to send and recieve messages from the MQTT Broker.
|
||||
public static func live(client: MQTTNIO.MQTTClient) -> Self {
|
||||
public static func live(client: MQTTNIO.MQTTClient, topics: Topics) -> Self {
|
||||
.init(
|
||||
fetchHumidity: { sensor in
|
||||
client.fetch(sensor: sensor)
|
||||
.debug(logger: client.logger)
|
||||
},
|
||||
fetchSetPoint: { setPointKeyPath in
|
||||
client.fetch(client.mqttSubscription(topic: topics.setPoints[keyPath: setPointKeyPath]))
|
||||
.debug(logger: client.logger)
|
||||
},
|
||||
fetchTemperature: { sensor, units in
|
||||
client.fetch(sensor: sensor)
|
||||
.debug(logger: client.logger)
|
||||
.convertIfNeeded(to: units)
|
||||
.debug(logger: client.logger)
|
||||
},
|
||||
setRelay: { relay, state in
|
||||
client.set(relay: relay, to: state)
|
||||
setRelay: { relayKeyPath, state in
|
||||
client.set(relay: topics.commands.relays[keyPath: relayKeyPath], to: state)
|
||||
},
|
||||
shutdown: {
|
||||
client.disconnect()
|
||||
|
||||
Reference in New Issue
Block a user