";
s += "After update, the reconnection only via IP, without arguments behind it!
";
s += "Click here for reconnect after update ";
} else{
s += "Wrong firmware for this IoT. Update canceled. ";
argument ="";
}
} else {
s += "Error: Missing name of update file! ";
s += "Update canceled. ";
argument ="";
}
s += HTTP_TEXT_END;
}
#endif
else if(argument == "/setTime"){
s = HTTP_ANSWER;
s += HTTP_BODYSTYLE_PWR; s += "";
s += HTTP_DIV_FIELD;
s += "
Die Uhr wird jetzt neu synchronisiert.
";
s += "
Zeit:
";
if (syncron_NTP_Time() == true){
getTime2Value(_timestamp);
s += "Neue Zeit:
";
} else {
s += "Serverfehler! Aktuallisierung nicht erfolgt. Bitte eine Wartezeit von 2 Minuten, bis zur wiederholten, manuellen Aktuallisierung einhalten. ";
}
s += "
";
s += HTTP_TEXT_END;
}
else s = "HTTP/1.1 403 OK\r\nContent-Type: text/html\r\n\r\n";
// Send the response to the client
client.print(s);
delay(1);
#ifdef OTA_on
if(argument == "/upDate"){
turnAllOff();
int valueBegin = line.indexOf("?");
if(valueBegin > 0){
int valueEnd = line.indexOf("HTTP");
argument = line.substring(valueBegin+1,valueEnd-1);
delay(1000); //wait one second
updateStromLog(argument); // start update now
}
}
#endif
}
}
}
//*********** update new firmware ****************************************/
//*********** get available files ****************************************/
#ifdef OTA_on
String getFilesFromServer(IPAddress ip){
String files = "";
if (WiFi.status() == WL_CONNECTED) {
WiFiClient client;
HTTPClient http;
String target = "http://"; target+=cPWR.getTargetServer(); target+="/fwpwr/getFiles.php";
if (http.begin(client,target)){
http.addHeader("Content-Type","application/json;charset=utf-8");
int httpCode = http.POST("{\"userIP\":\""+ip.toString()+"\",\"build\":\""+Version+"\"}");
if(httpCode >= 100){
files = http.getString();
}
else{
files = "Error: no connection. Return: "; files+=httpCode; files+=" ";
files+= target;
}
}
http.end();
}
return files;
}
//********** update, input file-name ************************************/
String updateStromLog(String file){
delay(500);
String result = "ERROR: Update failed!";
ESPhttpUpdate.rebootOnUpdate(false); // remove automatic update
digitalWrite(blueLED,LEDON);
WiFiClient client;
t_httpUpdate_return ret = ESPhttpUpdate.update(client, cPWR.getTargetServer(), 80, "/fwpwr/"+file);
switch (ret) {
case HTTP_UPDATE_FAILED:
break;
case HTTP_UPDATE_NO_UPDATES:
break;
case HTTP_UPDATE_OK:
String result = "Update successful.";
delay(500); // Wait a second and restart
ESP.restart();
break;
}
return result;
}
#endif
//*********** update end *************************************************/
//*********** prepare URL sending parameters *************/
//*********** send values to server **********************/
//***********************************************************
bool send2dbase(String restPoint, String content){
// Serial.println(t1); Serial.println(hum); Serial.println(hPa); Serial.println(heaterOnOff);
bool r=false;
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure clientSSL;
WiFiClient client;
HTTPClient http;
bool connect;
// String getTarget = cPWR.getTargetURLclean();
String target;
if(cPWR.SendSSL>0){
target = "https://"; target += restPoint;
int httpsPort=443;
clientSSL.setInsecure(); // magic line without check certificate because memory insufficient
clientSSL.connect(target,httpsPort); // set connection by https
connect = http.begin(clientSSL,target);
}else{
target= "http://"; target += restPoint;
connect = http.begin(client,target);
}
if(connect){
// http.setTimeout(10000); // 10 seconds?
http.addHeader("Content-Type","application/x-www-form-urlencoded");
int httpCode = 0; _SendResult = "";
httpCode = http.POST(content);
_httpMarker = httpCode; //debug
if (httpCode >= 100) {
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_NO_CONTENT){
_SendResult = http.getString();
if (_SendResult == "OK " || httpCode == HTTP_CODE_NO_CONTENT){
_SendResult = "Temperatur wurde gesendet: "+getTime2String(_hour,_minute,_second);
r = true; // if data saved successful than result=true else false
} else {
r = false;
}
} else {_SendResult ="[HTTP] Unable to connect! "; r = false; _SendResult +=httpCode;}
} else {_SendResult ="[HTTP] missing return-code!"; r = false;}
} else {_SendResult ="[HTTP] Service not connect!"; r = false;}
http.end();
}
if(r == false) _flashCounter = 300; // time to show flash on LED for infos
return r;
}
//*********** prepaire send string ***********************/
String prepaireValues2Send(){
String ret ="&time="; ret += _timestamp;
ret+="&name="; ret += cPWR.getPName();
ret+="&usip="; ret += WiFi.localIP().toString();
ret+="&name1=KesselTemperatur&temp1="; ret += int(_temperature0*1000);
ret+="&name2=HeizstabTemperatur&temp2="; ret += int(_temperature1*1000);
return ret;
}
//*********** get json data from meter *******************/
bool getConsumptionMeter(String restEndPoint){
bool r=false;
if (WiFi.status() == WL_CONNECTED) {
WiFiClient client;
HTTPClient http;
String target = "http://"; target += restEndPoint;
int httpCode = 0;
if (http.begin(client,target)){
httpCode = http.GET();
if (httpCode == HTTP_CODE_OK){
_TransmitResult = http.getString();
r=true;
#ifdef DEBUG_PAYLOAD
Serial.println(httpCode);
Serial.println(_TransmitResult);
#endif
} else {_TransmitResult ="Missing answer! "; _TransmitResult +=httpCode;}
} else _TransmitResult ="Target not found!";
http.end();
} else _TransmitResult ="WiFi not connect to meter!";
return r;
}
/***********************************************************
* convert a unix-timestamp into single bytes as value
* function works up to 1972 until 19.01.2038
***********************************************************/
uint32_t Timestamp2DateTime(uint32_t unixTime){
int dummy = 0; int years=0;
uint32_t SecOfYear; uint32_t timeDummy;
bool leapYear = false; // default: don't be a leap-year
timeDummy = unixTime - 31536000 *2; // sub two years (1970 and 1971) add the years later
years= (timeDummy / 126230400) *4; // get the periodes of four years cycle; 3Y+leapY = 126230400 seconds
timeDummy = timeDummy % 126230400; // get the rest of timestamp without the cycles like above this line
if (timeDummy >= 31622400) {
timeDummy -= 31622400; // sub the first leap-year if it's over
years++; // add the leapyear
years += timeDummy / 31536000; // get the rest of years between 0 until 2 years
}
years = years + 1972; // add start-year +2: now, we know the actual year and can figure out if is a leap-year
_date_time[YEAR]=years;
// if (year % 4 == 0) leapYear = true; // if year divison by four without some rest, then is a leap-year...yeeeh -> it works until 2036 only
if ( bitRead(years,0)==0 && bitRead(years,1)==0) { // it's very faster than %-arithmetic
leapYear = true;
SecOfYear = 31622400; // set the counts of seconds leap-year
// Serial.print("LeapYear ");
} else SecOfYear = 31536000; // or don't be a leap-year -> regulary seconds
_date_time[DAY] = (timeDummy % SecOfYear) / 86400; // get the days of actual year
_date_time[MONTH] = 0; // set zero
for (int i=0; _date_time[DAY]>=0; i++ ) { // do it until the day(s) are negativ, this loop has be exicute one time -> to set month at ones
dummy = _date_time[DAY]; // store the value befor result is negativ for break, because the last one was the day of actual month
_date_time[DAY] = _date_time[DAY] - DaysPerMonth[i]; // sub the days of month until it's negativ, according byte-array
if (i == 1 && leapYear == true) {_date_time[DAY] -= 1;} // sub the 29. of february on leapyears ;-)
_date_time[MONTH]++; // add one month on every loop
if (i > 11) return -1; // if this function wild ;-) then break (max. months are 0 - 11)
}
_date_time[DAY] = dummy+1; // add one, because the start was on 1. january (start of timstamp = 01.01.1970 and we have to add it)
/****** get time ******/
_date_time[HOUR] = (timeDummy % 86400) / 3600; // the value of _timeDummy contents the rest of hours, minutes and seconds only
_date_time[MINUTE] = (timeDummy % 3600) / 60; // it's shorter to take reduced _timeDummy than the whole timestamp
_date_time[SECOND] = timeDummy % 60;
// return values are in array "unsigned int _date_time[6]; //[YEAR][MONTH][DAY][HOUR][MINUTE][SECOND]"
return timeDummy; // return just the time without year, month and date. Its in use for daily events at the same times
}
void writeTime(){
_year = _date_time[YEAR];
_month = _date_time[MONTH];
_day = _date_time[DAY];
_hour = _date_time[HOUR];
_minute = _date_time[MINUTE];
_second = _date_time[SECOND];
}
void getTime2Value(uint32_t unixTime){
Timestamp2DateTime(unixTime);
writeTime();
}
//****************************** show received a protocol on red LED ***************************
void showProtocolOnLED(){
}
//**** get temperature from sensor DS18B20 ***************//
void getValuesTemperature() {
float tempDummy=0;
int readError=0;
oneWire.reset();
sensors.requestTemperatures();
tempDummy=sensors.getTempCByIndex(0);
if (tempDummy > -20 || _tempRequestError >=10) {
if(_exchangeTemp) _temperature1 = tempDummy;
else _temperature0 = tempDummy;
} else readError++;
tempDummy=sensors.getTempCByIndex(1);
if(tempDummy > -20 || _tempRequestError >=10){
if(_exchangeTemp) _temperature0 = tempDummy;
else _temperature1 = tempDummy;
} else readError++;
if(readError>0)_tempRequestError++;
if(_tempRequestError > 10 || readError == 0){
_tempRequestError=0;
}
if(_temp0Max < int(_temperature0-1000))_temp0Max = int(_temperature0-1000);
if(_temp1Max < int(_temperature1-1000))_temp1Max = int(_temperature1-1000);
if(_temp0Min > int(_temperature0-1000))_temp0Min = int(_temperature0-1000);
if(_temp1Min > int(_temperature1-1000))_temp1Min = int(_temperature1-1000);
}
//*********************** decode value from JSON *********************************
int decodeValue(){
_receivedOK=true;
int consumptionValue=0;
int valueBegin = _TransmitResult.indexOf("value");
if(valueBegin >= 0){
int valueEnd = _TransmitResult.indexOf(",",valueBegin);
if (valueEnd != -1){
String value = _TransmitResult.substring(valueBegin+7, valueEnd);
consumptionValue=value.toInt();
#ifdef DEBUG_VALUE
Serial.println(value);
#endif
}
// add cascading off PWM-regulation, get value of master
valueBegin = _TransmitResult.indexOf("pwm"); // check of master
if(valueBegin > 32){
int valueEnd = _TransmitResult.indexOf(",",valueBegin);
String value = _TransmitResult.substring(valueBegin+5, valueEnd);
_masterPWM=value.toInt();
} else _masterPWM=0; // no master recognised
// end of get PWM value of master
} else {
consumptionValue=0;
_receivedOK=false;
}
#ifdef DEBUG_VALUE
Serial.println(consumptionValue);
#endif
return consumptionValue;
}
//*********************** setup esp on start *****************************
void setup() {
pinMode(blueLED, OUTPUT); // set as output
digitalWrite(blueLED,LEDOFF);
SetupRelais();
_flashCounter = 30; // time to show flash on LED for infos
#ifdef SERIAL_ON
Serial.begin(115200);
#else
pinMode(BoardTaster, INPUT_PULLUP); // set as input
// pinMode(LEDboard, OUTPUT); // set as output (blue LED)
#endif
delay(200);
wifi_station_set_hostname("PWM_Regler"); // set hostname into WLAN network
bool result = setupWIFI();
if (result) {
cPWR.begin(); // start filesystem and properties of user
server.begin();
syncron_NTP_Time();
getTime2Value(_timestamp);
delay(200);
}
else {
for (int i=0 ; i<20;i++){
if (digitalRead(blueLED) == LEDOFF)digitalWrite(blueLED,LEDON); else digitalWrite(blueLED,LEDOFF);
delay(200);
}
ESP.restart();
}
sensors.getDeviceCount();
_temperature0 = sensors.getTempCByIndex(0);
setMQTTserver();
}
//************************* esp loop function ***************************
void loop() {
yield();
// disabled checkButton(); // check if user pressed button for set new SSID
uint32_t currentMillis = millis();
if(internClock(currentMillis)== true) { // every second will run this component
//*** mqtt part ***//
if(cPWR.SendMQTT){handleMQTTclient();}// check if mqtt is enabled
//*** mqtt part end ***//
if (_flashCounter > 0){ // Flash LED when errors occurs or for information
if (digitalRead(blueLED) == LEDOFF)digitalWrite(blueLED,LEDON); else digitalWrite(blueLED,LEDOFF);
_flashCounter --;
} else digitalWrite(blueLED,LEDOFF); // if flashtime over turn off LED
if (_hour == 23 && _minute==25 && _second==3){ // update _timestamp
if (syncron_NTP_Time() == true){
getTime2Value(_timestamp);
}
_sumConsumption=0; // set zero the sum of consumption every day
_errorCount=0;
_temp0Max=0;
_temp0Min=100000;
_temp1Max=0;
_temp1Min=100000;
}
if (_timestamp < TimeOf2021) { // change function that not every minute is calling the NTP-Server() Because there have to be a wait-time of min. 2 minute!
if(_minute % 5 ==0 && _second == 50){
if (syncron_NTP_Time() == true) getTime2Value(_timestamp); // get timestamp again if sync was failure, perhaps after power down
}
}
if(cPWR.getSend2Server()){
if(_minute % 15==0 && _second == 1) send2dbase(cPWR.getTargetURLclean(),prepaireValues2Send()); // send temperatur to server
}
if(_second % cPWR.getScanTime() == 0){ // handle get data from meter and switch relais
if(cPWR.getAutomatic()){ // is automatic on
if(getConsumptionMeter(cPWR.getTargetMeter())){ // get value of consumption from meter
_actualConsumption = decodeValue(); // decode value of consumption
#ifdef PC_EMULATOR
_TransmitResult="PC als Mock verbunden IP: ";
_TransmitResult += cPWR.getTargetMeter();
#else
_TransmitResult="Verbunden mit Strom-Zähler";
#endif
_errorWait=0; // set error wait of zero
if(_calibrationON == false)
handleRegulation(_actualConsumption,_masterPWM); // handle turn on off PWM control, circulation pump and secure relais, that can using as two point regulation
else handleCalibrationEntry(_actualConsumption,cPWR.getScanTime()); // handle calibration tool
saveDiagramWatt(_timestamp, relais.PWM_Power);
} else {
_errorWait++; // count error wait
errorConnect(); // if connection lost turn off relais after errorWait value
if(cPWR.SendMQTT){sendError2MQTT(_TransmitResult);}
#ifdef PC_EMULATOR
_TransmitResult="PC als Mock failed!";
#else
_TransmitResult="Zähler nicht gefunden (Timeout)";
#endif
if(!WiFi.isConnected()){
_flashCounter=20;
if(_errorWait > 20){
delay(500);
ESP.restart(); // connect lost do restart
}
}
}
#ifdef DEBUG_CONNECT
Serial.print("Status: "); Serial.println(WiFi.status());
Serial.print("RRSI: "); Serial.println(WiFi.RSSI());
Serial.print("ErroWait: "); Serial.println(_errorWait);
#endif
} else {
_TransmitResult="Automatic is off";
_actualConsumption = 0; //set zero because not connect to meter
turnOffCirculationPump();
turnAllOff();
}
}// else _TransmitResult="Error: No meter scan!";
if(_second % 10 ==0){
getValuesTemperature(); // get temperature of sensor DS18B20
}
}
check4Client(); // thats it's if with the browser show data on port 80 by html
}