From c56c785a1fdddfed93085f93449eed79c8c4679f Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 20 Feb 2023 22:10:05 +0100 Subject: [PATCH 01/92] basic implementation of HMS/HMT inverters --- src/CHANGES.md | 1 + src/app.cpp | 2 +- src/app.h | 8 + src/config/settings.h | 7 + src/hm/cmt2300a.h | 430 ++++++++++++++++++++++++++++++++++++++++++ src/hm/esp32_3wSpi.h | 138 ++++++++++++++ src/hm/hmPayload.h | 2 +- src/hm/hmRadio.h | 19 +- src/hm/hmsRadio.h | 191 +++++++++++++++++++ src/hm/miPayload.h | 2 +- src/main.cpp | 7 +- src/utils/helper.cpp | 9 + src/utils/helper.h | 3 +- 13 files changed, 800 insertions(+), 19 deletions(-) create mode 100644 src/hm/cmt2300a.h create mode 100644 src/hm/esp32_3wSpi.h create mode 100644 src/hm/hmsRadio.h diff --git a/src/CHANGES.md b/src/CHANGES.md index 447054fa..23ecaa33 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -7,6 +7,7 @@ * added part of mac address to MQTT client ID to seperate multiple ESPs in same network * added dictionary for MQTT to reduce heap-fragmentation * removed `last Alarm` from Live view, because it showed always the same alarm - will change in future +* #671, #650 ## 0.5.88 * MQTT Yield Day zero, next try to fix #671, thx @beegee3 diff --git a/src/app.cpp b/src/app.cpp index d32a5bfa..f609f279 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -115,7 +115,7 @@ void app::loopStandard(void) { DBGPRINT(F("B Ch")); DBGPRINT(String(p->ch)); DBGPRINT(F(" | ")); - mSys.Radio.dumpBuf(p->packet, p->len); + ah::dumpBuf(p->packet, p->len); } mStat.frmCnt++; diff --git a/src/app.h b/src/app.h index 68281492..e65f21b4 100644 --- a/src/app.h +++ b/src/app.h @@ -66,6 +66,10 @@ class app : public IApp, public ah::Scheduler { mSys.Radio.handleIntr(); } + void handleHmsIntr(void) { + //mSys.Radio.handleHmsIntr(); + } + uint32_t getUptime() { return Scheduler::getUptime(); } @@ -160,6 +164,10 @@ class app : public IApp, public ah::Scheduler { return mConfig->nrf.pinIrq; } + uint8_t getHmsIrqPin(void) { + return mConfig->cmt.pinIrq; + } + String getTimeStr(uint32_t offset = 0) { char str[10]; if(0 == mTimestamp) diff --git a/src/config/settings.h b/src/config/settings.h index 527dea72..e42201a5 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -68,6 +68,12 @@ typedef struct { uint8_t amplifierPower; } cfgNrf24_t; +typedef struct { + uint8_t pinCsb; + uint8_t pinFcsb; + uint8_t pinIrq; +} cfgCmt_t; + typedef struct { char addr[NTP_ADDR_LEN]; uint16_t port; @@ -138,6 +144,7 @@ typedef struct { typedef struct { cfgSys_t sys; cfgNrf24_t nrf; + cfgCmt_t cmt; cfgNtp_t ntp; cfgSun_t sun; cfgSerial_t serial; diff --git a/src/hm/cmt2300a.h b/src/hm/cmt2300a.h new file mode 100644 index 00000000..0c6c1641 --- /dev/null +++ b/src/hm/cmt2300a.h @@ -0,0 +1,430 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __CMT2300A_H__ +#define __CMT2300A_H__ + +#include "esp32_3wSpi.h" + +// detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf + +#define CMT2300A_CUS_MODE_CTL 0x60 // [7] go_switch + // [6] go_tx + // [5] go_tfs + // [4] go_sleep + // [3] go_rx + // [2] go_rfs + // [1] go_stby + // [0] n/a + +#define CMT2300A_CUS_MODE_STA 0x61 // [3:0] 0x00 IDLE + // 0x01 SLEEP + // 0x02 STBY + // 0x03 RFS + // 0x04 TFS + // 0x05 RX + // 0x06 TX + // 0x08 UNLOCKED/LOW_VDD + // 0x09 CAL +#define CMT2300A_CUS_EN_CTL 0x62 +#define CMT2300A_CUS_FREQ_CHNL 0x63 + +#define CMT2300A_CUS_IO_SEL 0x65 // [5:4] GPIO3 + // 0x00 CLKO + // 0x01 DOUT / DIN + // 0x02 INT2 + // 0x03 DCLK + // [3:2] GPIO2 + // 0x00 INT1 + // 0x01 INT2 + // 0x02 DOUT / DIN + // 0x03 DCLK + // [1:0] GPIO1 + // 0x00 DOUT / DIN + // 0x01 INT1 + // 0x02 INT2 + // 0x03 DCLK + +#define CMT2300A_CUS_INT1_CTL 0x66 // [4:0] INT1_SEL + // 0x00 RX active + // 0x01 TX active + // 0x02 RSSI VLD + // 0x03 Pream OK + // 0x04 SYNC OK + // 0x05 NODE OK + // 0x06 CRC OK + // 0x07 PKT OK + // 0x08 SL TMO + // 0x09 RX TMO + // 0x0A TX DONE + // 0x0B RX FIFO NMTY + // 0x0C RX FIFO TH + // 0x0D RX FIFO FULL + // 0x0E RX FIFO WBYTE + // 0x0F RX FIFO OVF + // 0x10 TX FIFO NMTY + // 0x11 TX FIFO TH + // 0x12 TX FIFO FULL + // 0x13 STATE IS STBY + // 0x14 STATE IS FS + // 0x15 STATE IS RX + // 0x16 STATE IS TX + // 0x17 LED + // 0x18 TRX ACTIVE + // 0x19 PKT DONE + +#define CMT2300A_CUS_INT2_CTL 0x67 // [4:0] INT2_SEL + +#define CMT2300A_CUS_INT_EN 0x68 // [7] SL TMO EN + // [6] RX TMO EN + // [5] TX DONE EN + // [4] PREAM OK EN + // [3] SYNC_OK EN + // [2] NODE OK EN + // [1] CRC OK EN + // [0] PKT DONE EN + +#define CMT2300A_CUS_FIFO_CTL 0x69 // [7] TX DIN EN + // [6:5] TX DIN SEL + // 0x00 SEL GPIO1 + // 0x01 SEL GPIO2 + // 0x02 SEL GPIO3 + // [4] FIFO AUTO CLR DIS + // [3] FIFO TX RD EN + // [2] FIFO RX TX SEL + // [1] FIFO MERGE EN + // [0] SPI FIFO RD WR SEL + +#define CMT2300A_CUS_INT_CLR1 0x6A // clear interrupts Bank1 +#define CMT2300A_CUS_INT_CLR2 0x6B // clear interrupts Bank2 +#define CMT2300A_CUS_FIFO_CLR 0x6C + +#define CMT2300A_CUS_INT_FLAG 0x6D // [7] LBD FLG + // [6] COL ERR FLG + // [5] PKT ERR FLG + // [4] PREAM OK FLG + // [3] SYNC OK FLG + // [2] NODE OK FLG + // [1] CRC OK FLG + // [0] PKT OK FLG + +#define CMT2300A_CUS_RSSI_DBM 0x70 + +#define CMT2300A_GO_SWITCH 0x80 +#define CMT2300A_GO_TX 0x40 +#define CMT2300A_GO_TFS 0x20 +#define CMT2300A_GO_SLEEP 0x10 +#define CMT2300A_GO_RX 0x08 +#define CMT2300A_GO_RFS 0x04 +#define CMT2300A_GO_STBY 0x02 +#define CMT2300A_GO_EEPROM 0x01 + +#define CMT2300A_STA_IDLE 0x00 +#define CMT2300A_STA_SLEEP 0x01 +#define CMT2300A_STA_STBY 0x02 +#define CMT2300A_STA_RFS 0x03 +#define CMT2300A_STA_TFS 0x04 +#define CMT2300A_STA_RX 0x05 +#define CMT2300A_STA_TX 0x06 +#define CMT2300A_STA_EEPROM 0x07 +#define CMT2300A_STA_ERROR 0x08 +#define CMT2300A_STA_CAL 0x09 + +#define CMT2300A_INT_SEL_TX_DONE 0x0A + +#define CMT2300A_MASK_TX_DONE_FLG 0x08 +#define CMT2300A_MASK_PKT_OK_FLG 0x01 + +// default CMT paramters +static uint8_t cmtConfig[0x60] PROGMEM { + // 0x00 - 0x0f + 0x00, 0x66, 0xEC, 0x1D, 0x70, 0x80, 0x14, 0x08, + 0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, + // 0x10 - 0x1f + 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, + 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, + // 0x20 - 0x2f + 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, + 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + // 0x30 - 0x3f + 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, + // 0x40 - 0x4f + 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, + // 0x50 - 0x5f + 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, + 0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F +}; + +enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_ERR_REG_VAL}; + +template +class Cmt2300a { + typedef SPI SpiType; + public: + Cmt2300a() {} + + void setup() { + mSpi.setup(); + mTxPending = false; + } + + // call as often as possible + void loop() { + if(mTxPending) { + if(CMT2300A_MASK_TX_DONE_FLG != spi3w.readReg(CMT2300A_CUS_INT_CLR1)) { + if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + mTxPending = false; + } + } + } + + inline void swichChannel(bool reset = true, uint8_t start = 0x00, uint8_t end = 0x22) { + if(reset) + mRxTxCh = start; + else if(++mRxTxCh > end) + mRxTxCh = start; + // 0: 868.00MHz + // 1: 868.23MHz + // 2: 868.46MHz + // 3: 868.72MHz + // 4: 868.97MHz + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh); + } + + uint8_t checkRx(uint8_t buf[], uint8_t len, int8_t *rssi) { + if(mTxPending) + return CMT_ERR_TX_PENDING; + + mSpi.readReg(CMT2300A_CUS_INT1_CTL); + mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); + + uint8_t tmp = mSpi.readReg(CMT2300A_CUS_INT_CLR1); + if(0x08 == tmp) // first time after TX this reg is 0x08 + mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x04); + else + mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); + + if(0x10 == tmp) + mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x10); + else + mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); + + mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? -> if 0x02 last was read + // 0x07 last was write + mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02); + + mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02); + mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE + + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); // 863.0 MHz + + if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) + return CMT_ERR_SWITCH_STATE; + + uint8_t state = 0x00; + uint16_t timeout = 5000; + for(uint8_t i = 0; i < 52; i++) { + state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); + if(0x00 != state) + break; + } + + if((state & 0x10) == 0x10) { + while(0 == digitalRead(INTR_PIN)) { + usleep(10); + if(0 == --timeout) + break; + } + if(0 != timeout) { + uint16_t timeout2 = 5000; + while(0x18 != (state & 0x18)) { + state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); + if(0 == timeout2--) + break; + } + } + } + + if(0 != digitalRead(INTR_PIN)) { + uint32_t loops = 0; + while((state & 0x1b) != 0x1b) { + state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); + + if((state & 0x20) == 0x20) + return CMT_ERR_REG_VAL; + else if((state & 0x40) == 0x40) + return CMT_ERR_REG_VAL; + if(++loops > 5000) + break; + } + } + + // receive ok (pream, sync, node, crc) + if((state & 0x1b) == 0x1b) { + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return CMT_ERR_SWITCH_STATE; + + mSpi.readFifo(buf, len); + *rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128; + + if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) + return CMT_ERR_SWITCH_STATE; + } + + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return CMT_ERR_SWITCH_STATE; + + return CMT_SUCCESS; + } + + bool tx(uint8_t buf[], uint8_t len) { + if(mTxPending) + return CMT_ERR_TX_PENDING; + + spi3w.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); + + if(0x00 == spi3w.readReg(CMT2300A_CUS_INT_FLAG)) { + // no data received + spi3w.readReg(CMT2300A_CUS_INT_CLR1); + spi3w.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); + spi3w.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); + + //spi3w.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? + spi3w.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); + spi3w.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); + + spi3w.writeReg(0x45, 0x01); + spi3w.writeReg(0x46, len); // payload length + + spi3w.writeFifo(buf, len); + + // send only on base frequency: here 863.0 MHz + spi3w.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); + + if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) + return CMT_ERR_SWITCH_STATE; + + // wait for tx done + mTxPending = CMT_SUCCESS; + } + else + return CMT_ERR_RX_IN_FIFO; + + return CMT_SUCCESS; + } + + // initialize CMT2300A, returns true on success + bool void reset(void) { + mSpi.writeReg(0x7f, 0xff); // soft reset + delay(30); + + if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return false; + + if(0xAA != mSpi.readReg(0x48)) + mSpi.writeReg(0x48, 0xAA); + //mSpi.readReg(0x48); + mSpi.writeReg(0x4c, 0x00); + + if(0x52 != mSpi.readReg(CMT2300A_CUS_MODE_STA)) + mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52); + if(0x20 != mSpi.readReg(0x62)) + mSpi.writeReg(0x62, 0x20); + //mSpi.readReg(0x0D); + mSpi.writeReg(0x0F, 0x00); + + for(uint8_t i = 0; i < 0x60; i++) { + mSpi.writeReg(i, cmtConfig[i]); + } + + if(0x02 != mSpi.readReg(0x09)) + mSpi.writeReg(0x09, 0x02); + + mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 + + // interrupt 1 control selection to TX DONE + if(CMT2300A_INT_SEL_TX_DONE != mSpi.readReg(CMT2300A_CUS_INT1_CTL)) + mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); + + // select interrupt 2 + if(0x07 != mSpi.readReg(CMT2300A_CUS_INT2_CTL)) + mSpi.writeReg(CMT2300A_CUS_INT2_CTL, 0x07); + + // interrupt enable (TX_DONE, PREAM_OK, SYNC_OK, CRC_OK, PKT_DONE) + mSpi.writeReg(CMT2300A_CUS_INT_EN, 0x3B); + + mSpi.writeReg(0x41, 0x48); + mSpi.writeReg(0x42, 0x5A); + mSpi.writeReg(0x43, 0x48); + mSpi.writeReg(0x44, 0x4D); + mSpi.writeReg(0x64, 0x64); + + if(0x00 == mSpi.readReg(CMT2300A_CUS_FIFO_CTL)) + mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02); // FIFO_MERGE_EN + + if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) + return false; + + delayMicroseconds(95); + + // base frequency 863MHz, with value of CMT2300A_CUS_FREQ_CHNL + // the frequency can be increase in a step size of ~0.24Hz + mSpi.writeReg(0x18, 0x42); + mSpi.writeReg(0x19, 0x6D); + mSpi.writeReg(0x1A, 0x80); + mSpi.writeReg(0x1B, 0x86); + mSpi.writeReg(0x1C, 0x42); + mSpi.writeReg(0x1D, 0x62); + mSpi.writeReg(0x1E, 0x27); + mSpi.writeReg(0x1F, 0x16); + + mSpi.writeReg(0x22, 0x20); + mSpi.writeReg(0x23, 0x20); + mSpi.writeReg(0x24, 0xD2); + mSpi.writeReg(0x25, 0x35); + mSpi.writeReg(0x26, 0x0C); + mSpi.writeReg(0x27, 0x0A); + mSpi.writeReg(0x28, 0x9F); + mSpi.writeReg(0x29, 0x4B); + mSpi.writeReg(0x27, 0x0A); + + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return false; + + mSpi.writeReg(0x03, 0x1D); + mSpi.writeReg(0x5C, 0x8A); + mSpi.writeReg(0x5D, 0x18); + + if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) + return false; + + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return false; + + return true; + } + + private: + // CMT state machine, wait for next state, true on success + bool cmtSwitchStatus(uint8_t cmd, uint8_t waitFor, uint16_t cycles = 40) { + mSpi.writeReg(CMT2300A_CUS_MODE_CTL, cmd); + while(cycles--) { + yield(); + delayMicroseconds(10); + if(waitFor == (getChipStatus() & waitFor)) + return true; + } + //Serial.println("status wait for: " + String(waitFor, HEX) + " read: " + String(getChipStatus(), HEX)); + return false; + } + + SpiType mSpi; + bool mTxPending; + uint8_t mRxTxCh; +}; + +#endif /*__CMT2300A_H__*/ diff --git a/src/hm/esp32_3wSpi.h b/src/hm/esp32_3wSpi.h new file mode 100644 index 00000000..41e1bc03 --- /dev/null +++ b/src/hm/esp32_3wSpi.h @@ -0,0 +1,138 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __ESP32_3WSPI_H__ +#define __ESP32_3WSPI_H__ + +#include "driver/spi_master.h" +#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal +#include "Arduino.h" + +#if defined(ESP32) + #define CLK_PIN 18 + #define MOSI_PIN 23 + #define MISO_PIN -1 +#endif + +#define SPI_CLK 1 * 1000 * 1000 // 1MHz + +template +class esp32_3wSpi { + public: + esp32_3wSpi() {} + void setup() { + spi_bus_config_t buscfg = { + .mosi_io_num = MOSI_PIN, + .miso_io_num = MISO_PIN, + .sclk_io_num = CLK_PIN, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 32, + }; + spi_device_interface_config_t devcfg = { + .command_bits = 0, + .address_bits = 0, + .dummy_bits = 0, + .mode = 0, // SPI mode 0 + .clock_speed_hz = SPI_CLK, // 1 MHz + .spics_io_num = CS_PIN, + .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, + .queue_size = 1, + .pre_cb = NULL, + .post_cb = NULL, + }; + + ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, 0)); + ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi_reg)); + + // FiFo + spi_device_interface_config_t devcfg2 = { + .command_bits = 0, + .address_bits = 0, + .dummy_bits = 0, + .mode = 0, // SPI mode 0 + .cs_ena_pretrans = 2, + .cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us + .clock_speed_hz = SPI_CLK, // 1 MHz + .spics_io_num = FCS_PIN, + .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, + .queue_size = 1, + .pre_cb = NULL, + .post_cb = NULL, + }; + ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg2, &spi_fifo)); + + esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI2_HOST].spid_out, true, false); + delay(100); + + pinMode(INTR_PIN, INPUT); + } + + void writeReg(uint8_t addr, uint8_t reg) { + uint8_t tx_data[2]; + tx_data[0] = ~addr; + tx_data[1] = ~reg; + spi_transaction_t t = { + .length = 2 * 8, + .tx_buffer = &tx_data, + .rx_buffer = NULL + }; + ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t)); + delayMicroseconds(100); + } + + uint8_t readReg(uint8_t addr) { + uint8_t tx_data, rx_data; + tx_data = ~(addr | 0x80); // negation and MSB high (read command) + spi_transaction_t t = { + .length = 8, + .rxlength = 8, + .tx_buffer = &tx_data, + .rx_buffer = &rx_data + }; + ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t)); + delayMicroseconds(100); + return rx_data; + } + + void writeFifo(uint8_t buf[], uint8_t len) { + uint8_t tx_data; + + spi_transaction_t t = { + .flags = SPI_TRANS_MODE_OCT, + .length = 8, + .tx_buffer = &tx_data, // reference to write data + .rx_buffer = NULL + }; + + for(uint8_t i = 0; i < len; i++) { + tx_data = ~buf[i]; // negate buffer contents + ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); + delayMicroseconds(4); // > 4 us + } + } + + void readFifo(uint8_t buf[], uint8_t len) { + uint8_t rx_data; + + spi_transaction_t t = { + .length = 8, + .rxlength = 8, + .tx_buffer = NULL, + .rx_buffer = &rx_data + }; + + for(uint8_t i = 0; i < len; i++) { + ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); + delayMicroseconds(4); // > 4 us + buf[i] = rx_data; + } + } + + private: + spi_device_handle_t spi_reg, spi_fifo; +}; + +#endif /*__ESP32_3WSPI_H__*/ diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 7a05bee3..acfcbd0b 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -307,7 +307,7 @@ class HmPayload { DPRINT(DBG_INFO, F("Payload (")); DBGPRINT(String(payloadLen)); DBGPRINT(F("): ")); - mSys->Radio.dumpBuf(payload, payloadLen); + ah::dumpBuf(payload, payloadLen); } if (NULL == rec) { diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index f0236362..47d81166 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -188,7 +188,7 @@ class HmRadio { mTxBuf[cnt++] = ((data[1] ) >> 8) & 0xff; // setting for persistens handlings mTxBuf[cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling } - sendPacket(invId, cnt, isRetransmit, true); + sendPacket(invId, cnt, isRetransmit); } void prepareDevInformCmd(uint64_t invId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. @@ -201,21 +201,12 @@ class HmRadio { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; } - sendPacket(invId, 24, isRetransmit, true); + sendPacket(invId, 24, isRetransmit); } void sendCmdPacket(uint64_t invId, uint8_t mid, uint8_t pid, bool isRetransmit) { initPacket(invId, mid, pid); - sendPacket(invId, 10, isRetransmit, false); - } - - void dumpBuf(uint8_t buf[], uint8_t len) { - //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:dumpBuf")); - for(uint8_t i = 0; i < len; i++) { - DHEX(buf[i]); - DBGPRINT(" "); - } - DBGPRINTLN(""); + sendPacket(invId, 10, isRetransmit); } uint8_t getDataRate(void) { @@ -279,7 +270,7 @@ class HmRadio { mTxBuf[9] = pid; } - void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit, bool clear=false) { + void sendPacket(uint64_t invId, uint8_t len, bool isRetransmit) { //DPRINTLN(DBG_VERBOSE, F("hmRadio.h:sendPacket")); //DPRINTLN(DBG_VERBOSE, "sent packet: #" + String(mSendCnt)); @@ -300,7 +291,7 @@ class HmRadio { DBGPRINT("B Ch"); DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(F(" | ")); - dumpBuf(mTxBuf, len); + ah::dumpBuf(mTxBuf, len); } mNrf24.stopListening(); diff --git a/src/hm/hmsRadio.h b/src/hm/hmsRadio.h new file mode 100644 index 00000000..afe61902 --- /dev/null +++ b/src/hm/hmsRadio.h @@ -0,0 +1,191 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __HMS_RADIO_H__ +#define __HMS_RADIO_H__ + +#include "../utils/dbg.h" +#include "cmt2300a.h" + +typedef struct { + int8_t rssi; + uint8_t data[28]; +} hmsPacket_t; + +#define U32_B3(val) ((uint8_t)((val >> 24) & 0xff)) +#define U32_B2(val) ((uint8_t)((val >> 16) & 0xff)) +#define U32_B1(val) ((uint8_t)((val >> 8) & 0xff)) +#define U32_B0(val) ((uint8_t)((val ) & 0xff)) + +template +class HmsRadio { + typedef SPI SpiType; + typedef Cmt2300a CmtType; + public: + HmsRadio() { + mDtuSn = DTU_SN; + } + + void setup(bool genDtuSn = true) { + if(genDtuSn) + generateDtuSn(); + if(!mCmt.resetCMT()) + DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); + + mSendCnt = 0; + mRetransmits = 0 + mSerialDebug = false; + mIvIdChannelSet = NULL; + mIrqRcvd = false; + } + + void loop() { + mCmt.loop(); + if(!mIrqRcvd) + return; + mIrqRcvd = false; + getRx(); + } + + void tickSecond() { + if(NULL != mIvIdChannelSet) + prepareSwitchFreqCmd(mIvIdChannelSet); + } + + void handeIntr(void) { + mIrqRcvd = true; + } + + void enableDebug() { + mSerialDebug = true; + } + + void setIvBackChannel(const uint32_t *ivId) { + mIvIdChannelSet = ivId; + prepareSwitchFreqCmd(); + + } + + void prepareDevInformCmd(const uint32_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. + initPacket(ivId, reqfld, ALL_FRAMES); + mTxBuf[10] = cmd; + mTxBuf[12] = U32_B3(ts); + mTxBuf[13] = U32_B2(ts); + mTxBuf[14] = U32_B1(ts); + mTxBuf[15] = U32_B0(ts); + /*if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) { + mTxBuf[18] = (alarmMesId >> 8) & 0xff; + mTxBuf[19] = (alarmMesId ) & 0xff; + }*/ + mCmt.swichChannel(true); + sendPacket(24, isRetransmit); + } + + inline void prepareSwitchChannelCmd(const uint32_t *ivId, uint8_t freqSel = 0x0c) { + /** freqSel: + * 0x0c: 863.00 MHz + * 0x0d: 863.24 MHz + * 0x0e: 863.48 MHz + * 0x0f: 863.72 MHz + * 0x10: 863.96 MHz + * */ + initPacket(ivId, 0x56, 0x02); + mTxBuf[10] = 0x15; + mTxBuf[11] = 0x21; + mTxBuf[12] = freqSel; + mTxBuf[13] = 0x14; + mCmt.swichChannel(); + sendPacket(14, false); + } + + void sendPacket(uint8_t len, bool isRetransmit) { + if (len > 14) { + uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); + mTxBuf[len++] = (crc >> 8) & 0xff; + mTxBuf[len++] = (crc ) & 0xff; + } + mTxBuf[len] = ah::crc8(mTxBuf, len); + len++; + + if(mSerialDebug) { + DPRINT(DBG_INFO, F("TX ")); + DBGPRINT(String(len)); + DBGPRINT("B Ch"); + DBGPRINT(String(mRfChLst[mTxChIdx])); + DBGPRINT(F(" | ")); + ah::dumpBuf(mTxBuf, len); + } + + uint8_t status = mCmt.tx(mTxBuf, len); + if(CMT_SUCCESS != status) { + DPRINT(DBG_WARN, F("CMT TX failed, code: ")); + DBGPRINTLN(String(status)); + } + + if(isRetransmit) + mRetransmits++; + else + mSendCnt++; + } + + uint32_t mSendCnt; + uint32_t mRetransmits; + std::queue mBufCtrl; + + private: + void initPacket(const uint32_t *ivId, uint8_t mid, uint8_t pid) { + mTxBuf[0] = mid; + mTxBuf[1] = U32_B3(*ivId); + mTxBuf[2] = U32_B2(*ivId); + mTxBuf[3] = U32_B1(*ivId); + mTxBuf[4] = U32_B0(*ivId); + mTxBuf[5] = U32_B3(mDtuSn); + mTxBuf[6] = U32_B2(mDtuSn); + mTxBuf[7] = U32_B1(mDtuSn); + mTxBuf[8] = U32_B0(mDtuSn); + mTxBuf[9] = pid; + memset(&mTxBuf[10], 0x00, 17); + } + + inline void generateDtuSn(void) { + uint32_t chipID = 0; + #ifdef ESP32 + uint64_t MAC = ESP.getEfuseMac(); + chipID = ((MAC >> 8) & 0xFF0000) | ((MAC >> 24) & 0xFF00) | ((MAC >> 40) & 0xFF); + #endif + dtuSn = 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal + for(int i = 0; i < 7; i++) { + dtuSn |= (chipID % 10) << (i * 4); + chipID /= 10; + } + } + + inline void getRx(void) { + hmsPacket_t p; + uint8_t status = mCmt.checkRx(p.data, 28, &p.rssi); + if(CMT_SUCCESS == status) + mBufCtrl.push(p); + if(NULL != mIvIdChannelSet) { + if(U32_B3(*mIvIdChannelSet) != p.data[2]) + return; + if(U32_B2(*mIvIdChannelSet) != p.data[3]) + return; + if(U32_B1(*mIvIdChannelSet) != p.data[4]) + return; + if(U32_B0(*mIvIdChannelSet) != p.data[5]) + return; + *mIvIdChannelSet = NULL; + } + } + + CmtType mCmt; + uint32_t mDtuSn; + uint8_t[27] mTxBuf; + bool mSerialDebug; + uint32_t *mIvIdChannelSet; + bool mIrqRcvd; +}; + +#endif /*__HMS_RADIO_H__*/ diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 9d294498..83e273e1 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -194,7 +194,7 @@ class MiPayload { if (mSerialDebug) { DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); - mSys->Radio.dumpBuf(payload, payloadLen); + ah::dumpBuf(payload, payloadLen); } if (NULL == rec) { diff --git a/src/main.cpp b/src/main.cpp index c585d0f2..677073f1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,13 +15,18 @@ IRAM_ATTR void handleIntr(void) { myApp.handleIntr(); } +//----------------------------------------------------------------------------- +IRAM_ATTR void handleHmsIntr(void) { + myApp.handleHmsIntr(); +} + //----------------------------------------------------------------------------- void setup() { myApp.setup(); - // TODO: move to HmRadio attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); + attachInterrupt(digitalPinToInterrupt(myApp.getHmsIrqPin()), handleHmsIntr, RISING); } diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp index 97d7418b..95f330e9 100644 --- a/src/utils/helper.cpp +++ b/src/utils/helper.cpp @@ -4,6 +4,7 @@ //----------------------------------------------------------------------------- #include "helper.h" +#include "dbg.h" namespace ah { void ip2Arr(uint8_t ip[], const char *ipStr) { @@ -64,4 +65,12 @@ namespace ah { } return ret; } + + void dumpBuf(uint8_t buf[], uint8_t len) { + for(uint8_t i = 0; i < len; i++) { + DHEX(buf[i]); + DBGPRINT(" "); + } + DBGPRINTLN(""); + } } diff --git a/src/utils/helper.h b/src/utils/helper.h index 179e6078..f7cad96b 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://ahoydtu.de +// 2023 Ahoy, https://ahoydtu.de // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- @@ -23,6 +23,7 @@ namespace ah { String getDateTimeStr(time_t t); String getTimeStr(time_t t); uint64_t Serial2u64(const char *val); + void dumpBuf(uint8_t buf[], uint8_t len); } #endif /*__HELPER_H__*/ From c4dd372554dcba258b93cd8f886c113bb14f8360 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 20 Feb 2023 23:00:51 +0100 Subject: [PATCH 02/92] improved general structures to support HMS in future --- src/app.cpp | 37 ++++++++++++++++++++--------------- src/app.h | 30 ++++++++++++++++++++-------- src/appInterface.h | 3 +++ src/config/settings.h | 2 ++ src/hm/hmDefines.h | 2 +- src/hm/hmPayload.h | 18 +++++++++-------- src/hm/hmSystem.h | 15 +------------- src/hm/miPayload.h | 28 ++++++++++++++------------ src/{hm => hms}/cmt2300a.h | 0 src/{hm => hms}/esp32_3wSpi.h | 0 src/{hm => hms}/hmsRadio.h | 0 src/main.cpp | 11 +++++------ src/web/RestApi.h | 20 ++++++++++--------- src/web/web.h | 7 +++++-- 14 files changed, 96 insertions(+), 77 deletions(-) rename src/{hm => hms}/cmt2300a.h (100%) rename src/{hm => hms}/esp32_3wSpi.h (100%) rename src/{hm => hms}/hmsRadio.h (100%) diff --git a/src/app.cpp b/src/app.cpp index f609f279..d20a2334 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -35,8 +35,11 @@ void app::setup() { else DBGPRINTLN(F("false")); - mSys.enableDebug(); - mSys.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mSys.setup(); + if(mConfig->nrf.enabled) { + mNrfRadio.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); + mNrfRadio.enableDebug(); + } #if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); @@ -50,19 +53,21 @@ void app::setup() { #endif mSys.addInverters(&mConfig->inst); - mPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); - mPayload.enableSerialDebug(mConfig->serial.debug); - mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + if(mConfig->nrf.enabled) { + mPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); + mPayload.enableSerialDebug(mConfig->serial.debug); + mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); - mMiPayload.setup(this, &mSys, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); - mMiPayload.enableSerialDebug(mConfig->serial.debug); + mMiPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); + mMiPayload.enableSerialDebug(mConfig->serial.debug); + } /*DBGPRINTLN("--- after payload"); DBGPRINTLN(String(ESP.getFreeHeap())); DBGPRINTLN(String(ESP.getHeapFragmentation())); DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ - if(!mSys.Radio.isChipConnected()) + if(!mNrfRadio.isChipConnected()) DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); // when WiFi is in client mode, then enable mqtt broker @@ -79,7 +84,7 @@ void app::setup() { mWeb.setup(this, &mSys, mConfig); mWeb.setProtection(strlen(mConfig->sys.adminPwd) != 0); - mApi.setup(this, &mSys, mWeb.getWebSrvPtr(), mConfig); + mApi.setup(this, &mSys, &mNrfRadio, mWeb.getWebSrvPtr(), mConfig); // Plugins if(mConfig->plugin.display.type != 0) @@ -105,9 +110,9 @@ void app::loop(void) { void app::loopStandard(void) { ah::Scheduler::loop(); - if (mSys.Radio.loop()) { - while (!mSys.Radio.mBufCtrl.empty()) { - packet_t *p = &mSys.Radio.mBufCtrl.front(); + if (mNrfRadio.loop()) { + while (!mNrfRadio.mBufCtrl.empty()) { + packet_t *p = &mNrfRadio.mBufCtrl.front(); if (mConfig->serial.debug) { DPRINT(DBG_INFO, F("RX ")); @@ -126,7 +131,7 @@ void app::loopStandard(void) { else mMiPayload.add(iv, p); } - mSys.Radio.mBufCtrl.pop(); + mNrfRadio.mBufCtrl.pop(); yield(); } mPayload.process(true); @@ -324,15 +329,15 @@ void app::tickMidnight(void) { //----------------------------------------------------------------------------- void app::tickSend(void) { - if(!mSys.Radio.isChipConnected()) { + if(!mNrfRadio.isChipConnected()) { DPRINTLN(DBG_WARN, F("NRF24 not connected!")); return; } if (mIVCommunicationOn) { - if (!mSys.Radio.mBufCtrl.empty()) { + if (!mNrfRadio.mBufCtrl.empty()) { if (mConfig->serial.debug) { DPRINT(DBG_DEBUG, F("recbuf not empty! #")); - DBGPRINTLN(String(mSys.Radio.mBufCtrl.size())); + DBGPRINTLN(String(mNrfRadio.mBufCtrl.size())); } } diff --git a/src/app.h b/src/app.h index e65f21b4..82a33069 100644 --- a/src/app.h +++ b/src/app.h @@ -9,8 +9,6 @@ #include "utils/dbg.h" #include -#include -#include #include #include "appInterface.h" @@ -21,6 +19,8 @@ #include "utils/scheduler.h" #include "hm/hmSystem.h" +#include "hm/hmRadio.h" +//#include "hms/hmsRadio.h" #include "hm/hmPayload.h" #include "hm/miPayload.h" #include "wifi/ahoywifi.h" @@ -38,10 +38,10 @@ #define ACOS(x) (degrees(acos(x))) typedef HmSystem HmSystemType; -typedef HmPayload PayloadType; -typedef MiPayload MiPayloadType; +typedef HmPayload> PayloadType; +typedef MiPayload> MiPayloadType; typedef Web WebType; -typedef RestApi RestApiType; +typedef RestApi> RestApiType; typedef PubMqtt PubMqttType; typedef PubSerial PubSerialType; @@ -63,7 +63,7 @@ class app : public IApp, public ah::Scheduler { void regularTickers(void); void handleIntr(void) { - mSys.Radio.handleIntr(); + mNrfRadio.handleIntr(); } void handleHmsIntr(void) { @@ -160,11 +160,24 @@ class app : public IApp, public ah::Scheduler { return mWeb.getProtection(); } - uint8_t getIrqPin(void) { + void getNrfRadioCounters(uint32_t *sendCnt, uint32_t *retransmits) { + *sendCnt = mNrfRadio.mSendCnt; + *retransmits = mNrfRadio.mRetransmits; + } + + bool getNrfEnabled(void) { + return mConfig->nrf.enabled; + } + + bool getCmtEnabled(void) { + return mConfig->cmt.enabled; + } + + uint8_t getNrfIrqPin(void) { return mConfig->nrf.pinIrq; } - uint8_t getHmsIrqPin(void) { + uint8_t getCmtIrqPin(void) { return mConfig->cmt.pinIrq; } @@ -199,6 +212,7 @@ class app : public IApp, public ah::Scheduler { } HmSystemType mSys; + HmRadio<> mNrfRadio; private: typedef std::function innerLoopCb; diff --git a/src/appInterface.h b/src/appInterface.h index 83a4f769..6b969c5a 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -46,6 +46,9 @@ class IApp { virtual uint32_t getMqttTxCnt() = 0; virtual bool getProtection() = 0; + + virtual void getNrfRadioCounters(uint32_t *sendCnt, uint32_t *retransmits) = 0; + //virtual void getCmtRadioCounters(uint32_t *sendCnt, uint32_t *retransmits) = 0; }; #endif /*__IAPP_H__*/ diff --git a/src/config/settings.h b/src/config/settings.h index e42201a5..0a738309 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -60,6 +60,7 @@ typedef struct { } cfgSys_t; typedef struct { + bool enabled; uint16_t sendInterval; uint8_t maxRetransPerPyld; uint8_t pinCs; @@ -69,6 +70,7 @@ typedef struct { } cfgNrf24_t; typedef struct { + bool enabled; uint8_t pinCsb; uint8_t pinFcsb; uint8_t pinIrq; diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index aa9fe24f..61850f04 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://github.com/lumpapu/ahoy +// 2023 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index acfcbd0b..6d10acd3 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -31,14 +31,15 @@ typedef std::function payloadListenerType; typedef std::function alarmListenerType; -template +template class HmPayload { public: HmPayload() {} - void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + void setup(IApp *app, HMSYSTEM *sys, HMRADIO *radio, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { mApp = app; mSys = sys; + mRadio = radio; mStat = stat; mMaxRetrans = maxRetransmits; mTimestamp = timestamp; @@ -149,7 +150,7 @@ class HmPayload { DBGPRINT(F(" power limit ")); DBGPRINTLN(String(iv->powerLimit[0])); } - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); + mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); mPayload[iv->id].txCmd = iv->devControlCmd; //iv->clearCmdQueue(); //iv->enqueCommand(SystemConfigPara); // read back power limit @@ -158,7 +159,7 @@ class HmPayload { DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); DBGPRINT(F(") prepareDevInformCmd")); // + String(cmd, HEX)); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); + mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; } } @@ -243,14 +244,14 @@ class HmPayload { mPayload[iv->id].retransmits = mMaxRetrans; } else if(iv->devControlCmd == ActivePowerContr) { DPRINTLN(DBG_INFO, F("retransmit power limit")); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); } else { if(false == mPayload[iv->id].gotFragment) { /* DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit")); mPayload[iv->id].txCmd = iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); */ DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); @@ -262,7 +263,7 @@ class HmPayload { DPRINT(DBG_WARN, F("Frame ")); DBGPRINT(String(i + 1)); DBGPRINTLN(F(" missing: Request Retransmit")); - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); break; // only request retransmit one frame per loop } yield(); @@ -280,7 +281,7 @@ class HmPayload { DBGPRINT(String(iv->id)); DBGPRINT(F(") prepareDevInformCmd 0x")); DBGPRINTLN(String(mPayload[iv->id].txCmd, HEX)); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); } } else { // payload complete DPRINT(DBG_INFO, F("procPyld: cmd: 0x")); @@ -407,6 +408,7 @@ class HmPayload { IApp *mApp; HMSYSTEM *mSys; + HMRADIO *mRadio; statistics_t *mStat; uint8_t mMaxRetrans; uint32_t *mTimestamp; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 3f3b29a7..fbadbdb6 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://github.com/lumpapu/ahoy +// 2023 Ahoy, https://github.com/lumpapu/ahoy // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- @@ -7,23 +7,14 @@ #define __HM_SYSTEM_H__ #include "hmInverter.h" -#include "hmRadio.h" template > class HmSystem { public: - HmRadio<> Radio; - HmSystem() {} void setup() { mNumInv = 0; - Radio.setup(); - } - - void setup(uint8_t ampPwr, uint8_t irqPin, uint8_t cePin, uint8_t csPin) { - mNumInv = 0; - Radio.setup(ampPwr, irqPin, cePin, csPin); } void addInverters(cfgInst_t *config) { @@ -124,10 +115,6 @@ class HmSystem { return MAX_NUM_INVERTERS; } - void enableDebug() { - Radio.enableDebug(); - } - private: INVERTERTYPE mInverter[MAX_INVERTER]; uint8_t mNumInv; diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 83e273e1..09702216 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -35,14 +35,15 @@ typedef struct { typedef std::function miPayloadListenerType; -template +template class MiPayload { public: MiPayload() {} - void setup(IApp *app, HMSYSTEM *sys, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + void setup(IApp *app, HMSYSTEM *sys, HMRADIO *radio, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { mApp = app; mSys = sys; + mRadio = radio; mStat = stat; mMaxRetrans = maxRetransmits; mTimestamp = timestamp; @@ -86,7 +87,7 @@ class MiPayload { uint8_t cmd = iv->type == INV_TYPE_4CH ? 0x36 : 0x09; //iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd")); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); + mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd; } @@ -104,8 +105,8 @@ class MiPayload { miDataDecode(iv,p); iv->setQueuedCmdFinished(); if (INV_TYPE_2CH == iv->type) { - //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, 0x11, mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); + //mRadio->prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); + mRadio->prepareDevInformCmd(iv->radioId.u64, 0x11, mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); } else { // additional check for mPayload[iv->id].stsa == true might be a good idea (request retransmit?) mPayload[iv->id].complete = true; //iv->setQueuedCmdFinished(); @@ -122,8 +123,8 @@ class MiPayload { miDataDecode(iv,p); iv->setQueuedCmdFinished(); if (p->packet[0] < (0x39 + ALL_FRAMES)) { - //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, p->packet[0] + 1 - ALL_FRAMES, mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); + //mRadio->prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); + mRadio->prepareDevInformCmd(iv->radioId.u64, p->packet[0] + 1 - ALL_FRAMES, mPayload[iv->id].ts, iv->alarmMesIndex, false, p->packet[0] + 1 - ALL_FRAMES); } else { mPayload[iv->id].complete = true; //iv->setValue(iv->getPosByChFld(0, FLD_YD, rec), rec, CALC_YD_CH0); @@ -259,12 +260,12 @@ class MiPayload { mPayload[iv->id].retransmits = mMaxRetrans; } else if(iv->devControlCmd == ActivePowerContr) { DPRINTLN(DBG_INFO, F("retransmit power limit")); - mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); } else { if (mPayload[iv->id].retransmits < mMaxRetrans) { mPayload[iv->id].retransmits++; - //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); - mSys->Radio.sendCmdPacket(iv->radioId.u64, iv->getQueuedCmd(), 24, true); + //mRadio->prepareDevInformCmd(iv->radioId.u64, iv->getQueuedCmd(), mPayload[iv->id].ts, iv->alarmMesIndex, false, 0x11); + mRadio->sendCmdPacket(iv->radioId.u64, iv->getQueuedCmd(), 24, true); /*if(false == mPayload[iv->id].gotFragment) { DPRINTLN(DBG_WARN, F("(#") + String(iv->id) + F(") nothing received")); mPayload[iv->id].retransmits = mMaxRetrans; @@ -272,7 +273,7 @@ class MiPayload { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { if (mPayload[iv->id].len[i] == 0) { DPRINTLN(DBG_WARN, F("Frame ") + String(i + 1) + F(" missing: Request Retransmit")); - mSys->Radio.sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); break; // only request retransmit one frame per loop } yield(); @@ -287,7 +288,7 @@ class MiPayload { DPRINTLN(DBG_WARN, F("CRC Error: Request Complete Retransmit")); mPayload[iv->id].txCmd = iv->getQueuedCmd(); DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); } } /*else { // payload complete DPRINTLN(DBG_INFO, F("procPyld: cmd: 0x") + String(mPayload[iv->id].txCmd, HEX)); @@ -310,7 +311,7 @@ class MiPayload { if (mSerialDebug) { DPRINT(DBG_INFO, F("Payload (") + String(payloadLen) + "): "); - mSys->Radio.dumpBuf(payload, payloadLen); + ah::dumpBuf(payload, payloadLen); } if (NULL == rec) { @@ -552,6 +553,7 @@ class MiPayload { IApp *mApp; HMSYSTEM *mSys; + HMRADIO *mRadio; statistics_t *mStat; uint8_t mMaxRetrans; uint32_t *mTimestamp; diff --git a/src/hm/cmt2300a.h b/src/hms/cmt2300a.h similarity index 100% rename from src/hm/cmt2300a.h rename to src/hms/cmt2300a.h diff --git a/src/hm/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h similarity index 100% rename from src/hm/esp32_3wSpi.h rename to src/hms/esp32_3wSpi.h diff --git a/src/hm/hmsRadio.h b/src/hms/hmsRadio.h similarity index 100% rename from src/hm/hmsRadio.h rename to src/hms/hmsRadio.h diff --git a/src/main.cpp b/src/main.cpp index 677073f1..b81f6145 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,10 @@ //----------------------------------------------------------------------------- -// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778 +// 2023 Ahoy, https://www.mikrocontroller.net/topic/525778 // Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ //----------------------------------------------------------------------------- #include "utils/dbg.h" #include "app.h" -#include "config/config.h" - app myApp; @@ -20,13 +18,14 @@ IRAM_ATTR void handleHmsIntr(void) { myApp.handleHmsIntr(); } - //----------------------------------------------------------------------------- void setup() { myApp.setup(); - attachInterrupt(digitalPinToInterrupt(myApp.getIrqPin()), handleIntr, FALLING); - attachInterrupt(digitalPinToInterrupt(myApp.getHmsIrqPin()), handleHmsIntr, RISING); + if(myApp.getNrfEnabled()) + attachInterrupt(digitalPinToInterrupt(myApp.getNrfIrqPin()), handleIntr, FALLING); + if(myApp.getCmtEnabled()) + attachInterrupt(digitalPinToInterrupt(myApp.getCmtIrqPin()), handleHmsIntr, RISING); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 3dcbc481..b1304510 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -24,7 +24,7 @@ #define F(sl) (sl) #endif -template +template class RestApi { public: RestApi() { @@ -35,10 +35,11 @@ class RestApi { nr = 0; } - void setup(IApp *app, HMSYSTEM *sys, AsyncWebServer *srv, settings_t *config) { + void setup(IApp *app, HMSYSTEM *sys, HMRADIO *radio, AsyncWebServer *srv, settings_t *config) { mApp = app; mSrv = srv; mSys = sys; + mRadio = radio; mConfig = config; mSrv->on("/api", HTTP_GET, std::bind(&RestApi::onApi, this, std::placeholders::_1)); mSrv->on("/api", HTTP_POST, std::bind(&RestApi::onApiPost, this, std::placeholders::_1)).onBody( @@ -281,8 +282,8 @@ class RestApi { obj[F("rx_fail")] = stat->rxFail; obj[F("rx_fail_answer")] = stat->rxFailNoAnser; obj[F("frame_cnt")] = stat->frmCnt; - obj[F("tx_cnt")] = mSys->Radio.mSendCnt; - obj[F("retransmits")] = mSys->Radio.mRetransmits; + obj[F("tx_cnt")] = mRadio->mSendCnt; + obj[F("retransmits")] = mRadio->mRetransmits; } void getInverterList(JsonObject obj) { @@ -346,9 +347,9 @@ class RestApi { void getRadio(JsonObject obj) { obj[F("power_level")] = mConfig->nrf.amplifierPower; - obj[F("isconnected")] = mSys->Radio.isChipConnected(); - obj[F("DataRate")] = mSys->Radio.getDataRate(); - obj[F("isPVariant")] = mSys->Radio.isPVariant(); + obj[F("isconnected")] = mRadio->isChipConnected(); + obj[F("DataRate")] = mRadio->getDataRate(); + obj[F("isPVariant")] = mRadio->isPVariant(); } void getSerial(JsonObject obj) { @@ -449,9 +450,9 @@ class RestApi { } JsonArray warn = obj.createNestedArray(F("warnings")); - if(!mSys->Radio.isChipConnected()) + if(!mRadio->isChipConnected()) warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); - else if(!mSys->Radio.isPVariant()) + else if(!mRadio->isPVariant()) warn.add(F("your NRF24 module isn't a plus version(+), maybe incompatible")); if(!mApp->getSettingsValid()) warn.add(F("your settings are invalid")); @@ -633,6 +634,7 @@ class RestApi { IApp *mApp; HMSYSTEM *mSys; + HMRADIO *mRadio; AsyncWebServer *mSrv; settings_t *mConfig; diff --git a/src/web/web.h b/src/web/web.h index b8468bb6..92809ca3 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -561,7 +561,7 @@ class Web { mConfig->serial.debug = (request->arg("serDbg") == "on"); mConfig->serial.showIv = (request->arg("serEn") == "on"); // Needed to log TX buffers to serial console - mSys->Radio.mSerialDebug = mConfig->serial.debug; + // mSys->Radio.mSerialDebug = mConfig->serial.debug; } // display @@ -767,11 +767,14 @@ class Web { // NRF Statistics stat = mApp->getStatistics(); + uint32_t *nrfSendCnt, *nrfRetransmits; + mApp->getNrfRadioCounters(nrfSendCnt, nrfRetransmits); metrics += radioStatistic(F("rx_success"), stat->rxSuccess); metrics += radioStatistic(F("rx_fail"), stat->rxFail); metrics += radioStatistic(F("rx_fail_answer"), stat->rxFailNoAnser); metrics += radioStatistic(F("frame_cnt"), stat->frmCnt); - metrics += radioStatistic(F("tx_cnt"), mSys->Radio.mSendCnt); + metrics += radioStatistic(F("tx_cnt"), *nrfSendCnt); + metrics += radioStatistic(F("retrans_cnt"), *nrfRetransmits); len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); // Start Inverter loop From 34f898df519444da5611b73515abb1bb596f833c Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 20 Feb 2023 23:24:10 +0100 Subject: [PATCH 03/92] fix compile errors for ESP32 --- src/app.h | 2 +- src/hms/cmt2300a.h | 101 +++++++++++++++++------------------------- src/hms/esp32_3wSpi.h | 6 +-- src/hms/hmsRadio.h | 17 +++---- 4 files changed, 53 insertions(+), 73 deletions(-) diff --git a/src/app.h b/src/app.h index 82a33069..c87cbb8f 100644 --- a/src/app.h +++ b/src/app.h @@ -20,7 +20,7 @@ #include "hm/hmSystem.h" #include "hm/hmRadio.h" -//#include "hms/hmsRadio.h" +#include "hms/hmsRadio.h" #include "hm/hmPayload.h" #include "hm/miPayload.h" #include "wifi/ahoywifi.h" diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 0c6c1641..ffce0ae2 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -10,6 +10,11 @@ // detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf +#define CMT2300A_MASK_CFG_RETAIN 0x10 +#define CMT2300A_MASK_RSTN_IN_EN 0x20 +#define CMT2300A_MASK_LOCKING_EN 0x20 +#define CMT2300A_MASK_CHIP_MODE_STA 0x0F + #define CMT2300A_CUS_MODE_CTL 0x60 // [7] go_switch // [6] go_tx // [5] go_tfs @@ -159,7 +164,7 @@ static uint8_t cmtConfig[0x60] PROGMEM { 0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F }; -enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_ERR_REG_VAL}; +enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO}; template class Cmt2300a { @@ -175,9 +180,11 @@ class Cmt2300a { // call as often as possible void loop() { if(mTxPending) { - if(CMT2300A_MASK_TX_DONE_FLG != spi3w.readReg(CMT2300A_CUS_INT_CLR1)) { - if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + if(CMT2300A_MASK_TX_DONE_FLG != mSpi.readReg(CMT2300A_CUS_INT_CLR1)) { + if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) { mTxPending = false; + goRx(); + } } } } @@ -195,7 +202,7 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh); } - uint8_t checkRx(uint8_t buf[], uint8_t len, int8_t *rssi) { + uint8_t goRx(void) { if(mTxPending) return CMT_ERR_TX_PENDING; @@ -224,56 +231,24 @@ class Cmt2300a { if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) return CMT_ERR_SWITCH_STATE; + } - uint8_t state = 0x00; - uint16_t timeout = 5000; - for(uint8_t i = 0; i < 52; i++) { - state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); - if(0x00 != state) - break; - } + uint8_t checkRx(uint8_t buf[], uint8_t len, int8_t *rssi) { + if(mTxPending) + return CMT_ERR_TX_PENDING; - if((state & 0x10) == 0x10) { - while(0 == digitalRead(INTR_PIN)) { - usleep(10); - if(0 == --timeout) - break; - } - if(0 != timeout) { - uint16_t timeout2 = 5000; - while(0x18 != (state & 0x18)) { - state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); - if(0 == timeout2--) - break; - } - } - } - - if(0 != digitalRead(INTR_PIN)) { - uint32_t loops = 0; - while((state & 0x1b) != 0x1b) { - state = mSpi.readReg(CMT2300A_CUS_INT_FLAG); - - if((state & 0x20) == 0x20) - return CMT_ERR_REG_VAL; - else if((state & 0x40) == 0x40) - return CMT_ERR_REG_VAL; - if(++loops > 5000) - break; - } - } + if(0x1b != (mSpi.readReg(CMT2300A_CUS_INT_FLAG) & 0x1b)) + return CMT_FIFO_EMPTY; // receive ok (pream, sync, node, crc) - if((state & 0x1b) == 0x1b) { - if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) - return CMT_ERR_SWITCH_STATE; + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return CMT_ERR_SWITCH_STATE; - mSpi.readFifo(buf, len); - *rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128; + mSpi.readFifo(buf, len); + *rssi = mSpi.readReg(CMT2300A_CUS_RSSI_DBM) - 128; - if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) - return CMT_ERR_SWITCH_STATE; - } + if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) + return CMT_ERR_SWITCH_STATE; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return CMT_ERR_SWITCH_STATE; @@ -285,25 +260,25 @@ class Cmt2300a { if(mTxPending) return CMT_ERR_TX_PENDING; - spi3w.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); + mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); - if(0x00 == spi3w.readReg(CMT2300A_CUS_INT_FLAG)) { + if(0x00 == mSpi.readReg(CMT2300A_CUS_INT_FLAG)) { // no data received - spi3w.readReg(CMT2300A_CUS_INT_CLR1); - spi3w.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); - spi3w.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); + mSpi.readReg(CMT2300A_CUS_INT_CLR1); + mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); + mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); - //spi3w.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? - spi3w.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); - spi3w.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); + //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? + mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); + mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); - spi3w.writeReg(0x45, 0x01); - spi3w.writeReg(0x46, len); // payload length + mSpi.writeReg(0x45, 0x01); + mSpi.writeReg(0x46, len); // payload length - spi3w.writeFifo(buf, len); + mSpi.writeFifo(buf, len); // send only on base frequency: here 863.0 MHz - spi3w.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) return CMT_ERR_SWITCH_STATE; @@ -318,7 +293,7 @@ class Cmt2300a { } // initialize CMT2300A, returns true on success - bool void reset(void) { + bool reset(void) { mSpi.writeReg(0x7f, 0xff); // soft reset delay(30); @@ -422,6 +397,10 @@ class Cmt2300a { return false; } + inline uint8_t getChipStatus(void) { + return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA; + } + SpiType mSpi; bool mTxPending; uint8_t mRxTxCh; diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 41e1bc03..26e0e201 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -37,7 +37,7 @@ class esp32_3wSpi { .dummy_bits = 0, .mode = 0, // SPI mode 0 .clock_speed_hz = SPI_CLK, // 1 MHz - .spics_io_num = CS_PIN, + .spics_io_num = CSB_PIN, .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, .queue_size = 1, .pre_cb = NULL, @@ -56,7 +56,7 @@ class esp32_3wSpi { .cs_ena_pretrans = 2, .cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us .clock_speed_hz = SPI_CLK, // 1 MHz - .spics_io_num = FCS_PIN, + .spics_io_num = FCSB_PIN, .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, .queue_size = 1, .pre_cb = NULL, @@ -67,7 +67,7 @@ class esp32_3wSpi { esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI2_HOST].spid_out, true, false); delay(100); - pinMode(INTR_PIN, INPUT); + pinMode(GPIO3_PIN, INPUT); } void writeReg(uint8_t addr, uint8_t reg) { diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index afe61902..6b54b8c3 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -33,9 +33,11 @@ class HmsRadio { generateDtuSn(); if(!mCmt.resetCMT()) DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); + else + mCmt.goRx(); mSendCnt = 0; - mRetransmits = 0 + mRetransmits = 0; mSerialDebug = false; mIvIdChannelSet = NULL; mIrqRcvd = false; @@ -47,11 +49,12 @@ class HmsRadio { return; mIrqRcvd = false; getRx(); + mCmt.goRx(); } void tickSecond() { if(NULL != mIvIdChannelSet) - prepareSwitchFreqCmd(mIvIdChannelSet); + prepareSwitchChannelCmd(mIvIdChannelSet); } void handeIntr(void) { @@ -64,7 +67,7 @@ class HmsRadio { void setIvBackChannel(const uint32_t *ivId) { mIvIdChannelSet = ivId; - prepareSwitchFreqCmd(); + prepareSwitchChannelCmd(mIvIdChannelSet); } @@ -112,8 +115,6 @@ class HmsRadio { if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); DBGPRINT(String(len)); - DBGPRINT("B Ch"); - DBGPRINT(String(mRfChLst[mTxChIdx])); DBGPRINT(F(" | ")); ah::dumpBuf(mTxBuf, len); } @@ -155,9 +156,9 @@ class HmsRadio { uint64_t MAC = ESP.getEfuseMac(); chipID = ((MAC >> 8) & 0xFF0000) | ((MAC >> 24) & 0xFF00) | ((MAC >> 40) & 0xFF); #endif - dtuSn = 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal + mDtuSn = 0x80000000; // the first digit is an 8 for DTU production year 2022, the rest is filled with the ESP chipID in decimal for(int i = 0; i < 7; i++) { - dtuSn |= (chipID % 10) << (i * 4); + mDtuSn |= (chipID % 10) << (i * 4); chipID /= 10; } } @@ -182,7 +183,7 @@ class HmsRadio { CmtType mCmt; uint32_t mDtuSn; - uint8_t[27] mTxBuf; + uint8_t mTxBuf[27]; bool mSerialDebug; uint32_t *mIvIdChannelSet; bool mIrqRcvd; From c7e01c849dbe4219c10c607e75cf87818936efdc Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 20 Feb 2023 23:28:21 +0100 Subject: [PATCH 04/92] fix ESP8266 compile --- src/hms/esp32_3wSpi.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 26e0e201..c70e37a8 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -6,15 +6,10 @@ #ifndef __ESP32_3WSPI_H__ #define __ESP32_3WSPI_H__ -#include "driver/spi_master.h" -#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal #include "Arduino.h" - #if defined(ESP32) - #define CLK_PIN 18 - #define MOSI_PIN 23 - #define MISO_PIN -1 -#endif +#include "driver/spi_master.h" +#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal #define SPI_CLK 1 * 1000 * 1000 // 1MHz @@ -134,5 +129,6 @@ class esp32_3wSpi { private: spi_device_handle_t spi_reg, spi_fifo; }; +#endif #endif /*__ESP32_3WSPI_H__*/ From 6cbd256c1f0c32ee40e84c01115aa8ad9d4ff620 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 21 Feb 2023 00:12:01 +0100 Subject: [PATCH 05/92] added setttings for cmt added HMS2000 as possible inverter added enable for NRF24 and CMT --- src/config/settings.h | 28 +++++++++++++++++ src/hm/hmDefines.h | 2 +- src/hm/hmSystem.h | 18 ++++++++--- src/hms/esp32_3wSpi.h | 4 +++ src/web/RestApi.h | 15 +++++++-- src/web/html/setup.html | 68 +++++++++++++++++++++++++++++++++-------- src/web/web.h | 13 ++++++-- 7 files changed, 124 insertions(+), 24 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index 0a738309..9894dcf9 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -234,6 +234,9 @@ class settings { mCfg.valid = true; jsonWifi(root[F("wifi")]); jsonNrf(root[F("nrf")]); + #if defined(ESP32) + jsonCmt(root[F("cmt")]); + #endif jsonNtp(root[F("ntp")]); jsonSun(root[F("sun")]); jsonSerial(root[F("serial")]); @@ -263,6 +266,9 @@ class settings { JsonObject root = json.to(); jsonWifi(root.createNestedObject(F("wifi")), true); jsonNrf(root.createNestedObject(F("nrf")), true); + #if defined(ESP32) + jsonCmt(root.createNestedObject(F("cmt")), true); + #endif jsonNtp(root.createNestedObject(F("ntp")), true); jsonSun(root.createNestedObject(F("sun")), true); jsonSerial(root.createNestedObject(F("serial")), true); @@ -317,6 +323,12 @@ class settings { mCfg.nrf.pinCe = DEF_CE_PIN; mCfg.nrf.pinIrq = DEF_IRQ_PIN; mCfg.nrf.amplifierPower = DEF_AMPLIFIERPOWER & 0x03; + mCfg.nrf.enabled = true; + + mCfg.cmt.pinCsb = DEF_PIN_OFF; + mCfg.cmt.pinFcsb = DEF_PIN_OFF; + mCfg.cmt.pinIrq = DEF_PIN_OFF; + mCfg.cmt.enabled = false; snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME); mCfg.ntp.port = DEF_NTP_PORT; @@ -394,6 +406,7 @@ class settings { obj[F("ce")] = mCfg.nrf.pinCe; obj[F("irq")] = mCfg.nrf.pinIrq; obj[F("pwr")] = mCfg.nrf.amplifierPower; + obj[F("en")] = (bool) mCfg.nrf.enabled; } else { mCfg.nrf.sendInterval = obj[F("intvl")]; mCfg.nrf.maxRetransPerPyld = obj[F("maxRetry")]; @@ -401,6 +414,21 @@ class settings { mCfg.nrf.pinCe = obj[F("ce")]; mCfg.nrf.pinIrq = obj[F("irq")]; mCfg.nrf.amplifierPower = obj[F("pwr")]; + mCfg.nrf.enabled = (bool) obj[F("en")]; + } + } + + void jsonCmt(JsonObject obj, bool set = false) { + if(set) { + obj[F("csb")] = mCfg.cmt.pinCsb; + obj[F("fcsb")] = mCfg.cmt.pinFcsb; + obj[F("irq")] = mCfg.cmt.pinIrq; + obj[F("en")] = (bool) mCfg.cmt.enabled; + } else { + mCfg.cmt.pinCsb = obj[F("csb")]; + mCfg.cmt.pinFcsb = obj[F("fcsb")]; + mCfg.cmt.pinIrq = obj[F("irq")]; + mCfg.cmt.enabled = (bool) obj[F("en")]; } } diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index 61850f04..f8e72205 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -10,7 +10,7 @@ #include // inverter generations -enum {IV_HM = 0, IV_MI}; +enum {IV_HM = 0, IV_MI, IV_HMS, IV_HMT}; // units enum {UNIT_V = 0, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT, UNIT_VAR, UNIT_NONE}; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index fbadbdb6..0508a6e0 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -24,9 +24,12 @@ class HmSystem { if (0ULL != config->iv[i].serial.u64) { if (NULL != iv) { DPRINT(DBG_INFO, "added inverter "); - if(iv->config->serial.b[5] == 0x11) - DBGPRINT("HM"); - else { + if(iv->config->serial.b[5] == 0x11) { + if((iv->config->serial.b[4] & 0x0f) == 0x04) + DBGPRINT("HMS"); + else + DBGPRINT("HM"); + } else { DBGPRINT(((iv->config->serial.b[4] & 0x03) == 0x01) ? " (2nd Gen) " : " (3rd Gen) "); } @@ -56,6 +59,7 @@ class HmSystem { case 0x21: p->type = INV_TYPE_1CH; break; case 0x42: case 0x41: p->type = INV_TYPE_2CH; break; + case 0x64: // HMS2000 case 0x62: case 0x61: p->type = INV_TYPE_4CH; break; default: @@ -63,8 +67,12 @@ class HmSystem { break; } - if(p->config->serial.b[5] == 0x11) - p->ivGen = IV_HM; + if(p->config->serial.b[5] == 0x11) { + if((p->config->serial.b[4] & 0x0f) == 0x04) + p->ivGen = IV_HMS; + else + p->ivGen = IV_HM; + } else if((p->config->serial.b[4] & 0x03) == 0x02) // MI 3rd Gen -> same as HM p->ivGen = IV_HM; else // MI 2nd Gen diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index c70e37a8..aeb01f2d 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -11,6 +11,10 @@ #include "driver/spi_master.h" #include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal +#define CLK_PIN 18 +#define MOSI_PIN 23 +#define MISO_PIN -1 + #define SPI_CLK 1 * 1000 * 1000 // 1MHz template diff --git a/src/web/RestApi.h b/src/web/RestApi.h index b1304510..11f87c64 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -212,7 +212,7 @@ class RestApi { obj[F("sketch_used")] = ESP.getSketchSize() / 1024; // in kb getGeneric(obj); - getRadio(obj.createNestedObject(F("radio"))); + getRadioNrf(obj.createNestedObject(F("radio"))); getStatistics(obj.createNestedObject(F("statistics"))); #if defined(ESP32) @@ -345,11 +345,19 @@ class RestApi { obj[F("led1")] = mConfig->led.led1; } - void getRadio(JsonObject obj) { + void getRadioCmt(JsonObject obj) { + obj[F("csb")] = mConfig->cmt.pinCsb; + obj[F("fcsb")] = mConfig->cmt.pinFcsb; + obj[F("irq")] = mConfig->cmt.pinIrq; + obj[F("en")] = (bool) mConfig->cmt.enabled; + } + + void getRadioNrf(JsonObject obj) { obj[F("power_level")] = mConfig->nrf.amplifierPower; obj[F("isconnected")] = mRadio->isChipConnected(); obj[F("DataRate")] = mRadio->getDataRate(); obj[F("isPVariant")] = mRadio->isPVariant(); + obj[F("en")] = (bool) mConfig->nrf.enabled; } void getSerial(JsonObject obj) { @@ -482,7 +490,8 @@ class RestApi { getNtp(obj.createNestedObject(F("ntp"))); getSun(obj.createNestedObject(F("sun"))); getPinout(obj.createNestedObject(F("pinout"))); - getRadio(obj.createNestedObject(F("radio"))); + getRadioCmt(obj.createNestedObject(F("radioCmt"))); + getRadioNrf(obj.createNestedObject(F("radioNrf"))); getSerial(obj.createNestedObject(F("serial"))); getStaticIp(obj.createNestedObject(F("static_ip"))); getDisplay(obj.createNestedObject(F("display"))); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index efcf0adc..03809290 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -173,6 +173,9 @@

Radio (NRF24L01+)

+

Radio (CMT2300A)

+
+

Serial Console


@@ -408,6 +411,11 @@ case "6": max = 4; break; } } + else if(serial.charAt(2) == 6) { + switch(serial.charAt(3) == 4) { + case "4": max = 4; break; + } + } } } @@ -519,22 +527,56 @@ function parsePinout(obj, type) { var e = document.getElementById("pinout"); - pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq'], ['led0', 'pinLed0'], ['led1', 'pinLed1']]; + pins = [['led0', 'pinLed0'], ['led1', 'pinLed1']]; for(p of pins) { - e.appendChild(lbl(p[1], p[0].toUpperCase())); - e.appendChild(sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]])); + e.append( + lbl(p[1], p[0].toUpperCase()), + sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ); } } - function parseRadio(obj) { + function parseNrfRadio(obj) { var e = document.getElementById("rf24"); - e.appendChild(lbl("rf24Power", "Amplifier Power Level")); - e.appendChild(sel("rf24Power", [ - [0, "MIN"], - [1, "LOW"], - [2, "HIGH"], - [3, "MAX"] - ], obj["power_level"])); + var en = inp("rf24Enable", null, null, ["cb"], "rf24Enable", "checkbox"); + en.checked = obj["en"]; + + e.append( + lbl("rf24Enable", "NRF24 Radio Enable"), + en, + lbl("rf24Power", "Amplifier Power Level"), + sel("rf24Power", [ + [0, "MIN"], + [1, "LOW"], + [2, "HIGH"], + [3, "MAX"] + ], obj["power_level"]) + ); + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; + for(p of pins) { + e.append( + lbl(p[1], p[0].toUpperCase()), + sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ); + } + } + + function parseCmtRadio(obj) { + var e = document.getElementById("cmt"); + var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); + en.checked = obj["en"]; + + e.append( + lbl("cmtEnable", "CMT2300A Radio Enable"), + en + ); + pins = [['csb', 'pinCsb'], ['fcsb', 'pinFcsb'], ['irq', 'pinGpio3']]; + for(p of pins) { + e.append( + lbl(p[1], p[0].toUpperCase()), + sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ); + } } function parseSerial(obj) { @@ -577,7 +619,9 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"]); - parseRadio(root["radio"]); + parseNrfRadio(root["radioNrf"]); + if(root["generic"]["esp_type"] == "ESP32") + parseCmtRadio(root["radioCmt"]); parseSerial(root["serial"]); parseDisplay(root["display"], root["system"]["esp_type"]); } diff --git a/src/web/web.h b/src/web/web.h index 92809ca3..c8b8e896 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -33,7 +33,7 @@ #define WEB_SERIAL_BUF_SIZE 2048 -const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1"}; +const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1", "pinCsb", "pinFcsb", "pinGpio3"}; template class Web { @@ -512,13 +512,20 @@ class Web { default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break; case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break; - case 3: mConfig->led.led0 = pin; break; - case 4: mConfig->led.led1 = pin; break; + case 3: mConfig->led.led0 = pin; break; + case 4: mConfig->led.led1 = pin; break; + case 5: mConfig->cmt.pinCsb = pin; break; + case 6: mConfig->cmt.pinFcsb = pin; break; + case 7: mConfig->cmt.pinIrq = pin; break; } } // nrf24 amplifier power mConfig->nrf.amplifierPower = request->arg("rf24Power").toInt() & 0x03; + mConfig->nrf.enabled = (request->arg("rf24Enable") == "on"); + + // cmt + mConfig->cmt.enabled = (request->arg("cmtEnable") == "on"); // ntp if(request->arg("ntpAddr") != "") { From 5525d25e4ba22e4711fd0a1a370259b629aaf3c5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 21 Feb 2023 00:26:47 +0100 Subject: [PATCH 06/92] added CmtRadio to app --- src/app.cpp | 28 +++++++++++++++++++++++++++- src/app.h | 4 +++- src/hms/hmsRadio.h | 13 +++++++------ 3 files changed, 37 insertions(+), 8 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index d20a2334..29cd0589 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -40,6 +40,12 @@ void app::setup() { mNrfRadio.setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs); mNrfRadio.enableDebug(); } + #if defined(ESP32) + if(mConfig->cmt.enabled) { + mCmtRadio.setup(); + mCmtRadio.enableDebug(); + } + #endif #if defined(AP_ONLY) mInnerLoopCb = std::bind(&app::loopStandard, this); @@ -67,7 +73,7 @@ void app::setup() { DBGPRINTLN(String(ESP.getHeapFragmentation())); DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ - if(!mNrfRadio.isChipConnected()) + if(!mNrfRadio.isChipConnected() && mConfig->nrf.enabled) DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); // when WiFi is in client mode, then enable mqtt broker @@ -137,6 +143,22 @@ void app::loopStandard(void) { mPayload.process(true); mMiPayload.process(true); } + #if defined(ESP32) + if (mCmtRadio.loop()) { + while (!mCmtRadio.mBufCtrl.empty()) { + hmsPacket_t *p = &mCmtRadio.mBufCtrl.front(); + if (mConfig->serial.debug) { + DPRINT(DBG_INFO, F("RX ")); + DBGPRINT(String(p->data[0])); + DBGPRINT(F("RSSI ")); + DBGPRINT(String(p->rssi)); + DBGPRINT(F("dBm | ")); + ah::dumpBuf(&p->data[1], p->data[0]); + } + mCmtRadio.mBufCtrl.pop(); + } + } + #endif mPayload.loop(); mMiPayload.loop(); @@ -158,6 +180,10 @@ void app::onWifi(bool gotIp) { if (gotIp) { mInnerLoopCb = std::bind(&app::loopStandard, this); every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); + #if defined(ESP32) + if(mConfig->cmt.enabled) + everySec(std::bind(&CmtRadioType::tickSecond, mCmtRadio), "tsCmt"); + #endif mMqttReconnect = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! once(std::bind(&app::tickNtpUpdate, this), 2, "ntp2"); diff --git a/src/app.h b/src/app.h index c87cbb8f..c844e52a 100644 --- a/src/app.h +++ b/src/app.h @@ -37,6 +37,7 @@ #define ASIN(x) (degrees(asin(x))) #define ACOS(x) (degrees(acos(x))) +typedef CmtRadio> CmtRadioType; typedef HmSystem HmSystemType; typedef HmPayload> PayloadType; typedef MiPayload> MiPayloadType; @@ -67,7 +68,7 @@ class app : public IApp, public ah::Scheduler { } void handleHmsIntr(void) { - //mSys.Radio.handleHmsIntr(); + mCmtRadio.handleIntr(); } uint32_t getUptime() { @@ -213,6 +214,7 @@ class app : public IApp, public ah::Scheduler { HmSystemType mSys; HmRadio<> mNrfRadio; + CmtRadioType mCmtRadio; private: typedef std::function innerLoopCb; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 6b54b8c3..aadc41fe 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -20,18 +20,18 @@ typedef struct { #define U32_B0(val) ((uint8_t)((val ) & 0xff)) template -class HmsRadio { +class CmtRadio { typedef SPI SpiType; typedef Cmt2300a CmtType; public: - HmsRadio() { + CmtRadio() { mDtuSn = DTU_SN; } void setup(bool genDtuSn = true) { if(genDtuSn) generateDtuSn(); - if(!mCmt.resetCMT()) + if(!mCmt.reset()) DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); else mCmt.goRx(); @@ -43,13 +43,14 @@ class HmsRadio { mIrqRcvd = false; } - void loop() { + bool loop() { mCmt.loop(); if(!mIrqRcvd) - return; + return false; mIrqRcvd = false; getRx(); mCmt.goRx(); + return true; } void tickSecond() { @@ -57,7 +58,7 @@ class HmsRadio { prepareSwitchChannelCmd(mIvIdChannelSet); } - void handeIntr(void) { + void handleIntr(void) { mIrqRcvd = true; } From 3a25ebb26f56e31cd91b234586e3edd93a75cfc9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 21 Feb 2023 20:23:45 +0100 Subject: [PATCH 07/92] improved HMS implementation, RX not functional Tx visible on SDR @ 863MHz --- src/app.cpp | 31 ++- src/app.h | 11 +- src/hm/hmRadio.h | 21 --- src/hms/cmt2300a.h | 86 ++++++--- src/hms/esp32_3wSpi.h | 31 ++- src/hms/hmsPayload.h | 405 ++++++++++++++++++++++++++++++++++++++++ src/hms/hmsRadio.h | 87 +++++---- src/main.cpp | 12 +- src/utils/helper.h | 16 ++ src/web/html/setup.html | 29 ++- src/web/web.h | 18 +- 11 files changed, 616 insertions(+), 131 deletions(-) create mode 100644 src/hms/hmsPayload.h diff --git a/src/app.cpp b/src/app.cpp index 29cd0589..bebfc688 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -42,7 +42,7 @@ void app::setup() { } #if defined(ESP32) if(mConfig->cmt.enabled) { - mCmtRadio.setup(); + mCmtRadio.setup(mConfig->cmt.pinCsb, mConfig->cmt.pinFcsb, false); mCmtRadio.enableDebug(); } #endif @@ -66,6 +66,13 @@ void app::setup() { mMiPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mMiPayload.enableSerialDebug(mConfig->serial.debug); + + if(!mNrfRadio.isChipConnected()) + DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); + } + if(mConfig->cmt.enabled) { + mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); + mHmsPayload.enableSerialDebug(mConfig->serial.debug); } /*DBGPRINTLN("--- after payload"); @@ -73,8 +80,6 @@ void app::setup() { DBGPRINTLN(String(ESP.getHeapFragmentation())); DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ - if(!mNrfRadio.isChipConnected() && mConfig->nrf.enabled) - DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); // when WiFi is in client mode, then enable mqtt broker #if !defined(AP_ONLY) @@ -182,7 +187,7 @@ void app::onWifi(bool gotIp) { every(std::bind(&app::tickSend, this), mConfig->nrf.sendInterval, "tSend"); #if defined(ESP32) if(mConfig->cmt.enabled) - everySec(std::bind(&CmtRadioType::tickSecond, mCmtRadio), "tsCmt"); + everySec(std::bind(&CmtRadioType::tickSecond, &mCmtRadio), "tsCmt"); #endif mMqttReconnect = true; mSunrise = 0; // needs to be set to 0, to reinstall sunrise and ivComm tickers! @@ -355,10 +360,10 @@ void app::tickMidnight(void) { //----------------------------------------------------------------------------- void app::tickSend(void) { - if(!mNrfRadio.isChipConnected()) { + /*if(!mNrfRadio.isChipConnected()) { DPRINTLN(DBG_WARN, F("NRF24 not connected!")); return; - } + }*/ if (mIVCommunicationOn) { if (!mNrfRadio.mBufCtrl.empty()) { if (mConfig->serial.debug) { @@ -366,6 +371,14 @@ void app::tickSend(void) { DBGPRINTLN(String(mNrfRadio.mBufCtrl.size())); } } + #if defined(ESP32) + if (!mCmtRadio.mBufCtrl.empty()) { + if (mConfig->serial.debug) { + DPRINT(DBG_INFO, F("recbuf not empty! #")); + DBGPRINTLN(String(mCmtRadio.mBufCtrl.size())); + } + } + #endif int8_t maxLoop = MAX_NUM_INVERTERS; Inverter<> *iv = mSys.getInverterByPos(mSendLastIvId); @@ -378,8 +391,12 @@ void app::tickSend(void) { if(iv->config->enabled) { if(iv->ivGen == IV_HM) mPayload.ivSend(iv); - else + else if(iv->ivGen == IV_MI) mMiPayload.ivSend(iv); + #if defined(ESP32) + else if(iv->ivGen == IV_HMS) + mHmsPayload.ivSend(iv); + #endif } } } else { diff --git a/src/app.h b/src/app.h index c844e52a..18e6093c 100644 --- a/src/app.h +++ b/src/app.h @@ -21,6 +21,7 @@ #include "hm/hmSystem.h" #include "hm/hmRadio.h" #include "hms/hmsRadio.h" +#include "hms/hmsPayload.h" #include "hm/hmPayload.h" #include "hm/miPayload.h" #include "wifi/ahoywifi.h" @@ -41,6 +42,7 @@ typedef CmtRadio> CmtRadioType; typedef HmSystem HmSystemType; typedef HmPayload> PayloadType; typedef MiPayload> MiPayloadType; +typedef HmsPayload HmsPayloadType; typedef Web WebType; typedef RestApi> RestApiType; typedef PubMqtt PubMqttType; @@ -212,10 +214,6 @@ class app : public IApp, public ah::Scheduler { Scheduler::setTimestamp(newTime); } - HmSystemType mSys; - HmRadio<> mNrfRadio; - CmtRadioType mCmtRadio; - private: typedef std::function innerLoopCb; @@ -269,6 +267,10 @@ class app : public IApp, public ah::Scheduler { innerLoopCb mInnerLoopCb; + HmSystemType mSys; + HmRadio<> mNrfRadio; + CmtRadioType mCmtRadio; + bool mShowRebootRequest; bool mIVCommunicationOn; @@ -277,6 +279,7 @@ class app : public IApp, public ah::Scheduler { RestApiType mApi; PayloadType mPayload; MiPayloadType mMiPayload; + HmsPayloadType mHmsPayload; PubSerialType mPubSerial; char mVersion[12]; diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 47d81166..17421b8a 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -23,27 +23,6 @@ const char* const rf24AmpPowerNames[] = {"MIN", "LOW", "HIGH", "MAX"}; -//----------------------------------------------------------------------------- -// MACROS -//----------------------------------------------------------------------------- -#define CP_U32_LittleEndian(buf, v) ({ \ - uint8_t *b = buf; \ - b[0] = ((v >> 24) & 0xff); \ - b[1] = ((v >> 16) & 0xff); \ - b[2] = ((v >> 8) & 0xff); \ - b[3] = ((v ) & 0xff); \ -}) - -#define CP_U32_BigEndian(buf, v) ({ \ - uint8_t *b = buf; \ - b[3] = ((v >> 24) & 0xff); \ - b[2] = ((v >> 16) & 0xff); \ - b[1] = ((v >> 8) & 0xff); \ - b[0] = ((v ) & 0xff); \ -}) - -#define BIT_CNT(x) ((x)<<3) - //----------------------------------------------------------------------------- // HM Radio class //----------------------------------------------------------------------------- diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index ffce0ae2..7a321991 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -172,9 +172,14 @@ class Cmt2300a { public: Cmt2300a() {} + void setup(uint8_t pinCsb, uint8_t pinFcsb) { + mSpi.setup(pinCsb, pinFcsb); + init(); + } + void setup() { mSpi.setup(); - mTxPending = false; + init(); } // call as often as possible @@ -189,23 +194,13 @@ class Cmt2300a { } } - inline void swichChannel(bool reset = true, uint8_t start = 0x00, uint8_t end = 0x22) { - if(reset) - mRxTxCh = start; - else if(++mRxTxCh > end) - mRxTxCh = start; - // 0: 868.00MHz - // 1: 868.23MHz - // 2: 868.46MHz - // 3: 868.72MHz - // 4: 868.97MHz - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh); - } - uint8_t goRx(void) { if(mTxPending) return CMT_ERR_TX_PENDING; + if(mInRxMode) + return CMT_SUCCESS; + mSpi.readReg(CMT2300A_CUS_INT1_CTL); mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); @@ -229,8 +224,14 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); // 863.0 MHz - if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) + if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) { + Serial.println("Go RX"); return CMT_ERR_SWITCH_STATE; + } + + mInRxMode = true; + + return CMT_SUCCESS; } uint8_t checkRx(uint8_t buf[], uint8_t len, int8_t *rssi) { @@ -253,16 +254,26 @@ class Cmt2300a { if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return CMT_ERR_SWITCH_STATE; + mInRxMode = false; + mCusIntFlag = mSpi.readReg(CMT2300A_CUS_INT_FLAG); + return CMT_SUCCESS; } - bool tx(uint8_t buf[], uint8_t len) { + uint8_t tx(uint8_t buf[], uint8_t len) { if(mTxPending) return CMT_ERR_TX_PENDING; + if(mInRxMode) { + mInRxMode = false; + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + return CMT_ERR_SWITCH_STATE; + } + mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); - if(0x00 == mSpi.readReg(CMT2300A_CUS_INT_FLAG)) { + //mCusIntFlag == mSpi.readReg(CMT2300A_CUS_INT_FLAG); + //if(0x00 == mCusIntFlag) { // no data received mSpi.readReg(CMT2300A_CUS_INT_CLR1); mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); @@ -278,16 +289,16 @@ class Cmt2300a { mSpi.writeFifo(buf, len); // send only on base frequency: here 863.0 MHz - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); + swichChannel((len != 15)); if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) return CMT_ERR_SWITCH_STATE; // wait for tx done - mTxPending = CMT_SUCCESS; - } - else - return CMT_ERR_RX_IN_FIFO; + mTxPending = true; + //} + //else + // return CMT_ERR_RX_IN_FIFO; return CMT_SUCCESS; } @@ -297,7 +308,7 @@ class Cmt2300a { mSpi.writeReg(0x7f, 0xff); // soft reset delay(30); - if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) + if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; if(0xAA != mSpi.readReg(0x48)) @@ -384,6 +395,13 @@ class Cmt2300a { } private: + void init() { + mTxPending = false; + mInRxMode = false; + mCusIntFlag = 0x00; + mCnt = 0; + } + // CMT state machine, wait for next state, true on success bool cmtSwitchStatus(uint8_t cmd, uint8_t waitFor, uint16_t cycles = 40) { mSpi.writeReg(CMT2300A_CUS_MODE_CTL, cmd); @@ -397,13 +415,35 @@ class Cmt2300a { return false; } + inline void swichChannel(bool def = true, uint8_t start = 0x00, uint8_t end = 0x22) { + if(!def) { + if(++mCnt > 2) { + if(++mRxTxCh > end) + mRxTxCh = start; + mCnt = 0; + } + } + // 0: 868.00MHz + // 1: 868.23MHz + // 2: 868.46MHz + // 3: 868.72MHz + // 4: 868.97MHz + if(!def) + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh); + else + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); + } + inline uint8_t getChipStatus(void) { return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA; } SpiType mSpi; + uint8_t mCnt; bool mTxPending; uint8_t mRxTxCh; + bool mInRxMode; + uint8_t mCusIntFlag; }; #endif /*__CMT2300A_H__*/ diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index aeb01f2d..8d8c062a 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -17,11 +17,14 @@ #define SPI_CLK 1 * 1000 * 1000 // 1MHz -template +template //, uint8_t GPIO3_PIN=15> class esp32_3wSpi { public: - esp32_3wSpi() {} - void setup() { + esp32_3wSpi() { + mInitialized = false; + } + + void setup(uint8_t pinCsb = CSB_PIN, uint8_t pinFcsb = FCSB_PIN) { //, uint8_t pinGpio3 = GPIO3_PIN) { spi_bus_config_t buscfg = { .mosi_io_num = MOSI_PIN, .miso_io_num = MISO_PIN, @@ -35,8 +38,8 @@ class esp32_3wSpi { .address_bits = 0, .dummy_bits = 0, .mode = 0, // SPI mode 0 - .clock_speed_hz = SPI_CLK, // 1 MHz - .spics_io_num = CSB_PIN, + .clock_speed_hz = SPI_CLK, + .spics_io_num = pinCsb, .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, .queue_size = 1, .pre_cb = NULL, @@ -54,8 +57,8 @@ class esp32_3wSpi { .mode = 0, // SPI mode 0 .cs_ena_pretrans = 2, .cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us - .clock_speed_hz = SPI_CLK, // 1 MHz - .spics_io_num = FCSB_PIN, + .clock_speed_hz = SPI_CLK, + .spics_io_num = pinFcsb, .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, .queue_size = 1, .pre_cb = NULL, @@ -66,10 +69,14 @@ class esp32_3wSpi { esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI2_HOST].spid_out, true, false); delay(100); - pinMode(GPIO3_PIN, INPUT); + //pinMode(pinGpio3, INPUT); + mInitialized = true; } void writeReg(uint8_t addr, uint8_t reg) { + if(!mInitialized) + return; + uint8_t tx_data[2]; tx_data[0] = ~addr; tx_data[1] = ~reg; @@ -83,6 +90,9 @@ class esp32_3wSpi { } uint8_t readReg(uint8_t addr) { + if(!mInitialized) + return 0; + uint8_t tx_data, rx_data; tx_data = ~(addr | 0x80); // negation and MSB high (read command) spi_transaction_t t = { @@ -97,6 +107,8 @@ class esp32_3wSpi { } void writeFifo(uint8_t buf[], uint8_t len) { + if(!mInitialized) + return; uint8_t tx_data; spi_transaction_t t = { @@ -114,6 +126,8 @@ class esp32_3wSpi { } void readFifo(uint8_t buf[], uint8_t len) { + if(!mInitialized) + return; uint8_t rx_data; spi_transaction_t t = { @@ -132,6 +146,7 @@ class esp32_3wSpi { private: spi_device_handle_t spi_reg, spi_fifo; + bool mInitialized; }; #endif diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h new file mode 100644 index 00000000..80f6f386 --- /dev/null +++ b/src/hms/hmsPayload.h @@ -0,0 +1,405 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://ahoydtu.de +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __HMS_PAYLOAD_H__ +#define __HMS_PAYLOAD_H__ + +#include "../utils/dbg.h" +#include "../utils/crc.h" +#include "../config/config.h" +#include + +typedef struct { + //uint8_t txCmd; + //uint8_t txId; + //uint8_t invId; + uint32_t ts; + //uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; + uint8_t len[MAX_PAYLOAD_ENTRIES]; + //bool complete; + //uint8_t maxPackId; + //bool lastFound; + //uint8_t retransmits; + bool requested; + //bool gotFragment; +} hmsPayload_t; + + +typedef std::function payloadListenerType; +typedef std::function alarmListenerType; + + +template +class HmsPayload { + public: + HmsPayload() {} + + void setup(IApp *app, HMSYSTEM *sys, RADIO *radio, statistics_t *stat, uint8_t maxRetransmits, uint32_t *timestamp) { + mApp = app; + mSys = sys; + mRadio = radio; + mStat = stat; + mMaxRetrans = maxRetransmits; + mTimestamp = timestamp; + for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { + reset(i); + } + mSerialDebug = false; + //mHighPrioIv = NULL; + mCbAlarm = NULL; + mCbPayload = NULL; + mFirst = true; + } + + void enableSerialDebug(bool enable) { + mSerialDebug = enable; + } + + void addPayloadListener(payloadListenerType cb) { + mCbPayload = cb; + } + + void addAlarmListener(alarmListenerType cb) { + mCbAlarm = cb; + } + + void loop() { + /*if(NULL != mHighPrioIv) { + ivSend(mHighPrioIv, true); + mHighPrioIv = NULL; + }*/ + } + + void ivSendHighPrio(Inverter<> *iv) { + //mHighPrioIv = iv; + } + + void ivSend(Inverter<> *iv, bool highPrio = false) { + if(mFirst) { + mFirst = false; + mRadio->setIvBackChannel(&iv->radioId.u64); + } else { + reset(iv->id); + mPayload[iv->id].requested = true; + mRadio->prepareDevInformCmd(&iv->radioId.u64, 0x0b, mPayload[iv->id].ts, iv->alarmMesIndex, false); + } + /*if(!highPrio) { + if (mPayload[iv->id].requested) { + if (!mPayload[iv->id].complete) + process(false); // no retransmit + + if (!mPayload[iv->id].complete) { + if (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId) + mStat->rxFailNoAnser++; // got nothing + else + mStat->rxFail++; // got fragments but not complete response + + iv->setQueuedCmdFinished(); // command failed + if (mSerialDebug) + DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") no Payload received! (retransmits: ")); + DBGPRINT(String(mPayload[iv->id].retransmits)); + DBGPRINTLN(F(")")); + } + } + } + } + + reset(iv->id); + mPayload[iv->id].requested = true; + + yield(); + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") Requesting Inv SN ")); + DBGPRINTLN(String(iv->config->serial.u64, HEX)); + } + + if (iv->getDevControlRequest()) { + if (mSerialDebug) { + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") Devcontrol request 0x")); + DBGPRINT(String(iv->devControlCmd, HEX)); + DBGPRINT(F(" power limit ")); + DBGPRINTLN(String(iv->powerLimit[0])); + } + mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); + mPayload[iv->id].txCmd = iv->devControlCmd; + //iv->clearCmdQueue(); + //iv->enqueCommand(SystemConfigPara); // read back power limit + } else { + uint8_t cmd = iv->getQueuedCmd(); + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") prepareDevInformCmd")); // + String(cmd, HEX)); + mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); + mPayload[iv->id].txCmd = cmd; + }*/ + } + + void add(Inverter<> *iv, packet_t *p) { + /*if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command + mPayload[iv->id].txId = p->packet[0]; + DPRINTLN(DBG_DEBUG, F("Response from info request received")); + uint8_t *pid = &p->packet[9]; + if (*pid == 0x00) { + DPRINT(DBG_DEBUG, F("fragment number zero received and ignored")); + } else { + DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX)); + if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { + memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); + mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; + mPayload[iv->id].gotFragment = true; + } + + if ((*pid & ALL_FRAMES) == ALL_FRAMES) { + // Last packet + if (((*pid & 0x7f) > mPayload[iv->id].maxPackId) || (MAX_PAYLOAD_ENTRIES == mPayload[iv->id].maxPackId)) { + mPayload[iv->id].maxPackId = (*pid & 0x7f); + if (*pid > 0x81) + mPayload[iv->id].lastFound = true; + } + } + } + } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command + DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received")); + + mPayload[iv->id].txId = p->packet[0]; + iv->clearDevControlRequest(); + + if ((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00)) { + bool ok = true; + if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) + mApp->setMqttPowerLimitAck(iv); + else + ok = false; + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(" has ")); + if(!ok) DBGPRINT(F("not ")); + DBGPRINT(F("accepted power limit set point ")); + DBGPRINT(String(iv->powerLimit[0])); + DBGPRINT(F(" with PowerLimitControl ")); + DBGPRINT(String(iv->powerLimit[1])); + + iv->clearCmdQueue(); + iv->enqueCommand(SystemConfigPara); // read back power limit + } + iv->devControlCmd = Init; + }*/ + } + + void process(bool retransmit) { + /*for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + Inverter<> *iv = mSys->getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + + if (IV_MI == iv->ivGen) // only process HM inverters + continue; // skip to next inverter + + if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { + // no processing needed if txId is not 0x95 + mPayload[iv->id].complete = true; + continue; // skip to next inverter + } + + if (!mPayload[iv->id].complete) { + bool crcPass, pyldComplete; + crcPass = build(iv->id, &pyldComplete); + if (!crcPass && !pyldComplete) { // payload not complete + if ((mPayload[iv->id].requested) && (retransmit)) { + if (mPayload[iv->id].retransmits < mMaxRetrans) { + mPayload[iv->id].retransmits++; + if (iv->devControlCmd == Restart || iv->devControlCmd == CleanState_LockAndAlarm) { + // This is required to prevent retransmissions without answer. + DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm...")); + mPayload[iv->id].retransmits = mMaxRetrans; + } else if(iv->devControlCmd == ActivePowerContr) { + DPRINTLN(DBG_INFO, F("retransmit power limit")); + mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + } else { + if(false == mPayload[iv->id].gotFragment) { + + //DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit")); + //mPayload[iv->id].txCmd = iv->getQueuedCmd(); + //DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); + //mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINTLN(F(") nothing received")); + mPayload[iv->id].retransmits = mMaxRetrans; + } else { + for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { + if (mPayload[iv->id].len[i] == 0) { + DPRINT(DBG_WARN, F("Frame ")); + DBGPRINT(String(i + 1)); + DBGPRINTLN(F(" missing: Request Retransmit")); + mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + break; // only request retransmit one frame per loop + } + yield(); + } + } + } + } + } + } else if(!crcPass && pyldComplete) { // crc error on complete Payload + if (mPayload[iv->id].retransmits < mMaxRetrans) { + mPayload[iv->id].retransmits++; + DPRINTLN(DBG_WARN, F("CRC Error: Request Complete Retransmit")); + mPayload[iv->id].txCmd = iv->getQueuedCmd(); + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") prepareDevInformCmd 0x")); + DBGPRINTLN(String(mPayload[iv->id].txCmd, HEX)); + mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); + } + } else { // payload complete + DPRINT(DBG_INFO, F("procPyld: cmd: 0x")); + DBGPRINTLN(String(mPayload[iv->id].txCmd, HEX)); + DPRINT(DBG_INFO, F("procPyld: txid: 0x")); + DBGPRINTLN(String(mPayload[iv->id].txId, HEX)); + DPRINTLN(DBG_DEBUG, F("procPyld: max: ") + String(mPayload[iv->id].maxPackId)); + record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser + mPayload[iv->id].complete = true; + + uint8_t payload[128]; + uint8_t payloadLen = 0; + + memset(payload, 0, 128); + + for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i++) { + memcpy(&payload[payloadLen], mPayload[iv->id].data[i], (mPayload[iv->id].len[i])); + payloadLen += (mPayload[iv->id].len[i]); + yield(); + } + payloadLen -= 2; + + if (mSerialDebug) { + DPRINT(DBG_INFO, F("Payload (")); + DBGPRINT(String(payloadLen)); + DBGPRINT(F("): ")); + ah::dumpBuf(payload, payloadLen); + } + + if (NULL == rec) { + DPRINTLN(DBG_ERROR, F("record is NULL!")); + } else if ((rec->pyldLen == payloadLen) || (0 == rec->pyldLen)) { + if (mPayload[iv->id].txId == (TX_REQ_INFO + ALL_FRAMES)) + mStat->rxSuccess++; + + rec->ts = mPayload[iv->id].ts; + for (uint8_t i = 0; i < rec->length; i++) { + iv->addValue(i, payload, rec); + yield(); + } + iv->doCalculations(); + notify(mPayload[iv->id].txCmd); + + if(AlarmData == mPayload[iv->id].txCmd) { + uint8_t i = 0; + uint16_t code; + uint32_t start, end; + while(1) { + code = iv->parseAlarmLog(i++, payload, payloadLen, &start, &end); + if(0 == code) + break; + if (NULL != mCbAlarm) + (mCbAlarm)(code, start, end); + yield(); + } + } + } else { + DPRINT(DBG_ERROR, F("plausibility check failed, expected ")); + DBGPRINT(String(rec->pyldLen)); + DBGPRINTLN(F(" bytes")); + mStat->rxFail++; + } + + iv->setQueuedCmdFinished(); + } + } + yield(); + }*/ + } + + private: + void notify(uint8_t val) { + if(NULL != mCbPayload) + (mCbPayload)(val); + } + + void notify(uint16_t code, uint32_t start, uint32_t endTime) { + if (NULL != mCbAlarm) + (mCbAlarm)(code, start, endTime); + } + + bool build(uint8_t id, bool *complete) { + /*DPRINTLN(DBG_VERBOSE, F("build")); + uint16_t crc = 0xffff, crcRcv = 0x0000; + if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES) + mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; + + // check if all fragments are there + *complete = true; + for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { + if(mPayload[id].len[i] == 0) + *complete = false; + } + if(!*complete) + return false; + + for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { + if (mPayload[id].len[i] > 0) { + if (i == (mPayload[id].maxPackId - 1)) { + crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc); + crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]); + } else + crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc); + } + yield(); + } + + return (crc == crcRcv) ? true : false;*/ + return true; + } + + void reset(uint8_t id) { + DPRINT(DBG_INFO, "resetPayload: id: "); + DBGPRINTLN(String(id)); + memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); + //mPayload[id].txCmd = 0; + //mPayload[id].gotFragment = false; + //mPayload[id].retransmits = 0; + //mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; + //mPayload[id].lastFound = false; + //mPayload[id].complete = false; + mPayload[id].requested = false; + mPayload[id].ts = *mTimestamp; + } + + IApp *mApp; + HMSYSTEM *mSys; + RADIO *mRadio; + statistics_t *mStat; + uint8_t mMaxRetrans; + uint32_t *mTimestamp; + hmsPayload_t mPayload[MAX_NUM_INVERTERS]; + bool mSerialDebug; + Inverter<> *mHighPrioIv; + bool mFirst; + + alarmListenerType mCbAlarm; + payloadListenerType mCbPayload; +}; + +#endif /*__HMS_PAYLOAD_H__*/ diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index aadc41fe..dd226b27 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -19,7 +19,7 @@ typedef struct { #define U32_B1(val) ((uint8_t)((val >> 8) & 0xff)) #define U32_B0(val) ((uint8_t)((val ) & 0xff)) -template +template class CmtRadio { typedef SPI SpiType; typedef Cmt2300a CmtType; @@ -28,23 +28,25 @@ class CmtRadio { mDtuSn = DTU_SN; } - void setup(bool genDtuSn = true) { - if(genDtuSn) - generateDtuSn(); - if(!mCmt.reset()) - DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); - else - mCmt.goRx(); + void setup(uint8_t pinCsb, uint8_t pinFcsb, bool genDtuSn = true) { + mCmt.setup(pinCsb, pinFcsb); + reset(genDtuSn); + } - mSendCnt = 0; - mRetransmits = 0; - mSerialDebug = false; - mIvIdChannelSet = NULL; - mIrqRcvd = false; + void setup(bool genDtuSn = true) { + mCmt.setup(); + reset(genDtuSn); } bool loop() { mCmt.loop(); + + if(++mCnt > 30000) { + mCnt = 0; + if(NULL != mIvIdChannelSet) + prepareSwitchChannelCmd(mIvIdChannelSet); + } + if(!mIrqRcvd) return false; mIrqRcvd = false; @@ -54,8 +56,6 @@ class CmtRadio { } void tickSecond() { - if(NULL != mIvIdChannelSet) - prepareSwitchChannelCmd(mIvIdChannelSet); } void handleIntr(void) { @@ -66,28 +66,24 @@ class CmtRadio { mSerialDebug = true; } - void setIvBackChannel(const uint32_t *ivId) { + void setIvBackChannel(const uint64_t *ivId) { mIvIdChannelSet = ivId; prepareSwitchChannelCmd(mIvIdChannelSet); } - void prepareDevInformCmd(const uint32_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. + void prepareDevInformCmd(const uint64_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. initPacket(ivId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; - mTxBuf[12] = U32_B3(ts); - mTxBuf[13] = U32_B2(ts); - mTxBuf[14] = U32_B1(ts); - mTxBuf[15] = U32_B0(ts); + CP_U32_LittleEndian(&mTxBuf[12], ts); /*if (cmd == RealTimeRunData_Debug || cmd == AlarmData ) { mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; }*/ - mCmt.swichChannel(true); sendPacket(24, isRetransmit); } - inline void prepareSwitchChannelCmd(const uint32_t *ivId, uint8_t freqSel = 0x0c) { + inline void prepareSwitchChannelCmd(const uint64_t *ivId, uint8_t freqSel = 0x0c) { /** freqSel: * 0x0c: 863.00 MHz * 0x0d: 863.24 MHz @@ -100,7 +96,6 @@ class CmtRadio { mTxBuf[11] = 0x21; mTxBuf[12] = freqSel; mTxBuf[13] = 0x14; - mCmt.swichChannel(); sendPacket(14, false); } @@ -124,6 +119,8 @@ class CmtRadio { if(CMT_SUCCESS != status) { DPRINT(DBG_WARN, F("CMT TX failed, code: ")); DBGPRINTLN(String(status)); + if(CMT_ERR_RX_IN_FIFO == status) + mIrqRcvd = true; } if(isRetransmit) @@ -137,16 +134,26 @@ class CmtRadio { std::queue mBufCtrl; private: - void initPacket(const uint32_t *ivId, uint8_t mid, uint8_t pid) { + inline void reset(bool genDtuSn) { + if(genDtuSn) + generateDtuSn(); + if(!mCmt.reset()) + DPRINTLN(DBG_WARN, F("Initializing CMT2300A failed!")); + else + mCmt.goRx(); + + mSendCnt = 0; + mRetransmits = 0; + mSerialDebug = false; + mIvIdChannelSet = NULL; + mIrqRcvd = false; + mCnt = 0; + } + + void initPacket(const uint64_t *ivId, uint8_t mid, uint8_t pid) { mTxBuf[0] = mid; - mTxBuf[1] = U32_B3(*ivId); - mTxBuf[2] = U32_B2(*ivId); - mTxBuf[3] = U32_B1(*ivId); - mTxBuf[4] = U32_B0(*ivId); - mTxBuf[5] = U32_B3(mDtuSn); - mTxBuf[6] = U32_B2(mDtuSn); - mTxBuf[7] = U32_B1(mDtuSn); - mTxBuf[8] = U32_B0(mDtuSn); + CP_U32_BigEndian(&mTxBuf[1], (*ivId) >> 8); + CP_U32_LittleEndian(&mTxBuf[5], mDtuSn); mTxBuf[9] = pid; memset(&mTxBuf[10], 0x00, 17); } @@ -170,15 +177,15 @@ class CmtRadio { if(CMT_SUCCESS == status) mBufCtrl.push(p); if(NULL != mIvIdChannelSet) { - if(U32_B3(*mIvIdChannelSet) != p.data[2]) + if(U32_B3((*mIvIdChannelSet) >> 8) != p.data[2]) return; - if(U32_B2(*mIvIdChannelSet) != p.data[3]) + if(U32_B2((*mIvIdChannelSet) >> 8) != p.data[3]) return; - if(U32_B1(*mIvIdChannelSet) != p.data[4]) + if(U32_B1((*mIvIdChannelSet) >> 8) != p.data[4]) return; - if(U32_B0(*mIvIdChannelSet) != p.data[5]) + if(U32_B0((*mIvIdChannelSet) >> 8) != p.data[5]) return; - *mIvIdChannelSet = NULL; + mIvIdChannelSet = NULL; } } @@ -186,8 +193,10 @@ class CmtRadio { uint32_t mDtuSn; uint8_t mTxBuf[27]; bool mSerialDebug; - uint32_t *mIvIdChannelSet; + const uint64_t *mIvIdChannelSet; bool mIrqRcvd; + + uint16_t mCnt; }; #endif /*__HMS_RADIO_H__*/ diff --git a/src/main.cpp b/src/main.cpp index b81f6145..966fda8f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -22,10 +22,14 @@ IRAM_ATTR void handleHmsIntr(void) { void setup() { myApp.setup(); - if(myApp.getNrfEnabled()) - attachInterrupt(digitalPinToInterrupt(myApp.getNrfIrqPin()), handleIntr, FALLING); - if(myApp.getCmtEnabled()) - attachInterrupt(digitalPinToInterrupt(myApp.getCmtIrqPin()), handleHmsIntr, RISING); + if(myApp.getNrfEnabled()) { + if(DEF_PIN_OFF != myApp.getNrfIrqPin()) + attachInterrupt(digitalPinToInterrupt(myApp.getNrfIrqPin()), handleIntr, FALLING); + } + if(myApp.getCmtEnabled()) { + if(DEF_PIN_OFF != myApp.getCmtIrqPin()) + attachInterrupt(digitalPinToInterrupt(myApp.getCmtIrqPin()), handleHmsIntr, RISING); + } } diff --git a/src/utils/helper.h b/src/utils/helper.h index f7cad96b..58acd3b9 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -16,6 +16,22 @@ #define CHECK_MASK(a,b) ((a & b) == b) +#define CP_U32_LittleEndian(buf, v) ({ \ + uint8_t *b = buf; \ + b[0] = ((v >> 24) & 0xff); \ + b[1] = ((v >> 16) & 0xff); \ + b[2] = ((v >> 8) & 0xff); \ + b[3] = ((v ) & 0xff); \ +}) + +#define CP_U32_BigEndian(buf, v) ({ \ + uint8_t *b = buf; \ + b[3] = ((v >> 24) & 0xff); \ + b[2] = ((v >> 16) & 0xff); \ + b[1] = ((v >> 8) & 0xff); \ + b[0] = ((v ) & 0xff); \ +}) + namespace ah { void ip2Arr(uint8_t ip[], const char *ipStr); void ip2Char(uint8_t ip[], char *str); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 03809290..d2e022d3 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -297,7 +297,7 @@ [39, "VN (GPIO39)"] ]; - const re = /11[2,4,6]1.*/; + const re = /11[2,4,6][1,2,4].*/; document.getElementById("btnAdd").addEventListener("click", function() { if(highestId <= (maxInv-1)) { @@ -383,8 +383,7 @@ iv.appendChild(lbl(id + "Enable", "Communication Enable")); var en = inp(id + "Enable", null, null, ["cb"], id + "Enable", "checkbox"); en.checked = obj["enabled"]; - iv.appendChild(en); - iv.appendChild(br()); + iv.append(en, br()); iv.appendChild(lbl(id + "Addr", "Serial Number (12 digits)*")); var addr = inp(id + "Addr", obj["serial"], 12, ["text"], null, "text", "[0-9]+", "Invalid input"); @@ -410,9 +409,8 @@ case "4": max = 2; break; case "6": max = 4; break; } - } - else if(serial.charAt(2) == 6) { - switch(serial.charAt(3) == 4) { + } else if(serial.charAt(2) == 6) { + switch(serial.charAt(3)) { case "4": max = 4; break; } } @@ -536,14 +534,14 @@ } } - function parseNrfRadio(obj) { + function parseNrfRadio(obj, type) { var e = document.getElementById("rf24"); var en = inp("rf24Enable", null, null, ["cb"], "rf24Enable", "checkbox"); en.checked = obj["en"]; e.append( - lbl("rf24Enable", "NRF24 Radio Enable"), - en, + lbl("rf24Enable", "NRF24 Enable"), + en, br(), lbl("rf24Power", "Amplifier Power Level"), sel("rf24Power", [ [0, "MIN"], @@ -561,14 +559,14 @@ } } - function parseCmtRadio(obj) { + function parseCmtRadio(obj, type) { var e = document.getElementById("cmt"); var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); en.checked = obj["en"]; e.append( - lbl("cmtEnable", "CMT2300A Radio Enable"), - en + lbl("cmtEnable", "CMT2300A Enable"), + en, br() ); pins = [['csb', 'pinCsb'], ['fcsb', 'pinFcsb'], ['irq', 'pinGpio3']]; for(p of pins) { @@ -619,9 +617,9 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"]); - parseNrfRadio(root["radioNrf"]); + parseNrfRadio(root["radioNrf"], root["system"]["esp_type"]); if(root["generic"]["esp_type"] == "ESP32") - parseCmtRadio(root["radioCmt"]); + parseCmtRadio(root["radioCmt"], root["system"]["esp_type"]); parseSerial(root["serial"]); parseDisplay(root["display"], root["system"]["esp_type"]); } @@ -635,8 +633,7 @@ for(i = 0; i < root["networks"].length; i++) { s.appendChild(opt(root["networks"][i]["ssid"], root["networks"][i]["ssid"] + " (" + root["networks"][i]["rssi"] + " dBm)")); } - } - else + } else s.appendChild(opt("-1", "no network found")); } diff --git a/src/web/web.h b/src/web/web.h index c8b8e896..b4ab8c95 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -506,17 +506,17 @@ class Web { // pinout uint8_t pin; - for(uint8_t i = 0; i < 5; i ++) { + for(uint8_t i = 0; i < 8; i ++) { pin = request->arg(String(pinArgNames[i])).toInt(); switch(i) { - default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; - case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break; - case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break; - case 3: mConfig->led.led0 = pin; break; - case 4: mConfig->led.led1 = pin; break; - case 5: mConfig->cmt.pinCsb = pin; break; - case 6: mConfig->cmt.pinFcsb = pin; break; - case 7: mConfig->cmt.pinIrq = pin; break; + case 0: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break; + case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break; + case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break; + case 3: mConfig->led.led0 = pin; break; + case 4: mConfig->led.led1 = pin; break; + case 5: mConfig->cmt.pinCsb = pin; break; + case 6: mConfig->cmt.pinFcsb = pin; break; + case 7: mConfig->cmt.pinIrq = pin; break; } } From e5145d312273d7e8a096e00e85dacd4747e363f5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 22 Feb 2023 07:35:24 +0100 Subject: [PATCH 08/92] data reception ok, search does not stop --- src/hms/cmt2300a.h | 50 +++++++++++++++++++++++----------------------- src/hms/hmsRadio.h | 2 +- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 7a321991..83639070 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -149,15 +149,15 @@ static uint8_t cmtConfig[0x60] PROGMEM { 0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, // 0x10 - 0x1f 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, - 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, + 0x42, 0x6D, 0x80, 0x86, 0x42, 0x62, 0x27, 0x16, // 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, // 0x20 - 0x2f 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, - 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + 0x9F, 0x4B, 0x0A, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x30 - 0x3f 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, // 0x40 - 0x4f - 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, + 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, // 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, // 0x50 - 0x5f 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, @@ -185,7 +185,7 @@ class Cmt2300a { // call as often as possible void loop() { if(mTxPending) { - if(CMT2300A_MASK_TX_DONE_FLG != mSpi.readReg(CMT2300A_CUS_INT_CLR1)) { + if(CMT2300A_MASK_TX_DONE_FLG == mSpi.readReg(CMT2300A_CUS_INT_CLR1)) { if(cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) { mTxPending = false; goRx(); @@ -205,7 +205,7 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); uint8_t tmp = mSpi.readReg(CMT2300A_CUS_INT_CLR1); - if(0x08 == tmp) // first time after TX this reg is 0x08 + if(0x08 == tmp) // first time after TX a value of 0x08 is read mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x04); else mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); @@ -215,7 +215,7 @@ class Cmt2300a { else mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); - mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? -> if 0x02 last was read + //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? -> if 0x02 last was read // 0x07 last was write mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02); @@ -234,7 +234,7 @@ class Cmt2300a { return CMT_SUCCESS; } - uint8_t checkRx(uint8_t buf[], uint8_t len, int8_t *rssi) { + uint8_t getRx(uint8_t buf[], uint8_t len, int8_t *rssi) { if(mTxPending) return CMT_ERR_TX_PENDING; @@ -311,24 +311,24 @@ class Cmt2300a { if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; - if(0xAA != mSpi.readReg(0x48)) - mSpi.writeReg(0x48, 0xAA); + //if(0xAA != mSpi.readReg(0x48)) + // mSpi.writeReg(0x48, 0xAA); //mSpi.readReg(0x48); - mSpi.writeReg(0x4c, 0x00); + //mSpi.writeReg(0x4c, 0x00); - if(0x52 != mSpi.readReg(CMT2300A_CUS_MODE_STA)) + //if(0x52 != mSpi.readReg(CMT2300A_CUS_MODE_STA)) mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52); - if(0x20 != mSpi.readReg(0x62)) + //if(0x20 != mSpi.readReg(0x62)) mSpi.writeReg(0x62, 0x20); //mSpi.readReg(0x0D); - mSpi.writeReg(0x0F, 0x00); + //mSpi.writeReg(0x0F, 0x00); for(uint8_t i = 0; i < 0x60; i++) { mSpi.writeReg(i, cmtConfig[i]); } - if(0x02 != mSpi.readReg(0x09)) - mSpi.writeReg(0x09, 0x02); + //if(0x02 != mSpi.readReg(0x09)) + // mSpi.writeReg(0x09, 0x02); mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 @@ -343,10 +343,10 @@ class Cmt2300a { // interrupt enable (TX_DONE, PREAM_OK, SYNC_OK, CRC_OK, PKT_DONE) mSpi.writeReg(CMT2300A_CUS_INT_EN, 0x3B); - mSpi.writeReg(0x41, 0x48); + /*mSpi.writeReg(0x41, 0x48); mSpi.writeReg(0x42, 0x5A); mSpi.writeReg(0x43, 0x48); - mSpi.writeReg(0x44, 0x4D); + mSpi.writeReg(0x44, 0x4D);*/ mSpi.writeReg(0x64, 0x64); if(0x00 == mSpi.readReg(CMT2300A_CUS_FIFO_CTL)) @@ -357,18 +357,18 @@ class Cmt2300a { delayMicroseconds(95); - // base frequency 863MHz, with value of CMT2300A_CUS_FREQ_CHNL - // the frequency can be increase in a step size of ~0.24Hz - mSpi.writeReg(0x18, 0x42); + // base frequency 863MHz; with value of CMT2300A_CUS_FREQ_CHNL + // the frequency can be increased in a step size of ~0.24Hz + /*mSpi.writeReg(0x18, 0x42); mSpi.writeReg(0x19, 0x6D); mSpi.writeReg(0x1A, 0x80); mSpi.writeReg(0x1B, 0x86); mSpi.writeReg(0x1C, 0x42); mSpi.writeReg(0x1D, 0x62); mSpi.writeReg(0x1E, 0x27); - mSpi.writeReg(0x1F, 0x16); + mSpi.writeReg(0x1F, 0x16);*/ - mSpi.writeReg(0x22, 0x20); + /*mSpi.writeReg(0x22, 0x20); mSpi.writeReg(0x23, 0x20); mSpi.writeReg(0x24, 0xD2); mSpi.writeReg(0x25, 0x35); @@ -376,14 +376,14 @@ class Cmt2300a { mSpi.writeReg(0x27, 0x0A); mSpi.writeReg(0x28, 0x9F); mSpi.writeReg(0x29, 0x4B); - mSpi.writeReg(0x27, 0x0A); + mSpi.writeReg(0x27, 0x0A);*/ if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; - mSpi.writeReg(0x03, 0x1D); + /*mSpi.writeReg(0x03, 0x1D); mSpi.writeReg(0x5C, 0x8A); - mSpi.writeReg(0x5D, 0x18); + mSpi.writeReg(0x5D, 0x18);*/ if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) return false; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index dd226b27..4a270eb5 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -173,7 +173,7 @@ class CmtRadio { inline void getRx(void) { hmsPacket_t p; - uint8_t status = mCmt.checkRx(p.data, 28, &p.rssi); + uint8_t status = mCmt.getRx(p.data, 28, &p.rssi); if(CMT_SUCCESS == status) mBufCtrl.push(p); if(NULL != mIvIdChannelSet) { From 9881a9f4ead03269951442e4c8c7892961bae6c9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 22 Feb 2023 21:42:58 +0100 Subject: [PATCH 09/92] minor changes --- src/hms/hmsRadio.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 4a270eb5..a0e561aa 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -68,6 +68,10 @@ class CmtRadio { void setIvBackChannel(const uint64_t *ivId) { mIvIdChannelSet = ivId; + Serial.println("Byte 3 " + String(U32_B3((*mIvIdChannelSet) >> 8), HEX)); + Serial.println("Byte 2 " + String(U32_B2((*mIvIdChannelSet) >> 8), HEX)); + Serial.println("Byte 1 " + String(U32_B1((*mIvIdChannelSet) >> 8), HEX)); + Serial.println("Byte 0 " + String(U32_B0((*mIvIdChannelSet) >> 8), HEX)); prepareSwitchChannelCmd(mIvIdChannelSet); } @@ -177,13 +181,13 @@ class CmtRadio { if(CMT_SUCCESS == status) mBufCtrl.push(p); if(NULL != mIvIdChannelSet) { - if(U32_B3((*mIvIdChannelSet) >> 8) != p.data[2]) + if(U32_B3((*mIvIdChannelSet) >> 8) != p.data[5]) return; - if(U32_B2((*mIvIdChannelSet) >> 8) != p.data[3]) + if(U32_B2((*mIvIdChannelSet) >> 8) != p.data[4]) return; - if(U32_B1((*mIvIdChannelSet) >> 8) != p.data[4]) + if(U32_B1((*mIvIdChannelSet) >> 8) != p.data[3]) return; - if(U32_B0((*mIvIdChannelSet) >> 8) != p.data[5]) + if(U32_B0((*mIvIdChannelSet) >> 8) != p.data[2]) return; mIvIdChannelSet = NULL; } From 300fc763c1630a5788531779601b10f55f49667f Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 23 Feb 2023 23:30:46 +0100 Subject: [PATCH 10/92] hms related changes --- src/app.cpp | 15 ++++++- src/hm/hmInverter.h | 15 +++++-- src/hm/hmPayload.h | 2 +- src/hm/miPayload.h | 2 +- src/hms/hmsPayload.h | 98 ++++++++++++++++++++++--------------------- src/wifi/ahoywifi.cpp | 6 +++ 6 files changed, 83 insertions(+), 55 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 2bb0ebd2..782b376d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -73,6 +73,7 @@ void app::setup() { if(mConfig->cmt.enabled) { mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); mHmsPayload.enableSerialDebug(mConfig->serial.debug); + mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); } /*DBGPRINTLN("--- after payload"); @@ -155,17 +156,29 @@ void app::loopStandard(void) { if (mConfig->serial.debug) { DPRINT(DBG_INFO, F("RX ")); DBGPRINT(String(p->data[0])); - DBGPRINT(F("RSSI ")); + DBGPRINT(F(" RSSI ")); DBGPRINT(String(p->rssi)); DBGPRINT(F("dBm | ")); ah::dumpBuf(&p->data[1], p->data[0]); } + mStat.frmCnt++; + + Inverter<> *iv = mSys.findInverter(&p->data[2]); + if(NULL != iv) { + if(IV_HMS == iv->ivGen) + mHmsPayload.add(iv, p); + } mCmtRadio.mBufCtrl.pop(); + yield(); } + mHmsPayload.process(true); } #endif mPayload.loop(); mMiPayload.loop(); + #if defined(ESP32) + mHmsPayload.loop(); + #endif if(mMqttEnabled) mMqtt.loop(); diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index c764cee0..064651fa 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -12,6 +12,7 @@ #endif #include "hmDefines.h" +#include "../hms/hmsDefines.h" #include #include #include "../config/settings.h" @@ -418,10 +419,16 @@ class Inverter { channels = 2; } else if (INV_TYPE_4CH == type) { - rec->length = (uint8_t)(HM4CH_LIST_LEN); - rec->assign = (byteAssign_t *)hm4chAssignment; - rec->pyldLen = HM4CH_PAYLOAD_LEN; - channels = 4; + if(IV_HM == ivGen) { + rec->length = (uint8_t)(HM4CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm4chAssignment; + rec->pyldLen = HM4CH_PAYLOAD_LEN; + } else if(IV_HMS == ivGen) { + rec->length = (uint8_t)(HMS4CH_LIST_LEN); + rec->assign = (byteAssign_t *)hms4chAssignment; + rec->pyldLen = HMS4CH_PAYLOAD_LEN; + } + channels = 4; } else { rec->length = 0; diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 6d10acd3..fe079b79 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -222,7 +222,7 @@ class HmPayload { if (NULL == iv) continue; // skip to next inverter - if (IV_MI == iv->ivGen) // only process HM inverters + if (IV_HM != iv->ivGen) // only process HM inverters continue; // skip to next inverter if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 09702216..7d16f58a 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -240,7 +240,7 @@ class MiPayload { if (NULL == iv) continue; // skip to next inverter - if (IV_HM == iv->ivGen) // only process MI inverters + if (IV_MI != iv->ivGen) // only process MI inverters continue; // skip to next inverter /*if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 80f6f386..729faf51 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -12,18 +12,18 @@ #include typedef struct { - //uint8_t txCmd; - //uint8_t txId; + uint8_t txCmd; + uint8_t txId; //uint8_t invId; uint32_t ts; - //uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; + uint8_t data[MAX_PAYLOAD_ENTRIES][MAX_RF_PAYLOAD_SIZE]; uint8_t len[MAX_PAYLOAD_ENTRIES]; - //bool complete; - //uint8_t maxPackId; - //bool lastFound; - //uint8_t retransmits; + bool complete; + uint8_t maxPackId; + bool lastFound; + uint8_t retransmits; bool requested; - //bool gotFragment; + bool gotFragment; } hmsPayload_t; @@ -77,15 +77,7 @@ class HmsPayload { } void ivSend(Inverter<> *iv, bool highPrio = false) { - if(mFirst) { - mFirst = false; - mRadio->setIvBackChannel(&iv->radioId.u64); - } else { - reset(iv->id); - mPayload[iv->id].requested = true; - mRadio->prepareDevInformCmd(&iv->radioId.u64, 0x0b, mPayload[iv->id].ts, iv->alarmMesIndex, false); - } - /*if(!highPrio) { + //if(!highPrio) { if (mPayload[iv->id].requested) { if (!mPayload[iv->id].complete) process(false); // no retransmit @@ -99,16 +91,16 @@ class HmsPayload { iv->setQueuedCmdFinished(); // command failed if (mSerialDebug) DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout")); - if (mSerialDebug) { + /*if (mSerialDebug) { DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); DBGPRINT(F(") no Payload received! (retransmits: ")); DBGPRINT(String(mPayload[iv->id].retransmits)); DBGPRINTLN(F(")")); - } + }*/ } } - } + //} reset(iv->id); mPayload[iv->id].requested = true; @@ -121,7 +113,7 @@ class HmsPayload { DBGPRINTLN(String(iv->config->serial.u64, HEX)); } - if (iv->getDevControlRequest()) { + /*if (iv->getDevControlRequest()) { if (mSerialDebug) { DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); @@ -142,20 +134,31 @@ class HmsPayload { mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; }*/ + if(mFirst) { + mFirst = false; + mRadio->setIvBackChannel(&iv->radioId.u64); + } else { + uint8_t cmd = iv->getQueuedCmd(); + DPRINT(DBG_INFO, F("(#")); + DBGPRINT(String(iv->id)); + DBGPRINT(F(") prepareDevInformCmd")); // + String(cmd, HEX)); + mRadio->prepareDevInformCmd(&iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); + mPayload[iv->id].txCmd = cmd; + } } - void add(Inverter<> *iv, packet_t *p) { - /*if (p->packet[0] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command - mPayload[iv->id].txId = p->packet[0]; + void add(Inverter<> *iv, hmsPacket_t *p) { + if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command + mPayload[iv->id].txId = p->data[1]; DPRINTLN(DBG_DEBUG, F("Response from info request received")); - uint8_t *pid = &p->packet[9]; + uint8_t *pid = &p->data[10]; if (*pid == 0x00) { DPRINT(DBG_DEBUG, F("fragment number zero received and ignored")); } else { DPRINTLN(DBG_DEBUG, "PID: 0x" + String(*pid, HEX)); if ((*pid & 0x7F) < MAX_PAYLOAD_ENTRIES) { - memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->packet[10], p->len - 11); - mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->len - 11; + memcpy(mPayload[iv->id].data[(*pid & 0x7F) - 1], &p->data[11], p->data[0] - 11); + mPayload[iv->id].len[(*pid & 0x7F) - 1] = p->data[0] -11; mPayload[iv->id].gotFragment = true; } @@ -168,7 +171,7 @@ class HmsPayload { } } } - } else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command + } /*else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received")); mPayload[iv->id].txId = p->packet[0]; @@ -197,12 +200,12 @@ class HmsPayload { } void process(bool retransmit) { - /*for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { + for (uint8_t id = 0; id < mSys->getNumInverters(); id++) { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL == iv) continue; // skip to next inverter - if (IV_MI == iv->ivGen) // only process HM inverters + if (IV_HMS != iv->ivGen) // only process HMS inverters continue; // skip to next inverter if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { @@ -222,10 +225,10 @@ class HmsPayload { // This is required to prevent retransmissions without answer. DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm...")); mPayload[iv->id].retransmits = mMaxRetrans; - } else if(iv->devControlCmd == ActivePowerContr) { + } /*else if(iv->devControlCmd == ActivePowerContr) { DPRINTLN(DBG_INFO, F("retransmit power limit")); mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); - } else { + }*/ else { if(false == mPayload[iv->id].gotFragment) { //DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit")); @@ -243,7 +246,7 @@ class HmsPayload { DPRINT(DBG_WARN, F("Frame ")); DBGPRINT(String(i + 1)); DBGPRINTLN(F(" missing: Request Retransmit")); - mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); + //mRadio->sendCmdPacket(iv->radioId.u64, TX_REQ_INFO, (SINGLE_FRAME + i), true); break; // only request retransmit one frame per loop } yield(); @@ -252,7 +255,7 @@ class HmsPayload { } } } - } else if(!crcPass && pyldComplete) { // crc error on complete Payload + } /*else if(!crcPass && pyldComplete) { // crc error on complete Payload if (mPayload[iv->id].retransmits < mMaxRetrans) { mPayload[iv->id].retransmits++; DPRINTLN(DBG_WARN, F("CRC Error: Request Complete Retransmit")); @@ -263,7 +266,7 @@ class HmsPayload { DBGPRINTLN(String(mPayload[iv->id].txCmd, HEX)); mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); } - } else { // payload complete + }*/ else { // payload complete DPRINT(DBG_INFO, F("procPyld: cmd: 0x")); DBGPRINTLN(String(mPayload[iv->id].txCmd, HEX)); DPRINT(DBG_INFO, F("procPyld: txid: 0x")); @@ -272,10 +275,10 @@ class HmsPayload { record_t<> *rec = iv->getRecordStruct(mPayload[iv->id].txCmd); // choose the parser mPayload[iv->id].complete = true; - uint8_t payload[128]; + uint8_t payload[100]; uint8_t payloadLen = 0; - memset(payload, 0, 128); + memset(payload, 0, 100); for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId); i++) { memcpy(&payload[payloadLen], mPayload[iv->id].data[i], (mPayload[iv->id].len[i])); @@ -305,7 +308,7 @@ class HmsPayload { iv->doCalculations(); notify(mPayload[iv->id].txCmd); - if(AlarmData == mPayload[iv->id].txCmd) { + /*if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; uint16_t code; uint32_t start, end; @@ -317,7 +320,7 @@ class HmsPayload { (mCbAlarm)(code, start, end); yield(); } - } + }*/ } else { DPRINT(DBG_ERROR, F("plausibility check failed, expected ")); DBGPRINT(String(rec->pyldLen)); @@ -329,7 +332,7 @@ class HmsPayload { } } yield(); - }*/ + } } private: @@ -344,7 +347,7 @@ class HmsPayload { } bool build(uint8_t id, bool *complete) { - /*DPRINTLN(DBG_VERBOSE, F("build")); + DPRINTLN(DBG_VERBOSE, F("build")); uint16_t crc = 0xffff, crcRcv = 0x0000; if (mPayload[id].maxPackId > MAX_PAYLOAD_ENTRIES) mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; @@ -361,7 +364,7 @@ class HmsPayload { for (uint8_t i = 0; i < mPayload[id].maxPackId; i++) { if (mPayload[id].len[i] > 0) { if (i == (mPayload[id].maxPackId - 1)) { - crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 2, crc); + crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i] - 1, crc); crcRcv = (mPayload[id].data[i][mPayload[id].len[i] - 2] << 8) | (mPayload[id].data[i][mPayload[id].len[i] - 1]); } else crc = ah::crc16(mPayload[id].data[i], mPayload[id].len[i], crc); @@ -369,8 +372,7 @@ class HmsPayload { yield(); } - return (crc == crcRcv) ? true : false;*/ - return true; + return (crc == crcRcv) ? true : false; } void reset(uint8_t id) { @@ -378,11 +380,11 @@ class HmsPayload { DBGPRINTLN(String(id)); memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); //mPayload[id].txCmd = 0; - //mPayload[id].gotFragment = false; + mPayload[id].gotFragment = false; //mPayload[id].retransmits = 0; - //mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; - //mPayload[id].lastFound = false; - //mPayload[id].complete = false; + mPayload[id].maxPackId = MAX_PAYLOAD_ENTRIES; + mPayload[id].lastFound = false; + mPayload[id].complete = false; mPayload[id].requested = false; mPayload[id].ts = *mTimestamp; } diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 9109c831..ec48759f 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -16,6 +16,12 @@ ahoywifi::ahoywifi() : mApIp(192, 168, 4, 1) {} +/** + * TODO: ESP32 has native strongest AP support! + * WiFi.setScanMethod(WIFI_ALL_CHANNEL_SCAN); + WiFi.setSortMethod(WIFI_CONNECT_AP_BY_SIGNAL); +*/ + //----------------------------------------------------------------------------- void ahoywifi::setup(settings_t *config, uint32_t *utcTimestamp, appWifiCb cb) { mConfig = config; From 1d5579f0031ae4f52b1255e3562d25bb1773f8cc Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 7 Mar 2023 21:15:42 +0100 Subject: [PATCH 11/92] small fix --- src/hms/hmsPayload.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 729faf51..85aeceb9 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -77,6 +77,9 @@ class HmsPayload { } void ivSend(Inverter<> *iv, bool highPrio = false) { + if (IV_HMS != iv->ivGen) // only process HMS inverters + return; + //if(!highPrio) { if (mPayload[iv->id].requested) { if (!mPayload[iv->id].complete) From a01666aee8338fdfd51836a25347df04d3084ab5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 8 Mar 2023 08:28:12 +0100 Subject: [PATCH 12/92] fix merge changes --- src/app.cpp | 6 +++--- src/hm/miPayload.h | 4 ++-- src/hms/hmsPayload.h | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 9d0cea28..cf8dfd87 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -64,11 +64,11 @@ void app::setup() { if(!mNrfRadio.isChipConnected()) DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); } - if(mConfig->cmt.enabled) { + //if(mConfig->cmt.enabled) { mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); mHmsPayload.enableSerialDebug(mConfig->serial.debug); mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); - } + //} /*DBGPRINTLN("--- after payload"); DBGPRINTLN(String(ESP.getFreeHeap())); @@ -167,7 +167,7 @@ void app::loopStandard(void) { mCmtRadio.mBufCtrl.pop(); yield(); } - mHmsPayload.process(true); + //mHmsPayload.process(true); } #endif mPayload.loop(); diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index 88a0b632..6588fe51 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -99,7 +99,7 @@ class MiPayload { cmd2 = 0x00; }; - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); + mRadio->prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); mPayload[iv->id].txCmd = cmd; if (iv->type == INV_TYPE_1CH || iv->type == INV_TYPE_2CH) { mPayload[iv->id].dataAB[CH1] = false; @@ -343,7 +343,7 @@ class MiPayload { } DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") next request is 0x") + String(cmd, HEX)); //mSys->Radio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true); - mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); + mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); mPayload[iv->id].txCmd = cmd; yield(); } diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 85aeceb9..08737aaf 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -381,7 +381,7 @@ class HmsPayload { void reset(uint8_t id) { DPRINT(DBG_INFO, "resetPayload: id: "); DBGPRINTLN(String(id)); - memset(mPayload[id].len, 0, MAX_PAYLOAD_ENTRIES); + memset(&mPayload[id], 0, sizeof(hmsPayload_t)); //mPayload[id].txCmd = 0; mPayload[id].gotFragment = false; //mPayload[id].retransmits = 0; From 30014e26494b18d3ea9f6b8f102595ac94ae279b Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 10 Mar 2023 18:28:56 +0100 Subject: [PATCH 13/92] added missing file --- src/hms/hmsDefines.h | 57 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 src/hms/hmsDefines.h diff --git a/src/hms/hmsDefines.h b/src/hms/hmsDefines.h new file mode 100644 index 00000000..2083783a --- /dev/null +++ b/src/hms/hmsDefines.h @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +//----------------------------------------------------------------------------- + +#ifndef __HMS_DEFINES_H__ +#define __HMS_DEFINES_H__ + +#include "../hm/hmDefines.h" + +//------------------------------------- +// HMS2000 +//------------------------------------- +const byteAssign_t hms4chAssignment[] = { + { FLD_UDC, UNIT_V, CH1, 2, 2, 10 }, + { FLD_UDC, UNIT_V, CH2, 4, 2, 10 }, + { FLD_IDC, UNIT_A, CH1, 6, 2, 100 }, + { FLD_IDC, UNIT_A, CH2, 8, 2, 100 }, + { FLD_PDC, UNIT_W, CH1, 10, 2, 10 }, + { FLD_PDC, UNIT_W, CH2, 12, 2, 10 }, + { FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 }, + { FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 }, + { FLD_YD, UNIT_WH, CH1, 22, 2, 1 }, + { FLD_YD, UNIT_WH, CH2, 24, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + { FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH3, 26, 2, 10 }, + { FLD_UDC, UNIT_V, CH4, 28, 2, 10 }, + { FLD_IDC, UNIT_A, CH3, 30, 2, 100 }, + { FLD_IDC, UNIT_A, CH4, 32, 2, 100 }, + { FLD_PDC, UNIT_W, CH3, 34, 2, 10 }, + { FLD_PDC, UNIT_W, CH4, 36, 2, 10 }, + { FLD_YT, UNIT_KWH, CH3, 38, 4, 1000 }, + { FLD_YT, UNIT_KWH, CH4, 42, 4, 1000 }, + { FLD_YD, UNIT_WH, CH3, 46, 2, 1 }, + { FLD_YD, UNIT_WH, CH4, 48, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC }, + { FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC }, + + { FLD_UAC, UNIT_V, CH0, 50, 2, 10 }, + { FLD_F, UNIT_HZ, CH0, 52, 2, 100 }, + { FLD_PAC, UNIT_W, CH0, 54, 2, 10 }, + { FLD_Q, UNIT_VAR, CH0, 56, 2, 10 }, // signed! + { FLD_IAC, UNIT_A, CH0, 58, 2, 100 }, + { FLD_PF, UNIT_NONE, CH0, 60, 2, 1000 }, + { FLD_T, UNIT_C, CH0, 62, 2, 10 }, // signed! + { FLD_EVT, UNIT_NONE, CH0, 64, 2, 1 }, + { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, + { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, + { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, + { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC } +}; +#define HMS4CH_LIST_LEN (sizeof(hms4chAssignment) / sizeof(byteAssign_t)) +#define HMS4CH_PAYLOAD_LEN 66 + +#endif /*__HMS_DEFINES_H__*/ From adb056fd4f93f1012f29e72bfbf11189ae31e4f4 Mon Sep 17 00:00:00 2001 From: Argafal Date: Mon, 20 Mar 2023 12:08:40 +0100 Subject: [PATCH 14/92] Parse power factor, Qvar as signed values --- src/hm/hmInverter.h | 6 +++--- src/hms/hmsDefines.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index bbe859de..3575e94a 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -264,9 +264,9 @@ class Inverter { val <<= 8; val |= buf[ptr]; } while(++ptr != end); - if (FLD_T == rec->assign[pos].fieldId) { - // temperature is a signed value! - rec->record[pos] = (REC_TYP)((int16_t)val) / (REC_TYP)(div); + if ((FLD_T == rec->assign[pos].fieldId) || (FLD_Q == rec->assign[pos].fieldId) || (FLD_PF == rec->assign[pos].fieldId)) { + // temperature, Qvar, and power factor are a signed values + rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div); } else if (FLD_YT == rec->assign[pos].fieldId) { rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div)) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); } else { diff --git a/src/hms/hmsDefines.h b/src/hms/hmsDefines.h index 2083783a..7246dd5b 100644 --- a/src/hms/hmsDefines.h +++ b/src/hms/hmsDefines.h @@ -43,7 +43,7 @@ const byteAssign_t hms4chAssignment[] = { { FLD_PAC, UNIT_W, CH0, 54, 2, 10 }, { FLD_Q, UNIT_VAR, CH0, 56, 2, 10 }, // signed! { FLD_IAC, UNIT_A, CH0, 58, 2, 100 }, - { FLD_PF, UNIT_NONE, CH0, 60, 2, 1000 }, + { FLD_PF, UNIT_NONE, CH0, 60, 2, 1000 }, // signed! { FLD_T, UNIT_C, CH0, 62, 2, 10 }, // signed! { FLD_EVT, UNIT_NONE, CH0, 64, 2, 1 }, { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, From c4e20b639589073c9d9f6b9d6820ee3b958cf2b0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 22 Mar 2023 23:14:03 +0100 Subject: [PATCH 15/92] improved HMS and CMT configuration reconnect on timeout (30s) introduced frequency ranges for EU --- src/hms/cmt2300a.h | 162 ++++++++++++++++++------------------------- src/hms/hmsPayload.h | 14 ++-- src/hms/hmsRadio.h | 71 +++++++------------ 3 files changed, 104 insertions(+), 143 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 83639070..58876af7 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -8,6 +8,15 @@ #include "esp32_3wSpi.h" +#define WORK_FREQ_KHZ 865000 // disired work frequency between DTU and + // inverter in kHz +#define HOY_BASE_FREQ_KHZ 860000 // in kHz +#define HOY_MAX_FREQ_KHZ 923500 // 0xFE * 250kHz + Base_freq +#define HOY_BOOT_FREQ_KHZ 868000 // Hoymiles boot/init frequency after power up inverter +#define FREQ_STEP_KHZ 250 // channel step size in kHz +#define FREQ_WARN_MIN_KHZ 863000 // for EU 863 - 870 MHz is allowed +#define FREQ_WARN_MAX_KHZ 870000 // for EU 863 - 870 MHz is allowed + // detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf #define CMT2300A_MASK_CFG_RETAIN 0x10 @@ -144,24 +153,24 @@ // default CMT paramters static uint8_t cmtConfig[0x60] PROGMEM { - // 0x00 - 0x0f - 0x00, 0x66, 0xEC, 0x1D, 0x70, 0x80, 0x14, 0x08, - 0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, + // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm + 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, + 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, // 0x10 - 0x1f 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, - 0x42, 0x6D, 0x80, 0x86, 0x42, 0x62, 0x27, 0x16, // 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, + 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default // 0x20 - 0x2f 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, - 0x9F, 0x4B, 0x0A, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x30 - 0x3f 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, // 0x40 - 0x4f - 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, // 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, + 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, - // 0x50 - 0x5f + // 0x50 - 0x5f - TX 13dBm 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, - 0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F + 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F }; enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO}; @@ -215,10 +224,7 @@ class Cmt2300a { else mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); - //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? -> if 0x02 last was read - // 0x07 last was write mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x02); - mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02); mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE @@ -272,33 +278,28 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); - //mCusIntFlag == mSpi.readReg(CMT2300A_CUS_INT_FLAG); - //if(0x00 == mCusIntFlag) { - // no data received - mSpi.readReg(CMT2300A_CUS_INT_CLR1); - mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); - mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); + // no data received + mSpi.readReg(CMT2300A_CUS_INT_CLR1); + mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); + mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); - //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? - mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); - mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); + //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? + mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); + mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); - mSpi.writeReg(0x45, 0x01); - mSpi.writeReg(0x46, len); // payload length + mSpi.writeReg(0x45, 0x01); + mSpi.writeReg(0x46, len); // payload length - mSpi.writeFifo(buf, len); + mSpi.writeFifo(buf, len); - // send only on base frequency: here 863.0 MHz - swichChannel((len != 15)); + // send only on base frequency: here 863.0 MHz + //switchChannel((len != 15)); - if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) - return CMT_ERR_SWITCH_STATE; + if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) + return CMT_ERR_SWITCH_STATE; - // wait for tx done - mTxPending = true; - //} - //else - // return CMT_ERR_RX_IN_FIFO; + // wait for tx done + mTxPending = true; return CMT_SUCCESS; } @@ -311,25 +312,13 @@ class Cmt2300a { if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; - //if(0xAA != mSpi.readReg(0x48)) - // mSpi.writeReg(0x48, 0xAA); - //mSpi.readReg(0x48); - //mSpi.writeReg(0x4c, 0x00); - - //if(0x52 != mSpi.readReg(CMT2300A_CUS_MODE_STA)) - mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52); - //if(0x20 != mSpi.readReg(0x62)) - mSpi.writeReg(0x62, 0x20); - //mSpi.readReg(0x0D); - //mSpi.writeReg(0x0F, 0x00); + mSpi.writeReg(CMT2300A_CUS_MODE_STA, 0x52); + mSpi.writeReg(0x62, 0x20); for(uint8_t i = 0; i < 0x60; i++) { mSpi.writeReg(i, cmtConfig[i]); } - //if(0x02 != mSpi.readReg(0x09)) - // mSpi.writeReg(0x09, 0x02); - mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 // interrupt 1 control selection to TX DONE @@ -343,10 +332,6 @@ class Cmt2300a { // interrupt enable (TX_DONE, PREAM_OK, SYNC_OK, CRC_OK, PKT_DONE) mSpi.writeReg(CMT2300A_CUS_INT_EN, 0x3B); - /*mSpi.writeReg(0x41, 0x48); - mSpi.writeReg(0x42, 0x5A); - mSpi.writeReg(0x43, 0x48); - mSpi.writeReg(0x44, 0x4D);*/ mSpi.writeReg(0x64, 0x64); if(0x00 == mSpi.readReg(CMT2300A_CUS_FIFO_CTL)) @@ -357,43 +342,44 @@ class Cmt2300a { delayMicroseconds(95); - // base frequency 863MHz; with value of CMT2300A_CUS_FREQ_CHNL - // the frequency can be increased in a step size of ~0.24Hz - /*mSpi.writeReg(0x18, 0x42); - mSpi.writeReg(0x19, 0x6D); - mSpi.writeReg(0x1A, 0x80); - mSpi.writeReg(0x1B, 0x86); - mSpi.writeReg(0x1C, 0x42); - mSpi.writeReg(0x1D, 0x62); - mSpi.writeReg(0x1E, 0x27); - mSpi.writeReg(0x1F, 0x16);*/ - - /*mSpi.writeReg(0x22, 0x20); - mSpi.writeReg(0x23, 0x20); - mSpi.writeReg(0x24, 0xD2); - mSpi.writeReg(0x25, 0x35); - mSpi.writeReg(0x26, 0x0C); - mSpi.writeReg(0x27, 0x0A); - mSpi.writeReg(0x28, 0x9F); - mSpi.writeReg(0x29, 0x4B); - mSpi.writeReg(0x27, 0x0A);*/ - if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; - /*mSpi.writeReg(0x03, 0x1D); - mSpi.writeReg(0x5C, 0x8A); - mSpi.writeReg(0x5D, 0x18);*/ - if(!cmtSwitchStatus(CMT2300A_GO_SLEEP, CMT2300A_STA_SLEEP)) return false; if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; + switchDtuFreq(WORK_FREQ_KHZ); + return true; } + inline uint8_t freq2Chan(const uint32_t freqKhz) { + if((freqKhz % FREQ_STEP_KHZ) != 0) { + DPRINT(DBG_WARN, F("swtich frequency to ")); + DBGPRINT(String(freqKhz)); + DBGPRINT(F("kHz not possible!")); + return 0xff; // error + // apply the nearest frequency + //freqKhz = (freqKhz + FREQ_STEP_KHZ/2) / FREQ_STEP_KHZ; + //freqKhz *= FREQ_STEP_KHZ; + } + + if((freqKhz < HOY_BASE_FREQ_KHZ) || (freqKhz > HOY_MAX_FREQ_KHZ)) + return 0xff; // error + + if((freqKhz < FREQ_WARN_MIN_KHZ) || (freqKhz > FREQ_WARN_MAX_KHZ)) + DPRINTLN(DBG_WARN, F("Disired frequency is out of EU legal range! (863 - 870MHz)")); + + return (freqKhz - HOY_BASE_FREQ_KHZ) / FREQ_STEP_KHZ; + } + + inline void switchChannel(uint8_t ch) { + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, ch); + } + private: void init() { mTxPending = false; @@ -415,23 +401,14 @@ class Cmt2300a { return false; } - inline void swichChannel(bool def = true, uint8_t start = 0x00, uint8_t end = 0x22) { - if(!def) { - if(++mCnt > 2) { - if(++mRxTxCh > end) - mRxTxCh = start; - mCnt = 0; - } - } - // 0: 868.00MHz - // 1: 868.23MHz - // 2: 868.46MHz - // 3: 868.72MHz - // 4: 868.97MHz - if(!def) - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mRxTxCh); - else - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); + inline bool switchDtuFreq(const uint32_t freqKhz) { + uint8_t toCh = freq2Chan(freqKhz); + if(0xff == toCh) + return false; + + switchChannel(toCh); + + return true; } inline uint8_t getChipStatus(void) { @@ -441,7 +418,6 @@ class Cmt2300a { SpiType mSpi; uint8_t mCnt; bool mTxPending; - uint8_t mRxTxCh; bool mInRxMode; uint8_t mCusIntFlag; }; diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 08737aaf..4a005874 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -11,6 +11,8 @@ #include "../config/config.h" #include +#define HMS_TIMEOUT_MS 30000 // 30s * 1000 + typedef struct { uint8_t txCmd; uint8_t txId; @@ -50,7 +52,7 @@ class HmsPayload { //mHighPrioIv = NULL; mCbAlarm = NULL; mCbPayload = NULL; - mFirst = true; + mLastRx = 0; } void enableSerialDebug(bool enable) { @@ -137,9 +139,10 @@ class HmsPayload { mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; }*/ - if(mFirst) { - mFirst = false; - mRadio->setIvBackChannel(&iv->radioId.u64); + DPRINT(DBG_INFO, "LastRx: "); + DBGPRINTLN(String(mLastRx)); + if((mLastRx + HMS_TIMEOUT_MS) < millis()) { + mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); } else { uint8_t cmd = iv->getQueuedCmd(); DPRINT(DBG_INFO, F("(#")); @@ -151,6 +154,7 @@ class HmsPayload { } void add(Inverter<> *iv, hmsPacket_t *p) { + mLastRx = millis(); if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command mPayload[iv->id].txId = p->data[1]; DPRINTLN(DBG_DEBUG, F("Response from info request received")); @@ -398,10 +402,10 @@ class HmsPayload { statistics_t *mStat; uint8_t mMaxRetrans; uint32_t *mTimestamp; + uint32_t mLastRx; hmsPayload_t mPayload[MAX_NUM_INVERTERS]; bool mSerialDebug; Inverter<> *mHighPrioIv; - bool mFirst; alarmListenerType mCbAlarm; payloadListenerType mCbPayload; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index a0e561aa..3c26263d 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -41,12 +41,6 @@ class CmtRadio { bool loop() { mCmt.loop(); - if(++mCnt > 30000) { - mCnt = 0; - if(NULL != mIvIdChannelSet) - prepareSwitchChannelCmd(mIvIdChannelSet); - } - if(!mIrqRcvd) return false; mIrqRcvd = false; @@ -66,14 +60,17 @@ class CmtRadio { mSerialDebug = true; } - void setIvBackChannel(const uint64_t *ivId) { - mIvIdChannelSet = ivId; - Serial.println("Byte 3 " + String(U32_B3((*mIvIdChannelSet) >> 8), HEX)); - Serial.println("Byte 2 " + String(U32_B2((*mIvIdChannelSet) >> 8), HEX)); - Serial.println("Byte 1 " + String(U32_B1((*mIvIdChannelSet) >> 8), HEX)); - Serial.println("Byte 0 " + String(U32_B0((*mIvIdChannelSet) >> 8), HEX)); - prepareSwitchChannelCmd(mIvIdChannelSet); + bool switchFrequency(const uint64_t *ivId, uint32_t fromkHz, uint32_t tokHz) { + uint8_t fromCh = mCmt.freq2Chan(fromkHz); + uint8_t toCh = mCmt.freq2Chan(tokHz); + if((0xff == fromCh) || (0xff == toCh)) + return false; + + mCmt.switchChannel(fromCh); + sendSwitchChCmd(ivId, toCh); + mCmt.switchChannel(toCh); + return true; } void prepareDevInformCmd(const uint64_t *ivId, uint8_t cmd, uint32_t ts, uint16_t alarmMesId, bool isRetransmit, uint8_t reqfld=TX_REQ_INFO) { // might not be necessary to add additional arg. @@ -87,22 +84,6 @@ class CmtRadio { sendPacket(24, isRetransmit); } - inline void prepareSwitchChannelCmd(const uint64_t *ivId, uint8_t freqSel = 0x0c) { - /** freqSel: - * 0x0c: 863.00 MHz - * 0x0d: 863.24 MHz - * 0x0e: 863.48 MHz - * 0x0f: 863.72 MHz - * 0x10: 863.96 MHz - * */ - initPacket(ivId, 0x56, 0x02); - mTxBuf[10] = 0x15; - mTxBuf[11] = 0x21; - mTxBuf[12] = freqSel; - mTxBuf[13] = 0x14; - sendPacket(14, false); - } - void sendPacket(uint8_t len, bool isRetransmit) { if (len > 14) { uint16_t crc = ah::crc16(&mTxBuf[10], len - 10); @@ -149,9 +130,23 @@ class CmtRadio { mSendCnt = 0; mRetransmits = 0; mSerialDebug = false; - mIvIdChannelSet = NULL; mIrqRcvd = false; - mCnt = 0; + } + + inline void sendSwitchChCmd(const uint64_t *ivId, uint8_t ch) { + /** ch: + * 0x0c: 863.00 MHz + * 0x0d: 863.24 MHz + * 0x0e: 863.48 MHz + * 0x0f: 863.72 MHz + * 0x10: 863.96 MHz + * */ + initPacket(ivId, 0x56, 0x02); + mTxBuf[10] = 0x15; + mTxBuf[11] = 0x21; + mTxBuf[12] = ch; + mTxBuf[13] = 0x14; + sendPacket(14, false); } void initPacket(const uint64_t *ivId, uint8_t mid, uint8_t pid) { @@ -180,27 +175,13 @@ class CmtRadio { uint8_t status = mCmt.getRx(p.data, 28, &p.rssi); if(CMT_SUCCESS == status) mBufCtrl.push(p); - if(NULL != mIvIdChannelSet) { - if(U32_B3((*mIvIdChannelSet) >> 8) != p.data[5]) - return; - if(U32_B2((*mIvIdChannelSet) >> 8) != p.data[4]) - return; - if(U32_B1((*mIvIdChannelSet) >> 8) != p.data[3]) - return; - if(U32_B0((*mIvIdChannelSet) >> 8) != p.data[2]) - return; - mIvIdChannelSet = NULL; - } } CmtType mCmt; uint32_t mDtuSn; uint8_t mTxBuf[27]; bool mSerialDebug; - const uint64_t *mIvIdChannelSet; bool mIrqRcvd; - - uint16_t mCnt; }; #endif /*__HMS_RADIO_H__*/ From 28c44168546d0b299dde75a652a11d16f21fd89c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 23 Mar 2023 17:36:38 +0100 Subject: [PATCH 16/92] improved, RX on SDR visible (865MHz) but not in Ahoy!? --- src/hms/cmt2300a.h | 47 +++++++++++++++++++++++++++++++++++++++++--- src/hms/hmsPayload.h | 2 ++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 58876af7..dbe16b24 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -24,6 +24,8 @@ #define CMT2300A_MASK_LOCKING_EN 0x20 #define CMT2300A_MASK_CHIP_MODE_STA 0x0F +#define CMT2300A_CUS_CMT10 0x09 + #define CMT2300A_CUS_MODE_CTL 0x60 // [7] go_switch // [6] go_tx // [5] go_tfs @@ -152,6 +154,28 @@ #define CMT2300A_MASK_PKT_OK_FLG 0x01 // default CMT paramters +/*static uint8_t cmtConfig[0x60] PROGMEM { + // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm + 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, + 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, + // 0x10 - 0x1f + 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, + 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default + // 0x20 - 0x2f + 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, + 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + // 0x30 - 0x3f + 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, + 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, + // 0x40 - 0x4f + 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, + // 0x50 - 0x5f + 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, + 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F // - TX 13dBm +};*/ + +// LP Settings static uint8_t cmtConfig[0x60] PROGMEM { // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, @@ -173,6 +197,7 @@ static uint8_t cmtConfig[0x60] PROGMEM { 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F }; + enum {CMT_SUCCESS = 0, CMT_ERR_SWITCH_STATE, CMT_ERR_TX_PENDING, CMT_FIFO_EMPTY, CMT_ERR_RX_IN_FIFO}; template @@ -292,8 +317,12 @@ class Cmt2300a { mSpi.writeFifo(buf, len); - // send only on base frequency: here 863.0 MHz - //switchChannel((len != 15)); + if(0xff != mRqstCh) { + DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(mRqstCh, HEX)); + mCurCh = mRqstCh; + mRqstCh = 0xff; + } + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mCurCh); if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) return CMT_ERR_SWITCH_STATE; @@ -319,6 +348,9 @@ class Cmt2300a { mSpi.writeReg(i, cmtConfig[i]); } + //uint8_t tmp = (~0x07) & mSpi.readReg(CMT2300A_CUS_CMT10); + //mSpi.writeReg(CMT2300A_CUS_CMT10, (tmp | 0x02)); + mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 // interrupt 1 control selection to TX DONE @@ -377,7 +409,13 @@ class Cmt2300a { } inline void switchChannel(uint8_t ch) { - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, ch); + mRqstCh = ch; + /*DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(ch, HEX)); + if(mInRxMode) + mInRxMode = false; + cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_SLEEP); + + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, ch);*/ } private: @@ -386,6 +424,8 @@ class Cmt2300a { mInRxMode = false; mCusIntFlag = 0x00; mCnt = 0; + mRqstCh = 0xff; + mCurCh = 0x20; } // CMT state machine, wait for next state, true on success @@ -420,6 +460,7 @@ class Cmt2300a { bool mTxPending; bool mInRxMode; uint8_t mCusIntFlag; + uint8_t mRqstCh, mCurCh; }; #endif /*__CMT2300A_H__*/ diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 4a005874..124b685a 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -142,7 +142,9 @@ class HmsPayload { DPRINT(DBG_INFO, "LastRx: "); DBGPRINTLN(String(mLastRx)); if((mLastRx + HMS_TIMEOUT_MS) < millis()) { + //mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, HOY_BOOT_FREQ_KHZ + FREQ_STEP_KHZ); mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); + mLastRx = millis() - (HMS_TIMEOUT_MS / 6); } else { uint8_t cmd = iv->getQueuedCmd(); DPRINT(DBG_INFO, F("(#")); From 38d01b704df42a469131810180e8001157d1efed Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 23 Mar 2023 18:32:55 +0100 Subject: [PATCH 17/92] further testing to re enable the communication --- src/hms/cmt2300a.h | 24 ++++++++++++------------ src/hms/hmsPayload.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index dbe16b24..03c61549 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -177,24 +177,24 @@ // LP Settings static uint8_t cmtConfig[0x60] PROGMEM { - // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm - 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, - 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, + // 0x00 - 0x0f + 0x00, 0x66, 0xEC, 0x1D, 0x70, 0x80, 0x14, 0x08, + 0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, // 0x10 - 0x1f 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, - 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 860MHz as default + 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, // 0x20 - 0x2f 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, - 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, + 0x9F, 0x4B, 0x0A, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x30 - 0x3f 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, // 0x40 - 0x4f - 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, + 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, // 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, - // 0x50 - 0x5f - TX 13dBm + // 0x50 - 0x5f 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, - 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F + 0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F }; @@ -235,6 +235,8 @@ class Cmt2300a { if(mInRxMode) return CMT_SUCCESS; + DPRINTLN(DBG_INFO, "goRX"); + mSpi.readReg(CMT2300A_CUS_INT1_CTL); mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); @@ -318,7 +320,7 @@ class Cmt2300a { mSpi.writeFifo(buf, len); if(0xff != mRqstCh) { - DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(mRqstCh, HEX)); + //DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(mRqstCh, HEX)); mCurCh = mRqstCh; mRqstCh = 0xff; } @@ -348,8 +350,6 @@ class Cmt2300a { mSpi.writeReg(i, cmtConfig[i]); } - //uint8_t tmp = (~0x07) & mSpi.readReg(CMT2300A_CUS_CMT10); - //mSpi.writeReg(CMT2300A_CUS_CMT10, (tmp | 0x02)); mSpi.writeReg(CMT2300A_CUS_IO_SEL, 0x20); // -> GPIO3_SEL[1:0] = 0x02 @@ -383,7 +383,7 @@ class Cmt2300a { if(!cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_STBY)) return false; - switchDtuFreq(WORK_FREQ_KHZ); + //switchDtuFreq(WORK_FREQ_KHZ); return true; } diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 124b685a..09dedf1c 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -142,7 +142,7 @@ class HmsPayload { DPRINT(DBG_INFO, "LastRx: "); DBGPRINTLN(String(mLastRx)); if((mLastRx + HMS_TIMEOUT_MS) < millis()) { - //mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, HOY_BOOT_FREQ_KHZ + FREQ_STEP_KHZ); + //mRadio->switchFrequency(&iv->radioId.u64, 863000, WORK_FREQ_KHZ); mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); mLastRx = millis() - (HMS_TIMEOUT_MS / 6); } else { From cd35ed9adf56c8e0543c9f087a0eb47fefc00fe4 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 24 Mar 2023 17:50:59 +0100 Subject: [PATCH 18/92] reenabled communication --- src/hms/cmt2300a.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 03c61549..cf1f023f 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -235,8 +235,6 @@ class Cmt2300a { if(mInRxMode) return CMT_SUCCESS; - DPRINTLN(DBG_INFO, "goRX"); - mSpi.readReg(CMT2300A_CUS_INT1_CTL); mSpi.writeReg(CMT2300A_CUS_INT1_CTL, CMT2300A_INT_SEL_TX_DONE); @@ -255,12 +253,10 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02); mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); // 863.0 MHz + //mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); // 863.0 MHz - if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) { - Serial.println("Go RX"); + if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) return CMT_ERR_SWITCH_STATE; - } mInRxMode = true; From d61b707a76b123d9ecbd4689d77a44fe8d126472 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 24 Mar 2023 18:05:33 +0100 Subject: [PATCH 19/92] switched config of cmt - RX still working --- src/hms/cmt2300a.h | 27 +-------------------------- src/hms/hmsPayload.h | 2 +- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index cf1f023f..5c1746de 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -154,7 +154,7 @@ #define CMT2300A_MASK_PKT_OK_FLG 0x01 // default CMT paramters -/*static uint8_t cmtConfig[0x60] PROGMEM { +static uint8_t cmtConfig[0x60] PROGMEM { // 0x00 - 0x0f -- RSSI offset +- 0 and 13dBm 0x00, 0x66, 0xEC, 0x1C, 0x70, 0x80, 0x14, 0x08, 0x11, 0x02, 0x02, 0x00, 0xAE, 0xE0, 0x35, 0x00, @@ -173,28 +173,6 @@ // 0x50 - 0x5f 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, 0x00, 0x07, 0x50, 0x00, 0x42, 0x0C, 0x3F, 0x7F // - TX 13dBm -};*/ - -// LP Settings -static uint8_t cmtConfig[0x60] PROGMEM { - // 0x00 - 0x0f - 0x00, 0x66, 0xEC, 0x1D, 0x70, 0x80, 0x14, 0x08, - 0x91, 0x02, 0x02, 0xD0, 0xAE, 0xE0, 0x35, 0x00, - // 0x10 - 0x1f - 0x00, 0xF4, 0x10, 0xE2, 0x42, 0x20, 0x0C, 0x81, - 0x42, 0x32, 0xCF, 0x82, 0x42, 0x27, 0x76, 0x12, // 0x42, 0xCF, 0xA7, 0x8C, 0x42, 0xC4, 0x4E, 0x1C, - // 0x20 - 0x2f - 0xA6, 0xC9, 0x20, 0x20, 0xD2, 0x35, 0x0C, 0x0A, - 0x9F, 0x4B, 0x0A, 0x29, 0xC0, 0x14, 0x05, 0x53, // 0x9F, 0x4B, 0x29, 0x29, 0xC0, 0x14, 0x05, 0x53, - // 0x30 - 0x3f - 0x10, 0x00, 0xB4, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x12, 0x1E, 0x00, 0xAA, 0x06, 0x00, 0x00, 0x00, - // 0x40 - 0x4f - 0x00, 0x48, 0x5A, 0x48, 0x4D, 0x01, 0x1D, 0x00, // 0x00, 0xD6, 0xD5, 0xD4, 0x2D, 0x01, 0x1D, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xC3, 0x00, 0x00, 0x60, - // 0x50 - 0x5f - 0xFF, 0x00, 0x00, 0x1F, 0x10, 0x70, 0x4D, 0x06, - 0x00, 0x07, 0x50, 0x00, 0x8A, 0x18, 0x3F, 0x7F }; @@ -253,8 +231,6 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x02); mSpi.writeReg(0x16, 0x0C); // [4:3]: RSSI_DET_SEL, [2:0]: RSSI_AVG_MODE - //mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, 0x00); // 863.0 MHz - if(!cmtSwitchStatus(CMT2300A_GO_RX, CMT2300A_STA_RX)) return CMT_ERR_SWITCH_STATE; @@ -316,7 +292,6 @@ class Cmt2300a { mSpi.writeFifo(buf, len); if(0xff != mRqstCh) { - //DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(mRqstCh, HEX)); mCurCh = mRqstCh; mRqstCh = 0xff; } diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 09dedf1c..bd87f181 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -149,7 +149,7 @@ class HmsPayload { uint8_t cmd = iv->getQueuedCmd(); DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); - DBGPRINT(F(") prepareDevInformCmd")); // + String(cmd, HEX)); + DBGPRINTLN(F(") prepareDevInformCmd")); // + String(cmd, HEX)); mRadio->prepareDevInformCmd(&iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; } From 23e848d2241995df126ce0185d84a1d10a56f5b0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 00:47:49 +0100 Subject: [PATCH 20/92] improved multi inverter fixed setup improved serial output --- src/hm/hmInverter.h | 2 +- src/hms/cmt2300a.h | 16 ++++++++-------- src/hms/hmsPayload.h | 20 +++++++++++++------- src/hms/hmsRadio.h | 18 ++++++++++-------- src/web/html/setup.html | 28 +++++++++++++++++++++++----- 5 files changed, 55 insertions(+), 29 deletions(-) diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 898df40a..01eb5700 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -145,7 +145,7 @@ class Inverter { void enqueCommand(uint8_t cmd) { _commandQueue.push(std::make_shared(cmd)); DPRINT_IVID(DBG_INFO, id); - DBGPRINTLN(F("enqueCommand: 0x")); + DBGPRINT(F("enqueCommand: 0x")); DBGHEXLN(cmd); } diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h index 5c1746de..95d62191 100644 --- a/src/hms/cmt2300a.h +++ b/src/hms/cmt2300a.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // 2023 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __CMT2300A_H__ @@ -282,7 +282,6 @@ class Cmt2300a { mSpi.writeReg(CMT2300A_CUS_INT_CLR1, 0x00); mSpi.writeReg(CMT2300A_CUS_INT_CLR2, 0x00); - //mSpi.readReg(CMT2300A_CUS_FIFO_CTL); // necessary? mSpi.writeReg(CMT2300A_CUS_FIFO_CTL, 0x07); mSpi.writeReg(CMT2300A_CUS_FIFO_CLR, 0x01); @@ -294,8 +293,8 @@ class Cmt2300a { if(0xff != mRqstCh) { mCurCh = mRqstCh; mRqstCh = 0xff; + mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mCurCh); } - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, mCurCh); if(!cmtSwitchStatus(CMT2300A_GO_TX, CMT2300A_STA_TX)) return CMT_ERR_SWITCH_STATE; @@ -381,12 +380,13 @@ class Cmt2300a { inline void switchChannel(uint8_t ch) { mRqstCh = ch; - /*DPRINTLN(DBG_INFO, "switchChannel: 0x" + String(ch, HEX)); - if(mInRxMode) - mInRxMode = false; - cmtSwitchStatus(CMT2300A_GO_STBY, CMT2300A_STA_SLEEP); + } - mSpi.writeReg(CMT2300A_CUS_FREQ_CHNL, ch);*/ + inline uint32_t getFreqKhz(void) { + if(0xff != mRqstCh) + return HOY_BASE_FREQ_KHZ + (mRqstCh * FREQ_STEP_KHZ); + else + return HOY_BASE_FREQ_KHZ + (mCurCh * FREQ_STEP_KHZ); } private: diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index bd87f181..ec2c492c 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // 2023 Ahoy, https://ahoydtu.de -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __HMS_PAYLOAD_H__ @@ -47,12 +47,13 @@ class HmsPayload { mTimestamp = timestamp; for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { reset(i); + mIvCmd56Cnt[i] = 0; } mSerialDebug = false; //mHighPrioIv = NULL; mCbAlarm = NULL; mCbPayload = NULL; - mLastRx = 0; + //mLastRx = 0; } void enableSerialDebug(bool enable) { @@ -139,13 +140,17 @@ class HmsPayload { mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; }*/ + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); DPRINT(DBG_INFO, "LastRx: "); - DBGPRINTLN(String(mLastRx)); - if((mLastRx + HMS_TIMEOUT_MS) < millis()) { + DBGPRINTLN(String(rec->ts)); + if(((rec->ts + HMS_TIMEOUT_MS) < millis()) && (mIvCmd56Cnt[iv->id] < 3)) { //mRadio->switchFrequency(&iv->radioId.u64, 863000, WORK_FREQ_KHZ); mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); - mLastRx = millis() - (HMS_TIMEOUT_MS / 6); + mIvCmd56Cnt[iv->id]++; + //mLastRx = millis() - (HMS_TIMEOUT_MS / 6); } else { + if(++mIvCmd56Cnt[iv->id] == 10) + mIvCmd56Cnt[iv->id] = 0; uint8_t cmd = iv->getQueuedCmd(); DPRINT(DBG_INFO, F("(#")); DBGPRINT(String(iv->id)); @@ -156,7 +161,7 @@ class HmsPayload { } void add(Inverter<> *iv, hmsPacket_t *p) { - mLastRx = millis(); + //mLastRx = millis(); if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command mPayload[iv->id].txId = p->data[1]; DPRINTLN(DBG_DEBUG, F("Response from info request received")); @@ -404,8 +409,9 @@ class HmsPayload { statistics_t *mStat; uint8_t mMaxRetrans; uint32_t *mTimestamp; - uint32_t mLastRx; + //uint32_t mLastRx; hmsPayload_t mPayload[MAX_NUM_INVERTERS]; + uint8_t mIvCmd56Cnt[MAX_NUM_INVERTERS]; bool mSerialDebug; Inverter<> *mHighPrioIv; diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 3c26263d..ae376758 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // 2023 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __HMS_RADIO_H__ @@ -95,8 +95,8 @@ class CmtRadio { if(mSerialDebug) { DPRINT(DBG_INFO, F("TX ")); - DBGPRINT(String(len)); - DBGPRINT(F(" | ")); + DBGPRINT(String(mCmt.getFreqKhz()/1000.0f)); + DBGPRINT(F("Mhz | ")); ah::dumpBuf(mTxBuf, len); } @@ -135,11 +135,13 @@ class CmtRadio { inline void sendSwitchChCmd(const uint64_t *ivId, uint8_t ch) { /** ch: - * 0x0c: 863.00 MHz - * 0x0d: 863.24 MHz - * 0x0e: 863.48 MHz - * 0x0f: 863.72 MHz - * 0x10: 863.96 MHz + * 0x00: 860.00 MHz + * 0x01: 860.25 MHz + * 0x02: 860.50 MHz + * ... + * 0x14: 865.00 MHz + * ... + * 0x28: 870.00 MHz * */ initPacket(ivId, 0x56, 0x02); mTxBuf[10] = 0x15; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 8d47abc6..13de33e6 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -629,7 +629,19 @@ } function parseNrfRadio(obj, type) { - var e = document.getElementById("rf24").append( + var e = document.getElementById("rf24"); + pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; + for(p of pins) { + e.append( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), + ml("div", {class: "col-12 col-sm-9"}, + sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ) + ]) + ); + } + e.append( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, "Power Level"), ml("div", {class: "col-12 col-sm-9"}, @@ -650,14 +662,20 @@ en.checked = obj["en"]; e.append( - lbl("cmtEnable", "CMT2300A Enable"), - en, br() + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-8 col-sm-3 my-2"}, "CMT2300A Enable"), + ml("div", {class: "col-4 col-sm-9"}, en) + ]) ); pins = [['csb', 'pinCsb'], ['fcsb', 'pinFcsb'], ['irq', 'pinGpio3']]; for(p of pins) { e.append( - lbl(p[1], p[0].toUpperCase()), - sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), + ml("div", {class: "col-12 col-sm-9"}, + sel(p[1], ("ESP8266" == type) ? esp8266pins : esp32pins, obj[p[0]]) + ) + ]) ); } } From 694d4bb58bd27c861652c27ebf64dc191799fb5f Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 00:58:32 +0100 Subject: [PATCH 21/92] fix save settings --- src/app.h | 4 ++++ src/web/web.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/app.h b/src/app.h index 95c63225..18b3ca82 100644 --- a/src/app.h +++ b/src/app.h @@ -82,6 +82,10 @@ class app : public IApp, public ah::Scheduler { mShowRebootRequest = true; // only message on index, no reboot mSavePending = true; mSaveReboot = reboot; + if(reboot) { + onWifi(false); + ah::Scheduler::resetTicker(); + } once(std::bind(&app::tickSave, this), 3, "save"); return true; } diff --git a/src/web/web.h b/src/web/web.h index 9a233a74..d4e58e70 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -600,7 +600,7 @@ class Web { mApp->saveSettings((request->arg("reboot") == "on")); - AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), system_html, save_html_len); + AsyncWebServerResponse *response = request->beginResponse_P(200, F("text/html; charset=UTF-8"), save_html, save_html_len); response->addHeader(F("Content-Encoding"), "gzip"); request->send(response); } From 98ba3b8a680020d25e48bc76c00857fe98b50335 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 13:35:25 +0200 Subject: [PATCH 22/92] fix communication --- src/hms/hmsPayload.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index ec2c492c..6ae2a42a 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -143,7 +143,7 @@ class HmsPayload { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); DPRINT(DBG_INFO, "LastRx: "); DBGPRINTLN(String(rec->ts)); - if(((rec->ts + HMS_TIMEOUT_MS) < millis()) && (mIvCmd56Cnt[iv->id] < 3)) { + if(((rec->ts + HMS_TIMEOUT_MS) < *mTimestamp) && (mIvCmd56Cnt[iv->id] < 3)) { //mRadio->switchFrequency(&iv->radioId.u64, 863000, WORK_FREQ_KHZ); mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); mIvCmd56Cnt[iv->id]++; From e4f100660bdff05ae752b7ad285ece04d3184b30 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 13:58:58 +0200 Subject: [PATCH 23/92] further improvement --- src/hms/hmsPayload.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 6ae2a42a..61d80ed8 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -11,7 +11,7 @@ #include "../config/config.h" #include -#define HMS_TIMEOUT_MS 30000 // 30s * 1000 +#define HMS_TIMEOUT_SEC 30 // 30s * 1000 typedef struct { uint8_t txCmd; @@ -141,13 +141,10 @@ class HmsPayload { mPayload[iv->id].txCmd = cmd; }*/ record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - DPRINT(DBG_INFO, "LastRx: "); - DBGPRINTLN(String(rec->ts)); - if(((rec->ts + HMS_TIMEOUT_MS) < *mTimestamp) && (mIvCmd56Cnt[iv->id] < 3)) { + if(((rec->ts + HMS_TIMEOUT_SEC) < *mTimestamp) && (mIvCmd56Cnt[iv->id] < 3)) { //mRadio->switchFrequency(&iv->radioId.u64, 863000, WORK_FREQ_KHZ); mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); mIvCmd56Cnt[iv->id]++; - //mLastRx = millis() - (HMS_TIMEOUT_MS / 6); } else { if(++mIvCmd56Cnt[iv->id] == 10) mIvCmd56Cnt[iv->id] = 0; @@ -161,7 +158,6 @@ class HmsPayload { } void add(Inverter<> *iv, hmsPacket_t *p) { - //mLastRx = millis(); if (p->data[1] == (TX_REQ_INFO + ALL_FRAMES)) { // response from get information command mPayload[iv->id].txId = p->data[1]; DPRINTLN(DBG_DEBUG, F("Response from info request received")); @@ -343,6 +339,7 @@ class HmsPayload { } iv->setQueuedCmdFinished(); + reset(iv->id); } } yield(); From 60bc9dd55256159fe2551ee92edb7d09282cea3e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 14:23:26 +0200 Subject: [PATCH 24/92] next improvement --- src/hms/hmsRadio.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index ae376758..db73dd9f 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -41,9 +41,9 @@ class CmtRadio { bool loop() { mCmt.loop(); - if(!mIrqRcvd) + if(0x00 != mIrqRcvd) return false; - mIrqRcvd = false; + mIrqRcvd--; getRx(); mCmt.goRx(); return true; @@ -53,7 +53,7 @@ class CmtRadio { } void handleIntr(void) { - mIrqRcvd = true; + mIrqRcvd++; } void enableDebug() { @@ -130,7 +130,7 @@ class CmtRadio { mSendCnt = 0; mRetransmits = 0; mSerialDebug = false; - mIrqRcvd = false; + mIrqRcvd = 0; } inline void sendSwitchChCmd(const uint64_t *ivId, uint8_t ch) { @@ -183,7 +183,7 @@ class CmtRadio { uint32_t mDtuSn; uint8_t mTxBuf[27]; bool mSerialDebug; - bool mIrqRcvd; + volatile uint8_t mIrqRcvd; }; #endif /*__HMS_RADIO_H__*/ From 7afd0b80feb1c87ac9ac57331e05bc543f9bae9c Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 26 Mar 2023 15:11:45 +0200 Subject: [PATCH 25/92] improve communication --- src/hms/hmsRadio.h | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index db73dd9f..8c6bf8af 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -41,19 +41,22 @@ class CmtRadio { bool loop() { mCmt.loop(); - if(0x00 != mIrqRcvd) + if((!mIrqRcvd) && (!mRqstGetRx)) return false; - mIrqRcvd--; getRx(); - mCmt.goRx(); - return true; + if(CMT_SUCCESS == mCmt.goRx()) { + mIrqRcvd = false; + mRqstGetRx = false; + return true; + } else + return false; } void tickSecond() { } void handleIntr(void) { - mIrqRcvd++; + mIrqRcvd = true; } void enableDebug() { @@ -130,7 +133,8 @@ class CmtRadio { mSendCnt = 0; mRetransmits = 0; mSerialDebug = false; - mIrqRcvd = 0; + mIrqRcvd = false; + mRqstGetRx = false; } inline void sendSwitchChCmd(const uint64_t *ivId, uint8_t ch) { @@ -149,6 +153,7 @@ class CmtRadio { mTxBuf[12] = ch; mTxBuf[13] = 0x14; sendPacket(14, false); + mRqstGetRx = true; } void initPacket(const uint64_t *ivId, uint8_t mid, uint8_t pid) { @@ -183,7 +188,8 @@ class CmtRadio { uint32_t mDtuSn; uint8_t mTxBuf[27]; bool mSerialDebug; - volatile uint8_t mIrqRcvd; + bool mIrqRcvd; + bool mRqstGetRx; }; #endif /*__HMS_RADIO_H__*/ From fbeabf7358c7c00c4d6878a2bbcdd1d4a67e3676 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 27 Mar 2023 15:24:25 +0200 Subject: [PATCH 26/92] fix WebUI --- src/web/html/setup.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 7d910c91..6157d63d 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -676,7 +676,7 @@ } } - function parseNrfRadio(obj, type) { + function parseNrfRadio(obj, type, system) { var e = document.getElementById("rf24"); if ("ESP8266" == type) { pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; @@ -708,7 +708,7 @@ ); } - function parseCmtRadio(obj, type) { + function parseCmtRadio(obj, type, system) { var e = document.getElementById("cmt"); var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); en.checked = obj["en"]; @@ -817,9 +817,9 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); - parseNrfRadio(root["radioNrf"], root["system"]["esp_type"]); + parseNrfRadio(root["radioNrf"], root["system"]["esp_type"], root["system"]); if(root["generic"]["esp_type"] == "ESP32") - parseCmtRadio(root["radioCmt"], root["system"]["esp_type"]); + parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); parseSerial(root["serial"]); parseDisplay(root["display"], root["system"]["esp_type"], root["system"]); getAjax("/api/inverter/list", parseIv); From e82099a8a8203ec52d8d43a8cab05a2644a4a164 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 30 Mar 2023 12:57:06 +0200 Subject: [PATCH 27/92] fix HMS RX --- src/app.cpp | 2 +- src/hms/hmsPayload.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 2a9189d3..858a310d 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -166,7 +166,7 @@ void app::loopStandard(void) { mCmtRadio.mBufCtrl.pop(); yield(); } - //mHmsPayload.process(true); + mHmsPayload.process(false); //true } #endif mPayload.loop(); diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 61d80ed8..023fef0f 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -339,7 +339,6 @@ class HmsPayload { } iv->setQueuedCmdFinished(); - reset(iv->id); } } yield(); From bfae0e0defe389b1523fb006fa38d2d66b2248d6 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 6 Apr 2023 12:16:23 +0200 Subject: [PATCH 28/92] basic implementation of improv --- src/app.cpp | 3 +++ src/app.h | 16 ++-------------- src/hm/hmRadio.h | 2 +- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 9ec6ff26..4d775473 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -82,6 +82,8 @@ void app::setup() { mPubSerial.setup(mConfig, &mSys, &mTimestamp); + mImprov.setup(mConfig->sys.deviceName, mVersion); + regularTickers(); @@ -169,6 +171,7 @@ void app::regularTickers(void) { if (mConfig->plugin.display.type != 0) everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); + everySec(std::bind(&Improv::tickSerial, &mImprov), "impro"); } //----------------------------------------------------------------------------- diff --git a/src/app.h b/src/app.h index 5ea40968..146e2210 100644 --- a/src/app.h +++ b/src/app.h @@ -22,6 +22,7 @@ #include "utils/crc.h" #include "utils/dbg.h" #include "utils/scheduler.h" +#include "utils/improv.h" #include "web/RestApi.h" #include "web/web.h" #include "wifi/ahoywifi.h" @@ -243,20 +244,6 @@ class app : public IApp, public ah::Scheduler { void tickMinute(void); void tickZeroValues(void); void tickMidnight(void); - /*void tickSerial(void) { - if(Serial.available() == 0) - return; - - uint8_t buf[80]; - uint8_t len = Serial.readBytes(buf, 80); - DPRINTLN(DBG_INFO, "got serial data, len: " + String(len)); - for(uint8_t i = 0; i < len; i++) { - if((0 != i) && (i % 8 == 0)) - DBGPRINTLN(""); - DBGPRINT(String(buf[i], HEX) + " "); - } - DBGPRINTLN(""); - }*/ innerLoopCb mInnerLoopCb; @@ -269,6 +256,7 @@ class app : public IApp, public ah::Scheduler { PayloadType mPayload; MiPayloadType mMiPayload; PubSerialType mPubSerial; + Improv mImprov; char mVersion[12]; settings mSettings; diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index c37ab7d0..602d76a1 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // 2023 Ahoy, https://github.com/lumpapu/ahoy -// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/ +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed //----------------------------------------------------------------------------- #ifndef __RADIO_H__ From 62c9cb7529df766e7f4c906663d0959c828a9b0c Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 6 Apr 2023 23:29:56 +0200 Subject: [PATCH 29/92] add missing file --- src/utils/improv.h | 173 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 src/utils/improv.h diff --git a/src/utils/improv.h b/src/utils/improv.h new file mode 100644 index 00000000..2ed16599 --- /dev/null +++ b/src/utils/improv.h @@ -0,0 +1,173 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://github.com/lumpapu/ahoy +// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#ifndef __IMPROV_H__ +#define __IMPROV_H__ + +#include +#include +#include "dbg.h" + +// https://www.improv-wifi.com/serial/ +// https://github.com/jnthas/improv-wifi-demo/blob/main/src/esp32-wifiimprov/esp32-wifiimprov.ino + +// configure ESP through Serial interface +class Improv { + public: + void setup(const char *devName, const char *version) { + mDevName = devName; + mVersion = version; + } + + void tickSerial(void) { + if(Serial.available() == 0) + return; + + uint8_t buf[80]; + uint8_t len = Serial.readBytes(buf, 80); + dumpBuf(buf, len); + + if(!checkPaket(&buf[0], 13, [this](uint8_t type, uint8_t buf[], uint8_t len) { + parsePayload(type, buf, len); + })) { + DBGPRINT(F("checkHeader failed")); + } + } + + private: + enum State : uint8_t { + STATE_STOPPED = 0x00, + STATE_AWAITING_AUTHORIZATION = 0x01, + STATE_AUTHORIZED = 0x02, + STATE_PROVISIONING = 0x03, + STATE_PROVISIONED = 0x04, + }; + + enum Command : uint8_t { + UNKNOWN = 0x00, + WIFI_SETTINGS = 0x01, + IDENTIFY = 0x02, + GET_CURRENT_STATE = 0x02, + GET_DEVICE_INFO = 0x03, + GET_WIFI_NETWORKS = 0x04, + BAD_CHECKSUM = 0xFF, + }; + + enum ImprovSerialType : uint8_t { + TYPE_CURRENT_STATE = 0x01, + TYPE_ERROR_STATE = 0x02, + TYPE_RPC = 0x03, + TYPE_RPC_RESPONSE = 0x04 + }; + + void dumpBuf(uint8_t buf[], uint8_t len) { + for(uint8_t i = 0; i < len; i++) { + DHEX(buf[i]); + DBGPRINT(" "); + } + DBGPRINTLN(""); + } + + inline uint8_t buildChecksum(uint8_t buf[], uint8_t len) { + uint8_t calc = 0; + for(uint8_t i = 0; i < (len - 1); i++) { + calc += buf[i]; + } + return calc; + } + + inline bool checkChecksum(uint8_t buf[], uint8_t len) { + return ((buildChecksum(buf, len)) == buf[len]); + } + + bool checkPaket(uint8_t buf[], uint8_t len, std::function cb) { + if(len < 11) + return false; + + if(0 != strncmp((char*)buf, "IMPROV", 6)) + return false; + + // verison check (only version 1 is supported!) + if(0x01 != buf[6]) + return false; + + if(!checkChecksum(buf, (6+3 + buf[9]))) + return false; + + cb(buf[7], &buf[9], buf[8]); + + return true; + } + + uint8_t char2Improv(const char *str, uint8_t buf[]) { + uint8_t len = strlen(str); + buf[0] = len; + for(uint8_t i = 1; i <= len; i++) { + buf[i] = (uint8_t)str[i-1]; + } + return len + 1; + } + + void sendDevInfo(void) { + uint8_t buf[100]; + buf[7] = TYPE_RPC_RESPONSE; + buf[9] = GET_DEVICE_INFO; // repsonse to cmd + uint8_t p = 11; + // firmware name + p += char2Improv("AhoyDTU", &buf[p]); + // firmware version + p += char2Improv(mVersion, &buf[p]); + // chip variant + #if defined(ESP32) + p += char2Improv("ESP32", &buf[p]); + #else + p += char2Improv("ESP8266", &buf[p]); + #endif + // device name + p += char2Improv(mDevName, &buf[p]); + + buf[10] = p - 11; // sub length + buf[8] = p - 9; // paket length + + sendPaket(buf, p); + } + + void setState(uint8_t state) { + uint8_t buf[20]; + buf[7] = TYPE_CURRENT_STATE; + buf[8] = 0x01; + buf[9] = state; + sendPaket(buf, 10); + } + + void sendPaket(uint8_t buf[], uint8_t len) { + buf[0] = 'I'; + buf[1] = 'M'; + buf[2] = 'P'; + buf[3] = 'R'; + buf[4] = 'O'; + buf[5] = 'V'; + buf[6] = 1; // protocol version + + buf[len] = buildChecksum(buf, (len+1)); + len++; + dumpBuf(buf, len); + Serial.write(buf, len); + } + + void parsePayload(uint8_t type, uint8_t buf[], uint8_t len) { + DBGPRINTLN(F("parsePayload")); + if(TYPE_RPC == type) { + if(GET_CURRENT_STATE == buf[0]) + setState(0x00); + else if(GET_DEVICE_INFO == buf[0]) + sendDevInfo(); + } + } + + const char *mDevName, *mVersion; +}; + +#endif /*__IMPROV_H__*/ From ba3f84d6845a012d0b019a7074fa74d8bc47125a Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 7 Apr 2023 01:16:29 +0200 Subject: [PATCH 30/92] improv: first two commands are working (state and device info) --- src/app.cpp | 3 ++- src/utils/dbg.h | 18 ++++++++++-------- src/utils/improv.h | 30 ++++++++++++++++-------------- 3 files changed, 28 insertions(+), 23 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 571d933a..7f2fefd7 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -98,6 +98,7 @@ void app::setup() { //----------------------------------------------------------------------------- void app::loop(void) { mInnerLoopCb(); + mImprov.tickSerial(); } //----------------------------------------------------------------------------- @@ -173,7 +174,7 @@ void app::regularTickers(void) { if (mConfig->plugin.display.type != 0) everySec(std::bind(&DisplayType::tickerSecond, &mDisplay), "disp"); every(std::bind(&PubSerialType::tick, &mPubSerial), mConfig->serial.interval, "uart"); - everySec(std::bind(&Improv::tickSerial, &mImprov), "impro"); + //everySec(std::bind(&Improv::tickSerial, &mImprov), "impro"); } //----------------------------------------------------------------------------- diff --git a/src/utils/dbg.h b/src/utils/dbg.h index 4716d7ae..53c9f79e 100644 --- a/src/utils/dbg.h +++ b/src/utils/dbg.h @@ -49,21 +49,23 @@ #endif //template - inline void DBGPRINT(String str) { DSERIAL.print(str); if(NULL != mCb) mCb(str); } + inline void DBGPRINT(String str, bool ser = true) { if(ser) DSERIAL.print(str); if(NULL != mCb) mCb(str); } //template - inline void DBGPRINTLN(String str) { DBGPRINT(str); DBGPRINT(F("\r\n")); } - inline void DHEX(uint8_t b) { - if( b<0x10 ) DSERIAL.print(F("0")); - DSERIAL.print(b,HEX); + inline void DBGPRINTLN(String str, bool ser = true) { DBGPRINT(str); DBGPRINT(F("\r\n")); } + inline void DHEX(uint8_t b, bool ser = true) { + if(ser) { + if( b<0x10 ) DSERIAL.print(F("0")); + DSERIAL.print(b,HEX); + } if(NULL != mCb) { if( b<0x10 ) mCb(F("0")); mCb(String(b, HEX)); } } - inline void DBGHEXLN(uint8_t b) { - DHEX(b); - DBGPRINT(F("\r\n")); + inline void DBGHEXLN(uint8_t b, bool ser = true) { + DHEX(b, ser); + DBGPRINT(F("\r\n"), ser); } /*inline void DHEX(uint16_t b) { if( b<0x10 ) DSERIAL.print(F("000")); diff --git a/src/utils/improv.h b/src/utils/improv.h index 2ed16599..c3b8c87c 100644 --- a/src/utils/improv.h +++ b/src/utils/improv.h @@ -25,15 +25,15 @@ class Improv { if(Serial.available() == 0) return; - uint8_t buf[80]; - uint8_t len = Serial.readBytes(buf, 80); - dumpBuf(buf, len); + uint8_t buf[40]; + uint8_t len = Serial.readBytes(buf, 40); - if(!checkPaket(&buf[0], 13, [this](uint8_t type, uint8_t buf[], uint8_t len) { + if(!checkPaket(&buf[0], len, [this](uint8_t type, uint8_t buf[], uint8_t len) { parsePayload(type, buf, len); })) { - DBGPRINT(F("checkHeader failed")); + DBGPRINTLN(F("check paket failed")); } + dumpBuf(buf, len); } private: @@ -64,21 +64,24 @@ class Improv { void dumpBuf(uint8_t buf[], uint8_t len) { for(uint8_t i = 0; i < len; i++) { - DHEX(buf[i]); - DBGPRINT(" "); + DHEX(buf[i], false); + DBGPRINT(" ", false); } - DBGPRINTLN(""); + DBGPRINTLN("", false); } inline uint8_t buildChecksum(uint8_t buf[], uint8_t len) { uint8_t calc = 0; - for(uint8_t i = 0; i < (len - 1); i++) { + for(uint8_t i = 0; i < len; i++) { calc += buf[i]; } return calc; } inline bool checkChecksum(uint8_t buf[], uint8_t len) { + /*DHEX(buf[len], false); + DBGPRINT(F(" == "), false); + DBGHEXLN(buildChecksum(buf, len), false);*/ return ((buildChecksum(buf, len)) == buf[len]); } @@ -93,7 +96,7 @@ class Improv { if(0x01 != buf[6]) return false; - if(!checkChecksum(buf, (6+3 + buf[9]))) + if(!checkChecksum(buf, (9 + buf[8]))) return false; cb(buf[7], &buf[9], buf[8]); @@ -151,17 +154,16 @@ class Improv { buf[5] = 'V'; buf[6] = 1; // protocol version - buf[len] = buildChecksum(buf, (len+1)); + buf[len] = buildChecksum(buf, len); len++; - dumpBuf(buf, len); Serial.write(buf, len); + dumpBuf(buf, len); } void parsePayload(uint8_t type, uint8_t buf[], uint8_t len) { - DBGPRINTLN(F("parsePayload")); if(TYPE_RPC == type) { if(GET_CURRENT_STATE == buf[0]) - setState(0x00); + setState(STATE_AUTHORIZED); else if(GET_DEVICE_INFO == buf[0]) sendDevInfo(); } From efe3bc4d20326cb6efed51d98679ba897eec0dfa Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 7 Apr 2023 02:00:19 +0200 Subject: [PATCH 31/92] improv does not open complete menu every time --- src/app.cpp | 2 +- src/app.h | 4 ++-- src/appInterface.h | 2 +- src/utils/dbg.cpp | 1 + src/utils/dbg.h | 9 ++++++-- src/utils/improv.h | 50 ++++++++++++++++++++++++++++++++++++++++--- src/wifi/ahoywifi.cpp | 6 ++++-- src/wifi/ahoywifi.h | 2 +- 8 files changed, 64 insertions(+), 12 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 7f2fefd7..001b18f6 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -84,7 +84,7 @@ void app::setup() { mPubSerial.setup(mConfig, &mSys, &mTimestamp); - mImprov.setup(mConfig->sys.deviceName, mVersion); + mImprov.setup(this, mConfig->sys.deviceName, mVersion); regularTickers(); diff --git a/src/app.h b/src/app.h index 010758c4..9a73ddcd 100644 --- a/src/app.h +++ b/src/app.h @@ -101,8 +101,8 @@ class app : public IApp, public ah::Scheduler { mWifi.scanAvailNetworks(); } - void getAvailNetworks(JsonObject obj) { - mWifi.getAvailNetworks(obj); + bool getAvailNetworks(JsonObject obj) { + return mWifi.getAvailNetworks(obj); } void setOnUpdate() { diff --git a/src/appInterface.h b/src/appInterface.h index 44491d91..a3240189 100644 --- a/src/appInterface.h +++ b/src/appInterface.h @@ -25,7 +25,7 @@ class IApp { virtual const char *getVersion() = 0; virtual statistics_t *getStatistics() = 0; virtual void scanAvailNetworks() = 0; - virtual void getAvailNetworks(JsonObject obj) = 0; + virtual bool getAvailNetworks(JsonObject obj) = 0; virtual uint32_t getUptime() = 0; virtual uint32_t getTimestamp() = 0; diff --git a/src/utils/dbg.cpp b/src/utils/dbg.cpp index 9f7c9fd3..e7ae4581 100644 --- a/src/utils/dbg.cpp +++ b/src/utils/dbg.cpp @@ -1,3 +1,4 @@ #include "dbg.h" DBG_CB mCb = NULL; +bool mDebugEn = true; diff --git a/src/utils/dbg.h b/src/utils/dbg.h index 53c9f79e..8ce23db9 100644 --- a/src/utils/dbg.h +++ b/src/utils/dbg.h @@ -39,6 +39,7 @@ #ifdef ARDUINO #define DBG_CB std::function extern DBG_CB mCb; + extern bool mDebugEn; inline void registerDebugCb(DBG_CB cb) { mCb = cb; @@ -48,12 +49,16 @@ #define DSERIAL Serial #endif + inline void setDebugEn(bool en) { + mDebugEn = en; + } + //template - inline void DBGPRINT(String str, bool ser = true) { if(ser) DSERIAL.print(str); if(NULL != mCb) mCb(str); } + inline void DBGPRINT(String str, bool ser = true) { if(ser && mDebugEn) DSERIAL.print(str); if(NULL != mCb) mCb(str); } //template inline void DBGPRINTLN(String str, bool ser = true) { DBGPRINT(str); DBGPRINT(F("\r\n")); } inline void DHEX(uint8_t b, bool ser = true) { - if(ser) { + if(ser && mDebugEn) { if( b<0x10 ) DSERIAL.print(F("0")); DSERIAL.print(b,HEX); } diff --git a/src/utils/improv.h b/src/utils/improv.h index c3b8c87c..ade1291e 100644 --- a/src/utils/improv.h +++ b/src/utils/improv.h @@ -9,6 +9,7 @@ #include #include #include "dbg.h" +#include "AsyncJson.h" // https://www.improv-wifi.com/serial/ // https://github.com/jnthas/improv-wifi-demo/blob/main/src/esp32-wifiimprov/esp32-wifiimprov.ino @@ -16,12 +17,18 @@ // configure ESP through Serial interface class Improv { public: - void setup(const char *devName, const char *version) { + void setup(IApp *app, const char *devName, const char *version) { + mApp = app; mDevName = devName; mVersion = version; + + mScanRunning = false; } void tickSerial(void) { + if(mScanRunning) + getNetworks(); + if(Serial.available() == 0) return; @@ -114,7 +121,7 @@ class Improv { } void sendDevInfo(void) { - uint8_t buf[100]; + uint8_t buf[50]; buf[7] = TYPE_RPC_RESPONSE; buf[9] = GET_DEVICE_INFO; // repsonse to cmd uint8_t p = 11; @@ -137,6 +144,37 @@ class Improv { sendPaket(buf, p); } + void getNetworks(void) { + if(!mScanRunning) + mApp->scanAvailNetworks(); + + JsonObject obj; + if(!mApp->getAvailNetworks(obj)) + return; + + mScanRunning = false; + + uint8_t buf[50]; + buf[7] = TYPE_RPC_RESPONSE; + buf[9] = GET_WIFI_NETWORKS; // repsonse to cmd + uint8_t p = 11; + + JsonArray arr = obj[F("networks")]; + for(uint8_t i = 0; i < arr.size(); i++) { + buf[p++] = strlen(arr[i][F("ssid")]); + // ssid + p += char2Improv(arr[i][F("ssid")], &buf[p]); + buf[p++] = String(arr[i][F("rssi")]).length(); + // rssi + p += char2Improv(String(arr[i][F("rssi")]).c_str(), &buf[p]); + + buf[10] = p - 11; // sub length + buf[8] = p - 9; // paket length + + sendPaket(buf, p); + } + } + void setState(uint8_t state) { uint8_t buf[20]; buf[7] = TYPE_CURRENT_STATE; @@ -162,14 +200,20 @@ class Improv { void parsePayload(uint8_t type, uint8_t buf[], uint8_t len) { if(TYPE_RPC == type) { - if(GET_CURRENT_STATE == buf[0]) + if(GET_CURRENT_STATE == buf[0]) { + setDebugEn(false); setState(STATE_AUTHORIZED); + } else if(GET_DEVICE_INFO == buf[0]) sendDevInfo(); + else if(GET_WIFI_NETWORKS == buf[0]) + getNetworks(); } } + IApp *mApp; const char *mDevName, *mVersion; + bool mScanRunning; }; #endif /*__IMPROV_H__*/ diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 08c19070..f590f67e 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -274,12 +274,12 @@ void ahoywifi::scanAvailNetworks(void) { } //----------------------------------------------------------------------------- -void ahoywifi::getAvailNetworks(JsonObject obj) { +bool ahoywifi::getAvailNetworks(JsonObject obj) { JsonArray nets = obj.createNestedArray("networks"); int n = WiFi.scanComplete(); if (n < 0) - return; + return false; if(n > 0) { int sort[n]; sortRSSI(&sort[0], n); @@ -292,6 +292,8 @@ void ahoywifi::getAvailNetworks(JsonObject obj) { WiFi.scanDelete(); if(mStaConn == IN_AP_MODE) WiFi.mode(WIFI_AP); + + return true; } //----------------------------------------------------------------------------- diff --git a/src/wifi/ahoywifi.h b/src/wifi/ahoywifi.h index 3a3a35a8..3fde2ab3 100644 --- a/src/wifi/ahoywifi.h +++ b/src/wifi/ahoywifi.h @@ -27,7 +27,7 @@ class ahoywifi { void tickWifiLoop(void); bool getNtpTime(void); void scanAvailNetworks(void); - void getAvailNetworks(JsonObject obj); + bool getAvailNetworks(JsonObject obj); private: typedef enum WiFiStatus { From d7eb4a0b982f7ca8a10ecf5db51394229f4ccc2b Mon Sep 17 00:00:00 2001 From: tastendruecker123 <111116980+tastendruecker123@users.noreply.github.com> Date: Mon, 17 Apr 2023 16:56:24 +0200 Subject: [PATCH 32/92] added option to reboot ahoy every 24 hours --- src/app.cpp | 8 ++++++++ src/config/settings.h | 4 ++++ src/web/RestApi.h | 1 + src/web/html/setup.html | 5 +++++ src/web/web.h | 1 + 5 files changed, 19 insertions(+) diff --git a/src/app.cpp b/src/app.cpp index d2d87f50..742b2fd2 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -193,6 +193,14 @@ void app::tickNtpUpdate(void) { uint32_t midTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time onceAt(std::bind(&app::tickMidnight, this), midTrig, "midNi"); } + if (mConfig->sys.schedReboot) { + uint32_t localTime = gTimezone.toLocal(mTimestamp); + uint32_t rebootTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86410); // reboot 10 secs after midnght + if (rebootTrig <= mTimestamp) { //necessary for times other than midnight to prevent reboot loop + rebootTrig += 86400; + } + onceAt(std::bind(&app::tickReboot, this), rebootTrig, "midRe"); + } } nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min diff --git a/src/config/settings.h b/src/config/settings.h index d04fdce5..c88565d4 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -64,6 +64,7 @@ typedef struct { char adminPwd[PWD_LEN]; uint16_t protectionMask; bool darkMode; + bool schedReboot; // wifi char stationSsid[SSID_LEN]; @@ -338,6 +339,7 @@ class settings { mCfg.sys.protectionMask = DEF_PROT_INDEX | DEF_PROT_LIVE | DEF_PROT_SERIAL | DEF_PROT_SETUP | DEF_PROT_UPDATE | DEF_PROT_SYSTEM | DEF_PROT_API | DEF_PROT_MQTT; mCfg.sys.darkMode = false; + mCfg.sys.schedReboot = true; // restore temp settings if(keepWifi) memcpy(&mCfg.sys, &tmp, sizeof(cfgSys_t)); @@ -409,6 +411,7 @@ class settings { obj[F("adm")] = mCfg.sys.adminPwd; obj[F("prot_mask")] = mCfg.sys.protectionMask; obj[F("dark")] = mCfg.sys.darkMode; + obj[F("reb")] = mCfg.sys.schedReboot; ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf); ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf); ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf); @@ -421,6 +424,7 @@ class settings { getChar(obj, F("adm"), mCfg.sys.adminPwd, PWD_LEN); getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask); getVal(obj, F("dark"), &mCfg.sys.darkMode); + getVal(obj, F("reb"), &mCfg.sys.schedReboot); if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); if(obj.containsKey(F("mask"))) ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); if(obj.containsKey(F("dns1"))) ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index fde8c7a4..57bf7a7c 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -207,6 +207,7 @@ class RestApi { obj[F("ssid")] = mConfig->sys.stationSsid; obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; + obj[F("sched_reboot")] = (bool)mConfig->sys.schedReboot; obj[F("mac")] = WiFi.macAddress(); obj[F("hostname")] = mConfig->sys.deviceName; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 77769fdd..cd3c5a5a 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -28,6 +28,10 @@
Device Name
+
+
Reboot Ahoy at midnight
+
+
Dark Mode
@@ -606,6 +610,7 @@ for(var i of [["device", "device_name"], ["ssid", "ssid"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; document.getElementsByName("darkMode")[0].checked = obj["dark_mode"]; + document.getElementsByName("schedReboot")[0].checked = obj["sched_reboot"]; e = document.getElementsByName("adminpwd")[0]; if(!obj["pwd_set"]) e.value = ""; diff --git a/src/web/web.h b/src/web/web.h index 056b9e7c..45138760 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -451,6 +451,7 @@ class Web { if (request->arg("device") != "") request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN); mConfig->sys.darkMode = (request->arg("darkMode") == "on"); + mConfig->sys.schedReboot = (request->arg("schedReboot") == "on"); // protection if (request->arg("adminpwd") != "{PWD}") { From b8533cc17d51ff4d1d6505d025b9626b9b185312 Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 21 Apr 2023 00:17:17 +0200 Subject: [PATCH 33/92] several HMS / HMT related changes --- src/app.cpp | 4 +- src/config/settings.h | 10 +-- src/hm/hmDefines.h | 10 +-- src/hm/hmInverter.h | 6 ++ src/hm/hmSystem.h | 27 ++++--- src/hm/miPayload.h | 10 +-- src/hms/hmsDefines.h | 155 +++++++++++++++++++++++++++++++++++++--- src/hms/hmsPayload.h | 4 +- src/web/html/setup.html | 15 ++-- src/web/web.h | 10 ++- 10 files changed, 204 insertions(+), 47 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index db4a9ea1..380860fa 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -162,7 +162,7 @@ void app::loopStandard(void) { Inverter<> *iv = mSys.findInverter(&p->data[2]); if(NULL != iv) { - if(IV_HMS == iv->ivGen) + if((iv->ivGen == IV_HMS) || (iv->ivGen == IV_HMT)) mHmsPayload.add(iv, p); } mCmtRadio.mBufCtrl.pop(); @@ -405,7 +405,7 @@ void app::tickSend(void) { else if(iv->ivGen == IV_MI) mMiPayload.ivSend(iv); #if defined(ESP32) - else if(iv->ivGen == IV_HMS) + else if((iv->ivGen == IV_HMS) || (iv->ivGen == IV_HMT)) mHmsPayload.ivSend(iv); #endif } diff --git a/src/config/settings.h b/src/config/settings.h index 2abeb4b0..ae00883a 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -129,9 +129,9 @@ typedef struct { bool enabled; char name[MAX_NAME_LENGTH]; serial_u serial; - uint16_t chMaxPwr[4]; - int32_t yieldCor[4]; // signed YieldTotal correction value - char chName[4][MAX_NAME_LENGTH]; + uint16_t chMaxPwr[6]; + int32_t yieldCor[6]; // signed YieldTotal correction value + char chName[6][MAX_NAME_LENGTH]; } cfgIv_t; typedef struct { @@ -634,7 +634,7 @@ class settings { obj[F("en")] = (bool)cfg->enabled; obj[F("name")] = cfg->name; obj[F("sn")] = cfg->serial.u64; - for(uint8_t i = 0; i < 4; i++) { + for(uint8_t i = 0; i < 6; i++) { obj[F("yield")][i] = cfg->yieldCor[i]; obj[F("pwr")][i] = cfg->chMaxPwr[i]; obj[F("chName")][i] = cfg->chName[i]; @@ -643,7 +643,7 @@ class settings { getVal(obj, F("en"), &cfg->enabled); getChar(obj, F("name"), cfg->name, MAX_NAME_LENGTH); getVal(obj, F("sn"), &cfg->serial.u64); - for(uint8_t i = 0; i < 4; i++) { + for(uint8_t i = 0; i < (sizeof(obj[F("yield")])/sizeof(int32_t)); i++) { if(obj.containsKey(F("yield"))) cfg->yieldCor[i] = obj[F("yield")][i]; if(obj.containsKey(F("pwr"))) cfg->chMaxPwr[i] = obj[F("pwr")][i]; if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index d5630077..abe03b24 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -18,13 +18,15 @@ const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var" // 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_PF, FLD_EFF, + FLD_UAC, FLD_UAC_1N, FLD_UAC_2N, FLD_UAC_3N, FLD_UAC_12, FLD_UAC_23, FLD_UAC_31, FLD_IAC, + FLD_IAC_1, FLD_IAC_2, FLD_IAC_3, FLD_PAC, FLD_F, FLD_T, FLD_PF, FLD_EFF, FLD_IRR, FLD_Q, FLD_EVT, FLD_FW_VERSION, FLD_FW_BUILD_YEAR, FLD_FW_BUILD_MONTH_DAY, FLD_FW_BUILD_HOUR_MINUTE, FLD_HW_ID, FLD_ACT_ACTIVE_PWR_LIMIT, /*FLD_ACT_REACTIVE_PWR_LIMIT, FLD_ACT_PF,*/ FLD_LAST_ALARM_CODE}; const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", "YieldTotal", - "U_AC", "I_AC", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", + "U_AC", "U_AC_1N", "U_AC_2N", "U_AC_3N", "UAC_12", "UAC_23", "UAC_31", "I_AC", + "IAC_1", "I_AC_2", "I_AC_3", "P_AC", "F_AC", "Temp", "PF_AC", "Efficiency", "Irradiation","Q_AC", "ALARM_MES_ID","FWVersion","FWBuildYear","FWBuildMonthDay","FWBuildHourMinute","HWPartId", "active_PowerLimit", /*"reactivePowerLimit","Powerfactor",*/ "LastAlarmCode"}; const char* const notAvail = "n/a"; @@ -67,9 +69,9 @@ enum {CMD_CALC = 0xffff}; // CH0 is default channel (freq, ac, temp) -enum {CH0 = 0, CH1, CH2, CH3, CH4}; +enum {CH0 = 0, CH1, CH2, CH3, CH4, CH5, CH6}; -enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH}; +enum {INV_TYPE_1CH = 0, INV_TYPE_2CH, INV_TYPE_4CH, INV_TYPE_6CH}; typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 35435b3b..8e162274 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -445,6 +445,12 @@ class Inverter { } channels = 4; } + else if (INV_TYPE_6CH == type) { + rec->length = (uint8_t)(HMT6CH_LIST_LEN); + rec->assign = (byteAssign_t *)hmt6chAssignment; + rec->pyldLen = HMT6CH_PAYLOAD_LEN; + channels = 6; + } else { rec->length = 0; rec->assign = NULL; diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 0508a6e0..a5a22885 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -29,9 +29,10 @@ class HmSystem { DBGPRINT("HMS"); else DBGPRINT("HM"); - } else { + } else if(iv->config->serial.b[5] == 0x13) + DBGPRINT("HMT"); + else DBGPRINT(((iv->config->serial.b[4] & 0x03) == 0x01) ? " (2nd Gen) " : " (3rd Gen) "); - } DBGPRINTLN(String(iv->config->serial.u64, HEX)); @@ -55,13 +56,21 @@ class HmSystem { DPRINTLN(DBG_VERBOSE, " " + String(p->config->serial.b[4], HEX)); if((p->config->serial.b[5] == 0x11) || (p->config->serial.b[5] == 0x10)) { switch(p->config->serial.b[4]) { + case 0x24: // HMS-500 case 0x22: - case 0x21: p->type = INV_TYPE_1CH; break; + case 0x21: p->type = INV_TYPE_1CH; + break; + + case 0x44: // HMS-1000 case 0x42: - case 0x41: p->type = INV_TYPE_2CH; break; - case 0x64: // HMS2000 + case 0x41: p->type = INV_TYPE_2CH; + break; + + case 0x64: // HMS-2000 case 0x62: - case 0x61: p->type = INV_TYPE_4CH; break; + case 0x61: p->type = INV_TYPE_4CH; + break; + default: DPRINTLN(DBG_ERROR, F("unknown inverter type")); break; @@ -77,8 +86,10 @@ class HmSystem { p->ivGen = IV_HM; else // MI 2nd Gen p->ivGen = IV_MI; - } - else if(p->config->serial.u64 != 0ULL) + } else if(p->config->serial.b[5] == 0x13) { + p->ivGen = IV_HMT; + p->type = INV_TYPE_6CH; + } else if(p->config->serial.u64 != 0ULL) DPRINTLN(DBG_ERROR, F("inverter type can't be detected!")); p->init(); diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index a2368ad0..b42d4ae2 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -148,10 +148,10 @@ class MiPayload { if (cmd == 0x01 || cmd == SystemConfigPara ) { //0x1 and 0x05 for HM-types cmd = 0x0f; // for MI, these seem to make part of the Polling the device software and hardware version number command cmd2 = cmd == SystemConfigPara ? 0x01 : 0x00; //perhaps we can only try to get second frame? - mRadio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); + mRadio->sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); } else { //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd2, mPayload[iv->id].ts, iv->alarmMesIndex, false, cmd); - mRadio.sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); + mRadio->sendCmdPacket(iv->radioId.u64, cmd, cmd2, false, false); }; mPayload[iv->id].txCmd = cmd; @@ -442,7 +442,7 @@ const byteAssign_t InfoAssignment[] = { mPayload[iv->id].retransmits = mMaxRetrans; } else if ( cmd == 0x0f ) { //hard/firmware request - mRadio.sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false); + mRadio->sendCmdPacket(iv->radioId.u64, 0x0f, 0x00, true, false); //iv->setQueuedCmdFinished(); //cmd = iv->getQueuedCmd(); } else { @@ -479,7 +479,7 @@ const byteAssign_t InfoAssignment[] = { } DBGPRINT(F(" 0x")); DBGHEXLN(cmd); - mRadio.sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false); + mRadio->sendCmdPacket(iv->radioId.u64, cmd, cmd, true, false); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, true, cmd); yield(); } @@ -497,7 +497,7 @@ const byteAssign_t InfoAssignment[] = { DBGPRINT(F("prepareDevInformCmd 0x")); DBGHEXLN(mPayload[iv->id].txCmd); //mSys->Radio.prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); - mRadio.sendCmdPacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false); + mRadio->sendCmdPacket(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].txCmd, false, false); } } /*else { // payload complete diff --git a/src/hms/hmsDefines.h b/src/hms/hmsDefines.h index 7246dd5b..7f27a4fd 100644 --- a/src/hms/hmsDefines.h +++ b/src/hms/hmsDefines.h @@ -9,33 +9,97 @@ #include "../hm/hmDefines.h" //------------------------------------- -// HMS2000 +// HMS-350, HMS-500 +//------------------------------------- +const byteAssign_t hms1chAssignment[] = { + { 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_YT, UNIT_KWH, CH1, 8, 4, 1000 }, + { FLD_YD, UNIT_WH, CH1, 12, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + + { FLD_UAC, UNIT_V, CH0, 14, 2, 10 }, + { FLD_F, UNIT_HZ, CH0, 16, 2, 100 }, + { FLD_PAC, UNIT_W, CH0, 18, 2, 10 }, + { FLD_Q, UNIT_VAR, CH0, 20, 2, 10 }, // signed! + { FLD_IAC, UNIT_A, CH0, 22, 2, 100 }, + { FLD_PF, UNIT_NONE, CH0, 24, 2, 1000 }, // signed! + { FLD_T, UNIT_C, CH0, 26, 2, 10 }, // signed! + { FLD_EVT, UNIT_NONE, CH0, 28, 2, 1 }, + + { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, + { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, + { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, + { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC } +}; +#define HMS1CH_LIST_LEN (sizeof(hms1chAssignment) / sizeof(byteAssign_t)) +#define HMS1CH_PAYLOAD_LEN 30 + +//------------------------------------- +// HMS-800, HMS-1000 +//------------------------------------- +const byteAssign_t hms2chAssignment[] = { + { FLD_UDC, UNIT_V, CH1, 2, 2, 10 }, + { FLD_IDC, UNIT_A, CH1, 6, 2, 100 }, + { FLD_PDC, UNIT_W, CH1, 10, 2, 10 }, + { FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 }, + { FLD_YD, UNIT_WH, CH1, 22, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH2, 4, 2, 10 }, + { FLD_IDC, UNIT_A, CH2, 8, 2, 100 }, + { FLD_PDC, UNIT_W, CH2, 12, 2, 10 }, + { FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 }, + { FLD_YD, UNIT_WH, CH2, 24, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC }, + + { FLD_UAC, UNIT_V, CH0, 26, 2, 10 }, + { FLD_F, UNIT_HZ, CH0, 28, 2, 100 }, + { FLD_PAC, UNIT_W, CH0, 30, 2, 10 }, + { FLD_Q, UNIT_VAR, CH0, 32, 2, 10 }, // signed! + { FLD_IAC, UNIT_A, CH0, 34, 2, 100 }, + { FLD_PF, UNIT_NONE, CH0, 36, 2, 1000 }, // signed! + { FLD_T, UNIT_C, CH0, 38, 2, 10 }, // signed! + { FLD_EVT, UNIT_NONE, CH0, 40, 2, 1 }, + { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, + { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, + { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, + { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC } +}; +#define HMS2CH_LIST_LEN (sizeof(hms2chAssignment) / sizeof(byteAssign_t)) +#define HMS2CH_PAYLOAD_LEN 42 + +//------------------------------------- +// HMS-1800, HMS-2000 //------------------------------------- const byteAssign_t hms4chAssignment[] = { { FLD_UDC, UNIT_V, CH1, 2, 2, 10 }, - { FLD_UDC, UNIT_V, CH2, 4, 2, 10 }, { FLD_IDC, UNIT_A, CH1, 6, 2, 100 }, - { FLD_IDC, UNIT_A, CH2, 8, 2, 100 }, { FLD_PDC, UNIT_W, CH1, 10, 2, 10 }, - { FLD_PDC, UNIT_W, CH2, 12, 2, 10 }, { FLD_YT, UNIT_KWH, CH1, 14, 4, 1000 }, - { FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 }, { FLD_YD, UNIT_WH, CH1, 22, 2, 1 }, - { FLD_YD, UNIT_WH, CH2, 24, 2, 1 }, { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH2, 4, 2, 10 }, + { FLD_IDC, UNIT_A, CH2, 8, 2, 100 }, + { FLD_PDC, UNIT_W, CH2, 12, 2, 10 }, + { FLD_YT, UNIT_KWH, CH2, 18, 4, 1000 }, + { FLD_YD, UNIT_WH, CH2, 24, 2, 1 }, { FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC }, { FLD_UDC, UNIT_V, CH3, 26, 2, 10 }, - { FLD_UDC, UNIT_V, CH4, 28, 2, 10 }, { FLD_IDC, UNIT_A, CH3, 30, 2, 100 }, - { FLD_IDC, UNIT_A, CH4, 32, 2, 100 }, { FLD_PDC, UNIT_W, CH3, 34, 2, 10 }, - { FLD_PDC, UNIT_W, CH4, 36, 2, 10 }, { FLD_YT, UNIT_KWH, CH3, 38, 4, 1000 }, - { FLD_YT, UNIT_KWH, CH4, 42, 4, 1000 }, { FLD_YD, UNIT_WH, CH3, 46, 2, 1 }, - { FLD_YD, UNIT_WH, CH4, 48, 2, 1 }, { FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH4, 28, 2, 10 }, + { FLD_IDC, UNIT_A, CH4, 32, 2, 100 }, + { FLD_PDC, UNIT_W, CH4, 36, 2, 10 }, + { FLD_YT, UNIT_KWH, CH4, 42, 4, 1000 }, + { FLD_YD, UNIT_WH, CH4, 48, 2, 1 }, { FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC }, { FLD_UAC, UNIT_V, CH0, 50, 2, 10 }, @@ -54,4 +118,73 @@ const byteAssign_t hms4chAssignment[] = { #define HMS4CH_LIST_LEN (sizeof(hms4chAssignment) / sizeof(byteAssign_t)) #define HMS4CH_PAYLOAD_LEN 66 +//------------------------------------- +// HMT-1800, HMT-2250 +//------------------------------------- +const byteAssign_t hmt6chAssignment[] = { + { 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_YT, UNIT_KWH, CH1, 12, 4, 1000 }, + { FLD_YD, UNIT_WH, CH1, 20, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH1, CALC_IRR_CH, CH1, CMD_CALC }, + + { 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_YT, UNIT_KWH, CH2, 16, 4, 1000 }, + { FLD_YD, UNIT_WH, CH2, 22, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH2, CALC_IRR_CH, CH2, CMD_CALC }, + + { 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_YT, UNIT_KWH, CH3, 34, 4, 1000 }, + { FLD_YD, UNIT_WH, CH3, 42, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH3, CALC_IRR_CH, CH3, CMD_CALC }, + + { 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_YT, UNIT_KWH, CH4, 38, 4, 1000 }, + { FLD_YD, UNIT_WH, CH4, 44, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH4, CALC_IRR_CH, CH4, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH5, 46, 2, 10 }, + { FLD_IDC, UNIT_A, CH5, 48, 2, 100 }, + { FLD_PDC, UNIT_W, CH5, 52, 2, 10 }, + { FLD_YT, UNIT_KWH, CH5, 56, 4, 1000 }, + { FLD_YD, UNIT_WH, CH5, 64, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH5, CALC_IRR_CH, CH5, CMD_CALC }, + + { FLD_UDC, UNIT_V, CH6, CALC_UDC_CH, CH5, CMD_CALC }, + { FLD_IDC, UNIT_A, CH6, 50, 2, 100 }, + { FLD_PDC, UNIT_W, CH6, 54, 2, 10 }, + { FLD_YT, UNIT_KWH, CH6, 60, 4, 1000 }, + { FLD_YD, UNIT_WH, CH6, 66, 2, 1 }, + { FLD_IRR, UNIT_PCT, CH6, CALC_IRR_CH, CH6, CMD_CALC }, + + { FLD_UAC_1N, UNIT_V, CH0, 68, 2, 10 }, + { FLD_UAC_2N, UNIT_V, CH0, 70, 2, 10 }, + { FLD_UAC_3N, UNIT_V, CH0, 72, 2, 10 }, + { FLD_UAC_12, UNIT_V, CH0, 74, 2, 10 }, + { FLD_UAC_23, UNIT_V, CH0, 76, 2, 10 }, + { FLD_UAC_31, UNIT_V, CH0, 78, 2, 10 }, + { FLD_F, UNIT_HZ, CH0, 80, 2, 100 }, + { FLD_PAC, UNIT_W, CH0, 82, 2, 10 }, + { FLD_Q, UNIT_VAR, CH0, 84, 2, 10 }, + { FLD_IAC_1, UNIT_A, CH0, 86, 2, 100 }, + { FLD_IAC_2, UNIT_A, CH0, 88, 2, 100 }, + { FLD_IAC_3, UNIT_A, CH0, 90, 2, 100 }, + { FLD_PF, UNIT_NONE, CH0, 92, 2, 1000 }, + { FLD_T, UNIT_C, CH0, 94, 2, 10 }, + { FLD_EVT, UNIT_NONE, CH0, 96, 2, 1 }, + { FLD_YD, UNIT_WH, CH0, CALC_YD_CH0, 0, CMD_CALC }, + { FLD_YT, UNIT_KWH, CH0, CALC_YT_CH0, 0, CMD_CALC }, + { FLD_PDC, UNIT_W, CH0, CALC_PDC_CH0, 0, CMD_CALC }, + { FLD_EFF, UNIT_PCT, CH0, CALC_EFF_CH0, 0, CMD_CALC } +}; +#define HMT6CH_LIST_LEN (sizeof(hmt6chAssignment) / sizeof(byteAssign_t)) +#define HMT6CH_PAYLOAD_LEN 98 + #endif /*__HMS_DEFINES_H__*/ diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index 023fef0f..d71863b3 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -80,7 +80,7 @@ class HmsPayload { } void ivSend(Inverter<> *iv, bool highPrio = false) { - if (IV_HMS != iv->ivGen) // only process HMS inverters + if ((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) // only process HMS inverters return; //if(!highPrio) { @@ -215,7 +215,7 @@ class HmsPayload { if (NULL == iv) continue; // skip to next inverter - if (IV_HMS != iv->ivGen) // only process HMS inverters + if ((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) // only process HMS inverters continue; // skip to next inverter if ((mPayload[iv->id].txId != (TX_REQ_INFO + ALL_FRAMES)) && (0 != mPayload[iv->id].txId)) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 6ce72a44..6f821faf 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -410,7 +410,7 @@ [1, "high active"], ]; - const re = /11[2,4,6][1,2,4].*/; + const re = /1[1,3][2,4,6,8][1,2,4].*/; window.onload = function() { for(it of document.getElementsByClassName("s_collapsible")) { @@ -432,7 +432,7 @@ document.getElementById("btnAdd").addEventListener("click", function() { if(highestId <= (maxInv-1)) { - ivHtml(JSON.parse('{"enabled":true,"name":"","serial":"","channels":4,"ch_max_pwr":[0,0,0,0],"ch_name":["","","",""],"ch_yield_cor":[0,0,0,0]}'), highestId); + ivHtml(JSON.parse('{"enabled":true,"name":"","serial":"","channels":6,"ch_max_pwr":[0,0,0,0,0,0],"ch_name":["","","","","",""],"ch_yield_cor":[0,0,0,0,0,0]}'), highestId); } }); @@ -539,7 +539,7 @@ addr.addEventListener(evt, (e) => { var serial = addr.value.substring(0,4); var max = 0; - for(var i=0;i<4;i++) { + for(var i=0;i<6;i++) { setHide(id+"ModPwr"+i, true); setHide(id+"ModName"+i, true); setHide(id+"YieldCor"+i, true); @@ -549,16 +549,13 @@ setHide("row"+id+"YieldCor", true); if(serial.charAt(0) == 1) { - if((serial.charAt(1) == 0) || (serial.charAt(1) == 1)) { - if((serial.charAt(3) == 1) || (serial.charAt(3) == 2)) { + if((serial.charAt(1) == 0) || (serial.charAt(1) == 1) || (serial.charAt(1) == 3)) { + if((serial.charAt(3) == 1) || (serial.charAt(3) == 2) || (serial.charAt(3) == 4)) { switch(serial.charAt(2)) { case "2": max = 1; break; case "4": max = 2; break; case "6": max = 4; break; - } - } else if(serial.charAt(2) == 6) { - switch(serial.charAt(3)) { - case "4": max = 4; break; + case "8": max = 6; break; } } } diff --git a/src/web/web.h b/src/web/web.h index b4c6cd8d..815bc550 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -487,8 +487,16 @@ class Web { memset(buf, 0, 20); iv->config->serial.u64 = ah::Serial2u64(buf); switch(iv->config->serial.b[4]) { + case 0x24: + case 0x22: case 0x21: iv->type = INV_TYPE_1CH; iv->channels = 1; break; + + case 0x44: + case 0x42: case 0x41: iv->type = INV_TYPE_2CH; iv->channels = 2; break; + + case 0x64: + case 0x62: case 0x61: iv->type = INV_TYPE_4CH; iv->channels = 4; break; default: break; } @@ -497,7 +505,7 @@ class Web { request->arg("inv" + String(i) + "Name").toCharArray(iv->config->name, MAX_NAME_LENGTH); // max channel power / name - for (uint8_t j = 0; j < 4; j++) { + for (uint8_t j = 0; j < 6; j++) { iv->config->yieldCor[j] = request->arg("inv" + String(i) + "YieldCor" + String(j)).toInt(); iv->config->chMaxPwr[j] = request->arg("inv" + String(i) + "ModPwr" + String(j)).toInt() & 0xffff; request->arg("inv" + String(i) + "ModName" + String(j)).toCharArray(iv->config->chName[j], MAX_NAME_LENGTH); From 8c67f59eed53064ebfbbd65d58c6bc5749a28471 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 24 Apr 2023 21:42:31 +0200 Subject: [PATCH 34/92] small enhancement for esp8266 (compile) --- src/hms/esp32_3wSpi.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 8d8c062a..2be85724 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -148,6 +148,14 @@ class esp32_3wSpi { spi_device_handle_t spi_reg, spi_fifo; bool mInitialized; }; +#else + template + class esp32_3wSpi { + public: + esp32_3wSpi() {} + void setup() {} + void loop() {} + }; #endif #endif /*__ESP32_3WSPI_H__*/ From 27f16c4e915fee4b573d444f1884d054fffd8478 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 25 Apr 2023 20:37:43 +0200 Subject: [PATCH 35/92] Improved ESP8266 support for HMS version (same code base: only ESP32 supports HMS!) --- src/app.cpp | 24 ++++++++++++------------ src/app.h | 12 +++++++++--- src/defines.h | 2 +- src/main.cpp | 4 ++++ src/web/html/setup.html | 16 +++++++++++++--- 5 files changed, 39 insertions(+), 19 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 380860fa..8834ea25 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -61,22 +61,20 @@ void app::setup() { mMiPayload.enableSerialDebug(mConfig->serial.debug); mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); - if(!mNrfRadio.isChipConnected()) - DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); - } - //if(mConfig->cmt.enabled) { + #if defined(ESP32) mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); mHmsPayload.enableSerialDebug(mConfig->serial.debug); mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); - //} - + #endif /*DBGPRINTLN("--- after payload"); DBGPRINTLN(String(ESP.getFreeHeap())); DBGPRINTLN(String(ESP.getHeapFragmentation())); DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ - //if (!mSys.Radio.isChipConnected()) - // DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); + if(mConfig->nrf.enabled) { + if (!mSys.Radio.isChipConnected()) + DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); + } // when WiFi is in client mode, then enable mqtt broker #if !defined(AP_ONLY) @@ -371,10 +369,12 @@ void app::tickMidnight(void) { //----------------------------------------------------------------------------- void app::tickSend(void) { - /*if(!mNrfRadio.isChipConnected()) { - DPRINTLN(DBG_WARN, F("NRF24 not connected!")); - return; - }*/ + if(mConfig->nrf.enabled) { + if(!mNrfRadio.isChipConnected()) { + DPRINTLN(DBG_WARN, F("NRF24 not connected!")); + return; + } + } if (mIVCommunicationOn) { if (!mNrfRadio.mBufCtrl.empty()) { if (mConfig->serial.debug) { diff --git a/src/app.h b/src/app.h index 25fde351..24abde39 100644 --- a/src/app.h +++ b/src/app.h @@ -36,11 +36,13 @@ #define ASIN(x) (degrees(asin(x))) #define ACOS(x) (degrees(acos(x))) -typedef CmtRadio> CmtRadioType; typedef HmSystem HmSystemType; typedef HmPayload> PayloadType; typedef MiPayload> MiPayloadType; +#ifdef ESP32 +typedef CmtRadio> CmtRadioType; typedef HmsPayload HmsPayloadType; +#endif typedef Web WebType; typedef RestApi> RestApiType; typedef PubMqtt PubMqttType; @@ -66,9 +68,11 @@ class app : public IApp, public ah::Scheduler { mNrfRadio.handleIntr(); } + #ifdef ESP32 void handleHmsIntr(void) { mCmtRadio.handleIntr(); } + #endif uint32_t getUptime() { return Scheduler::getUptime(); @@ -299,7 +303,6 @@ class app : public IApp, public ah::Scheduler { HmSystemType mSys; HmRadio<> mNrfRadio; - CmtRadioType mCmtRadio; bool mShowRebootRequest; bool mIVCommunicationOn; @@ -309,8 +312,11 @@ class app : public IApp, public ah::Scheduler { RestApiType mApi; PayloadType mPayload; MiPayloadType mMiPayload; - HmsPayloadType mHmsPayload; PubSerialType mPubSerial; + #ifdef ESP32 + CmtRadioType mCmtRadio; + HmsPayloadType mHmsPayload; + #endif char mVersion[12]; settings mSettings; diff --git a/src/defines.h b/src/defines.h index 93722b6c..916977d2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 6 -#define VERSION_PATCH 9 +#define VERSION_PATCH 10 //------------------------------------- typedef struct { diff --git a/src/main.cpp b/src/main.cpp index f780a002..c7d2a52d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,9 +14,11 @@ IRAM_ATTR void handleIntr(void) { } //----------------------------------------------------------------------------- +#ifdef ESP32 IRAM_ATTR void handleHmsIntr(void) { myApp.handleHmsIntr(); } +#endif //----------------------------------------------------------------------------- void setup() { @@ -26,10 +28,12 @@ void setup() { if(DEF_PIN_OFF != myApp.getNrfIrqPin()) attachInterrupt(digitalPinToInterrupt(myApp.getNrfIrqPin()), handleIntr, FALLING); } + #ifdef ESP32 if(myApp.getCmtEnabled()) { if(DEF_PIN_OFF != myApp.getCmtIrqPin()) attachInterrupt(digitalPinToInterrupt(myApp.getCmtIrqPin()), handleHmsIntr, RISING); } + #endif } diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 6f821faf..01ebde87 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -21,7 +21,7 @@
Dark Mode
-
(empty browser cache or use CTRL + F5 after reboot to apply this setting)
+
(empty browser cache or use CTRL + F5 after reboot to apply this setting)
@@ -33,7 +33,7 @@

Radio (CMT2300A)

-
+
(ESP32 only)

Serial Console

@@ -695,6 +695,16 @@ function parseNrfRadio(obj, type, system) { var e = document.getElementById("rf24"); + var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox"); + en.checked = obj["en"]; + + e.replaceChildren ( + ml("div", {class: "row mb-3"}, [ + ml("div", {class: "col-8 col-sm-3 my-2"}, "NRF24 Enable"), + ml("div", {class: "col-4 col-sm-9"}, en) + ]) + ); + if ("ESP8266" == type) { pins = [['cs', 'pinCs'], ['ce', 'pinCe'], ['irq', 'pinIrq']]; } else { @@ -730,7 +740,7 @@ var en = inp("cmtEnable", null, null, ["cb"], "cmtEnable", "checkbox"); en.checked = obj["en"]; - e.append( + e.replaceChildren ( ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-8 col-sm-3 my-2"}, "CMT2300A Enable"), ml("div", {class: "col-4 col-sm-9"}, en) From f2aad42be456945e00ac64bb8ca1d867d4be465a Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 25 Apr 2023 20:51:26 +0200 Subject: [PATCH 36/92] fix compile error --- src/app.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 8834ea25..b33db83b 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -59,7 +59,8 @@ void app::setup() { mMiPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mMiPayload.enableSerialDebug(mConfig->serial.debug); - mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + } #if defined(ESP32) mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); @@ -72,7 +73,7 @@ void app::setup() { DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ if(mConfig->nrf.enabled) { - if (!mSys.Radio.isChipConnected()) + if (!mNrfRadio.isChipConnected()) DPRINTLN(DBG_WARN, F("WARNING! your NRF24 module can't be reached, check the wiring")); } @@ -482,6 +483,6 @@ void app::updateLed(void) { digitalWrite(mConfig->led.led1, led_on); } else { digitalWrite(mConfig->led.led1, led_off); -} + } } -} +} \ No newline at end of file From a0f44deb677ceb50d270e2533d9eb536ea708e0b Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 25 Apr 2023 21:06:48 +0200 Subject: [PATCH 37/92] fix pinout for NRF24 read back, store enable --- src/web/html/setup.html | 6 +++--- src/web/web.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 01ebde87..649491f0 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -693,7 +693,7 @@ ) } - function parseNrfRadio(obj, type, system) { + function parseNrfRadio(obj, objPin, type, system) { var e = document.getElementById("rf24"); var en = inp("nrfEnable", null, null, ["cb"], "nrfEnable", "checkbox"); en.checked = obj["en"]; @@ -715,7 +715,7 @@ ml("div", {class: "row mb-3"}, [ ml("div", {class: "col-12 col-sm-3 my-2"}, p[0].toUpperCase()), ml("div", {class: "col-12 col-sm-9"}, - sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, obj[p[0]]) + sel(p[1], ("ESP8266" == type) ? esp8266pins : ("ESP32-S3" == system["chip_model"]) ? esp32s3pins : esp32pins, objPin[p[0]]) ) ]) ); @@ -844,7 +844,7 @@ parseNtp(root["ntp"]); parseSun(root["sun"]); parsePinout(root["pinout"], root["system"]["esp_type"], root["system"]); - parseNrfRadio(root["radioNrf"], root["system"]["esp_type"], root["system"]); + parseNrfRadio(root["radioNrf"], root["pinout"], root["system"]["esp_type"], root["system"]); if(root["generic"]["esp_type"] == "ESP32") parseCmtRadio(root["radioCmt"], root["system"]["esp_type"], root["system"]); parseSerial(root["serial"]); diff --git a/src/web/web.h b/src/web/web.h index 815bc550..ff774334 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -543,7 +543,7 @@ class Web { // nrf24 amplifier power mConfig->nrf.amplifierPower = request->arg("rf24Power").toInt() & 0x03; - mConfig->nrf.enabled = (request->arg("rf24Enable") == "on"); + mConfig->nrf.enabled = (request->arg("nrfEnable") == "on"); // cmt mConfig->cmt.enabled = (request->arg("cmtEnable") == "on"); From 3072ddb59e5abbbbde0be28f60c869419ebb3bb0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 6 May 2023 00:45:41 +0200 Subject: [PATCH 38/92] SPI related changes for CMT / 3 wire SPI --- src/hms/esp32_3wSpi.h | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 2be85724..0d494ba6 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -17,6 +17,11 @@ #define SPI_CLK 1 * 1000 * 1000 // 1MHz +// for ESP32 this is the so-called HSPI +// for ESP32-S2/S3/C3 this nomenclature does not really exist anymore, +// it is simply the first externally usable hardware SPI master controller +#define SPI_CMT SPI2_HOST + template //, uint8_t GPIO3_PIN=15> class esp32_3wSpi { public: @@ -34,10 +39,12 @@ class esp32_3wSpi { .max_transfer_sz = 32, }; spi_device_interface_config_t devcfg = { - .command_bits = 0, - .address_bits = 0, + .command_bits = 1, + .address_bits = 7, .dummy_bits = 0, - .mode = 0, // SPI mode 0 + .mode = 0, + .cs_ena_pretrans = 1, + .cs_ena_posttrans = 1, .clock_speed_hz = SPI_CLK, .spics_io_num = pinCsb, .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE, @@ -46,15 +53,15 @@ class esp32_3wSpi { .post_cb = NULL, }; - ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, 0)); - ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi_reg)); + ESP_ERROR_CHECK(spi_bus_initialize(SPI_CMT, &buscfg, SPI_DMA_DISABLED)); + ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg, &spi_reg)); // FiFo spi_device_interface_config_t devcfg2 = { .command_bits = 0, .address_bits = 0, .dummy_bits = 0, - .mode = 0, // SPI mode 0 + .mode = 0, .cs_ena_pretrans = 2, .cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us .clock_speed_hz = SPI_CLK, @@ -64,9 +71,9 @@ class esp32_3wSpi { .pre_cb = NULL, .post_cb = NULL, }; - ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg2, &spi_fifo)); + ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg2, &spi_fifo)); - esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI2_HOST].spid_out, true, false); + esp_rom_gpio_connect_out_signal(MOSI_PIN, spi_periph_signal[SPI_CMT].spid_out, true, false); delay(100); //pinMode(pinGpio3, INPUT); @@ -77,11 +84,12 @@ class esp32_3wSpi { if(!mInitialized) return; - uint8_t tx_data[2]; - tx_data[0] = ~addr; - tx_data[1] = ~reg; + uint8_t tx_data; + tx_data = ~reg; spi_transaction_t t = { - .length = 2 * 8, + .cmd = 1, + .addr = (uint64_t)(~addr), + .length = 8, .tx_buffer = &tx_data, .rx_buffer = NULL }; @@ -93,12 +101,13 @@ class esp32_3wSpi { if(!mInitialized) return 0; - uint8_t tx_data, rx_data; - tx_data = ~(addr | 0x80); // negation and MSB high (read command) + uint8_t rx_data; spi_transaction_t t = { + .cmd = 0, + .addr = (uint64_t)(~addr), .length = 8, .rxlength = 8, - .tx_buffer = &tx_data, + .tx_buffer = NULL, .rx_buffer = &rx_data }; ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t)); @@ -112,7 +121,6 @@ class esp32_3wSpi { uint8_t tx_data; spi_transaction_t t = { - .flags = SPI_TRANS_MODE_OCT, .length = 8, .tx_buffer = &tx_data, // reference to write data .rx_buffer = NULL From 7c9938a91213329267e6c0a5885a0ca6636c4a79 Mon Sep 17 00:00:00 2001 From: Argafal Date: Fri, 12 May 2023 09:49:34 +0200 Subject: [PATCH 39/92] Support for Fusion v2 board, bug fix NRF CMT and NRF now work concurrently. --- src/hm/hmRadio.h | 4 ++-- src/hms/esp32_3wSpi.h | 24 ++++++++++++++++++++++-- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h index 7b8250fd..dba24bb3 100644 --- a/src/hm/hmRadio.h +++ b/src/hm/hmRadio.h @@ -84,8 +84,8 @@ class HmRadio { DTU_RADIO_ID = ((uint64_t)(((dtuSn >> 24) & 0xFF) | ((dtuSn >> 8) & 0xFF00) | ((dtuSn << 8) & 0xFF0000) | ((dtuSn << 24) & 0xFF000000)) << 8) | 0x01; #ifdef ESP32 - #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 - mSpi = new SPIClass(FSPI); + #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 + mSpi = new SPIClass(HSPI); #else mSpi = new SPIClass(VSPI); #endif diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 0d494ba6..cc54f6a4 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -11,12 +11,21 @@ #include "driver/spi_master.h" #include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal +#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#define CLK_PIN 6 +#define MOSI_PIN 5 +#else #define CLK_PIN 18 #define MOSI_PIN 23 -#define MISO_PIN -1 +#endif #define SPI_CLK 1 * 1000 * 1000 // 1MHz +#define SPI_PARAM_LOCK() \ + do { \ + } while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS) +#define SPI_PARAM_UNLOCK() xSemaphoreGive(paramLock) + // for ESP32 this is the so-called HSPI // for ESP32-S2/S3/C3 this nomenclature does not really exist anymore, // it is simply the first externally usable hardware SPI master controller @@ -30,9 +39,10 @@ class esp32_3wSpi { } void setup(uint8_t pinCsb = CSB_PIN, uint8_t pinFcsb = FCSB_PIN) { //, uint8_t pinGpio3 = GPIO3_PIN) { + paramLock = xSemaphoreCreateMutex(); spi_bus_config_t buscfg = { .mosi_io_num = MOSI_PIN, - .miso_io_num = MISO_PIN, + .miso_io_num = -1, // single wire MOSI/MISO .sclk_io_num = CLK_PIN, .quadwp_io_num = -1, .quadhd_io_num = -1, @@ -93,7 +103,9 @@ class esp32_3wSpi { .tx_buffer = &tx_data, .rx_buffer = NULL }; + SPI_PARAM_LOCK(); ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t)); + SPI_PARAM_UNLOCK(); delayMicroseconds(100); } @@ -110,7 +122,10 @@ class esp32_3wSpi { .tx_buffer = NULL, .rx_buffer = &rx_data }; + + SPI_PARAM_LOCK(); ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t)); + SPI_PARAM_UNLOCK(); delayMicroseconds(100); return rx_data; } @@ -126,11 +141,13 @@ class esp32_3wSpi { .rx_buffer = NULL }; + SPI_PARAM_LOCK(); for(uint8_t i = 0; i < len; i++) { tx_data = ~buf[i]; // negate buffer contents ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); delayMicroseconds(4); // > 4 us } + SPI_PARAM_UNLOCK(); } void readFifo(uint8_t buf[], uint8_t len) { @@ -145,16 +162,19 @@ class esp32_3wSpi { .rx_buffer = &rx_data }; + SPI_PARAM_LOCK(); for(uint8_t i = 0; i < len; i++) { ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); delayMicroseconds(4); // > 4 us buf[i] = rx_data; } + SPI_PARAM_UNLOCK(); } private: spi_device_handle_t spi_reg, spi_fifo; bool mInitialized; + SemaphoreHandle_t paramLock = NULL; }; #else template From e17c5f90ffcded052fbabb6b7e26cf8e55c5b9a2 Mon Sep 17 00:00:00 2001 From: Argafal Date: Fri, 12 May 2023 10:06:41 +0200 Subject: [PATCH 40/92] Fix SPI2_HOST pins, remove C3 and S2 as I don't know their correct values --- src/hms/esp32_3wSpi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index cc54f6a4..24774bbc 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -11,7 +11,7 @@ #include "driver/spi_master.h" #include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal -#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 +#if CONFIG_IDF_TARGET_ESP32S3 #define CLK_PIN 6 #define MOSI_PIN 5 #else From 45a5aa6bd716ef05fa0a07a6b009910b23145183 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 16 May 2023 20:54:21 +0200 Subject: [PATCH 41/92] fix whitespaces --- src/hms/esp32_3wSpi.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h index 24774bbc..080e2251 100644 --- a/src/hms/esp32_3wSpi.h +++ b/src/hms/esp32_3wSpi.h @@ -162,13 +162,13 @@ class esp32_3wSpi { .rx_buffer = &rx_data }; - SPI_PARAM_LOCK(); + SPI_PARAM_LOCK(); for(uint8_t i = 0; i < len; i++) { ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t)); delayMicroseconds(4); // > 4 us buf[i] = rx_data; } - SPI_PARAM_UNLOCK(); + SPI_PARAM_UNLOCK(); } private: From ef36bc46d6fc9d0e29e99fc75c2aabf21fa1d6d1 Mon Sep 17 00:00:00 2001 From: Henning Date: Fri, 26 May 2023 19:15:43 +0200 Subject: [PATCH 42/92] AC Frequency is a measurement --- src/hm/hmDefines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index bd12f72b..38599f9a 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -53,7 +53,7 @@ const byteAssign_fieldDeviceClass deviceFieldAssignment[] = { {FLD_UAC, DEVICE_CLS_VOLTAGE, STATE_CLS_MEASUREMENT}, {FLD_IAC, DEVICE_CLS_CURRENT, STATE_CLS_MEASUREMENT}, {FLD_PAC, DEVICE_CLS_PWR, STATE_CLS_MEASUREMENT}, - {FLD_F, DEVICE_CLS_FREQ, STATE_CLS_NONE}, + {FLD_F, DEVICE_CLS_FREQ, STATE_CLS_MEASUREMENT}, {FLD_T, DEVICE_CLS_TEMP, STATE_CLS_MEASUREMENT}, {FLD_PF, DEVICE_CLS_NONE, STATE_CLS_NONE}, {FLD_EFF, DEVICE_CLS_NONE, STATE_CLS_NONE}, From 72cdaf326a1d43e31527bb23a5978e205af99c75 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 27 May 2023 01:29:27 +0200 Subject: [PATCH 43/92] fix HMT with 6 channels --- src/config/settings.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/config/settings.h b/src/config/settings.h index ae00883a..430efad3 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -643,7 +643,10 @@ class settings { getVal(obj, F("en"), &cfg->enabled); getChar(obj, F("name"), cfg->name, MAX_NAME_LENGTH); getVal(obj, F("sn"), &cfg->serial.u64); - for(uint8_t i = 0; i < (sizeof(obj[F("yield")])/sizeof(int32_t)); i++) { + uint8_t size = 4; + if(obj.containsKey(F("pwr"))) + size = obj[F("pwr")].size(); + for(uint8_t i = 0; i < size; i++) { if(obj.containsKey(F("yield"))) cfg->yieldCor[i] = obj[F("yield")][i]; if(obj.containsKey(F("pwr"))) cfg->chMaxPwr[i] = obj[F("pwr")][i]; if(obj.containsKey(F("chName"))) snprintf(cfg->chName[i], MAX_NAME_LENGTH, "%s", obj[F("chName")][i].as()); From 0f594d13c80008738a9602b4513fad97dbebb6da Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 4 Jun 2023 17:30:43 +0200 Subject: [PATCH 44/92] fix esp8266 --- src/app.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index 88ad2bd4..3f3452dc 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -118,7 +118,7 @@ void app::loop(void) { void app::loopStandard(void) { ah::Scheduler::loop(); - if (mNrfRadio.loop()) { + if (mNrfRadio.loop() && mConfig->nrf.enabled) { while (!mNrfRadio.mBufCtrl.empty()) { packet_t *p = &mNrfRadio.mBufCtrl.front(); @@ -146,7 +146,7 @@ void app::loopStandard(void) { mMiPayload.process(true); } #if defined(ESP32) - if (mCmtRadio.loop()) { + if (mCmtRadio.loop() && mConfig->cmt.enabled) { while (!mCmtRadio.mBufCtrl.empty()) { hmsPacket_t *p = &mCmtRadio.mBufCtrl.front(); if (mConfig->serial.debug) { @@ -418,13 +418,17 @@ void app::tickSend(void) { if (NULL != iv) { if (iv->config->enabled) { - if (iv->ivGen == IV_HM) - mPayload.ivSend(iv); - else if(iv->ivGen == IV_MI) - mMiPayload.ivSend(iv); + if(mConfig->nrf.enabled) { + if (iv->ivGen == IV_HM) + mPayload.ivSend(iv); + else if(iv->ivGen == IV_MI) + mMiPayload.ivSend(iv); + } #if defined(ESP32) - else if((iv->ivGen == IV_HMS) || (iv->ivGen == IV_HMT)) - mHmsPayload.ivSend(iv); + if(mCmtRadio.enabled) { + if((iv->ivGen == IV_HMS) || (iv->ivGen == IV_HMT)) + mHmsPayload.ivSend(iv); + } #endif } } @@ -502,4 +506,4 @@ void app::updateLed(void) { digitalWrite(mConfig->led.led1, led_off); } } -} \ No newline at end of file +} From 545d7f0ba6efa4236ce771a51ab276a95681b39e Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 4 Jun 2023 18:06:07 +0200 Subject: [PATCH 45/92] 0.7.0 HMS / HMT support for ESP32 devices --- src/CHANGES.md | 3 +++ src/defines.h | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 6b97e319..61421e88 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.7.0 - 2023-06-04 +* HMS / HMT support for ESP32 devices + ## 0.6.15 - 2023-05-25 * improved Prometheus Endpoint PR #958 * fix turn off ePaper only if setting was set #956 diff --git a/src/defines.h b/src/defines.h index baaea8b6..0cdffe8c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -12,8 +12,8 @@ // VERSION //------------------------------------- #define VERSION_MAJOR 0 -#define VERSION_MINOR 6 -#define VERSION_PATCH 15 +#define VERSION_MINOR 7 +#define VERSION_PATCH 0 //------------------------------------- typedef struct { From a1c00bdc017a5faa541f6ac1da518c072c8568ff Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 4 Jun 2023 19:57:21 +0200 Subject: [PATCH 46/92] 0.7.0 esp32 compile fix --- src/app.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.cpp b/src/app.cpp index 3f3452dc..5f6ef3cc 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -425,7 +425,7 @@ void app::tickSend(void) { mMiPayload.ivSend(iv); } #if defined(ESP32) - if(mCmtRadio.enabled) { + if(mConfig->cmt.enabled) { if((iv->ivGen == IV_HMS) || (iv->ivGen == IV_HMT)) mHmsPayload.ivSend(iv); } From f0848ecfb4f7e35f44e841ecd57e73589c8d2e01 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 5 Jun 2023 22:15:08 +0200 Subject: [PATCH 47/92] 0.7.1 * enabled power limit control for HMS / HMT devices * changed NRF24 lib version back to 1.4.5 because of compile problems for EPS8266 --- src/CHANGES.md | 4 ++++ src/app.h | 1 - src/defines.h | 2 +- src/hms/hmsPayload.h | 49 +++++++++++++++++--------------------------- src/hms/hmsRadio.h | 18 ++++++++++++++++ src/platformio.ini | 10 ++++----- 6 files changed, 47 insertions(+), 37 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 61421e88..7d19bc3d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.1 - 2023-06-05 +* enabled power limit control for HMS / HMT devices +* changed NRF24 lib version back to 1.4.5 because of compile problems for EPS8266 + ## 0.7.0 - 2023-06-04 * HMS / HMT support for ESP32 devices diff --git a/src/app.h b/src/app.h index 24abde39..4d5a90a8 100644 --- a/src/app.h +++ b/src/app.h @@ -9,7 +9,6 @@ #include #include #include -#include #include "appInterface.h" #include "config/settings.h" diff --git a/src/defines.h b/src/defines.h index 0cdffe8c..6b220179 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 0 +#define VERSION_PATCH 1 //------------------------------------- typedef struct { diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index d71863b3..a3463bd1 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -83,7 +83,7 @@ class HmsPayload { if ((IV_HMS != iv->ivGen) && (IV_HMT != iv->ivGen)) // only process HMS inverters return; - //if(!highPrio) { + if(!highPrio) { if (mPayload[iv->id].requested) { if (!mPayload[iv->id].complete) process(false); // no retransmit @@ -106,52 +106,41 @@ class HmsPayload { }*/ } } - //} + } reset(iv->id); mPayload[iv->id].requested = true; yield(); if (mSerialDebug) { - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); + DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F(") Requesting Inv SN ")); DBGPRINTLN(String(iv->config->serial.u64, HEX)); } - /*if (iv->getDevControlRequest()) { + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + if (iv->getDevControlRequest()) { if (mSerialDebug) { - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); + DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F(") Devcontrol request 0x")); DBGPRINT(String(iv->devControlCmd, HEX)); DBGPRINT(F(" power limit ")); DBGPRINTLN(String(iv->powerLimit[0])); } - mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); + mRadio->sendControlPacket(&iv->radioId.u64, iv->devControlCmd, iv->powerLimit, false); mPayload[iv->id].txCmd = iv->devControlCmd; //iv->clearCmdQueue(); //iv->enqueCommand(SystemConfigPara); // read back power limit - } else { - uint8_t cmd = iv->getQueuedCmd(); - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); - DBGPRINT(F(") prepareDevInformCmd")); // + String(cmd, HEX)); - mRadio->prepareDevInformCmd(iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); - mPayload[iv->id].txCmd = cmd; - }*/ - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if(((rec->ts + HMS_TIMEOUT_SEC) < *mTimestamp) && (mIvCmd56Cnt[iv->id] < 3)) { - //mRadio->switchFrequency(&iv->radioId.u64, 863000, WORK_FREQ_KHZ); + } else if(((rec->ts + HMS_TIMEOUT_SEC) < *mTimestamp) && (mIvCmd56Cnt[iv->id] < 3)) { mRadio->switchFrequency(&iv->radioId.u64, HOY_BOOT_FREQ_KHZ, WORK_FREQ_KHZ); mIvCmd56Cnt[iv->id]++; } else { if(++mIvCmd56Cnt[iv->id] == 10) mIvCmd56Cnt[iv->id] = 0; uint8_t cmd = iv->getQueuedCmd(); - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); - DBGPRINTLN(F(") prepareDevInformCmd")); // + String(cmd, HEX)); + DPRINT_IVID(DBG_INFO, iv->id); + DBGPRINT(F("prepareDevInformCmd 0x")); + DBGHEXLN(cmd); mRadio->prepareDevInformCmd(&iv->radioId.u64, cmd, mPayload[iv->id].ts, iv->alarmMesIndex, false); mPayload[iv->id].txCmd = cmd; } @@ -181,15 +170,15 @@ class HmsPayload { } } } - } /*else if (p->packet[0] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command + } else if (p->data[1] == (TX_REQ_DEVCONTROL + ALL_FRAMES)) { // response from dev control command DPRINTLN(DBG_DEBUG, F("Response from devcontrol request received")); - mPayload[iv->id].txId = p->packet[0]; + mPayload[iv->id].txId = p->data[1]; iv->clearDevControlRequest(); - if ((p->packet[12] == ActivePowerContr) && (p->packet[13] == 0x00)) { + if ((p->data[13] == ActivePowerContr) && (p->data[14] == 0x00)) { bool ok = true; - if((p->packet[10] == 0x00) && (p->packet[11] == 0x00)) + if((p->data[11] == 0x00) && (p->data[12] == 0x00)) mApp->setMqttPowerLimitAck(iv); else ok = false; @@ -206,7 +195,7 @@ class HmsPayload { iv->enqueCommand(SystemConfigPara); // read back power limit } iv->devControlCmd = Init; - }*/ + } } void process(bool retransmit) { @@ -235,10 +224,10 @@ class HmsPayload { // This is required to prevent retransmissions without answer. DPRINTLN(DBG_INFO, F("Prevent retransmit on Restart / CleanState_LockAndAlarm...")); mPayload[iv->id].retransmits = mMaxRetrans; - } /*else if(iv->devControlCmd == ActivePowerContr) { + } else if(iv->devControlCmd == ActivePowerContr) { DPRINTLN(DBG_INFO, F("retransmit power limit")); - mRadio->sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); - }*/ else { + mRadio->sendControlPacket(&iv->radioId.u64, iv->devControlCmd, iv->powerLimit, true); + } else { if(false == mPayload[iv->id].gotFragment) { //DPRINTLN(DBG_WARN, F("nothing received: Request Complete Retransmit")); diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index 8c6bf8af..1bce5102 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -63,6 +63,24 @@ class CmtRadio { mSerialDebug = true; } + void sendControlPacket(const uint64_t *ivId, uint8_t cmd, uint16_t *data, bool isRetransmit) { + DPRINT(DBG_INFO, F("sendControlPacket cmd: 0x")); + DBGHEXLN(cmd); + initPacket(ivId, TX_REQ_DEVCONTROL, SINGLE_FRAME); + uint8_t cnt = 10; + + mTxBuf[cnt++] = cmd; // cmd -> 0 on, 1 off, 2 restart, 11 active power, 12 reactive power, 13 power factor + mTxBuf[cnt++] = 0x00; + if(cmd >= ActivePowerContr && cmd <= PFSet) { // ActivePowerContr, ReactivePowerContr, PFSet + mTxBuf[cnt++] = ((data[0] * 10) >> 8) & 0xff; // power limit + mTxBuf[cnt++] = ((data[0] * 10) ) & 0xff; // power limit + mTxBuf[cnt++] = ((data[1] ) >> 8) & 0xff; // setting for persistens handlings + mTxBuf[cnt++] = ((data[1] ) ) & 0xff; // setting for persistens handling + } + + sendPacket(cnt, isRetransmit); + } + bool switchFrequency(const uint64_t *ivId, uint32_t fromkHz, uint32_t tokHz) { uint8_t fromCh = mCmt.freq2Chan(fromkHz); uint8_t toCh = mCmt.freq2Chan(tokHz); diff --git a/src/platformio.ini b/src/platformio.ini index 904f6120..c05908f0 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -24,7 +24,7 @@ extra_scripts = lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer - nrf24/RF24 @ ^1.4.5 + nrf24/RF24 @ 1.4.5 paulstoffregen/Time @ ^1.6.1 https://github.com/bertmelis/espMqttClient#v1.4.2 bblanchon/ArduinoJson @ ^6.21.2 @@ -37,7 +37,7 @@ lib_deps = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE +build_flags = -D RELEASE -std=gnu++17 ;-Wl,-Map,output.map monitor_filters = ;default ; Remove typical terminal control codes from input @@ -50,7 +50,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -D RELEASE -DENABLE_PROMETHEUS_EP +build_flags = -D RELEASE -std=gnu++17 -DENABLE_PROMETHEUS_EP monitor_filters = ;default ; Remove typical terminal control codes from input ;time ; Add timestamp with milliseconds for each new line @@ -61,7 +61,7 @@ monitor_filters = platform = espressif8266 board = esp12e board_build.f_cpu = 80000000L -build_flags = -DDEBUG_LEVEL=DBG_DEBUG -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial -DPIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 +build_flags = -DDEBUG_LEVEL=DBG_DEBUG -std=gnu++17 -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_OOM -DDEBUG_ESP_PORT=Serial -DPIO_FRAMEWORK_ARDUINO_MMU_CACHE16_IRAM48 build_type = debug monitor_filters = ;default ; Remove typical terminal control codes from input @@ -73,7 +73,7 @@ platform = espressif8266 board = esp8285 board_build.ldscript = eagle.flash.1m64.ld board_build.f_cpu = 80000000L -build_flags = -D RELEASE +build_flags = -D RELEASE -std=gnu++17 monitor_filters = ;default ; Remove typical terminal control codes from input time ; Add timestamp with milliseconds for each new line From 53853f842921c2bdb9b160e3c4f97255105000a0 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 8 Jun 2023 23:42:30 +0200 Subject: [PATCH 48/92] 0.7.2 * fix HMS-800 and HMS-1000 assignments #981 * make nrf enabled all the time for ESP8266 * fix menu item `active` highlight for 'API' and 'Doku' * fix MqTT totals issue #927, #980 * reduce maximum number of inverters to 4 for ESP8266, increase to 16 for ESP32 --- README.md | 2 +- src/CHANGES.md | 7 +++++++ src/config/config.h | 6 +++++- src/config/settings.h | 8 ++++++-- src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 1 + src/web/html/api.js | 6 ++++-- 7 files changed, 25 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 73c4184f..1af6f41d 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Table of approaches: | Board | MI | HM | HMS/HMT | comment | HowTo start | | ------ | -- | -- | ------- | ------- | ---------- | -| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | coming soon✨ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) | +| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | ✔️ development version ✨ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) | | [Arduino Nano, C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | | [Raspberry Pi, Python](tools/rpi/) | ❌ | ✔️ | ❌ | | | [Others, C/C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | diff --git a/src/CHANGES.md b/src/CHANGES.md index 7d19bc3d..fdde045d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,12 @@ # Development Changes +## 0.7.2 - 2023-06-08 +* fix HMS-800 and HMS-1000 assignments #981 +* make nrf enabled all the time for ESP8266 +* fix menu item `active` highlight for 'API' and 'Doku' +* fix MqTT totals issue #927, #980 +* reduce maximum number of inverters to 4 for ESP8266, increase to 16 for ESP32 + ## 0.7.1 - 2023-06-05 * enabled power limit control for HMS / HMT devices * changed NRF24 lib version back to 1.4.5 because of compile problems for EPS8266 diff --git a/src/config/config.h b/src/config/config.h index ac28c1a2..a03712bd 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -72,7 +72,11 @@ #define PACKET_BUFFER_SIZE 30 // number of configurable inverters -#define MAX_NUM_INVERTERS 10 +#if defined(ESP32) + #define MAX_NUM_INVERTERS 16 +#else + #define MAX_NUM_INVERTERS 4 +#endif // default serial interval #define SERIAL_INTERVAL 5 diff --git a/src/config/settings.h b/src/config/settings.h index 430efad3..540d00df 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -414,7 +414,7 @@ class settings { mCfg.plugin.display.pxShift = true; mCfg.plugin.display.rot = 0; mCfg.plugin.display.disp_data = DEF_PIN_OFF; // SDA - mCfg.plugin.display.disp_clk = DEF_PIN_OFF; // SCL + mCfg.plugin.display.disp_clk = DEF_PIN_OFF; // SCL mCfg.plugin.display.disp_cs = DEF_PIN_OFF; mCfg.plugin.display.disp_reset = DEF_PIN_OFF; mCfg.plugin.display.disp_busy = DEF_PIN_OFF; @@ -476,7 +476,11 @@ class settings { getVal(obj, F("mosi"), &mCfg.nrf.pinMosi); getVal(obj, F("miso"), &mCfg.nrf.pinMiso); getVal(obj, F("pwr"), &mCfg.nrf.amplifierPower); - mCfg.nrf.enabled = (bool) obj[F("en")]; + #if !defined(ESP32) + mCfg.nrf.enabled = true; // ESP8266, read always as enabled + #else + mCfg.nrf.enabled = (bool) obj[F("en")]; + #endif if((obj[F("cs")] == obj[F("ce")])) { mCfg.nrf.pinCs = DEF_CS_PIN; mCfg.nrf.pinCe = DEF_CE_PIN; diff --git a/src/defines.h b/src/defines.h index 6b220179..3c315e99 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 1 +#define VERSION_PATCH 2 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 947cd2f4..5e72e522 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -114,6 +114,7 @@ class PubMqttIvData { case FLD_YD: if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart mPos++; + mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built return; } retained = true; diff --git a/src/web/html/api.js b/src/web/html/api.js index 1dd5422e..f201d8c5 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -78,8 +78,10 @@ function parseNav(obj) { if(i == 2) continue; var l = document.getElementById("nav"+i); - if(window.location.pathname == "/" + l.href.substring(0, l.href.indexOf("?")).split('/').pop()) - l.classList.add("active"); + if(window.location.pathname == "/" + l.href.substring(0, l.href.indexOf("?")).split('/').pop()) { + if((i != 8 )&& (i != 9)) + l.classList.add("active"); + } if(obj["menu_protEn"]) { if(obj["menu_prot"]) { From 4e54bcf2994fe3ccfccfd9dab15e935bb7337bdf Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 10 Jun 2023 01:04:50 +0200 Subject: [PATCH 49/92] 0.7.3 * fix hidden SSID scan #983 * improved NRF24 missing message on home screen #981 * fix MqTT publishing only updated values #982 --- src/CHANGES.md | 5 +++++ src/app.cpp | 10 +++++----- src/app.h | 4 ++-- src/config/settings.h | 6 +++++- src/defines.h | 2 +- src/hm/hmPayload.h | 8 ++++---- src/hm/miPayload.h | 10 +++++----- src/hms/hmsPayload.h | 8 ++++---- src/publisher/pubMqtt.h | 10 +++++----- src/publisher/pubMqttIvData.h | 23 ++++++++++++++++------- src/web/RestApi.h | 3 ++- src/web/html/setup.html | 7 ++++++- src/web/web.h | 1 + src/wifi/ahoywifi.cpp | 9 +++++++-- 14 files changed, 68 insertions(+), 38 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index fdde045d..8225f1df 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.7.3 - 2023-06-09 +* fix hidden SSID scan #983 +* improved NRF24 missing message on home screen #981 +* fix MqTT publishing only updated values #982 + ## 0.7.2 - 2023-06-08 * fix HMS-800 and HMS-1000 assignments #981 * make nrf enabled all the time for ESP8266 diff --git a/src/app.cpp b/src/app.cpp index 5f6ef3cc..f30ed4db 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -55,11 +55,11 @@ void app::setup() { if(mConfig->nrf.enabled) { mPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mPayload.enableSerialDebug(mConfig->serial.debug); - mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); mMiPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); mMiPayload.enableSerialDebug(mConfig->serial.debug); - mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mMiPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); } #if defined(ESP32) @@ -334,7 +334,7 @@ void app::tickZeroValues(void) { } if(changed) - payloadEventListener(RealTimeRunData_Debug); + payloadEventListener(RealTimeRunData_Debug, NULL); } //----------------------------------------------------------------------------- @@ -356,7 +356,7 @@ void app::tickMinute(void) { } if(changed) - payloadEventListener(RealTimeRunData_Debug); + payloadEventListener(RealTimeRunData_Debug, NULL); } //----------------------------------------------------------------------------- @@ -379,7 +379,7 @@ void app::tickMidnight(void) { } if(changed) - payloadEventListener(RealTimeRunData_Debug); + payloadEventListener(RealTimeRunData_Debug, NULL); if (mMqttEnabled) mMqtt.tickerMidnight(); diff --git a/src/app.h b/src/app.h index 4d5a90a8..e053cfd9 100644 --- a/src/app.h +++ b/src/app.h @@ -242,10 +242,10 @@ class app : public IApp, public ah::Scheduler { void resetSystem(void); - void payloadEventListener(uint8_t cmd) { + void payloadEventListener(uint8_t cmd, Inverter<> *iv) { #if !defined(AP_ONLY) if (mMqttEnabled) - mMqtt.payloadEventListener(cmd); + mMqtt.payloadEventListener(cmd, iv); #endif if(mConfig->plugin.display.type != 0) mDisplay.payloadEventListener(cmd); diff --git a/src/config/settings.h b/src/config/settings.h index 540d00df..610b2fef 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -68,6 +68,7 @@ typedef struct { // wifi char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; + bool isHidden; cfgIp_t ip; } cfgSys_t; @@ -359,6 +360,7 @@ class settings { else { snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID); snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD); + mCfg.sys.isHidden = false; } snprintf(mCfg.sys.deviceName, DEVNAME_LEN, DEF_DEVICE_NAME); @@ -426,6 +428,7 @@ class settings { char buf[16]; obj[F("ssid")] = mCfg.sys.stationSsid; obj[F("pwd")] = mCfg.sys.stationPwd; + obj[F("hidd")] = (bool) mCfg.sys.isHidden; obj[F("dev")] = mCfg.sys.deviceName; obj[F("adm")] = mCfg.sys.adminPwd; obj[F("prot_mask")] = mCfg.sys.protectionMask; @@ -438,11 +441,12 @@ class settings { } else { getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); getChar(obj, F("pwd"), mCfg.sys.stationPwd, PWD_LEN); + getVal(obj, F("hidd"), &mCfg.sys.isHidden); getChar(obj, F("dev"), mCfg.sys.deviceName, DEVNAME_LEN); getChar(obj, F("adm"), mCfg.sys.adminPwd, PWD_LEN); getVal(obj, F("prot_mask"), &mCfg.sys.protectionMask); getVal(obj, F("dark"), &mCfg.sys.darkMode); - if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); + if(obj.containsKey(F("ip"))) ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as()); if(obj.containsKey(F("mask"))) ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as()); if(obj.containsKey(F("dns1"))) ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as()); if(obj.containsKey(F("dns2"))) ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as()); diff --git a/src/defines.h b/src/defines.h index 3c315e99..90eefe87 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 2 +#define VERSION_PATCH 3 //------------------------------------- typedef struct { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 1b36e26a..59f678d9 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -28,7 +28,7 @@ typedef struct { } invPayload_t; -typedef std::function payloadListenerType; +typedef std::function *)> payloadListenerType; typedef std::function alarmListenerType; @@ -342,7 +342,7 @@ class HmPayload { yield(); } iv->doCalculations(); - notify(mPayload[iv->id].txCmd); + notify(mPayload[iv->id].txCmd, iv); if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; @@ -372,9 +372,9 @@ class HmPayload { } private: - void notify(uint8_t val) { + void notify(uint8_t val, Inverter<> *iv) { if(NULL != mCbPayload) - (mCbPayload)(val); + (mCbPayload)(val, iv); } void notify(uint16_t code, uint32_t start, uint32_t endTime) { diff --git a/src/hm/miPayload.h b/src/hm/miPayload.h index b42d4ae2..2205ecb9 100644 --- a/src/hm/miPayload.h +++ b/src/hm/miPayload.h @@ -33,7 +33,7 @@ typedef struct { } miPayload_t; -typedef std::function miPayloadListenerType; +typedef std::function *)> miPayloadListenerType; template @@ -363,7 +363,7 @@ const byteAssign_t InfoAssignment[] = { yield(); } iv->doCalculations(); - notify(mPayload[iv->id].txCmd); + notify(mPayload[iv->id].txCmd, iv); if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; @@ -556,9 +556,9 @@ const byteAssign_t InfoAssignment[] = { } private: - void notify(uint8_t val) { + void notify(uint8_t val, Inverter<> *iv) { if(NULL != mCbMiPayload) - (mCbMiPayload)(val); + (mCbMiPayload)(val, iv); } void miStsDecode(Inverter<> *iv, packet_t *p, uint8_t stschan = CH1) { @@ -752,7 +752,7 @@ const byteAssign_t InfoAssignment[] = { iv->setQueuedCmdFinished(); mStat->rxSuccess++; yield(); - notify(RealTimeRunData_Debug); //iv->type == INV_TYPE_4CH ? 0x36 : 0x09 ); + notify(RealTimeRunData_Debug, iv); //iv->type == INV_TYPE_4CH ? 0x36 : 0x09 ); } bool build(uint8_t id, bool *complete) { diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index a3463bd1..fdef3e45 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -29,7 +29,7 @@ typedef struct { } hmsPayload_t; -typedef std::function payloadListenerType; +typedef std::function *)> payloadListenerType; typedef std::function alarmListenerType; @@ -305,7 +305,7 @@ class HmsPayload { yield(); } iv->doCalculations(); - notify(mPayload[iv->id].txCmd); + notify(mPayload[iv->id].txCmd, iv); /*if(AlarmData == mPayload[iv->id].txCmd) { uint8_t i = 0; @@ -335,9 +335,9 @@ class HmsPayload { } private: - void notify(uint8_t val) { + void notify(uint8_t val, Inverter<> *iv) { if(NULL != mCbPayload) - (mCbPayload)(val); + (mCbPayload)(val, iv); } void notify(uint16_t code, uint32_t start, uint32_t endTime) { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 1f8519f5..5be82c0f 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -119,7 +119,7 @@ class PubMqtt { else { // send mqtt data in a fixed interval if(mIntervalTimeout == 0) { mIntervalTimeout = mCfgMqtt->interval; - mSendList.push(RealTimeRunData_Debug); + mSendList.push(sendListCmdIv(RealTimeRunData_Debug, NULL)); sendIvData(); } } @@ -165,10 +165,10 @@ class PubMqtt { publish(mSubTopic, mVal, true); } - void payloadEventListener(uint8_t cmd) { + void payloadEventListener(uint8_t cmd, Inverter<> *iv) { if(mClient.connected()) { // prevent overflow if MQTT broker is not reachable but set if((0 == mCfgMqtt->interval) || (RealTimeRunData_Debug != cmd)) // no interval or no live data - mSendList.push(cmd); + mSendList.push(sendListCmdIv(cmd, iv)); } } @@ -564,7 +564,7 @@ class PubMqtt { void sendIvData() { bool anyAvail = processIvStatus(); if (mLastAnyAvail != anyAvail) - mSendList.push(RealTimeRunData_Debug); // makes sure that total values are calculated + mSendList.push(sendListCmdIv(RealTimeRunData_Debug, NULL)); // makes sure that total values are calculated if(mSendList.empty()) return; @@ -584,7 +584,7 @@ class PubMqtt { uint32_t *mUtcTimestamp; uint32_t mRxCnt, mTxCnt; - std::queue mSendList; + std::queue mSendList; std::queue mAlarmList; subscriptionCb mSubscriptionCb; bool mLastAnyAvail; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 5e72e522..11742c29 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -12,10 +12,16 @@ typedef std::function pubMqttPublisherType; +struct sendListCmdIv { + uint8_t cmd; + Inverter<> *iv; + sendListCmdIv(uint8_t a, Inverter<> *i) : cmd(a), iv(i) {} +}; + template class PubMqttIvData { public: - void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { + void setup(HMSYSTEM *sys, uint32_t *utcTs, std::queue *sendList) { mSys = sys; mUtcTimestamp = utcTs; mSendList = sendList; @@ -60,7 +66,8 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; if(!mSendList->empty()) { - mCmd = mSendList->front(); + mCmd = mSendList->front().cmd; + mIvSend = mSendList->front().iv; if((RealTimeRunData_Debug != mCmd) || !mRTRDataHasBeenSent) { mSendTotals = (RealTimeRunData_Debug == mCmd); @@ -141,9 +148,11 @@ class PubMqttIvData { } else mIvLastRTRpub[mIv->id] = lastTs; - snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); - snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec))); - mPublish(mSubTopic, mVal, retained); + if((mIvSend == mIv) || (NULL == mIvSend)) { // send only updated values, or all if the inverter is NULL + snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]); + snprintf(mVal, 40, "%g", ah::round3(mIv->getValue(mPos, rec))); + mPublish(mSubTopic, mVal, retained); + } mPos++; } else mState = FIND_NXT_IV; @@ -195,7 +204,7 @@ class PubMqttIvData { bool mSendTotals; float mTotal[4]; - Inverter<> *mIv; + Inverter<> *mIv, *mIvSend; uint8_t mPos; uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; bool mRTRDataHasBeenSent; @@ -203,7 +212,7 @@ class PubMqttIvData { char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; - std::queue *mSendList; + std::queue *mSendList; }; #endif /*__PUB_MQTT_IV_DATA_H__*/ diff --git a/src/web/RestApi.h b/src/web/RestApi.h index ea08f8c0..35c22e44 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -206,6 +206,7 @@ class RestApi { void getSysInfo(AsyncWebServerRequest *request, JsonObject obj) { obj[F("ssid")] = mConfig->sys.stationSsid; + obj[F("hidd")] = mConfig->sys.isHidden; obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -467,7 +468,7 @@ class RestApi { JsonArray warn = obj.createNestedArray(F("warnings")); if(!mRadio->isChipConnected()) - warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); + warn.add(F("your NRF24 module can't be reached, check the wiring, pinout and enable")); else if(!mRadio->isPVariant()) warn.add(F("your NRF24 module isn't a plus version(+), maybe incompatible")); if(!mApp->getSettingsValid()) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index f717c2e3..01d481c2 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -72,7 +72,11 @@
SSID
-
+
+
+
+
hidden SSID
+
Password
@@ -617,6 +621,7 @@ function parseSys(obj) { for(var i of [["device", "device_name"], ["ssid", "ssid"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; + document.getElementsByName("hidd")[0].checked = obj["hidd"]; document.getElementsByName("darkMode")[0].checked = obj["dark_mode"]; e = document.getElementsByName("adminpwd")[0]; if(!obj["pwd_set"]) diff --git a/src/web/web.h b/src/web/web.h index d1a0a4a7..0b7ca7de 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -448,6 +448,7 @@ class Web { request->arg("ssid").toCharArray(mConfig->sys.stationSsid, SSID_LEN); if (request->arg("pwd") != "{PWD}") request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN); + mConfig->sys.isHidden = (request->arg("hidd") == "on"); if (request->arg("device") != "") request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN); mConfig->sys.darkMode = (request->arg("darkMode") == "on"); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index cd4a44d0..91c8b8d2 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -104,10 +104,15 @@ void ahoywifi::tickWifiLoop() { DBGPRINTLN(String(mConfig->sys.stationSsid)); mScanCnt = 0; mScanActive = true; + uint8_t *ssid = ([this] () { + if(mConfig->sys.isHidden) + return (uint8_t *)NULL; + return (uint8_t *)(mConfig->sys.stationSsid); + })(); #if defined(ESP8266) - WiFi.scanNetworks(true, false, 0U, (uint8_t *)mConfig->sys.stationSsid); + WiFi.scanNetworks(true, true, 0U, ssid); #else - WiFi.scanNetworks(true, false, false, 300U, 0U, mConfig->sys.stationSsid); + WiFi.scanNetworks(true, true, false, 300U, 0U, ssid); #endif return; } From bdf43fd52204e73fc37a23eee8a265d5a9f1764c Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 10 Jun 2023 09:10:33 +0200 Subject: [PATCH 50/92] fix compile --- src/app.cpp | 2 +- src/wifi/ahoywifi.cpp | 13 ++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/app.cpp b/src/app.cpp index f30ed4db..0df468e3 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -65,7 +65,7 @@ void app::setup() { #if defined(ESP32) mHmsPayload.setup(this, &mSys, &mCmtRadio, &mStat, 5, &mTimestamp); mHmsPayload.enableSerialDebug(mConfig->serial.debug); - mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1)); + mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); #endif /*DBGPRINTLN("--- after payload"); DBGPRINTLN(String(ESP.getFreeHeap())); diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 91c8b8d2..6def5282 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -104,15 +104,18 @@ void ahoywifi::tickWifiLoop() { DBGPRINTLN(String(mConfig->sys.stationSsid)); mScanCnt = 0; mScanActive = true; - uint8_t *ssid = ([this] () { + #if defined(ESP8266) + WiFi.scanNetworks(true, true, 0U, ([this] () { if(mConfig->sys.isHidden) return (uint8_t *)NULL; return (uint8_t *)(mConfig->sys.stationSsid); - })(); - #if defined(ESP8266) - WiFi.scanNetworks(true, true, 0U, ssid); + })()); #else - WiFi.scanNetworks(true, true, false, 300U, 0U, ssid); + WiFi.scanNetworks(true, true, false, 300U, 0U, ([this] () { + if(mConfig->sys.isHidden) + return (char*)NULL; + return (mConfig->sys.stationSsid); + })()); #endif return; } From 3fa274e34294fc9498e42b8ff199bb0c4d2b9035 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Sch=C3=BCller?= Date: Sun, 11 Jun 2023 09:21:07 +0200 Subject: [PATCH 51/92] Fix suntimes working if mqtt is enabled but suntimes is disabled --- tools/rpi/hoymiles/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 3589de1a..9dab5d3c 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -101,7 +101,7 @@ class SunsetHandler: logging.info (f'Woke up...') def sun_status2mqtt(self, dtu_ser, dtu_name): - if not mqtt_client: + if not mqtt_client or not self.suntimes: return local_sunrise = self.suntimes.riselocal(datetime.now()).strftime("%d.%m.%YT%H:%M") local_sunset = self.suntimes.setlocal(datetime.now()).strftime("%d.%m.%YT%H:%M") From f649d26f66cec1887608ae294f94e40e8db20151 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 15 Jun 2023 23:18:12 +0200 Subject: [PATCH 52/92] 0.7.4 * fix MqTT `P_AC` send if inverters are available #987 * fix assignments for HMS 1CH and 2CH devices * fixed uptime overflow #990 --- src/CHANGES.md | 5 +++++ src/app.cpp | 2 +- src/defines.h | 2 +- src/hm/hmDefines.h | 3 ++- src/hm/hmInverter.h | 28 ++++++++++++++++++++-------- src/publisher/pubMqtt.h | 7 ++++--- src/publisher/pubMqttIvData.h | 3 ++- src/utils/scheduler.h | 2 +- src/web/html/visualization.html | 1 - 9 files changed, 36 insertions(+), 17 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 8225f1df..f6e4f8b2 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.7.4 - 2023-06-15 +* fix MqTT `P_AC` send if inverters are available #987 +* fix assignments for HMS 1CH and 2CH devices +* fixed uptime overflow #990 + ## 0.7.3 - 2023-06-09 * fix hidden SSID scan #983 * improved NRF24 missing message on home screen #981 diff --git a/src/app.cpp b/src/app.cpp index 0df468e3..5ae2b845 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -81,7 +81,7 @@ void app::setup() { #if !defined(AP_ONLY) mMqttEnabled = (mConfig->mqtt.broker[0] > 0); if (mMqttEnabled) { - mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp); + mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, &mSys, &mTimestamp, &mUptime); mMqtt.setSubscriptionCb(std::bind(&app::mqttSubRxCb, this, std::placeholders::_1)); mPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); mMiPayload.addAlarmListener(std::bind(&PubMqttType::alarmEventListener, &mMqtt, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); diff --git a/src/defines.h b/src/defines.h index 90eefe87..f13b038d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 3 +#define VERSION_PATCH 4 //------------------------------------- typedef struct { diff --git a/src/hm/hmDefines.h b/src/hm/hmDefines.h index abe03b24..be59330d 100644 --- a/src/hm/hmDefines.h +++ b/src/hm/hmDefines.h @@ -32,7 +32,8 @@ const char* const fields[] = {"U_DC", "I_DC", "P_DC", "YieldDay", "YieldWeek", " const char* const notAvail = "n/a"; const uint8_t fieldUnits[] = {UNIT_V, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_KWH, - UNIT_V, UNIT_A, UNIT_W, UNIT_HZ, UNIT_C, UNIT_NONE, UNIT_PCT, UNIT_PCT, UNIT_VAR, + UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_V, UNIT_A, UNIT_A, UNIT_A, UNIT_A, + UNIT_W, UNIT_HZ, UNIT_C, UNIT_NONE, UNIT_PCT, UNIT_PCT, UNIT_VAR, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_NONE, UNIT_PCT, UNIT_NONE}; // mqtt discovery device classes diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 8e162274..094be658 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -422,16 +422,28 @@ class Inverter { switch (cmd) { case RealTimeRunData_Debug: if (INV_TYPE_1CH == type) { - rec->length = (uint8_t)(HM1CH_LIST_LEN); - rec->assign = (byteAssign_t *)hm1chAssignment; - rec->pyldLen = HM1CH_PAYLOAD_LEN; - channels = 1; + if(IV_HM == ivGen) { + rec->length = (uint8_t)(HM1CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm1chAssignment; + rec->pyldLen = HM1CH_PAYLOAD_LEN; + } else if(IV_HMS == ivGen) { + rec->length = (uint8_t)(HMS1CH_LIST_LEN); + rec->assign = (byteAssign_t *)hms1chAssignment; + rec->pyldLen = HMS1CH_PAYLOAD_LEN; + } + channels = 1; } else if (INV_TYPE_2CH == type) { - rec->length = (uint8_t)(HM2CH_LIST_LEN); - rec->assign = (byteAssign_t *)hm2chAssignment; - rec->pyldLen = HM2CH_PAYLOAD_LEN; - channels = 2; + if(IV_HM == ivGen) { + rec->length = (uint8_t)(HM2CH_LIST_LEN); + rec->assign = (byteAssign_t *)hm2chAssignment; + rec->pyldLen = HM2CH_PAYLOAD_LEN; + } else if(IV_HMS == ivGen) { + rec->length = (uint8_t)(HMS2CH_LIST_LEN); + rec->assign = (byteAssign_t *)hms2chAssignment; + rec->pyldLen = HMS2CH_PAYLOAD_LEN; + } + channels = 2; } else if (INV_TYPE_4CH == type) { if(IV_HM == ivGen) { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 5be82c0f..3a64c686 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -56,12 +56,13 @@ class PubMqtt { ~PubMqtt() { } - void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs) { + void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) { mCfgMqtt = cfg_mqtt; mDevName = devName; mVersion = version; mSys = sys; mUtcTimestamp = utcTs; + mUptime = uptime; mIntervalTimeout = 1; mSendIvData.setup(sys, utcTs, &mSendList); @@ -126,7 +127,7 @@ class PubMqtt { } void tickerMinute() { - snprintf(mVal, 40, "%ld", millis() / 1000); + snprintf(mVal, 40, "%d", (*mUptime)); publish(subtopics[MQTT_UPTIME], mVal); publish(subtopics[MQTT_RSSI], String(WiFi.RSSI()).c_str()); publish(subtopics[MQTT_FREE_HEAP], String(ESP.getFreeHeap()).c_str()); @@ -582,7 +583,7 @@ class PubMqtt { HMSYSTEM *mSys; PubMqttIvData mSendIvData; - uint32_t *mUtcTimestamp; + uint32_t *mUtcTimestamp, *mUptime; uint32_t mRxCnt, mTxCnt; std::queue mSendList; std::queue mAlarmList; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 11742c29..eaff9491 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -121,7 +121,8 @@ class PubMqttIvData { case FLD_YD: if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart mPos++; - mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built + if(!mIv->isAvailable(*mUtcTimestamp)) + mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built return; } retained = true; diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index ca250a3e..50a46826 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -117,6 +117,7 @@ namespace ah { protected: uint32_t mTimestamp; + uint32_t mUptime; private: inline uint8_t addTicker(scdCb c, uint32_t timeout, uint32_t reload, bool isTimestamp, const char *name) { @@ -162,7 +163,6 @@ namespace ah { sP mTicker[MAX_NUM_TICKER]; bool mTickerInUse[MAX_NUM_TICKER]; uint32_t mMillis, mPrevMillis, mDiff; - uint32_t mUptime; uint8_t mDiffSeconds; uint8_t mMax; }; diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index de5b0069..fe8256cf 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -19,7 +19,6 @@ var units, ivEn; var mIvHtml = []; var mNum = 0; - var names = ["Voltage", "Current", "Power", "Yield Day", "Yield Total", "Irradiation"]; var total = Array(5).fill(0); function parseGeneric(obj) { From 76f01bbe958c7ae3a3263ddd9499d90d04e458fe Mon Sep 17 00:00:00 2001 From: lumapu Date: Fri, 16 Jun 2023 19:00:57 +0200 Subject: [PATCH 53/92] 0.7.5 * fix yield day reset on midnight #957 * improved tickers in `app.cpp` --- src/CHANGES.md | 4 ++ src/app.cpp | 92 ++++++++++++++++++----------------- src/app.h | 1 + src/defines.h | 2 +- src/hm/hmPayload.h | 22 --------- src/publisher/pubMqtt.h | 4 ++ src/publisher/pubMqttIvData.h | 20 ++++++-- 7 files changed, 73 insertions(+), 72 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index f6e4f8b2..4815879a 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.5 - 2023-06-16 +* fix yield day reset on midnight #957 +* improved tickers in `app.cpp` + ## 0.7.4 - 2023-06-15 * fix MqTT `P_AC` send if inverters are available #987 * fix assignments for HMS 1CH and 2CH devices diff --git a/src/app.cpp b/src/app.cpp index 5ae2b845..bd060425 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -321,42 +321,14 @@ void app::tickComm(void) { //----------------------------------------------------------------------------- void app::tickZeroValues(void) { - Inverter<> *iv; - bool changed = false; - // set values to zero, except yields - for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { - iv = mSys.getInverterByPos(id); - if (NULL == iv) - continue; // skip to next inverter - - mPayload.zeroInverterValues(iv); - changed = true; - } - - if(changed) - payloadEventListener(RealTimeRunData_Debug, NULL); + zeroIvValues(false); } //----------------------------------------------------------------------------- void app::tickMinute(void) { // only triggered if 'reset values on no avail is enabled' - Inverter<> *iv; - bool changed = false; - // set values to zero, except yields - for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { - iv = mSys.getInverterByPos(id); - if (NULL == iv) - continue; // skip to next inverter - - if (!iv->isAvailable(mTimestamp) && !iv->isProducing(mTimestamp) && iv->config->enabled) { - mPayload.zeroInverterValues(iv); - changed = true; - } - } - - if(changed) - payloadEventListener(RealTimeRunData_Debug, NULL); + zeroIvValues(true); } //----------------------------------------------------------------------------- @@ -366,20 +338,7 @@ void app::tickMidnight(void) { uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); - Inverter<> *iv; - bool changed = false; - // set values to zero, except yield total - for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { - iv = mSys.getInverterByPos(id); - if (NULL == iv) - continue; // skip to next inverter - - mPayload.zeroInverterValues(iv, false); - changed = true; - } - - if(changed) - payloadEventListener(RealTimeRunData_Debug, NULL); + zeroIvValues(false, false); if (mMqttEnabled) mMqtt.tickerMidnight(); @@ -441,6 +400,51 @@ void app::tickSend(void) { updateLed(); } +//----------------------------------------------------------------------------- +void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { + Inverter<> *iv; + bool changed = false; + // set values to zero, except yields + for (uint8_t id = 0; id < mSys.getNumInverters(); id++) { + iv = mSys.getInverterByPos(id); + if (NULL == iv) + continue; // skip to next inverter + if (!iv->config->enabled) + continue; // skip to next inverter + + if (checkAvail) { + if (!iv->isAvailable(mTimestamp)) + continue; + } + + record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); + for(uint8_t ch = 0; ch <= iv->channels; ch++) { + uint8_t pos = 0; + for(uint8_t fld = 0; fld < FLD_EVT; fld++) { + switch(fld) { + case FLD_YD: + if(skipYieldDay) + continue; + else + break; + case FLD_YT: + continue; + } + pos = iv->getPosByChFld(ch, fld, rec); + iv->setValue(pos, rec, 0.0f); + } + iv->doCalculations(); + } + changed = true; + } + + if(changed) { + if(mMqttEnabled) + mMqtt.setZeroValuesEnable(); + payloadEventListener(RealTimeRunData_Debug, NULL); + } +} + //----------------------------------------------------------------------------- void app::resetSystem(void) { snprintf(mVersion, 12, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH); diff --git a/src/app.h b/src/app.h index e053cfd9..60ba9ff0 100644 --- a/src/app.h +++ b/src/app.h @@ -241,6 +241,7 @@ class app : public IApp, public ah::Scheduler { typedef std::function innerLoopCb; void resetSystem(void); + void zeroIvValues(bool checkAvail = false, bool skipYieldDay = true); void payloadEventListener(uint8_t cmd, Inverter<> *iv) { #if !defined(AP_ONLY) diff --git a/src/defines.h b/src/defines.h index f13b038d..da7fffc2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 4 +#define VERSION_PATCH 5 //------------------------------------- typedef struct { diff --git a/src/hm/hmPayload.h b/src/hm/hmPayload.h index 59f678d9..2b59cd69 100644 --- a/src/hm/hmPayload.h +++ b/src/hm/hmPayload.h @@ -95,28 +95,6 @@ class HmPayload { notify(0x0b); }*/ - void zeroInverterValues(Inverter<> *iv, bool skipYieldDay = true) { - DPRINTLN(DBG_DEBUG, F("zeroInverterValues")); - record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - for(uint8_t ch = 0; ch <= iv->channels; ch++) { - uint8_t pos = 0; - for(uint8_t fld = 0; fld < FLD_EVT; fld++) { - switch(fld) { - case FLD_YD: - if(skipYieldDay) - continue; - else - break; - case FLD_YT: - continue; - } - pos = iv->getPosByChFld(ch, fld, rec); - iv->setValue(pos, rec, 0.0f); - } - iv->doCalculations(); - } - } - void ivSendHighPrio(Inverter<> *iv) { mHighPrioIv = iv; } diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 3a64c686..d04416d2 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -240,6 +240,10 @@ class PubMqtt { } } + void setZeroValuesEnable(void) { + mSendIvData.setZeroValuesEnable(); + } + private: void onConnect(bool sessionPreset) { DPRINTLN(DBG_INFO, F("MQTT connected")); diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index eaff9491..9f8ff318 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -26,6 +26,7 @@ class PubMqttIvData { mUtcTimestamp = utcTs; mSendList = sendList; mState = IDLE; + mZeroValues = false; memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); mRTRDataHasBeenSent = false; @@ -55,6 +56,10 @@ class PubMqttIvData { mPublish = cb; } + void setZeroValuesEnable(void) { + mZeroValues = true; + } + private: enum State {IDLE, START, FIND_NXT_IV, SEND_DATA, SEND_TOTALS, NUM_STATES}; typedef void (PubMqttIvData::*StateFunction)(); @@ -101,6 +106,7 @@ class PubMqttIvData { mState = SEND_TOTALS; else { mSendList->pop(); + mZeroValues = false; mState = START; } } @@ -119,11 +125,13 @@ class PubMqttIvData { switch (rec->assign[mPos].fieldId) { case FLD_YT: case FLD_YD: - if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart - mPos++; - if(!mIv->isAvailable(*mUtcTimestamp)) - mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built - return; + if(!mZeroValues) { + if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart + mPos++; + if(!mIv->isAvailable(*mUtcTimestamp)) + mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built + return; + } } retained = true; break; @@ -188,6 +196,7 @@ class PubMqttIvData { mPos++; } else { mSendList->pop(); + mZeroValues = false; mState = START; } @@ -212,6 +221,7 @@ class PubMqttIvData { char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; + bool mZeroValues; std::queue *mSendList; }; From b6de5b9bebd8eb62cf54ddb23b00529ab44c067d Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 17 Jun 2023 08:20:41 +0200 Subject: [PATCH 54/92] Update Dockerfile update to bookworm --- tools/rpi/Dockerfile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/rpi/Dockerfile b/tools/rpi/Dockerfile index 1a62b01b..31023a09 100644 --- a/tools/rpi/Dockerfile +++ b/tools/rpi/Dockerfile @@ -2,11 +2,14 @@ # build executable binary ############################ -FROM python:slim-bullseye +FROM python:slim-bookworm COPY . /hoymiles WORKDIR /hoymiles +# RUN apt-get update \ +# && groupadd spi + RUN python3 -m pip install pyrf24 influxdb_client && \ python3 -m pip list #watch for RF24 module - if its there its installed From c1479068341492c9297032043e640e1af5241410 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 18 Jun 2023 00:20:27 +0200 Subject: [PATCH 55/92] 0.7.6 * fix display of hidden SSID checkbox * changed yield correction data type to `double`, now decimal places are supported * corrected name of 0.91" display in settings * attempt to fix MqTT zero values only if setting is there #980, #957 * made AP password configurable #951 * added option to start without time-sync, eg. for AP-only-mode #951 --- src/CHANGES.md | 8 ++++++++ src/app.cpp | 15 ++------------- src/config/settings.h | 10 +++++++++- src/defines.h | 2 +- src/publisher/pubMqtt.h | 7 +++++-- src/publisher/pubMqttIvData.h | 35 ++++++++++++++++------------------- src/utils/scheduler.h | 4 ++-- src/web/RestApi.h | 2 ++ src/web/html/index.html | 8 ++++++-- src/web/html/setup.html | 21 ++++++++++++++++----- src/web/html/style.css | 5 +++++ src/web/web.h | 3 +++ src/wifi/ahoywifi.cpp | 4 ++-- 13 files changed, 77 insertions(+), 47 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 4815879a..ed280f46 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,13 @@ # Development Changes +## 0.7.6 - 2023-06-17 +* fix display of hidden SSID checkbox +* changed yield correction data type to `double`, now decimal places are supported +* corrected name of 0.91" display in settings +* attempt to fix MqTT zero values only if setting is there #980, #957 +* made AP password configurable #951 +* added option to start without time-sync, eg. for AP-only-mode #951 + ## 0.7.5 - 2023-06-16 * fix yield day reset on midnight #957 * improved tickers in `app.cpp` diff --git a/src/app.cpp b/src/app.cpp index bd060425..fc5f6b0f 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -17,12 +17,12 @@ void app::setup() { while (!Serial) yield(); - ah::Scheduler::setup(); resetSystem(); mSettings.setup(); mSettings.getPtr(mConfig); + ah::Scheduler::setup(mConfig->inst.startWithoutTime); DPRINT(DBG_INFO, F("Settings valid: ")); if (mSettings.getValid()) DBGPRINTLN(F("true")); @@ -67,10 +67,6 @@ void app::setup() { mHmsPayload.enableSerialDebug(mConfig->serial.debug); mHmsPayload.addPayloadListener(std::bind(&app::payloadEventListener, this, std::placeholders::_1, std::placeholders::_2)); #endif - /*DBGPRINTLN("--- after payload"); - DBGPRINTLN(String(ESP.getFreeHeap())); - DBGPRINTLN(String(ESP.getHeapFragmentation())); - DBGPRINTLN(String(ESP.getMaxFreeBlockSize()));*/ if(mConfig->nrf.enabled) { if (!mNrfRadio.isChipConnected()) @@ -101,12 +97,6 @@ void app::setup() { mPubSerial.setup(mConfig, &mSys, &mTimestamp); regularTickers(); - - - // DBGPRINTLN("--- end setup"); - // DBGPRINTLN(String(ESP.getFreeHeap())); - // DBGPRINTLN(String(ESP.getHeapFragmentation())); - // DBGPRINTLN(String(ESP.getMaxFreeBlockSize())); } //----------------------------------------------------------------------------- @@ -253,7 +243,6 @@ void app::tickNtpUpdate(void) { } // immediately start communicating - // @TODO: leads to reboot loops? not sure #674 if (isOK && mSendFirst) { mSendFirst = false; once(std::bind(&app::tickSend, this), 2, "senOn"); @@ -439,7 +428,7 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { } if(changed) { - if(mMqttEnabled) + if(mMqttEnabled && !skipYieldDay) mMqtt.setZeroValuesEnable(); payloadEventListener(RealTimeRunData_Debug, NULL); } diff --git a/src/config/settings.h b/src/config/settings.h index 610b2fef..2fdcab0e 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -68,6 +68,7 @@ typedef struct { // wifi char stationSsid[SSID_LEN]; char stationPwd[PWD_LEN]; + char apPwd[PWD_LEN]; bool isHidden; cfgIp_t ip; @@ -131,7 +132,7 @@ typedef struct { char name[MAX_NAME_LENGTH]; serial_u serial; uint16_t chMaxPwr[6]; - int32_t yieldCor[6]; // signed YieldTotal correction value + double yieldCor[6]; // signed YieldTotal correction value char chName[6][MAX_NAME_LENGTH]; } cfgIv_t; @@ -142,6 +143,7 @@ typedef struct { bool rstYieldMidNight; bool rstValsNotAvail; bool rstValsCommStop; + bool startWithoutTime; } cfgInst_t; typedef struct { @@ -360,6 +362,7 @@ class settings { else { snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID); snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD); + snprintf(mCfg.sys.apPwd, PWD_LEN, WIFI_AP_PWD); mCfg.sys.isHidden = false; } @@ -404,6 +407,7 @@ class settings { mCfg.inst.rstYieldMidNight = false; mCfg.inst.rstValsNotAvail = false; mCfg.inst.rstValsCommStop = false; + mCfg.inst.startWithoutTime = false; mCfg.led.led0 = DEF_PIN_OFF; mCfg.led.led1 = DEF_PIN_OFF; @@ -428,6 +432,7 @@ class settings { char buf[16]; obj[F("ssid")] = mCfg.sys.stationSsid; obj[F("pwd")] = mCfg.sys.stationPwd; + obj[F("ap_pwd")] = mCfg.sys.apPwd; obj[F("hidd")] = (bool) mCfg.sys.isHidden; obj[F("dev")] = mCfg.sys.deviceName; obj[F("adm")] = mCfg.sys.adminPwd; @@ -441,6 +446,7 @@ class settings { } else { getChar(obj, F("ssid"), mCfg.sys.stationSsid, SSID_LEN); getChar(obj, F("pwd"), mCfg.sys.stationPwd, PWD_LEN); + getChar(obj, F("ap_pwd"), mCfg.sys.apPwd, PWD_LEN); getVal(obj, F("hidd"), &mCfg.sys.isHidden); getChar(obj, F("dev"), mCfg.sys.deviceName, DEVNAME_LEN); getChar(obj, F("adm"), mCfg.sys.adminPwd, PWD_LEN); @@ -617,12 +623,14 @@ class settings { obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight; obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail; obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; + obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime; } else { getVal(obj, F("en"), &mCfg.inst.enabled); getVal(obj, F("rstMidNight"), &mCfg.inst.rstYieldMidNight); getVal(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail); getVal(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop); + getVal(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime); } JsonArray ivArr; diff --git a/src/defines.h b/src/defines.h index da7fffc2..caa556eb 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 5 +#define VERSION_PATCH 6 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index d04416d2..c6723396 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -52,6 +52,7 @@ class PubMqtt { memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); mLastAnyAvail = false; + mZeroValues = false; } ~PubMqtt() { } @@ -241,7 +242,7 @@ class PubMqtt { } void setZeroValuesEnable(void) { - mSendIvData.setZeroValuesEnable(); + mZeroValues = true; } private: @@ -574,7 +575,8 @@ class PubMqtt { if(mSendList.empty()) return; - mSendIvData.start(); + mSendIvData.start(mZeroValues); + mZeroValues = false; mLastAnyAvail = anyAvail; } @@ -593,6 +595,7 @@ class PubMqtt { std::queue mAlarmList; subscriptionCb mSubscriptionCb; bool mLastAnyAvail; + bool mZeroValues; uint8_t mLastIvState[MAX_NUM_INVERTERS]; uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 9f8ff318..eb1bdb1c 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -43,10 +43,11 @@ class PubMqttIvData { yield(); } - bool start(void) { + bool start(bool zeroValues = false) { if(IDLE != mState) return false; + mZeroValues = zeroValues; mRTRDataHasBeenSent = false; mState = START; return true; @@ -56,10 +57,6 @@ class PubMqttIvData { mPublish = cb; } - void setZeroValuesEnable(void) { - mZeroValues = true; - } - private: enum State {IDLE, START, FIND_NXT_IV, SEND_DATA, SEND_TOTALS, NUM_STATES}; typedef void (PubMqttIvData::*StateFunction)(); @@ -100,8 +97,11 @@ class PubMqttIvData { mLastIvId++; mPos = 0; - if(found) + if(found) { mState = SEND_DATA; + if(!mIv->isAvailable(*mUtcTimestamp)) + mSendTotals = false; // avoid send total values on not producing, because the sum of values is not built + } else if(mSendTotals) mState = SEND_TOTALS; else { @@ -122,19 +122,16 @@ class PubMqttIvData { if(mPos < rec->length) { bool retained = false; if (mCmd == RealTimeRunData_Debug) { - switch (rec->assign[mPos].fieldId) { - case FLD_YT: - case FLD_YD: - if(!mZeroValues) { - if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart - mPos++; - if(!mIv->isAvailable(*mUtcTimestamp)) - mSendTotals = false; // avoid send total values on not producing, because the sum of values is no built - return; - } + if(FLD_YT == rec->assign[mPos].fieldId) + retained = true; + else if(FLD_YD == rec->assign[mPos].fieldId) { + if(!mZeroValues) { + if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart + mPos++; + return; } - retained = true; - break; + } + retained = true; } // calculate total values for RealTimeRunData_Debug @@ -221,7 +218,7 @@ class PubMqttIvData { char mSubTopic[32 + MAX_NAME_LENGTH + 1]; char mVal[40]; - bool mZeroValues; + bool mZeroValues; // makes sure that yield day is sent even if no inverter is online std::queue *mSendList; }; diff --git a/src/utils/scheduler.h b/src/utils/scheduler.h index 50a46826..954ae18a 100644 --- a/src/utils/scheduler.h +++ b/src/utils/scheduler.h @@ -31,9 +31,9 @@ namespace ah { public: Scheduler() {} - void setup() { + void setup(bool directStart) { mUptime = 0; - mTimestamp = 0; + mTimestamp = (directStart) ? 1 : 0; mMax = 0; mPrevMillis = millis(); resetTicker(); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 35c22e44..e2fefd86 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -206,6 +206,7 @@ class RestApi { void getSysInfo(AsyncWebServerRequest *request, JsonObject obj) { obj[F("ssid")] = mConfig->sys.stationSsid; + obj[F("ap_pwd")] = mConfig->sys.apPwd; obj[F("hidd")] = mConfig->sys.isHidden; obj[F("device_name")] = mConfig->sys.deviceName; obj[F("dark_mode")] = (bool)mConfig->sys.darkMode; @@ -326,6 +327,7 @@ class RestApi { obj[F("rstMid")] = (bool)mConfig->inst.rstYieldMidNight; obj[F("rstNAvail")] = (bool)mConfig->inst.rstValsNotAvail; obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop; + obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime; } void getInverter(JsonObject obj, uint8_t id) { diff --git a/src/web/html/index.html b/src/web/html/index.html index 72537e5e..2799598f 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -88,8 +88,12 @@ + ("0"+min).substr(-2) + ":" + ("0"+sec).substr(-2); var dSpan = document.getElementById("date"); - if(0 != obj["ts_now"]) - dSpan.innerHTML = date.toLocaleString('de-DE'); + if(0 != obj["ts_now"]) { + if(obj["ts_now"] < 1680000000) + setTime(); + else + dSpan.innerHTML = date.toLocaleString('de-DE'); + } else { dSpan.innerHTML = ""; var e = inp("set", "sync from browser", 0, ["btn"], "set", "button"); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 01d481c2..c968e390 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -55,6 +55,12 @@
WiFi + +
+
AP Password (min. length: 8)
+
+
+

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

@@ -72,11 +78,11 @@
SSID
-
+
-
hidden SSID
-
+
SSID is hidden
+
Password
@@ -162,6 +168,10 @@
Reset values when inverter status is 'not available'
+
+
Start without time sync (useful in AP-Only-Mode)
+
+
@@ -616,10 +626,11 @@ document.getElementsByName(i[0])[0].value = obj[i[1]]; for(var i of [["Mid", "rstMid"], ["ComStop", "rstComStop"], ["NotAvail", "rstNAvail"]]) document.getElementsByName("invRst"+i[0])[0].checked = obj[i[1]]; + document.getElementsByName("strtWthtTm")[0].checked = obj["strtWthtTm"]; } function parseSys(obj) { - for(var i of [["device", "device_name"], ["ssid", "ssid"]]) + for(var i of [["device", "device_name"], ["ssid", "ssid"], ["ap_pwd", "ap_pwd"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; document.getElementsByName("hidd")[0].checked = obj["hidd"]; document.getElementsByName("darkMode")[0].checked = obj["dark_mode"]; @@ -789,7 +800,7 @@ ); } - var opts = [[0, "None"], [1, "SSD1306 0.96\" 128X64"], [2, "SH1106 1.3\""], [3, "Nokia5110"], [4, "SSD1306 0.96\" 128X32"]]; + var opts = [[0, "None"], [1, "SSD1306 0.96\" 128X64"], [2, "SH1106 1.3\""], [3, "Nokia5110"], [4, "SSD1306 0.91\" 128X32"]]; if("ESP32" == type) opts.push([10, "ePaper"]); var dispType = sel("disp_typ", opts, obj["disp_typ"]); diff --git a/src/web/html/style.css b/src/web/html/style.css index bb231881..fdbf5aa7 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -475,6 +475,11 @@ input[type=text], input[type=password], select, input[type=number] { color: var(--fg); } +input:invalid { + border: 2px solid #f00 !important; + background-color: #400 !important; +} + input.sh { max-width: 150px !important; margin-right: 10px; diff --git a/src/web/web.h b/src/web/web.h index 0b7ca7de..92b024ac 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -448,6 +448,8 @@ class Web { request->arg("ssid").toCharArray(mConfig->sys.stationSsid, SSID_LEN); if (request->arg("pwd") != "{PWD}") request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN); + if (request->arg("ap_pwd") != "") + request->arg("ap_pwd").toCharArray(mConfig->sys.apPwd, PWD_LEN); mConfig->sys.isHidden = (request->arg("hidd") == "on"); if (request->arg("device") != "") request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN); @@ -521,6 +523,7 @@ class Web { mConfig->inst.rstYieldMidNight = (request->arg("invRstMid") == "on"); mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on"); mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on"); + mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on"); // pinout uint8_t pin; diff --git a/src/wifi/ahoywifi.cpp b/src/wifi/ahoywifi.cpp index 6def5282..933ffff7 100644 --- a/src/wifi/ahoywifi.cpp +++ b/src/wifi/ahoywifi.cpp @@ -170,7 +170,7 @@ void ahoywifi::setupAp(void) { DBGPRINT(F("\n---------\nAP MODE\nSSID: ")); DBGPRINTLN(WIFI_AP_SSID); DBGPRINT(F("PWD: ")); - DBGPRINTLN(WIFI_AP_PWD); + DBGPRINTLN(mConfig->sys.apPwd); DBGPRINT(F("IP Address: http://")); DBGPRINTLN(mApIp.toString()); DBGPRINTLN(F("---------\n")); @@ -180,7 +180,7 @@ void ahoywifi::setupAp(void) { WiFi.mode(WIFI_AP_STA); WiFi.softAPConfig(mApIp, mApIp, IPAddress(255, 255, 255, 0)); - WiFi.softAP(WIFI_AP_SSID, WIFI_AP_PWD); + WiFi.softAP(WIFI_AP_SSID, mConfig->sys.apPwd); } From 0118fd1431176e2add1d1421e45af2b005c6bd00 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 18 Jun 2023 01:03:55 +0200 Subject: [PATCH 56/92] fix yield correction (data type was not correct during save) --- src/config/settings.h | 2 +- src/web/RestApi.h | 2 +- src/web/html/setup.html | 2 +- src/web/web.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/config/settings.h b/src/config/settings.h index 2fdcab0e..2f35295d 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -132,7 +132,7 @@ typedef struct { char name[MAX_NAME_LENGTH]; serial_u serial; uint16_t chMaxPwr[6]; - double yieldCor[6]; // signed YieldTotal correction value + double yieldCor[6]; // YieldTotal correction value char chName[6][MAX_NAME_LENGTH]; } cfgIv_t; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index e2fefd86..20a7245d 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -315,7 +315,7 @@ class RestApi { obj2[F("version")] = String(iv->getFwVersion()); for(uint8_t j = 0; j < iv->channels; j ++) { - obj2[F("ch_yield_cor")][j] = iv->config->yieldCor[j]; + obj2[F("ch_yield_cor")][j] = (double)iv->config->yieldCor[j]; obj2[F("ch_name")][j] = iv->config->chName[j]; obj2[F("ch_max_pwr")][j] = iv->config->chMaxPwr[j]; } diff --git a/src/web/html/setup.html b/src/web/html/setup.html index c968e390..4f1f7b6a 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -593,7 +593,7 @@ for(var j of [ ["ModPwr", "ch_max_pwr", "Max Module Power (Wp)", 4, "[0-9]+"], ["ModName", "ch_name", "Module Name", 15, null], - ["YieldCor", "ch_yield_cor", "Yield Total Correction [kWh]", 8, "[0-9-]+"]]) { + ["YieldCor", "ch_yield_cor", "Yield Total Correction [kWh]", 8, "[0-9-\.]+"]]) { var cl = (re.test(obj["serial"])) ? "" : " hide"; diff --git a/src/web/web.h b/src/web/web.h index 92b024ac..b8841f2e 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -509,7 +509,7 @@ class Web { // max channel power / name for (uint8_t j = 0; j < 6; j++) { - iv->config->yieldCor[j] = request->arg("inv" + String(i) + "YieldCor" + String(j)).toInt(); + iv->config->yieldCor[j] = request->arg("inv" + String(i) + "YieldCor" + String(j)).toDouble(); iv->config->chMaxPwr[j] = request->arg("inv" + String(i) + "ModPwr" + String(j)).toInt() & 0xffff; request->arg("inv" + String(i) + "ModName" + String(j)).toCharArray(iv->config->chName[j], MAX_NAME_LENGTH); } From d6d93a3c26f1727bf4bf4bfd3c5bf111aea1083e Mon Sep 17 00:00:00 2001 From: rmom Date: Sat, 24 Jun 2023 19:14:27 +0200 Subject: [PATCH 57/92] Implemented quick fix for #889 from anorak-47 --- src/publisher/pubMqtt.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index c6723396..95f45b65 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -314,7 +314,9 @@ class PubMqtt { delete[] pyld; } - const char *p = topic; + # quick fix for #889 + # initial line: const char *p = topic; + const char *p = topic + strlen(mCfgMqtt->topic); uint8_t pos = 0; uint8_t elm = 0; char tmp[30]; From 45e02b94c325848724d5b8478782a755d9829436 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 3 Jul 2023 22:10:49 +0200 Subject: [PATCH 58/92] 0.7.7 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ed280f46..ee3c6740 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.7.7 - 2023-07-03 +* attempt to fix MqTT `YieldDay` in `TotalValues` #927 + ## 0.7.6 - 2023-06-17 * fix display of hidden SSID checkbox * changed yield correction data type to `double`, now decimal places are supported diff --git a/src/defines.h b/src/defines.h index caa556eb..21803069 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 6 +#define VERSION_PATCH 7 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index eb1bdb1c..f998aeda 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -100,7 +100,7 @@ class PubMqttIvData { if(found) { mState = SEND_DATA; if(!mIv->isAvailable(*mUtcTimestamp)) - mSendTotals = false; // avoid send total values on not producing, because the sum of values is not built + mSendTotals = false; // avoid send total values on no availability, because the sum of values is not built } else if(mSendTotals) mState = SEND_TOTALS; @@ -125,12 +125,12 @@ class PubMqttIvData { if(FLD_YT == rec->assign[mPos].fieldId) retained = true; else if(FLD_YD == rec->assign[mPos].fieldId) { - if(!mZeroValues) { + /*if(!mZeroValues) { if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart mPos++; return; } - } + }*/ retained = true; } From 982c201d4811592b8ae927ca4755e99043863d9b Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 3 Jul 2023 22:29:38 +0200 Subject: [PATCH 59/92] 0.7.7 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 * attempt to fix MqTT `YieldDay` and `YieldTotal` even if inverters are not completly available #929 * fix wrong message 'NRF not connected' if it is disabled #1007 --- src/CHANGES.md | 2 ++ src/publisher/pubMqttIvData.h | 22 +++++++--------------- src/web/RestApi.h | 4 ++-- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ee3c6740..5907f51d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,8 @@ ## 0.7.7 - 2023-07-03 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 +* attempt to fix MqTT `YieldDay` and `YieldTotal` even if inverters are not completly available #929 +* fix wrong message 'NRF not connected' if it is disabled #1007 ## 0.7.6 - 2023-06-17 * fix display of hidden SSID checkbox diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index f998aeda..58880f72 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -71,8 +71,7 @@ class PubMqttIvData { mCmd = mSendList->front().cmd; mIvSend = mSendList->front().iv; - if((RealTimeRunData_Debug != mCmd) || !mRTRDataHasBeenSent) { - mSendTotals = (RealTimeRunData_Debug == mCmd); + if((RealTimeRunData_Debug != mCmd) || !mRTRDataHasBeenSent) { // send RealTimeRunData only once memset(mTotal, 0, sizeof(float) * 4); mState = FIND_NXT_IV; } else @@ -97,18 +96,10 @@ class PubMqttIvData { mLastIvId++; mPos = 0; - if(found) { + if(found) mState = SEND_DATA; - if(!mIv->isAvailable(*mUtcTimestamp)) - mSendTotals = false; // avoid send total values on no availability, because the sum of values is not built - } - else if(mSendTotals) + else mState = SEND_TOTALS; - else { - mSendList->pop(); - mZeroValues = false; - mState = START; - } } void stateSend() { @@ -138,7 +129,8 @@ class PubMqttIvData { if (CH0 == rec->assign[mPos].ch) { switch (rec->assign[mPos].fieldId) { case FLD_PAC: - mTotal[0] += mIv->getValue(mPos, rec); + if(mIv->isProducing(*mUtcTimestamp)) + mTotal[0] += mIv->getValue(mPos, rec); break; case FLD_YT: mTotal[1] += mIv->getValue(mPos, rec); @@ -147,7 +139,8 @@ class PubMqttIvData { mTotal[2] += mIv->getValue(mPos, rec); break; case FLD_PDC: - mTotal[3] += mIv->getValue(mPos, rec); + if(mIv->isProducing(*mUtcTimestamp)) + mTotal[3] += mIv->getValue(mPos, rec); break; } } @@ -208,7 +201,6 @@ class PubMqttIvData { uint8_t mCmd; uint8_t mLastIvId; - bool mSendTotals; float mTotal[4]; Inverter<> *mIv, *mIvSend; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 20a7245d..b95065b7 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -469,9 +469,9 @@ class RestApi { } JsonArray warn = obj.createNestedArray(F("warnings")); - if(!mRadio->isChipConnected()) + if(!mRadio->isChipConnected() && mConfig->nrf.enabled) warn.add(F("your NRF24 module can't be reached, check the wiring, pinout and enable")); - else if(!mRadio->isPVariant()) + else if(!mRadio->isPVariant() && mConfig->nrf.enabled) warn.add(F("your NRF24 module isn't a plus version(+), maybe incompatible")); if(!mApp->getSettingsValid()) warn.add(F("your settings are invalid")); From cb3080e177dfa7e3e627a2faf687e7e77df8b46b Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 5 Jul 2023 23:19:11 +0200 Subject: [PATCH 60/92] 0.7.8 * fix `YieldDay`, `YieldTotal` and `P_AC` in `TotalValues` #929 * fix some serial debug prints --- src/CHANGES.md | 4 ++++ src/defines.h | 2 +- src/hms/hmsPayload.h | 14 ++++++-------- src/publisher/pubMqttIvData.h | 4 ++-- 4 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 5907f51d..c461ab31 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.8 - 2023-07-05 +* fix `YieldDay`, `YieldTotal` and `P_AC` in `TotalValues` #929 +* fix some serial debug prints + ## 0.7.7 - 2023-07-03 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 * attempt to fix MqTT `YieldDay` and `YieldTotal` even if inverters are not completly available #929 diff --git a/src/defines.h b/src/defines.h index 21803069..45782b7a 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 7 +#define VERSION_PATCH 8 //------------------------------------- typedef struct { diff --git a/src/hms/hmsPayload.h b/src/hms/hmsPayload.h index fdef3e45..5c7a08d2 100644 --- a/src/hms/hmsPayload.h +++ b/src/hms/hmsPayload.h @@ -114,7 +114,7 @@ class HmsPayload { yield(); if (mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F(") Requesting Inv SN ")); + DBGPRINT(F("Requesting Inv SN ")); DBGPRINTLN(String(iv->config->serial.u64, HEX)); } @@ -122,7 +122,7 @@ class HmsPayload { if (iv->getDevControlRequest()) { if (mSerialDebug) { DPRINT_IVID(DBG_INFO, iv->id); - DBGPRINT(F(") Devcontrol request 0x")); + DBGPRINT(F("Devcontrol request 0x")); DBGPRINT(String(iv->devControlCmd, HEX)); DBGPRINT(F(" power limit ")); DBGPRINTLN(String(iv->powerLimit[0])); @@ -182,14 +182,13 @@ class HmsPayload { mApp->setMqttPowerLimitAck(iv); else ok = false; - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); + DPRINT_IVID(DBG_INFO, iv->id); DBGPRINT(F(" has ")); if(!ok) DBGPRINT(F("not ")); DBGPRINT(F("accepted power limit set point ")); DBGPRINT(String(iv->powerLimit[0])); DBGPRINT(F(" with PowerLimitControl ")); - DBGPRINT(String(iv->powerLimit[1])); + DBGPRINTLN(String(iv->powerLimit[1])); iv->clearCmdQueue(); iv->enqueCommand(SystemConfigPara); // read back power limit @@ -235,9 +234,8 @@ class HmsPayload { //DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") prepareDevInformCmd 0x") + String(mPayload[iv->id].txCmd, HEX)); //mRadio->prepareDevInformCmd(iv->radioId.u64, mPayload[iv->id].txCmd, mPayload[iv->id].ts, iv->alarmMesIndex, true); - DPRINT(DBG_INFO, F("(#")); - DBGPRINT(String(iv->id)); - DBGPRINTLN(F(") nothing received")); + DPRINT_IVID(DBG_INFO, iv->id); + DBGPRINTLN(F("nothing received")); mPayload[iv->id].retransmits = mMaxRetrans; } else { for (uint8_t i = 0; i < (mPayload[iv->id].maxPackId - 1); i++) { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 58880f72..111bbd37 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -129,7 +129,7 @@ class PubMqttIvData { if (CH0 == rec->assign[mPos].ch) { switch (rec->assign[mPos].fieldId) { case FLD_PAC: - if(mIv->isProducing(*mUtcTimestamp)) + if(mIv->isAvailable(*mUtcTimestamp)) mTotal[0] += mIv->getValue(mPos, rec); break; case FLD_YT: @@ -139,7 +139,7 @@ class PubMqttIvData { mTotal[2] += mIv->getValue(mPos, rec); break; case FLD_PDC: - if(mIv->isProducing(*mUtcTimestamp)) + if(mIv->isAvailable(*mUtcTimestamp)) mTotal[3] += mIv->getValue(mPos, rec); break; } From eaa0c51bcf683f9577cedaee602e8dbbd2fc2d79 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 5 Jul 2023 23:23:57 +0200 Subject: [PATCH 61/92] 0.7.8 * merge PR #1005 which fixes issue #889 * merge homeassistant PR #963 --- src/CHANGES.md | 2 ++ src/publisher/pubMqtt.h | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index c461ab31..68742e3f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -3,6 +3,8 @@ ## 0.7.8 - 2023-07-05 * fix `YieldDay`, `YieldTotal` and `P_AC` in `TotalValues` #929 * fix some serial debug prints +* merge PR #1005 which fixes issue #889 +* merge homeassistant PR #963 ## 0.7.7 - 2023-07-03 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 95f45b65..60a826a0 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -314,8 +314,6 @@ class PubMqtt { delete[] pyld; } - # quick fix for #889 - # initial line: const char *p = topic; const char *p = topic + strlen(mCfgMqtt->topic); uint8_t pos = 0; uint8_t elm = 0; From 70b4f6bc2de827092507607701d543bb32b91de3 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 5 Jul 2023 23:31:45 +0200 Subject: [PATCH 62/92] 0.7.8 * merge PR #890 which gives option for scheduled reboot at midnight (default off) --- src/CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/CHANGES.md b/src/CHANGES.md index 68742e3f..1eae1916 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -5,6 +5,7 @@ * fix some serial debug prints * merge PR #1005 which fixes issue #889 * merge homeassistant PR #963 +* merge PR #890 which gives option for scheduled reboot at midnight (default off) ## 0.7.7 - 2023-07-03 * attempt to fix MqTT `YieldDay` in `TotalValues` #927 From baf392f2e98a259633cb4a38821c853d7337aba9 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 8 Jul 2023 23:47:40 +0200 Subject: [PATCH 63/92] 0.7.10 * fix MqTT endless loop #1013 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 97705c3d..37195152 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.7.10 - 2023-07-08 +* fix MqTT endless loop #1013 + ## 0.7.9 - 2023-07-08 * added 'improve' functions to set wifi password directly with ESP web tools #1014 * fixed MqTT publish while appling power limit #1013 diff --git a/src/defines.h b/src/defines.h index 40e56d23..19042100 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 9 +#define VERSION_PATCH 10 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 1a697388..475f40ce 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -101,6 +101,8 @@ class PubMqttIvData { mState = SEND_DATA; else if(mSendTotals) mState = SEND_TOTALS; + else + mState = START; } void stateSend() { From 0be3a23603bef416d779e779cd784bfa761de044 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 9 Jul 2023 11:19:31 +0200 Subject: [PATCH 64/92] 0.7.11 * fix MqTT endless loop #1013 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 37195152..6590e708 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.7.11 - 2023-07-09 +* fix MqTT endless loop #1013 + ## 0.7.10 - 2023-07-08 * fix MqTT endless loop #1013 diff --git a/src/defines.h b/src/defines.h index 19042100..6cb90b55 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 10 +#define VERSION_PATCH 11 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 475f40ce..1b2827b1 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -101,8 +101,11 @@ class PubMqttIvData { mState = SEND_DATA; else if(mSendTotals) mState = SEND_TOTALS; - else + else { + mSendList->pop(); + mZeroValues = false; mState = START; + } } void stateSend() { From 60f2876d9cf75ec80739a0ed7a8b2bf79e554dc6 Mon Sep 17 00:00:00 2001 From: Andy Voigt Date: Thu, 13 Jul 2023 14:06:05 +0200 Subject: [PATCH 65/92] Fixed index out of bounds --- tools/rpi/hoymiles/decoders/__init__.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index ad49d664..279d54c0 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -154,15 +154,16 @@ class StatusResponse(Response): while s_exists: s_exists = False string_id = len(strings) - string = {} - string['name'] = self.inv_strings[string_id]['s_name'] - for key in self.string_keys: - prop = f'dc_{key}_{string_id}' - if hasattr(self, prop): - s_exists = True - string[key] = getattr(self, prop) - if s_exists: - strings.append(string) + if string_id < len(self.inv_strings): + string = {} + string['name'] = self.inv_strings[string_id]['s_name'] + for key in self.string_keys: + prop = f'dc_{key}_{string_id}' + if hasattr(self, prop): + s_exists = True + string[key] = getattr(self, prop) + if s_exists: + strings.append(string) return strings From 1dc66037ad61908bd70ecb54b825c9a7660c0196 Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sat, 15 Jul 2023 20:53:15 +0200 Subject: [PATCH 66/92] -add mono display "Wemos OLED shield 64x48" - remove senseless "display type" check (copy&paste from first display) - reorder displays --- src/.vscode/settings.json | 5 +- src/plugins/Display/Display.h | 11 +- src/plugins/Display/Display_Mono_128X32.h | 2 - src/plugins/Display/Display_Mono_128X64.h | 5 +- src/plugins/Display/Display_Mono_64X48.h | 131 ++++++++++++++++++++++ src/plugins/Display/Display_Mono_84X48.h | 9 +- src/web/html/setup.html | 2 +- 7 files changed, 148 insertions(+), 17 deletions(-) create mode 100644 src/plugins/Display/Display_Mono_64X48.h diff --git a/src/.vscode/settings.json b/src/.vscode/settings.json index 58a2c3c7..e61851fb 100644 --- a/src/.vscode/settings.json +++ b/src/.vscode/settings.json @@ -8,7 +8,7 @@ "files.eol": "\n", "files.trimTrailingWhitespace": true, "diffEditor.ignoreTrimWhitespace": true, - "files.autoSave": "afterDelay", + "files.autoSave": "off", "editor.tabSize": 4, "editor.insertSpaces": true, // `editor.tabSize` and `editor.insertSpaces` will be detected based on the file contents. @@ -79,7 +79,8 @@ "mutex": "cpp", "ranges": "cpp", "stop_token": "cpp", - "thread": "cpp" + "thread": "cpp", + "variant": "cpp" }, "cmake.configureOnOpen": false, "editor.formatOnSave": false, diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index ba187c7d..fee4e35e 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -10,6 +10,7 @@ #include "Display_Mono_128X32.h" #include "Display_Mono_128X64.h" #include "Display_Mono_84X48.h" +#include "Display_Mono_64X48.h" #include "Display_ePaper.h" template @@ -30,9 +31,8 @@ class Display { if ((0 < mCfg->type) && (mCfg->type < 10)) { switch (mCfg->type) { + case 1: // fall-through case 2: - case 1: - default: mMono = new DisplayMono128X64(); break; case 3: @@ -41,6 +41,13 @@ class Display { case 4: mMono = new DisplayMono128X32(); break; + case 5: + mMono = new DisplayMono64X48(); + break; + + default: + mMono = new DisplayMono128X64(); + break; } mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); diff --git a/src/plugins/Display/Display_Mono_128X32.h b/src/plugins/Display/Display_Mono_128X32.h index 9d5ade7e..e9e09d28 100644 --- a/src/plugins/Display/Display_Mono_128X32.h +++ b/src/plugins/Display/Display_Mono_128X32.h @@ -21,8 +21,6 @@ class DisplayMono128X32 : public DisplayMono { void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { - if((0 == type) || (type > 4)) - return; u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); mType = type; diff --git a/src/plugins/Display/Display_Mono_128X64.h b/src/plugins/Display/Display_Mono_128X64.h index 3d4f91ee..a828816c 100644 --- a/src/plugins/Display/Display_Mono_128X64.h +++ b/src/plugins/Display/Display_Mono_128X64.h @@ -19,8 +19,6 @@ class DisplayMono128X64 : public DisplayMono { } void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { - if((0 == type) || (type > 4)) - return; u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); mType = type; @@ -65,8 +63,7 @@ class DisplayMono128X64 : public DisplayMono { mDisplay->clearBuffer(); // set Contrast of the Display to raise the lifetime - if (3 != mType) - mDisplay->setContrast(mLuminance); + mDisplay->setContrast(mLuminance); if ((totalPower > 0) && (isprod > 0)) { mTimeout = DISP_DEFAULT_TIMEOUT; diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h new file mode 100644 index 00000000..5c3a95f4 --- /dev/null +++ b/src/plugins/Display/Display_Mono_64X48.h @@ -0,0 +1,131 @@ +//----------------------------------------------------------------------------- +// 2023 Ahoy, https://ahoydtu.de +// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed +//----------------------------------------------------------------------------- + +#pragma once +#include "Display_Mono.h" + +class DisplayMono64X48 : public DisplayMono { + public: + DisplayMono64X48() : DisplayMono() { + mEnPowerSafe = true; + mEnScreenSaver = true; + mLuminance = 50; + mExtra = 0; + mDispY = 0; + mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds) + mUtcTs = NULL; + mType = 0; + } + + void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { + + u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); + mType = type; + + // Wemos OLed Shield is not defined in u8 lib -> use nearest compatible + mDisplay = new U8G2_SSD1306_64X48_ER_F_HW_I2C(rot, reset, clock, data); + + mUtcTs = utcTs; + + mDisplay->begin(); + calcLinePositions(); + + mDisplay->clearBuffer(); + mDisplay->setContrast(mLuminance); + + printText("AHOY!", 0); + printText("ahoydtu.de", 2); + printText(version, 3); + mDisplay->sendBuffer(); + } + + void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { + mEnPowerSafe = enPowerSafe; + mEnScreenSaver = enScreenSaver; + mLuminance = lum; + } + + void loop(void) { + if (mEnPowerSafe) { + if (mTimeout != 0) + mTimeout--; + } + } + + void disp(float totalPower, float totalYieldDay, float totalYieldTotal, uint8_t isprod) { + mDisplay->clearBuffer(); + + // set Contrast of the Display to raise the lifetime + mDisplay->setContrast(mLuminance); + + if ((totalPower > 0) && (isprod > 0)) { + mTimeout = DISP_DEFAULT_TIMEOUT; + mDisplay->setPowerSave(false); + + if (totalPower > 999) + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%2.2f kW", (totalPower / 1000)); + else + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%3.0f W", totalPower); + + printText(mFmtText, 0); + } else { + printText("offline", 0); + // check if it's time to enter power saving mode + if (mTimeout == 0) + mDisplay->setPowerSave(mEnPowerSafe); + } + + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); + printText(mFmtText, 1); + + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); + printText(mFmtText, 2); + + IPAddress ip = WiFi.localIP(); + if (!(mExtra % 10) && (ip)) + printText(ip.toString().c_str(), 3); + else if (!(mExtra % 5)) { + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); + printText(mFmtText, 3); + } else if (NULL != mUtcTs) + printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); + + mDisplay->sendBuffer(); + + mExtra = 1; + } + + private: + void calcLinePositions() { + uint8_t yOff = 0; + for (uint8_t i = 0; i < 4; i++) { + setFont(i); + yOff += (mDisplay->getMaxCharHeight()); + mLineYOffsets[i] = yOff; + } + } + + inline void setFont(uint8_t line) { + switch (line) { + case 0: + mDisplay->setFont(u8g2_font_logisoso16_tr); + break; + case 3: + mDisplay->setFont(u8g2_font_5x8_tr); + break; + default: + mDisplay->setFont(u8g2_font_5x8_tr); + break; + } + } + + void printText(const char *text, uint8_t line) { + uint8_t dispX = (line == 0) ? 10 : 5; + setFont(line); + + dispX += (mEnScreenSaver) ? (mExtra % 7) : 0; + mDisplay->drawStr(dispX, mLineYOffsets[line], text); + } +}; diff --git a/src/plugins/Display/Display_Mono_84X48.h b/src/plugins/Display/Display_Mono_84X48.h index 82aa83fa..e527ec23 100644 --- a/src/plugins/Display/Display_Mono_84X48.h +++ b/src/plugins/Display/Display_Mono_84X48.h @@ -20,8 +20,6 @@ class DisplayMono84X48 : public DisplayMono { } void init(uint8_t type, uint8_t rotation, uint8_t cs, uint8_t dc, uint8_t reset, uint8_t clock, uint8_t data, uint32_t *utcTs, const char *version) { - if((0 == type) || (type > 4)) - return; u8g2_cb_t *rot = (u8g2_cb_t *)((rotation != 0x00) ? U8G2_R2 : U8G2_R0); mType = type; @@ -33,8 +31,8 @@ class DisplayMono84X48 : public DisplayMono { calcLinePositions(); mDisplay->clearBuffer(); - if (3 != mType) - mDisplay->setContrast(mLuminance); + mDisplay->setContrast(mLuminance); + printText("AHOY!", 0); printText("ahoydtu.de", 2); printText(version, 3); @@ -58,8 +56,7 @@ class DisplayMono84X48 : public DisplayMono { mDisplay->clearBuffer(); // set Contrast of the Display to raise the lifetime - if (3 != mType) - mDisplay->setContrast(mLuminance); + mDisplay->setContrast(mLuminance); if ((totalPower > 0) && (isprod > 0)) { mTimeout = DISP_DEFAULT_TIMEOUT; diff --git a/src/web/html/setup.html b/src/web/html/setup.html index c0f7cf83..a57b9e83 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -805,7 +805,7 @@ ); } - var opts = [[0, "None"], [1, "SSD1306 0.96\" 128X64"], [2, "SH1106 1.3\""], [3, "Nokia5110"], [4, "SSD1306 0.91\" 128X32"]]; + var opts = [[0, "None"], [5, "SSD1306 0.66\" 64X48"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [2, "SH1106 1.3\""], [3, "Nokia5110"]]; if("ESP32" == type) opts.push([10, "ePaper"]); var dispType = sel("disp_typ", opts, obj["disp_typ"]); From 41ce98d2df7249f48e2f279045aa7769a6a5e9dd Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sat, 15 Jul 2023 21:32:52 +0200 Subject: [PATCH 67/92] avoid compile warning about uninitialized pointers --- src/web/web.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/web.h b/src/web/web.h index f9f04291..0b4f2616 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -701,7 +701,7 @@ class Web { // NRF Statistics stat = mApp->getStatistics(); - uint32_t *nrfSendCnt, *nrfRetransmits; + uint32_t *nrfSendCnt=NULL, *nrfRetransmits=NULL; mApp->getNrfRadioCounters(nrfSendCnt, nrfRetransmits); metrics += radioStatistic(F("rx_success"), stat->rxSuccess); metrics += radioStatistic(F("rx_fail"), stat->rxFail); From 62f96d8351493fb1042d7133cbde0490aa6efb9f Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sat, 15 Jul 2023 21:33:25 +0200 Subject: [PATCH 68/92] group display types in frontend --- src/web/html/setup.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/web/html/setup.html b/src/web/html/setup.html index a57b9e83..f5649ff7 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -805,7 +805,8 @@ ); } - var opts = [[0, "None"], [5, "SSD1306 0.66\" 64X48"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [2, "SH1106 1.3\""], [3, "Nokia5110"]]; + // keep display types grouped + var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [3, "Nokia5110"]]; if("ESP32" == type) opts.push([10, "ePaper"]); var dispType = sel("disp_typ", opts, obj["disp_typ"]); From 47d5531d05302c861ce3199a5dfb30aac88006ac Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sat, 15 Jul 2023 21:47:24 +0200 Subject: [PATCH 69/92] fix illegal memory access (pointers were missused) --- src/web/web.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/web/web.h b/src/web/web.h index 0b4f2616..70fae62e 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -701,14 +701,15 @@ class Web { // NRF Statistics stat = mApp->getStatistics(); - uint32_t *nrfSendCnt=NULL, *nrfRetransmits=NULL; - mApp->getNrfRadioCounters(nrfSendCnt, nrfRetransmits); + uint32_t nrfSendCnt; + uint32_t nrfRetransmits; + mApp->getNrfRadioCounters(&nrfSendCnt, &nrfRetransmits); metrics += radioStatistic(F("rx_success"), stat->rxSuccess); metrics += radioStatistic(F("rx_fail"), stat->rxFail); metrics += radioStatistic(F("rx_fail_answer"), stat->rxFailNoAnser); metrics += radioStatistic(F("frame_cnt"), stat->frmCnt); - metrics += radioStatistic(F("tx_cnt"), *nrfSendCnt); - metrics += radioStatistic(F("retrans_cnt"), *nrfRetransmits); + metrics += radioStatistic(F("tx_cnt"), nrfSendCnt); + metrics += radioStatistic(F("retrans_cnt"), nrfRetransmits); len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); // Next is Inverter information From c99851364ad6e3a5a71affbf138d0ded9775b23a Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sat, 15 Jul 2023 23:49:11 +0200 Subject: [PATCH 70/92] - rework "hiding Pins" to easier configure pins for new displays (using a pin map, remove hard-coded if-statements) - rework display type handling: remove uneeded checks because defined context from which functions are called - default initialize "mMono" pointer (potential illegal memory access) - define EXACTLY one display type for ePaper display (type 10). There is no need to use ranges and distinguish oled from epaper display. Simply one switch/case - correct type handling for display type (javascript). Event handler gives a string instead of number (display type) --- src/plugins/Display/Display.h | 58 ++++++++++++-------------- src/plugins/Display/Display_ePaper.cpp | 2 +- src/web/html/setup.html | 36 +++++++++------- 3 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index fee4e35e..24c5b515 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -26,37 +26,29 @@ class Display { mLoopCnt = 0; mVersion = version; - if (mCfg->type == 0) - return; + switch (mCfg->type) { + case 0: mMono = NULL; break; + case 1: // fall-through + case 2: mMono = new DisplayMono128X64(); break; + case 3: mMono = new DisplayMono84X48(); break; + case 4: mMono = new DisplayMono128X32(); break; + case 5: mMono = new DisplayMono64X48(); break; - if ((0 < mCfg->type) && (mCfg->type < 10)) { - switch (mCfg->type) { - case 1: // fall-through - case 2: - mMono = new DisplayMono128X64(); - break; - case 3: - mMono = new DisplayMono84X48(); - break; - case 4: - mMono = new DisplayMono128X32(); - break; - case 5: - mMono = new DisplayMono64X48(); - break; - - default: - mMono = new DisplayMono128X64(); - break; - } - mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); - mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); - } else if (mCfg->type >= 10) { #if defined(ESP32) - mRefreshCycle = 0; - mEpaper.config(mCfg->rot, mCfg->pwrSaveAtIvOffline); - mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); + case 10: + mMono = NULL; // ePaper does not use this + mRefreshCycle = 0; + mEpaper.config(mCfg->rot, mCfg->pwrSaveAtIvOffline); + mEpaper.init(mCfg->type, mCfg->disp_cs, mCfg->disp_dc, mCfg->disp_reset, mCfg->disp_busy, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); + break; #endif + + default: mMono = NULL; break; + } + if(mMono) + { + mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); + mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); } } @@ -104,14 +96,16 @@ class Display { totalYieldTotal += iv->getChannelFieldValue(CH0, FLD_YT, rec); } - if ((0 < mCfg->type) && (mCfg->type < 10) && (mMono != NULL)) { + if (mMono ) { mMono->disp(totalPower, totalYieldDay, totalYieldTotal, isprod); - } else if (mCfg->type >= 10) { + } #if defined(ESP32) + else if (mCfg->type == 10) { + mEpaper.loop(totalPower, totalYieldDay, totalYieldTotal, isprod); mRefreshCycle++; -#endif } +#endif #if defined(ESP32) if (mRefreshCycle > 480) { @@ -133,7 +127,7 @@ class Display { #if defined(ESP32) DisplayEPaper mEpaper; #endif - DisplayMono *mMono; + DisplayMono *mMono = NULL; //default !!! }; #endif /*__DISPLAY__*/ diff --git a/src/plugins/Display/Display_ePaper.cpp b/src/plugins/Display/Display_ePaper.cpp index 924961a3..74000180 100644 --- a/src/plugins/Display/Display_ePaper.cpp +++ b/src/plugins/Display/Display_ePaper.cpp @@ -26,7 +26,7 @@ DisplayEPaper::DisplayEPaper() { void DisplayEPaper::init(uint8_t type, uint8_t _CS, uint8_t _DC, uint8_t _RST, uint8_t _BUSY, uint8_t _SCK, uint8_t _MOSI, uint32_t *utcTs, const char *version) { mUtcTs = utcTs; - if (type > 9) { + if (type == 10) { Serial.begin(115200); _display = new GxEPD2_BW(GxEPD2_150_BN(_CS, _DC, _RST, _BUSY)); hspi.begin(_SCK, _BUSY, _MOSI, _CS); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index f5649ff7..1ee056df 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -791,6 +791,7 @@ document.getElementsByName(i)[0].checked = obj[i]; var e = document.getElementById("dispPins"); + //KEEP this order !!! var pins = [['clock', 'disp_clk'], ['data', 'disp_data'], ['cs', 'disp_cs'], ['dc', 'disp_dc'], ['reset', 'disp_rst']]; if("ESP32" == type) pins.push(['busy', 'disp_bsy']); @@ -806,7 +807,7 @@ } // keep display types grouped - var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [3, "Nokia5110"]]; + var opts = [[0, "None"], [2, "SH1106 1.3\" 128X64"], [5, "SSD1306 0.66\" 64X48 (Wemos OLED Shield)"], [4, "SSD1306 0.91\" 128X32"], [1, "SSD1306 0.96\" 128X64"], [3, "Nokia5110"]]; if("ESP32" == type) opts.push([10, "ePaper"]); var dispType = sel("disp_typ", opts, obj["disp_typ"]); @@ -817,7 +818,7 @@ ]) ); dispType.addEventListener('change', (e) => { - hideDispPins(pins, e.target.value) + hideDispPins(pins, parseInt(e.target.value)) }); opts = [[0, "0°"], [2, "180°"]]; @@ -837,23 +838,26 @@ } function hideDispPins(pins, dispType) { + // create pin map for each display type. + // It depends on fix pin array (see var pins) + // var pins = [['clock', 'disp_clk'], ['data', 'disp_data'], ['cs', 'disp_cs'], ['dc', 'disp_dc'], ['reset', 'disp_rst']]; + const pinMap = new Map([ + [0, [0,0,0,0,0]], //none + [1, [1,1,0,0,0]], //SSD1306_128X64 + [2, [1,1,0,0,0]], //SH1106_128X64 + [3, [1,1,1,1,0]], //PCD8544_84X48 /nokia5110 + [4, [1,1,0,0,0]], //SSD1306_128X32 + [5, [1,1,0,0,0]], //SSD1306_64X48 + [10, [1,1,1,1,1]] //ePaper + ]) for(var i = 0; i < pins.length; i++) { var cl = document.getElementById("row_" + pins[i][1]).classList; - - if(0 == dispType) - cl.add("hide"); - else if(dispType <= 2 || dispType == 4) { // OLED - if(i < 2) - cl.remove("hide"); - else - cl.add("hide"); - } else if(dispType == 3) { // Nokia - if(i < 4) - cl.remove("hide"); - else - cl.add("hide"); - } else // ePaper + if(pinMap.get(dispType)[i]) { cl.remove("hide"); + } + else { + cl.add("hide"); + } } } From 1b977012ef210e5a5133262691afb8ee520eee86 Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sun, 16 Jul 2023 00:25:41 +0200 Subject: [PATCH 71/92] fix automatic message change last line (ip,time) --- src/plugins/Display/Display_Mono_84X48.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/Display/Display_Mono_84X48.h b/src/plugins/Display/Display_Mono_84X48.h index e527ec23..490fdf9e 100644 --- a/src/plugins/Display/Display_Mono_84X48.h +++ b/src/plugins/Display/Display_Mono_84X48.h @@ -92,7 +92,7 @@ class DisplayMono84X48 : public DisplayMono { mDisplay->sendBuffer(); - mExtra = 1; + mExtra++; } private: From a9e2fc9aebba99d142ec4ffc86ca8120e3abf490 Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sun, 16 Jul 2023 01:08:58 +0200 Subject: [PATCH 72/92] initalize offsets --- src/plugins/Display/Display_Mono.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/Display/Display_Mono.h b/src/plugins/Display/Display_Mono.h index ed9154af..42eea5f3 100644 --- a/src/plugins/Display/Display_Mono.h +++ b/src/plugins/Display/Display_Mono.h @@ -35,8 +35,8 @@ class DisplayMono { uint8_t mLoopCnt; uint32_t* mUtcTs; - uint8_t mLineXOffsets[5]; - uint8_t mLineYOffsets[5]; + uint8_t mLineXOffsets[5] = {}; + uint8_t mLineYOffsets[5] = {}; uint16_t mDispY; From e04f3ff948b97c229d9c2404f43a53bd270364df Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sun, 16 Jul 2023 01:09:56 +0200 Subject: [PATCH 73/92] - define display defaults - adjust font sizes and positions --- src/plugins/Display/Display_Mono_64X48.h | 33 +++++++++++++----------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h index 5c3a95f4..035d1fa6 100644 --- a/src/plugins/Display/Display_Mono_64X48.h +++ b/src/plugins/Display/Display_Mono_64X48.h @@ -10,8 +10,8 @@ class DisplayMono64X48 : public DisplayMono { public: DisplayMono64X48() : DisplayMono() { mEnPowerSafe = true; - mEnScreenSaver = true; - mLuminance = 50; + mEnScreenSaver = false; + mLuminance = 20; mExtra = 0; mDispY = 0; mTimeout = DISP_DEFAULT_TIMEOUT; // interval at which to power save (milliseconds) @@ -36,8 +36,8 @@ class DisplayMono64X48 : public DisplayMono { mDisplay->setContrast(mLuminance); printText("AHOY!", 0); - printText("ahoydtu.de", 2); - printText(version, 3); + printText("ahoydtu.de", 1); + printText(version, 2); mDisplay->sendBuffer(); } @@ -77,24 +77,24 @@ class DisplayMono64X48 : public DisplayMono { mDisplay->setPowerSave(mEnPowerSafe); } - snprintf(mFmtText, DISP_FMT_TEXT_LEN, "today: %4.0f Wh", totalYieldDay); + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", totalYieldDay); printText(mFmtText, 1); - snprintf(mFmtText, DISP_FMT_TEXT_LEN, "total: %.1f kWh", totalYieldTotal); + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "T: %.1f kWh", totalYieldTotal); printText(mFmtText, 2); IPAddress ip = WiFi.localIP(); if (!(mExtra % 10) && (ip)) printText(ip.toString().c_str(), 3); else if (!(mExtra % 5)) { - snprintf(mFmtText, DISP_FMT_TEXT_LEN, "%d Inverter on", isprod); + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "active Inv: %d", isprod); printText(mFmtText, 3); } else if (NULL != mUtcTs) printText(ah::getTimeStr(gTimezone.toLocal(*mUtcTs)).c_str(), 3); mDisplay->sendBuffer(); - mExtra = 1; + mExtra++; } private: @@ -110,22 +110,25 @@ class DisplayMono64X48 : public DisplayMono { inline void setFont(uint8_t line) { switch (line) { case 0: - mDisplay->setFont(u8g2_font_logisoso16_tr); + mDisplay->setFont(u8g2_font_fur11_tf); + break; + case 1: + case 2: + mDisplay->setFont(u8g2_font_6x10_tf); break; case 3: - mDisplay->setFont(u8g2_font_5x8_tr); + mDisplay->setFont(u8g2_font_4x6_tr); break; - default: - mDisplay->setFont(u8g2_font_5x8_tr); + case 4: + mDisplay->setFont(u8g2_font_4x6_tr); break; } } void printText(const char *text, uint8_t line) { - uint8_t dispX = (line == 0) ? 10 : 5; + uint8_t dispX = 0; //small display, use all we have + dispX += (mEnScreenSaver) ? (mExtra % 4) : 0; setFont(line); - - dispX += (mEnScreenSaver) ? (mExtra % 7) : 0; mDisplay->drawStr(dispX, mLineYOffsets[line], text); } }; From 6a11a1a3b7348300d89eef4de1951b2fd4da9b01 Mon Sep 17 00:00:00 2001 From: Stephan Enderlein Date: Sun, 16 Jul 2023 21:44:59 +0200 Subject: [PATCH 74/92] remove decimal place from "total" to have more space --- src/plugins/Display/Display_Mono_64X48.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h index 035d1fa6..8c355322 100644 --- a/src/plugins/Display/Display_Mono_64X48.h +++ b/src/plugins/Display/Display_Mono_64X48.h @@ -80,7 +80,7 @@ class DisplayMono64X48 : public DisplayMono { snprintf(mFmtText, DISP_FMT_TEXT_LEN, "D: %4.0f Wh", totalYieldDay); printText(mFmtText, 1); - snprintf(mFmtText, DISP_FMT_TEXT_LEN, "T: %.1f kWh", totalYieldTotal); + snprintf(mFmtText, DISP_FMT_TEXT_LEN, "T: %4.0f kWh", totalYieldTotal); printText(mFmtText, 2); IPAddress ip = WiFi.localIP(); From 9331d9197b3d9845c48eccb39b54973098d62ffe Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Mon, 17 Jul 2023 19:25:24 +0200 Subject: [PATCH 75/92] RPi:crash when using additional InfoCommands Python goes in crash, when using an other InfoCommend i.e. uncomment line 178 of __main__.py --- tools/rpi/hoymiles/__init__.py | 2 ++ tools/rpi/hoymiles/__main__.py | 2 +- tools/rpi/hoymiles/decoders/__init__.py | 6 +++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index 688e271d..32fbf08d 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -183,6 +183,8 @@ class ResponseDecoder(ResponseDecoderFactory): model_desc = "Firmware version / date" elif command.upper() == '02': model_desc = "Inverter generic events log" + elif command.upper() == '05': + model_desc = "Inverter generic SystemConfigPara" elif command.upper() == '0B': model_desc = "mirco-inverters status data" elif command.upper() == '0C': diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index 3589de1a..c03de32e 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -175,7 +175,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): inv_str = str(inverter_ser) if do_init: command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.InverterDevInform_All)) -# command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.SystemConfigPara)) + command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.SystemConfigPara)) command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.RealTimeRunData_Debug)) # Put all queued commands for current inverter on air diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index ad49d664..3bf84bc2 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -430,15 +430,15 @@ class DebugDecodeAny(UnknownResponse): l_payload = len(self.response) logging.debug(f' payload has {l_payload} bytes') - logging.debug() + logging.debug('') logging.debug('Field view: int') print_table_unpack('>B', self.response) - logging.debug() + logging.debug('') logging.debug('Field view: shorts') print_table_unpack('>H', self.response) - logging.debug() + logging.debug('') logging.debug('Field view: longs') print_table_unpack('>L', self.response) From 5a935369403f1f7ae87938bd83c4d101c307ff27 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Mon, 17 Jul 2023 19:44:52 +0200 Subject: [PATCH 76/92] Python goes in crash, when using an other InfoCommend comment line 178 of main.py as before add an else path in __init__.py --- tools/rpi/hoymiles/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index 32fbf08d..e9ebc623 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -193,6 +193,8 @@ class ResponseDecoder(ResponseDecoderFactory): model_desc = "Inverter generic events log" elif command.upper() == '12': model_desc = "Inverter major events log" + else: + model_desc = "event not configured - check ahoy script" logging.info(f'model_decoder: {model}Decode{command.upper()} - {model_desc}') model_decoders = __import__('hoymiles.decoders') From be9c505407bcdee8541d7e9a6f79cc575af715ed Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 9 Jul 2023 13:25:43 +0200 Subject: [PATCH 77/92] 0.6.12 added inverter status - state-machine #1016 --- src/CHANGES.md | 4 +++ src/app.cpp | 5 +-- src/defines.h | 2 +- src/hm/hmInverter.h | 59 ++++++++++++++++++++++++++--------- src/hm/hmSystem.h | 3 +- src/platformio.ini | 2 +- src/plugins/Display/Display.h | 2 +- src/publisher/pubMqtt.h | 6 ++-- src/publisher/pubMqttIvData.h | 38 +++++++++++----------- src/publisher/pubSerial.h | 2 +- src/web/RestApi.h | 4 +-- 11 files changed, 83 insertions(+), 44 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 6590e708..ca05d60e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes + +## 0.7.12 - 2023-07-09 +* added inverter status - state-machine #1016 + ## 0.7.11 - 2023-07-09 * fix MqTT endless loop #1013 diff --git a/src/app.cpp b/src/app.cpp index 0c51949a..535af4c8 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -51,6 +51,7 @@ void app::setup() { everySec(std::bind(&ahoywifi::tickWifiLoop, &mWifi), "wifiL"); #endif + mSys.setup(&mTimestamp); mSys.addInverters(&mConfig->inst); if(mConfig->nrf.enabled) { mPayload.setup(this, &mSys, &mNrfRadio, &mStat, mConfig->nrf.maxRetransPerPyld, &mTimestamp); @@ -413,7 +414,7 @@ void app:: zeroIvValues(bool checkAvail, bool skipYieldDay) { continue; // skip to next inverter if (checkAvail) { - if (!iv->isAvailable(mTimestamp)) + if (!iv->isAvailable()) continue; } @@ -496,7 +497,7 @@ void app::updateLed(void) { if (mConfig->led.led0 != 0xff) { Inverter<> *iv = mSys.getInverterByPos(0); if (NULL != iv) { - if (iv->isProducing(mTimestamp)) + if (iv->isProducing()) digitalWrite(mConfig->led.led0, led_on); else digitalWrite(mConfig->led.led0, led_off); diff --git a/src/defines.h b/src/defines.h index 6cb90b55..60fd78b2 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 11 +#define VERSION_PATCH 12 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 094be658..b926ca7a 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -102,6 +102,13 @@ const calcFunc_t calcFunctions[] = { { CALC_IRR_CH, &calcIrradiation } }; +enum class InverterStatus : uint8_t { + OFF, + STARTING, + PRODUCING, + WAS_PRODUCING, + WAS_ON +}; template class Inverter { @@ -123,6 +130,9 @@ class Inverter { //String lastAlarmMsg; bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null) bool isConnected; // shows if inverter was successfully identified (fw version and hardware info) + InverterStatus status; // indicates the current inverter status + + static uint32_t *timestamp; // system timestamp Inverter() { ivGen = IV_HM; @@ -135,6 +145,7 @@ class Inverter { //lastAlarmMsg = "nothing"; alarmMesIndex = 0; isConnected = false; + status = InverterStatus::OFF; } ~Inverter() { @@ -319,6 +330,9 @@ class Inverter { } else DPRINTLN(DBG_ERROR, F("addValue: assignment not found with cmd 0x")); + + // update status state-machine + isProducing(); } /*inline REC_TYP getPowerLimit(void) { @@ -372,25 +386,39 @@ class Inverter { } } - bool isAvailable(uint32_t timestamp) { - if((timestamp - recordMeas.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordInfo.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordConfig.ts) < INACT_THRES_SEC) - return true; - if((timestamp - recordAlarm.ts) < INACT_THRES_SEC) - return true; - return false; + bool isAvailable() { + bool val = false; + if((*timestamp - recordMeas.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordInfo.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordConfig.ts) < INACT_THRES_SEC) + val = true; + if((*timestamp - recordAlarm.ts) < INACT_THRES_SEC) + val = true; + + if(val) { + if((InverterStatus::OFF == status) || (InverterStatus::WAS_ON == status)) + status = InverterStatus::STARTING; + } else + status = InverterStatus::WAS_ON; + + return val; } - bool isProducing(uint32_t timestamp) { + bool isProducing() { + bool val = false; DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); - if(isAvailable(timestamp)) { + if(isAvailable()) { uint8_t pos = getPosByChFld(CH0, FLD_PAC, &recordMeas); - return (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + val = (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + + if(val) + status = InverterStatus::PRODUCING; + else if(InverterStatus::PRODUCING == status) + status = InverterStatus::WAS_PRODUCING; } - return false; + return val; } uint16_t getFwVersion() { @@ -605,6 +633,9 @@ class Inverter { bool mDevControlRequest; // true if change needed }; +template +uint32_t *Inverter::timestamp {0}; + /** * To calculate values which are not transmitted by the unit there is a generic diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index a5a22885..09f8a8ba 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -13,7 +13,8 @@ class HmSystem { public: HmSystem() {} - void setup() { + void setup(uint32_t *timestamp) { + mInverter[0].timestamp = timestamp; mNumInv = 0; } diff --git a/src/platformio.ini b/src/platformio.ini index c05908f0..e6980552 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -26,7 +26,7 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 @ 1.4.5 paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.4.2 + https://github.com/bertmelis/espMqttClient#v1.4.4 bblanchon/ArduinoJson @ ^6.21.2 https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.34.17 diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index ba187c7d..b26218e6 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -89,7 +89,7 @@ class Display { if (iv == NULL) continue; - if (iv->isProducing(*mUtcTs)) + if (iv->isProducing()) isprod++; totalPower += iv->getChannelFieldValue(CH0, FLD_PAC, rec); diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 60a826a0..943017ed 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -489,9 +489,9 @@ class PubMqtt { // inverter status uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; - if (iv->isAvailable(*mUtcTimestamp)) { + if (iv->isAvailable()) { anyAvail = true; - status = (iv->isProducing(*mUtcTimestamp)) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; + status = (iv->isProducing()) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; } else // inverter is enabled but not available allAvail = false; @@ -551,7 +551,7 @@ class PubMqtt { switch (rec->assign[i].fieldId) { case FLD_YT: case FLD_YD: - if ((rec->assign[i].ch == CH0) && (!iv->isProducing(*mUtcTimestamp))) // avoids returns to 0 on restart + if ((rec->assign[i].ch == CH0) && (!iv->isProducing())) // avoids returns to 0 on restart continue; retained = true; break; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 1b2827b1..e945598b 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -67,6 +67,7 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; + mTotalFound = false; if(!mSendList->empty()) { mCmd = mSendList->front().cmd; mIvSend = mSendList->front().iv; @@ -99,7 +100,7 @@ class PubMqttIvData { mPos = 0; if(found) mState = SEND_DATA; - else if(mSendTotals) + else if(mSendTotals && mTotalFound) mState = SEND_TOTALS; else { mSendList->pop(); @@ -122,32 +123,33 @@ class PubMqttIvData { if(FLD_YT == rec->assign[mPos].fieldId) retained = true; else if(FLD_YD == rec->assign[mPos].fieldId) { - /*if(!mZeroValues) { - if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing(*mUtcTimestamp))) { // avoids returns to 0 on restart + if(!mZeroValues) { + if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing())) { // avoids returns to 0 on restart mPos++; return; } - }*/ + } retained = true; } // calculate total values for RealTimeRunData_Debug if (CH0 == rec->assign[mPos].ch) { - switch (rec->assign[mPos].fieldId) { - case FLD_PAC: - if(mIv->isAvailable(*mUtcTimestamp)) + if(mIv->status > InverterStatus::STARTING) { + mTotalFound = true; + switch (rec->assign[mPos].fieldId) { + case FLD_PAC: mTotal[0] += mIv->getValue(mPos, rec); - break; - case FLD_YT: - mTotal[1] += mIv->getValue(mPos, rec); - break; - case FLD_YD: - mTotal[2] += mIv->getValue(mPos, rec); - break; - case FLD_PDC: - if(mIv->isAvailable(*mUtcTimestamp)) + break; + case FLD_YT: + mTotal[1] += mIv->getValue(mPos, rec); + break; + case FLD_YD: + mTotal[2] += mIv->getValue(mPos, rec); + break; + case FLD_PDC: mTotal[3] += mIv->getValue(mPos, rec); - break; + break; + } } } } else @@ -207,7 +209,7 @@ class PubMqttIvData { uint8_t mCmd; uint8_t mLastIvId; - bool mSendTotals; + bool mSendTotals, mTotalFound; float mTotal[4]; Inverter<> *mIv, *mIvSend; diff --git a/src/publisher/pubSerial.h b/src/publisher/pubSerial.h index 522a227d..34dc64f2 100644 --- a/src/publisher/pubSerial.h +++ b/src/publisher/pubSerial.h @@ -28,7 +28,7 @@ class PubSerial { Inverter<> *iv = mSys->getInverterByPos(id); if (NULL != iv) { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - if (iv->isAvailable(*mUtcTimestamp)) { + if (iv->isAvailable()) { DPRINTLN(DBG_INFO, "Iv: " + String(id)); for (uint8_t i = 0; i < rec->length; i++) { if (0.0f != iv->getValue(i, rec)) { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index c4964dc3..d88e8db8 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -472,8 +472,8 @@ class RestApi { invObj[F("id")] = i; invObj[F("name")] = String(iv->config->name); invObj[F("version")] = String(iv->getFwVersion()); - invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp()); - invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp()); + invObj[F("is_avail")] = iv->isAvailable(); + invObj[F("is_producing")] = iv->isProducing(); invObj[F("ts_last_success")] = iv->getLastTs(rec); } } From 48594c565aa93b9946207ed8eda9456a88b2d0a6 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Jul 2023 22:35:36 +0200 Subject: [PATCH 78/92] 0.7.13 * merged display PR #1027 --- src/CHANGES.md | 2 ++ src/defines.h | 2 +- src/plugins/Display/Display.h | 9 +++++---- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ca05d60e..affdc71e 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,7 @@ # Development Changes +## 0.7.13 - 2023-07-19 +* merged display PR #1027 ## 0.7.12 - 2023-07-09 * added inverter status - state-machine #1016 diff --git a/src/defines.h b/src/defines.h index 60fd78b2..4f4601cc 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 12 +#define VERSION_PATCH 13 //------------------------------------- typedef struct { diff --git a/src/plugins/Display/Display.h b/src/plugins/Display/Display.h index 9849f03e..2340fd42 100644 --- a/src/plugins/Display/Display.h +++ b/src/plugins/Display/Display.h @@ -16,7 +16,9 @@ template class Display { public: - Display() {} + Display() { + mMono = NULL; + } void setup(display_t *cfg, HMSYSTEM *sys, uint32_t *utcTs, const char *version) { mCfg = cfg; @@ -45,8 +47,7 @@ class Display { default: mMono = NULL; break; } - if(mMono) - { + if(mMono) { mMono->config(mCfg->pwrSaveAtIvOffline, mCfg->pxShift, mCfg->contrast); mMono->init(mCfg->type, mCfg->rot, mCfg->disp_cs, mCfg->disp_dc, 0xff, mCfg->disp_clk, mCfg->disp_data, mUtcTs, mVersion); } @@ -127,7 +128,7 @@ class Display { #if defined(ESP32) DisplayEPaper mEpaper; #endif - DisplayMono *mMono = NULL; //default !!! + DisplayMono *mMono; }; #endif /*__DISPLAY__*/ From 308dc064fee41ea85d7c706e6dc7d438d39356c2 Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 19 Jul 2023 23:56:07 +0200 Subject: [PATCH 79/92] 0.7.13 * add date, time and version to export json #1024 --- src/CHANGES.md | 1 + src/app.cpp | 2 +- src/platformio.ini | 2 +- src/utils/helper.cpp | 9 +++++++++ src/utils/helper.h | 1 + src/web/RestApi.h | 5 ++++- 6 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index affdc71e..ca360a36 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -2,6 +2,7 @@ ## 0.7.13 - 2023-07-19 * merged display PR #1027 +* add date, time and version to export json #1024 ## 0.7.12 - 2023-07-09 * added inverter status - state-machine #1016 diff --git a/src/app.cpp b/src/app.cpp index 535af4c8..bf647f23 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -330,7 +330,7 @@ void app::tickMinute(void) { // only triggered if 'reset values on no avail is enabled' zeroIvValues(true); - } +} //----------------------------------------------------------------------------- void app::tickMidnight(void) { diff --git a/src/platformio.ini b/src/platformio.ini index e6980552..c05908f0 100644 --- a/src/platformio.ini +++ b/src/platformio.ini @@ -26,7 +26,7 @@ lib_deps = https://github.com/yubox-node-org/ESPAsyncWebServer nrf24/RF24 @ 1.4.5 paulstoffregen/Time @ ^1.6.1 - https://github.com/bertmelis/espMqttClient#v1.4.4 + https://github.com/bertmelis/espMqttClient#v1.4.2 bblanchon/ArduinoJson @ ^6.21.2 https://github.com/JChristensen/Timezone @ ^1.2.4 olikraus/U8g2 @ ^2.34.17 diff --git a/src/utils/helper.cpp b/src/utils/helper.cpp index 95f330e9..26cbdad2 100644 --- a/src/utils/helper.cpp +++ b/src/utils/helper.cpp @@ -41,6 +41,15 @@ namespace ah { return String(str); } + String getDateTimeStrFile(time_t t) { + char str[20]; + if(0 == t) + sprintf(str, "na"); + else + sprintf(str, "%04d-%02d-%02d_%02d-%02d-%02d", year(t), month(t), day(t), hour(t), minute(t), second(t)); + return String(str); + } + String getTimeStr(time_t t) { char str[9]; if(0 == t) diff --git a/src/utils/helper.h b/src/utils/helper.h index 3112ffd3..054ae0c3 100644 --- a/src/utils/helper.h +++ b/src/utils/helper.h @@ -41,6 +41,7 @@ namespace ah { void ip2Char(uint8_t ip[], char *str); double round3(double value); String getDateTimeStr(time_t t); + String getDateTimeStrFile(time_t t); String getTimeStr(time_t t); uint64_t Serial2u64(const char *val); void dumpBuf(uint8_t buf[], uint8_t len); diff --git a/src/web/RestApi.h b/src/web/RestApi.h index d88e8db8..29a70d85 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -184,9 +184,12 @@ class RestApi { response = request->beginResponse(200, F("application/json; charset=utf-8"), tmp); } + String filename = ah::getDateTimeStrFile(mApp->getTimezoneOffset()); + filename += "_v" + String(mApp->getVersion()); + response->addHeader("Content-Type", "application/octet-stream"); response->addHeader("Content-Description", "File Transfer"); - response->addHeader("Content-Disposition", "attachment; filename=ahoy_setup.json"); + response->addHeader("Content-Disposition", "attachment; filename=" + filename + "_ahoy_setup.json"); request->send(response); fp.close(); } From ac57e1690290423496b231e6dd761559a3f2d6e5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 20 Jul 2023 08:38:09 +0200 Subject: [PATCH 80/92] fix prometheus builds --- src/web/web.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/web/web.h b/src/web/web.h index 70fae62e..b8fe7a79 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -737,7 +737,7 @@ class Web { case metricsStateInverter3: // Information about all inverters configured : fit to one packet metrics += "# TYPE ahoy_solar_inverter_is_available gauge\n"; metrics += inverterMetric(topic, sizeof(topic),"ahoy_solar_inverter_is_available {inverter=\"%s\"} %d\n", - [](Inverter<> *iv,IApp *mApp)-> uint64_t {return iv->isAvailable(mApp->getTimestamp());}); + [](Inverter<> *iv,IApp *mApp)-> uint64_t {return iv->isAvailable();}); len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); metricsStep = metricsStateInverter4; break; @@ -745,7 +745,7 @@ class Web { case metricsStateInverter4: // Information about all inverters configured : fit to one packet metrics += "# TYPE ahoy_solar_inverter_is_producing gauge\n"; metrics += inverterMetric(topic, sizeof(topic),"ahoy_solar_inverter_is_producing {inverter=\"%s\"} %d\n", - [](Inverter<> *iv,IApp *mApp)-> uint64_t {return iv->isProducing(mApp->getTimestamp());}); + [](Inverter<> *iv,IApp *mApp)-> uint64_t {return iv->isProducing();}); len = snprintf((char *)buffer,maxLen,"%s",metrics.c_str()); // Start Realtime Field loop metricsFieldId = FLD_UDC; From 8eef8e2ef4343a72b0a7389d543844393816b8ea Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Thu, 20 Jul 2023 13:02:23 +0200 Subject: [PATCH 81/92] RPi: crash while using multi inverters with diff num of strings add some comments change timestamp format for logging --- tools/rpi/hoymiles/__init__.py | 41 +++++++++++++++++++------ tools/rpi/hoymiles/__main__.py | 20 +++++++----- tools/rpi/hoymiles/decoders/__init__.py | 2 +- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/tools/rpi/hoymiles/__init__.py b/tools/rpi/hoymiles/__init__.py index e9ebc623..dbe564cc 100644 --- a/tools/rpi/hoymiles/__init__.py +++ b/tools/rpi/hoymiles/__init__.py @@ -179,20 +179,43 @@ class ResponseDecoder(ResponseDecoderFactory): command = self.request_command if HOYMILES_DEBUG_LOGGING: - if command.upper() == '01': + if command.upper() == '00': + model_desc = "Inverter Dev Inform Simple" + elif command.upper() == '01': model_desc = "Firmware version / date" elif command.upper() == '02': model_desc = "Inverter generic events log" - elif command.upper() == '05': + elif command.upper() == '03': ## HardWareConfig + model_desc = "Hardware configuration" + elif command.upper() == '04': ## SimpleCalibrationPara + model_desc = "Simple Calibration Parameter" + elif command.upper() == '05': ## SystemConfigPara model_desc = "Inverter generic SystemConfigPara" - elif command.upper() == '0B': + elif command.upper() == '0B': ## 11 - RealTimeRunData_Debug model_desc = "mirco-inverters status data" - elif command.upper() == '0C': + elif command.upper() == '0C': ## 12 - RealTimeRunData_Reality model_desc = "mirco-inverters status data" - elif command.upper() == '11': + elif command.upper() == '0D': ## 13 - RealTimeRunData_A_Phase + model_desc = "Real-Time Run Data A Phase " + elif command.upper() == '0E': ## 14 - RealTimeRunData_B_Phase + model_desc = "Real-Time Run Data B Phase " + elif command.upper() == '0F': ## 15 - RealTimeRunData_C_Phase + model_desc = "Real-Time Run Data C Phase " + elif command.upper() == '11': ## 17 - AlarmData model_desc = "Inverter generic events log" - elif command.upper() == '12': + elif command.upper() == '12': ## 18 - AlarmUpdate model_desc = "Inverter major events log" + elif command.upper() == '13': ## 19 - RecordData + model_desc = "Record Data" + elif command.upper() == '14': ## 20 - InternalData + model_desc = "Internal Data" + elif command.upper() == '15': ## 21 - GetLossRate + model_desc = "Get Loss Rate" + elif command.upper() == '1E': ## 30 - GetSelfCheckState + model_desc = "Get Self Check State" + elif command.upper() == 'FF': ## 255 - InitDataState + model_desc = "Initi Data State" + else: model_desc = "event not configured - check ahoy script" logging.info(f'model_decoder: {model}Decode{command.upper()} - {model_desc}') @@ -294,10 +317,9 @@ class InverterPacketFragment: :return: log line received frame :rtype: str """ - c_datetime = self.time_rx.strftime("%Y-%m-%d %H:%M:%S.%f") size = len(self.frame) channel = f' channel {self.ch_rx}' if self.ch_rx else '' - return f"{c_datetime} Received {size} bytes{channel}: {hexify_payload(self.frame)}" + return f"Received {size} bytes{channel}: {hexify_payload(self.frame)}" class HoymilesNRF: """Hoymiles NRF24 Interface""" @@ -747,9 +769,8 @@ class InverterTransaction: :return: log line of payload for transmission :rtype: str """ - c_datetime = self.request_time.strftime("%Y-%m-%d %H:%M:%S.%f") size = len(self.request) - return f'{c_datetime} Transmit | {hexify_payload(self.request)}' + return f'Transmit | {hexify_payload(self.request)}' def hexify_payload(byte_var): """ diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index c03de32e..ba10a05a 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -129,6 +129,11 @@ def main_loop(ahoy_config): sunset.sun_status2mqtt(dtu_ser, dtu_name) loop_interval = ahoy_config.get('interval', 1) transmit_retries = ahoy_config.get('transmit_retries', 5) + if (transmit_retries <= 0): + logging.critical('Parameter "transmit_retries" must be >0 - please check ahoy.yml.') + # print message to console too + print('Parameter "transmit_retries" must be >0 - please check ahoy.yml - STOP(0)x') + sys.exit(0) try: do_init = True @@ -175,15 +180,16 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): inv_str = str(inverter_ser) if do_init: command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.InverterDevInform_All)) - command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.SystemConfigPara)) + #command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.SystemConfigPara)) command_queue[inv_str].append(hoymiles.compose_send_time_payload(InfoCommands.RealTimeRunData_Debug)) # Put all queued commands for current inverter on air while len(command_queue[inv_str]) > 0: - payload = command_queue[inv_str].pop(0) + payload = command_queue[inv_str].pop(0) ## Sub.Cmd # Send payload {ttl}-times until we get at least one reponse payload_ttl = retries + response = None while payload_ttl > 0: payload_ttl = payload_ttl - 1 com = hoymiles.InverterTransaction( @@ -197,7 +203,6 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): src=dtu_ser, dst=inverter_ser ))) - response = None while com.rxtx(): try: response = com.get_payload() @@ -210,8 +215,7 @@ def poll_inverter(inverter, dtu_ser, do_init, retries): # Handle the response data if any if response: if hoymiles.HOYMILES_TRANSACTION_LOGGING: - c_datetime = datetime.now() - logging.debug(f'{c_datetime} Payload: ' + hoymiles.hexify_payload(response)) + logging.debug(f'Payload: ' + hoymiles.hexify_payload(response)) # prepare decoder object decoder = hoymiles.ResponseDecoder(response, @@ -319,9 +323,11 @@ def init_logging(ahoy_config): max_log_files = log_config.get('max_log_files', max_log_files) if hoymiles.HOYMILES_TRANSACTION_LOGGING: lvl = logging.DEBUG - logging.basicConfig(handlers=[RotatingFileHandler(fn, maxBytes=max_log_filesize, backupCount=max_log_files)], format='%(asctime)s %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S', level=lvl) + logging.basicConfig(handlers=[RotatingFileHandler(fn, maxBytes=max_log_filesize, backupCount=max_log_files)], + format='%(asctime)s %(levelname)s: %(message)s', + datefmt='%Y-%m-%d %H:%M:%S.%f', level=lvl) dtu_name = ahoy_config.get('dtu',{}).get('name','hoymiles-dtu') - logging.info(f'start logging for {dtu_name} with level: {logging.root.level}') + logging.info(f'start logging for {dtu_name} with level: {logging.getLevelName(logging.root.level)}') if __name__ == '__main__': parser = argparse.ArgumentParser(description='Ahoy - Hoymiles solar inverter gateway', prog="hoymiles") diff --git a/tools/rpi/hoymiles/decoders/__init__.py b/tools/rpi/hoymiles/decoders/__init__.py index 8b8d3521..0d370cea 100644 --- a/tools/rpi/hoymiles/decoders/__init__.py +++ b/tools/rpi/hoymiles/decoders/__init__.py @@ -151,7 +151,7 @@ class StatusResponse(Response): """ strings = [] s_exists = True - while s_exists: + while s_exists and len(strings) < len(self.inv_strings): s_exists = False string_id = len(strings) if string_id < len(self.inv_strings): From 3ee80c47904b6b26ef61a05fb699375e2e5ed863 Mon Sep 17 00:00:00 2001 From: Knuti_in_Paese Date: Thu, 20 Jul 2023 13:15:30 +0200 Subject: [PATCH 82/92] RPi: crash while using multi inverters with diff num of strings - add some comments - change timestamp format for logging --- tools/rpi/hoymiles/__main__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/rpi/hoymiles/__main__.py b/tools/rpi/hoymiles/__main__.py index ba10a05a..985b60a5 100644 --- a/tools/rpi/hoymiles/__main__.py +++ b/tools/rpi/hoymiles/__main__.py @@ -325,7 +325,7 @@ def init_logging(ahoy_config): lvl = logging.DEBUG logging.basicConfig(handlers=[RotatingFileHandler(fn, maxBytes=max_log_filesize, backupCount=max_log_files)], format='%(asctime)s %(levelname)s: %(message)s', - datefmt='%Y-%m-%d %H:%M:%S.%f', level=lvl) + datefmt='%Y-%m-%d %H:%M:%S.%s', level=lvl) dtu_name = ahoy_config.get('dtu',{}).get('name','hoymiles-dtu') logging.info(f'start logging for {dtu_name} with level: {logging.getLevelName(logging.root.level)}') From c9d705baa4ebcd59716d8dfb0d720bed2429ab12 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 23 Jul 2023 18:37:35 +0200 Subject: [PATCH 83/92] 0.7.14 * fix Contrast for Nokia Display #1041 * attempt to fix #1016 by improving inverter status * added option to adjust effiency for yield (day/total) #1028 --- src/CHANGES.md | 5 +++ src/config/config.h | 5 ++- src/config/settings.h | 19 ++++++--- src/defines.h | 2 +- src/hm/hmInverter.h | 51 ++++++++++++++---------- src/hm/hmSystem.h | 1 + src/plugins/Display/Display_Mono_64X48.h | 2 +- src/web/RestApi.h | 1 + src/web/html/setup.html | 6 ++- src/web/web.h | 2 + 10 files changed, 64 insertions(+), 30 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index ca360a36..06a80306 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.7.14 - 2023-07-23 +* fix Contrast for Nokia Display #1041 +* attempt to fix #1016 by improving inverter status +* added option to adjust effiency for yield (day/total) #1028 + ## 0.7.13 - 2023-07-19 * merged display PR #1027 * add date, time and version to export json #1024 diff --git a/src/config/config.h b/src/config/config.h index a03712bd..ad43ec2d 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -97,7 +97,10 @@ #define DEF_MAX_RETRANS_PER_PYLD 5 // number of seconds since last successful response, before inverter is marked inactive -#define INACT_THRES_SEC 300 +#define INVERTER_INACT_THRES_SEC 300 + +// number of seconds since last successful response, before inverter is marked offline +#define INVERTER_OFF_THRES_SEC 3600 // threshold of minimum power on which the inverter is marked as inactive #define INACT_PWR_THRESH 3 diff --git a/src/config/settings.h b/src/config/settings.h index 4d0ab505..255cfde3 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -145,6 +145,7 @@ typedef struct { bool rstValsNotAvail; bool rstValsCommStop; bool startWithoutTime; + float yieldEffiency; } cfgInst_t; typedef struct { @@ -409,7 +410,8 @@ class settings { mCfg.inst.rstYieldMidNight = false; mCfg.inst.rstValsNotAvail = false; mCfg.inst.rstValsCommStop = false; - mCfg.inst.startWithoutTime = false; + mCfg.inst.startWithoutTime = false; + mCfg.inst.yieldEffiency = 0.955f; mCfg.led.led0 = DEF_PIN_OFF; mCfg.led.led1 = DEF_PIN_OFF; @@ -624,10 +626,11 @@ class settings { void jsonInst(JsonObject obj, bool set = false) { if(set) { obj[F("en")] = (bool)mCfg.inst.enabled; - obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight; - obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail; - obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; - obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime; + obj[F("rstMidNight")] = (bool)mCfg.inst.rstYieldMidNight; + obj[F("rstNotAvail")] = (bool)mCfg.inst.rstValsNotAvail; + obj[F("rstComStop")] = (bool)mCfg.inst.rstValsCommStop; + obj[F("strtWthtTime")] = (bool)mCfg.inst.startWithoutTime; + obj[F("yldEff")] = mCfg.inst.yieldEffiency; } else { getVal(obj, F("en"), &mCfg.inst.enabled); @@ -635,6 +638,12 @@ class settings { getVal(obj, F("rstNotAvail"), &mCfg.inst.rstValsNotAvail); getVal(obj, F("rstComStop"), &mCfg.inst.rstValsCommStop); getVal(obj, F("strtWthtTime"), &mCfg.inst.startWithoutTime); + getVal(obj, F("yldEff"), &mCfg.inst.yieldEffiency); + + if(mCfg.inst.yieldEffiency < 0.5) + mCfg.inst.yieldEffiency = 1.0f; + else if(mCfg.inst.yieldEffiency > 1.0f) + mCfg.inst.yieldEffiency = 1.0f; } JsonArray ivArr; diff --git a/src/defines.h b/src/defines.h index 4f4601cc..7c19c062 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 13 +#define VERSION_PATCH 14 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index b926ca7a..cdd6428d 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -133,6 +133,7 @@ class Inverter { InverterStatus status; // indicates the current inverter status static uint32_t *timestamp; // system timestamp + static cfgInst_t *generalConfig; // general inverter configuration from setup Inverter() { ivGen = IV_HM; @@ -281,7 +282,9 @@ class Inverter { // temperature, Qvar, and power factor are a signed values rec->record[pos] = ((REC_TYP)((int16_t)val)) / (REC_TYP)(div); } else if (FLD_YT == rec->assign[pos].fieldId) { - rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div)) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); + rec->record[pos] = ((REC_TYP)(val) / (REC_TYP)(div) * generalConfig->yieldEffiency) + ((REC_TYP)config->yieldCor[rec->assign[pos].ch-1]); + } else if (FLD_YD == rec->assign[pos].fieldId) { + rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div) * generalConfig->yieldEffiency; } else { if ((REC_TYP)(div) > 1) rec->record[pos] = (REC_TYP)(val) / (REC_TYP)(div); @@ -387,38 +390,42 @@ class Inverter { } bool isAvailable() { - bool val = false; - if((*timestamp - recordMeas.ts) < INACT_THRES_SEC) - val = true; - if((*timestamp - recordInfo.ts) < INACT_THRES_SEC) - val = true; - if((*timestamp - recordConfig.ts) < INACT_THRES_SEC) - val = true; - if((*timestamp - recordAlarm.ts) < INACT_THRES_SEC) - val = true; - - if(val) { - if((InverterStatus::OFF == status) || (InverterStatus::WAS_ON == status)) + bool avail = false; + if((*timestamp - recordMeas.ts) < INVERTER_INACT_THRES_SEC) + avail = true; + if((*timestamp - recordInfo.ts) < INVERTER_INACT_THRES_SEC) + avail = true; + if((*timestamp - recordConfig.ts) < INVERTER_INACT_THRES_SEC) + avail = true; + if((*timestamp - recordAlarm.ts) < INVERTER_INACT_THRES_SEC) + avail = true; + + if(avail) { + if(InverterStatus::OFF == status) status = InverterStatus::STARTING; - } else - status = InverterStatus::WAS_ON; + else + status = InverterStatus::WAS_ON; + } else { + if((*timestamp - recordMeas.ts) < INVERTER_OFF_THRES_SEC) + status = InverterStatus::OFF; + } - return val; + return avail; } bool isProducing() { - bool val = false; + bool producing = false; DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); if(isAvailable()) { uint8_t pos = getPosByChFld(CH0, FLD_PAC, &recordMeas); - val = (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + producing = (getValue(pos, &recordMeas) > INACT_PWR_THRESH); - if(val) + if(producing) status = InverterStatus::PRODUCING; else if(InverterStatus::PRODUCING == status) - status = InverterStatus::WAS_PRODUCING; + status = InverterStatus::WAS_PRODUCING; } - return val; + return producing; } uint16_t getFwVersion() { @@ -635,6 +642,8 @@ class Inverter { template uint32_t *Inverter::timestamp {0}; +template +cfgInst_t *Inverter::generalConfig {0}; /** diff --git a/src/hm/hmSystem.h b/src/hm/hmSystem.h index 09f8a8ba..25d6dd11 100644 --- a/src/hm/hmSystem.h +++ b/src/hm/hmSystem.h @@ -19,6 +19,7 @@ class HmSystem { } void addInverters(cfgInst_t *config) { + mInverter[0].generalConfig = config; Inverter<> *iv; for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { iv = addInverter(&config->iv[i]); diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h index 8c355322..6b400a62 100644 --- a/src/plugins/Display/Display_Mono_64X48.h +++ b/src/plugins/Display/Display_Mono_64X48.h @@ -44,7 +44,7 @@ class DisplayMono64X48 : public DisplayMono { void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { mEnPowerSafe = enPowerSafe; mEnScreenSaver = enScreenSaver; - mLuminance = lum; + mLuminance = lum * 255 / 100; } void loop(void) { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 29a70d85..6531600d 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -333,6 +333,7 @@ class RestApi { obj[F("rstNAvail")] = (bool)mConfig->inst.rstValsNotAvail; obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop; obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime; + obj[F("yldEff")] = mConfig->inst.yieldEffiency; } void getInverter(JsonObject obj, uint8_t id) { diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 1ee056df..6eed603c 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -176,6 +176,10 @@
Start without time sync (useful in AP-Only-Mode)
+
+
Yield Effiency (should be between 0.95 and 0.96)
+
+
@@ -626,7 +630,7 @@ } function ivGlob(obj) { - for(var i of [["invInterval", "interval"], ["invRetry", "retries"]]) + for(var i of [["invInterval", "interval"], ["invRetry", "retries"], ["yldEff", "yldEff"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; for(var i of [["Mid", "rstMid"], ["ComStop", "rstComStop"], ["NotAvail", "rstNAvail"]]) document.getElementsByName("invRst"+i[0])[0].checked = obj[i[1]]; diff --git a/src/web/web.h b/src/web/web.h index b8fe7a79..fdede860 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -525,6 +525,8 @@ class Web { mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on"); mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on"); mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on"); + mConfig->inst.yieldEffiency = (request->arg("yldEff")).toFloat(); + // pinout uint8_t pin; From 984e344f05e44226f784d0fb35e7f80285dd0407 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sun, 23 Jul 2023 23:08:21 +0200 Subject: [PATCH 84/92] 0.7.15 * add NTP sync interval #1019 * adjusted range of contrast / luminance setting #1041 * use only ISO time format in Web-UI #913 --- src/CHANGES.md | 5 +++++ src/app.cpp | 2 +- src/config/settings.h | 11 +++++++++-- src/defines.h | 2 +- src/plugins/Display/Display_Mono_64X48.h | 2 +- src/web/RestApi.h | 5 +++-- src/web/html/index.html | 6 +++--- src/web/html/setup.html | 8 ++++++-- src/web/html/visualization.html | 2 +- src/web/web.h | 1 + 10 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 06a80306..07654865 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.7.15 - 2023-07-23 +* add NTP sync interval #1019 +* adjusted range of contrast / luminance setting #1041 +* use only ISO time format in Web-UI #913 + ## 0.7.14 - 2023-07-23 * fix Contrast for Nokia Display #1041 * attempt to fix #1016 by improving inverter status diff --git a/src/app.cpp b/src/app.cpp index bf647f23..e13943e9 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -247,7 +247,7 @@ void app::tickNtpUpdate(void) { } } - nxtTrig = isOK ? 43200 : 60; // depending on NTP update success check again in 12 h or in 1 min + nxtTrig = isOK ? (mConfig->ntp.interval * 60) : 60; // depending on NTP update success check again in 12h (depends on setting) or in 1 min if ((mSunrise == 0) && (mConfig->sun.lat) && (mConfig->sun.lon)) { mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600; diff --git a/src/config/settings.h b/src/config/settings.h index 255cfde3..25891813 100644 --- a/src/config/settings.h +++ b/src/config/settings.h @@ -98,6 +98,7 @@ typedef struct { typedef struct { char addr[NTP_ADDR_LEN]; uint16_t port; + uint16_t interval; // in minutes } cfgNtp_t; typedef struct { @@ -390,6 +391,7 @@ class settings { snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME); mCfg.ntp.port = DEF_NTP_PORT; + mCfg.ntp.interval = 720; mCfg.sun.lat = 0.0; mCfg.sun.lon = 0.0; @@ -524,11 +526,16 @@ class settings { void jsonNtp(JsonObject obj, bool set = false) { if(set) { - obj[F("addr")] = mCfg.ntp.addr; - obj[F("port")] = mCfg.ntp.port; + obj[F("addr")] = mCfg.ntp.addr; + obj[F("port")] = mCfg.ntp.port; + obj[F("intvl")] = mCfg.ntp.interval; } else { getChar(obj, F("addr"), mCfg.ntp.addr, NTP_ADDR_LEN); getVal(obj, F("port"), &mCfg.ntp.port); + getVal(obj, F("intvl"), &mCfg.ntp.interval); + + if(mCfg.ntp.interval < 5) // minimum 5 minutes + mCfg.ntp.interval = 720; // default -> 12 hours } } diff --git a/src/defines.h b/src/defines.h index 7c19c062..c47662bb 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 14 +#define VERSION_PATCH 15 //------------------------------------- typedef struct { diff --git a/src/plugins/Display/Display_Mono_64X48.h b/src/plugins/Display/Display_Mono_64X48.h index 6b400a62..8c355322 100644 --- a/src/plugins/Display/Display_Mono_64X48.h +++ b/src/plugins/Display/Display_Mono_64X48.h @@ -44,7 +44,7 @@ class DisplayMono64X48 : public DisplayMono { void config(bool enPowerSafe, bool enScreenSaver, uint8_t lum) { mEnPowerSafe = enPowerSafe; mEnScreenSaver = enScreenSaver; - mLuminance = lum * 255 / 100; + mLuminance = lum; } void loop(void) { diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 6531600d..9d349214 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -390,8 +390,9 @@ class RestApi { } void getNtp(JsonObject obj) { - obj[F("addr")] = String(mConfig->ntp.addr); - obj[F("port")] = String(mConfig->ntp.port); + obj[F("addr")] = String(mConfig->ntp.addr); + obj[F("port")] = String(mConfig->ntp.port); + obj[F("interval")] = String(mConfig->ntp.interval); } void getSun(JsonObject obj) { diff --git a/src/web/html/index.html b/src/web/html/index.html index 2799598f..f3d9a565 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -92,7 +92,7 @@ if(obj["ts_now"] < 1680000000) setTime(); else - dSpan.innerHTML = date.toLocaleString('de-DE'); + dSpan.innerHTML = date.toISOString().substring(0, 19).replace('T', ', '); } else { dSpan.innerHTML = ""; @@ -157,7 +157,7 @@ if(false == i["is_avail"]) { if(i["ts_last_success"] > 0) { var date = new Date(i["ts_last_success"] * 1000); - p.append(span("-> last successful transmission: " + date.toLocaleString('de-DE')), br()); + p.append(span("-> last successful transmission: " + date.toISOString().substring(0, 19).replace('T', ', ')), br()); } } } @@ -190,7 +190,7 @@ function tick() { if(0 != ts) - document.getElementById("date").innerHTML = (new Date((++ts) * 1000)).toLocaleString('de-DE'); + document.getElementById("date").innerHTML = (new Date((++ts) * 1000)).toISOString().substring(0, 19).replace('T', ', '); if(++tickCnt >= 10) { tickCnt = 0; getAjax('/api/index', parse); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 6eed603c..7c910838 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -195,6 +195,10 @@
NTP Port
+
+
NTP Intervall (in Minutes, min. 5 Minutes)
+
+
set system time
@@ -284,7 +288,7 @@
Luminance
-
+

Pinout

@@ -681,7 +685,7 @@ } function parseNtp(obj) { - for(var i of [["ntpAddr", "addr"], ["ntpPort", "port"]]) + for(var i of [["ntpAddr", "addr"], ["ntpPort", "port"], ["ntpIntvl", "interval"]]) document.getElementsByName(i[0])[0].value = obj[i[1]]; } diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index fe8256cf..e4d23507 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -158,7 +158,7 @@ var ageInfo = "Last received data requested at: "; if(ts > 0) { var date = new Date(ts * 1000); - ageInfo += date.toLocaleString('de-DE'); + ageInfo += date.toISOString().substring(0, 19).replace('T', ', '); } else ageInfo += "nothing received"; diff --git a/src/web/web.h b/src/web/web.h index fdede860..a289f230 100644 --- a/src/web/web.h +++ b/src/web/web.h @@ -559,6 +559,7 @@ class Web { if (request->arg("ntpAddr") != "") { request->arg("ntpAddr").toCharArray(mConfig->ntp.addr, NTP_ADDR_LEN); mConfig->ntp.port = request->arg("ntpPort").toInt() & 0xffff; + mConfig->ntp.interval = request->arg("ntpIntvl").toInt() & 0xffff; } // sun From ffe7d47b31167605ff89d3310d8161ca222d8ab6 Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 24 Jul 2023 23:33:54 +0200 Subject: [PATCH 85/92] 0.7.16 * next attempt to fix yield day for multiple inverters #1016 * fix export settings date #1040 * fix time on WebUI (timezone was not observed) #913 #1016 --- src/CHANGES.md | 5 +++++ src/defines.h | 2 +- src/hm/hmInverter.h | 2 +- src/publisher/pubMqttIvData.h | 17 +++++++++++++---- src/web/RestApi.h | 2 +- src/web/html/api.js | 4 ++++ src/web/html/index.html | 10 +++------- src/web/html/visualization.html | 2 +- 8 files changed, 29 insertions(+), 15 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 07654865..b428404c 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,10 @@ # Development Changes +## 0.7.16 - 2023-07-24 +* next attempt to fix yield day for multiple inverters #1016 +* fix export settings date #1040 +* fix time on WebUI (timezone was not observed) #913 #1016 + ## 0.7.15 - 2023-07-23 * add NTP sync interval #1019 * adjusted range of contrast / luminance setting #1041 diff --git a/src/defines.h b/src/defines.h index c47662bb..b203aa01 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 15 +#define VERSION_PATCH 16 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index cdd6428d..3fcaf55c 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -401,7 +401,7 @@ class Inverter { avail = true; if(avail) { - if(InverterStatus::OFF == status) + if(status < InverterStatus::PRODUCING) status = InverterStatus::STARTING; else status = InverterStatus::WAS_ON; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index e945598b..c7b60446 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -68,6 +68,7 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; mTotalFound = false; + mAllTotalFound = true; if(!mSendList->empty()) { mCmd = mSendList->front().cmd; mIvSend = mSendList->front().iv; @@ -150,7 +151,8 @@ class PubMqttIvData { mTotal[3] += mIv->getValue(mPos, rec); break; } - } + } else + mAllTotalFound = false; } } else mIvLastRTRpub[mIv->id] = lastTs; @@ -169,6 +171,7 @@ class PubMqttIvData { void stateSendTotals() { uint8_t fieldId; + mRTRDataHasBeenSent = true; if(mPos < 4) { bool retained = true; switch (mPos) { @@ -178,9 +181,17 @@ class PubMqttIvData { retained = false; break; case 1: + if(!mAllTotalFound) { + mPos++ + return; + } fieldId = FLD_YT; break; case 2: + if(!mAllTotalFound) { + mPos++ + return; + } fieldId = FLD_YD; break; case 3: @@ -197,8 +208,6 @@ class PubMqttIvData { mZeroValues = false; mState = START; } - - mRTRDataHasBeenSent = true; } HMSYSTEM *mSys; @@ -209,7 +218,7 @@ class PubMqttIvData { uint8_t mCmd; uint8_t mLastIvId; - bool mSendTotals, mTotalFound; + bool mSendTotals, mTotalFound, mAllTotalFound; float mTotal[4]; Inverter<> *mIv, *mIvSend; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 9d349214..0f7f8112 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -184,7 +184,7 @@ class RestApi { response = request->beginResponse(200, F("application/json; charset=utf-8"), tmp); } - String filename = ah::getDateTimeStrFile(mApp->getTimezoneOffset()); + String filename = ah::getDateTimeStrFile(gTimezone.toLocal(mApp->getTimestamp())); filename += "_v" + String(mApp->getVersion()); response->addHeader("Content-Type", "application/octet-stream"); diff --git a/src/web/html/api.js b/src/web/html/api.js index f201d8c5..299144a9 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -119,6 +119,10 @@ function parseRssi(obj) { document.getElementById("wifiicon").replaceChildren(svg(icon, 32, 32, "wifi", obj["wifi_rssi"])); } +function toIsoDateStr(d) { + return new Date(d.getTime() + (d.getTimezoneOffset() * -60000)).toISOString().substring(0, 19).replace('T', ', '); +} + function setHide(id, hide) { var elm = document.getElementById(id); if(hide) { diff --git a/src/web/html/index.html b/src/web/html/index.html index f3d9a565..f2afe3c0 100644 --- a/src/web/html/index.html +++ b/src/web/html/index.html @@ -62,10 +62,6 @@ getAjax("/api/setup", apiCb, "POST", JSON.stringify(obj)); } - function ts2Span(ts) { - return span(new Date(ts * 1000).toLocaleString('de-DE')); - } - function parseGeneric(obj) { if(exeOnce) parseESP(obj); @@ -92,7 +88,7 @@ if(obj["ts_now"] < 1680000000) setTime(); else - dSpan.innerHTML = date.toISOString().substring(0, 19).replace('T', ', '); + dSpan.innerHTML = toIsoDateStr(date); } else { dSpan.innerHTML = ""; @@ -157,7 +153,7 @@ if(false == i["is_avail"]) { if(i["ts_last_success"] > 0) { var date = new Date(i["ts_last_success"] * 1000); - p.append(span("-> last successful transmission: " + date.toISOString().substring(0, 19).replace('T', ', ')), br()); + p.append(span("-> last successful transmission: " + toIsoDateStr(date)), br()); } } } @@ -190,7 +186,7 @@ function tick() { if(0 != ts) - document.getElementById("date").innerHTML = (new Date((++ts) * 1000)).toISOString().substring(0, 19).replace('T', ', '); + document.getElementById("date").innerHTML = toIsoDateStr((new Date((++ts) * 1000))); if(++tickCnt >= 10) { tickCnt = 0; getAjax('/api/index', parse); diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index e4d23507..b7e5042e 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -158,7 +158,7 @@ var ageInfo = "Last received data requested at: "; if(ts > 0) { var date = new Date(ts * 1000); - ageInfo += date.toISOString().substring(0, 19).replace('T', ', '); + ageInfo += toIsoDateStr(date); } else ageInfo += "nothing received"; From aaf685f465d16384224131216b11a07fe9a7b8fe Mon Sep 17 00:00:00 2001 From: lumapu Date: Mon, 24 Jul 2023 23:38:00 +0200 Subject: [PATCH 86/92] 0.7.16 fix typo --- src/publisher/pubMqttIvData.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index c7b60446..7ca51f2e 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -182,14 +182,14 @@ class PubMqttIvData { break; case 1: if(!mAllTotalFound) { - mPos++ + mPos++; return; } fieldId = FLD_YT; break; case 2: if(!mAllTotalFound) { - mPos++ + mPos++; return; } fieldId = FLD_YD; From 812adce64ed2bbafeb7ea88ddaac7645b8cd09ee Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 25 Jul 2023 22:18:33 +0200 Subject: [PATCH 87/92] 0.7.17 * next attempt to fix total yield day for multiple inverters #1016 * added two more states for the inverter status (also docu) --- Getting_Started.md | 2 ++ README.md | 2 +- User_Manual.md | 4 +++- src/CHANGES.md | 4 ++++ src/app.cpp | 6 +++--- src/app.h | 3 +++ src/defines.h | 6 +----- src/publisher/pubMqtt.h | 18 ++++++++---------- src/publisher/pubMqttIvData.h | 5 +++-- 9 files changed, 28 insertions(+), 22 deletions(-) diff --git a/Getting_Started.md b/Getting_Started.md index d66aeca0..e0254c12 100644 --- a/Getting_Started.md +++ b/Getting_Started.md @@ -14,6 +14,8 @@ Hoymiles Inverters | ----- | ----- | ------ | ------- | | ✔️ | MI | 300, 600, 1000/1200/⚠️ 1500 | 4-Channel is not tested yet | | ✔️ | HM | 300, 350, 400, 600, 700, 800, 1000?, 1200, 1500 | | +| ✔️ | HMS | 350, 500, 800, 1000, 1600, 1800, 2000 | | +| ✔️ | HMT | 1600, 1800, 2250 | | | ⚠️ | TSUN | [TSOL-M350](https://www.tsun-ess.com/Micro-Inverter/M350-M400), [TSOL-M400](https://www.tsun-ess.com/Micro-Inverter/M350-M400), [TSOL-M800/TSOL-M800(DE)](https://www.tsun-ess.com/Micro-Inverter/M800) | others may work as well (need to be verified). | ## Table of Contents diff --git a/README.md b/README.md index 1af6f41d..e744dde8 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ Table of approaches: | Board | MI | HM | HMS/HMT | comment | HowTo start | | ------ | -- | -- | ------- | ------- | ---------- | -| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | ✔️ development version ✨ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) | +| [ESP8266/ESP32, C++](Getting_Started.md) | ✔️ | ✔️ | ✔️ ✨ | 👈 the most effort is spent here | [create your own DTU](https://ahoydtu.de/getting_started/) | | [Arduino Nano, C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | | [Raspberry Pi, Python](tools/rpi/) | ❌ | ✔️ | ❌ | | | [Others, C/C++](tools/nano/NRF24_SendRcv/) | ❌ | ✔️ | ❌ | | diff --git a/User_Manual.md b/User_Manual.md index a7be8f80..1508a60f 100644 --- a/User_Manual.md +++ b/User_Manual.md @@ -48,9 +48,11 @@ The AhoyDTU will publish on the following topics | status code | Remarks | |---|---| -| 0 | not available and not producing | +| 0 | off: not available and not producing | | 1 | available but not producing | | 2 | available and producing | +| 3 | available and was producing | +| 4 | was available | ### `//ch0/#` diff --git a/src/CHANGES.md b/src/CHANGES.md index b428404c..17d25923 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.17 - 2023-07-25 +* next attempt to fix yield day for multiple inverters #1016 +* added two more states for the inverter status (also docu) + ## 0.7.16 - 2023-07-24 * next attempt to fix yield day for multiple inverters #1016 * fix export settings date #1040 diff --git a/src/app.cpp b/src/app.cpp index e13943e9..56a85f18 100644 --- a/src/app.cpp +++ b/src/app.cpp @@ -322,14 +322,14 @@ void app::tickComm(void) { //----------------------------------------------------------------------------- void app::tickZeroValues(void) { - zeroIvValues(false); + zeroIvValues(!CHECK_AVAIL, SKIP_YIELD_DAY); } //----------------------------------------------------------------------------- void app::tickMinute(void) { // only triggered if 'reset values on no avail is enabled' - zeroIvValues(true); + zeroIvValues(CHECK_AVAIL, SKIP_YIELD_DAY); } //----------------------------------------------------------------------------- @@ -339,7 +339,7 @@ void app::tickMidnight(void) { uint32_t nxtTrig = gTimezone.toUTC(localTime - (localTime % 86400) + 86400); // next midnight local time onceAt(std::bind(&app::tickMidnight, this), nxtTrig, "mid2"); - zeroIvValues(false, false); + zeroIvValues(!CHECK_AVAIL, !SKIP_YIELD_DAY); if (mMqttEnabled) mMqtt.tickerMidnight(); diff --git a/src/app.h b/src/app.h index 6f9cda5d..585147b2 100644 --- a/src/app.h +++ b/src/app.h @@ -239,6 +239,9 @@ class app : public IApp, public ah::Scheduler { } private: + #define CHECK_AVAIL true + #define SKIP_YIELD_DAY true + typedef std::function innerLoopCb; void resetSystem(void); diff --git a/src/defines.h b/src/defines.h index b203aa01..1e7a61ee 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 16 +#define VERSION_PATCH 17 //------------------------------------- typedef struct { @@ -74,10 +74,6 @@ union serial_u { #define MIN_MQTT_INTERVAL 60 -#define MQTT_STATUS_NOT_AVAIL_NOT_PROD 0 -#define MQTT_STATUS_AVAIL_NOT_PROD 1 -#define MQTT_STATUS_AVAIL_PROD 2 - enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE}; //------------------------------------- diff --git a/src/publisher/pubMqtt.h b/src/publisher/pubMqtt.h index 943017ed..fa12e969 100644 --- a/src/publisher/pubMqtt.h +++ b/src/publisher/pubMqtt.h @@ -49,7 +49,7 @@ class PubMqtt { mRxCnt = 0; mTxCnt = 0; mSubscriptionCb = NULL; - memset(mLastIvState, MQTT_STATUS_NOT_AVAIL_NOT_PROD, MAX_NUM_INVERTERS); + memset(mLastIvState, (uint8_t)InverterStatus::OFF, MAX_NUM_INVERTERS); memset(mIvLastRTRpub, 0, MAX_NUM_INVERTERS * 4); mLastAnyAvail = false; mZeroValues = false; @@ -488,24 +488,22 @@ class PubMqtt { rec = iv->getRecordStruct(RealTimeRunData_Debug); // inverter status - uint8_t status = MQTT_STATUS_NOT_AVAIL_NOT_PROD; - if (iv->isAvailable()) { + iv->isProducing(); // recalculate status + if (iv->isAvailable()) anyAvail = true; - status = (iv->isProducing()) ? MQTT_STATUS_AVAIL_PROD : MQTT_STATUS_AVAIL_NOT_PROD; - } else // inverter is enabled but not available allAvail = false; - if(mLastIvState[id] != status) { + if(mLastIvState[id] != iv->status) { // if status changed from producing to not producing send last data immediately - if (MQTT_STATUS_AVAIL_PROD == mLastIvState[id]) + if (InverterStatus::WAS_PRODUCING == mLastIvState[id]) sendData(iv, RealTimeRunData_Debug); - mLastIvState[id] = status; + mLastIvState[id] = iv->status; changed = true; snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); - snprintf(mVal, 40, "%d", status); + snprintf(mVal, 40, "%d", (uint8_t)iv->status); publish(mSubTopic, mVal, true); snprintf(mSubTopic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name); @@ -596,7 +594,7 @@ class PubMqtt { subscriptionCb mSubscriptionCb; bool mLastAnyAvail; bool mZeroValues; - uint8_t mLastIvState[MAX_NUM_INVERTERS]; + InverterStatus mLastIvState[MAX_NUM_INVERTERS]; uint32_t mIvLastRTRpub[MAX_NUM_INVERTERS]; uint16_t mIntervalTimeout; diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 7ca51f2e..41e6a0bd 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -99,9 +99,10 @@ class PubMqttIvData { mLastIvId++; mPos = 0; - if(found) + if(found) { + mIv->isProducing(); // recalculate status mState = SEND_DATA; - else if(mSendTotals && mTotalFound) + } else if(mSendTotals && mTotalFound) mState = SEND_TOTALS; else { mSendList->pop(); From 58f19f88d0ed5b0dcd73e9186895b6a8b9a7e8cc Mon Sep 17 00:00:00 2001 From: lumapu Date: Wed, 26 Jul 2023 22:39:50 +0200 Subject: [PATCH 88/92] 0.7.18 - 2023-07-26 * next attempt to fix yield day for multiple inverters #1016 --- src/CHANGES.md | 3 +++ src/defines.h | 2 +- src/hm/hmInverter.h | 9 ++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 17d25923..78635620 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,8 @@ # Development Changes +## 0.7.18 - 2023-07-26 +* next attempt to fix yield day for multiple inverters #1016 + ## 0.7.17 - 2023-07-25 * next attempt to fix yield day for multiple inverters #1016 * added two more states for the inverter status (also docu) diff --git a/src/defines.h b/src/defines.h index 1e7a61ee..c144e89c 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 17 +#define VERSION_PATCH 18 //------------------------------------- typedef struct { diff --git a/src/hm/hmInverter.h b/src/hm/hmInverter.h index 3fcaf55c..4e6dd77f 100644 --- a/src/hm/hmInverter.h +++ b/src/hm/hmInverter.h @@ -403,11 +403,11 @@ class Inverter { if(avail) { if(status < InverterStatus::PRODUCING) status = InverterStatus::STARTING; - else - status = InverterStatus::WAS_ON; } else { - if((*timestamp - recordMeas.ts) < INVERTER_OFF_THRES_SEC) + if((*timestamp - recordMeas.ts) > INVERTER_OFF_THRES_SEC) status = InverterStatus::OFF; + else + status = InverterStatus::WAS_ON; } return avail; @@ -417,8 +417,7 @@ class Inverter { bool producing = false; DPRINTLN(DBG_VERBOSE, F("hmInverter.h:isProducing")); if(isAvailable()) { - uint8_t pos = getPosByChFld(CH0, FLD_PAC, &recordMeas); - producing = (getValue(pos, &recordMeas) > INACT_PWR_THRESH); + producing = (getChannelFieldValue(CH0, FLD_PAC, &recordMeas) > INACT_PWR_THRESH); if(producing) status = InverterStatus::PRODUCING; From 6e901a656c2701fc01f0aeee6b888ed520ecb3f5 Mon Sep 17 00:00:00 2001 From: lumapu Date: Thu, 27 Jul 2023 23:10:12 +0200 Subject: [PATCH 89/92] 0.7.19 * next attempt to fix yield day for multiple inverters #1016 * reduced threshold for inverter state machine from 60min to 15min to go from state `WAS_ON` to `OFF` --- src/CHANGES.md | 4 ++++ src/config/config.h | 4 ++-- src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 11 +---------- 4 files changed, 8 insertions(+), 13 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 78635620..8aeec68f 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.19 - 2023-07-27 +* next attempt to fix yield day for multiple inverters #1016 +* reduced threshold for inverter state machine from 60min to 15min to go from state `WAS_ON` to `OFF` + ## 0.7.18 - 2023-07-26 * next attempt to fix yield day for multiple inverters #1016 diff --git a/src/config/config.h b/src/config/config.h index ad43ec2d..65b7aa1a 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -97,10 +97,10 @@ #define DEF_MAX_RETRANS_PER_PYLD 5 // number of seconds since last successful response, before inverter is marked inactive -#define INVERTER_INACT_THRES_SEC 300 +#define INVERTER_INACT_THRES_SEC 5*60 // number of seconds since last successful response, before inverter is marked offline -#define INVERTER_OFF_THRES_SEC 3600 +#define INVERTER_OFF_THRES_SEC 15*60 // threshold of minimum power on which the inverter is marked as inactive #define INACT_PWR_THRESH 3 diff --git a/src/defines.h b/src/defines.h index c144e89c..ccafdea7 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 18 +#define VERSION_PATCH 19 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 41e6a0bd..372ac9b5 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -122,17 +122,8 @@ class PubMqttIvData { if(mPos < rec->length) { bool retained = false; if (mCmd == RealTimeRunData_Debug) { - if(FLD_YT == rec->assign[mPos].fieldId) + if((FLD_YT == rec->assign[mPos].fieldId) || (FLD_YD == rec->assign[mPos].fieldId)) retained = true; - else if(FLD_YD == rec->assign[mPos].fieldId) { - if(!mZeroValues) { - if ((rec->assign[mPos].ch == CH0) && (!mIv->isProducing())) { // avoids returns to 0 on restart - mPos++; - return; - } - } - retained = true; - } // calculate total values for RealTimeRunData_Debug if (CH0 == rec->assign[mPos].ch) { From 2b67ed433d0eb62d00ec734499c6313240e159b9 Mon Sep 17 00:00:00 2001 From: Julian Gog Date: Fri, 28 Jul 2023 16:25:55 +0200 Subject: [PATCH 90/92] Feature(web/RestApi): re-adding version and build number to api --- src/web/RestApi.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 0f7f8112..dcc67513 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -197,6 +197,8 @@ class RestApi { void getGeneric(AsyncWebServerRequest *request, JsonObject obj) { obj[F("wifi_rssi")] = (WiFi.status() != WL_CONNECTED) ? 0 : WiFi.RSSI(); obj[F("ts_uptime")] = mApp->getUptime(); + obj[F("version")] = String(mApp->getVersion()); + obj[F("build")] = String(AUTO_GIT_HASH); obj[F("menu_prot")] = mApp->getProtection(request); obj[F("menu_mask")] = (uint16_t)(mConfig->sys.protectionMask ); obj[F("menu_protEn")] = (bool) (strlen(mConfig->sys.adminPwd) > 0); From 53ff04b6894e0005ea17043889361a530ba75645 Mon Sep 17 00:00:00 2001 From: lumapu Date: Sat, 29 Jul 2023 01:30:02 +0200 Subject: [PATCH 91/92] 0.7.20 * merge PR #1048 version and hash in API, fixes #1045 * fix: no yield day update if yield day reads `0` after inverter reboot (mostly on evening) #848 * try to fix Wifi override #1047 * added information after NTP sync to WebUI #1040 --- src/CHANGES.md | 6 ++++++ src/defines.h | 2 +- src/publisher/pubMqttIvData.h | 14 ++++++++++---- src/web/RestApi.h | 1 + src/web/html/setup.html | 26 +++++++++++++++++++++++--- src/wifi/ahoywifi.cpp | 14 ++++++++------ 6 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index 8aeec68f..a6746af5 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,11 @@ # Development Changes +## 0.7.20 - 2023-07-28 +* merge PR #1048 version and hash in API, fixes #1045 +* fix: no yield day update if yield day reads `0` after inverter reboot (mostly on evening) #848 +* try to fix Wifi override #1047 +* added information after NTP sync to WebUI #1040 + ## 0.7.19 - 2023-07-27 * next attempt to fix yield day for multiple inverters #1016 * reduced threshold for inverter state machine from 60min to 15min to go from state `WAS_ON` to `OFF` diff --git a/src/defines.h b/src/defines.h index ccafdea7..062bb0a9 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 19 +#define VERSION_PATCH 20 //------------------------------------- typedef struct { diff --git a/src/publisher/pubMqttIvData.h b/src/publisher/pubMqttIvData.h index 372ac9b5..40abd6bf 100644 --- a/src/publisher/pubMqttIvData.h +++ b/src/publisher/pubMqttIvData.h @@ -68,6 +68,7 @@ class PubMqttIvData { void stateStart() { mLastIvId = 0; mTotalFound = false; + mSendTotalYd = true; mAllTotalFound = true; if(!mSendList->empty()) { mCmd = mSendList->front().cmd; @@ -136,9 +137,14 @@ class PubMqttIvData { case FLD_YT: mTotal[1] += mIv->getValue(mPos, rec); break; - case FLD_YD: - mTotal[2] += mIv->getValue(mPos, rec); + case FLD_YD: { + uint8_t val = mIv->getValue(mPos, rec); + if(0 == val) // inverter restarted during day + mSendTotalYd = false; + else + mTotal[2] += val; break; + } case FLD_PDC: mTotal[3] += mIv->getValue(mPos, rec); break; @@ -180,7 +186,7 @@ class PubMqttIvData { fieldId = FLD_YT; break; case 2: - if(!mAllTotalFound) { + if((!mAllTotalFound) || (!mSendTotalYd)) { mPos++; return; } @@ -210,7 +216,7 @@ class PubMqttIvData { uint8_t mCmd; uint8_t mLastIvId; - bool mSendTotals, mTotalFound, mAllTotalFound; + bool mSendTotals, mTotalFound, mAllTotalFound, mSendTotalYd; float mTotal[4]; Inverter<> *mIv, *mIvSend; diff --git a/src/web/RestApi.h b/src/web/RestApi.h index dcc67513..fba6486e 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -197,6 +197,7 @@ class RestApi { void getGeneric(AsyncWebServerRequest *request, JsonObject obj) { obj[F("wifi_rssi")] = (WiFi.status() != WL_CONNECTED) ? 0 : WiFi.RSSI(); obj[F("ts_uptime")] = mApp->getUptime(); + obj[F("ts_now")] = mApp->getTimestamp(); obj[F("version")] = String(mApp->getVersion()); obj[F("build")] = String(AUTO_GIT_HASH); obj[F("menu_prot")] = mApp->getProtection(request); diff --git a/src/web/html/setup.html b/src/web/html/setup.html index 7c910838..52c4634d 100644 --- a/src/web/html/setup.html +++ b/src/web/html/setup.html @@ -200,13 +200,17 @@
-
set system time
+
set System time
- +
+
+
System Time
+
+
@@ -333,6 +337,7 @@