Reading / calculating dew-point.
This commit is contained in:
@@ -13,8 +13,8 @@ let package = Package(
|
|||||||
.library(name: "DewPointEnvironment", targets: ["DewPointEnvironment"]),
|
.library(name: "DewPointEnvironment", targets: ["DewPointEnvironment"]),
|
||||||
.library(name: "EnvVars", targets: ["EnvVars"]),
|
.library(name: "EnvVars", targets: ["EnvVars"]),
|
||||||
.library(name: "Models", targets: ["Models"]),
|
.library(name: "Models", targets: ["Models"]),
|
||||||
.library(name: "RelayClient", targets: ["RelayClient"]),
|
.library(name: "Client", targets: ["Client"]),
|
||||||
.library(name: "TemperatureSensorClient", targets: ["TemperatureSensorClient"]),
|
.library(name: "ClientLive", targets: ["ClientLive"]),
|
||||||
],
|
],
|
||||||
dependencies: [
|
dependencies: [
|
||||||
.package(url: "https://github.com/adam-fowler/mqtt-nio.git", from: "2.0.0"),
|
.package(url: "https://github.com/adam-fowler/mqtt-nio.git", from: "2.0.0"),
|
||||||
@@ -39,8 +39,7 @@ let package = Package(
|
|||||||
dependencies: [
|
dependencies: [
|
||||||
"DewPointEnvironment",
|
"DewPointEnvironment",
|
||||||
"EnvVars",
|
"EnvVars",
|
||||||
"RelayClient",
|
"ClientLive",
|
||||||
"TemperatureSensorClient",
|
|
||||||
.product(name: "MQTTNIO", package: "mqtt-nio"),
|
.product(name: "MQTTNIO", package: "mqtt-nio"),
|
||||||
.product(name: "NIO", package: "swift-nio")
|
.product(name: "NIO", package: "swift-nio")
|
||||||
]
|
]
|
||||||
@@ -49,8 +48,7 @@ let package = Package(
|
|||||||
name: "DewPointEnvironment",
|
name: "DewPointEnvironment",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"EnvVars",
|
"EnvVars",
|
||||||
"RelayClient",
|
"Client",
|
||||||
"TemperatureSensorClient",
|
|
||||||
.product(name: "MQTTNIO", package: "mqtt-nio"),
|
.product(name: "MQTTNIO", package: "mqtt-nio"),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
@@ -63,20 +61,19 @@ let package = Package(
|
|||||||
dependencies: []
|
dependencies: []
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "RelayClient",
|
name: "Client",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"Models",
|
"Models",
|
||||||
|
.product(name: "CoreUnitTypes", package: "swift-psychrometrics"),
|
||||||
.product(name: "NIO", package: "swift-nio"),
|
.product(name: "NIO", package: "swift-nio"),
|
||||||
.product(name: "MQTTNIO", package: "mqtt-nio")
|
.product(name: "Psychrometrics", package: "swift-psychrometrics")
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
.target(
|
.target(
|
||||||
name: "TemperatureSensorClient",
|
name: "ClientLive",
|
||||||
dependencies: [
|
dependencies: [
|
||||||
"Models",
|
"Client",
|
||||||
.product(name: "NIO", package: "swift-nio"),
|
.product(name: "MQTTNIO", package: "mqtt-nio")
|
||||||
.product(name: "MQTTNIO", package: "mqtt-nio"),
|
|
||||||
.product(name: "CoreUnitTypes", package: "swift-psychrometrics")
|
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
|
import ClientLive
|
||||||
import DewPointEnvironment
|
import DewPointEnvironment
|
||||||
import EnvVars
|
import EnvVars
|
||||||
import Logging
|
import Logging
|
||||||
import Foundation
|
import Foundation
|
||||||
import MQTTNIO
|
import MQTTNIO
|
||||||
import NIO
|
import NIO
|
||||||
import RelayClient
|
|
||||||
import TemperatureSensorClient
|
|
||||||
|
|
||||||
public func bootstrap(
|
public func bootstrap(
|
||||||
eventLoopGroup: EventLoopGroup,
|
eventLoopGroup: EventLoopGroup,
|
||||||
@@ -16,10 +15,9 @@ public func bootstrap(
|
|||||||
.map { (envVars) -> DewPointEnvironment in
|
.map { (envVars) -> DewPointEnvironment in
|
||||||
let mqttClient = MQTTClient(envVars: envVars, eventLoopGroup: eventLoopGroup, logger: logger)
|
let mqttClient = MQTTClient(envVars: envVars, eventLoopGroup: eventLoopGroup, logger: logger)
|
||||||
return DewPointEnvironment.init(
|
return DewPointEnvironment.init(
|
||||||
mqttClient: mqttClient,
|
client: .live(client: mqttClient),
|
||||||
envVars: envVars,
|
envVars: envVars,
|
||||||
relayClient: .live(client: mqttClient),
|
mqttClient: mqttClient
|
||||||
temperatureSensorClient: .live(client: mqttClient)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.flatMap { environment in
|
.flatMap { environment in
|
||||||
|
|||||||
46
Sources/Client/Interface.swift
Normal file
46
Sources/Client/Interface.swift
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import CoreUnitTypes
|
||||||
|
import Logging
|
||||||
|
import Foundation
|
||||||
|
import Models
|
||||||
|
import NIO
|
||||||
|
import Psychrometrics
|
||||||
|
|
||||||
|
public struct Client {
|
||||||
|
|
||||||
|
public var fetchHumidity: (HumiditySensor) -> EventLoopFuture<RelativeHumidity>
|
||||||
|
public var fetchTemperature: (TemperatureSensor, PsychrometricEnvironment.Units?) -> EventLoopFuture<Temperature>
|
||||||
|
public var toggleRelay: (Relay) -> EventLoopFuture<Void>
|
||||||
|
public var turnOnRelay: (Relay) -> EventLoopFuture<Void>
|
||||||
|
public var turnOffRelay: (Relay) -> EventLoopFuture<Void>
|
||||||
|
public var shutdown: () -> EventLoopFuture<Void>
|
||||||
|
|
||||||
|
public init(
|
||||||
|
fetchHumidity: @escaping (HumiditySensor) -> EventLoopFuture<RelativeHumidity>,
|
||||||
|
fetchTemperature: @escaping (TemperatureSensor, PsychrometricEnvironment.Units?) -> EventLoopFuture<Temperature>,
|
||||||
|
toggleRelay: @escaping (Relay) -> EventLoopFuture<Void>,
|
||||||
|
turnOnRelay: @escaping (Relay) -> EventLoopFuture<Void>,
|
||||||
|
turnOffRelay: @escaping (Relay) -> EventLoopFuture<Void>,
|
||||||
|
shutdown: @escaping () -> EventLoopFuture<Void>
|
||||||
|
) {
|
||||||
|
self.fetchHumidity = fetchHumidity
|
||||||
|
self.fetchTemperature = fetchTemperature
|
||||||
|
self.toggleRelay = toggleRelay
|
||||||
|
self.turnOnRelay = turnOnRelay
|
||||||
|
self.turnOffRelay = turnOffRelay
|
||||||
|
self.shutdown = shutdown
|
||||||
|
}
|
||||||
|
|
||||||
|
public func fetchDewPoint(
|
||||||
|
temperature: TemperatureSensor,
|
||||||
|
humidity: HumiditySensor,
|
||||||
|
units: PsychrometricEnvironment.Units? = nil,
|
||||||
|
logger: Logger? = nil
|
||||||
|
) -> EventLoopFuture<DewPoint> {
|
||||||
|
fetchTemperature(temperature, units)
|
||||||
|
.and(fetchHumidity(humidity))
|
||||||
|
.map { temp, humidity in
|
||||||
|
logger?.debug("Creating dew-point for temperature: \(temp) with humidity: \(humidity)")
|
||||||
|
return DewPoint.init(dryBulb: temp, humidity: humidity, units: units)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
137
Sources/ClientLive/Live.swift
Normal file
137
Sources/ClientLive/Live.swift
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
import Foundation
|
||||||
|
import Client
|
||||||
|
import CoreUnitTypes
|
||||||
|
import Models
|
||||||
|
import MQTTNIO
|
||||||
|
import NIO
|
||||||
|
|
||||||
|
extension Client {
|
||||||
|
|
||||||
|
public static func live(client: MQTTClient) -> Self {
|
||||||
|
.init(
|
||||||
|
fetchHumidity: { sensor in
|
||||||
|
client.fetchHumidity(sensor: sensor)
|
||||||
|
},
|
||||||
|
fetchTemperature: { sensor, units in
|
||||||
|
client.fetchTemperature(sensor: sensor, units: units)
|
||||||
|
},
|
||||||
|
toggleRelay: { relay in
|
||||||
|
client.publish(relay: relay, state: .toggle, qos: .atLeastOnce)
|
||||||
|
},
|
||||||
|
turnOnRelay: { relay in
|
||||||
|
client.publish(relay: relay, state: .on, qos: .atLeastOnce)
|
||||||
|
},
|
||||||
|
turnOffRelay: { relay in
|
||||||
|
client.publish(relay: relay, state: .off, qos: .atLeastOnce)
|
||||||
|
},
|
||||||
|
shutdown: {
|
||||||
|
client.disconnect()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Helpers
|
||||||
|
enum TemperatureError: Error {
|
||||||
|
case invalidTemperature
|
||||||
|
}
|
||||||
|
|
||||||
|
enum HumidityError: Error {
|
||||||
|
case invalidHumidity
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Relay {
|
||||||
|
enum State: String {
|
||||||
|
case toggle, on, off
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MQTTClient {
|
||||||
|
|
||||||
|
fileprivate func publish(relay: Relay, state: Relay.State, qos: MQTTQoS = .atLeastOnce) -> EventLoopFuture<Void> {
|
||||||
|
publish(
|
||||||
|
to: relay.topic,
|
||||||
|
payload: ByteBufferAllocator().buffer(string: state.rawValue),
|
||||||
|
qos: qos
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func fetchTemperature(
|
||||||
|
sensor: TemperatureSensor,
|
||||||
|
units: PsychrometricEnvironment.Units?
|
||||||
|
) -> EventLoopFuture<Temperature> {
|
||||||
|
logger.debug("Adding listener for temperature sensor...")
|
||||||
|
let subscription = MQTTSubscribeInfoV5.init(
|
||||||
|
topicFilter: sensor.topic,
|
||||||
|
qos: .atLeastOnce,
|
||||||
|
retainAsPublished: true,
|
||||||
|
retainHandling: .sendAlways
|
||||||
|
)
|
||||||
|
return v5.subscribe(to: [subscription])
|
||||||
|
.flatMap { _ in
|
||||||
|
let promise = self.eventLoopGroup.next().makePromise(of: Temperature.self)
|
||||||
|
self.addPublishListener(named: "temperature-sensor", { result in
|
||||||
|
switch result.temperature() {
|
||||||
|
case let .success(celsius):
|
||||||
|
let userUnits = units ?? PsychrometricEnvironment.shared.units
|
||||||
|
let temperatureUnits = Temperature.Units.defaultFor(units: userUnits)
|
||||||
|
promise.succeed(.init(celsius[temperatureUnits], units: temperatureUnits))
|
||||||
|
case let .failure(error):
|
||||||
|
promise.fail(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
return promise.futureResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func fetchHumidity(sensor: HumiditySensor) -> EventLoopFuture<RelativeHumidity> {
|
||||||
|
logger.debug("Adding listener for humidity sensor...")
|
||||||
|
let subscription = MQTTSubscribeInfoV5.init(
|
||||||
|
topicFilter: sensor.topic,
|
||||||
|
qos: .atLeastOnce,
|
||||||
|
retainAsPublished: true,
|
||||||
|
retainHandling: .sendAlways
|
||||||
|
)
|
||||||
|
return v5.subscribe(to: [subscription])
|
||||||
|
.flatMap { _ in
|
||||||
|
let promise = self.eventLoopGroup.next().makePromise(of: RelativeHumidity.self)
|
||||||
|
self.addPublishListener(named: "humidity-sensor", { result in
|
||||||
|
switch result.humidity() {
|
||||||
|
case let .success(humidity):
|
||||||
|
promise.succeed(humidity)
|
||||||
|
case let .failure(error):
|
||||||
|
promise.fail(error)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return promise.futureResult
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension Result where Success == MQTTPublishInfo, Failure == Error {
|
||||||
|
|
||||||
|
fileprivate func humidity() -> Result<RelativeHumidity, Error> {
|
||||||
|
flatMap { info in
|
||||||
|
var buffer = info.payload
|
||||||
|
guard let string = buffer.readString(length: buffer.readableBytes),
|
||||||
|
let double = Double(string)
|
||||||
|
else {
|
||||||
|
return .failure(HumidityError.invalidHumidity)
|
||||||
|
}
|
||||||
|
return .success(.init(double))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileprivate func temperature() -> Result<Temperature, Error> {
|
||||||
|
flatMap { info in
|
||||||
|
var buffer = info.payload
|
||||||
|
guard let string = buffer.readString(length: buffer.readableBytes),
|
||||||
|
let temperatureValue = Double(string)
|
||||||
|
else {
|
||||||
|
return .failure(TemperatureError.invalidTemperature)
|
||||||
|
}
|
||||||
|
return .success(.celsius(temperatureValue))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,24 +1,20 @@
|
|||||||
|
import Client
|
||||||
import EnvVars
|
import EnvVars
|
||||||
import MQTTNIO
|
import MQTTNIO
|
||||||
import RelayClient
|
|
||||||
import TemperatureSensorClient
|
|
||||||
|
|
||||||
public struct DewPointEnvironment {
|
public struct DewPointEnvironment {
|
||||||
|
|
||||||
public var mqttClient: MQTTClient
|
public var client: Client
|
||||||
public var envVars: EnvVars
|
public var envVars: EnvVars
|
||||||
public var relayClient: RelayClient
|
public var mqttClient: MQTTClient
|
||||||
public var temperatureSensorClient: TemperatureSensorClient
|
|
||||||
|
|
||||||
public init(
|
public init(
|
||||||
mqttClient: MQTTClient,
|
client: Client,
|
||||||
envVars: EnvVars,
|
envVars: EnvVars,
|
||||||
relayClient: RelayClient,
|
mqttClient: MQTTClient
|
||||||
temperatureSensorClient: TemperatureSensorClient
|
|
||||||
) {
|
) {
|
||||||
self.mqttClient = mqttClient
|
self.mqttClient = mqttClient
|
||||||
self.envVars = envVars
|
self.envVars = envVars
|
||||||
self.relayClient = relayClient
|
self.client = client
|
||||||
self.temperatureSensorClient = temperatureSensorClient
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import Models
|
|
||||||
import NIO
|
|
||||||
|
|
||||||
public struct RelayClient {
|
|
||||||
public var toggle: (Relay) -> EventLoopFuture<Void>
|
|
||||||
public var turnOn: (Relay) -> EventLoopFuture<Void>
|
|
||||||
public var turnOff: (Relay) -> EventLoopFuture<Void>
|
|
||||||
|
|
||||||
public init(
|
|
||||||
toggle: @escaping (Relay) -> EventLoopFuture<Void>,
|
|
||||||
turnOn: @escaping (Relay) -> EventLoopFuture<Void>,
|
|
||||||
turnOff: @escaping (Relay) -> EventLoopFuture<Void>
|
|
||||||
) {
|
|
||||||
self.toggle = toggle
|
|
||||||
self.turnOn = turnOn
|
|
||||||
self.turnOff = turnOff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
import Models
|
|
||||||
import MQTTNIO
|
|
||||||
import NIO
|
|
||||||
|
|
||||||
extension RelayClient {
|
|
||||||
|
|
||||||
public static func live(client: MQTTClient) -> RelayClient {
|
|
||||||
.init(
|
|
||||||
toggle: { relay in
|
|
||||||
client.publish(relay: relay, state: .toggle)
|
|
||||||
},
|
|
||||||
turnOn: { relay in
|
|
||||||
client.publish(relay: relay, state: .on)
|
|
||||||
},
|
|
||||||
turnOff: { relay in
|
|
||||||
client.publish(relay: relay, state: .off)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension Relay {
|
|
||||||
enum State: String {
|
|
||||||
case toggle, on, off
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extension MQTTClient {
|
|
||||||
|
|
||||||
func publish(relay: Relay, state: Relay.State, qos: MQTTQoS = .atLeastOnce) -> EventLoopFuture<Void> {
|
|
||||||
publish(
|
|
||||||
to: relay.topic,
|
|
||||||
payload: ByteBufferAllocator().buffer(string: state.rawValue),
|
|
||||||
qos: qos
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
import Foundation
|
|
||||||
import CoreUnitTypes
|
|
||||||
import Models
|
|
||||||
import NIO
|
|
||||||
|
|
||||||
public struct TemperatureSensorClient {
|
|
||||||
public var state: (TemperatureSensor, PsychrometricEnvironment.Units?) -> EventLoopFuture<Temperature>
|
|
||||||
|
|
||||||
public init(
|
|
||||||
state: @escaping (TemperatureSensor, PsychrometricEnvironment.Units?) -> EventLoopFuture<Temperature>
|
|
||||||
) {
|
|
||||||
self.state = state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import CoreUnitTypes
|
|
||||||
import Foundation
|
|
||||||
import MQTTNIO
|
|
||||||
|
|
||||||
extension TemperatureSensorClient {
|
|
||||||
|
|
||||||
public static func live(client: MQTTClient) -> TemperatureSensorClient {
|
|
||||||
.init(
|
|
||||||
state: { sensor, units in
|
|
||||||
client.logger.debug("Adding listener for temperature sensor...")
|
|
||||||
let subscription = MQTTSubscribeInfoV5.init(topicFilter: sensor.topic, qos: .atLeastOnce)
|
|
||||||
return client.v5.subscribe(to: [subscription])
|
|
||||||
.flatMap { _ in
|
|
||||||
let promise = client.eventLoopGroup.next().makePromise(of: Temperature.self)
|
|
||||||
client.addPublishListener(named: "temperature-sensor", { result in
|
|
||||||
switch result.temperature() {
|
|
||||||
case let .success(celsius):
|
|
||||||
let userUnits = units ?? PsychrometricEnvironment.shared.units
|
|
||||||
let temperatureUnits = Temperature.Units.defaultFor(units: userUnits)
|
|
||||||
promise.succeed(.init(celsius[temperatureUnits], units: temperatureUnits))
|
|
||||||
case let .failure(error):
|
|
||||||
promise.fail(error)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return promise.futureResult
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum TemperatureError: Error {
|
|
||||||
case invalidTemperature
|
|
||||||
}
|
|
||||||
|
|
||||||
// MARK: - Helpers
|
|
||||||
extension Result where Success == MQTTPublishInfo, Failure == Error {
|
|
||||||
|
|
||||||
fileprivate func temperature() -> Result<Temperature, Error> {
|
|
||||||
flatMap { info in
|
|
||||||
var buffer = info.payload
|
|
||||||
guard let string = buffer.readString(length: buffer.readableBytes),
|
|
||||||
let temperatureValue = Double(string)
|
|
||||||
else {
|
|
||||||
return .failure(TemperatureError.invalidTemperature)
|
|
||||||
}
|
|
||||||
return .success(.celsius(temperatureValue))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,23 +12,36 @@ logger.debug("Swift Dew Point Controller!")
|
|||||||
|
|
||||||
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
|
||||||
let environment = try bootstrap(eventLoopGroup: eventLoopGroup, logger: logger).wait()
|
let environment = try bootstrap(eventLoopGroup: eventLoopGroup, logger: logger).wait()
|
||||||
let relayClient = environment.relayClient
|
|
||||||
let relay = Relay(topic: "frankensystem/relays/switch/relay_1/command")
|
let relay = Relay(topic: "frankensystem/relays/switch/relay_1/command")
|
||||||
let tempSensor = TemperatureSensor(topic: "frankensystem/relays/sensor/temperature_-_1/state")
|
let tempSensor = TemperatureSensor(topic: "frankensystem/relays/sensor/temperature_-_1/state")
|
||||||
|
let humiditySensor = HumiditySensor(topic: "frankensystem/relays/sensor/humidity_-_1/state")
|
||||||
|
|
||||||
defer {
|
defer {
|
||||||
logger.debug("Disconnecting")
|
logger.debug("Disconnecting")
|
||||||
_ = try? environment.mqttClient.disconnect().wait()
|
_ = try? environment.client.shutdown().wait()
|
||||||
try? environment.mqttClient.syncShutdownGracefully()
|
try? environment.mqttClient.syncShutdownGracefully()
|
||||||
}
|
}
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
logger.debug("Toggling relay.")
|
// logger.debug("Toggling relay.")
|
||||||
_ = try relayClient.toggle(relay).wait()
|
// _ = try environment.client.toggleRelay(relay).wait()
|
||||||
|
|
||||||
logger.debug("Reading temperature sensor.")
|
// logger.debug("Reading temperature sensor.")
|
||||||
let temp = try environment.temperatureSensorClient.state(tempSensor, .imperial).wait()
|
// let temp = try environment.client.fetchTemperature(tempSensor, .imperial).wait()
|
||||||
logger.debug("Temperature: \(temp)")
|
// logger.debug("Temperature: \(temp)")
|
||||||
|
|
||||||
|
// logger.debug("Reading humidity sensor.")
|
||||||
|
// let humidity = try environment.client.fetchHumidity(humiditySensor).wait()
|
||||||
|
// logger.debug("Humdity: \(humidity)")
|
||||||
|
|
||||||
|
logger.debug("Fetching dew point...")
|
||||||
|
let dp = try environment.client.fetchDewPoint(
|
||||||
|
temperature: tempSensor,
|
||||||
|
humidity: humiditySensor,
|
||||||
|
units: .imperial,
|
||||||
|
logger: logger
|
||||||
|
).wait()
|
||||||
|
logger.debug("Dew Point: \(dp)")
|
||||||
|
|
||||||
Thread.sleep(forTimeInterval: 5)
|
Thread.sleep(forTimeInterval: 5)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user