Browse Source

changed timestamp to UTC in ESP only, local timezone is calculated by browser thx @homeautomation22

pull/372/head
lumapu 2 years ago
parent
commit
72219cdf17
  1. 58
      tools/esp8266/app.cpp
  2. 10
      tools/esp8266/app.h
  3. 4
      tools/esp8266/hmDefines.h
  4. 8
      tools/esp8266/html/index.html
  5. 12
      tools/esp8266/html/visualization.html

58
tools/esp8266/app.cpp

@ -58,8 +58,6 @@ void app::loop(void) {
mUptimeSecs++; mUptimeSecs++;
if(0 != mUtcTimestamp) if(0 != mUtcTimestamp)
mUtcTimestamp++; mUtcTimestamp++;
if(0 != mTimestamp)
mTimestamp++;
} }
if(checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) { if(checkTicker(&mNtpRefreshTicker, mNtpRefreshInterval)) {
@ -70,8 +68,7 @@ void app::loop(void) {
if(mUpdateNtp) { if(mUpdateNtp) {
mUpdateNtp = false; mUpdateNtp = false;
mUtcTimestamp = mWifi->getNtpTime(); mUtcTimestamp = mWifi->getNtpTime();
mTimestamp = mUtcTimestamp + ((TIMEZONE + offsetDayLightSaving(mUtcTimestamp)) * 3600); DPRINTLN(DBG_INFO, F("[NTP]: ") + getDateTimeStr(mUtcTimestamp) + F(" UTC"));
DPRINTLN(DBG_INFO, "[NTP]: " + getDateTimeStr(mTimestamp));
} }
if(mFlagSendDiscoveryConfig) { if(mFlagSendDiscoveryConfig) {
@ -157,10 +154,12 @@ void app::loop(void) {
mMqtt.loop(); mMqtt.loop();
if(checkTicker(&mTicker, 1000)) { if(checkTicker(&mTicker, 1000)) {
if(mTimestamp > 946684800 && mConfig.sunLat && mConfig.sunLon && mTimestamp / 86400 > mLatestSunTimestamp / 86400) // update on reboot or new day if(mUtcTimestamp > 946684800 && mConfig.sunLat && mConfig.sunLon && (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 > (mLatestSunTimestamp + mCalculatedTimezoneOffset) / 86400) { // update on reboot or midnight
{ if (!mLatestSunTimestamp) { // first call: calculate time zone from longitude to refresh at local midnight
mCalculatedTimezoneOffset = (int8_t)((mConfig.sunLon >= 0 ? mConfig.sunLon + 7.5 : mConfig.sunLon - 7.5) / 15) * 3600;
}
calculateSunriseSunset(); calculateSunriseSunset();
mLatestSunTimestamp = mTimestamp; mLatestSunTimestamp = mUtcTimestamp;
} }
if((++mMqttTicker >= mMqttInterval) && (mMqttInterval != 0xffff) && mMqttActive) { if((++mMqttTicker >= mMqttInterval) && (mMqttInterval != 0xffff) && mMqttActive) {
@ -185,7 +184,7 @@ void app::loop(void) {
Inverter<> *iv = mSys->getInverterByPos(id); Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL != iv) { if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
if(iv->isAvailable(mTimestamp, rec)) { if(iv->isAvailable(mUtcTimestamp, rec)) {
DPRINTLN(DBG_INFO, "Inverter: " + String(id)); DPRINTLN(DBG_INFO, "Inverter: " + String(id));
for(uint8_t i = 0; i < rec->length; i++) { for(uint8_t i = 0; i < rec->length; i++) {
if(0.0f != iv->getValue(i, rec)) { if(0.0f != iv->getValue(i, rec)) {
@ -205,7 +204,7 @@ void app::loop(void) {
if(++mSendTicker >= mConfig.sendInterval) { if(++mSendTicker >= mConfig.sendInterval) {
mSendTicker = 0; mSendTicker = 0;
if(mUtcTimestamp > 946684800 && (!mConfig.sunDisNightCom || !mLatestSunTimestamp || (mTimestamp >= mSunrise && mTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set) if(mUtcTimestamp > 946684800 && (!mConfig.sunDisNightCom || !mLatestSunTimestamp || (mUtcTimestamp >= mSunrise && mUtcTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
if(mConfig.serialDebug) if(mConfig.serialDebug)
DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX)); DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX));
@ -391,7 +390,7 @@ void app::processPayload(bool retransmit) {
if(mPayload[iv->id].txId == (TX_REQ_INFO + 0x80)) if(mPayload[iv->id].txId == (TX_REQ_INFO + 0x80))
mStat.rxSuccess++; mStat.rxSuccess++;
rec->ts = mPayload[iv->id].ts + ((TIMEZONE + offsetDayLightSaving(mUtcTimestamp)) * 3600); rec->ts = mPayload[iv->id].ts;
for(uint8_t i = 0; i < rec->length; i++) { for(uint8_t i = 0; i < rec->length; i++) {
iv->addValue(i, payload, rec); iv->addValue(i, payload, rec);
yield(); yield();
@ -407,7 +406,7 @@ void app::processPayload(bool retransmit) {
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
Inverter<> *iv = mSys->getInverterByPos(id); Inverter<> *iv = mSys->getInverterByPos(id);
if (NULL != iv) { if (NULL != iv) {
if (iv->isAvailable(mTimestamp, rec)) { if (iv->isAvailable(mUtcTimestamp, rec)) {
for (uint8_t i = 0; i < rec->length; i++) { for (uint8_t i = 0; i < rec->length; i++) {
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
snprintf(val, 10, "%.3f", iv->getValue(i, rec)); snprintf(val, 10, "%.3f", iv->getValue(i, rec));
@ -423,7 +422,7 @@ void app::processPayload(bool retransmit) {
} }
} }
if(iv->isProducing(mTimestamp, rec)){ if(iv->isProducing(mUtcTimestamp, rec)){
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_PRODUCED); snprintf(val, 32, DEF_MQTT_IV_MESSAGE_INVERTER_AVAIL_AND_PRODUCED);
mMqtt.sendMsg(topic, val); mMqtt.sendMsg(topic, val);
@ -484,7 +483,7 @@ void app::processPayload(bool retransmit) {
if(mMqttActive) { if(mMqttActive) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
char topic[32 + MAX_NAME_LENGTH], val[32]; char topic[32 + MAX_NAME_LENGTH], val[32];
if (!iv->isAvailable(mTimestamp, rec) && !iv->isProducing(mTimestamp, rec)){ if (!iv->isAvailable(mUtcTimestamp, rec) && !iv->isProducing(mUtcTimestamp, rec)){
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
snprintf(val, 32, DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED); snprintf(val, 32, DEF_MQTT_IV_MESSAGE_NOT_AVAIL_AND_NOT_PRODUCED);
mMqtt.sendMsg(topic, val); mMqtt.sendMsg(topic, val);
@ -615,7 +614,7 @@ void app::sendMqttDiscoveryConfig(void) {
if(NULL != iv) { if(NULL != iv) {
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
// TODO: next line makes no sense if discovery config is send manually by button // TODO: next line makes no sense if discovery config is send manually by button
//if(iv->isAvailable(mTimestamp, rec) && mMqttConfigSendState[id] != true) { //if(iv->isAvailable(mUtcTimestamp, rec) && mMqttConfigSendState[id] != true) {
DynamicJsonDocument deviceDoc(128); DynamicJsonDocument deviceDoc(128);
deviceDoc["name"] = iv->name; deviceDoc["name"] = iv->name;
deviceDoc["ids"] = String(iv->serial.u64, HEX); deviceDoc["ids"] = String(iv->serial.u64, HEX);
@ -698,10 +697,8 @@ void app::resetSystem(void) {
#ifdef AP_ONLY #ifdef AP_ONLY
mUtcTimestamp = 1; mUtcTimestamp = 1;
mTimestamp = 1;
#else #else
mUtcTimestamp = 0; mUtcTimestamp = 0;
mTimestamp = 0;
#endif #endif
mHeapStatCnt = 0; mHeapStatCnt = 0;
@ -893,29 +890,11 @@ void app::resetPayload(Inverter<>* iv) {
mPayload[iv->id].ts = mUtcTimestamp; mPayload[iv->id].ts = mUtcTimestamp;
} }
//-----------------------------------------------------------------------------
// calculates the daylight saving time for middle Europe. Input: Unixtime in UTC
// from: https://forum.arduino.cc/index.php?topic=172044.msg1278536#msg1278536
uint8_t app::offsetDayLightSaving (uint32_t local_t) {
//DPRINTLN(DBG_VERBOSE, F("wifi::offsetDayLightSaving"));
int m = month (local_t);
if(m < 3 || m > 10) return 0; // no DSL in Jan, Feb, Nov, Dez
if(m > 3 && m < 10) return 1; // DSL in Apr, May, Jun, Jul, Aug, Sep
int y = year (local_t);
int h = hour (local_t);
int hToday = (h + 24 * day(local_t));
if((m == 3 && hToday >= (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 4) % 7)))
|| (m == 10 && hToday < (1 + TIMEZONE + 24 * (31 - (5 * y /4 + 1) % 7))) )
return 1;
else
return 0;
}
void app::calculateSunriseSunset() { void app::calculateSunriseSunset() {
// Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth // Source: https://en.wikipedia.org/wiki/Sunrise_equation#Complete_calculation_on_Earth
// Julian day since 1.1.2000 12:00 + correction 69.12s // Julian day since 1.1.2000 12:00 + correction 69.12s
double n_JulianDay = mTimestamp / 86400 - 10957.0 + 0.0008; double n_JulianDay = (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 - 10957.0 + 0.0008;
// Mean solar time // Mean solar time
double J = n_JulianDay - mConfig.sunLon / 360; double J = n_JulianDay - mConfig.sunLon / 360;
// Solar mean anomaly // Solar mean anomaly
@ -933,10 +912,7 @@ void app::calculateSunriseSunset() {
// Calculate sunrise and sunset // Calculate sunrise and sunset
double Jrise = Jtransit - omega / 360; double Jrise = Jtransit - omega / 360;
double Jset = Jtransit + omega / 360; double Jset = Jtransit + omega / 360;
// Julian sunrise/sunset to unix timestamp (days incl. fraction to seconds + unix offset 1.1.2000 12:00) // Julian sunrise/sunset to UTC unix timestamp (days incl. fraction to seconds + unix offset 1.1.2000 12:00)
uint32_t UTC_Timestamp_Sunrise = (Jrise - 2451545.0) * 86400 + 946728000; mSunrise = (Jrise - 2451545.0) * 86400 + 946728000; // OPTIONAL: Add an offset of +-seconds to the end of the line
uint32_t UTC_Timestamp_Sunset = (Jset - 2451545.0) * 86400 + 946728000; mSunset = (Jset - 2451545.0) * 86400 + 946728000; // OPTIONAL: Add an offset of +-seconds to the end of the line
mSunrise = UTC_Timestamp_Sunrise + ((TIMEZONE + offsetDayLightSaving(UTC_Timestamp_Sunrise)) * 3600); // sunrise in local time, OPTIONAL: Add an offset of +-seconds to the end of the line
mSunset = UTC_Timestamp_Sunset + ((TIMEZONE + offsetDayLightSaving(UTC_Timestamp_Sunset)) * 3600); // sunset in local time, OPTIONAL: Add an offset of +-seconds to the end of the line
} }

10
tools/esp8266/app.h

@ -100,10 +100,10 @@ class app {
String getTimeStr(void) { String getTimeStr(void) {
char str[20]; char str[20];
if(0 == mTimestamp) if(0 == mUtcTimestamp)
sprintf(str, "n/a"); sprintf(str, "n/a");
else else
sprintf(str, "%02d:%02d:%02d ", hour(mTimestamp), minute(mTimestamp), second(mTimestamp)); sprintf(str, "%02d:%02d:%02d UTC", hour(mUtcTimestamp), minute(mUtcTimestamp), second(mUtcTimestamp));
return String(str); return String(str);
} }
@ -112,7 +112,7 @@ class app {
} }
inline uint32_t getTimestamp(void) { inline uint32_t getTimestamp(void) {
return mTimestamp; return mUtcTimestamp;
} }
inline void setTimestamp(uint32_t newTime) { inline void setTimestamp(uint32_t newTime) {
@ -122,7 +122,6 @@ class app {
else else
{ {
mUtcTimestamp = newTime; mUtcTimestamp = newTime;
mTimestamp = mUtcTimestamp + ((TIMEZONE + offsetDayLightSaving(mUtcTimestamp)) * 3600);
} }
} }
@ -252,7 +251,6 @@ class app {
DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag)); DPRINTLN(DBG_VERBOSE, F(" - frag: ") + String(frag));
} }
uint8_t offsetDayLightSaving(uint32_t local_t);
void calculateSunriseSunset(void); void calculateSunriseSunset(void);
uint32_t mUptimeSecs; uint32_t mUptimeSecs;
@ -267,7 +265,6 @@ class app {
eep *mEep; eep *mEep;
uint32_t mUtcTimestamp; uint32_t mUtcTimestamp;
uint32_t mTimestamp;
bool mUpdateNtp; bool mUpdateNtp;
bool mShowRebootRequest; bool mShowRebootRequest;
@ -300,6 +297,7 @@ class app {
uint16_t mSerialTicker; uint16_t mSerialTicker;
// sun // sun
int32_t mCalculatedTimezoneOffset;
uint32_t mSunrise; uint32_t mSunrise;
uint32_t mSunset; uint32_t mSunset;
uint32_t mLatestSunTimestamp; uint32_t mLatestSunTimestamp;

4
tools/esp8266/hmDefines.h

@ -106,13 +106,13 @@ const byteAssign_t SystemConfigParaAssignment[] = {
{ FLD_ACT_PF, UNIT_NONE, CH0, 6, 2, 1000 }*/ { FLD_ACT_PF, UNIT_NONE, CH0, 6, 2, 1000 }*/
}; };
#define HMSYSTEM_LIST_LEN (sizeof(SystemConfigParaAssignment) / sizeof(byteAssign_t)) #define HMSYSTEM_LIST_LEN (sizeof(SystemConfigParaAssignment) / sizeof(byteAssign_t))
#define HMSYSTEM_PAYLOAD_LEN 0 // 0: means check off #define HMSYSTEM_PAYLOAD_LEN 0 // 0: means check is off
const byteAssign_t AlarmDataAssignment[] = { const byteAssign_t AlarmDataAssignment[] = {
{ FLD_LAST_ALARM_CODE, UNIT_NONE, CH0, 0, 2, 1 } { FLD_LAST_ALARM_CODE, UNIT_NONE, CH0, 0, 2, 1 }
}; };
#define HMALARMDATA_LIST_LEN (sizeof(AlarmDataAssignment) / sizeof(byteAssign_t)) #define HMALARMDATA_LIST_LEN (sizeof(AlarmDataAssignment) / sizeof(byteAssign_t))
#define HMALARMDATA_PAYLOAD_LEN 0 // 0: means check off #define HMALARMDATA_PAYLOAD_LEN 0 // 0: means check is off

8
tools/esp8266/html/index.html

@ -106,7 +106,7 @@
+ ("0"+sec).substr(-2); + ("0"+sec).substr(-2);
var dSpan = document.getElementById("date") var dSpan = document.getElementById("date")
if(0 != obj["ts_now"]) if(0 != obj["ts_now"])
dSpan.innerHTML = date.toLocaleString('de-DE', {timeZone: 'UTC'}); dSpan.innerHTML = date.toLocaleString('de-DE');
else { else {
var e = inp("set", "sync from browser", 0, ["btn"], "set", "button"); var e = inp("set", "sync from browser", 0, ["btn"], "set", "button");
dSpan.appendChild(span("NTP timeserver unreachable. ")); dSpan.appendChild(span("NTP timeserver unreachable. "));
@ -114,8 +114,8 @@
dSpan.appendChild(span("", ["span"], "apiResult")); dSpan.appendChild(span("", ["span"], "apiResult"));
e.addEventListener("click", setTime); e.addEventListener("click", setTime);
} }
document.getElementById("sunrise").innerHTML = sunrise.toLocaleString('de-DE', {timeZone: 'UTC'}); document.getElementById("sunrise").innerHTML = sunrise.toLocaleString('de-DE');
document.getElementById("sunset").innerHTML = sunset.toLocaleString('de-DE', {timeZone: 'UTC'}); document.getElementById("sunset").innerHTML = sunset.toLocaleString('de-DE');
if(!obj["ts_sun_upd"]) { if(!obj["ts_sun_upd"]) {
var elem = document.getElementById("sun"); var elem = document.getElementById("sun");
@ -145,7 +145,7 @@
if(false == i["is_avail"]) { if(false == i["is_avail"]) {
if(i["ts_last_success"] > 0) { if(i["ts_last_success"] > 0) {
var date = new Date(i["ts_last_success"] * 1000); var date = new Date(i["ts_last_success"] * 1000);
html += "-> last successful transmission: " + date.toLocaleString('de-DE', {timeZone: 'UTC'}); html += "-> last successful transmission: " + date.toLocaleString('de-DE');
} }
} }

12
tools/esp8266/html/visualization.html

@ -76,8 +76,16 @@
} }
var ts = div(["ts"]); var ts = div(["ts"]);
var date = new Date(iv["ts_last_success"] * 1000); var ageInfo = "Last received data requested at: ";
ts.innerHTML = "Last received data requested at: " + date.toLocaleString('de-DE', {timeZone: 'UTC'}); if(iv["ts_last_success"] > 0) {
var date = new Date(iv["ts_last_success"] * 1000);
ageInfo += date.toLocaleString('de-DE');
}
else
ageInfo += "nothing received";
ts.innerHTML = ageInfo;
main.appendChild(ts); main.appendChild(ts);
ivHtml.push(main); ivHtml.push(main);
} }

Loading…
Cancel
Save