void measureTempHum() {
  float tmpHum = round(dht.readHumidity());
  float tmpTemp = dht.readTemperature();  // Read temperature as Celsius (the default)

  int tmpHumInt = tmpHum;

  // Check if any reads failed
  if (isnan(tmpHum) || isnan(tmpTemp)) {
    //Serial.println("Failed to read from DHT sensor!");
    sendStatus("Error: Failed to read from DHT sensor!");
  }
  else {
    if (tmpTemp < 50.0 && tmpTemp > -20.0) {
      // measurement is in range
      if ( lastTempUpdate > 0 && tmpTemp <= ( temperature + 2.0 ) && tmpTemp >= ( temperature - 2.0 ) ) {
        // temp has already been measured - only accept new measurement if it does not differ much from the last value
        //Temp = (Temp * (FilterFaktor -1) + AktuellerMesswert) / FilterFaktor;
        //temperature = tmpTemp;
        temperature = ((temperature * 9 + tmpTemp) / 10) + tempCorrVal; // filter
        humidity = tmpHumInt + humCorrVal;
        lastTempUpdate = millis();
      }
      else if ( lastTempUpdate == 0 || (millis() - lastTempUpdate) > 300000 ) {
        // this is the first measurement or the last one is older than 5m - then accept this measurement
        temperature = tmpTemp + tempCorrVal;
        humidity = tmpHumInt + humCorrVal;
        lastTempUpdate = millis();

      }
      // skip in all other cases

      //#ifdef DEBUG_VERBOSE
      //      Serial.print("lastTempUpdate: ");
      //      long lastTempUpdateDelta = millis() - lastTempUpdate;
      //      Serial.print(lastTempUpdateDelta / 1000);
      //      Serial.println("s ago");
      //#endif
    }
  }
}

void thermostat() {
  float curr_setTemp;
  // set target temp for heating mode
  if (heatingMode == 1) { // heating on - default/day mode
    curr_setTemp = setTemp;
  }
  else if (heatingMode == 2) { // heating of - night/reduction mode
    curr_setTemp = setTempLow;
  }

  char tmp_topic_out[50];
  if (heatingMode > 0 && turnHeatingOn) {
    heatingOnTime = (millis() - heatingLastOnMillis) / 1000;

    char buf[101];
    sprintf(buf, "heating on since %d s", heatingOnTime);
    sendStatus(buf);
  }
  else if (heatingMode > 0 && !turnHeatingOn) {
    heatingOffTime = (millis() - heatingLastOffMillis) / 1000;

    char buf[101];
    sprintf(buf, "heating off since %d s", heatingOffTime);
    sendStatus(buf);
  }


  //char tmp_topic_out[50];
  //sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating");

  if ( lastTempUpdate != 0 && (millis() - lastTempUpdate) <= 120000 ) {
    // thermostat - only active if measured temperature is < 2 min old

#ifdef DEBUG_VERBOSE
    Serial.print("thermostat, lastTempUpdate=");
    Serial.print(lastTempUpdate);
    Serial.print(", lastTempUpdate_delta=");
    long lastTempUpdateDelta = millis() - lastTempUpdate;
    Serial.println(lastTempUpdateDelta);
#endif

    // thermostat with hysteresis
    if ( turnHeatingOn && temperature >= curr_setTemp ) {
      turnHeatingOn = false;
      heatingLastOffMillis = millis();
      digitalWrite(PIN_RELAIS, !RELAISONSTATE);
      updateDisplay();

      char buf[101];
      sprintf(buf, "switch heating OFF, on since %d s", heatingOnTime);
      sendStatus(buf);

      //Serial.println("heating off");
      //mqttclient.publish(tmp_topic_out, "off");
      publishCurrentThermostatValues();
    }
    else if ( !turnHeatingOn && heatingMode > 0 && ( temperature < (curr_setTemp - hysteresis) ) && ( heatingOffTime > heatingMinOffTime ) ) {
      turnHeatingOn = true;
      heatingLastOnMillis = millis();
      digitalWrite(PIN_RELAIS, RELAISONSTATE);
      updateDisplay();

      char buf[101];
      sprintf(buf, "switch heating ON, off since %d s", heatingOffTime);
      sendStatus(buf);

      //Serial.println("heating on");
      //mqttclient.publish(tmp_topic_out, "on");
      publishCurrentThermostatValues();
    }
  }
  else {
    if (turnHeatingOn) {
      digitalWrite(PIN_RELAIS, !RELAISONSTATE);
      turnHeatingOn = false;
      heatingLastOffMillis = millis();
    }

    if ( lastTempUpdate != 0 ) sendStatus("switch heating OFF, temp reading not yet available");
    else if ( (millis() - lastTempUpdate) > 120000 ) sendStatus("switch heating OFF, last temp reading too old");

    //mqttclient.publish(tmp_topic_out, "off");
    publishCurrentThermostatValues();
  }

}

void toggleHeatingMode() {
  if (heatingMode > 0) {
    Serial.print("switch mode to ");
    if (heatingMode == 1) {
      heatingMode = 2;
      lastValueChange = millis();
      heatingModeAlreadySaved = false;
    }
    else if (heatingMode == 2) {
      heatingMode = 1;
      lastValueChange = millis();
      heatingModeAlreadySaved = false;
    }
    Serial.println(heatingMode);
    updateDisplay();
  }
}

void toggleThermostatOnOff() {
  if (heatingMode > 0) {
    heatingMode = 0;
    lastValueChange = millis();
    heatingModeAlreadySaved = false;
  }
  else {
    heatingMode = 1;
    lastValueChange = millis();
    heatingModeAlreadySaved = false;
  }
  updateDisplay();
}

void setTempStepUp() {
  if (heatingMode == 1) {
    Serial.println("+");
    if ( setTemp <= (setTempMax - 0.5)) {
      setTemp += 0.5;
      lastValueChange = millis();
      setTempAlreadySaved = false;
    }
    updateDisplay();
  }
}

void setTempStepDown() {
  if (heatingMode == 1) {
    Serial.println("-");
    if ( setTemp >= (setTempMin + 0.5)) {
      setTemp -= 0.5;
      lastValueChange = millis();
      setTempAlreadySaved = false;
    }
    updateDisplay();
  }
}

void setTempTo(float setTo) {
  bool changes = false;
  if (setTo >= setTempMin && setTo <= setTempMax) {
    setTemp = setTo;
    changes = true;
  }
  else if (setTo > setTempMax) {
    setTemp = setTempMax;
    changes = true;
  }
  else if (setTo < setTempMin) {
    setTemp = setTempMin;
    changes = true;
  }
  if (changes) {
    lastValueChange = millis();
    setTempAlreadySaved = false;
    updateDisplay();
    publishCurrentThermostatValues();
  }
}

void setTempLowTo(float setTo) {
  bool changes = false;
  if (setTo >= setTempLowMin && setTo <= setTempLowMax) {
    setTempLow = setTo;
    changes = true;
  }
  else if (setTo > setTempLowMax) {
    setTempLow = setTempLowMax;
    changes = true;
  }
  else if (setTo < setTempLowMin) {
    setTempLow = setTempLowMin;
    changes = true;
  }
  if (changes) {
    updateDisplay();
    publishCurrentThermostatValues();
  }
}

void setHeatingmodeTo(byte setTo) {
  bool changes = false;
  switch (setTo) {
    case 0:
      heatingMode = 0;
      changes = true;
      break;
    case 1:
      heatingMode = 1;
      changes = true;
      break;
    case 2:
      heatingMode = 2;
      changes = true;
      break;
  }
  if (changes) {
    lastValueChange = millis();
    heatingModeAlreadySaved = false;
    updateDisplay();
    publishCurrentThermostatValues();
  }
}

void checkValuesChanged() { // called every second by everySecond() / misc.ino
  if ( !setTempAlreadySaved || !heatingModeAlreadySaved ) {
    if ( (millis() - lastValueChange) > saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled
      if (!setTempAlreadySaved) {
        lastUpdate_setTemp = millis();
        sendToDomoticz_thermostat();
        if (autoSaveSetTemp && setTemp != setTempSaved) {
          saveSetTemp();
          sendStatus("setTemp autosave done");
        }
        setTempAlreadySaved = true;
      }
      if (!heatingModeAlreadySaved) {
        lastUpdate_heatingMode = millis();
        sendToDomoticz_heatingMode();
        if (autoSaveHeatingMode && heatingMode != heatingModeSaved) {
          saveHeatingMode();
          sendStatus("heatingMode autosave done");
        }
        heatingModeAlreadySaved = true;
      }
    }
  }
}


