diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 0c6c499e..f62089d5 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -10,11 +10,14 @@ app::app() : Main() { mSendTicker = new Ticker(); mFlagSend = false; + mShowRebootRequest = false; + mMqttTicker = NULL; mMqttEvt = false; - memset(mCmds, 0, sizeof(uint32_t)); - memset(mChannelStat, 0, sizeof(uint32_t)); + + memset(mCmds, 0, sizeof(uint32_t)*DBG_CMD_LIST_LEN); + //memset(mChannelStat, 0, sizeof(uint32_t) * 4); mSys = new HmSystemType(); } @@ -30,13 +33,14 @@ app::~app(void) { void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { Main::setup(ssid, pwd, timeout); - mWeb->on("/", std::bind(&app::showIndex, this)); - mWeb->on("/setup", std::bind(&app::showSetup, this)); - mWeb->on("/save", std::bind(&app::showSave, this)); - mWeb->on("/cmdstat", std::bind(&app::showCmdStatistics, this)); - mWeb->on("/hoymiles", std::bind(&app::showHoymiles, this)); - mWeb->on("/livedata", std::bind(&app::showLiveData, this)); - mWeb->on("/mqttstate", std::bind(&app::showMqtt, this)); + mWeb->on("/", std::bind(&app::showIndex, this)); + mWeb->on("/setup", std::bind(&app::showSetup, this)); + mWeb->on("/save", std::bind(&app::showSave, this)); + mWeb->on("/erase", std::bind(&app::showErase, this)); + mWeb->on("/cmdstat", std::bind(&app::showStatistics, this)); + mWeb->on("/hoymiles", std::bind(&app::showHoymiles, this)); + mWeb->on("/livedata", std::bind(&app::showLiveData, this)); + mWeb->on("/mqttstate", std::bind(&app::showMqtt, this)); if(mSettingsValid) { uint16_t interval; @@ -51,7 +55,7 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { 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)); + DPRINTLN("add inverter: " + String(invName) + ", SN: " + String(invSerial, HEX) + ", type: " + String(invType)); } } @@ -67,8 +71,12 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { mEep->read(ADDR_PINOUT+2, &mSys->Radio.pinIrq); + // nrf24 amplifier power + mEep->read(ADDR_RF24_AMP_PWR, &mSys->Radio.AmplifierPower); + // mqtt uint8_t mqttAddr[MQTT_ADDR_LEN]; + uint16_t mqttPort; char mqttUser[MQTT_USER_LEN]; char mqttPwd[MQTT_PWD_LEN]; char mqttTopic[MQTT_TOPIC_LEN]; @@ -77,13 +85,14 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { mEep->read(ADDR_MQTT_PWD, mqttPwd, MQTT_PWD_LEN); mEep->read(ADDR_MQTT_TOPIC, mqttTopic, MQTT_TOPIC_LEN); mEep->read(ADDR_MQTT_INTERVAL, &interval); + mEep->read(ADDR_MQTT_PORT, &mqttPort); char addr[16] = {0}; sprintf(addr, "%d.%d.%d.%d", mqttAddr[0], mqttAddr[1], mqttAddr[2], mqttAddr[3]); if(interval < 1000) interval = 1000; - mMqtt.setup(addr, mqttTopic, mqttUser, mqttPwd); + mMqtt.setup(addr, mqttTopic, mqttUser, mqttPwd, mqttPort); mMqttTicker = new Ticker(); mMqttTicker->attach_ms(interval, std::bind(&app::mqttTicker, this)); @@ -92,8 +101,16 @@ void app::setup(const char *ssid, const char *pwd, uint32_t timeout) { mSys->setup(); - if(!mSettingsValid) - Serial.println("Warn: your settings are not valid! check [IP]/setup"); + if(!mWifiSettingsValid) + DPRINTLN("Warn: your settings are not valid! check [IP]/setup"); + else { + DPRINTLN("\n\n----------------------------------------"); + DPRINTLN("Welcome to AHOY!"); + DPRINT("\npoint your browser to http://"); + DPRINTLN(WiFi.localIP()); + DPRINTLN("to configure your device"); + DPRINTLN("----------------------------------------\n"); + } } @@ -110,14 +127,14 @@ void app::loop(void) { // process buffer only on first occurrence if((0 != len) && (0 == rptCnt)) { uint8_t *cmd = &p->packet[11]; - //Serial.println("CMD " + String(*cmd, HEX)); + //DPRINTLN("CMD " + String(*cmd, HEX)); //mSys->Radio.dumpBuf("Payload ", p->packet, len); - inverter_t *iv = mSys->findInverter(&p->packet[3]); + Inverter<> *iv = mSys->findInverter(&p->packet[3]); if(NULL != iv) { for(uint8_t i = 0; i < iv->listLen; i++) { if(iv->assign[i].cmdId == *cmd) - mSys->addValue(iv, i, &p->packet[11]); + iv->addValue(i, &p->packet[11]); } } @@ -125,13 +142,15 @@ void app::loop(void) { else if(*cmd == 0x02) mCmds[1]++; else if(*cmd == 0x03) mCmds[2]++; else if(*cmd == 0x81) mCmds[3]++; - else if(*cmd == 0x84) mCmds[4]++; - else mCmds[5]++; + else if(*cmd == 0x82) mCmds[4]++; + else if(*cmd == 0x83) mCmds[5]++; + else if(*cmd == 0x84) mCmds[6]++; + else mCmds[7]++; - if(p->sendCh == 23) mChannelStat[0]++; + /*if(p->sendCh == 23) mChannelStat[0]++; else if(p->sendCh == 40) mChannelStat[1]++; else if(p->sendCh == 61) mChannelStat[2]++; - else mChannelStat[3]++; + else mChannelStat[3]++;*/ } } mSys->BufCtrl.popBack(); @@ -139,12 +158,13 @@ void app::loop(void) { if(mFlagSend) { mFlagSend = false; - inverter_t *inv; + Inverter<> *inv; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) { inv = mSys->getInverterByPos(i); if(NULL != inv) { mSys->Radio.sendTimePacket(inv->radioId.u64, mTimestamp); - delay(20); + yield(); + delay(100); } } } @@ -157,14 +177,15 @@ void app::loop(void) { mMqtt.isConnected(true); char topic[30], val[10]; for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - inverter_t *iv = mSys->getInverterByPos(id); + Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { for(uint8_t i = 0; i < iv->listLen; i++) { - if(0.0f != mSys->getValue(iv, i)) { + if(0.0f != iv->getValue(i)) { 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", iv->getValue(i)); mMqtt.sendMsg(topic, val); delay(20); + yield(); } } } @@ -173,14 +194,15 @@ void app::loop(void) { // Serial debug //char topic[30], val[10]; for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - inverter_t *iv = mSys->getInverterByPos(id); + Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { for(uint8_t i = 0; i < iv->listLen; i++) { - if(0.0f != mSys->getValue(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)); - Serial.println(String(topic) + ": " + String(val)); + if(0.0f != iv->getValue(i)) { + snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i)); + snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i)); + DPRINTLN(String(topic) + ": " + String(val)); } + yield(); } } } @@ -282,17 +304,31 @@ void app::showSetup(void) { html.replace("{PINOUT}", String(pinout)); + // nrf24l01+ + String rf24; + for(uint8_t i = 0; i <= 3; i++) { + rf24 += ""; + } + html.replace("{RF24}", String(rf24)); + + if(mSettingsValid) { mEep->read(ADDR_INV_INTERVAL, &interval); html.replace("{INV_INTERVAL}", String(interval)); uint8_t mqttAddr[MQTT_ADDR_LEN] = {0}; + uint16_t mqttPort; mEep->read(ADDR_MQTT_ADDR, mqttAddr, MQTT_ADDR_LEN); mEep->read(ADDR_MQTT_INTERVAL, &interval); + mEep->read(ADDR_MQTT_PORT, &mqttPort); char addr[16] = {0}; sprintf(addr, "%d.%d.%d.%d", mqttAddr[0], mqttAddr[1], mqttAddr[2], mqttAddr[3]); html.replace("{MQTT_ADDR}", String(addr)); + html.replace("{MQTT_PORT}", String(mqttPort)); html.replace("{MQTT_USER}", String(mMqtt.getUser())); html.replace("{MQTT_PWD}", String(mMqtt.getPwd())); html.replace("{MQTT_TOPIC}", String(mMqtt.getTopic())); @@ -302,6 +338,7 @@ void app::showSetup(void) { html.replace("{INV_INTERVAL}", "1000"); html.replace("{MQTT_ADDR}", ""); + html.replace("{MQTT_PORT}", "1883"); html.replace("{MQTT_USER}", ""); html.replace("{MQTT_PWD}", ""); html.replace("{MQTT_TOPIC}", "/inverter"); @@ -319,20 +356,32 @@ void app::showSave(void) { //----------------------------------------------------------------------------- -void app::showCmdStatistics(void) { - String content = "CMDs:\n"; - content += String("0x01: ") + String(mCmds[0]) + String("\n"); - content += String("0x02: ") + String(mCmds[1]) + String("\n"); - content += String("0x03: ") + String(mCmds[2]) + String("\n"); - content += String("0x81: ") + String(mCmds[3]) + String("\n"); - content += String("0x84: ") + String(mCmds[4]) + String("\n"); - content += String("other: ") + String(mCmds[5]) + String("\n"); +void app::showErase() { + eraseSettings(); + showReboot(); +} - content += "\nCHANNELs:\n"; + +//----------------------------------------------------------------------------- +void app::showStatistics(void) { + String content = "CMDs:\n"; + for(uint8_t i = 0; i < DBG_CMD_LIST_LEN; i ++) { + content += String("0x") + String(dbgCmds[i], HEX) + String(": ") + String(mCmds[i]) + String("\n"); + } + content += String("other: ") + String(mCmds[DBG_CMD_LIST_LEN]) + String("\n\n"); + + /*content += "\nCHANNELs:\n"; content += String("23: ") + String(mChannelStat[0]) + String("\n"); content += String("40: ") + String(mChannelStat[1]) + String("\n"); content += String("61: ") + String(mChannelStat[2]) + String("\n"); - content += String("75: ") + String(mChannelStat[3]) + String("\n"); + content += String("75: ") + String(mChannelStat[3]) + String("\n");*/ + + if(!mSys->Radio.isChipConnected()) + content += "WARNING! your NRF24 module can't be reached, check the wiring\n"; + + if(mShowRebootRequest) + content += "INFO: reboot your ESP to apply all your configuration changes!\n"; + mWeb->send(200, "text/plain", content); } @@ -350,7 +399,7 @@ void app::showHoymiles(void) { void app::showLiveData(void) { String modHtml; for(uint8_t id = 0; id < mSys->getNumInverters(); id++) { - inverter_t *iv = mSys->getInverterByPos(id); + Inverter<> *iv = mSys->getInverterByPos(id); if(NULL != iv) { #ifdef LIVEDATA_VISUALIZED uint8_t modNum, pos; @@ -364,16 +413,16 @@ void app::showLiveData(void) { modHtml += "
CHANNEL " + String(ch) + ""; for(uint8_t j = 0; j < 5; j++) { switch(j) { - 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; + default: pos = (iv->getPosByChFld(ch, FLD_UDC)); break; + case 1: pos = (iv->getPosByChFld(ch, FLD_IDC)); break; + case 2: pos = (iv->getPosByChFld(ch, FLD_PDC)); break; + case 3: pos = (iv->getPosByChFld(ch, FLD_YD)); break; + case 4: pos = (iv->getPosByChFld(ch, FLD_YT)); break; } if(0xff != pos) { - modHtml += "" + String(mSys->getValue(iv, pos)); - modHtml += "" + String(mSys->getUnit(iv, pos)) + ""; - modHtml += "" + String(mSys->getFieldName(iv, pos)) + ""; + modHtml += "" + String(iv->getValue(pos)); + modHtml += "" + String(iv->getUnit(pos)) + ""; + modHtml += "" + String(iv->getFieldName(pos)) + ""; } } modHtml += "
"; @@ -383,8 +432,8 @@ void app::showLiveData(void) { modHtml = "
";
             char topic[30], val[10];
             for(uint8_t i = 0; i < iv->listLen; 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));
+                snprintf(topic, 30, "%s/ch%d/%s", iv->name, iv->assign[i].ch, iv->getFieldName(i));
+                snprintf(val, 10, "%.3f %s", iv->getValue(i), iv->getUnit(i));
                 modHtml += String(topic) + ": " + String(val) + "\n";
             }
             modHtml += "
"; @@ -400,7 +449,7 @@ void app::showLiveData(void) { //----------------------------------------------------------------------------- void app::showMqtt(void) { String txt = "connected"; - if(mMqtt.isConnected()) + if(!mMqtt.isConnected()) txt = "not " + txt; mWeb->send(200, "text/plain", txt); } @@ -447,8 +496,13 @@ void app::saveValues(bool webSend = true) { } + // nrf24 amplifier power + mSys->Radio.AmplifierPower = mWeb->arg("rf24Power").toInt() & 0x03; + mEep->write(ADDR_RF24_AMP_PWR, mSys->Radio.AmplifierPower); + // mqtt uint8_t mqttAddr[MQTT_ADDR_LEN] = {0}; + uint16_t mqttPort; char mqttUser[MQTT_USER_LEN]; char mqttPwd[MQTT_PWD_LEN]; char mqttTopic[MQTT_TOPIC_LEN]; @@ -463,7 +517,9 @@ void app::saveValues(bool webSend = true) { mWeb->arg("mqttPwd").toCharArray(mqttPwd, MQTT_PWD_LEN); mWeb->arg("mqttTopic").toCharArray(mqttTopic, MQTT_TOPIC_LEN); interval = mWeb->arg("mqttInterval").toInt(); + mqttPort = mWeb->arg("mqttPort").toInt(); mEep->write(ADDR_MQTT_ADDR, mqttAddr, MQTT_ADDR_LEN); + mEep->write(ADDR_MQTT_PORT, mqttPort); mEep->write(ADDR_MQTT_USER, mqttUser, MQTT_USER_LEN); mEep->write(ADDR_MQTT_PWD, mqttPwd, MQTT_PWD_LEN); mEep->write(ADDR_MQTT_TOPIC, mqttTopic, MQTT_TOPIC_LEN); @@ -473,6 +529,7 @@ void app::saveValues(bool webSend = true) { if((mWeb->arg("reboot") == "on")) showReboot(); else { + mShowRebootRequest = true; mWeb->send(200, "text/html", "Setup saved" "

saved

"); } @@ -490,6 +547,6 @@ void app::updateCrc(void) { uint16_t crc; crc = buildEEpCrc(ADDR_START_SETTINGS, (ADDR_NEXT - ADDR_START_SETTINGS)); - //Serial.println("new CRC: " + String(crc, HEX)); + //DPRINTLN("new CRC: " + String(crc, HEX)); mEep->write(ADDR_SETTINGS_CRC, crc); } diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index c4cabcdd..75ae6cd5 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -13,7 +13,8 @@ typedef CircularBuffer BufferType; typedef HmRadio RadioType; -typedef HmSystem HmSystemType; +typedef Inverter InverterType; +typedef HmSystem HmSystemType; const char* const wemosPins[] = {"D3 (GPIO0)", "TX (GPIO1)", "D4 (GPIO2)", "RX (GPIO3)", "D2 (GPIO4)", "D1 (GPIO5)", "GPIO6", "GPIO7", "GPIO8", @@ -22,6 +23,9 @@ const char* const wemosPins[] = {"D3 (GPIO0)", "TX (GPIO1)", "D4 (GPIO2)", "RX ( const char* const pinNames[] = {"CS", "CE", "IRQ"}; const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq"}; +const uint8_t dbgCmds[] = {0x01, 0x02, 0x03, 0x81, 0x82, 0x83, 0x84}; +#define DBG_CMD_LIST_LEN 7 + class app : public Main { public: app(); @@ -42,7 +46,8 @@ class app : public Main { void showIndex(void); void showSetup(void); void showSave(void); - void showCmdStatistics(void); + void showErase(void); + void showStatistics(void); void showHoymiles(void); void showLiveData(void); void showMqtt(void); @@ -65,16 +70,15 @@ class app : public Main { return ret; } - uint8_t mState; - bool mKeyPressed; + bool mShowRebootRequest; HmSystemType *mSys; Ticker *mSendTicker; bool mFlagSend; - uint32_t mCmds[6]; - uint32_t mChannelStat[4]; + uint32_t mCmds[DBG_CMD_LIST_LEN+1]; + //uint32_t mChannelStat[4]; uint32_t mRecCnt; // mqtt diff --git a/tools/esp8266/debug.h b/tools/esp8266/debug.h index 11e8e071..26bf1d89 100644 --- a/tools/esp8266/debug.h +++ b/tools/esp8266/debug.h @@ -1,8 +1,11 @@ #ifndef __DEBUG_H__ #define __DEBUG_H__ +#include "Arduino.h" + #ifdef NDEBUG #define DPRINT(str) + #define DPRINTLN(str) #else #ifndef DSERIAL diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 765ba2b2..74a51a0b 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -25,7 +25,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 2 -#define VERSION_PATCH 4 +#define VERSION_PATCH 10 //------------------------------------- @@ -50,11 +50,14 @@ typedef struct { #define PINOUT_LEN 3 // 3 pins: CS, CE, IRQ +#define RF24_AMP_PWR_LEN 1 + #define MQTT_ADDR_LEN 4 // IP #define MQTT_USER_LEN 16 #define MQTT_PWD_LEN 32 #define MQTT_TOPIC_LEN 32 #define MQTT_INTERVAL_LEN 2 // uint16_t +#define MQTT_PORT_LEN 2 // uint16_t #define ADDR_START 0 @@ -66,7 +69,9 @@ typedef struct { #define ADDR_PINOUT ADDR_START_SETTINGS -#define ADDR_INV_ADDR ADDR_PINOUT + PINOUT_LEN +#define ADDR_RF24_AMP_PWR ADDR_PINOUT + PINOUT_LEN + +#define ADDR_INV_ADDR ADDR_RF24_AMP_PWR + RF24_AMP_PWR_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 @@ -77,7 +82,8 @@ typedef struct { #define ADDR_MQTT_TOPIC ADDR_MQTT_PWD + MQTT_PWD_LEN #define ADDR_MQTT_INTERVAL ADDR_MQTT_TOPIC + MQTT_TOPIC_LEN -#define ADDR_NEXT ADDR_MQTT_INTERVAL + MQTT_INTERVAL_LEN +#define ADDR_MQTT_PORT ADDR_MQTT_INTERVAL + MQTT_INTERVAL_LEN +#define ADDR_NEXT ADDR_MQTT_PORT + MQTT_PORT_LEN #define ADDR_SETTINGS_CRC 400 diff --git a/tools/esp8266/eep.h b/tools/esp8266/eep.h index da1450b0..a49cae67 100644 --- a/tools/esp8266/eep.h +++ b/tools/esp8266/eep.h @@ -37,7 +37,7 @@ class eep { } void read(uint32_t addr, uint8_t data[], uint16_t length) { - for(uint8_t i = 0; i < length; i ++) { + for(uint16_t i = 0; i < length; i ++) { *(data++) = EEPROM.read(addr++); } } @@ -78,7 +78,7 @@ class eep { } void write(uint32_t addr, uint8_t data[], uint16_t length) { - for(uint8_t i = 0; i < length; i ++) { + for(uint16_t i = 0; i < length; i ++) { EEPROM.write(addr++, data[i]); } EEPROM.commit(); diff --git a/tools/esp8266/hmInverters.h b/tools/esp8266/hmInverters.h deleted file mode 100644 index 45c79167..00000000 --- a/tools/esp8266/hmInverters.h +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef __HM_INVERTERS_H__ -#define __HM_INVERTERS_H__ - -#include "debug.h" -#include - -// units -enum {UNIT_V = 0, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT}; -const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%"}; - -// field types -enum {FLD_UDC = 0, FLD_IDC, FLD_PDC, FLD_YD, FLD_YW, FLD_YT, - FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_T, FLD_PCT}; -const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", - "U_AC", "I_AC", "P_AC", "Freq", "Temp", "Pct"}; - - - -// CH0 is default channel (freq, ac, temp) -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 - uint8_t unitId; // uint id - uint8_t ch; // channel 0 - 3 - uint8_t cmdId; // received command id - uint8_t start; // pos of first byte in buffer - uint8_t num; // number of bytes in buffer - uint16_t div; // divisor -} byteAssign_t; - - -union serial_u { - uint64_t u64; - uint8_t b[8]; -}; - -typedef struct { - uint8_t id; // unique id - 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 - serial_u serial; // serial number as on barcode - serial_u radioId; // id converted to modbus -} inverter_t; - - -/** - * indices are built for the buffer starting with cmd-id in first byte - * (complete payload in buffer) - * */ - -//------------------------------------- -// HM600, HM700 -//------------------------------------- -const byteAssign_t hm600assignment[] = { - { FLD_UDC, UNIT_V, CH1, CMD01, 14, 2, 10 }, - { FLD_IDC, UNIT_A, CH1, CMD01, 16, 2, 100 }, - { FLD_PDC, UNIT_W, CH1, CMD01, 18, 2, 10 }, - { FLD_UDC, UNIT_V, CH2, CMD01, 20, 2, 10 }, - { FLD_IDC, UNIT_A, CH2, CMD01, 22, 2, 100 }, - { FLD_PDC, UNIT_W, CH2, CMD01, 24, 2, 10 }, - { FLD_YW, UNIT_WH, CH0, CMD02, 12, 2, 1 }, - { FLD_YT, UNIT_WH, CH0, CMD02, 14, 4, 1 }, - { FLD_YD, UNIT_WH, CH1, CMD02, 18, 2, 1 }, - { FLD_YD, UNIT_WH, CH2, CMD02, 20, 2, 1 }, - { FLD_UAC, UNIT_V, CH0, CMD02, 22, 2, 10 }, - { FLD_F, UNIT_HZ, CH0, CMD02, 24, 2, 100 }, - { FLD_IAC, UNIT_A, CH0, CMD02, 26, 2, 10 }, - { FLD_T, UNIT_C, CH0, CMD83, 18, 2, 10 } -}; -#define HM600_LIST_LEN (sizeof(hm600assignment) / sizeof(byteAssign_t)) - - -//------------------------------------- -// HM1200, HM1500? -//------------------------------------- -const byteAssign_t hm1200assignment[] = { - { FLD_UDC, UNIT_V, CH1, CMD01, 3, 2, 10 }, - { FLD_IDC, UNIT_A, CH1, CMD01, 5, 2, 100 }, - { FLD_PDC, UNIT_W, CH1, CMD01, 9, 2, 10 }, - { FLD_YD, UNIT_WH, CH1, CMD02, 5, 2, 1 }, - { FLD_YT, UNIT_KWH, CH1, CMD01, 13, 4, 1000 }, - { FLD_UDC, UNIT_V, CH2, CMD02, 9, 2, 10 }, - { FLD_IDC, UNIT_A, CH2, CMD01, 7, 2, 100 }, - { FLD_PDC, UNIT_W, CH2, CMD01, 11, 2, 10 }, - { FLD_YD, UNIT_WH, CH2, CMD02, 7, 2, 1 }, - { FLD_YT, UNIT_KWH, CH2, CMD02, 1, 4, 1000 }, - { FLD_IDC, UNIT_A, CH3, CMD02, 11, 2, 100 }, - { FLD_PDC, UNIT_W, CH3, CMD02, 15, 2, 10 }, - { FLD_YD, UNIT_WH, CH3, CMD03, 11, 2, 1 }, - { FLD_YT, UNIT_KWH, CH3, CMD03, 3, 4, 1000 }, - { FLD_IDC, UNIT_A, CH4, CMD02, 13, 2, 100 }, - { FLD_PDC, UNIT_W, CH4, CMD03, 1, 2, 10 }, - { FLD_YD, UNIT_WH, CH4, CMD03, 13, 2, 1 }, - { FLD_YT, UNIT_KWH, CH4, CMD03, 7, 4, 1000 }, - { FLD_UAC, UNIT_V, CH0, CMD03, 15, 2, 10 }, - { FLD_IAC, UNIT_A, CH0, CMD84, 7, 2, 100 }, - { FLD_PAC, UNIT_W, CH0, CMD84, 3, 2, 10 }, - { FLD_F, UNIT_HZ, CH0, CMD84, 1, 2, 100 }, - { FLD_PCT, UNIT_PCT, CH0, CMD84, 9, 2, 10 }, - { FLD_T, UNIT_C, CH0, CMD84, 11, 2, 10 } -}; -#define HM1200_LIST_LEN (sizeof(hm1200assignment) / sizeof(byteAssign_t)) - -#endif /*__HM_INVERTERS_H__*/ diff --git a/tools/esp8266/hmRadio.h b/tools/esp8266/hmRadio.h index 70e710e0..65a098a5 100644 --- a/tools/esp8266/hmRadio.h +++ b/tools/esp8266/hmRadio.h @@ -13,6 +13,10 @@ #define DUMMY_RADIO_ID ((uint64_t)0xDEADBEEF01ULL) +const char* const rf24AmpPower[] = {"MIN", "LOW", "HIGH", "MAX"}; + + + //----------------------------------------------------------------------------- // MACROS //----------------------------------------------------------------------------- @@ -54,12 +58,13 @@ class HmRadio { pinCe = CE_PIN; pinIrq = IRQ_PIN; - mSendCnt = 0; + AmplifierPower = 1; + mSendCnt = 0; } ~HmRadio() {} void setup(BUFFER *ctrl) { - //Serial.println("HmRadio::setup, pins: " + String(pinCs) + ", " + String(pinCe) + ", " + String(pinIrq)); + //DPRINTLN("HmRadio::setup, pins: " + String(pinCs) + ", " + String(pinCe) + ", " + String(pinIrq)); pinMode(pinIrq, INPUT_PULLUP); mBufCtrl = ctrl; @@ -79,14 +84,18 @@ class HmRadio { // enable only receiving interrupts mNrf24.maskIRQ(true, true, false); - // Use lo PA level, as a higher level will disturb CH340 serial usb adapter - mNrf24.setPALevel(RF24_PA_MAX); + DPRINTLN("RF24 Amp Pwr: RF24_PA_" + String(rf24AmpPower[AmplifierPower])); + mNrf24.setPALevel(AmplifierPower & 0x03); mNrf24.startListening(); - Serial.println("Radio Config:"); + DPRINTLN("Radio Config:"); mNrf24.printPrettyDetails(); mSendChannel = getDefaultChannel(); + + if(!mNrf24.isChipConnected()) { + DPRINTLN("WARNING! your NRF24 module can't be reached, check the wiring"); + } } void handleIntr(void) { @@ -177,13 +186,30 @@ class HmRadio { return valid; } + void dumpBuf(const char *info, uint8_t buf[], uint8_t len) { + DPRINT(String(info)); + for(uint8_t i = 0; i < len; i++) { + if(buf[i] < 10) + DPRINT("0"); + DHEX(buf[i]); + DPRINT(" "); + } + DPRINTLN(""); + } + + bool isChipConnected(void) { + return mNrf24.isChipConnected(); + } + uint8_t pinCs; uint8_t pinCe; uint8_t pinIrq; + uint8_t AmplifierPower; + private: void sendPacket(uint64_t invId, uint8_t buf[], uint8_t len) { - //Serial.println("sent packet: #" + String(mSendCnt)); + //DPRINTLN("sent packet: #" + String(mSendCnt)); //dumpBuf("SEN ", buf, len); DISABLE_IRQ; @@ -195,7 +221,7 @@ class HmRadio { mSendChannel = getDefaultChannel(); #endif mNrf24.setChannel(mSendChannel); - //Serial.println("CH: " + String(mSendChannel)); + //DPRINTLN("CH: " + String(mSendChannel)); mNrf24.openWritingPipe(invId); // TODO: deprecated mNrf24.setCRCLength(RF24_CRC_16); @@ -230,15 +256,6 @@ class HmRadio { mDtuIdCrc = crc16nrf24(tmp, BIT_CNT(5)); } - void dumpBuf(const char *info, uint8_t buf[], uint8_t len) { - Serial.print(String(info)); - for(uint8_t i = 0; i < len; i++) { - Serial.print(buf[i], HEX); - Serial.print(" "); - } - Serial.println(); - } - uint8_t mChanOut[4]; uint8_t mChanIdx; uint16_t mDtuIdCrc; diff --git a/tools/esp8266/hmSystem.h b/tools/esp8266/hmSystem.h index 0f79ca9f..62a76cc3 100644 --- a/tools/esp8266/hmSystem.h +++ b/tools/esp8266/hmSystem.h @@ -1,12 +1,12 @@ #ifndef __HM_SYSTEM_H__ #define __HM_SYSTEM_H__ -#include "hmInverters.h" +#include "hmInverter.h" #include "hmRadio.h" -template +template > class HmSystem { public: typedef RADIO RadioType; @@ -25,34 +25,30 @@ class HmSystem { Radio.setup(&BufCtrl); } - inverter_t *addInverter(const char *name, uint64_t serial, uint8_t type) { + INVERTERTYPE *addInverter(const char *name, uint64_t serial, uint8_t type) { if(MAX_INVERTER <= mNumInv) { DPRINT("max number of inverters reached!"); return NULL; } - inverter_t *p = &mInverter[mNumInv]; + INVERTERTYPE *p = &mInverter[mNumInv]; p->id = mNumInv; p->serial.u64 = serial; p->type = type; uint8_t len = strlen(name); strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len); - getAssignment(p); - toRadioId(p); if(NULL == p->assign) { DPRINT("no assignment for type found!"); return NULL; } else { - mRecord[p->id] = new RECORDTYPE[p->listLen]; - memset(mRecord[p->id], 0, sizeof(RECORDTYPE) * p->listLen); mNumInv ++; return p; } } - inverter_t *findInverter(uint8_t buf[]) { - inverter_t *p; + INVERTERTYPE *findInverter(uint8_t buf[]) { + INVERTERTYPE *p; for(uint8_t i = 0; i < mNumInv; i++) { p = &mInverter[i]; if((p->serial.b[3] == buf[0]) @@ -64,96 +60,20 @@ class HmSystem { return NULL; } - inverter_t *getInverterByPos(uint8_t pos) { + INVERTERTYPE *getInverterByPos(uint8_t pos) { if(mInverter[pos].serial.u64 != 0ULL) return &mInverter[pos]; else return NULL; } - const char *getFieldName(inverter_t *p, uint8_t pos) { - return fields[p->assign[pos].fieldId]; - } - - const char *getUnit(inverter_t *p, uint8_t pos) { - return units[p->assign[pos].unitId]; - } - - uint64_t getSerial(inverter_t *p) { - return p->serial.u64; - } - - void updateSerial(inverter_t *p, uint64_t serial) { - p->serial.u64 = serial; - } - - uint8_t getChannel(inverter_t *p, uint8_t pos) { - return p->assign[pos].ch; - } - - uint8_t getCmdId(inverter_t *p, uint8_t pos) { - return p->assign[pos].cmdId; - } - - void addValue(inverter_t *p, uint8_t pos, uint8_t buf[]) { - uint8_t ptr = p->assign[pos].start; - uint8_t end = ptr + p->assign[pos].num; - uint16_t div = p->assign[pos].div; - - uint32_t val = 0; - do { - val <<= 8; - val |= buf[ptr]; - } while(++ptr != end); - - mRecord[p->id][pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div); - } - - RECORDTYPE getValue(inverter_t *p, uint8_t 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) { return mNumInv; } private: - void toRadioId(inverter_t *p) { - p->radioId.u64 = 0ULL; - p->radioId.b[4] = p->serial.b[0]; - p->radioId.b[3] = p->serial.b[1]; - p->radioId.b[2] = p->serial.b[2]; - p->radioId.b[1] = p->serial.b[3]; - p->radioId.b[0] = 0x01; - } - - void getAssignment(inverter_t *p) { - if(INV_TYPE_HM600 == p->type) { - p->listLen = (uint8_t)(HM1200_LIST_LEN); - p->assign = (byteAssign_t*)hm600assignment; - } - else if(INV_TYPE_HM1200 == p->type) { - p->listLen = (uint8_t)(HM1200_LIST_LEN); - p->assign = (byteAssign_t*)hm1200assignment; - } - else { - p->listLen = 0; - p->assign = NULL; - } - } - - inverter_t mInverter[MAX_INVERTER]; + INVERTERTYPE mInverter[MAX_INVERTER]; uint8_t mNumInv; - RECORDTYPE *mRecord[MAX_INVERTER]; }; #endif /*__HM_SYSTEM_H__*/ diff --git a/tools/esp8266/html/h/setup_html.h b/tools/esp8266/html/h/setup_html.h index f4e99a1a..95f1236f 100644 --- a/tools/esp8266/html/h/setup_html.h +++ b/tools/esp8266/html/h/setup_html.h @@ -1,4 +1,4 @@ #ifndef __SETUP_H__ #define __SETUP_H__ -const char setup_html[] PROGMEM = "Setup - {DEVICE}

Setup

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

WiFi

Device Host Name

Inverter

{INVERTERS}

General

Pinout (Wemos)

{PINOUT}

MQTT

 

Home

Update Firmware

AHOY - {VERSION}

"; +const char setup_html[] PROGMEM = "Setup - {DEVICE}

Setup

Enter the credentials to your prefered WiFi station. After rebooting the device tries to connect with this information.

WiFi

Device Host Name

ERASE SETTINGS (not WiFi)

Inverter

{INVERTERS}

General

Pinout (Wemos)

{PINOUT}

Radio (NRF24L01+)

MQTT

 

Home

Update Firmware

AHOY - {VERSION}

"; #endif /*__SETUP_H__*/ diff --git a/tools/esp8266/html/h/style_css.h b/tools/esp8266/html/h/style_css.h index cf8ac694..dc3639c4 100644 --- a/tools/esp8266/html/h/style_css.h +++ b/tools/esp8266/html/h/style_css.h @@ -1,4 +1,4 @@ #ifndef __STYLE_H__ #define __STYLE_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: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, 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;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;}"; +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: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;}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%;}#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, 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 {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;}"; #endif /*__STYLE_H__*/ diff --git a/tools/esp8266/html/setup.html b/tools/esp8266/html/setup.html index 0ab66fff..5103c412 100644 --- a/tools/esp8266/html/setup.html +++ b/tools/esp8266/html/setup.html @@ -22,6 +22,9 @@ + + ERASE SETTINGS (not WiFi) +

Inverter

{INVERTERS}

General

@@ -31,16 +34,22 @@

Pinout (Wemos)

{PINOUT} +

Radio (NRF24L01+)

+ + +

MQTT

+ + - +

 

diff --git a/tools/esp8266/html/style.css b/tools/esp8266/html/style.css index 5eb5f7dc..21d5340f 100644 --- a/tools/esp8266/html/style.css +++ b/tools/esp8266/html/style.css @@ -57,6 +57,15 @@ 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; } @@ -103,6 +112,7 @@ input.btn { color: #fff; border: 0px; float: right; + margin: 10px 0 30px; text-transform: uppercase; } diff --git a/tools/esp8266/main.cpp b/tools/esp8266/main.cpp index 61b2075c..25b68c71 100644 --- a/tools/esp8266/main.cpp +++ b/tools/esp8266/main.cpp @@ -43,8 +43,6 @@ void Main::setup(const char *ssid, const char *pwd, uint32_t timeout) { mWeb->onNotFound (std::bind(&Main::showNotFound, this)); startAp = getConfig(); - if(String(mDeviceName) != "") - WiFi.hostname(mDeviceName); if(false == startAp) startAp = setupStation(timeout); @@ -90,9 +88,8 @@ bool Main::getConfig(void) { memset(mStationPwd, 0, PWD_LEN); memset(mDeviceName, 0, DEVNAME_LEN); - // erase eeprom - uint8_t buf[ADDR_NEXT-ADDR_START_SETTINGS] = {0}; - mEep->write(ADDR_START_SETTINGS, buf, (ADDR_NEXT-ADDR_START_SETTINGS)); + // erase application settings except wifi settings + eraseSettings(); } return mApActive; @@ -127,6 +124,8 @@ bool Main::setupStation(uint32_t timeout) { WiFi.mode(WIFI_STA); WiFi.begin(mStationSsid, mStationPwd); + if(String(mDeviceName) != "") + WiFi.hostname(mDeviceName); delay(5000); Serial.println("wait for network"); diff --git a/tools/esp8266/main.h b/tools/esp8266/main.h index 9014b6fb..6e096789 100644 --- a/tools/esp8266/main.h +++ b/tools/esp8266/main.h @@ -53,6 +53,17 @@ class Main { return (crcCheck == crcRd); } + void eraseSettings(void) { + uint8_t buf[64] = {0}; + uint16_t addr = ADDR_START_SETTINGS, end; + do { + end = addr += 64; + if(end > (ADDR_SETTINGS_CRC + 2)) + end = (ADDR_SETTINGS_CRC + 2 - addr); + mEep->write(ADDR_START_SETTINGS, buf, (ADDR_NEXT-ADDR_START_SETTINGS)); + } while(addr < ADDR_START_SETTINGS); + } + char mStationSsid[SSID_LEN]; char mStationPwd[PWD_LEN]; bool mWifiSettingsValid; diff --git a/tools/esp8266/mqtt.h b/tools/esp8266/mqtt.h index b3247d14..4f9bc4b7 100644 --- a/tools/esp8266/mqtt.h +++ b/tools/esp8266/mqtt.h @@ -20,9 +20,9 @@ class mqtt { delete mClient; } - void setup(const char *broker, const char *topic, const char *user, const char *pwd) { + void setup(const char *broker, const char *topic, const char *user, const char *pwd, uint16_t port) { mAddressSet = true; - mClient->setServer(broker, 1883); + mClient->setServer(broker, port); snprintf(mUser, MQTT_USER_LEN, "%s", user); snprintf(mPwd, MQTT_PWD_LEN, "%s", pwd);