#ifndef DEVICE_H #define DEVICE_H #include #include #include #include #include #include #include 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