Added ability to load topics from a configuration file in the root directory. Dew point calculation seems to be off though.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,3 +6,4 @@ xcuserdata/
|
||||
DerivedData/
|
||||
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
|
||||
.dewPoint-env
|
||||
.topics
|
||||
|
||||
@@ -4,11 +4,5 @@
|
||||
"MQTT_PORT": "1883",
|
||||
"MQTT_IDENTIFIER": "dewPoint-controller",
|
||||
"MQTT_USERNAME": "mqtt_user",
|
||||
"MQTT_PASSWORD": "secret!",
|
||||
"DEHUMIDIFICATION_STAGE_1_RELAY": "relays/dehumidification_1",
|
||||
"DEHUMIDIFICATION_STAGE_2_RELAY": "relays/dehumidification_2",
|
||||
"DEW_POINT_TOPIC": "sensors/dew_point",
|
||||
"HUMIDIFICATION_RELAY": "relays/humidification",
|
||||
"HUMIDITY_SENSOR": "sensors/humidity",
|
||||
"TEMPERATURE_SENSOR": "sensors/temperature"
|
||||
"MQTT_PASSWORD": "secret!"
|
||||
}
|
||||
|
||||
34
Bootstrap/topics-example
Normal file
34
Bootstrap/topics-example
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"sensors": {
|
||||
"humidity": "sensors/humidity",
|
||||
"temperature":"sensors/temperature",
|
||||
"dewPoint":"sensors/dew_point"
|
||||
},
|
||||
"setPoints": {
|
||||
"dehumidify":{
|
||||
"lowDewPoint":"set_points/dehumidify/low_dew_point",
|
||||
"highDewPoint":"set_points/dehumidify/high_dew_point",
|
||||
"lowRelativeHumidity":"set_points/dehumidify/low_relative_humidity",
|
||||
"highRelativeHumidity":"set_points/dehumidify/high_relative_humidity"
|
||||
},
|
||||
"humidify":{
|
||||
"relativeHumidity":"set_points/humidify/relative_humidity",
|
||||
"dewPoint":"set_points/humidify/dew_point"
|
||||
}
|
||||
},
|
||||
"states":{
|
||||
"mode":"states/mode",
|
||||
"relays":{
|
||||
"dehumdification1":"states/relays/dehumidification_1",
|
||||
"humdification":"states/relays/humidification",
|
||||
"dehumidification2":"states/relays/dehumidification_2"
|
||||
}
|
||||
},
|
||||
"commands":{
|
||||
"relays":{
|
||||
"dehumidification2":"relays/dehumidification_2",
|
||||
"humidification":"relays/humidification",
|
||||
"dehumidification1":"relays/dehumidification_1"
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Makefile
3
Makefile
@@ -2,6 +2,9 @@
|
||||
bootstrap-env:
|
||||
@cp Bootstrap/dewPoint-env-example .dewPoint-env
|
||||
|
||||
bootstrap-topics:
|
||||
@cp Bootstrap/topics-example .topics
|
||||
|
||||
build:
|
||||
@swift build
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ public func bootstrap(
|
||||
logger?.debug("Bootstrapping Dew Point Controller...")
|
||||
|
||||
return loadEnvVars(eventLoopGroup: eventLoopGroup, logger: logger)
|
||||
.and(loadTopics(eventLoopGroup: eventLoopGroup, logger: logger))
|
||||
.makeDewPointEnvironment(eventLoopGroup: eventLoopGroup, logger: logger)
|
||||
.connectToMQTTBroker(logger: logger)
|
||||
}
|
||||
@@ -68,7 +69,42 @@ private func loadEnvVars(eventLoopGroup: EventLoopGroup, logger: Logger?) -> Eve
|
||||
return eventLoopGroup.next().makeSucceededFuture(envVars)
|
||||
}
|
||||
|
||||
extension EventLoopFuture where Value == EnvVars {
|
||||
func loadTopics(eventLoopGroup: EventLoopGroup, logger: Logger?) -> EventLoopFuture<Topics> {
|
||||
|
||||
logger?.debug("Loading topics from file...")
|
||||
|
||||
let topicsFilePath = URL(fileURLWithPath: #file)
|
||||
.deletingLastPathComponent()
|
||||
.deletingLastPathComponent()
|
||||
.deletingLastPathComponent()
|
||||
.appendingPathComponent(".topics")
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
|
||||
let data = try? Data.init(contentsOf: topicsFilePath)
|
||||
logger?.debug("Data: \(data!)")
|
||||
|
||||
let localTopics = data
|
||||
.flatMap { try? decoder.decode(Topics.self, from: $0) }
|
||||
|
||||
// .flatMap { try decoder.decode(Topics.self, from: $0) }
|
||||
|
||||
logger?.debug(
|
||||
localTopics == nil
|
||||
? "Failed to load topics from file, falling back to defaults."
|
||||
: "Done loading topics from file."
|
||||
)
|
||||
|
||||
// let defaultData = Topics()
|
||||
// let jsonData = try! JSONEncoder().encode(defaultData)
|
||||
// let string = String.init(data: jsonData, encoding: .utf8) ?? "Invalid data"
|
||||
// logger?.debug("\(string)")
|
||||
// try! string.write(to: topicsFilePath, atomically: true, encoding: .utf8)
|
||||
//
|
||||
return eventLoopGroup.next().makeSucceededFuture(localTopics ?? .init())
|
||||
}
|
||||
|
||||
extension EventLoopFuture where Value == (EnvVars, Topics) {
|
||||
|
||||
/// Creates the ``DewPointEnvironment`` for the application after the ``EnvVars`` have been loaded.
|
||||
///
|
||||
@@ -79,13 +115,13 @@ extension EventLoopFuture where Value == EnvVars {
|
||||
eventLoopGroup: EventLoopGroup,
|
||||
logger: Logger?
|
||||
) -> EventLoopFuture<DewPointEnvironment> {
|
||||
map { envVars in
|
||||
map { envVars, topics in
|
||||
let nioClient = MQTTClient(envVars: envVars, eventLoopGroup: eventLoopGroup, logger: logger)
|
||||
return DewPointEnvironment.init(
|
||||
mqttClient: .live(client: nioClient),
|
||||
envVars: envVars,
|
||||
nioClient: nioClient,
|
||||
topics: .init(envVars: envVars)
|
||||
topics: topics
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -128,22 +164,3 @@ extension MQTTClient {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - TODO Make topics loadable from a file in the root directory.
|
||||
extension Topics {
|
||||
|
||||
init(envVars: EnvVars) {
|
||||
self.init(
|
||||
sensors: .init(
|
||||
temperature: envVars.temperatureSensor,
|
||||
humidity: envVars.humiditySensor,
|
||||
dewPoint: envVars.dewPointTopic
|
||||
),
|
||||
relays: .init(
|
||||
dehumidification1: envVars.dehumidificationStage1Relay,
|
||||
dehumidification2: envVars.dehumidificationStage2Relay,
|
||||
humidification: envVars.humidificationRelay
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,15 +24,6 @@ public struct EnvVars: Codable, Equatable {
|
||||
/// The MQTT user password.
|
||||
public var password: String?
|
||||
|
||||
// MARK: TODO Move Topics to their own file that can be loaded.
|
||||
// Topics
|
||||
public var dehumidificationStage1Relay: String
|
||||
public var dehumidificationStage2Relay: String
|
||||
public var dewPointTopic: String
|
||||
public var humidificationRelay: String
|
||||
public var humiditySensor: String
|
||||
public var temperatureSensor: String
|
||||
|
||||
/// Create a new ``EnvVars``
|
||||
///
|
||||
/// - Parameters:
|
||||
@@ -48,13 +39,7 @@ public struct EnvVars: Codable, Equatable {
|
||||
port: String? = "1883",
|
||||
identifier: String = "dewPoint-controller",
|
||||
userName: String? = "mqtt_user",
|
||||
password: String? = "secret!",
|
||||
dehumidificationStage1Relay: String = "relays/dehumidification_1",
|
||||
dehumidificationStage2Relay: String = "relays/dehumidification_2",
|
||||
dewPointTopic: String = "sensors/dew_point",
|
||||
humidificationRelay: String = "relays/humidification",
|
||||
humiditySensor: String = "sensors/humidity",
|
||||
temperatureSensor: String = "sensors/temperature"
|
||||
password: String? = "secret!"
|
||||
){
|
||||
self.appEnv = appEnv
|
||||
self.host = host
|
||||
@@ -62,12 +47,6 @@ public struct EnvVars: Codable, Equatable {
|
||||
self.identifier = identifier
|
||||
self.userName = userName
|
||||
self.password = password
|
||||
self.dehumidificationStage1Relay = dehumidificationStage1Relay
|
||||
self.dehumidificationStage2Relay = dehumidificationStage2Relay
|
||||
self.dewPointTopic = dewPointTopic
|
||||
self.humidificationRelay = humidificationRelay
|
||||
self.humiditySensor = humiditySensor
|
||||
self.temperatureSensor = temperatureSensor
|
||||
}
|
||||
|
||||
/// Custom coding keys.
|
||||
@@ -78,12 +57,6 @@ public struct EnvVars: Codable, Equatable {
|
||||
case identifier = "MQTT_IDENTIFIER"
|
||||
case userName = "MQTT_USERNAME"
|
||||
case password = "MQTT_PASSWORD"
|
||||
case dehumidificationStage1Relay = "DEHUMIDIFICATION_STAGE_1_RELAY"
|
||||
case dehumidificationStage2Relay = "DEHUMIDIFICATION_STAGE_2_RELAY"
|
||||
case dewPointTopic = "DEW_POINT_TOPIC"
|
||||
case humidificationRelay = "HUMIDIFICATION_RELAY"
|
||||
case humiditySensor = "HUMIDITY_SENSOR"
|
||||
case temperatureSensor = "TEMPERATURE_SENSOR"
|
||||
}
|
||||
|
||||
/// Represents the different app environments.
|
||||
|
||||
@@ -1,27 +1,56 @@
|
||||
public struct Topics {
|
||||
|
||||
/// A container for all the different topics that are needed by the application.
|
||||
public struct Topics: Codable, Equatable {
|
||||
|
||||
/// The command topics the application can publish to.
|
||||
public var commands: Commands
|
||||
|
||||
/// The sensor topics the application can read sensor values from.
|
||||
public var sensors: Sensors
|
||||
public var setPoints: SetPoints
|
||||
public var states: States
|
||||
public var relays: Relays
|
||||
|
||||
/// The set point topics the application can read set point values from.
|
||||
public var setPoints: SetPoints
|
||||
|
||||
/// The state topics the application can read state values from.
|
||||
public var states: States
|
||||
|
||||
/// Create the topics required by the application.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - sensors: The sensor topics.
|
||||
/// - setPoints: The set point topics
|
||||
/// - states: The states topics
|
||||
/// - relays: The relay topics
|
||||
public init(
|
||||
commands: Commands = .init(),
|
||||
sensors: Sensors = .init(),
|
||||
setPoints: SetPoints = .init(),
|
||||
states: States = .init(),
|
||||
relays: Relays = .init()
|
||||
states: States = .init()
|
||||
) {
|
||||
self.commands = commands
|
||||
self.sensors = sensors
|
||||
self.setPoints = setPoints
|
||||
self.states = states
|
||||
self.relays = relays
|
||||
}
|
||||
|
||||
public struct Sensors {
|
||||
/// Represents the sensor topics.
|
||||
public struct Sensors: Codable, Equatable {
|
||||
|
||||
/// The temperature sensor topic.
|
||||
public var temperature: String
|
||||
|
||||
/// The humidity sensor topic.
|
||||
public var humidity: String
|
||||
|
||||
/// The dew point topic (we write / publish this data from the application).
|
||||
public var dewPoint: String
|
||||
|
||||
/// Create a new sensor topic container.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - temperature: The temperature sensor topic.
|
||||
/// - humidity: The humidity sensor topic.
|
||||
/// - dewPoint: The dew point sensor topic.
|
||||
public init(
|
||||
temperature: String = "sensors/temperature",
|
||||
humidity: String = "sensors/humidity",
|
||||
@@ -33,24 +62,73 @@ public struct Topics {
|
||||
}
|
||||
}
|
||||
|
||||
public struct SetPoints {
|
||||
public var humidify: String
|
||||
/// A container for set point related topics used by the application.
|
||||
public struct SetPoints: Codable, Equatable {
|
||||
|
||||
/// The topic for the humidify set point.
|
||||
public var humidify: Humidify
|
||||
|
||||
/// The topics for dehumidification set points.
|
||||
public var dehumidify: Dehumidify
|
||||
|
||||
/// Create a new set point topic container.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - humidify: The topic for humidification set points.
|
||||
/// - dehumidify: The topics for dehumidification set points.
|
||||
public init(
|
||||
humidify: String = "set_points/humidify",
|
||||
humidify: Humidify = .init(),
|
||||
dehumidify: Dehumidify = .init()
|
||||
) {
|
||||
self.humidify = humidify
|
||||
self.dehumidify = dehumidify
|
||||
}
|
||||
|
||||
public struct Dehumidify {
|
||||
/// A container for the humidification set point topics used by the application.
|
||||
public struct Humidify: Codable, Equatable {
|
||||
|
||||
/// The topic for dew point control mode set point.
|
||||
public var dewPoint: String
|
||||
|
||||
/// The topic for relative humidity control mode set point.
|
||||
public var relativeHumidity: String
|
||||
|
||||
/// Create a new container for the humidification set point topics.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - dewPoint: The topic for dew point control mode set point.
|
||||
/// - relativeHumidity: The topic for relative humidity control mode set point.
|
||||
public init(
|
||||
dewPoint: String = "set_points/humidify/dew_point",
|
||||
relativeHumidity: String = "set_points/humidify/relative_humidity"
|
||||
) {
|
||||
self.dewPoint = dewPoint
|
||||
self.relativeHumidity = relativeHumidity
|
||||
}
|
||||
}
|
||||
|
||||
/// A container for dehumidifcation set point topics.
|
||||
public struct Dehumidify: Codable, Equatable {
|
||||
|
||||
/// A low setting for dew point control modes.
|
||||
public var lowDewPoint: String
|
||||
|
||||
/// A high setting for dew point control modes.
|
||||
public var highDewPoint: String
|
||||
|
||||
/// A low setting for relative humidity control modes.
|
||||
public var lowRelativeHumidity: String
|
||||
|
||||
/// A high setting for relative humidity control modes.
|
||||
public var highRelativeHumidity: String
|
||||
|
||||
/// Create a new container for dehumidification set point topics.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - lowDewPoint: A low setting for dew point control modes.
|
||||
/// - highDewPoint: A high setting for dew point control modes.
|
||||
/// - lowRelativeHumidity: A low setting for relative humidity control modes.
|
||||
/// - highRelativeHumidity: A high setting for relative humidity control modes.
|
||||
public init(
|
||||
lowDewPoint: String = "set_points/dehumidify/low_dew_point",
|
||||
highDewPoint: String = "set_points/dehumidify/high_dew_point",
|
||||
@@ -65,27 +143,98 @@ public struct Topics {
|
||||
}
|
||||
}
|
||||
|
||||
public struct States {
|
||||
/// A container for control state topics used by the application.
|
||||
public struct States: Codable, Equatable {
|
||||
|
||||
/// The topic for the control mode.
|
||||
public var mode: String
|
||||
|
||||
public init(mode: String = "states/mode") {
|
||||
/// The relay state topics.
|
||||
public var relays: Relays
|
||||
|
||||
/// Create a new container for control state topics.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - mode: The topic for the control mode.
|
||||
public init(
|
||||
mode: String = "states/mode",
|
||||
relays: Relays = .init()
|
||||
) {
|
||||
self.mode = mode
|
||||
self.relays = relays
|
||||
}
|
||||
|
||||
/// A container for reading the current state of a relay.
|
||||
public struct Relays: Codable, Equatable {
|
||||
|
||||
/// The dehumidification stage-1 relay topic.
|
||||
public var dehumdification1: String
|
||||
|
||||
/// The dehumidification stage-2 relay topic.
|
||||
public var dehumidification2: String
|
||||
|
||||
/// The humidification relay topic.
|
||||
public var humdification: String
|
||||
|
||||
/// Create a new container for relay state topics.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - dehumidification1: The dehumidification stage-1 relay topic.
|
||||
/// - dehumidification2: The dehumidification stage-2 relay topic.
|
||||
/// - humidification: The humidification relay topic.
|
||||
public init(
|
||||
dehumidefication1: String = "states/relays/dehumidification_1",
|
||||
dehumidification2: String = "states/relays/dehumidification_2",
|
||||
humidification: String = "states/relays/humidification"
|
||||
) {
|
||||
self.dehumdification1 = dehumidefication1
|
||||
self.dehumidification2 = dehumidification2
|
||||
self.humdification = humidification
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public struct Relays {
|
||||
public var dehumidification1: String
|
||||
public var dehumidification2: String
|
||||
public var humidification: String
|
||||
/// A container for commands topics that the application can publish to.
|
||||
public struct Commands: Codable, Equatable {
|
||||
|
||||
public init(
|
||||
dehumidification1: String = "relays/dehumidification_1",
|
||||
dehumidification2: String = "relays/dehumidification_2",
|
||||
humidification: String = "relays/humidification"
|
||||
) {
|
||||
self.dehumidification1 = dehumidification1
|
||||
self.dehumidification2 = dehumidification2
|
||||
self.humidification = humidification
|
||||
/// The relay command topics.
|
||||
public var relays: Relays
|
||||
|
||||
/// Create a new command topics container.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - relays: The relay command topics.
|
||||
public init(relays: Relays = .init()) {
|
||||
self.relays = relays
|
||||
}
|
||||
|
||||
/// A container for relay command topics used by the application.
|
||||
public struct Relays: Codable, Equatable {
|
||||
|
||||
/// The dehumidification stage-1 relay topic.
|
||||
public var dehumidification1: String
|
||||
|
||||
/// The dehumidification stage-2 relay topic.
|
||||
public var dehumidification2: String
|
||||
|
||||
/// The humidification relay topic.
|
||||
public var humidification: String
|
||||
|
||||
/// Create a new container for commanding relays.
|
||||
///
|
||||
/// - Parameters:
|
||||
/// - dehumidification1: The dehumidification stage-1 relay topic.
|
||||
/// - dehumidification2: The dehumidification stage-2 relay topic.
|
||||
/// - humidification: The humidification relay topic.
|
||||
public init(
|
||||
dehumidification1: String = "relays/dehumidification_1",
|
||||
dehumidification2: String = "relays/dehumidification_2",
|
||||
humidification: String = "relays/humidification"
|
||||
) {
|
||||
self.dehumidification1 = dehumidification1
|
||||
self.dehumidification2 = dehumidification2
|
||||
self.humidification = humidification
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ if environment.envVars.appEnv == .production {
|
||||
logger.logLevel = .info
|
||||
}
|
||||
|
||||
let relay = Relay(topic: environment.topics.relays.dehumidification1)
|
||||
let relay = Relay(topic: environment.topics.commands.relays.dehumidification1)
|
||||
let tempSensor = Sensor<Temperature>(topic: environment.topics.sensors.temperature)
|
||||
let humiditySensor = Sensor<RelativeHumidity>(topic: environment.topics.sensors.humidity)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user