184 lines
4.1 KiB
C
184 lines
4.1 KiB
C
#ifndef DEVICE_H
|
|
#define DEVICE_H
|
|
#include <ArduinoJson.h>
|
|
#include <PubSubClient.h>
|
|
#include <OneWire.h>
|
|
#include <DallasTemperature.h>
|
|
#include <ESP8266WiFi.h>
|
|
|
|
#include <Tools.h>
|
|
#include <secrets.h>
|
|
|
|
const char version[] = "0.0.1";
|
|
|
|
#define ACTION_TPC "action/state"
|
|
#define MODE_SET "mode/set"
|
|
#define MODE_STATE "mode/state"
|
|
#define SWING_STATE "swing/state"
|
|
#define SWING_SET "swing/set"
|
|
#define TEMP_SET "temp/set"
|
|
#define TEMP_STATE "temp/state"
|
|
#define TEMP_CURRENT "temp/current"
|
|
#define TEMP_HI_SET "temp_hi/set"
|
|
#define TEMP_HI_STATE "temp_hi/state"
|
|
#define TEMP_LO_SET "temp_lo/set"
|
|
#define TEMP_LO_STATE "temp_lo/state"
|
|
|
|
#define ACTION_OFF "off"
|
|
#define ACTION_HEATING "heating"
|
|
#define ACTION_COOLING "cooling"
|
|
#define ACTION_IDLE "idle"
|
|
|
|
#ifndef DEVICE_NAME
|
|
#define DEVICE_NAME "MQTT Thermostat"
|
|
#endif
|
|
|
|
#ifndef DEVICE_MDL
|
|
#define DEVICE_MDL "Thermostat"
|
|
#endif
|
|
|
|
#ifndef DEVICE_MF
|
|
#define DEVICE_MF ""
|
|
#endif
|
|
|
|
#ifndef ROOT
|
|
#define ROOT "thermostat/"
|
|
#endif
|
|
|
|
#ifndef CONFIG_ROOT
|
|
#define CONFIG_ROOT "homeassistant/climate/"
|
|
#endif
|
|
|
|
#ifndef MSG_RETAIN
|
|
#define MSG_RETAIN true
|
|
#endif
|
|
|
|
#define TOPIC_LIMIT 4
|
|
|
|
//~ #define OFF 0
|
|
//~ #define COOL 1
|
|
//~ #define HEAT 2
|
|
//~ #define AUTO 3
|
|
|
|
#define TEMP 0
|
|
#define TEMP_HI 1
|
|
#define TEMP_LO 2
|
|
|
|
uint8_t CHILLER_SP = 70;
|
|
uint8_t FERMA_SP = 70;
|
|
uint8_t FERMB_SP = 70;
|
|
|
|
//~ typedef void (*ptr)(uint8_t*, uint8_t*);
|
|
//typedef ptr (*pm)();
|
|
|
|
struct CommandTopic {
|
|
//~ ptr CmdFunc;
|
|
byte* Setting;
|
|
String CmdTopic;
|
|
};
|
|
|
|
struct Mode {
|
|
String CmdTopic;
|
|
String StateTopic;
|
|
String Setting;
|
|
};
|
|
|
|
struct SetPoint {
|
|
String CmdTopic;
|
|
String StateTopic;
|
|
int Setting;
|
|
};
|
|
|
|
struct ControlDevice {
|
|
String name; // "Glycol Chiller"
|
|
String topic_root; // "brewhouse/"
|
|
String current_temp_topic;
|
|
byte temp_sensor[8];
|
|
String action_topic;
|
|
String action_state;
|
|
String swing_topic;
|
|
String swing_state;
|
|
byte heat_pin;
|
|
byte cool_pin;
|
|
Mode mode;
|
|
SetPoint setpoints[3];
|
|
bool dual;
|
|
};
|
|
|
|
float UpdateTemperature(DallasTemperature *sensors, DeviceAddress glycol_tank) {
|
|
// method 2 - faster
|
|
float tempC = sensors->getTempC(glycol_tank);
|
|
if(tempC == DEVICE_DISCONNECTED_C)
|
|
{
|
|
Serial.println("Error: Could not read temperature data");
|
|
return 0;
|
|
}
|
|
|
|
return DallasTemperature::toFahrenheit(tempC);
|
|
|
|
}
|
|
|
|
bool DeviceLoop(ControlDevice &device, DallasTemperature *sensors) {
|
|
Serial.println(device.name);
|
|
|
|
float dsTemp = UpdateTemperature(sensors, device.temp_sensor);
|
|
String initial_action = device.action_state;
|
|
|
|
if (device.mode.Setting == "auto") {
|
|
int setHi = device.setpoints[TEMP_HI].Setting;
|
|
int setLo = device.setpoints[TEMP_LO].Setting;
|
|
|
|
if ((setLo <= dsTemp) && (dsTemp <= setHi)) { // Within Temp Range
|
|
device.action_state = ACTION_IDLE;
|
|
digitalWrite(device.cool_pin, LOW);
|
|
digitalWrite(device.heat_pin, LOW);
|
|
} else if (dsTemp < setLo) { // Needs Heat
|
|
device.action_state = ACTION_HEATING;
|
|
digitalWrite(device.cool_pin, LOW);
|
|
digitalWrite(device.heat_pin, HIGH);
|
|
} else if (dsTemp > setHi) { // Needs Cooling
|
|
device.action_state = ACTION_COOLING;
|
|
digitalWrite(device.cool_pin, HIGH);
|
|
digitalWrite(device.heat_pin, LOW);
|
|
}
|
|
}
|
|
|
|
int setTemp = device.setpoints[TEMP].Setting;
|
|
|
|
if (device.mode.Setting == "cool") {
|
|
|
|
|
|
if (dsTemp > setTemp) { // Needs Cooling
|
|
device.action_state = ACTION_COOLING;
|
|
digitalWrite(device.cool_pin, HIGH);
|
|
digitalWrite(device.heat_pin, LOW);
|
|
} else {
|
|
device.action_state = ACTION_IDLE;
|
|
digitalWrite(device.cool_pin, LOW);
|
|
digitalWrite(device.heat_pin, LOW);
|
|
}
|
|
}
|
|
|
|
if (device.mode.Setting == "heat") {
|
|
if (dsTemp < setTemp) { // Needs Cooling
|
|
device.action_state = ACTION_HEATING;
|
|
digitalWrite(device.cool_pin, LOW);
|
|
digitalWrite(device.heat_pin, HIGH);
|
|
} else {
|
|
device.action_state = ACTION_IDLE;
|
|
digitalWrite(device.cool_pin, LOW);
|
|
digitalWrite(device.heat_pin, LOW);
|
|
}
|
|
}
|
|
|
|
if (device.mode.Setting == "off") {
|
|
device.action_state = ACTION_IDLE;
|
|
}
|
|
|
|
if (initial_action != device.action_state) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
#endif
|