Browse Source

Merge branch 'development03' into Zero-Export

pull/1155/head
DanielR92 2 years ago
parent
commit
aea4a3f5ab
  1. 1
      scripts/applyPatches.py
  2. 10
      src/CHANGES.md
  3. 7
      src/app.cpp
  4. 12
      src/config/settings.h
  5. 2
      src/defines.h
  6. 16
      src/eth/ahoyeth.cpp
  7. 1
      src/hm/CommQueue.h
  8. 8
      src/hm/Communication.h
  9. 23
      src/hm/hmInverter.h
  10. 20
      src/hm/hmRadio.h
  11. 2
      src/hm/nrfHal.h
  12. 4
      src/hms/cmt2300a.h
  13. 11
      src/platformio.ini
  14. 14
      src/web/RestApi.h
  15. 5
      src/web/html/setup.html
  16. 10
      src/web/html/visualization.html
  17. 1
      src/web/web.h

1
scripts/applyPatches.py

@ -31,5 +31,4 @@ if env['PIOENV'][:22] != "opendtufusion-ethernet":
if env['PIOENV'][:13] == "opendtufusion": if env['PIOENV'][:13] == "opendtufusion":
applyPatch("GxEPD2", "../patches/GxEPD2_SW_SPI.patch") applyPatch("GxEPD2", "../patches/GxEPD2_SW_SPI.patch")
if env['PIOENV'][:22] == "opendtufusion-ethernet":
applyPatch("RF24", "../patches/RF24_Hal.patch") applyPatch("RF24", "../patches/RF24_Hal.patch")

10
src/CHANGES.md

@ -1,5 +1,15 @@
# Development Changes # Development Changes
## 0.8.26 - 2023-12-17
* read grid profile as HEX (`live` -> click inverter name -> `show grid profile`)
## 0.8.25 - 2023-12-17
* RX channel ID starts with fixed value #1277
* fix static IP for Ethernet
## 0.8.24 - 2023-12-16
* fix NRF communication for opendtufusion ethernet variant
## 0.8.23 - 2023-12-14 ## 0.8.23 - 2023-12-14
* heuristics fix #1269 #1270 * heuristics fix #1269 #1270
* moved `sendInterval` in settings, **important:** *will be reseted to 15s after update to this version* * moved `sendInterval` in settings, **important:** *will be reseted to 15s after update to this version*

7
src/app.cpp

@ -40,11 +40,7 @@ void app::setup() {
#endif #endif
#ifdef ETHERNET #ifdef ETHERNET
delay(1000); delay(1000);
DPRINT(DBG_INFO, F("mEth setup..."));
DSERIAL.flush();
mEth.setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); }); mEth.setup(mConfig, &mTimestamp, [this](bool gotIp) { this->onNetwork(gotIp); }, [this](bool gotTime) { this->onNtpUpdate(gotTime); });
DBGPRINTLN(F("done..."));
DSERIAL.flush();
#endif // ETHERNET #endif // ETHERNET
#if !defined(ETHERNET) #if !defined(ETHERNET)
@ -161,7 +157,6 @@ void app::regularTickers(void) {
#if !defined(ETHERNET) #if !defined(ETHERNET)
//everySec([this]() { mImprov.tickSerial(); }, "impro"); //everySec([this]() { mImprov.tickSerial(); }, "impro");
#endif #endif
// every([this]() { mPayload.simulation();}, 15, "simul");
} }
#if defined(ETHERNET) #if defined(ETHERNET)
@ -353,7 +348,7 @@ void app::tickSend(void) {
DBGPRINT(String(fill)); DBGPRINT(String(fill));
DBGPRINT(F(" of ")); DBGPRINT(F(" of "));
DBGPRINT(String(max)); DBGPRINT(String(max));
DBGPRINTLN(F("entries used")); DBGPRINTLN(F(" entries used"));
} }
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {

12
src/config/settings.h

@ -30,7 +30,7 @@
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout * https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
* */ * */
#define CONFIG_VERSION 5 #define CONFIG_VERSION 6
#define PROT_MASK_INDEX 0x0001 #define PROT_MASK_INDEX 0x0001
@ -175,6 +175,7 @@ typedef struct {
bool startWithoutTime; bool startWithoutTime;
float yieldEffiency; float yieldEffiency;
uint16_t gapMs; uint16_t gapMs;
bool readGrid;
} cfgInst_t; } cfgInst_t;
typedef struct { typedef struct {
@ -479,6 +480,7 @@ class settings {
mCfg.inst.rstMaxValsMidNight = false; mCfg.inst.rstMaxValsMidNight = false;
mCfg.inst.yieldEffiency = 1.0f; mCfg.inst.yieldEffiency = 1.0f;
mCfg.inst.gapMs = 2000; mCfg.inst.gapMs = 2000;
mCfg.inst.readGrid = true;
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) { for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value mCfg.inst.iv[i].powerLevel = 0xff; // impossible high value
@ -520,12 +522,16 @@ class settings {
mCfg.serial.printWholeTrace = false; mCfg.serial.printWholeTrace = false;
} }
if(mCfg.configVersion < 4) { if(mCfg.configVersion < 4) {
mCfg.inst.gapMs = 2000; mCfg.inst.gapMs = 500;
} }
if(mCfg.configVersion < 5) { if(mCfg.configVersion < 5) {
mCfg.inst.sendInterval = SEND_INTERVAL; mCfg.inst.sendInterval = SEND_INTERVAL;
mCfg.serial.printWholeTrace = false; mCfg.serial.printWholeTrace = false;
} }
if(mCfg.configVersion < 6) {
mCfg.inst.gapMs = 500;
mCfg.inst.readGrid = true;
}
} }
} }
@ -792,6 +798,7 @@ class settings {
obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight; obj[F("rstMaxMidNight")] = (bool)mCfg.inst.rstMaxValsMidNight;
obj[F("yldEff")] = mCfg.inst.yieldEffiency; obj[F("yldEff")] = mCfg.inst.yieldEffiency;
obj[F("gap")] = mCfg.inst.gapMs; obj[F("gap")] = mCfg.inst.gapMs;
obj[F("rdGrid")] = (bool)mCfg.inst.readGrid;
} }
else { else {
getVal<uint16_t>(obj, F("intvl"), &mCfg.inst.sendInterval); getVal<uint16_t>(obj, F("intvl"), &mCfg.inst.sendInterval);
@ -803,6 +810,7 @@ class settings {
getVal<bool>(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight); getVal<bool>(obj, F("rstMaxMidNight"), &mCfg.inst.rstMaxValsMidNight);
getVal<float>(obj, F("yldEff"), &mCfg.inst.yieldEffiency); getVal<float>(obj, F("yldEff"), &mCfg.inst.yieldEffiency);
getVal<uint16_t>(obj, F("gap"), &mCfg.inst.gapMs); getVal<uint16_t>(obj, F("gap"), &mCfg.inst.gapMs);
getVal<bool>(obj, F("rdGrid"), &mCfg.inst.readGrid);
if(mCfg.inst.yieldEffiency < 0.5) if(mCfg.inst.yieldEffiency < 0.5)
mCfg.inst.yieldEffiency = 1.0f; mCfg.inst.yieldEffiency = 1.0f;

2
src/defines.h

@ -13,7 +13,7 @@
//------------------------------------- //-------------------------------------
#define VERSION_MAJOR 0 #define VERSION_MAJOR 0
#define VERSION_MINOR 8 #define VERSION_MINOR 8
#define VERSION_PATCH 23 #define VERSION_PATCH 26
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

16
src/eth/ahoyeth.cpp

@ -26,12 +26,16 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe
mOnNetworkCB = onNetworkCB; mOnNetworkCB = onNetworkCB;
mOnTimeCB = onTimeCB; mOnTimeCB = onTimeCB;
DPRINTLN(DBG_INFO, F("[ETH]: Register for events..."));
Serial.flush(); Serial.flush();
WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); }); WiFi.onEvent([this](WiFiEvent_t event, arduino_event_info_t info) -> void { this->onEthernetEvent(event, info); });
DPRINTLN(DBG_INFO, F("[ETH]: begin..."));
Serial.flush(); Serial.flush();
#if defined(CONFIG_IDF_TARGET_ESP32S3)
mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN);
#else
ETH.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, ETH_SPI_CLOCK_MHZ, ETH_SPI_HOST);
#endif
if(mConfig->sys.ip.ip[0] != 0) { if(mConfig->sys.ip.ip[0] != 0) {
IPAddress ip(mConfig->sys.ip.ip); IPAddress ip(mConfig->sys.ip.ip);
IPAddress mask(mConfig->sys.ip.mask); IPAddress mask(mConfig->sys.ip.mask);
@ -41,11 +45,6 @@ void ahoyeth::setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNe
if(!ETH.config(ip, gateway, mask, dns1, dns2)) if(!ETH.config(ip, gateway, mask, dns1, dns2))
DPRINTLN(DBG_ERROR, F("failed to set static IP!")); DPRINTLN(DBG_ERROR, F("failed to set static IP!"));
} }
#if defined(CONFIG_IDF_TARGET_ESP32S3)
mEthSpi.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, DEF_ETH_RST_PIN);
#else
ETH.begin(DEF_ETH_MISO_PIN, DEF_ETH_MOSI_PIN, DEF_ETH_SCK_PIN, DEF_ETH_CS_PIN, DEF_ETH_IRQ_PIN, ETH_SPI_CLOCK_MHZ, ETH_SPI_HOST);
#endif
} }
@ -130,8 +129,7 @@ void ahoyeth::welcome(String ip, String mode) {
DBGPRINTLN(F("--------------------------------\n")); DBGPRINTLN(F("--------------------------------\n"));
} }
void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) void ahoyeth::onEthernetEvent(WiFiEvent_t event, arduino_event_info_t info) {
{
AWS_LOG(F("[ETH]: Got event...")); AWS_LOG(F("[ETH]: Got event..."));
switch (event) { switch (event) {
#if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) ) #if ( ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) ) && ( ARDUINO_ESP32_GIT_VER != 0x46d5afb1 ) )

1
src/hm/CommQueue.h

@ -31,6 +31,7 @@ class CommQueue {
} }
uint8_t getFillState(void) { uint8_t getFillState(void) {
DPRINTLN(DBG_INFO, "wr: " + String(mWrPtr) + ", rd: " + String(mRdPtr));
return abs(mRdPtr - mWrPtr); return abs(mRdPtr - mWrPtr);
} }

8
src/hm/Communication.h

@ -254,7 +254,7 @@ class Communication : public CommQueue<> {
compilePayload(q); compilePayload(q);
if(NULL != mCbPayload) if((NULL != mCbPayload) && (GridOnProFilePara != q->cmd))
(mCbPayload)(q->cmd, q->iv); (mCbPayload)(q->cmd, q->iv);
closeRequest(q, true); closeRequest(q, true);
@ -440,9 +440,15 @@ class Communication : public CommQueue<> {
} else } else
DBGPRINTLN(F(")")); DBGPRINTLN(F(")"));
if(GridOnProFilePara == q->cmd) {
q->iv->addGridProfile(mPayload, len);
return;
}
record_t<> *rec = q->iv->getRecordStruct(q->cmd); record_t<> *rec = q->iv->getRecordStruct(q->cmd);
if(NULL == rec) { if(NULL == rec) {
DPRINTLN(DBG_ERROR, F("record is NULL!")); DPRINTLN(DBG_ERROR, F("record is NULL!"));
closeRequest(q, false);
return; return;
} }
if((rec->pyldLen != len) && (0 != rec->pyldLen)) { if((rec->pyldLen != len) && (0 != rec->pyldLen)) {

23
src/hm/hmInverter.h

@ -11,6 +11,8 @@
#define F(sl) (sl) #define F(sl) (sl)
#endif #endif
#define MAX_GRID_LENGTH 150
#include "hmDefines.h" #include "hmDefines.h"
#include "HeuristicInv.h" #include "HeuristicInv.h"
#include "../hms/hmsDefines.h" #include "../hms/hmsDefines.h"
@ -133,7 +135,7 @@ class Inverter {
bool mGotLastMsg; // shows if inverter has already finished transmission cycle bool mGotLastMsg; // shows if inverter has already finished transmission cycle
Radio *radio; // pointer to associated radio class Radio *radio; // pointer to associated radio class
statistics_t radioStatistics; // information about transmitted, failed, ... packets statistics_t radioStatistics; // information about transmitted, failed, ... packets
HeuristicInv heuristics; HeuristicInv heuristics; // heuristic information / logic
uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime uint8_t curCmtFreq; // current used CMT frequency, used to check if freq. was changed during runtime
bool commEnabled; // 'pause night communication' sets this field to false bool commEnabled; // 'pause night communication' sets this field to false
@ -183,6 +185,8 @@ class Inverter {
else if(InitDataState != devControlCmd) { else if(InitDataState != devControlCmd) {
cb(devControlCmd, false); // custom command which was received by API cb(devControlCmd, false); // custom command which was received by API
devControlCmd = InitDataState; devControlCmd = InitDataState;
} else if((0 == mGridLen) && generalConfig->readGrid) { // read grid profile
cb(GridOnProFilePara, false);
} else } else
cb(RealTimeRunData_Debug, false); // get live data cb(RealTimeRunData_Debug, false); // get live data
} else { } else {
@ -721,6 +725,21 @@ class Inverter {
} }
} }
void addGridProfile(uint8_t buf[], uint8_t length) {
mGridLen = (length > MAX_GRID_LENGTH) ? MAX_GRID_LENGTH : length;
std::copy(buf, &buf[mGridLen], mGridProfile);
}
String getGridProfile(void) {
char buf[MAX_GRID_LENGTH * 3];
memset(buf, 0, MAX_GRID_LENGTH);
for(uint8_t i = 0; i < mGridLen; i++) {
snprintf(&buf[i*3], 4, "%02X ", mGridProfile[i]);
}
buf[mGridLen*3] = 0;
return String(buf);
}
private: private:
inline void addAlarm(uint16_t code, uint32_t start, uint32_t end) { inline void addAlarm(uint16_t code, uint32_t start, uint32_t end) {
lastAlarm[alarmNxtWrPos] = alarm_t(code, start, end); lastAlarm[alarmNxtWrPos] = alarm_t(code, start, end);
@ -741,6 +760,8 @@ class Inverter {
private: private:
float mOffYD[6], mLastYD[6]; float mOffYD[6], mLastYD[6];
bool mDevControlRequest; // true if change needed bool mDevControlRequest; // true if change needed
uint8_t mGridLen = 0;
uint8_t mGridProfile[MAX_GRID_LENGTH];
}; };
template <class REC_TYP> template <class REC_TYP>

20
src/hm/hmRadio.h

@ -10,7 +10,7 @@
#include "SPI.h" #include "SPI.h"
#include "radio.h" #include "radio.h"
#include "../config/config.h" #include "../config/config.h"
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
#include "nrfHal.h" #include "nrfHal.h"
#endif #endif
@ -35,8 +35,8 @@ class HmRadio : public Radio {
HmRadio() { HmRadio() {
mDtuSn = DTU_SN; mDtuSn = DTU_SN;
mIrqRcvd = false; mIrqRcvd = false;
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
mNrf24.reset(new RF24()); //mNrf24.reset(new RF24());
#else #else
mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED)); mNrf24.reset(new RF24(CE_PIN, CS_PIN, SPI_SPEED));
#endif #endif
@ -56,8 +56,8 @@ class HmRadio : public Radio {
DTU_RADIO_ID = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01; DTU_RADIO_ID = ((uint64_t)(((mDtuSn >> 24) & 0xFF) | ((mDtuSn >> 8) & 0xFF00) | ((mDtuSn << 8) & 0xFF0000) | ((mDtuSn << 24) & 0xFF000000)) << 8) | 0x01;
#ifdef ESP32 #ifdef ESP32
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
mNrfHal.init(mosi, miso, sclk, cs, ce); mNrfHal.init(mosi, miso, sclk, cs, ce, SPI_SPEED);
mNrf24.reset(new RF24(&mNrfHal)); mNrf24.reset(new RF24(&mNrfHal));
#else #else
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
@ -73,7 +73,7 @@ class HmRadio : public Radio {
mSpi->begin(); mSpi->begin();
#endif #endif
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
mNrf24->begin(); mNrf24->begin();
#else #else
mNrf24->begin(mSpi.get(), ce, cs); mNrf24->begin(mSpi.get(), ce, cs);
@ -133,14 +133,12 @@ class HmRadio : public Radio {
yield(); yield();
} }
// switch to next RX channel // switch to next RX channel
if(++mRxChIdx >= RF_CHANNELS) mRxChIdx = (mRxChIdx + 1) % RF_CHANNELS;
mRxChIdx = 0;
mNrf24->setChannel(mRfChLst[mRxChIdx]); mNrf24->setChannel(mRfChLst[mRxChIdx]);
startMicros = micros(); startMicros = micros();
} }
// not finished but time is over // not finished but time is over
if(++mRxChIdx >= RF_CHANNELS) mRxChIdx = 1;
mRxChIdx = 0;
return; return;
} }
@ -344,7 +342,7 @@ class HmRadio : public Radio {
std::unique_ptr<SPIClass> mSpi; std::unique_ptr<SPIClass> mSpi;
std::unique_ptr<RF24> mNrf24; std::unique_ptr<RF24> mNrf24;
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
nrfHal mNrfHal; nrfHal mNrfHal;
#endif #endif
Inverter<> *mLastIv = NULL; Inverter<> *mLastIv = NULL;

2
src/hm/nrfHal.h

@ -118,7 +118,7 @@ class nrfHal: public RF24_hal, public SpiPatcherHandle {
uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t data_len, uint8_t blank_len) override { uint8_t write(uint8_t cmd, const uint8_t* buf, uint8_t data_len, uint8_t blank_len) override {
uint8_t data[NRF_MAX_TRANSFER_SZ]; uint8_t data[NRF_MAX_TRANSFER_SZ];
data[0] = cmd; data[0] = cmd;
memset(data, 0, NRF_MAX_TRANSFER_SZ); memset(&data[1], 0, (NRF_MAX_TRANSFER_SZ-1));
std::copy(&buf[0], &buf[data_len], &data[1]); std::copy(&buf[0], &buf[data_len], &data[1]);
request_spi(); request_spi();

4
src/hms/cmt2300a.h

@ -6,7 +6,7 @@
#ifndef __CMT2300A_H__ #ifndef __CMT2300A_H__
#define __CMT2300A_H__ #define __CMT2300A_H__
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
#include "cmtHal.h" #include "cmtHal.h"
#else #else
#include "esp32_3wSpi.h" #include "esp32_3wSpi.h"
@ -480,7 +480,7 @@ class Cmt2300a {
return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA; return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
} }
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(ETHERNET) #if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(SPI_HAL)
cmtHal mSpi; cmtHal mSpi;
#else #else
esp32_3wSpi mSpi; esp32_3wSpi mSpi;

11
src/platformio.ini

@ -162,6 +162,7 @@ lib_deps =
upload_protocol = esp-builtin upload_protocol = esp-builtin
build_flags = ${env.build_flags} build_flags = ${env.build_flags}
-DETHERNET -DETHERNET
-DSPI_HAL
-DUSE_HSPI_FOR_EPD -DUSE_HSPI_FOR_EPD
-DDEF_ETH_CS_PIN=42 -DDEF_ETH_CS_PIN=42
-DDEF_ETH_SCK_PIN=39 -DDEF_ETH_SCK_PIN=39
@ -191,6 +192,15 @@ monitor_filters =
[env:opendtufusion-dev] [env:opendtufusion-dev]
platform = espressif32@6.4.0 platform = espressif32@6.4.0
board = esp32-s3-devkitc-1 board = esp32-s3-devkitc-1
lib_deps =
https://github.com/yubox-node-org/ESPAsyncWebServer
https://github.com/nrf24/RF24 @ ^1.4.8
paulstoffregen/Time @ ^1.6.1
https://github.com/bertmelis/espMqttClient#v1.5.0
bblanchon/ArduinoJson @ ^6.21.3
https://github.com/JChristensen/Timezone @ ^1.2.4
olikraus/U8g2 @ ^2.35.7
https://github.com/zinggjm/GxEPD2 @ ^1.5.2
upload_protocol = esp-builtin upload_protocol = esp-builtin
build_flags = ${env.build_flags} build_flags = ${env.build_flags}
-DDEF_NRF_CS_PIN=37 -DDEF_NRF_CS_PIN=37
@ -209,5 +219,6 @@ build_flags = ${env.build_flags}
-DLED_ACTIVE_HIGH -DLED_ACTIVE_HIGH
-DARDUINO_USB_MODE=1 -DARDUINO_USB_MODE=1
-DARDUINO_USB_CDC_ON_BOOT=1 -DARDUINO_USB_CDC_ON_BOOT=1
-DSPI_HAL
monitor_filters = monitor_filters =
esp32_exception_decoder, colorize esp32_exception_decoder, colorize

14
src/web/RestApi.h

@ -109,6 +109,8 @@ class RestApi {
getIvStatistis(root, request->url().substring(24).toInt()); getIvStatistis(root, request->url().substring(24).toInt());
else if(path.substring(0, 16) == "inverter/pwrack/") else if(path.substring(0, 16) == "inverter/pwrack/")
getIvPowerLimitAck(root, request->url().substring(21).toInt()); getIvPowerLimitAck(root, request->url().substring(21).toInt());
else if(path.substring(0, 14) == "inverter/grid/")
getGridProfile(root, request->url().substring(19).toInt());
else else
getNotFound(root, F("http://") + request->host() + F("/api/")); getNotFound(root, F("http://") + request->host() + F("/api/"));
} }
@ -395,6 +397,7 @@ class RestApi {
obj[F("rstNotAvail")] = (bool)mConfig->inst.rstValsNotAvail; obj[F("rstNotAvail")] = (bool)mConfig->inst.rstValsNotAvail;
obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop; obj[F("rstComStop")] = (bool)mConfig->inst.rstValsCommStop;
obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime; obj[F("strtWthtTm")] = (bool)mConfig->inst.startWithoutTime;
obj[F("rdGrid")] = (bool)mConfig->inst.readGrid;
obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight; obj[F("rstMaxMid")] = (bool)mConfig->inst.rstMaxValsMidNight;
obj[F("yldEff")] = mConfig->inst.yieldEffiency; obj[F("yldEff")] = mConfig->inst.yieldEffiency;
obj[F("gap")] = mConfig->inst.gapMs; obj[F("gap")] = mConfig->inst.gapMs;
@ -452,6 +455,16 @@ class RestApi {
} }
} }
void getGridProfile(JsonObject obj, uint8_t id) {
Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL == iv) {
return;
}
obj[F("name")] = String(iv->config->name);
obj[F("grid")] = iv->getGridProfile();
}
void getIvAlarms(JsonObject obj, uint8_t id) { void getIvAlarms(JsonObject obj, uint8_t id) {
Inverter<> *iv = mSys->getInverterByPos(id); Inverter<> *iv = mSys->getInverterByPos(id);
if(NULL == iv) { if(NULL == iv) {
@ -484,6 +497,7 @@ class RestApi {
record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple); record_t<> *rec = iv->getRecordStruct(InverterDevInform_Simple);
obj[F("id")] = id;
obj[F("name")] = String(iv->config->name); obj[F("name")] = String(iv->config->name);
obj[F("serial")] = String(iv->config->serial.u64, HEX); obj[F("serial")] = String(iv->config->serial.u64, HEX);
obj[F("generation")] = iv->ivGen; obj[F("generation")] = iv->ivGen;

5
src/web/html/setup.html

@ -176,6 +176,10 @@
<div class="col-8">Start without time sync (useful in AP-Only-Mode)</div> <div class="col-8">Start without time sync (useful in AP-Only-Mode)</div>
<div class="col-4"><input type="checkbox" name="strtWthtTm"/></div> <div class="col-4"><input type="checkbox" name="strtWthtTm"/></div>
</div> </div>
<div class="row mb-3">
<div class="col-8">Read Grid Profile</div>
<div class="col-4"><input type="checkbox" name="rdGrid"/></div>
</div>
<div class="row mb-3"> <div class="row mb-3">
<div class="col-8">Yield Efficiency (Standard 1.0)</div> <div class="col-8">Yield Efficiency (Standard 1.0)</div>
<div class="col-4"><input type="number" name="yldEff" step="any"/></div> <div class="col-4"><input type="number" name="yldEff" step="any"/></div>
@ -627,6 +631,7 @@
for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"]) for(var i of ["Mid", "ComStop", "NotAvail", "MaxMid"])
document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i]; document.getElementsByName("invRst"+i)[0].checked = obj["rst" + i];
document.getElementsByName("strtWthtTm")[0].checked = obj["strtWthtTm"]; document.getElementsByName("strtWthtTm")[0].checked = obj["strtWthtTm"];
document.getElementsByName("rdGrid")[0].checked = obj["rdGrid"];
} }
function parseSys(obj) { function parseSys(obj) {

10
src/web/html/visualization.html

@ -290,12 +290,20 @@
tr("Firmware Version / Build", String(obj.fw_ver) + " (build: " + String(obj.fw_date) + " " + String(obj.fw_time) + ")"), tr("Firmware Version / Build", String(obj.fw_ver) + " (build: " + String(obj.fw_date) + " " + String(obj.fw_time) + ")"),
tr("Hardware Version / Build", (obj.hw_ver/100).toFixed(2) + " (build: " + String(obj.prod_cw) + "/" + String(obj.prod_year) + ")"), tr("Hardware Version / Build", (obj.hw_ver/100).toFixed(2) + " (build: " + String(obj.prod_cw) + "/" + String(obj.prod_year) + ")"),
tr("Hardware Number", obj.part_num.toString(16)), tr("Hardware Number", obj.part_num.toString(16)),
tr("Bootloader Version", (obj.boot_ver/100).toFixed(2)) tr("Bootloader Version", (obj.boot_ver/100).toFixed(2)),
tr("Grid Profile", ml("input", {type: "button", value: "show", class: "btn", onclick: function() {
modalClose();
getAjax("/api/inverter/grid/" + obj.id, showGridProfile);
}}, null))
]) ])
]); ]);
modal("Info for inverter " + obj.name, ml("div", {}, html)); modal("Info for inverter " + obj.name, ml("div", {}, html));
} }
function showGridProfile(obj) {
var html = ml("pre", {}, obj.grid);
modal("Grid Profile for inverter " + obj.name, ml("div", {}, html));
}
function parseIvRadioStats(obj) { function parseIvRadioStats(obj) {

1
src/web/web.h

@ -501,6 +501,7 @@ class Web {
mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on"); mConfig->inst.rstValsCommStop = (request->arg("invRstComStop") == "on");
mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on"); mConfig->inst.rstValsNotAvail = (request->arg("invRstNotAvail") == "on");
mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on"); mConfig->inst.startWithoutTime = (request->arg("strtWthtTm") == "on");
mConfig->inst.readGrid = (request->arg("rdGrid") == "on");
mConfig->inst.rstMaxValsMidNight = (request->arg("invRstMaxMid") == "on"); mConfig->inst.rstMaxValsMidNight = (request->arg("invRstMaxMid") == "on");
mConfig->inst.yieldEffiency = (request->arg("yldEff")).toFloat(); mConfig->inst.yieldEffiency = (request->arg("yldEff")).toFloat();
mConfig->inst.gapMs = (request->arg("invGap")).toInt(); mConfig->inst.gapMs = (request->arg("invGap")).toInt();

Loading…
Cancel
Save