Browse Source

* increased number of inverters

* name, serial and type can be configured using setup.html
pull/8/head
lumapu 3 years ago
parent
commit
9e6cae26a7
  1. 164
      tools/esp8266/app.cpp
  2. 4
      tools/esp8266/app.h
  3. 16
      tools/esp8266/defines.h
  4. 5
      tools/esp8266/hmInverters.h
  5. 26
      tools/esp8266/hmSystem.h
  6. 2
      tools/esp8266/html/h/setup_html.h
  7. 2
      tools/esp8266/html/h/style_css.h
  8. 1
      tools/esp8266/html/setup.html
  9. 14
      tools/esp8266/html/style.css

164
tools/esp8266/app.cpp

@ -44,12 +44,21 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) {
if(mSettingsValid) {
uint16_t interval;
uint64_t invSerial;
char invName[MAX_NAME_LENGTH + 1] = {0};
uint8_t invType;
// hoymiles
mEep->read(ADDR_INV0_ADDR, &invSerial);
mEep->read(ADDR_INV_INTERVAL, &interval);
mSys->addInverter("HM1200", invSerial, INV_TYPE_HM1200);
// inverter
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
mEep->read(ADDR_INV_ADDR + (i * 8), &invSerial);
mEep->read(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), invName, MAX_NAME_LENGTH);
mEep->read(ADDR_INV_TYPE + i, &invType);
if(0ULL != invSerial) {
mSys->addInverter(invName, invSerial, invType);
Serial.println("add inverter: " + String(invName) + ", SN: " + String(invSerial, HEX) + ", type: " + String(invType));
}
}
mEep->read(ADDR_INV_INTERVAL, &interval);
if(interval < 1000)
interval = 1000;
mSendTicker->attach_ms(interval, std::bind(&app::sendTicker, this));
@ -129,29 +138,32 @@ void app::loop(void) {
mFlagSend = false;
uint8_t size = 0;
inverter_t *inv = mSys->getInverterByPos(0);
//if((mSendCnt % 6) == 0)
size = mSys->Radio.getTimePacket(&inv->radioId.u64, mSendBuf, mTimestamp);
/*else if((mSendCnt % 6) == 1)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x81);
else if((mSendCnt % 6) == 2)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x80);
else if((mSendCnt % 6) == 3)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x83);
else if((mSendCnt % 6) == 4)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x82);
else if((mSendCnt % 6) == 5)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x84);*/
//Serial.println("sent packet: #" + String(mSendCnt));
//dumpBuf("SEN ", mSendBuf, size);
sendPacket(inv, mSendBuf, size);
mSendCnt++;
inverter_t *inv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
inv = mSys->getInverterByPos(i);
if(NULL != inv) {
//if((mSendCnt % 6) == 0)
size = mSys->Radio.getTimePacket(&inv->radioId.u64, mSendBuf, mTimestamp);
/*else if((mSendCnt % 6) == 1)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x81);
else if((mSendCnt % 6) == 2)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x80);
else if((mSendCnt % 6) == 3)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x83);
else if((mSendCnt % 6) == 4)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x82);
else if((mSendCnt % 6) == 5)
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x84);*/
//Serial.println("sent packet: #" + String(mSendCnt));
//dumpBuf("SEN ", mSendBuf, size);
sendPacket(inv, mSendBuf, size);
mSendCnt++;
delay(20);
}
}
}
@ -169,7 +181,7 @@ void app::loop(void) {
snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, fields[iv->assign[i].fieldId]);
snprintf(val, 10, "%.3f", mSys->getValue(iv, i));
mMqtt.sendMsg(topic, val);
delay(10);
delay(20);
}
}
}
@ -328,25 +340,35 @@ void app::showSetup(void) {
html.replace("{VERSION}", String(mVersion));
String inv;
inverter_t *pInv;
uint64_t invSerial;
char invName[MAX_NAME_LENGTH + 1] = {0};
uint8_t invType;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
pInv = mSys->getInverterByPos(i);
mEep->read(ADDR_INV_ADDR + (i * 8), &invSerial);
mEep->read(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), invName, MAX_NAME_LENGTH);
mEep->read(ADDR_INV_TYPE + i, &invType);
inv += "<p class=\"subdes\">Inverter "+ String(i) + "</p>";
inv += "<label for=\"inv" + String(i) + "Addr\">Address</label>";
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Addr\" value=\"";
inv += (NULL != pInv) ? String(mSys->getSerial(pInv), HEX) : "";
inv += "\"/>";
if(0ULL != invSerial)
inv += String(invSerial, HEX);
inv += "\"/ maxlength=\"12\">";
inv += "<label for=\"inv" + String(i) + "Name\">Name</label>";
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
inv += (NULL != pInv) ? String(pInv->name) : "";
inv += "\"/>";
inv += String(invName);
inv += "\"/ maxlength=\"" + String(MAX_NAME_LENGTH) + "\">";
inv += "<label for=\"inv" + String(i) + "Type\">Type</label>";
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
inv += (NULL != pInv) ? String(pInv->type) : "";
inv += "\"/>";
inv += "<select name=\"inv" + String(i) + "Type\">";
for(uint8_t t = 0; t < NUM_INVERTER_TYPES; t++) {
inv += "<option value=\"" + String(t) + "\"";
if(invType == t)
inv += " selected";
inv += ">" + String(invTypes[t]) + "</option>";
}
inv += "</select>";
}
html.replace("{INVERTERS}", String(inv));
@ -416,45 +438,50 @@ void app::showHoymiles(void) {
//-----------------------------------------------------------------------------
void app::showLiveData(void) {
String modHtml = "<pre>";
char topic[20], val[10];
String modHtml;
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
inverter_t *iv = mSys->getInverterByPos(id);
if(NULL != iv) {
/*uint8_t modNum;
#ifdef LIVEDATA_VISUALIZED
uint8_t modNum, pos;
switch(iv->type) {
default: modNum = 1; break;
case INV_TYPE_HM600: modNum = 2; break;
case INV_TYPE_HM1200: modNum = 4; break;
}
for(uint8_t mod = 1; mod <= modNum; mod ++) {
modHtml += "<div class=\"module\"><span class=\"header\">CHANNEL " + String(i) + "</span>";
for(uint8_t ch = 1; ch <= modNum; ch ++) {
modHtml += "<div class=\"ch\"><span class=\"head\">CHANNEL " + String(ch) + "</span>";
for(uint8_t j = 0; j < 5; j++) {
modHtml += "<span class=\"value\">";
switch(j) {
default: modHtml += String(mDecoder->mData.ch_dc[i/2].u); break;
case 1: modHtml += String(mDecoder->mData.ch_dc[i].i); break;
case 2: modHtml += String(mDecoder->mData.ch_dc[i].p); break;
case 3: modHtml += String(mDecoder->mData.ch_dc[i].y_d); break;
case 4: modHtml += String(mDecoder->mData.ch_dc[i].y_t); break;
default: pos = (mSys->getPosByChField(iv, ch, FLD_UDC)); break;
case 1: pos = (mSys->getPosByChField(iv, ch, FLD_IDC)); break;
case 2: pos = (mSys->getPosByChField(iv, ch, FLD_PDC)); break;
case 3: pos = (mSys->getPosByChField(iv, ch, FLD_YD)); break;
case 4: pos = (mSys->getPosByChField(iv, ch, FLD_YT)); break;
}
if(0xff != pos) {
modHtml += "<span class=\"value\">" + String(mSys->getValue(iv, pos));
modHtml += "<span class=\"unit\">" + String(mSys->getUnit(iv, pos)) + "</span></span>";
modHtml += "<span class=\"info\">" + String(mSys->getFieldName(iv, pos)) + "</span>";
}
modHtml += "<span class=\"unit\">" + unit[j] + "</span></span>";
modHtml += "<span class=\"info\">" + info[j] + "</span>";
}
modHtml += "</div>";
}*/
}
#else
// dump all data to web frontend
modHtml = "<pre>";
char topic[30], val[10];
for(uint8_t i = 0; i < iv->listLen; i++) {
sprintf(topic, "%s/ch%d/%s", iv->name, iv->assign[i].ch, mSys->getFieldName(iv, i));
sprintf(val, "%.3f %s", mSys->getValue(iv, i), mSys->getUnit(iv, i));
snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, mSys->getFieldName(iv, i));
snprintf(val, 10, "%.3f %s", mSys->getValue(iv, i), mSys->getUnit(iv, i));
modHtml += String(topic) + ": " + String(val) + "\n";
}
modHtml += "</pre>";
#endif
}
}
modHtml += "</pre>";
mWeb->send(200, "text/html", modHtml);
}
@ -481,18 +508,25 @@ void app::saveValues(bool webSend = true) {
// inverter
serial_u addr;
mWeb->arg("inv0Addr").toCharArray(buf, 20);
addr.u64 = Serial2u64(buf);
mSys->updateSerial(mSys->getInverterByPos(0), addr.u64);
for(uint8_t i = 0; i < 8; i++) {
Serial.print(String(addr.b[i], HEX) + " ");
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
// address
mWeb->arg("inv" + String(i) + "Addr").toCharArray(buf, 20);
if(strlen(buf) == 0)
snprintf(buf, 20, "\0");
addr.u64 = Serial2u64(buf);
mEep->write(ADDR_INV_ADDR + (i * 8), addr.u64);
// name
mWeb->arg("inv" + String(i) + "Name").toCharArray(buf, 20);
mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), buf, MAX_NAME_LENGTH);
// type
mWeb->arg("inv" + String(i) + "Type").toCharArray(buf, 20);
uint8_t type = atoi(buf);
mEep->write(ADDR_INV_TYPE + (i * MAX_NAME_LENGTH), type);
}
Serial.println();
Serial.println("addr: " + String(addr.u64, HEX));
interval = mWeb->arg("invInterval").toInt();
mEep->write(ADDR_INV0_ADDR, addr.u64);
mEep->write(ADDR_INV_INTERVAL, interval);

4
tools/esp8266/app.h

@ -15,7 +15,7 @@
typedef HmRadio<RF24_CE_PIN, RF24_CS_PIN, RF24_IRQ_PIN> RadioType;
typedef CircularBuffer<packet_t, PACKET_BUFFER_SIZE> BufferType;
typedef HmSystem<RadioType, BufferType, MAX_NUM_INVERTERS, double> HmSystemType;
typedef HmSystem<RadioType, BufferType, MAX_NUM_INVERTERS, float> HmSystemType;
class app : public Main {
public:
@ -59,6 +59,8 @@ class app : public Main {
for(uint8_t i = 0; i < 6; i++) {
tmp[0] = val[i*2];
tmp[1] = val[i*2 + 1];
if((tmp[0] == '\0') || (tmp[1] == '\0'))
break;
u64 = strtol(tmp, NULL, 16);
ret |= (u64 << ((5-i) << 3));
}

16
tools/esp8266/defines.h

@ -16,6 +16,8 @@
//-------------------------------------
#define PACKET_BUFFER_SIZE 30
#define MAX_NUM_INVERTERS 3
#define MAX_NAME_LENGTH 16
#define LIVEDATA_VISUALIZED // show live data pv-module wise or as dump
//-------------------------------------
@ -23,7 +25,7 @@
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 2
#define VERSION_PATCH 2
#define VERSION_PATCH 3
//-------------------------------------
@ -34,8 +36,10 @@
#define DEVNAME_LEN 16
#define CRC_LEN 2
#define INV_ADDR_LEN 8 // uint64_t
#define INV_INTERVAL_LEN 2 // uint16_t
#define INV_ADDR_LEN MAX_NUM_INVERTERS * 8 // uint64_t
#define INV_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH // char[]
#define INV_TYPE_LEN MAX_NUM_INVERTERS * 1 // uint8_t
#define INV_INTERVAL_LEN 2 // uint16_t
#define MQTT_ADDR_LEN 4 // IP
@ -49,8 +53,10 @@
#define ADDR_SSID ADDR_START
#define ADDR_PWD ADDR_SSID + SSID_LEN
#define ADDR_DEVNAME ADDR_PWD + PWD_LEN
#define ADDR_INV0_ADDR ADDR_DEVNAME + DEVNAME_LEN
#define ADDR_INV_INTERVAL ADDR_INV0_ADDR + INV_ADDR_LEN
#define ADDR_INV_ADDR ADDR_DEVNAME + DEVNAME_LEN
#define ADDR_INV_NAME ADDR_INV_ADDR + INV_ADDR_LEN
#define ADDR_INV_TYPE ADDR_INV_NAME + INV_NAME_LEN
#define ADDR_INV_INTERVAL ADDR_INV_TYPE + INV_TYPE_LEN
#define ADDR_MQTT_ADDR ADDR_INV_INTERVAL + INV_INTERVAL_LEN
#define ADDR_MQTT_USER ADDR_MQTT_ADDR + MQTT_ADDR_LEN

5
tools/esp8266/hmInverters.h

@ -21,7 +21,8 @@ enum {CH0 = 0, CH1, CH2, CH3, CH4};
enum {CMD01 = 0x01, CMD02, CMD03, CMD83 = 0x83, CMD84};
enum {INV_TYPE_HM600 = 0, INV_TYPE_HM1200};
const char* const invTypes[] = {"HM600", "HM1200"};
#define NUM_INVERTER_TYPES 2
typedef struct {
uint8_t fieldId; // field id
@ -41,7 +42,7 @@ union serial_u {
typedef struct {
uint8_t id; // unique id
char name[20]; // human readable name, eg. "HM-600.1"
char name[MAX_NAME_LENGTH]; // human readable name, eg. "HM-600.1"
uint8_t type; // integer which refers to inverter type
byteAssign_t* assign; // type of inverter
uint8_t listLen; // length of assignments

26
tools/esp8266/hmSystem.h

@ -31,11 +31,11 @@ class HmSystem {
return NULL;
}
inverter_t *p = &mInverter[mNumInv];
p->id = mNumInv++;
p->id = mNumInv;
p->serial.u64 = serial;
p->type = type;
uint8_t len = strlen(name);
strncpy(p->name, name, (len > 20) ? 20 : len);
strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len);
getAssignment(p);
toRadioId(p);
@ -44,8 +44,9 @@ class HmSystem {
return NULL;
}
else {
mRecord = new RECORDTYPE[p->listLen];
memset(mRecord, 0, sizeof(RECORDTYPE) * p->listLen);
mRecord[p->id] = new RECORDTYPE[p->listLen];
memset(mRecord[p->id], 0, sizeof(RECORDTYPE) * p->listLen);
mNumInv ++;
return p;
}
}
@ -105,11 +106,20 @@ class HmSystem {
val |= buf[ptr];
} while(++ptr != end);
mRecord[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
mRecord[p->id][pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
}
RECORDTYPE getValue(inverter_t *p, uint8_t pos) {
return mRecord[pos];
return mRecord[p->id][pos];
}
uint8_t getPosByChField(inverter_t *p, uint8_t channel, uint8_t fieldId) {
uint8_t pos = 0;
for(; pos < p->listLen; pos++) {
if((p->assign[pos].ch == channel) && (p->assign[pos].fieldId == fieldId))
break;
}
return (pos >= p->listLen) ? 0xff : pos;
}
uint8_t getNumInverters(void) {
@ -141,9 +151,9 @@ class HmSystem {
}
}
inverter_t mInverter[MAX_INVERTER]; // TODO: only one inverter supported!!!
inverter_t mInverter[MAX_INVERTER];
uint8_t mNumInv;
RECORDTYPE *mRecord;
RECORDTYPE *mRecord[MAX_INVERTER];
};
#endif /*__HM_SYSTEM_H__*/

2
tools/esp8266/html/h/setup_html.h

@ -1 +1 @@
String setup_html = "<!doctype html><html><head><title>Setup - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body><h1>Setup</h1><div id=\"setup\" class=\"content\"><div id=\"content\"><p> Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information. </p><form method=\"post\" action=\"/save\"><p class=\"des\">WiFi</p><label for=\"ssid\">SSID</label><input type=\"text\" class=\"text\" name=\"ssid\" value=\"{SSID}\"/><label for=\"pwd\">Password</label><input type=\"password\" class=\"text\" name=\"pwd\" value=\"{PWD}\"/><p class=\"des\">Device Host Name</p><label for=\"device\">Device Name</label><input type=\"text\" class=\"text\" name=\"device\" value=\"{DEVICE}\"/><p class=\"des\">Inverter</p> {INVERTERS}<br/><label for=\"invInterval\">Interval (ms)</label><input type=\"text\" class=\"text\" name=\"invInterval\" value=\"{INV_INTERVAL}\"/><p class=\"des\">MQTT</p><label for=\"mqttAddr\">Broker / Server IP</label><input type=\"text\" class=\"text\" name=\"mqttAddr\" value=\"{MQTT_ADDR}\"/><label for=\"mqttUser\">Username (optional)</label><input type=\"text\" class=\"text\" name=\"mqttUser\" value=\"{MQTT_USER}\"/><label for=\"mqttPwd\">Password (optional)</label><input type=\"text\" class=\"text\" name=\"mqttPwd\" value=\"{MQTT_PWD}\"/><label for=\"mqttTopic\">Topic</label><input type=\"text\" class=\"text\" name=\"mqttTopic\" value=\"{MQTT_TOPIC}\"/><label for=\"mqttInterval\">Interval (seconds)</label><input type=\"text\" class=\"text\" name=\"mqttInterval\" value=\"{MQTT_INTERVAL}\"/><p class=\"des\">&nbsp;</p><input type=\"checkbox\" class=\"cb\" name=\"reboot\"/><label for=\"reboot\">Reboot device after successful save</label><input type=\"submit\" value=\"save\" class=\"button\" /></form></div></div><div id=\"footer\"><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY - {VERSION}</p></div></body></html>";
String setup_html = "<!doctype html><html><head><title>Setup - {DEVICE}</title><link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\"/><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"></head><body><h1>Setup</h1><div id=\"setup\" class=\"content\"><div id=\"content\"><p> Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information. </p><form method=\"post\" action=\"/save\"><p class=\"des\">WiFi</p><label for=\"ssid\">SSID</label><input type=\"text\" class=\"text\" name=\"ssid\" value=\"{SSID}\"/><label for=\"pwd\">Password</label><input type=\"password\" class=\"text\" name=\"pwd\" value=\"{PWD}\"/><p class=\"des\">Device Host Name</p><label for=\"device\">Device Name</label><input type=\"text\" class=\"text\" name=\"device\" value=\"{DEVICE}\"/><p class=\"des\">Inverter</p> {INVERTERS}<br/><p class=\"subdes\">General</p><label for=\"invInterval\">Interval (ms)</label><input type=\"text\" class=\"text\" name=\"invInterval\" value=\"{INV_INTERVAL}\"/><p class=\"des\">MQTT</p><label for=\"mqttAddr\">Broker / Server IP</label><input type=\"text\" class=\"text\" name=\"mqttAddr\" value=\"{MQTT_ADDR}\"/><label for=\"mqttUser\">Username (optional)</label><input type=\"text\" class=\"text\" name=\"mqttUser\" value=\"{MQTT_USER}\"/><label for=\"mqttPwd\">Password (optional)</label><input type=\"text\" class=\"text\" name=\"mqttPwd\" value=\"{MQTT_PWD}\"/><label for=\"mqttTopic\">Topic</label><input type=\"text\" class=\"text\" name=\"mqttTopic\" value=\"{MQTT_TOPIC}\"/><label for=\"mqttInterval\">Interval (seconds)</label><input type=\"text\" class=\"text\" name=\"mqttInterval\" value=\"{MQTT_INTERVAL}\"/><p class=\"des\">&nbsp;</p><input type=\"checkbox\" class=\"cb\" name=\"reboot\"/><label for=\"reboot\">Reboot device after successful save</label><input type=\"submit\" value=\"save\" class=\"button\" /></form></div></div><div id=\"footer\"><p class=\"left\"><a href=\"/\">Home</a></p><p class=\"left\"><a href=\"/update\">Update Firmware</a></p><p class=\"right\">AHOY - {VERSION}</p></div></body></html>";

2
tools/esp8266/html/h/style_css.h

@ -1 +1 @@
String style_css = "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: 14pt; color: #006ec0; } .subdes { font-size: 13pt; color: #006ec0; margin-left: 7px; } .fw { width: 60px; display: block; float: left; } .color { width: 50px; height: 50px; border: 1px solid #ccc; } .range { width: 300px; } a:link, a:visited { text-decoration: none; font-size: 13pt; color: #006ec0; } a:hover, a:focus { color: #f00; } #content { padding: 15px 15px 60px 15px; } #footer { position: fixed; bottom: 0px; height: 45px; background-color: #006ec0; width: 100%; } #footer p { color: #fff; padding-left: 20px; padding-right: 20px; font-size: 10pt !important; } #footer a { color: #fff; } div.content { background-color: #fff; padding-bottom: 65px; overflow: hidden; } input { padding: 7px; font-size: 13pt; } input.text, input.password { width: 70%; box-sizing: border-box; margin-bottom: 10px; /*float: right;*/ border: 1px solid #ccc; } input.button { background-color: #006ec0; color: #fff; border: 0px; float: right; 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.module { display: block; width: 250px; height: 410px; background-color: #006ec0; display: inline-block; position: relative; margin-right: 20px; margin-bottom: 20px; } div.module .value, div.module .info, div.module .header { color: #fff; display: block; width: 100%; text-align: center; } div.module .unit { font-size: 19px; margin-left: 10px; } div.module .value { margin-top: 20px; font-size: 30px; } div.module .info { margin-top: 3px; font-size: 10px; } div.module .header { background-color: #003c80; padding: 10px 0 10px 0; } ";
String style_css = "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: 14pt; color: #006ec0; } .subdes { font-size: 13pt; color: #006ec0; margin-left: 7px; } .fw { width: 60px; display: block; float: left; } .color { width: 50px; height: 50px; border: 1px solid #ccc; } .range { width: 300px; } a:link, a:visited { text-decoration: none; font-size: 13pt; color: #006ec0; } a:hover, a:focus { color: #f00; } #content { padding: 15px 15px 60px 15px; } #footer { position: fixed; bottom: 0px; height: 45px; background-color: #006ec0; width: 100%; } #footer p { color: #fff; padding-left: 20px; padding-right: 20px; font-size: 10pt !important; } #footer a { color: #fff; } div.content { background-color: #fff; padding-bottom: 65px; overflow: hidden; } input { padding: 7px; font-size: 13pt; } input.text, input.password { width: 70%; box-sizing: border-box; margin-bottom: 10px; /*float: right;*/ border: 1px solid #ccc; } input.button { background-color: #006ec0; color: #fff; border: 0px; float: right; 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 { width: 250px; height: 410px; background-color: #006ec0; display: inline-block; margin-right: 20px; margin-bottom: 20px; } div.ch .value, div.ch .info, div.ch .head { color: #fff; display: block; width: 100%; text-align: center; } div.ch .unit { font-size: 19px; margin-left: 10px; } div.ch .value { margin-top: 20px; font-size: 30px; } div.ch .info { margin-top: 3px; font-size: 10px; } div.ch .head { background-color: #003c80; padding: 10px 0 10px 0; } ";

1
tools/esp8266/html/setup.html

@ -24,6 +24,7 @@
<p class="des">Inverter</p>
{INVERTERS}<br/>
<p class="subdes">General</p>
<label for="invInterval">Interval (ms)</label>
<input type="text" class="text" name="invInterval" value="{INV_INTERVAL}"/>

14
tools/esp8266/html/style.css

@ -127,39 +127,37 @@ label {
float: right;
}
div.module {
display: block;
div.ch {
width: 250px;
height: 410px;
background-color: #006ec0;
display: inline-block;
position: relative;
margin-right: 20px;
margin-bottom: 20px;
}
div.module .value, div.module .info, div.module .header {
div.ch .value, div.ch .info, div.ch .head {
color: #fff;
display: block;
width: 100%;
text-align: center;
}
div.module .unit {
div.ch .unit {
font-size: 19px;
margin-left: 10px;
}
div.module .value {
div.ch .value {
margin-top: 20px;
font-size: 30px;
}
div.module .info {
div.ch .info {
margin-top: 3px;
font-size: 10px;
}
div.module .header {
div.ch .head {
background-color: #003c80;
padding: 10px 0 10px 0;
}

Loading…
Cancel
Save