Browse Source

* complete payload processed (and crc checked)

* inverter type is defined by serial number
* serial debug can be switched live (using setup)
-> Note: only one inverter is supported for now!
pull/44/head^2
lumapu 3 years ago
parent
commit
724f0ab83a
  1. 161
      tools/esp8266/app.cpp
  2. 6
      tools/esp8266/app.h
  3. 3
      tools/esp8266/config.h
  4. 4
      tools/esp8266/crc.cpp
  5. 2
      tools/esp8266/crc.h
  6. 6
      tools/esp8266/defines.h
  7. 166
      tools/esp8266/hmDefines.h
  8. 43
      tools/esp8266/hmInverter.h
  9. 59
      tools/esp8266/hmRadio.h
  10. 16
      tools/esp8266/hmSystem.h

161
tools/esp8266/app.cpp

@ -25,6 +25,11 @@ app::app() : Main() {
memset(mPacketIds, 0, sizeof(uint32_t)*DBG_CMD_LIST_LEN);
memset(mPayload, 0, (MAX_PAYLOAD_ENTRIES * MAX_RF_PAYLOAD_SIZE));
memset(mPayloadLen, 0, MAX_PAYLOAD_ENTRIES);
mPayloadComplete = true;
mMaxPackId = 0;
mSys = new HmSystemType();
}
@ -50,21 +55,20 @@ void app::setup(uint32_t timeout) {
if(mSettingsValid) {
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);
DPRINTLN("add inverter: " + String(invName) + ", SN: " + String(invSerial, HEX) + ", type: " + String(invType));
mSys->addInverter(invName, invSerial);
DPRINTLN("add inverter: " + String(invName) + ", SN: " + String(invSerial, HEX));
}
}
mEep->read(ADDR_INV_INTERVAL, &mSendInterval);
if(mSendInterval < 5)
mSendInterval = 5;
mSendTicker = mSendInterval;
// pinout
mEep->read(ADDR_PINOUT, &mSys->Radio.pinCs);
@ -84,6 +88,7 @@ void app::setup(uint32_t timeout) {
mSerialDebug = (tmp == 0x01);
if(mSerialInterval < 1)
mSerialInterval = 1;
mSys->Radio.mSerialDebug = mSerialDebug;
// mqtt
@ -134,31 +139,39 @@ void app::loop(void) {
Main::loop();
if(checkTicker(&mRxTicker, 5)) {
mSys->Radio.switchRxCh();
bool rcvRdy = mSys->Radio.switchRxCh();
if(!mSys->BufCtrl.empty()) {
uint8_t len, rptCnt;
uint8_t len;
packet_t *p = mSys->BufCtrl.getBack();
//if(mSerialDebug)
// mSys->Radio.dumpBuf("RAW ", p->packet, MAX_RF_PAYLOAD_SIZE);
if(mSys->Radio.checkPaketCrc(p->packet, &len, &rptCnt, p->rxCh)) {
if(mSys->Radio.checkPaketCrc(p->packet, &len, p->rxCh)) {
// process buffer only on first occurrence
if((0 != len) && (0 == rptCnt)) {
if(mSerialDebug) {
DPRINT("Received " + String(len) + " bytes channel " + String(p->rxCh) + ": ");
mSys->Radio.dumpBuf(NULL, p->packet, len);
}
if(0 != len) {
uint8_t *packetId = &p->packet[9];
//DPRINTLN("CMD " + String(*packetId, HEX));
if(mSerialDebug)
mSys->Radio.dumpBuf("Payload ", p->packet, len);
if((*packetId & 0x7F) < 5) {
memcpy(mPayload[(*packetId & 0x7F) - 1], &p->packet[10], len-11);
mPayloadLen[(*packetId & 0x7F) - 1] = len-11;
}
if((*packetId & 0x80) == 0x80) {
if((*packetId & 0x7f) > mMaxPackId)
mMaxPackId = (*packetId & 0x7f);
}
Inverter<> *iv = mSys->findInverter(&p->packet[1]);
/*Inverter<> *iv = mSys->findInverter(&p->packet[1]);
if(NULL != iv) {
for(uint8_t i = 0; i < iv->listLen; i++) {
if(iv->assign[i].cmdId == *packetId)
iv->addValue(i, &p->packet[9]);
}
iv->doCalculations();
//memcpy(mPayload[(*packetId & 0x7F) - 1], &p->packet[9], MAX_RF_PAYLOAD_SIZE - 11);
}
}*/
if(*packetId == 0x01) mPacketIds[0]++;
else if(*packetId == 0x02) mPacketIds[1]++;
@ -170,8 +183,49 @@ void app::loop(void) {
else mPacketIds[7]++;
}
}
mSys->BufCtrl.popBack();
}
// TODO: support more than one inverter!
if(rcvRdy && (!mPayloadComplete)) {
Inverter<> *iv = mSys->getInverterByPos(0);
if(!buildPayload()) {
if(mMaxPackId != 0) {
for(uint8_t i = 0; i < (mMaxPackId-1); i ++) {
// retransmit
if(mPayloadLen[i] == 0) {
if(mSerialDebug)
DPRINTLN("Error while retrieving data: Frame " + String(i+1) + " missing: Request Retransmit");
mSys->Radio.sendCmdPacket(iv->radioId.u64, 0x15, (0x81+i), true);
}
}
}
mSys->Radio.switchRxCh(200);
}
else {
mPayloadComplete = true;
uint8_t payload[256] = {0};
uint8_t offs = 0;
for(uint8_t i = 0; i < (mMaxPackId); i ++) {
memcpy(&payload[offs], mPayload[i], (mPayloadLen[i]));
offs += (mPayloadLen[i]);
}
offs-=2;
if(mSerialDebug) {
DPRINT("Payload (" + String(offs) + "): ");
mSys->Radio.dumpBuf(NULL, payload, offs);
}
if(NULL != iv) {
for(uint8_t i = 0; i < iv->listLen; i++) {
iv->addValue(i, payload);
}
iv->doCalculations();
}
}
}
}
if(checkTicker(&mTicker, 1000)) {
@ -220,8 +274,18 @@ void app::loop(void) {
if(++mSendTicker >= mSendInterval) {
mSendTicker = 0;
if(!mSys->BufCtrl.empty())
DPRINTLN("recbuf not empty! #" + String(mSys->BufCtrl.getFill()));
memset(mPayloadLen, 0, MAX_PAYLOAD_ENTRIES);
mMaxPackId = 0;
if(mSerialDebug) {
if(!mPayloadComplete)
DPRINTLN("no Payload received!");
}
mPayloadComplete = false;
if(!mSys->BufCtrl.empty()) {
if(mSerialDebug)
DPRINTLN("recbuf not empty! #" + String(mSys->BufCtrl.getFill()));
}
Inverter<> *inv;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
inv = mSys->getInverterByPos(i);
@ -242,6 +306,30 @@ void app::handleIntr(void) {
}
//-----------------------------------------------------------------------------
bool app::buildPayload() {
//DPRINTLN("Payload");
uint16_t crc = 0xffff, crcRcv;
if(mMaxPackId > MAX_PAYLOAD_ENTRIES)
mMaxPackId = MAX_PAYLOAD_ENTRIES;
for(uint8_t i = 0; i < mMaxPackId; i ++) {
if(mPayloadLen[i] > 0) {
if(i == (mMaxPackId-1)) {
crc = crc16(mPayload[i], mPayloadLen[i] - 2, crc);
crcRcv = (mPayload[i][mPayloadLen[i] - 2] << 8)
| (mPayload[i][mPayloadLen[i] - 1]);
}
else
crc = crc16(mPayload[i], mPayloadLen[i], crc);
}
}
if(crc == crcRcv)
return true;
return false;
}
//-----------------------------------------------------------------------------
void app::showIndex(void) {
String html = FPSTR(index_html);
@ -276,7 +364,6 @@ void app::showSetup(void) {
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);
inv += "<p class=\"subdes\">Inverter "+ String(i) + "</p>";
inv += "<label for=\"inv" + String(i) + "Addr\">Address</label>";
@ -289,16 +376,6 @@ void app::showSetup(void) {
inv += "<input type=\"text\" class=\"text\" name=\"inv" + String(i) + "Name\" value=\"";
inv += String(invName);
inv += "\"/ maxlength=\"" + String(MAX_NAME_LENGTH) + "\">";
inv += "<label for=\"inv" + String(i) + "Type\">Type</label>";
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));
@ -371,7 +448,7 @@ void app::showSetup(void) {
html.replace("{MQTT_PORT}", "1883");
html.replace("{MQTT_USER}", "");
html.replace("{MQTT_PWD}", "");
html.replace("{MQTT_TOPIC}", "/inverter");
html.replace("{MQTT_TOPIC}", "inverter");
html.replace("{MQTT_INTVL}", "10");
html.replace("{SER_INTVL}", "10");
@ -440,10 +517,10 @@ void app::showLiveData(void) {
#ifdef LIVEDATA_VISUALIZED
uint8_t modNum, pos;
switch(iv->type) {
default: modNum = 1; break;
case INV_TYPE_HM600:
case INV_TYPE_HM800: modNum = 2; break;
case INV_TYPE_HM1200: modNum = 4; break;
default: modNum = 1; break;
case INV_TYPE_1CH:
case INV_TYPE_2CH: modNum = 2; break;
case INV_TYPE_4CH: modNum = 4; break;
}
modHtml += "<div class=\"iv\">";
@ -524,11 +601,6 @@ void app::saveValues(bool webSend = true) {
// 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, type);
}
interval = mWeb->arg("invInterval").toInt();
@ -578,15 +650,18 @@ void app::saveValues(bool webSend = true) {
mEep->write(ADDR_SER_INTERVAL, interval);
tmp = (mWeb->arg("serEn") == "on");
mEep->write(ADDR_SER_ENABLE, (uint8_t)((tmp) ? 0x01 : 0x00));
tmp = (mWeb->arg("serDbg") == "on");
mEep->write(ADDR_SER_DEBUG, (uint8_t)((tmp) ? 0x01 : 0x00));
mSerialDebug = (mWeb->arg("serDbg") == "on");
mEep->write(ADDR_SER_DEBUG, (uint8_t)((mSerialDebug) ? 0x01 : 0x00));
DPRINT("Info: Serial debug is ");
if(mSerialDebug) DPRINTLN("on"); else DPRINTLN("off");
mSys->Radio.mSerialDebug = mSerialDebug;
updateCrc();
if((mWeb->arg("reboot") == "on"))
showReboot();
else {
mShowRebootRequest = true;
mWeb->send(200, "text/html", "<!doctype html><html><head><title>Setup saved</title><meta http-equiv=\"refresh\" content=\"3; URL=/setup\"></head><body>"
mWeb->send(200, "text/html", "<!doctype html><html><head><title>Setup saved</title><meta http-equiv=\"refresh\" content=\"1; URL=/setup\"></head><body>"
"<p>saved</p></body></html>");
}
}

6
tools/esp8266/app.h

@ -40,6 +40,8 @@ class app : public Main {
}
private:
bool buildPayload();
void showIndex(void);
void showSetup(void);
void showSave(void);
@ -75,6 +77,10 @@ class app : public Main {
uint32_t mPacketIds[DBG_CMD_LIST_LEN+1];
uint32_t mRecCnt;
uint8_t mPayload[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE];
uint8_t mPayloadLen[MAX_PAYLOAD_ENTRIES];
bool mPayloadComplete;
uint8_t mMaxPackId;
// timer
uint32_t mTicker;

3
tools/esp8266/config.h

@ -38,6 +38,9 @@
// maximum buffer length of packet received / sent to RF24 module
#define MAX_RF_PAYLOAD_SIZE 32
// maximum total payload size
#define MAX_PAYLOAD_ENTRIES 4
// changes the style of "/setup" page, visualized = nicer
#define LIVEDATA_VISUALIZED

4
tools/esp8266/crc.cpp

@ -11,8 +11,8 @@ uint8_t crc8(uint8_t buf[], uint8_t len) {
return crc;
}
uint16_t crc16(uint8_t buf[], uint8_t len) {
uint16_t crc = 0xffff;
uint16_t crc16(uint8_t buf[], uint8_t len, uint16_t start) {
uint16_t crc = start;
uint8_t shift = 0;
for(uint8_t i = 0; i < len; i ++) {

2
tools/esp8266/crc.h

@ -10,7 +10,7 @@
#define CRC16_NRF24_POLYNOM 0x1021
uint8_t crc8(uint8_t buf[], uint8_t len);
uint16_t crc16(uint8_t buf[], uint8_t len);
uint16_t crc16(uint8_t buf[], uint8_t len, uint16_t start = 0xffff);
uint16_t crc16nrf24(uint8_t buf[], uint16_t lenBits, uint16_t startBit = 0, uint16_t crcIn = 0xffff);
#endif /*__CRC_H__*/

6
tools/esp8266/defines.h

@ -15,8 +15,8 @@
// VERSION
//-------------------------------------
#define VERSION_MAJOR 0
#define VERSION_MINOR 3
#define VERSION_PATCH 9
#define VERSION_MINOR 4
#define VERSION_PATCH 0
//-------------------------------------
@ -68,7 +68,7 @@ typedef struct {
#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_TYPE ADDR_INV_NAME + INV_NAME_LEN // obsolete
#define ADDR_INV_INTERVAL ADDR_INV_TYPE + INV_TYPE_LEN
#define ADDR_MQTT_ADDR ADDR_INV_INTERVAL + INV_INTERVAL_LEN

166
tools/esp8266/hmDefines.h

@ -25,26 +25,22 @@ const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "
// indices to calculation functions, defined in hmInverter.h
enum {CALC_YT_CH0 = 0, CALC_YD_CH0, CALC_UDC_CH};
enum {CMD_CALC = 0xffff};
// CH0 is default channel (freq, ac, temp)
enum {CH0 = 0, CH1, CH2, CH3, CH4};
// received command ids, special command CMDFF for calculations
enum {CMD01 = 0x01, CMD02, CMD03, CMD82 = 0x82, CMD83, CMD84, CMDFF=0xff};
enum {INV_TYPE_HM600 = 0, INV_TYPE_HM1200, INV_TYPE_HM400, INV_TYPE_HM800};
const char* const invTypes[] = {"HM600", "HM1200 / HM1500", "HM400", "HM800"};
#define NUM_INVERTER_TYPES 4
enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH};
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 ch; // channel 0 - 4
uint8_t start; // pos of first byte in buffer
uint8_t num; // number of bytes in buffer
uint16_t div; // divisor
uint16_t div; // divisor / calc command
} byteAssign_t;
@ -54,106 +50,88 @@ typedef struct {
* */
//-------------------------------------
// HM400 HM350?, HM300?
// HM300, HM350, HM400
//-------------------------------------
const byteAssign_t hm400assignment[] = {
{ FLD_UDC, UNIT_V, CH1, CMD01, 3, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, CMD01, 5, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, CMD01, 7, 2, 10 },
{ FLD_YT, UNIT_KWH, CH1, CMD01, 9, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, CMD01, 13, 2, 1 },
{ FLD_UAC, UNIT_V, CH0, CMD01, 15, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, CMD82, 1, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, CMD82, 3, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, CMD82, 7, 2, 100 },
{ FLD_T, UNIT_C, CH0, CMD82, 11, 2, 10 }
const byteAssign_t hm1chAssignment[] = {
{ FLD_UDC, UNIT_V, CH1, 2, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, 4, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, 6, 2, 10 },
{ FLD_YD, UNIT_WH, CH1, 12, 2, 1 },
{ FLD_YT, UNIT_KWH, CH1, 8, 4, 1000 },
{ FLD_UAC, UNIT_V, CH0, 14, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 22, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, 18, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 16, 2, 100 },
{ FLD_T, UNIT_C, CH0, 26, 2, 10 }
};
#define HM400_LIST_LEN (sizeof(hm400assignment) / sizeof(byteAssign_t))
#define HM1CH_LIST_LEN (sizeof(hm1chAssignment) / sizeof(byteAssign_t))
//-------------------------------------
// HM600, HM700
// HM600, HM700, HM800
//-------------------------------------
const byteAssign_t hm600assignment[] = {
{ FLD_UDC, UNIT_V, CH1, CMD01, 3, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, CMD01, 5, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, CMD01, 7, 2, 10 },
{ FLD_UDC, UNIT_V, CH2, CMD01, 9, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, CMD01, 11, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, CMD01, 13, 2, 10 },
{ FLD_YW, UNIT_WH, CH0, CMD02, 1, 2, 1 },
{ FLD_YT, UNIT_KWH, CH0, CMD02, 3, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, CMD02, 7, 2, 1 },
{ FLD_YD, UNIT_WH, CH2, CMD02, 9, 2, 1 },
{ FLD_UAC, UNIT_V, CH0, CMD02, 11, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, CMD02, 13, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, CMD02, 15, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, CMD83, 3, 2, 100 },
{ FLD_T, UNIT_C, CH0, CMD83, 7, 2, 10 }
};
#define HM600_LIST_LEN (sizeof(hm600assignment) / sizeof(byteAssign_t))
const byteAssign_t hm2chAssignment[] = {
{ FLD_UDC, UNIT_V, CH1, 2, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, 4, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, 6, 2, 10 },
{ FLD_YD, UNIT_WH, CH1, 22, 2, 1 },
{ FLD_YD, UNIT_KWH, CH1, 14, 4, 1000 },
{ FLD_UDC, UNIT_V, CH2, 8, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, 10, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, 12, 2, 10 },
{ FLD_YD, UNIT_WH, CH2, 18, 2, 1 },
{ FLD_YD, UNIT_KWH, CH2, 24, 4, 1000 },
{ FLD_UAC, UNIT_V, CH0, 26, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 34, 2, 10 },
{ FLD_PAC, UNIT_W, CH0, 30, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 28, 2, 100 },
{ FLD_T, UNIT_C, CH0, 38, 2, 10 }
//-------------------------------------
// HM800
//-------------------------------------
const byteAssign_t hm800assignment[] = {
{ FLD_UDC, UNIT_V, CH1, CMD01, 3, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, CMD01, 5, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, CMD01, 7, 2, 10 },
{ FLD_UDC, UNIT_V, CH2, CMD01, 9, 2, 10 },
{ FLD_IDC, UNIT_A, CH2, CMD01, 11, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, CMD01, 13, 2, 10 },
{ FLD_YW, UNIT_WH, CH0, CMD02, 1, 2, 1 },
{ FLD_YT, UNIT_KWH, CH0, CMD02, 3, 4, 1000 },
{ FLD_YD, UNIT_WH, CH1, CMD02, 7, 2, 1 },
{ FLD_YD, UNIT_WH, CH2, CMD02, 9, 2, 1 },
{ FLD_UAC, UNIT_V, CH0, CMD02, 11, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, CMD02, 13, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, CMD02, 15, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, CMD83, 3, 2, 100 },
{ FLD_T, UNIT_C, CH0, CMD83, 7, 2, 10 }
};
#define HM800_LIST_LEN (sizeof(hm800assignment) / sizeof(byteAssign_t))
#define HM2CH_LIST_LEN (sizeof(hm2chAssignment) / 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, CH3, 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 },
{ FLD_YD, UNIT_WH, CH0, CMDFF, CALC_YD_CH0, 0, 0 },
{ FLD_YT, UNIT_KWH, CH0, CMDFF, CALC_YT_CH0, 0, 0 },
{ FLD_UDC, UNIT_V, CH2, CMDFF, CALC_UDC_CH, CH1, 0 },
{ FLD_UDC, UNIT_V, CH4, CMDFF, CALC_UDC_CH, CH3, 0 }
const byteAssign_t hm4chAssignment[] = {
{ FLD_UDC, UNIT_V, CH1, 2, 2, 10 },
{ FLD_IDC, UNIT_A, CH1, 4, 2, 100 },
{ FLD_PDC, UNIT_W, CH1, 8, 2, 10 },
{ FLD_YD, UNIT_WH, CH1, 20, 2, 1 },
{ FLD_YT, UNIT_KWH, CH1, 12, 4, 1000 },
{ FLD_UDC, UNIT_V, CH2, CALC_UDC_CH, CH1, CMD_CALC },
{ FLD_IDC, UNIT_A, CH2, 6, 2, 100 },
{ FLD_PDC, UNIT_W, CH2, 10, 2, 10 },
{ FLD_YD, UNIT_WH, CH2, 22, 2, 1 },
{ FLD_YT, UNIT_KWH, CH2, 16, 4, 1000 },
{ FLD_UDC, UNIT_V, CH3, 24, 2, 10 },
{ FLD_IDC, UNIT_A, CH3, 26, 2, 100 },
{ FLD_PDC, UNIT_W, CH3, 30, 2, 10 },
{ FLD_YD, UNIT_WH, CH3, 42, 2, 1 },
{ FLD_YT, UNIT_KWH, CH3, 34, 4, 1000 },
{ FLD_UDC, UNIT_V, CH4, CALC_UDC_CH, CH3, CMD_CALC },
{ FLD_IDC, UNIT_A, CH4, 28, 2, 100 },
{ FLD_PDC, UNIT_W, CH4, 32, 2, 10 },
{ FLD_YD, UNIT_WH, CH4, 44, 2, 1 },
{ FLD_YT, UNIT_KWH, CH4, 38, 4, 1000 },
{ FLD_UAC, UNIT_V, CH0, 46, 2, 10 },
{ FLD_IAC, UNIT_A, CH0, 54, 2, 100 },
{ FLD_PAC, UNIT_W, CH0, 50, 2, 10 },
{ FLD_F, UNIT_HZ, CH0, 48, 2, 100 },
{ FLD_PCT, UNIT_PCT, CH0, 56, 2, 10 },
{ FLD_T, UNIT_C, CH0, 58, 2, 10 },
{ FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC },
{ FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }
};
#define HM1200_LIST_LEN (sizeof(hm1200assignment) / sizeof(byteAssign_t))
#define HM4CH_LIST_LEN (sizeof(hm4chAssignment) / sizeof(byteAssign_t))
#endif /*__HM_DEFINES_H__*/

43
tools/esp8266/hmInverter.h

@ -95,22 +95,20 @@ class Inverter {
return assign[pos].ch;
}
uint8_t getCmdId(uint8_t pos) {
return assign[pos].cmdId;
}
void addValue(uint8_t pos, uint8_t buf[]) {
uint8_t ptr = assign[pos].start;
uint8_t end = ptr + assign[pos].num;
uint16_t div = assign[pos].div;
uint32_t val = 0;
do {
val <<= 8;
val |= buf[ptr];
} while(++ptr != end);
if(CMD_CALC != div) {
uint32_t val = 0;
do {
val <<= 8;
val |= buf[ptr];
} while(++ptr != end);
record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
record[pos] = (RECORDTYPE)(val) / (RECORDTYPE)(div);
}
}
RECORDTYPE getValue(uint8_t pos) {
@ -119,7 +117,7 @@ class Inverter {
void doCalculations(void) {
for(uint8_t i = 0; i < listLen; i++) {
if(CMDFF == assign[i].cmdId) {
if(CMD_CALC == assign[i].div) {
record[i] = calcFunctions<RECORDTYPE>[assign[i].start].func(this, assign[i].num);
}
}
@ -136,24 +134,19 @@ class Inverter {
}
void getAssignment(void) {
if(INV_TYPE_HM400 == type) {
listLen = (uint8_t)(HM400_LIST_LEN);
assign = (byteAssign_t*)hm400assignment;
if(INV_TYPE_1CH == type) {
listLen = (uint8_t)(HM1CH_LIST_LEN);
assign = (byteAssign_t*)hm1chAssignment;
channels = 1;
}
else if(INV_TYPE_HM600 == type) {
listLen = (uint8_t)(HM600_LIST_LEN);
assign = (byteAssign_t*)hm600assignment;
channels = 2;
}
else if(INV_TYPE_HM800 == type) {
listLen = (uint8_t)(HM800_LIST_LEN);
assign = (byteAssign_t*)hm800assignment;
else if(INV_TYPE_2CH == type) {
listLen = (uint8_t)(HM2CH_LIST_LEN);
assign = (byteAssign_t*)hm2chAssignment;
channels = 2;
}
else if(INV_TYPE_HM1200 == type) {
listLen = (uint8_t)(HM1200_LIST_LEN);
assign = (byteAssign_t*)hm1200assignment;
else if(INV_TYPE_4CH == type) {
listLen = (uint8_t)(HM4CH_LIST_LEN);
assign = (byteAssign_t*)hm4chAssignment;
channels = 4;
}
else {

59
tools/esp8266/hmRadio.h

@ -58,14 +58,14 @@ class HmRadio {
mRxChIdx = 0;
mRxLoopCnt = RX_LOOP_CNT;
//calcDtuCrc();
pinCs = CS_PIN;
pinCe = CE_PIN;
pinIrq = IRQ_PIN;
AmplifierPower = 1;
mSendCnt = 0;
mSerialDebug = false;
}
~HmRadio() {}
@ -111,7 +111,7 @@ class HmRadio {
if(!mBufCtrl->full()) {
p = mBufCtrl->getFront();
memset(p->packet, 0xcc, MAX_RF_PAYLOAD_SIZE);
p->rxCh = mRxChIdx;
p->rxCh = mRxChLst[mRxChIdx];
len = mNrf24.getPayloadSize();
if(len > MAX_RF_PAYLOAD_SIZE)
len = MAX_RF_PAYLOAD_SIZE;
@ -156,19 +156,19 @@ class HmRadio {
sendPacket(invId, mTxBuf, 27, true);
}
void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t cmd, bool calcCrc = true) {
void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool calcCrc = true) {
memset(mTxBuf, 0, MAX_RF_PAYLOAD_SIZE);
mTxBuf[0] = mid; // message id
CP_U32_BigEndian(&mTxBuf[1], (invId >> 8));
CP_U32_BigEndian(&mTxBuf[5], (DTU_ID >> 8));
mTxBuf[9] = cmd;
mTxBuf[9] = pid;
if(calcCrc) {
mTxBuf[10] = crc8(mTxBuf, 10);
sendPacket(invId, mTxBuf, 11, false);
}
}
bool checkPaketCrc(uint8_t buf[], uint8_t *len, uint8_t *rptCnt, uint8_t rxCh) {
bool checkPaketCrc(uint8_t buf[], uint8_t *len, uint8_t rxCh) {
*len = (buf[0] >> 2);
if(*len > (MAX_RF_PAYLOAD_SIZE - 2))
*len = MAX_RF_PAYLOAD_SIZE - 2;
@ -179,17 +179,10 @@ class HmRadio {
uint8_t crc = crc8(buf, *len-1);
bool valid = (crc == buf[*len-1]);
if(valid) {
if(mLastCrc == crc)
*rptCnt = (++mRptCnt);
else {
mRptCnt = 0;
*rptCnt = 0;
mLastCrc = crc;
}
mRxStat[(buf[9] & 0x7F)-1]++;
mRxChStat[(buf[9] & 0x7F)-1][rxCh & 0x7]++;
}
//if(valid) {
//mRxStat[(buf[9] & 0x7F)-1]++;
//mRxChStat[(buf[9] & 0x7F)-1][rxCh & 0x7]++;
//}
/*else {
DPRINT("CRC wrong: ");
DHEX(crc);
@ -215,7 +208,8 @@ class HmRadio {
}
void dumpBuf(const char *info, uint8_t buf[], uint8_t len) {
DPRINT(String(info));
if(NULL != info)
DPRINT(String(info));
for(uint8_t i = 0; i < len; i++) {
DHEX(buf[i]);
DPRINT(" ");
@ -234,16 +228,22 @@ class HmRadio {
uint8_t AmplifierPower;
uint32_t mSendCnt;
bool mSerialDebug;
private:
void sendPacket(uint64_t invId, uint8_t buf[], uint8_t len, bool clear=false) {
//DPRINTLN("sent packet: #" + String(mSendCnt));
//dumpBuf("SEN ", buf, len);
if(mSerialDebug) {
DPRINT("Transmit " + String(len) + " | ");
dumpBuf(NULL, buf, len);
}
DISABLE_IRQ;
mNrf24.stopListening();
if(clear) {
uint8_t cnt = 4;
/*uint8_t cnt = 4;
for(uint8_t i = 0; i < 4; i ++) {
DPRINT(String(mRxStat[i]) + " (");
for(uint8_t j = 0; j < 4; j++) {
@ -258,7 +258,7 @@ class HmRadio {
else
DPRINTLN(" -> missing: " + String(cnt));
memset(mRxStat, 0, 4);
memset(mRxChStat, 0, 4*8);
memset(mRxChStat, 0, 4*8);*/
mRxLoopCnt = RX_LOOP_CNT;
}
@ -295,34 +295,19 @@ class HmRadio {
return mRxChLst[mRxChIdx];
}
/*void calcDtuCrc(void) {
uint64_t addr = DTU_RADIO_ID;
uint8_t tmp[5];
for(int8_t i = 4; i >= 0; i--) {
tmp[i] = addr;
addr >>= 8;
}
mDtuIdCrc = crc16nrf24(tmp, BIT_CNT(5));
}*/
uint8_t mTxCh;
uint8_t mTxChLst[1];
//uint8_t mTxChIdx;
uint8_t mRxChLst[4];
uint8_t mRxChIdx;
uint8_t mRxStat[4];
uint8_t mRxChStat[4][8];
//uint8_t mRxStat[4];
//uint8_t mRxChStat[4][8];
uint16_t mRxLoopCnt;
//uint16_t mDtuIdCrc;
uint16_t mLastCrc;
uint8_t mRptCnt;
RF24 mNrf24;
BUFFER *mBufCtrl;
uint8_t mTxBuf[MAX_RF_PAYLOAD_SIZE];
};
#endif /*__RADIO_H__*/

16
tools/esp8266/hmSystem.h

@ -27,7 +27,7 @@ class HmSystem {
Radio.setup(&BufCtrl);
}
INVERTERTYPE *addInverter(const char *name, uint64_t serial, uint8_t type) {
INVERTERTYPE *addInverter(const char *name, uint64_t serial) {
if(MAX_INVERTER <= mNumInv) {
DPRINT("max number of inverters reached!");
return NULL;
@ -35,7 +35,19 @@ class HmSystem {
INVERTERTYPE *p = &mInverter[mNumInv];
p->id = mNumInv;
p->serial.u64 = serial;
p->type = type;
DPRINT("SERIAL: " + String(p->serial.b[5], HEX));
DPRINTLN(" " + String(p->serial.b[4], HEX));
if(p->serial.b[5] == 0x11) {
switch(p->serial.b[4]) {
case 0x21: p->type = INV_TYPE_1CH; break;
case 0x41: p->type = INV_TYPE_2CH; break;
case 0x61: p->type = INV_TYPE_4CH; break;
default: DPRINTLN("unknown inverter type: 11" + String(p->serial.b[4], HEX)); break;
}
}
else
DPRINTLN("inverter type can't be detected!");
p->init();
uint8_t len = (uint8_t)strlen(name);
strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len);

Loading…
Cancel
Save