mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-10 15:36:38 +02:00
* increased number of inverters
* name, serial and type can be configured using setup.html
This commit is contained in:
parent
97dfbb5936
commit
9e6cae26a7
9 changed files with 139 additions and 87 deletions
|
@ -44,12 +44,21 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) {
|
||||||
if(mSettingsValid) {
|
if(mSettingsValid) {
|
||||||
uint16_t interval;
|
uint16_t interval;
|
||||||
uint64_t invSerial;
|
uint64_t invSerial;
|
||||||
|
char invName[MAX_NAME_LENGTH + 1] = {0};
|
||||||
|
uint8_t invType;
|
||||||
|
|
||||||
|
// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// hoymiles
|
|
||||||
mEep->read(ADDR_INV0_ADDR, &invSerial);
|
|
||||||
mEep->read(ADDR_INV_INTERVAL, &interval);
|
mEep->read(ADDR_INV_INTERVAL, &interval);
|
||||||
mSys->addInverter("HM1200", invSerial, INV_TYPE_HM1200);
|
|
||||||
|
|
||||||
if(interval < 1000)
|
if(interval < 1000)
|
||||||
interval = 1000;
|
interval = 1000;
|
||||||
mSendTicker->attach_ms(interval, std::bind(&app::sendTicker, this));
|
mSendTicker->attach_ms(interval, std::bind(&app::sendTicker, this));
|
||||||
|
@ -129,29 +138,32 @@ void app::loop(void) {
|
||||||
mFlagSend = false;
|
mFlagSend = false;
|
||||||
|
|
||||||
uint8_t size = 0;
|
uint8_t size = 0;
|
||||||
inverter_t *inv = mSys->getInverterByPos(0);
|
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);*/
|
||||||
|
|
||||||
//if((mSendCnt % 6) == 0)
|
//Serial.println("sent packet: #" + String(mSendCnt));
|
||||||
size = mSys->Radio.getTimePacket(&inv->radioId.u64, mSendBuf, mTimestamp);
|
//dumpBuf("SEN ", mSendBuf, size);
|
||||||
/*else if((mSendCnt % 6) == 1)
|
sendPacket(inv, mSendBuf, size);
|
||||||
size = mSys->Radio.getCmdPacket(&inv->radioId.u64, mSendBuf, 0x15, 0x81);
|
mSendCnt++;
|
||||||
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);*/
|
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
//Serial.println("sent packet: #" + String(mSendCnt));
|
}
|
||||||
//dumpBuf("SEN ", mSendBuf, size);
|
|
||||||
sendPacket(inv, mSendBuf, size);
|
|
||||||
|
|
||||||
mSendCnt++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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(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));
|
snprintf(val, 10, "%.3f", mSys->getValue(iv, i));
|
||||||
mMqtt.sendMsg(topic, val);
|
mMqtt.sendMsg(topic, val);
|
||||||
delay(10);
|
delay(20);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,25 +340,35 @@ void app::showSetup(void) {
|
||||||
html.replace("{VERSION}", String(mVersion));
|
html.replace("{VERSION}", String(mVersion));
|
||||||
|
|
||||||
String inv;
|
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 ++) {
|
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 += "<p class=\"subdes\">Inverter "+ String(i) + "</p>";
|
||||||
|
|
||||||
inv += "<label for=\"inv" + String(i) + "Addr\">Address</label>";
|
inv += "<label for=\"inv" + String(i) + "Addr\">Address</label>";
|
||||||
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Addr\" value=\"";
|
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Addr\" value=\"";
|
||||||
inv += (NULL != pInv) ? String(mSys->getSerial(pInv), HEX) : "";
|
if(0ULL != invSerial)
|
||||||
inv += "\"/>";
|
inv += String(invSerial, HEX);
|
||||||
|
inv += "\"/ maxlength=\"12\">";
|
||||||
|
|
||||||
inv += "<label for=\"inv" + String(i) + "Name\">Name</label>";
|
inv += "<label for=\"inv" + String(i) + "Name\">Name</label>";
|
||||||
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
|
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
|
||||||
inv += (NULL != pInv) ? String(pInv->name) : "";
|
inv += String(invName);
|
||||||
inv += "\"/>";
|
inv += "\"/ maxlength=\"" + String(MAX_NAME_LENGTH) + "\">";
|
||||||
|
|
||||||
inv += "<label for=\"inv" + String(i) + "Type\">Type</label>";
|
inv += "<label for=\"inv" + String(i) + "Type\">Type</label>";
|
||||||
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
|
inv += "<select name=\"inv" + String(i) + "Type\">";
|
||||||
inv += (NULL != pInv) ? String(pInv->type) : "";
|
for(uint8_t t = 0; t < NUM_INVERTER_TYPES; t++) {
|
||||||
inv += "\"/>";
|
inv += "<option value=\"" + String(t) + "\"";
|
||||||
|
if(invType == t)
|
||||||
|
inv += " selected";
|
||||||
|
inv += ">" + String(invTypes[t]) + "</option>";
|
||||||
|
}
|
||||||
|
inv += "</select>";
|
||||||
}
|
}
|
||||||
html.replace("{INVERTERS}", String(inv));
|
html.replace("{INVERTERS}", String(inv));
|
||||||
|
|
||||||
|
@ -416,45 +438,50 @@ void app::showHoymiles(void) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::showLiveData(void) {
|
void app::showLiveData(void) {
|
||||||
String modHtml = "<pre>";
|
String modHtml;
|
||||||
|
|
||||||
char topic[20], val[10];
|
|
||||||
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
for(uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
||||||
inverter_t *iv = mSys->getInverterByPos(id);
|
inverter_t *iv = mSys->getInverterByPos(id);
|
||||||
if(NULL != iv) {
|
if(NULL != iv) {
|
||||||
/*uint8_t modNum;
|
#ifdef LIVEDATA_VISUALIZED
|
||||||
|
uint8_t modNum, pos;
|
||||||
switch(iv->type) {
|
switch(iv->type) {
|
||||||
default: modNum = 1; break;
|
default: modNum = 1; break;
|
||||||
case INV_TYPE_HM600: modNum = 2; break;
|
case INV_TYPE_HM600: modNum = 2; break;
|
||||||
case INV_TYPE_HM1200: modNum = 4; break;
|
case INV_TYPE_HM1200: modNum = 4; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint8_t mod = 1; mod <= modNum; mod ++) {
|
for(uint8_t ch = 1; ch <= modNum; ch ++) {
|
||||||
modHtml += "<div class=\"module\"><span class=\"header\">CHANNEL " + String(i) + "</span>";
|
modHtml += "<div class=\"ch\"><span class=\"head\">CHANNEL " + String(ch) + "</span>";
|
||||||
for(uint8_t j = 0; j < 5; j++) {
|
for(uint8_t j = 0; j < 5; j++) {
|
||||||
modHtml += "<span class=\"value\">";
|
|
||||||
switch(j) {
|
switch(j) {
|
||||||
default: modHtml += String(mDecoder->mData.ch_dc[i/2].u); break;
|
default: pos = (mSys->getPosByChField(iv, ch, FLD_UDC)); break;
|
||||||
case 1: modHtml += String(mDecoder->mData.ch_dc[i].i); break;
|
case 1: pos = (mSys->getPosByChField(iv, ch, FLD_IDC)); break;
|
||||||
case 2: modHtml += String(mDecoder->mData.ch_dc[i].p); break;
|
case 2: pos = (mSys->getPosByChField(iv, ch, FLD_PDC)); break;
|
||||||
case 3: modHtml += String(mDecoder->mData.ch_dc[i].y_d); break;
|
case 3: pos = (mSys->getPosByChField(iv, ch, FLD_YD)); break;
|
||||||
case 4: modHtml += String(mDecoder->mData.ch_dc[i].y_t); 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>";
|
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++) {
|
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));
|
snprintf(topic, 30, "%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(val, 10, "%.3f %s", mSys->getValue(iv, i), mSys->getUnit(iv, i));
|
||||||
modHtml += String(topic) + ": " + String(val) + "\n";
|
modHtml += String(topic) + ": " + String(val) + "\n";
|
||||||
}
|
}
|
||||||
|
modHtml += "</pre>";
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
modHtml += "</pre>";
|
|
||||||
|
|
||||||
mWeb->send(200, "text/html", modHtml);
|
mWeb->send(200, "text/html", modHtml);
|
||||||
}
|
}
|
||||||
|
@ -481,18 +508,25 @@ void app::saveValues(bool webSend = true) {
|
||||||
|
|
||||||
// inverter
|
// inverter
|
||||||
serial_u addr;
|
serial_u addr;
|
||||||
mWeb->arg("inv0Addr").toCharArray(buf, 20);
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
addr.u64 = Serial2u64(buf);
|
// address
|
||||||
mSys->updateSerial(mSys->getInverterByPos(0), addr.u64);
|
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);
|
||||||
|
|
||||||
for(uint8_t i = 0; i < 8; i++) {
|
// name
|
||||||
Serial.print(String(addr.b[i], HEX) + " ");
|
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();
|
interval = mWeb->arg("invInterval").toInt();
|
||||||
mEep->write(ADDR_INV0_ADDR, addr.u64);
|
|
||||||
mEep->write(ADDR_INV_INTERVAL, interval);
|
mEep->write(ADDR_INV_INTERVAL, interval);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
|
|
||||||
typedef HmRadio<RF24_CE_PIN, RF24_CS_PIN, RF24_IRQ_PIN> RadioType;
|
typedef HmRadio<RF24_CE_PIN, RF24_CS_PIN, RF24_IRQ_PIN> RadioType;
|
||||||
typedef CircularBuffer<packet_t, PACKET_BUFFER_SIZE> BufferType;
|
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 {
|
class app : public Main {
|
||||||
public:
|
public:
|
||||||
|
@ -59,6 +59,8 @@ class app : public Main {
|
||||||
for(uint8_t i = 0; i < 6; i++) {
|
for(uint8_t i = 0; i < 6; i++) {
|
||||||
tmp[0] = val[i*2];
|
tmp[0] = val[i*2];
|
||||||
tmp[1] = val[i*2 + 1];
|
tmp[1] = val[i*2 + 1];
|
||||||
|
if((tmp[0] == '\0') || (tmp[1] == '\0'))
|
||||||
|
break;
|
||||||
u64 = strtol(tmp, NULL, 16);
|
u64 = strtol(tmp, NULL, 16);
|
||||||
ret |= (u64 << ((5-i) << 3));
|
ret |= (u64 << ((5-i) << 3));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define PACKET_BUFFER_SIZE 30
|
#define PACKET_BUFFER_SIZE 30
|
||||||
#define MAX_NUM_INVERTERS 3
|
#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_MAJOR 0
|
||||||
#define VERSION_MINOR 2
|
#define VERSION_MINOR 2
|
||||||
#define VERSION_PATCH 2
|
#define VERSION_PATCH 3
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
@ -34,8 +36,10 @@
|
||||||
#define DEVNAME_LEN 16
|
#define DEVNAME_LEN 16
|
||||||
#define CRC_LEN 2
|
#define CRC_LEN 2
|
||||||
|
|
||||||
#define INV_ADDR_LEN 8 // uint64_t
|
#define INV_ADDR_LEN MAX_NUM_INVERTERS * 8 // uint64_t
|
||||||
#define INV_INTERVAL_LEN 2 // uint16_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
|
#define MQTT_ADDR_LEN 4 // IP
|
||||||
|
@ -49,8 +53,10 @@
|
||||||
#define ADDR_SSID ADDR_START
|
#define ADDR_SSID ADDR_START
|
||||||
#define ADDR_PWD ADDR_SSID + SSID_LEN
|
#define ADDR_PWD ADDR_SSID + SSID_LEN
|
||||||
#define ADDR_DEVNAME ADDR_PWD + PWD_LEN
|
#define ADDR_DEVNAME ADDR_PWD + PWD_LEN
|
||||||
#define ADDR_INV0_ADDR ADDR_DEVNAME + DEVNAME_LEN
|
#define ADDR_INV_ADDR ADDR_DEVNAME + DEVNAME_LEN
|
||||||
#define ADDR_INV_INTERVAL ADDR_INV0_ADDR + INV_ADDR_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_ADDR ADDR_INV_INTERVAL + INV_INTERVAL_LEN
|
||||||
#define ADDR_MQTT_USER ADDR_MQTT_ADDR + MQTT_ADDR_LEN
|
#define ADDR_MQTT_USER ADDR_MQTT_ADDR + MQTT_ADDR_LEN
|
||||||
|
|
|
@ -21,7 +21,8 @@ enum {CH0 = 0, CH1, CH2, CH3, CH4};
|
||||||
enum {CMD01 = 0x01, CMD02, CMD03, CMD83 = 0x83, CMD84};
|
enum {CMD01 = 0x01, CMD02, CMD03, CMD83 = 0x83, CMD84};
|
||||||
|
|
||||||
enum {INV_TYPE_HM600 = 0, INV_TYPE_HM1200};
|
enum {INV_TYPE_HM600 = 0, INV_TYPE_HM1200};
|
||||||
|
const char* const invTypes[] = {"HM600", "HM1200"};
|
||||||
|
#define NUM_INVERTER_TYPES 2
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t fieldId; // field id
|
uint8_t fieldId; // field id
|
||||||
|
@ -41,7 +42,7 @@ union serial_u {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t id; // unique id
|
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
|
uint8_t type; // integer which refers to inverter type
|
||||||
byteAssign_t* assign; // type of inverter
|
byteAssign_t* assign; // type of inverter
|
||||||
uint8_t listLen; // length of assignments
|
uint8_t listLen; // length of assignments
|
||||||
|
|
|
@ -31,11 +31,11 @@ class HmSystem {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
inverter_t *p = &mInverter[mNumInv];
|
inverter_t *p = &mInverter[mNumInv];
|
||||||
p->id = mNumInv++;
|
p->id = mNumInv;
|
||||||
p->serial.u64 = serial;
|
p->serial.u64 = serial;
|
||||||
p->type = type;
|
p->type = type;
|
||||||
uint8_t len = strlen(name);
|
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);
|
getAssignment(p);
|
||||||
toRadioId(p);
|
toRadioId(p);
|
||||||
|
|
||||||
|
@ -44,8 +44,9 @@ class HmSystem {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
mRecord = new RECORDTYPE[p->listLen];
|
mRecord[p->id] = new RECORDTYPE[p->listLen];
|
||||||
memset(mRecord, 0, sizeof(RECORDTYPE) * p->listLen);
|
memset(mRecord[p->id], 0, sizeof(RECORDTYPE) * p->listLen);
|
||||||
|
mNumInv ++;
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,11 +106,20 @@ class HmSystem {
|
||||||
val |= buf[ptr];
|
val |= buf[ptr];
|
||||||
} while(++ptr != end);
|
} 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) {
|
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) {
|
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;
|
uint8_t mNumInv;
|
||||||
RECORDTYPE *mRecord;
|
RECORDTYPE *mRecord[MAX_INVERTER];
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__HM_SYSTEM_H__*/
|
#endif /*__HM_SYSTEM_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\"> </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\"> </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>";
|
||||||
|
|
|
@ -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; } ";
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
<p class="des">Inverter</p>
|
<p class="des">Inverter</p>
|
||||||
{INVERTERS}<br/>
|
{INVERTERS}<br/>
|
||||||
|
<p class="subdes">General</p>
|
||||||
<label for="invInterval">Interval (ms)</label>
|
<label for="invInterval">Interval (ms)</label>
|
||||||
<input type="text" class="text" name="invInterval" value="{INV_INTERVAL}"/>
|
<input type="text" class="text" name="invInterval" value="{INV_INTERVAL}"/>
|
||||||
|
|
||||||
|
|
|
@ -127,39 +127,37 @@ label {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.module {
|
div.ch {
|
||||||
display: block;
|
|
||||||
width: 250px;
|
width: 250px;
|
||||||
height: 410px;
|
height: 410px;
|
||||||
background-color: #006ec0;
|
background-color: #006ec0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
position: relative;
|
|
||||||
margin-right: 20px;
|
margin-right: 20px;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
div.module .value, div.module .info, div.module .header {
|
div.ch .value, div.ch .info, div.ch .head {
|
||||||
color: #fff;
|
color: #fff;
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.module .unit {
|
div.ch .unit {
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.module .value {
|
div.ch .value {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.module .info {
|
div.ch .info {
|
||||||
margin-top: 3px;
|
margin-top: 3px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.module .header {
|
div.ch .head {
|
||||||
background-color: #003c80;
|
background-color: #003c80;
|
||||||
padding: 10px 0 10px 0;
|
padding: 10px 0 10px 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue