Digital outputs not working when using httpclient library

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.");
    }
}

I now have the http calls in a slower loop running every 30 seconds. The 5 second loop is setting the digital output several times in between yet the write is not working. Is this httpclient somehow messing with the gpio?

My guess is that all of those HTTP requests just take a long time to execute. You should log the time that all of those operations take. Assuming they're all necessary, and say, take 15 seconds to run, but you want to process the short sample interval from a thread so the http operations don't block the sensing and relay control.

I put the http calls in a thread and still have the same problem. I got time before and after the http calls and it is less than 2 seconds. http calls are every 30 seconds and other temperature control logic with digital pin write is every 5 seconds.

I also tried it the other way around with the temperature control and digital pin write in a thread.

Then I added an if statement so I could turn off the http calls with a particle function. I started with them turned off. With another particle function I can turn on the heater logic and change the setpoint. Everything works. When allow the http calls to execute the digital pin no longer works even if I don't allow the http calls again. Once an http call has been made my digital pin can no longer be written to. It remains stuck in the its last state whether that is on or off.

I don't think this has anything to do with blocking. It seems to be directly breaking the ability to write to my pin

I finally got something to work! But I don't understand it. It took 2 things to make it work.

I had to change this code. Instead of using the variable the relay variable that was assigned to D7 I had to hard code D7. I don't know why this matters since it works fine when I have the http calls disabled and I run the code.
// digitalWrite(relay,relayState);
digitalWrite(D7,relayState);

Second, I have to with the http calls disable and enable them a few seconds after starting. Strangely this doesn't work with a delay before the http calls.

Luck that I figured out these 2 things would get it working. I'll keep trying understand what is going on. Right now this isn't workable because I have to enable the http calls but that has to be automatable.

@pitchlynn, just a few observations:

  • when declaring values which will not change, it is good practice to use "const". So when you declare your pins, useconst int tempPin = A1 for example.
  • headers[] is declared as a two element array through:
  http_header_t headers[] = {
      { "Content-Type", "application/json" },
      { NULL, NULL } // End of headers
};

YET, you assign values to THREE headers array elements using:

    // **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

This will overwrite memory, likely explaining the relay variable issue. I'm surprised this was not flagged by the compiler. Since the http_header_t structure uses pointers for each header entry, you can simply initialize headers with a third item like a duplicate of the "End of headers entry" like this:

http_header_t headers[] = {
    { "Content-Type", "application/json" },
    { NULL, NULL },
    { NULL, NULL } // End of headers
};

I could not get your code to compile on the Web IDE since I was getting an error from the HttpClient.cpp file which was not obvious.

2 Likes

Thank you so much!!! Adding the third array element to the declaration solved both of my problems. My digital output is working and I don't have to delay the first http calls either.

Thanks for looking at my horrible code. I'm not great at it and admittedly used AI to write some of it. But it is working now. I'll post my working code in case someone finds it useful. I'm running this on a photon and it is a wifi thermostat for my shop heater that interfaces with Home Assistant using hass-template-climate and http webhooks and can be accessed from apple home using the home bridge integration. I have some safety circuits that use external temperature sensors. I like that it is local to my network and doesn't require an mqtt broker to be hosted (although I have not really tried mqtt yet)

#include <HttpClient.h>
#include "eeprom.h"

// 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;

// Create HTTP client
HttpClient http;
http_request_t request;
http_response_t response;

http_header_t headers[] = {
   { "Content-Type", "application/json" },
   { NULL, NULL },
   { NULL, NULL } // End of headers
};

double watchdog = 0;

TParameters Parameters;

//temp sensors
int tempPin = A1;
int tempPin2 = A3;
float temperatureF = 0.0;
float actualTemp = 0;
double deadband = 0;
uint32_t msLastSample;
uint32_t msLastSample2;
const uint32_t msSAMPLE_INTERVAL = 5000;
const uint32_t msSAMPLE_INTERVAL2 = 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;

bool enableHttp = 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;
}

int togglePWR(String extra) {
 if (targetMode == 0) {
   targetMode = 1;
 }
 else {
   targetMode = 0;  
 }
 return 0;
}

int toggleEnable(String extra) {
 if (enableHttp == 0) {
   enableHttp = 1;
 }
 else {
   enableHttp = 0;  
 }
 return 0;
}

int ChangeSetpoint(String extra) {
 setpoint = extra.toInt();
 return 0;
}

float strength = -99.9;
int wifiStrength = -88;
int readingRaw = 0;

void setup() {

   // Connect to WiFi
   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);
   Particle.function("togglePWR", togglePWR);
   Particle.function("ChangeSetpoint", ChangeSetpoint);
   Particle.function("toggleEnable",  toggleEnable);

 
   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);
   Particle.variable("EnableHttp", enableHttp);
 
   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);
       Serial.print("relayState after logic: ");
       Serial.println(relayState);

       if(relayState == 1){ //if heater add 5 sec to runtime
           Parameters.runTime += 5;
           fuelGauge = (Parameters.maxRunTime - Parameters.runTime) * 100 / Parameters.maxRunTime;
           Serial.print("add 5 secs");
       }   

   }    

   enableHttp = 1;
   if (millis() - msLastSample2 >= msSAMPLE_INTERVAL2){
       msLastSample2 = millis();

       if (enableHttp == 1){
           // // 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();
           Serial.print("Http loop");
       }
 }

}

// 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";  //

   // Serial.println("Fetching Setpoint 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 setpointStr = response.body.substring(valueStart, valueEnd);
           setpoint = round(atof(setpointStr.c_str()));  
           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"; 

   // 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"); 
           // 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";  

   // 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.");
   }
}



1 Like