diff --git a/tools/esp8266/app.cpp b/tools/esp8266/app.cpp index 6e0d45fa..0b6db0a0 100644 --- a/tools/esp8266/app.cpp +++ b/tools/esp8266/app.cpp @@ -5,21 +5,16 @@ extern String setup_html; //----------------------------------------------------------------------------- app::app() : Main() { - uint8_t wrAddr[6]; - mRadio = new RF24(RF24_CE_PIN, RF24_CS_PIN); - - mRadio->begin(); - mRadio->setAutoAck(false); - mRadio->setRetries(0, 0); - mHoymiles = new hoymiles(); - mEep->read(ADDR_HOY_ADDR, mHoymiles->mAddrBytes, HOY_ADDR_LEN); - mHoymiles->serial2RadioId(); mBufCtrl = new CircularBuffer(mBuffer, PACKET_BUFFER_SIZE); mSendCnt = 0; mSendTicker = new Ticker(); + mFlagSend = false; + + memset(mCmds, 0, sizeof(uint32_t)); + memset(mChannelStat, 0, sizeof(uint32_t)); } @@ -33,13 +28,23 @@ 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("/", 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)); + + if(mSettingsValid) + mEep->read(ADDR_HOY_ADDR, mHoymiles->mAddrBytes, HOY_ADDR_LEN); + else + memset(mHoymiles->mAddrBytes, 0, 6); + mHoymiles->serial2RadioId(); initRadio(); - mSendTicker->attach_ms(1000, std::bind(&app::sendTicker, this)); + if(mSettingsValid) + mSendTicker->attach_ms(1000, std::bind(&app::sendTicker, this)); + else + Serial.println("Warn: your settings are not valid! check [IP]/setup"); } @@ -51,22 +56,53 @@ void app::loop(void) { uint8_t len, rptCnt; NRF24_packet_t *p = mBufCtrl->getBack(); - //mHoymiles->dumpBuf("RAW", p->packet, PACKET_BUFFER_SIZE); + //mHoymiles->dumpBuf("RAW ", p->packet, PACKET_BUFFER_SIZE); if(mHoymiles->checkCrc(p->packet, &len, &rptCnt)) { // process buffer only on first occurrence if((0 != len) && (0 == rptCnt)) { - mHoymiles->dumpBuf("Payload", p->packet, len); + Serial.println("CMD " + String(p->packet[11], HEX)); + mHoymiles->dumpBuf("Payload ", p->packet, len); // @TODO: do analysis here - } - } - else { - if(p->packetsLost != 0) { - Serial.println("Lost packets: " + String(p->packetsLost)); + if(p->packet[11] == 0x01) mCmds[0]++; + else if(p->packet[11] == 0x02) mCmds[1]++; + else if(p->packet[11] == 0x03) mCmds[2]++; + else if(p->packet[11] == 0x81) mCmds[3]++; + else if(p->packet[11] == 0x84) mCmds[4]++; + else mCmds[5]++; + + if(p->sendCh == 23) mChannelStat[0]++; + else if(p->sendCh == 40) mChannelStat[1]++; + else if(p->sendCh == 61) mChannelStat[2]++; + else mChannelStat[3]++; } } mBufCtrl->popBack(); } + + if(mFlagSend) { + mFlagSend = false; + + uint8_t size = 0; + if((mSendCnt % 6) == 0) + size = mHoymiles->getTimePacket(mSendBuf, mTimestamp); + else if((mSendCnt % 6) == 1) + size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x81); + else if((mSendCnt % 6) == 2) + size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x80); + else if((mSendCnt % 6) == 3) + size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x83); + else if((mSendCnt % 6) == 4) + size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x82); + else if((mSendCnt % 6) == 5) + size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x84); + + //Serial.println("sent packet: #" + String(mSendCnt)); + //dumpBuf(mSendBuf, size); + sendPacket(mSendBuf, size); + + mSendCnt++; + } } @@ -81,8 +117,7 @@ void app::handleIntr(void) { if(!mBufCtrl->full()) { p = mBufCtrl->getFront(); memset(p->packet, 0xcc, MAX_RF_PAYLOAD_SIZE); - p->timestamp = micros(); // Micros does not increase in interrupt, but it can be used. - p->packetsLost = lostCnt; + p->sendCh = mSendChannel; len = mRadio->getPayloadSize(); if(len > MAX_RF_PAYLOAD_SIZE) len = MAX_RF_PAYLOAD_SIZE; @@ -106,6 +141,12 @@ void app::handleIntr(void) { //----------------------------------------------------------------------------- void app::initRadio(void) { + mRadio = new RF24(RF24_CE_PIN, RF24_CS_PIN); + + mRadio->begin(); + mRadio->setAutoAck(false); + mRadio->setRetries(0, 0); + mRadio->setChannel(DEFAULT_RECV_CHANNEL); mRadio->setDataRate(RF24_250KBPS); mRadio->disableCRC(); @@ -123,20 +164,26 @@ void app::initRadio(void) { Serial.println("Radio Config:"); mRadio->printPrettyDetails(); + + mSendChannel = mHoymiles->getDefaultChannel(); } //----------------------------------------------------------------------------- void app::sendPacket(uint8_t buf[], uint8_t len) { DISABLE_IRQ; - mRadio->stopListening(); #ifdef CHANNEL_HOP - mRadio->setChannel(mHoymiles->getNxtChannel()); + if(mSendCnt % 6 == 0) + mSendChannel = mHoymiles->getNxtChannel(); + else + mSendChannel = mHoymiles->getLastChannel(); #else - mRadio->setChannel(mHoymiles->getDefaultChannel()); + mSendChannel = mHoymiles->getDefaultChannel(); #endif + mRadio->setChannel(mSendChannel); + //Serial.println("CH: " + String(mSendChannel)); mRadio->openWritingPipe(mHoymiles->mRadioId); mRadio->setCRCLength(RF24_CRC_16); @@ -147,7 +194,7 @@ void app::sendPacket(uint8_t buf[], uint8_t len) { mRadio->write(buf, len); // Try to avoid zero payload acks (has no effect) - mRadio->openWritingPipe(DUMMY_RADIO_ID); + mRadio->openWritingPipe(DUMMY_RADIO_ID); // TODO: why dummy radio id? mRadio->setAutoAck(false); mRadio->setRetries(0, 0); @@ -163,25 +210,7 @@ void app::sendPacket(uint8_t buf[], uint8_t len) { //----------------------------------------------------------------------------- void app::sendTicker(void) { - uint8_t size = 0; - if((mSendCnt % 6) == 0) - size = mHoymiles->getTimePacket(mSendBuf, mTimestamp); - else if((mSendCnt % 6) == 5) - size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x81); - else if((mSendCnt % 6) == 4) - size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x80); - else if((mSendCnt % 6) == 3) - size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x83); - else if((mSendCnt % 6) == 2) - size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x82); - else if((mSendCnt % 6) == 1) - size = mHoymiles->getCmdPacket(mSendBuf, 0x15, 0x84); - - Serial.println("sent packet: #" + String(mSendCnt)); - dumpBuf(mSendBuf, size); - sendPacket(mSendBuf, size); - - mSendCnt++; + mFlagSend = true; } @@ -220,6 +249,25 @@ 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"); + + 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"); + mWeb->send(200, "text/plain", content); +} + + //----------------------------------------------------------------------------- void app::saveValues(bool webSend = true) { Main::saveValues(false); // general configuration @@ -240,6 +288,7 @@ void app::saveValues(bool webSend = true) { mEep->write(ADDR_HOY_ADDR, mHoymiles->mAddrBytes, HOY_ADDR_LEN); + updateCrc(); if((mWeb->arg("reboot") == "on")) showReboot(); else { diff --git a/tools/esp8266/app.h b/tools/esp8266/app.h index 147693b8..01883643 100644 --- a/tools/esp8266/app.h +++ b/tools/esp8266/app.h @@ -29,6 +29,7 @@ class app : public Main { void showIndex(void); void showSetup(void); void showSave(void); + void showCmdStatistics(void); void saveValues(bool webSend); void dumpBuf(uint8_t buf[], uint8_t len); @@ -45,6 +46,11 @@ class app : public Main { Ticker *mSendTicker; uint32_t mSendCnt; uint8_t mSendBuf[MAX_RF_PAYLOAD_SIZE]; + bool mFlagSend; + uint8_t mSendChannel; + + uint32_t mCmds[6]; + uint32_t mChannelStat[4]; }; #endif /*__APP_H__*/ diff --git a/tools/esp8266/crc.cpp b/tools/esp8266/crc.cpp new file mode 100644 index 00000000..be2d8a57 --- /dev/null +++ b/tools/esp8266/crc.cpp @@ -0,0 +1,43 @@ +#include "crc.h" + +uint8_t crc8(uint8_t buf[], uint8_t len) { + uint8_t crc = CRC8_INIT; + for(uint8_t i = 0; i < len; i++) { + crc ^= buf[i]; + for(uint8_t b = 0; b < 8; b ++) { + crc = (crc << 1) ^ ((crc & 0x80) ? CRC8_POLY : 0x00); + } + } + return crc; +} + +uint16_t crc16(uint8_t buf[], uint8_t len) { + uint16_t crc = 0xffff; + uint8_t shift = 0; + + for(uint8_t i = 0; i < len; i ++) { + crc = crc ^ buf[i]; + for(uint8_t bit = 0; bit < 8; bit ++) { + shift = (crc & 0x0001); + crc = crc >> 1; + if(shift != 0) + crc = crc ^ 0xA001; + } + } + return crc; +} + +uint16_t crc16nrf24(uint8_t buf[], uint16_t lenBits, uint16_t startBit, uint16_t crcIn) { + uint16_t crc = crcIn; + uint8_t idx, val = buf[(startBit >> 3)]; + + for(uint16_t bit = startBit; bit < lenBits; bit ++) { + idx = bit & 0x07; + if(0 == idx) + val = buf[(bit >> 3)]; + crc ^= 0x8000 & (val << (8 + idx)); + crc = (crc & 0x8000) ? ((crc << 1) ^ CRC16_NRF24_POLYNOM) : (crc << 1); + } + + return crc; +} diff --git a/tools/esp8266/crc.h b/tools/esp8266/crc.h new file mode 100644 index 00000000..90baa548 --- /dev/null +++ b/tools/esp8266/crc.h @@ -0,0 +1,16 @@ +#ifndef __CRC_H__ +#define __CRC_H__ + +#include + +#define CRC8_INIT 0x00 +#define CRC8_POLY 0x01 + +#define CRC16_MODBUS_POLYNOM 0xA001 +#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 crc16nrf24(uint8_t buf[], uint16_t lenBits, uint16_t startBit = 0, uint16_t crcIn = 0xffff); + +#endif /*__CRC_H__*/ diff --git a/tools/esp8266/defines.h b/tools/esp8266/defines.h index 34614e8f..4939da5b 100644 --- a/tools/esp8266/defines.h +++ b/tools/esp8266/defines.h @@ -15,7 +15,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 1 -#define VERSION_PATCH 7 +#define VERSION_PATCH 9 //------------------------------------- @@ -24,14 +24,18 @@ #define SSID_LEN 32 #define PWD_LEN 64 #define DEVNAME_LEN 32 +#define CRC_LEN 2 #define HOY_ADDR_LEN 6 - -#define ADDR_SSID 0 // start address +#define ADDR_START 0 +#define ADDR_SSID ADDR_START #define ADDR_PWD ADDR_SSID + SSID_LEN #define ADDR_DEVNAME ADDR_PWD + PWD_LEN - #define ADDR_HOY_ADDR ADDR_DEVNAME + DEVNAME_LEN +#define ADDR_NEXT ADDR_HOY_ADDR + HOY_ADDR_LEN + +#define ADDR_SETTINGS_CRC 200 + #endif /*__DEFINES_H__*/ diff --git a/tools/esp8266/ahoy-esp.ino b/tools/esp8266/esp8266.ino similarity index 100% rename from tools/esp8266/ahoy-esp.ino rename to tools/esp8266/esp8266.ino diff --git a/tools/esp8266/hoymiles.h b/tools/esp8266/hoymiles.h index 26724ba7..66b80c3c 100644 --- a/tools/esp8266/hoymiles.h +++ b/tools/esp8266/hoymiles.h @@ -3,6 +3,7 @@ #include #include +#include "crc.h" #define CHANNEL_HOP // switch between channels or use static channel to send @@ -14,11 +15,6 @@ #define DUMMY_RADIO_ID ((uint64_t)0xDEADBEEF01ULL) #define PACKET_BUFFER_SIZE 30 -#define CRC8_INIT 0x00 -#define CRC8_POLY 0x01 - -#define CRC16_MODBUS_POLYNOM 0xA001 -#define CRC16_NRF24_POLYNOM 0x1021 //----------------------------------------------------------------------------- @@ -49,9 +45,8 @@ union uint64Bytes { }; typedef struct { - uint32_t timestamp; - uint8_t packetsLost; - uint8_t packet[MAX_RF_PAYLOAD_SIZE]; + uint8_t sendCh; + uint8_t packet[MAX_RF_PAYLOAD_SIZE]; } NRF24_packet_t; @@ -62,7 +57,6 @@ class hoymiles { serial2RadioId(); calcDtuIdCrc(); - mChannels = new uint8_t(4); mChannels[0] = 23; mChannels[1] = 40; mChannels[2] = 61; @@ -76,7 +70,10 @@ class hoymiles { ~hoymiles() {} uint8_t getDefaultChannel(void) { - return mChannels[1]; + return mChannels[2]; + } + uint8_t getLastChannel(void) { + return mChannels[mChanIdx]; } uint8_t getNxtChannel(void) { @@ -99,12 +96,7 @@ class hoymiles { } uint8_t getTimePacket(uint8_t buf[], uint32_t ts) { - memset(buf, 0, MAX_RF_PAYLOAD_SIZE); - - buf[0] = 0x15; - CP_U32_BigEndian(&buf[1], (mRadioId >> 8)); - CP_U32_BigEndian(&buf[5], (DTU_RADIO_ID >> 8)); - buf[9] = 0x00; + getCmdPacket(buf, 0x15, 0x80, false); buf[10] = 0x0b; // cid buf[11] = 0x00; CP_U32_LittleEndian(&buf[12], ts); @@ -118,12 +110,14 @@ class hoymiles { return 27; } - uint8_t getCmdPacket(uint8_t buf[], uint8_t mid, uint8_t cmd) { - buf[0] = mid; + uint8_t getCmdPacket(uint8_t buf[], uint8_t mid, uint8_t cmd, bool calcCrc = true) { + memset(buf, 0, MAX_RF_PAYLOAD_SIZE); + buf[0] = mid; // message id CP_U32_BigEndian(&buf[1], (mRadioId >> 8)); CP_U32_BigEndian(&buf[5], (DTU_RADIO_ID >> 8)); - buf[9] = cmd; - buf[10] = crc8(buf, 10); + buf[9] = cmd; + if(calcCrc) + buf[10] = crc8(buf, 10); return 11; } @@ -173,52 +167,8 @@ class hoymiles { mDtuIdCrc = crc16nrf24(dtuAddr, BIT_CNT(5)); } - uint8_t crc8(uint8_t buf[], uint8_t len) { - uint8_t crc = CRC8_INIT; - for(uint8_t i = 0; i < len; i++) { - crc ^= buf[i]; - for(uint8_t b = 0; b < 8; b ++) { - crc = (crc << 1) ^ ((crc & 0x80) ? CRC8_POLY : 0x00); - } - } - return crc; - } - - uint16_t crc16(uint8_t buf[], uint8_t len) { - uint16_t crc = 0xffff; - uint8_t lsb; - - for(uint8_t i = 0; i < len; i++) { - crc = crc ^ buf[i]; - for(int8_t b = 7; b >= 0; b--) { - lsb = (crc & 0x0001); - if(lsb == 0x01) - crc--; - crc = crc >> 1; - if(lsb == 0x01) - crc = crc ^ CRC16_MODBUS_POLYNOM; - } - } - - return crc; - } - - uint16_t crc16nrf24(uint8_t buf[], uint16_t lenBits, uint16_t startBit = 0, uint16_t crcIn = 0xffff) { - uint16_t crc = crcIn; - uint8_t idx, val = buf[(startBit >> 3)]; - - for(uint16_t bit = startBit; bit < lenBits; bit ++) { - idx = bit & 0x07; - if(0 == idx) - val = buf[(bit >> 3)]; - crc ^= 0x8000 & (val << (8 + idx)); - crc = (crc & 0x8000) ? ((crc << 1) ^ CRC16_NRF24_POLYNOM) : (crc << 1); - } - - return crc; - } - uint8_t *mChannels; + uint8_t mChannels[4]; uint8_t mChanIdx; uint16_t mDtuIdCrc; uint16_t mLastCrc; diff --git a/tools/esp8266/html/h/index_html.h b/tools/esp8266/html/h/index_html.h index 81ea0775..8c2921e0 100644 --- a/tools/esp8266/html/h/index_html.h +++ b/tools/esp8266/html/h/index_html.h @@ -1 +1 @@ -String index_html = "Index - {DEVICE}

AHOY - {DEVICE}

Update

Setup
Reboot

Uptime:

Time:

© 2022

AHOY :: {VERSION}

"; +String index_html = "Index - {DEVICE}

AHOY - {DEVICE}

Update

Setup
Reboot

Uptime:

Time:

Statistics:

© 2022

AHOY :: {VERSION}

"; diff --git a/tools/esp8266/html/index.html b/tools/esp8266/html/index.html index 479cc483..2cd0b1b6 100644 --- a/tools/esp8266/html/index.html +++ b/tools/esp8266/html/index.html @@ -7,6 +7,7 @@