mirror of
https://github.com/lumapu/ahoy.git
synced 2025-06-02 10:41:40 +02:00
Merge branch 'development03' into Ethernet+Wifi
This commit is contained in:
commit
1ab05f3a98
16 changed files with 297 additions and 44 deletions
4
.github/workflows/compile_development.yml
vendored
4
.github/workflows/compile_development.yml
vendored
|
@ -25,6 +25,8 @@ jobs:
|
||||||
variant:
|
variant:
|
||||||
- opendtufusion
|
- opendtufusion
|
||||||
- opendtufusion-ethernet
|
- opendtufusion-ethernet
|
||||||
|
- opendtufusion-16MB
|
||||||
|
- opendtufusion-ethernet-16MB
|
||||||
- esp8266
|
- esp8266
|
||||||
- esp8266-all
|
- esp8266-all
|
||||||
- esp8266-minimal
|
- esp8266-minimal
|
||||||
|
@ -94,6 +96,8 @@ jobs:
|
||||||
variant:
|
variant:
|
||||||
- opendtufusion-de
|
- opendtufusion-de
|
||||||
- opendtufusion-ethernet-de
|
- opendtufusion-ethernet-de
|
||||||
|
- opendtufusion-16MB-de
|
||||||
|
- opendtufusion-ethernet-16MB-de
|
||||||
- esp8266-de
|
- esp8266-de
|
||||||
- esp8266-all-de
|
- esp8266-all-de
|
||||||
- esp8266-prometheus-de
|
- esp8266-prometheus-de
|
||||||
|
|
|
@ -1,10 +1,35 @@
|
||||||
# Development Changes
|
# Development Changes
|
||||||
|
|
||||||
|
## 0.8.129 - 2024-07-11
|
||||||
|
* sort alarms ascending #1471
|
||||||
|
* fix alarm counter for first alarm
|
||||||
|
* prevent add inverter multiple times #1700
|
||||||
|
|
||||||
|
## 0.8.128 - 2024-07-10
|
||||||
|
* add environments for 16MB flash size ESP32-S3 aka opendtufusion
|
||||||
|
* prevent duplicate alarms, update end time once it is received #1471
|
||||||
|
|
||||||
|
## 0.8.127 - 2024-06-21
|
||||||
|
* add grid file #1677
|
||||||
|
* merge PR: Bugfix Inv delete not working with password protection #1678
|
||||||
|
|
||||||
|
## 0.8.126 - 2024-06-12
|
||||||
|
* merge PR: Update pubMqtt.h - Bugfix #1673 #1674
|
||||||
|
|
||||||
|
## 0.8.125 - 2024-06-09
|
||||||
|
* fix ESP8266 compilation
|
||||||
|
* merge PR: active_PowerLimit #1663
|
||||||
|
|
||||||
|
## 0.8.124 - 2024-06-06
|
||||||
|
* improved MqTT `OnMessage` (threadsafe)
|
||||||
|
* support of HERF inverters, serial number is converted in Javascript #1425
|
||||||
|
* revert buffer size in `RestAPI` for ESP8266 #1650
|
||||||
|
|
||||||
## 0.8.123 - 2024-05-30
|
## 0.8.123 - 2024-05-30
|
||||||
* fix ESP8266, ESP32 static IP #1643 #1608
|
* fix ESP8266, ESP32 static IP #1643 #1608
|
||||||
* update MqTT library which enhances stability #1646
|
* update MqTT library which enhances stability #1646
|
||||||
* merge PR: MQTT JSON Payload pro Kanal und total, auswählbar #1541
|
* merge PR: MqTT JSON Payload pro Kanal und total, auswählbar #1541
|
||||||
* add option to publish mqtt as json
|
* add option to publish MqTT as json
|
||||||
* publish rssi not on ch0 any more, published on `topic/rssi`
|
* publish rssi not on ch0 any more, published on `topic/rssi`
|
||||||
* add total power to index page (if multiple inverters are configured)
|
* add total power to index page (if multiple inverters are configured)
|
||||||
* show device name in html title #1639
|
* show device name in html title #1639
|
||||||
|
|
|
@ -16,9 +16,8 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
|
|
||||||
// Fallback WiFi Info
|
// Fallback WiFi Info
|
||||||
#define FB_WIFI_SSID "YOUR_WIFI_SSID"
|
#define FB_WIFI_SSID ""
|
||||||
#define FB_WIFI_PWD "YOUR_WIFI_PWD"
|
#define FB_WIFI_PWD ""
|
||||||
|
|
||||||
|
|
||||||
// Access Point Info
|
// Access Point Info
|
||||||
// In case there is no WiFi Network or Ahoy can not connect to it, it will act as an Access Point
|
// In case there is no WiFi Network or Ahoy can not connect to it, it will act as an Access Point
|
||||||
|
|
|
@ -6,9 +6,6 @@
|
||||||
#ifndef __CONFIG_OVERRIDE_H__
|
#ifndef __CONFIG_OVERRIDE_H__
|
||||||
#define __CONFIG_OVERRIDE_H__
|
#define __CONFIG_OVERRIDE_H__
|
||||||
|
|
||||||
// override fallback WiFi info
|
|
||||||
#define FB_WIFI_OVERRIDDEN
|
|
||||||
|
|
||||||
// each override must be preceded with an #undef statement
|
// each override must be preceded with an #undef statement
|
||||||
#undef FB_WIFI_SSID
|
#undef FB_WIFI_SSID
|
||||||
#define FB_WIFI_SSID "MY_SSID"
|
#define FB_WIFI_SSID "MY_SSID"
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 8
|
#define VERSION_MINOR 8
|
||||||
#define VERSION_PATCH 123
|
#define VERSION_PATCH 129
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t ch;
|
uint8_t ch;
|
||||||
|
|
|
@ -670,7 +670,6 @@ class Inverter {
|
||||||
DPRINTLN(DBG_DEBUG, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(endTime));
|
DPRINTLN(DBG_DEBUG, "Alarm #" + String(pyld[startOff+1]) + " '" + String(getAlarmStr(pyld[startOff+1])) + "' start: " + ah::getTimeStr(start) + ", end: " + ah::getTimeStr(endTime));
|
||||||
addAlarm(pyld[startOff+1], start, endTime);
|
addAlarm(pyld[startOff+1], start, endTime);
|
||||||
|
|
||||||
alarmCnt++;
|
|
||||||
alarmLastId = alarmMesIndex;
|
alarmLastId = alarmMesIndex;
|
||||||
|
|
||||||
return pyld[startOff+1];
|
return pyld[startOff+1];
|
||||||
|
@ -818,6 +817,26 @@ class Inverter {
|
||||||
|
|
||||||
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) {
|
||||||
|
bool found = false;
|
||||||
|
uint8_t i = 0;
|
||||||
|
|
||||||
|
if(start > end)
|
||||||
|
end = 0;
|
||||||
|
|
||||||
|
for(; i < 10; i++) {
|
||||||
|
mAlarmNxtWrPos = (++mAlarmNxtWrPos) % 10;
|
||||||
|
|
||||||
|
if(lastAlarm[mAlarmNxtWrPos].code == code && lastAlarm[mAlarmNxtWrPos].start == start) {
|
||||||
|
// replace with same or update end time
|
||||||
|
if(lastAlarm[mAlarmNxtWrPos].end == 0 || lastAlarm[mAlarmNxtWrPos].end == end) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(alarmCnt < 10 && alarmCnt <= mAlarmNxtWrPos)
|
||||||
|
alarmCnt = mAlarmNxtWrPos + 1;
|
||||||
|
|
||||||
lastAlarm[mAlarmNxtWrPos] = alarm_t(code, start, end);
|
lastAlarm[mAlarmNxtWrPos] = alarm_t(code, start, end);
|
||||||
if(++mAlarmNxtWrPos >= 10) // rolling buffer
|
if(++mAlarmNxtWrPos >= 10) // rolling buffer
|
||||||
mAlarmNxtWrPos = 0;
|
mAlarmNxtWrPos = 0;
|
||||||
|
|
|
@ -17,7 +17,7 @@ class AhoyWifi : public AhoyNetwork {
|
||||||
virtual void begin() override {
|
virtual void begin() override {
|
||||||
mAp.enable();
|
mAp.enable();
|
||||||
|
|
||||||
if(String(FB_WIFI_SSID) == mConfig->sys.stationSsid)
|
if(strlen(mConfig->sys.stationSsid) == 0)
|
||||||
return; // no station wifi defined
|
return; // no station wifi defined
|
||||||
|
|
||||||
WiFi.disconnect(); // clean up
|
WiFi.disconnect(); // clean up
|
||||||
|
|
|
@ -30,7 +30,7 @@ lib_deps =
|
||||||
https://github.com/nRF24/RF24.git#v1.4.8
|
https://github.com/nRF24/RF24.git#v1.4.8
|
||||||
paulstoffregen/Time @ ^1.6.1
|
paulstoffregen/Time @ ^1.6.1
|
||||||
https://github.com/bertmelis/espMqttClient#v1.7.0
|
https://github.com/bertmelis/espMqttClient#v1.7.0
|
||||||
bblanchon/ArduinoJson @ ^6.21.3
|
bblanchon/ArduinoJson @ ^6.21.5
|
||||||
https://github.com/JChristensen/Timezone @ ^1.2.4
|
https://github.com/JChristensen/Timezone @ ^1.2.4
|
||||||
olikraus/U8g2 @ ^2.35.9
|
olikraus/U8g2 @ ^2.35.9
|
||||||
https://github.com/zinggjm/GxEPD2#1.5.3
|
https://github.com/zinggjm/GxEPD2#1.5.3
|
||||||
|
@ -149,7 +149,7 @@ monitor_filters =
|
||||||
esp8266_exception_decoder
|
esp8266_exception_decoder
|
||||||
|
|
||||||
[env:esp32-wroom32-minimal]
|
[env:esp32-wroom32-minimal]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
-DSPI_HAL
|
-DSPI_HAL
|
||||||
|
@ -157,7 +157,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-wroom32]
|
[env:esp32-wroom32]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
build_flags = ${env:esp32-wroom32-minimal.build_flags}
|
build_flags = ${env:esp32-wroom32-minimal.build_flags}
|
||||||
-DUSE_HSPI_FOR_EPD
|
-DUSE_HSPI_FOR_EPD
|
||||||
|
@ -168,7 +168,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-wroom32-de]
|
[env:esp32-wroom32-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
build_flags = ${env:esp32-wroom32.build_flags}
|
build_flags = ${env:esp32-wroom32.build_flags}
|
||||||
-DLANG_DE
|
-DLANG_DE
|
||||||
|
@ -176,7 +176,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-wroom32-prometheus]
|
[env:esp32-wroom32-prometheus]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
build_flags = ${env:esp32-wroom32.build_flags}
|
build_flags = ${env:esp32-wroom32.build_flags}
|
||||||
-DENABLE_PROMETHEUS_EP
|
-DENABLE_PROMETHEUS_EP
|
||||||
|
@ -184,7 +184,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-wroom32-prometheus-de]
|
[env:esp32-wroom32-prometheus-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_d32
|
board = lolin_d32
|
||||||
build_flags = ${env:esp32-wroom32-prometheus.build_flags}
|
build_flags = ${env:esp32-wroom32-prometheus.build_flags}
|
||||||
-DLANG_DE
|
-DLANG_DE
|
||||||
|
@ -220,7 +220,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-s2-mini]
|
[env:esp32-s2-mini]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_s2_mini
|
board = lolin_s2_mini
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
-DUSE_HSPI_FOR_EPD
|
-DUSE_HSPI_FOR_EPD
|
||||||
|
@ -243,7 +243,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-s2-mini-de]
|
[env:esp32-s2-mini-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_s2_mini
|
board = lolin_s2_mini
|
||||||
build_flags = ${env:esp32-s2-mini.build_flags}
|
build_flags = ${env:esp32-s2-mini.build_flags}
|
||||||
-DLANG_DE
|
-DLANG_DE
|
||||||
|
@ -251,7 +251,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-c3-mini]
|
[env:esp32-c3-mini]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_c3_mini
|
board = lolin_c3_mini
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
-DUSE_HSPI_FOR_EPD
|
-DUSE_HSPI_FOR_EPD
|
||||||
|
@ -274,7 +274,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:esp32-c3-mini-de]
|
[env:esp32-c3-mini-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = lolin_c3_mini
|
board = lolin_c3_mini
|
||||||
build_flags = ${env:esp32-c3-mini.build_flags}
|
build_flags = ${env:esp32-c3-mini.build_flags}
|
||||||
-DLANG_DE
|
-DLANG_DE
|
||||||
|
@ -282,7 +282,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder
|
esp32_exception_decoder
|
||||||
|
|
||||||
[env:opendtufusion-minimal]
|
[env:opendtufusion-minimal]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esp-builtin
|
||||||
build_flags = ${env.build_flags}
|
build_flags = ${env.build_flags}
|
||||||
|
@ -307,7 +307,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder, colorize
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
[env:opendtufusion]
|
[env:opendtufusion]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esp-builtin
|
||||||
build_flags = ${env:opendtufusion-minimal.build_flags}
|
build_flags = ${env:opendtufusion-minimal.build_flags}
|
||||||
|
@ -318,7 +318,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder, colorize
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
[env:opendtufusion-de]
|
[env:opendtufusion-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esp-builtin
|
||||||
build_flags = ${env:opendtufusion.build_flags}
|
build_flags = ${env:opendtufusion.build_flags}
|
||||||
|
@ -327,7 +327,7 @@ monitor_filters =
|
||||||
esp32_exception_decoder, colorize
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
[env:opendtufusion-ethernet]
|
[env:opendtufusion-ethernet]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esp-builtin
|
||||||
build_flags = ${env:opendtufusion-minimal.build_flags}
|
build_flags = ${env:opendtufusion-minimal.build_flags}
|
||||||
|
@ -346,10 +346,46 @@ monitor_filters =
|
||||||
esp32_exception_decoder, colorize
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
[env:opendtufusion-ethernet-de]
|
[env:opendtufusion-ethernet-de]
|
||||||
platform = espressif32@6.6.0
|
platform = espressif32@6.7.0
|
||||||
board = esp32-s3-devkitc-1
|
board = esp32-s3-devkitc-1
|
||||||
upload_protocol = esp-builtin
|
upload_protocol = esp-builtin
|
||||||
build_flags = ${env:opendtufusion-ethernet.build_flags}
|
build_flags = ${env:opendtufusion-ethernet.build_flags}
|
||||||
-DLANG_DE
|
-DLANG_DE
|
||||||
monitor_filters =
|
monitor_filters =
|
||||||
esp32_exception_decoder, colorize
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
|
[env:opendtufusion-16MB]
|
||||||
|
platform = espressif32@6.7.0
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
board_upload.flash_size = 16MB
|
||||||
|
upload_protocol = esp-builtin
|
||||||
|
build_flags = ${env:opendtufusion.build_flags}
|
||||||
|
monitor_filters =
|
||||||
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
|
[env:opendtufusion-16MB-de]
|
||||||
|
platform = espressif32@6.7.0
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
upload_protocol = esp-builtin
|
||||||
|
build_flags = ${env:opendtufusion-16MB.build_flags}
|
||||||
|
-DLANG_DE
|
||||||
|
monitor_filters =
|
||||||
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
|
[env:opendtufusion-ethernet-16MB]
|
||||||
|
platform = espressif32@6.7.0
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
board_upload.flash_size = 16MB
|
||||||
|
upload_protocol = esp-builtin
|
||||||
|
build_flags = ${env:opendtufusion-ethernet.build_flags}
|
||||||
|
monitor_filters =
|
||||||
|
esp32_exception_decoder, colorize
|
||||||
|
|
||||||
|
[env:opendtufusion-ethernet-16MB-de]
|
||||||
|
platform = espressif32@6.7.0
|
||||||
|
board = esp32-s3-devkitc-1
|
||||||
|
upload_protocol = esp-builtin
|
||||||
|
build_flags = ${env:opendtufusion-ethernet-16MB.build_flags}
|
||||||
|
-DLANG_DE
|
||||||
|
monitor_filters =
|
||||||
|
esp32_exception_decoder, colorize
|
||||||
|
|
|
@ -50,7 +50,7 @@ class MaxPower {
|
||||||
if((mValues[i].first + mMaxDiff) >= *mTs)
|
if((mValues[i].first + mMaxDiff) >= *mTs)
|
||||||
val += mValues[i].second;
|
val += mValues[i].second;
|
||||||
else if(mValues[i].first > 0)
|
else if(mValues[i].first > 0)
|
||||||
return mLast; // old data
|
break; // old data
|
||||||
}
|
}
|
||||||
if(val > mLast)
|
if(val > mLast)
|
||||||
mLast = val;
|
mLast = val;
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#if defined(ENABLE_MQTT)
|
#if defined(ENABLE_MQTT)
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
#include <ESP8266WiFi.h>
|
#include <ESP8266WiFi.h>
|
||||||
|
#define xSemaphoreTake(a, b) { while(a) { yield(); } a = true; }
|
||||||
|
#define xSemaphoreGive(a) { a = false; }
|
||||||
#elif defined(ESP32)
|
#elif defined(ESP32)
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -39,6 +41,13 @@ template<class HMSYSTEM>
|
||||||
class PubMqtt {
|
class PubMqtt {
|
||||||
public:
|
public:
|
||||||
PubMqtt() : SendIvData() {
|
PubMqtt() : SendIvData() {
|
||||||
|
#if defined(ESP32)
|
||||||
|
mutex = xSemaphoreCreateBinaryStatic(&mutexBuffer);
|
||||||
|
xSemaphoreGive(mutex);
|
||||||
|
#else
|
||||||
|
mutex = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
mLastIvState.fill(InverterStatus::OFF);
|
mLastIvState.fill(InverterStatus::OFF);
|
||||||
mIvLastRTRpub.fill(0);
|
mIvLastRTRpub.fill(0);
|
||||||
|
|
||||||
|
@ -50,7 +59,11 @@ class PubMqtt {
|
||||||
mSendAlarm.fill(false);
|
mSendAlarm.fill(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
~PubMqtt() { }
|
~PubMqtt() {
|
||||||
|
#if defined(ESP32)
|
||||||
|
vSemaphoreDelete(mutex);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void setup(IApp *app, cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) {
|
void setup(IApp *app, cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *uptime) {
|
||||||
mApp = app;
|
mApp = app;
|
||||||
|
@ -96,6 +109,17 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
std::queue<message_s> queue;
|
||||||
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
|
queue.swap(mReceiveQueue);
|
||||||
|
xSemaphoreGive(mutex);
|
||||||
|
|
||||||
|
while (!queue.empty()) {
|
||||||
|
message_s *entry = &queue.front();
|
||||||
|
handleMessage(entry->topic, entry->payload, entry->len, entry->index, entry->total);
|
||||||
|
queue.pop();
|
||||||
|
}
|
||||||
|
|
||||||
SendIvData.loop();
|
SendIvData.loop();
|
||||||
|
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
|
@ -301,6 +325,14 @@ class PubMqtt {
|
||||||
void onMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) {
|
void onMessage(const espMqttClientTypes::MessageProperties& properties, const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) {
|
||||||
if(len == 0)
|
if(len == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
xSemaphoreTake(mutex, portMAX_DELAY);
|
||||||
|
mReceiveQueue.push(message_s(topic, payload, len, index, total));
|
||||||
|
xSemaphoreGive(mutex);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void handleMessage(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total) {
|
||||||
DPRINT(DBG_INFO, mqttStr[MQTT_STR_GOT_TOPIC]);
|
DPRINT(DBG_INFO, mqttStr[MQTT_STR_GOT_TOPIC]);
|
||||||
DBGPRINTLN(String(topic));
|
DBGPRINTLN(String(topic));
|
||||||
if(NULL == mSubscriptionCb)
|
if(NULL == mSubscriptionCb)
|
||||||
|
@ -613,12 +645,77 @@ class PubMqtt {
|
||||||
private:
|
private:
|
||||||
enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE};
|
enum {MQTT_STATUS_OFFLINE = 0, MQTT_STATUS_PARTIAL, MQTT_STATUS_ONLINE};
|
||||||
|
|
||||||
|
struct message_s
|
||||||
|
{
|
||||||
|
char *topic;
|
||||||
|
uint8_t *payload;
|
||||||
|
size_t len;
|
||||||
|
size_t index;
|
||||||
|
size_t total;
|
||||||
|
|
||||||
|
message_s()
|
||||||
|
: topic { nullptr }
|
||||||
|
, payload { nullptr }
|
||||||
|
, len { 0 }
|
||||||
|
, index { 0 }
|
||||||
|
, total { 0 }
|
||||||
|
{}
|
||||||
|
|
||||||
|
message_s(const char* topic, const uint8_t* payload, size_t len, size_t index, size_t total)
|
||||||
|
{
|
||||||
|
uint8_t topic_len = strlen(topic) + 1;
|
||||||
|
this->topic = new char[topic_len];
|
||||||
|
this->payload = new uint8_t[len];
|
||||||
|
|
||||||
|
memcpy(this->topic, topic, topic_len);
|
||||||
|
memcpy(this->payload, payload, len);
|
||||||
|
this->len = len;
|
||||||
|
this->index = index;
|
||||||
|
this->total = total;
|
||||||
|
}
|
||||||
|
|
||||||
|
message_s(const message_s &) = delete;
|
||||||
|
|
||||||
|
message_s(message_s && other) : message_s {}
|
||||||
|
{
|
||||||
|
this->swap( other );
|
||||||
|
}
|
||||||
|
|
||||||
|
~message_s()
|
||||||
|
{
|
||||||
|
delete[] this->topic;
|
||||||
|
delete[] this->payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
message_s &operator = (const message_s &) = delete;
|
||||||
|
|
||||||
|
message_s &operator = (message_s &&other)
|
||||||
|
{
|
||||||
|
this->swap(other);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
void swap(message_s &other)
|
||||||
|
{
|
||||||
|
std::swap(this->topic, other.topic);
|
||||||
|
std::swap(this->payload, other.payload);
|
||||||
|
std::swap(this->len, other.len);
|
||||||
|
std::swap(this->index, other.index);
|
||||||
|
std::swap(this->total, other.total);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
espMqttClient mClient;
|
espMqttClient mClient;
|
||||||
cfgMqtt_t *mCfgMqtt = nullptr;
|
cfgMqtt_t *mCfgMqtt = nullptr;
|
||||||
IApp *mApp;
|
IApp *mApp;
|
||||||
#if defined(ESP8266)
|
#if defined(ESP8266)
|
||||||
WiFiEventHandler mHWifiCon, mHWifiDiscon;
|
WiFiEventHandler mHWifiCon, mHWifiDiscon;
|
||||||
|
volatile bool mutex;
|
||||||
|
#else
|
||||||
|
SemaphoreHandle_t mutex;
|
||||||
|
StaticSemaphore_t mutexBuffer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
HMSYSTEM *mSys = nullptr;
|
HMSYSTEM *mSys = nullptr;
|
||||||
|
@ -634,6 +731,8 @@ class PubMqtt {
|
||||||
std::array<uint32_t, MAX_NUM_INVERTERS> mIvLastRTRpub;
|
std::array<uint32_t, MAX_NUM_INVERTERS> mIvLastRTRpub;
|
||||||
uint16_t mIntervalTimeout = 0;
|
uint16_t mIntervalTimeout = 0;
|
||||||
|
|
||||||
|
std::queue<message_s> mReceiveQueue;
|
||||||
|
|
||||||
// last will topic and payload must be available through lifetime of 'espMqttClient'
|
// last will topic and payload must be available through lifetime of 'espMqttClient'
|
||||||
std::array<char, (MQTT_TOPIC_LEN + 5)> mLwtTopic;
|
std::array<char, (MQTT_TOPIC_LEN + 5)> mLwtTopic;
|
||||||
const char *mDevName = nullptr, *mVersion = nullptr;
|
const char *mDevName = nullptr, *mVersion = nullptr;
|
||||||
|
|
|
@ -197,13 +197,20 @@ class PubMqttIvData {
|
||||||
if (!mCfg->json) {
|
if (!mCfg->json) {
|
||||||
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]);
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/ch%d/%s", mIv->config->name, rec->assign[mPos].ch, fields[rec->assign[mPos].fieldId]);
|
||||||
snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec)));
|
snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec)));
|
||||||
|
} else {
|
||||||
|
if (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) {
|
||||||
|
uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0;
|
||||||
|
snprintf(mSubTopic.data(), mSubTopic.size(), "%s/%s", mIv->config->name, fields[rec->assign[mPos].fieldId]);
|
||||||
|
snprintf(mVal.data(), mVal.size(), "%g", ah::round3(mIv->getValue(mPos, rec)));
|
||||||
|
mPublish(mSubTopic.data(), mVal.data(), retained, qos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((InverterDevInform_All == mCmd) || (InverterDevInform_Simple == mCmd) || !mCfg->json) {
|
if ((InverterDevInform_All == mCmd) || (InverterDevInform_Simple == mCmd) || !mCfg->json)
|
||||||
|
{
|
||||||
uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0;
|
uint8_t qos = (FLD_ACT_ACTIVE_PWR_LIMIT == rec->assign[mPos].fieldId) ? QOS_2 : QOS_0;
|
||||||
if((FLD_EVT != rec->assign[mPos].fieldId)
|
if((FLD_EVT != rec->assign[mPos].fieldId) && (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId))
|
||||||
&& (FLD_LAST_ALARM_CODE != rec->assign[mPos].fieldId))
|
|
||||||
mPublish(mSubTopic.data(), mVal.data(), retained, qos);
|
mPublish(mSubTopic.data(), mVal.data(), retained, qos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,11 @@ class RestApi {
|
||||||
mHeapFrag = ESP.getHeapFragmentation();
|
mHeapFrag = ESP.getHeapFragmentation();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP32)
|
||||||
AsyncJsonResponse* response = new AsyncJsonResponse(false, 8000);
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, 8000);
|
||||||
|
#else
|
||||||
|
AsyncJsonResponse* response = new AsyncJsonResponse(false, 6000);
|
||||||
|
#endif
|
||||||
JsonObject root = response->getRoot();
|
JsonObject root = response->getRoot();
|
||||||
|
|
||||||
String path = request->url().substring(5);
|
String path = request->url().substring(5);
|
||||||
|
@ -692,11 +696,23 @@ class RestApi {
|
||||||
obj[F("last_id")] = iv->getChannelFieldValue(CH0, FLD_EVT, rec);
|
obj[F("last_id")] = iv->getChannelFieldValue(CH0, FLD_EVT, rec);
|
||||||
|
|
||||||
JsonArray alarm = obj.createNestedArray(F("alarm"));
|
JsonArray alarm = obj.createNestedArray(F("alarm"));
|
||||||
|
|
||||||
|
// find oldest alarm
|
||||||
|
uint8_t offset = 0;
|
||||||
|
uint32_t oldestStart = 0xffffffff;
|
||||||
for(uint8_t i = 0; i < 10; i++) {
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
alarm[i][F("code")] = iv->lastAlarm[i].code;
|
if((iv->lastAlarm[i].start != 0) && (iv->lastAlarm[i].start < oldestStart)) {
|
||||||
alarm[i][F("str")] = iv->getAlarmStr(iv->lastAlarm[i].code);
|
offset = i;
|
||||||
alarm[i][F("start")] = iv->lastAlarm[i].start;
|
oldestStart = iv->lastAlarm[i].start;
|
||||||
alarm[i][F("end")] = iv->lastAlarm[i].end;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < 10; i++) {
|
||||||
|
uint8_t pos = (i + offset) % 10;
|
||||||
|
alarm[pos][F("code")] = iv->lastAlarm[pos].code;
|
||||||
|
alarm[pos][F("str")] = iv->getAlarmStr(iv->lastAlarm[pos].code);
|
||||||
|
alarm[pos][F("start")] = iv->lastAlarm[pos].start;
|
||||||
|
alarm[pos][F("end")] = iv->lastAlarm[pos].end;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1086,7 +1102,19 @@ class RestApi {
|
||||||
mApp->saveSettings(true);
|
mApp->saveSettings(true);
|
||||||
}
|
}
|
||||||
else if(F("save_iv") == jsonIn[F("cmd")]) {
|
else if(F("save_iv") == jsonIn[F("cmd")]) {
|
||||||
Inverter<> *iv = mSys->getInverterByPos(jsonIn[F("id")], false);
|
Inverter<> *iv;
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
|
iv = mSys->getInverterByPos(jsonIn[F("id")], true);
|
||||||
|
if(nullptr != iv) {
|
||||||
|
if((i != jsonIn[F("id")]) && (iv->config->serial.u64 == jsonIn[F("ser")])) {
|
||||||
|
jsonOut[F("error")] = F("ERR_DUPLICATE_INVERTER");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
iv = mSys->getInverterByPos(jsonIn[F("id")], false);
|
||||||
iv->config->enabled = jsonIn[F("en")];
|
iv->config->enabled = jsonIn[F("en")];
|
||||||
iv->config->serial.u64 = jsonIn[F("ser")];
|
iv->config->serial.u64 = jsonIn[F("ser")];
|
||||||
snprintf(iv->config->name, MAX_NAME_LENGTH, "%s", jsonIn[F("name")].as<const char*>());
|
snprintf(iv->config->name, MAX_NAME_LENGTH, "%s", jsonIn[F("name")].as<const char*>());
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
{"0x0908": "France_VFR2014"},
|
{"0x0908": "France_VFR2014"},
|
||||||
{"0x0a00": "DE NF_EN_50549-1:2019"},
|
{"0x0a00": "DE NF_EN_50549-1:2019"},
|
||||||
{"0x0c00": "AT_TOR_Erzeuger_default"},
|
{"0x0c00": "AT_TOR_Erzeuger_default"},
|
||||||
|
{"0x0c03": "AT_TOR_Erzeuger_cosphi=1"},
|
||||||
{"0x0c04": "AT_TOR_Erzeuger_default"},
|
{"0x0c04": "AT_TOR_Erzeuger_default"},
|
||||||
{"0x0d00": "FR_VFR2019"},
|
{"0x0d00": "FR_VFR2019"},
|
||||||
{"0x0d04": "NF_EN_50549-1:2019"},
|
{"0x0d04": "NF_EN_50549-1:2019"},
|
||||||
|
|
|
@ -116,6 +116,8 @@
|
||||||
var p = div(["none"]);
|
var p = div(["none"]);
|
||||||
var total = 0;
|
var total = 0;
|
||||||
var count = 0;
|
var count = 0;
|
||||||
|
var mobile = window.screen.width < 470;
|
||||||
|
|
||||||
for(var i of obj) {
|
for(var i of obj) {
|
||||||
var icon = iconSuccess;
|
var icon = iconSuccess;
|
||||||
var cl = "icon-success";
|
var cl = "icon-success";
|
||||||
|
@ -131,7 +133,8 @@
|
||||||
} else if(0 == i["ts_last_success"]) {
|
} else if(0 == i["ts_last_success"]) {
|
||||||
avail = "{#AVAIL_NO_DATA}";
|
avail = "{#AVAIL_NO_DATA}";
|
||||||
} else {
|
} else {
|
||||||
avail = "{#AVAIL} ";
|
if (!mobile)
|
||||||
|
avail = "{#AVAIL} ";
|
||||||
if(false == i["is_producing"])
|
if(false == i["is_producing"])
|
||||||
avail += "{#NOT_PRODUCING}";
|
avail += "{#NOT_PRODUCING}";
|
||||||
else {
|
else {
|
||||||
|
@ -142,11 +145,16 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var text;
|
||||||
|
if (mobile)
|
||||||
|
text = "#";
|
||||||
|
else
|
||||||
|
text = "{#INVERTER} #";
|
||||||
p.append(
|
p.append(
|
||||||
svg(icon, 30, 30, "icon " + cl),
|
svg(icon, 30, 30, "icon " + cl),
|
||||||
span("{#INVERTER} #" + i["id"] + ": " + i["name"] + " {#IS} " + avail),
|
span(text + i["id"] + ": " + i["name"] + " {#IS} " + avail),
|
||||||
br()
|
br()
|
||||||
);
|
);
|
||||||
|
|
||||||
if(false == i["is_avail"]) {
|
if(false == i["is_avail"]) {
|
||||||
if(i["ts_last_success"] > 0) {
|
if(i["ts_last_success"] > 0) {
|
||||||
|
|
|
@ -873,11 +873,16 @@
|
||||||
ser.dispatchEvent(new Event('change'));
|
ser.dispatchEvent(new Event('change'));
|
||||||
|
|
||||||
function ivSave() {
|
function ivSave() {
|
||||||
var o = new Object();
|
var o = {}
|
||||||
o.cmd = "save_iv"
|
o.cmd = "save_iv"
|
||||||
o.token = "*"
|
o.token = "*"
|
||||||
o.id = obj.id
|
o.id = obj.id
|
||||||
o.ser = parseInt(document.getElementsByName("ser")[0].value, 16);
|
|
||||||
|
let sn = document.getElementsByName("ser")[0].value
|
||||||
|
if(sn[0] == 'A')
|
||||||
|
sn = convHerf(sn)
|
||||||
|
o.ser = parseInt(sn, 16)
|
||||||
|
|
||||||
o.name = document.getElementsByName("name")[0].value;
|
o.name = document.getElementsByName("name")[0].value;
|
||||||
o.en = document.getElementsByName("enable")[0].checked;
|
o.en = document.getElementsByName("enable")[0].checked;
|
||||||
o.ch = [];
|
o.ch = [];
|
||||||
|
@ -897,6 +902,30 @@
|
||||||
getAjax("/api/setup", cb, "POST", JSON.stringify(o));
|
getAjax("/api/setup", cb, "POST", JSON.stringify(o));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convHerf(sn) {
|
||||||
|
let sn_int = 0n;
|
||||||
|
const CHARS = "0123456789ABCDEFGHJKLMNPRSTUVWXY";
|
||||||
|
|
||||||
|
for (let i = 0; i < 9; ++i) {
|
||||||
|
const pos = CHARS.indexOf(sn[i])
|
||||||
|
const shift = 42 - 5 * i - (i <= 2 ? 0 : 2)
|
||||||
|
sn_int |= BigInt(pos) << BigInt(shift)
|
||||||
|
}
|
||||||
|
|
||||||
|
let first4Hex = (sn_int >> 32n) & 0xFFFFn
|
||||||
|
|
||||||
|
if (first4Hex === 0x2841n)
|
||||||
|
first4Hex = 0x1121n
|
||||||
|
else if (first4Hex === 0x2821n)
|
||||||
|
first4Hex = 0x1141n
|
||||||
|
else if (first4Hex === 0x2801n)
|
||||||
|
first4Hex = 0x1161n
|
||||||
|
|
||||||
|
sn_int = (sn_int & ~(0xFFFFn << 32n)) | (first4Hex << 32n);
|
||||||
|
|
||||||
|
return sn_int.toString(16)
|
||||||
|
}
|
||||||
|
|
||||||
function cb(obj2) {
|
function cb(obj2) {
|
||||||
var e = document.getElementById("res");
|
var e = document.getElementById("res");
|
||||||
if(!obj2.success)
|
if(!obj2.success)
|
||||||
|
@ -918,6 +947,7 @@
|
||||||
function del() {
|
function del() {
|
||||||
var o = new Object();
|
var o = new Object();
|
||||||
o.cmd = "save_iv";
|
o.cmd = "save_iv";
|
||||||
|
o.token = "*"
|
||||||
o.id = obj.id;
|
o.id = obj.id;
|
||||||
o.ser = 0;
|
o.ser = 0;
|
||||||
o.name = "";
|
o.name = "";
|
||||||
|
|
|
@ -276,7 +276,7 @@
|
||||||
ml("div", {class: "col mt-3"}, String(a.str)),
|
ml("div", {class: "col mt-3"}, String(a.str)),
|
||||||
ml("div", {class: "col mt-3"}, String(a.code)),
|
ml("div", {class: "col mt-3"}, String(a.code)),
|
||||||
ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date((a.start + offs) * 1000)))),
|
ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date((a.start + offs) * 1000)))),
|
||||||
ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date((a.end + offs) * 1000))))
|
ml("div", {class: "col mt-3"}, (a.end == 0) ? "-" : String(toIsoTimeStr(new Date((a.end + offs) * 1000))))
|
||||||
])
|
])
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue