Implement bed cooler...
This commit is contained in:
@@ -5,6 +5,10 @@ ApiDef customApiDefs[] = {
|
||||
{"/api/ping", "GET", "", true, handlePing, nullptr},
|
||||
{"/api/add", "POST", "", true, handleAdd, nullptr},
|
||||
{"/api/led", "POST", "", true, handleLed, nullptr},
|
||||
{"/api/pump", "GET", "WebUIConnect", false, handlePump, nullptr},
|
||||
{"/api/pump", "POST", "WebUIConnect", false, handlePump, nullptr},
|
||||
{"/api/program", "GET", "WebUIConnect", false, handleProgram, nullptr},
|
||||
{"/api/program", "POST", "WebUIConnect", false, handleProgram, nullptr},
|
||||
{"/api/temperature", "GET", "WebUIConnect", false, handleTemperature, nullptr},
|
||||
{"/api/temperature/events", "GET", "WebUIConnect", false, handleTemperatureEvents, nullptr},
|
||||
};
|
||||
|
||||
@@ -10,6 +10,10 @@ void applyLed() {
|
||||
analogWrite(LED_BUILTIN, duty);
|
||||
}
|
||||
|
||||
void applyPump() {
|
||||
digitalWrite(PUMP_PIN, pumpEnabled ? PUMP_ACTIVE_LEVEL : !PUMP_ACTIVE_LEVEL);
|
||||
}
|
||||
|
||||
void factoryReset() {
|
||||
prefs.clear();
|
||||
LittleFS.remove(LOG_FILE_PATH);
|
||||
|
||||
@@ -27,6 +27,9 @@ size_t maxLogBytes = 50 * 1024;
|
||||
bool setupMode = false;
|
||||
uint8_t ledBrightness = 0;
|
||||
bool ledInverted = DEFAULT_LED_INVERTED;
|
||||
bool pumpEnabled = false;
|
||||
ProgramMode programMode = PROGRAM_OFF;
|
||||
float programTargetC = PROGRAM_DEFAULT_TARGET_C;
|
||||
String updateUrl = DEFAULT_UPDATE_URL;
|
||||
String networkHostname;
|
||||
bool networkDhcp = true;
|
||||
@@ -106,6 +109,9 @@ void loadSettings() {
|
||||
maxLogBytes = prefs.getUInt("logMax", 50 * 1024);
|
||||
ledInverted = prefs.getBool("ledInv", DEFAULT_LED_INVERTED);
|
||||
ledBrightness = constrain(prefs.getUChar("ledBright", 0), 0, 100);
|
||||
programMode = (ProgramMode)constrain(prefs.getUChar("progMode", PROGRAM_OFF), PROGRAM_OFF, PROGRAM_WARM);
|
||||
programTargetC = prefs.getFloat("progTargetC", PROGRAM_DEFAULT_TARGET_C);
|
||||
if (isnan(programTargetC) || programTargetC < -40.0f || programTargetC > 85.0f) programTargetC = PROGRAM_DEFAULT_TARGET_C;
|
||||
updateUrl = prefString("updateUrl", DEFAULT_UPDATE_URL);
|
||||
networkHostname = prefString("netHost", "");
|
||||
networkDhcp = prefs.getBool("netDhcp", true);
|
||||
|
||||
@@ -22,7 +22,7 @@ static void beginTemperatureSensor() {
|
||||
temperatureStarted = true;
|
||||
}
|
||||
|
||||
static void updateTemperatureSensor() {
|
||||
void updateTemperatureSensor() {
|
||||
beginTemperatureSensor();
|
||||
uint32_t now = millis();
|
||||
if (temperaturePending && now - temperatureRequestMs >= 750) {
|
||||
@@ -37,6 +37,11 @@ static void updateTemperatureSensor() {
|
||||
}
|
||||
}
|
||||
|
||||
float currentTemperatureC() {
|
||||
updateTemperatureSensor();
|
||||
return lastTemperatureC;
|
||||
}
|
||||
|
||||
static String temperatureJsonFields() {
|
||||
updateTemperatureSensor();
|
||||
String json = "\"pin\":" + String(DS18B20_PIN);
|
||||
@@ -49,6 +54,85 @@ static String temperatureJsonFields() {
|
||||
return json;
|
||||
}
|
||||
|
||||
static String pumpJsonFields() {
|
||||
return "\"enabled\":" + String(pumpEnabled ? "true" : "false") + ",\"pin\":" + String(PUMP_PIN);
|
||||
}
|
||||
|
||||
String programModeName() {
|
||||
if (programMode == PROGRAM_COOL) return "cool";
|
||||
if (programMode == PROGRAM_WARM) return "warm";
|
||||
return "off";
|
||||
}
|
||||
|
||||
static ProgramMode parseProgramMode(const String &value, ProgramMode fallback) {
|
||||
String mode = value;
|
||||
mode.toLowerCase();
|
||||
if (mode == "cool") return PROGRAM_COOL;
|
||||
if (mode == "warm") return PROGRAM_WARM;
|
||||
if (mode == "off") return PROGRAM_OFF;
|
||||
return fallback;
|
||||
}
|
||||
|
||||
static float jsonFloatValue(const String &json, const char *key, float fallback) {
|
||||
String needle = "\"" + String(key) + "\"";
|
||||
int p = json.indexOf(needle);
|
||||
if (p < 0) return fallback;
|
||||
p = json.indexOf(':', p + needle.length());
|
||||
if (p < 0) return fallback;
|
||||
p++;
|
||||
while (p < (int)json.length() && isspace(json[p])) p++;
|
||||
if (p >= (int)json.length()) return fallback;
|
||||
if (json[p] == '"') return jsonStringValue(json, key, String(fallback, 2)).toFloat();
|
||||
return json.substring(p).toFloat();
|
||||
}
|
||||
|
||||
static void setPumpEnabled(bool enabled, const String &reason) {
|
||||
if (pumpEnabled == enabled) return;
|
||||
pumpEnabled = enabled;
|
||||
applyPump();
|
||||
appendLog(LOG_INFO, "Pump switched " + String(pumpEnabled ? "on" : "off") + reason);
|
||||
}
|
||||
|
||||
static String programJsonFields() {
|
||||
float temperatureC = currentTemperatureC();
|
||||
String json = "\"mode\":\"" + programModeName() + "\"";
|
||||
json += ",\"targetTemperatureC\":" + String(programTargetC, 2);
|
||||
json += ",\"targetTemperatureF\":" + String((programTargetC * 9.0f / 5.0f) + 32.0f, 2);
|
||||
json += ",\"toleranceC\":" + String(PROGRAM_TOLERANCE_C, 2);
|
||||
json += ",\"pumpEnabled\":" + String(pumpEnabled ? "true" : "false");
|
||||
json += ",\"sensorConnected\":";
|
||||
json += isnan(temperatureC) ? "false" : "true";
|
||||
json += ",\"temperatureC\":";
|
||||
json += isnan(temperatureC) ? "null" : String(temperatureC, 2);
|
||||
return json;
|
||||
}
|
||||
|
||||
void updateProgram() {
|
||||
static uint32_t lastProgramMs = 0;
|
||||
uint32_t now = millis();
|
||||
updateTemperatureSensor();
|
||||
if (now - lastProgramMs < 500) return;
|
||||
lastProgramMs = now;
|
||||
|
||||
if (programMode == PROGRAM_OFF) {
|
||||
setPumpEnabled(false, " by program");
|
||||
return;
|
||||
}
|
||||
|
||||
float temperatureC = currentTemperatureC();
|
||||
if (isnan(temperatureC)) {
|
||||
setPumpEnabled(false, " by program sensor fault");
|
||||
return;
|
||||
}
|
||||
|
||||
float roundedTemperatureC = roundf(temperatureC * 100.0f) / 100.0f;
|
||||
if (programMode == PROGRAM_COOL) {
|
||||
setPumpEnabled(roundedTemperatureC >= programTargetC + PROGRAM_TOLERANCE_C, " by cool program");
|
||||
} else if (programMode == PROGRAM_WARM) {
|
||||
setPumpEnabled(roundedTemperatureC <= programTargetC - PROGRAM_TOLERANCE_C, " by warm program");
|
||||
}
|
||||
}
|
||||
|
||||
void handlePing() {
|
||||
if (!authorize()) return;
|
||||
sendJson(200, jsonOk("\"uptimeMs\":" + String(millis()) + ",\"version\":\"" + APP_VERSION + "\",\"name\":\"" + jsonEscape(deviceName()) + "\",\"ip\":\"" + WiFi.localIP().toString() + "\""));
|
||||
@@ -71,6 +155,29 @@ void handleLed() {
|
||||
sendJson(200, jsonOk("\"brightness\":" + String(ledBrightness)));
|
||||
}
|
||||
|
||||
void handlePump() {
|
||||
if (!authorize()) return;
|
||||
if (server.method() == HTTP_POST) {
|
||||
setPumpEnabled(jsonBoolValue(requestBody(), "enabled", server.arg("enabled") == "true"), " manually");
|
||||
}
|
||||
sendJson(200, jsonOk(pumpJsonFields()));
|
||||
}
|
||||
|
||||
void handleProgram() {
|
||||
if (!authorize()) return;
|
||||
if (server.method() == HTTP_POST) {
|
||||
String body = requestBody();
|
||||
programMode = parseProgramMode(jsonStringValue(body, "mode", programModeName()), programMode);
|
||||
programTargetC = constrain(jsonFloatValue(body, "targetTemperatureC", programTargetC), -40.0f, 85.0f);
|
||||
programTargetC = roundf(programTargetC * 100.0f) / 100.0f;
|
||||
prefs.putUChar("progMode", programMode);
|
||||
prefs.putFloat("progTargetC", programTargetC);
|
||||
updateProgram();
|
||||
appendLog(LOG_INFO, "Program set to " + programModeName() + " target " + String(programTargetC, 2) + " C");
|
||||
}
|
||||
sendJson(200, jsonOk(programJsonFields()));
|
||||
}
|
||||
|
||||
void handleTemperature() {
|
||||
if (!authorize()) return;
|
||||
sendJson(200, jsonOk(temperatureJsonFields()));
|
||||
@@ -81,6 +188,8 @@ void handleTemperatureEvents() {
|
||||
String payload = "retry: 1000\n";
|
||||
payload += "event: temperature\n";
|
||||
payload += "data: {" + temperatureJsonFields() + "}\n\n";
|
||||
payload += "event: pump\n";
|
||||
payload += "data: {" + pumpJsonFields() + "}\n\n";
|
||||
server.sendHeader("Cache-Control", "no-store");
|
||||
server.sendHeader("Connection", "close");
|
||||
server.send(200, "text/event-stream", payload);
|
||||
|
||||
@@ -10,6 +10,8 @@ void setup() {
|
||||
loadSettings();
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
applyLed();
|
||||
pinMode(PUMP_PIN, OUTPUT);
|
||||
applyPump();
|
||||
checkFactoryResetPin();
|
||||
|
||||
bool configured = prefs.getBool("configured", false);
|
||||
@@ -34,5 +36,6 @@ void setup() {
|
||||
|
||||
void loop() {
|
||||
if (setupMode) dnsServer.processNextRequest();
|
||||
updateProgram();
|
||||
server.handleClient();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user