mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-10 15:36:38 +02:00
* fix #38 current assignment for 4-channel inverters
* added last received timestamp in /hoymiles livedata web page #47 * improved style.css * improved NTP as described in #46
This commit is contained in:
parent
ec6cfba895
commit
8238e90903
9 changed files with 37 additions and 27 deletions
|
@ -319,6 +319,7 @@ void app::processPayload(bool retransmit) {
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mPayload[iv->id].complete = true;
|
mPayload[iv->id].complete = true;
|
||||||
|
iv->ts = mPayload[iv->id].ts;
|
||||||
uint8_t payload[128] = {0};
|
uint8_t payload[128] = {0};
|
||||||
uint8_t offs = 0;
|
uint8_t offs = 0;
|
||||||
for(uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i ++) {
|
for(uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i ++) {
|
||||||
|
@ -513,6 +514,8 @@ void app::showHoymiles(void) {
|
||||||
String html = FPSTR(hoymiles_html);
|
String html = FPSTR(hoymiles_html);
|
||||||
html.replace("{DEVICE}", mDeviceName);
|
html.replace("{DEVICE}", mDeviceName);
|
||||||
html.replace("{VERSION}", mVersion);
|
html.replace("{VERSION}", mVersion);
|
||||||
|
html.replace("{TS}", String(mSendInterval) + " ");
|
||||||
|
html.replace("{JS_TS}", String(mSendInterval * 1000));
|
||||||
mWeb->send(200, "text/html", html);
|
mWeb->send(200, "text/html", html);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,7 +569,7 @@ void app::showLiveData(void) {
|
||||||
}
|
}
|
||||||
modHtml += "</div>";
|
modHtml += "</div>";
|
||||||
}
|
}
|
||||||
|
modHtml += "<div class=\"ts\">Last data update: " + getDateTimeStr(iv->ts) + "</div>";
|
||||||
modHtml += "</div>";
|
modHtml += "</div>";
|
||||||
#else
|
#else
|
||||||
// dump all data to web frontend
|
// dump all data to web frontend
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 4
|
#define VERSION_MINOR 4
|
||||||
#define VERSION_PATCH 4
|
#define VERSION_PATCH 5
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
|
@ -56,10 +56,11 @@ class Inverter {
|
||||||
serial_u serial; // serial number as on barcode
|
serial_u serial; // serial number as on barcode
|
||||||
serial_u radioId; // id converted to modbus
|
serial_u radioId; // id converted to modbus
|
||||||
uint8_t channels; // number of PV channels (1-4)
|
uint8_t channels; // number of PV channels (1-4)
|
||||||
|
uint32_t ts; // timestamp of last received payload
|
||||||
RECORDTYPE *record; // pointer for values
|
RECORDTYPE *record; // pointer for values
|
||||||
|
|
||||||
Inverter() {
|
Inverter() {
|
||||||
|
ts = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~Inverter() {
|
~Inverter() {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __HOYMILES_HTML_H__
|
#ifndef __HOYMILES_HTML_H__
|
||||||
#define __HOYMILES_HTML_H__
|
#define __HOYMILES_HTML_H__
|
||||||
const char hoymiles_html[] PROGMEM = "<!doctype html><html><head><title>Index - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><script type=\"text/javascript\">getAjax('/livedata', 'livedata');window.setInterval(\"getAjax('/livedata', 'livedata')\", 10000);function getAjax(url, resid) {var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"GET\", url, true);http.onreadystatechange = print;http.send(null);}function print() {if(http.readyState == 4) {document.getElementById(resid).innerHTML = http.responseText;}}}</script><style type=\"text/css\"></style></head><body><h1>AHOY - {DEVICE}</h1><div id=\"content\" class=\"content\"><div id=\"livedata\"></div><p>Every 10 seconds the values are updated</p></div><div id=\"footer\"><p class=\"left\">© 2022</p><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"right\">AHOY :: {VERSION}</p></div></body></html>";
|
const char hoymiles_html[] PROGMEM = "<!doctype html><html><head><title>Index - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><script type=\"text/javascript\">getAjax('/livedata', 'livedata');window.setInterval(\"getAjax('/livedata', 'livedata')\", {JS_TS});function getAjax(url, resid) {var http = null;http = new XMLHttpRequest();if(http != null) {http.open(\"GET\", url, true);http.onreadystatechange = print;http.send(null);}function print() {if(http.readyState == 4) {document.getElementById(resid).innerHTML = http.responseText;}}}</script><style type=\"text/css\"></style></head><body><h1>AHOY - {DEVICE}</h1><div id=\"content\" class=\"content\"><div id=\"livedata\"></div><p>Every {TS}seconds the values are updated</p></div><div id=\"footer\"><p class=\"left\">© 2022</p><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"right\">AHOY :: {VERSION}</p></div></body></html>";
|
||||||
#endif /*__HOYMILES_HTML_H__*/
|
#endif /*__HOYMILES_HTML_H__*/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#ifndef __STYLE_CSS_H__
|
#ifndef __STYLE_CSS_H__
|
||||||
#define __STYLE_CSS_H__
|
#define __STYLE_CSS_H__
|
||||||
const char style_css[] PROGMEM = "h1 {margin:0;padding:20pt;font-size:22pt;color:#fff;background-color:#006ec0;display:block;text-transform:uppercase;}html, body {font-family:Arial;margin:0;padding:0;}p {text-align:justify;font-size:13pt;}.des {margin-top:35px;font-size:13pt;color:#006ec0;}.subdes {font-size:12pt;color:#006ec0;margin-left:7px;}a:link, a:visited {text-decoration:none;font-size:13pt;color:#006ec0;}a:hover, a:focus {color:#f00;}a.erase {background-color:#006ec0;color:#fff;padding:7px;display:inline-block;margin-top:30px;float:right;}#content {padding:15px 15px 60px 15px;}#footer {position:fixed;bottom:0px;height:45px;background-color:#006ec0;width:100%;border-top:5px solid #fff;}#footer p, #footer a {color:#fff;padding:0 7px 0 7px;font-size:10pt !important;}div.content {background-color:#fff;padding-bottom:65px;overflow:auto;}input, select {padding:7px;font-size:13pt;}input.text, select {width:70%;box-sizing:border-box;margin-bottom:10px;border:1px solid #ccc;}input.btn {background-color:#006ec0;color:#fff;border:0px;float:right;margin:10px 0 30px;text-transform:uppercase;}input.cb {margin-bottom:20px;}label {width:20%;display:inline-block;font-size:12pt;padding-right:10px;margin-left:10px;}.left {float:left;}.right {float:right;}div.ch-iv {width:100%;background-color:#32b004;display:inline-block;margin-bottom:20px;padding-bottom:20px;overflow:auto;}div.ch {width:250px;min-height:420px;background-color:#006ec0;display:inline-block;margin-right:20px;margin-bottom:20px;overflow:auto;padding-bottom:20px;}div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, div.ch-iv .head {color:#fff;display:block;width:100%;text-align:center;}.subgrp {float:left;width:250px;}div.ch .unit, div.ch-iv .unit {font-size:19px;margin-left:10px;}div.ch .value, div.ch-iv .value {margin-top:20px;font-size:30px;}div.ch .info, div.ch-iv .info {margin-top:3px;font-size:10px;}div.ch .head {background-color:#003c80;padding:10px 0 10px 0;}div.ch-iv .head {background-color:#1c6800;padding:10px 0 10px 0;}div.iv {max-width:1060px;}div.ch:last-child {margin-right:0px !important;}#note {margin:50px 10px 10px 10px;padding-top:10px;width:100%;border-top:1px solid #bbb;}@media(max-width:500px) {div.ch .unit, div.ch-iv .unit {font-size:18px;}div.ch {width:170px;min-height:100px;}.subgrp {width:180px;}}";
|
const char style_css[] PROGMEM = "h1 {margin:0;padding:20pt;font-size:22pt;color:#fff;background-color:#006ec0;display:block;text-transform:uppercase;}html, body {font-family:Arial;margin:0;padding:0;}p {text-align:justify;font-size:13pt;}.des {margin-top:35px;font-size:13pt;color:#006ec0;}.subdes {font-size:12pt;color:#006ec0;margin-left:7px;}a:link, a:visited {text-decoration:none;font-size:13pt;color:#006ec0;}a:hover, a:focus {color:#f00;}a.erase {background-color:#006ec0;color:#fff;padding:7px;display:inline-block;margin-top:30px;float:right;}#content {padding:15px 15px 60px 15px;}#footer {position:fixed;bottom:0px;height:45px;background-color:#006ec0;width:100%;border-top:5px solid #fff;}#footer p, #footer a {color:#fff;padding:0 7px 0 7px;font-size:10pt !important;}div.content {background-color:#fff;padding-bottom:65px;overflow:auto;}input, select {padding:7px;font-size:13pt;}input.text, select {width:70%;box-sizing:border-box;margin-bottom:10px;border:1px solid #ccc;}input.btn {background-color:#006ec0;color:#fff;border:0px;float:right;margin:10px 0 30px;text-transform:uppercase;}input.cb {margin-bottom:20px;}label {width:20%;display:inline-block;font-size:12pt;padding-right:10px;margin-left:10px;}.left {float:left;}.right {float:right;}div.ch-iv {width:100%;background-color:#32b004;display:inline-block;margin-bottom:15px;padding-bottom:20px;overflow:auto;}div.ch {width:220px;min-height:350px;background-color:#006ec0;display:inline-block;margin:0 10px 15px 10px;overflow:auto;padding-bottom:20px;}div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, div.ch-iv .head {color:#fff;display:block;width:100%;text-align:center;}.subgrp {float:left;width:220px;}div.ch .unit, div.ch-iv .unit {font-size:19px;margin-left:10px;}div.ch .value, div.ch-iv .value {margin-top:20px;font-size:24px;}div.ch .info, div.ch-iv .info {margin-top:3px;font-size:10px;}div.ch .head {background-color:#003c80;padding:10px 0 10px 0;}div.ch-iv .head {background-color:#1c6800;padding:10px 0 10px 0;}div.iv {max-width:960px;margin-bottom:40px;}div.ts {font-size:13px;background-color:#ddd;border-top:7px solid #999;padding:7px;}#note {margin:50px 10px 10px 10px;padding-top:10px;width:100%;border-top:1px solid #bbb;}@media(max-width:500px) {div.ch .unit, div.ch-iv .unit {font-size:18px;}div.ch {width:170px;min-height:100px;}.subgrp {width:180px;}}";
|
||||||
#endif /*__STYLE_CSS_H__*/
|
#endif /*__STYLE_CSS_H__*/
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
getAjax('/livedata', 'livedata');
|
getAjax('/livedata', 'livedata');
|
||||||
window.setInterval("getAjax('/livedata', 'livedata')", 10000);
|
window.setInterval("getAjax('/livedata', 'livedata')", {JS_TS});
|
||||||
|
|
||||||
function getAjax(url, resid) {
|
function getAjax(url, resid) {
|
||||||
var http = null;
|
var http = null;
|
||||||
|
@ -31,7 +31,7 @@
|
||||||
<h1>AHOY - {DEVICE}</h1>
|
<h1>AHOY - {DEVICE}</h1>
|
||||||
<div id="content" class="content">
|
<div id="content" class="content">
|
||||||
<div id="livedata"></div>
|
<div id="livedata"></div>
|
||||||
<p>Every 10 seconds the values are updated</p>
|
<p>Every {TS}seconds the values are updated</p>
|
||||||
</div>
|
</div>
|
||||||
<div id="footer">
|
<div id="footer">
|
||||||
<p class="left">© 2022</p>
|
<p class="left">© 2022</p>
|
||||||
|
|
|
@ -121,18 +121,17 @@ div.ch-iv {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-color: #32b004;
|
background-color: #32b004;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 15px;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ch {
|
div.ch {
|
||||||
width: 250px;
|
width: 220px;
|
||||||
min-height: 420px;
|
min-height: 350px;
|
||||||
background-color: #006ec0;
|
background-color: #006ec0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin-right: 20px;
|
margin: 0 10px 15px 10px;
|
||||||
margin-bottom: 20px;
|
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
padding-bottom: 20px;
|
padding-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -146,7 +145,7 @@ div.ch .value, div.ch .info, div.ch .head, div.ch-iv .value, div.ch-iv .info, d
|
||||||
|
|
||||||
.subgrp {
|
.subgrp {
|
||||||
float: left;
|
float: left;
|
||||||
width: 250px;
|
width: 220px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ch .unit, div.ch-iv .unit {
|
div.ch .unit, div.ch-iv .unit {
|
||||||
|
@ -156,7 +155,7 @@ div.ch .unit, div.ch-iv .unit {
|
||||||
|
|
||||||
div.ch .value, div.ch-iv .value {
|
div.ch .value, div.ch-iv .value {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
font-size: 30px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ch .info, div.ch-iv .info {
|
div.ch .info, div.ch-iv .info {
|
||||||
|
@ -175,11 +174,15 @@ div.ch-iv .head {
|
||||||
}
|
}
|
||||||
|
|
||||||
div.iv {
|
div.iv {
|
||||||
max-width: 1060px;
|
max-width: 960px;
|
||||||
|
margin-bottom: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.ch:last-child {
|
div.ts {
|
||||||
margin-right: 0px !important;
|
font-size: 13px;
|
||||||
|
background-color: #ddd;
|
||||||
|
border-top: 7px solid #999;
|
||||||
|
padding: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#note {
|
#note {
|
||||||
|
|
|
@ -30,6 +30,8 @@ Main::Main(void) {
|
||||||
mUptimeSecs = 0;
|
mUptimeSecs = 0;
|
||||||
mUptimeTicker = 0xffffffff;
|
mUptimeTicker = 0xffffffff;
|
||||||
mUptimeInterval = 1000;
|
mUptimeInterval = 1000;
|
||||||
|
|
||||||
|
mTimestamp = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,12 +58,6 @@ void Main::setup(uint32_t timeout) {
|
||||||
setupAp(WIFI_AP_SSID, WIFI_AP_PWD);
|
setupAp(WIFI_AP_SSID, WIFI_AP_PWD);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!startAp) {
|
|
||||||
delay(5000);
|
|
||||||
mTimestamp = getNtpTime();
|
|
||||||
DPRINTLN("[NTP]: " + getDateTimeStr(getNtpTime()));
|
|
||||||
}
|
|
||||||
|
|
||||||
mUpdater->setup(mWeb);
|
mUpdater->setup(mWeb);
|
||||||
mApActive = startAp;
|
mApActive = startAp;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +94,14 @@ void Main::loop(void) {
|
||||||
|
|
||||||
if(checkTicker(&mUptimeTicker, mUptimeInterval)) {
|
if(checkTicker(&mUptimeTicker, mUptimeInterval)) {
|
||||||
mUptimeSecs++;
|
mUptimeSecs++;
|
||||||
|
if(0 != mTimestamp)
|
||||||
mTimestamp++;
|
mTimestamp++;
|
||||||
|
else {
|
||||||
|
if(!mApActive) {
|
||||||
|
mTimestamp = getNtpTime();
|
||||||
|
DPRINTLN("[NTP]: " + getDateTimeStr(getNtpTime()));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -414,7 +417,7 @@ void Main::sendNTPpacket(IPAddress& address) {
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
String Main::getDateTimeStr(time_t t) {
|
String Main::getDateTimeStr(time_t t) {
|
||||||
char str[20] = {0};
|
char str[20] = {0};
|
||||||
sprintf(str, "%04d-%02d-%02d+%02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
|
sprintf(str, "%04d-%02d-%02d %02d:%02d:%02d", year(t), month(t), day(t), hour(t), minute(t), second(t));
|
||||||
return String(str);
|
return String(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -549,7 +549,7 @@ class Hm600Decode12(EventsResponse):
|
||||||
""" Inverter major events log """
|
""" Inverter major events log """
|
||||||
|
|
||||||
|
|
||||||
# 1161-Series Inverters, 4 MPPT, 1 Phase
|
# 1161-Series Inverters, 2 MPPT, 1 Phase
|
||||||
class Hm1200Decode0B(StatusResponse):
|
class Hm1200Decode0B(StatusResponse):
|
||||||
""" 1161-series mirco-inverters status data """
|
""" 1161-series mirco-inverters status data """
|
||||||
|
|
||||||
|
@ -581,7 +581,7 @@ class Hm1200Decode0B(StatusResponse):
|
||||||
@property
|
@property
|
||||||
def dc_current_1(self):
|
def dc_current_1(self):
|
||||||
""" String 2 ampere """
|
""" String 2 ampere """
|
||||||
return self.unpack('>H', 4)[0]/100
|
return self.unpack('>H', 6)[0]/100
|
||||||
@property
|
@property
|
||||||
def dc_power_1(self):
|
def dc_power_1(self):
|
||||||
""" String 2 watts """
|
""" String 2 watts """
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue