I can't figure out why my digitalwrite to pin isn't working. The first write after flashing seems to work but not subsequent writes. I think it is related to the httpclient library I'm using blocking the writes or something. The http calls are updating variables properly. If I comment out the http calls and use particle functions to write to my setpoint and toggle power it works.
#include <HttpClient.h>
#include "eeprom.h"
// #define RELAY_PIN D5 // Relay pin to control the heater
// Home Assistant Webhooks
const char* HA_SETPOINT_URL = "/api/webhook/set_thermostat";
const char* HA_TEMP_UPDATE_URL = "/api/webhook/receive_temp";
const char* HA_HOST = "192.168.0.43"; // Replace with your Home Assistant IP
const int HA_PORT = 8123;
// const char* responseBody = "";
// Create HTTP client
HttpClient http;
http_request_t request;
http_response_t response;
http_header_t headers[] = {
{ "Content-Type", "application/json" },
{ NULL, NULL } // End of headers
};
// Default setpoint (will be updated via webhook)
// double setpoint = 22.0;
// double temperature = 20.0; // Hardcoded for testing
double watchdog = 0;
TParameters Parameters;
int tempPin = A1;
int tempPin2 = A3;
float temperatureF = 0.0;
float actualTemp = 0;
double deadband = 1;
uint32_t msLastSample;
const uint32_t msSAMPLE_INTERVAL = 5000;
float temperature1 = 0.0;
float temperature2 = 0.0;
double temperature1D = 0.0;
double temperature1DFltr = 0.0;
double temperature2D = 0.0;
int relay = D7;
bool relayState = 0;
int fuelGauge = 0;
int prevFuelGauge = 0;
double maxRunTime = 0;
double setpoint = 85;
double temperature = 31;
bool targetMode = 0;
int currentMode = 0;
int resetFuel(String extra) { //function called from particle console to reset fuel tank to full
Parameters.runTime = 0;
Parameters.maxRunTime = Parameters.runTime;//143529.0;//Parameters.runTime; //calibrate fuel gauge to make next run more accurate
EEPROM.put(0, Parameters);
return 0;
}
float strength = -99.9;
int wifiStrength = -88;
int readingRaw = 0;
void setup() {
Particle.connect();
WiFi.selectAntenna(ANT_EXTERNAL); //ANT_AUTO, ANT_INTERNAL, ANT_EXTERNAL
randomSeed(Time.now());//we need to somehow init random seed, so device identity will be unique
Serial.begin();
Particle.function("resetFuel", resetFuel);
pinMode(tempPin, INPUT); //temperature input
pinMode(tempPin2, INPUT);
pinMode(relay, OUTPUT);
Particle.variable("Strength", wifiStrength);
Particle.variable("Temp1", temperature1DFltr);
Particle.variable("Temp2", temperature2D);
Particle.variable("Temp1Raw", readingRaw);
Particle.variable("Runtime", Parameters.runTime);
Particle.variable("Running", relayState);
Particle.variable("Fuel Gauge", fuelGauge);
Particle.variable("maxRunTime", maxRunTime);
Particle.variable("Setpoint", setpoint);
int reading = analogRead(tempPin);
double voltage = (reading * 3.3) / 4095.0;
readingRaw = reading;
temperature1 = (voltage - 0.5) * 100;
temperature1D = ((((voltage - 0.5) * 100) * 9.0) / 5.0) + 32.0;
temperature1DFltr = temperature1D;
EEPROM.get(0, Parameters);
if (Parameters.Magic != 0xA5A5) {
Parameters.Magic = 0xA5A5;
Parameters.runTime = 0;
Parameters.maxRunTime = 143529.0;
EEPROM.put(0, Parameters);
}
}
void loop() {
WiFiSignal sig = WiFi.RSSI();
strength = sig.getStrength();
wifiStrength = strength;
maxRunTime = Parameters.maxRunTime;
if (prevFuelGauge != fuelGauge){ //save runtime to eeprom every time the fuel gauge value changes
EEPROM.put(0, Parameters);
prevFuelGauge = fuelGauge;
}
if (millis() - msLastSample >= msSAMPLE_INTERVAL){
msLastSample = millis();
int reading = analogRead(tempPin);
double voltage = (reading * 3.3) / 4095.0;
readingRaw = reading;
temperature1 = (voltage - 0.5) * 100;
temperature1D = ((((voltage - 0.5) * 100) * 9.0) / 5.0) + 32.0;
int reading2 = analogRead(tempPin2);
double voltage2 = (reading2 * 3.3) / 4095.0;
temperature2 = (voltage2 - 0.5) * 100;
temperature2D = ((((voltage2 - 0.5) * 100) * 9.0) / 5.0) + 32.0;
if(targetMode == 1){
if(temperature1DFltr < setpoint - deadband){
relayState = 1;
currentMode = 1;
}
if(temperature1DFltr > setpoint){
relayState = 0;
currentMode = 0;
}
}
else{
relayState = 0;
currentMode = 0;
}
digitalWrite(relay, relayState);
// // Send temperature to Home Assistant
sendTemperatureToHA();
// Fetch updated setpoint from Home Assistant
fetchSetpointFromHA();
// // Fetch updated power from home assistant
fetchPwrFromHA();
// // Fetch updated watchdog from home assistant
fetchWatchdogFromHA();
if(relayState == 1){ //if heater add 5 sec to runtime
Parameters.runTime += 5;
fuelGauge = (Parameters.maxRunTime - Parameters.runTime) * 100 / Parameters.maxRunTime;
}
}
}
// Function to send temperature data to Home Assistant webhook
void sendTemperatureToHA() {
String payload = String::format("{\"value\": %.2f}", temperature1DFltr);
request.hostname = HA_HOST;
request.port = HA_PORT;
request.path = HA_TEMP_UPDATE_URL;
request.body = payload;
// Perform POST request
http.post(request, response, headers);
}
// Function to fetch setpoint from Home Assistant webhook
void fetchSetpointFromHA() {
request.hostname = HA_HOST;
request.port = HA_PORT;
request.path = "/api/states/input_number.thermostat_setpoint"; // Corrected endpoint
// **Add Home Assistant Authorization Token**
headers[0] = { "Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyNjQ1ZWU2ZjRmYWY0ZTQwOGY5OWZhMDg0MjM3YzdiMSIsImlhdCI6MTczOTE0NDU4NCwiZXhwIjoyMDU0NTA0NTg0fQ.wZuOZ3wGiPMeJDRNyLFPyyEM-LUKl-NuC1LMcOTBc3Q" };
headers[1] = { "Content-Type", "application/json" };
headers[2] = { NULL, NULL }; // End of headers
// Perform GET request
http.get(request, response, headers);
// Serial.println("------ Full HTTP Response ------");
// Serial.println("Status Code: " + String(response.status));
// Serial.println("Response Body: ");
// Serial.println(response.body);
// Serial.println("--------------------------------");
// **Check if the response is successful**
if (response.status != 200) {
// Serial.println("ERROR: Failed to get setpoint from HA.");
return;
}
// **Find the "state" key in the JSON response**
int stateIndex = response.body.indexOf("\"state\":\"");
if (stateIndex != -1) {
int valueStart = stateIndex + 9; // Move past `"state":"`
int valueEnd = response.body.indexOf("\"", valueStart); // Find closing quote
if (valueEnd != -1) {
String setpointStr = response.body.substring(valueStart, valueEnd);
setpoint = atof(setpointStr.c_str()); // Proper conversion to double
Serial.println("Updated Setpoint: " + String(setpoint)); // Debug output
}
} else {
Serial.println("ERROR: 'state' key not found in response.");
}
}
void fetchPwrFromHA() {
request.hostname = HA_HOST;
request.port = HA_PORT;
request.path = "/api/states/input_boolean.thermostat_power"; // Updated for boolean entity
// Serial.println("Fetching power from Home Assistant...");
// **Add Home Assistant Authorization Token**
headers[0] = { "Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyNjQ1ZWU2ZjRmYWY0ZTQwOGY5OWZhMDg0MjM3YzdiMSIsImlhdCI6MTczOTE0NDU4NCwiZXhwIjoyMDU0NTA0NTg0fQ.wZuOZ3wGiPMeJDRNyLFPyyEM-LUKl-NuC1LMcOTBc3Q" };
headers[1] = { "Content-Type", "application/json" };
headers[2] = { NULL, NULL }; // End of headers
// Perform GET request
http.get(request, response, headers);
// Serial.println("------ Full HTTP Response ------");
// Serial.println("Status Code: " + String(response.status));
// Serial.println("Response Body: ");
// Serial.println(response.body);
// Serial.println("--------------------------------");
// **Check if the response is successful**
if (response.status != 200) {
// Serial.println("ERROR: Failed to get power state from HA.");
return;
}
// **Find the "state" key in the JSON response**
int stateIndex = response.body.indexOf("\"state\":\"");
if (stateIndex != -1) {
int valueStart = stateIndex + 9; // Move past `"state":"`
int valueEnd = response.body.indexOf("\"", valueStart); // Find closing quote
if (valueEnd != -1) {
String powerState = response.body.substring(valueStart, valueEnd);
targetMode = (powerState == "on"); // Convert to boolean
// Serial.println("Updated Power: " + String(targetMode ? "ON" : "OFF")); // Debug output
}
} else {
Serial.println("ERROR: 'state' key not found in response.");
}
}
// Function to fetch setpoint from Home Assistant webhook
void fetchWatchdogFromHA() {
request.hostname = HA_HOST;
request.port = HA_PORT;
request.path = "/api/states/input_number.thermostat_watchdog2"; // Corrected endpoint
// Serial.println("Fetching watchdog from Home Assistant...");
// **Add Home Assistant Authorization Token**
headers[0] = { "Authorization", "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIyNjQ1ZWU2ZjRmYWY0ZTQwOGY5OWZhMDg0MjM3YzdiMSIsImlhdCI6MTczOTE0NDU4NCwiZXhwIjoyMDU0NTA0NTg0fQ.wZuOZ3wGiPMeJDRNyLFPyyEM-LUKl-NuC1LMcOTBc3Q" };
headers[1] = { "Content-Type", "application/json" };
headers[2] = { NULL, NULL }; // End of headers
// Perform GET request
http.get(request, response, headers);
// Serial.println("------ Full HTTP Response ------");
// Serial.println("Status Code: " + String(response.status));
// Serial.println("Response Body: ");
// Serial.println(response.body);
// Serial.println("--------------------------------");
// **Check if the response is successful**
if (response.status != 200) {
// Serial.println("ERROR: Failed to get setpoint from HA.");
return;
}
// **Find the "state" key in the JSON response**
int stateIndex = response.body.indexOf("\"state\":\"");
if (stateIndex != -1) {
int valueStart = stateIndex + 9; // Move past `"state":"`
int valueEnd = response.body.indexOf("\"", valueStart); // Find closing quote
if (valueEnd != -1) {
String watchdogStr = response.body.substring(valueStart, valueEnd);
watchdog = watchdogStr.toFloat(); // Convert to float
// Serial.println("Updated Watchdog:" + String(watchdog)); // Debug output
}
} else {
Serial.println("ERROR: 'state' key not found in response.");
}
}