Skip to content

Commit eb1c2db

Browse files
committed
Merge remote-tracking branch 'tbnobody/OpenDTU/master' into development
2 parents 0cb42a6 + a0f9d22 commit eb1c2db

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+1060
-465
lines changed

include/Configuration.h

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: GPL-2.0-or-later
22
#pragma once
33

4-
#include <Arduino.h>
4+
#include <cstdint>
55

66
#define CONFIG_FILENAME "/config.json"
77
#define CONFIG_VERSION 0x00011900 // 0.1.24 // make sure to clean all after change
@@ -54,6 +54,9 @@ struct INVERTER_CONFIG_T {
5454
bool Poll_Enable_Night;
5555
bool Command_Enable;
5656
bool Command_Enable_Night;
57+
uint8_t ReachableThreshold;
58+
bool ZeroRuntimeDataIfUnrechable;
59+
bool ZeroYieldDayOnMidnight;
5760
CHANNEL_CONFIG_T channel[INV_MAX_CHAN_COUNT];
5861
};
5962

@@ -72,18 +75,18 @@ struct POWERMETER_HTTP_PHASE_CONFIG_T {
7275

7376
struct CONFIG_T {
7477
uint32_t Cfg_Version;
75-
uint Cfg_SaveCount;
78+
uint32_t Cfg_SaveCount;
7679

7780
char WiFi_Ssid[WIFI_MAX_SSID_STRLEN + 1];
7881
char WiFi_Password[WIFI_MAX_PASSWORD_STRLEN + 1];
79-
byte WiFi_Ip[4];
80-
byte WiFi_Netmask[4];
81-
byte WiFi_Gateway[4];
82-
byte WiFi_Dns1[4];
83-
byte WiFi_Dns2[4];
82+
uint8_t WiFi_Ip[4];
83+
uint8_t WiFi_Netmask[4];
84+
uint8_t WiFi_Gateway[4];
85+
uint8_t WiFi_Dns1[4];
86+
uint8_t WiFi_Dns2[4];
8487
bool WiFi_Dhcp;
8588
char WiFi_Hostname[WIFI_MAX_HOSTNAME_STRLEN + 1];
86-
uint WiFi_ApTimeout;
89+
uint32_t WiFi_ApTimeout;
8790

8891
char Ntp_Server[NTP_MAX_SERVER_STRLEN + 1];
8992
char Ntp_Timezone[NTP_MAX_TIMEZONE_STRLEN + 1];
@@ -95,7 +98,7 @@ struct CONFIG_T {
9598
bool Mqtt_Enabled;
9699
char Mqtt_Hostname[MQTT_MAX_HOSTNAME_STRLEN + 1];
97100
bool Mqtt_VerboseLogging;
98-
uint Mqtt_Port;
101+
uint32_t Mqtt_Port;
99102
char Mqtt_Username[MQTT_MAX_USERNAME_STRLEN + 1];
100103
char Mqtt_Password[MQTT_MAX_PASSWORD_STRLEN + 1];
101104
char Mqtt_Topic[MQTT_MAX_TOPIC_STRLEN + 1];
@@ -104,6 +107,7 @@ struct CONFIG_T {
104107
char Mqtt_LwtValue_Online[MQTT_MAX_LWTVALUE_STRLEN + 1];
105108
char Mqtt_LwtValue_Offline[MQTT_MAX_LWTVALUE_STRLEN + 1];
106109
uint32_t Mqtt_PublishInterval;
110+
bool Mqtt_CleanSession;
107111

108112
INVERTER_CONFIG_T Inverter[INV_MAX_COUNT];
109113

include/Datastore.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,16 @@ class DatastoreClass {
3131
float getTotalDcIrradiation();
3232

3333
// Amount of relevant digits for yield total
34-
unsigned int getTotalAcYieldTotalDigits();
34+
uint32_t getTotalAcYieldTotalDigits();
3535

3636
// Amount of relevant digits for yield total
37-
unsigned int getTotalAcYieldDayDigits();
37+
uint32_t getTotalAcYieldDayDigits();
3838

3939
// Amount of relevant digits for AC power
40-
unsigned int getTotalAcPowerDigits();
40+
uint32_t getTotalAcPowerDigits();
4141

4242
// Amount of relevant digits for DC power
43-
unsigned int getTotalDcPowerDigits();
43+
uint32_t getTotalDcPowerDigits();
4444

4545
// True, if at least one inverter is reachable
4646
bool getIsAtLeastOneReachable();
@@ -68,10 +68,10 @@ class DatastoreClass {
6868
float _totalDcPowerIrradiation = 0;
6969
float _totalDcIrradiationInstalled = 0;
7070
float _totalDcIrradiation = 0;
71-
unsigned int _totalAcYieldTotalDigits = 0;
72-
unsigned int _totalAcYieldDayDigits = 0;
73-
unsigned int _totalAcPowerDigits = 0;
74-
unsigned int _totalDcPowerDigits = 0;
71+
uint32_t _totalAcYieldTotalDigits = 0;
72+
uint32_t _totalAcYieldDayDigits = 0;
73+
uint32_t _totalAcPowerDigits = 0;
74+
uint32_t _totalDcPowerDigits = 0;
7575
bool _isAtLeastOneReachable = false;
7676
bool _isAtLeastOneProducing = false;
7777
bool _isAllEnabledProducing = false;

include/MqttHandleInverter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "Configuration.h"
55
#include <Hoymiles.h>
6+
#include <TimeoutHelper.h>
67
#include <espMqttClient.h>
78

89
class MqttHandleInverterClass {
@@ -19,6 +20,8 @@ class MqttHandleInverterClass {
1920
uint32_t _lastPublishStats[INV_MAX_COUNT];
2021
uint32_t _lastPublish;
2122

23+
TimeoutHelper _statsTimeout;
24+
2225
FieldId_t _publishFields[14] = {
2326
FLD_UDC,
2427
FLD_IDC,

include/NetworkSettings.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,10 @@ class NetworkSettingsClass {
6363
void NetworkEvent(WiFiEvent_t event);
6464
bool adminEnabled = true;
6565
bool forceDisconnection = false;
66-
int adminTimeoutCounter = 0;
67-
int adminTimeoutCounterMax = 0;
68-
int connectTimeoutTimer = 0;
69-
int connectRedoTimer = 0;
66+
uint32_t adminTimeoutCounter = 0;
67+
uint32_t adminTimeoutCounterMax = 0;
68+
uint32_t connectTimeoutTimer = 0;
69+
uint32_t connectRedoTimer = 0;
7070
uint32_t lastTimerCall = 0;
7171
const byte DNS_PORT = 53;
7272
IPAddress apIp;

include/SunPosition.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ class SunPositionClass {
2222
SunSet _sun;
2323
bool _isDayPeriod = true;
2424
bool _isSunsetAvailable = true;
25-
uint _sunriseMinutes = 0;
26-
uint _sunsetMinutes = 0;
25+
uint32_t _sunriseMinutes = 0;
26+
uint32_t _sunsetMinutes = 0;
2727

2828
uint32_t _lastUpdate = 0;
2929
bool _isValidInfo = false;

include/WebApi.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include "WebApi_dtu.h"
99
#include "WebApi_eventlog.h"
1010
#include "WebApi_firmware.h"
11+
#include "WebApi_gridprofile.h"
1112
#include "WebApi_inverter.h"
1213
#include "WebApi_limit.h"
1314
#include "WebApi_maintenance.h"
@@ -52,6 +53,7 @@ class WebApiClass {
5253
WebApiDtuClass _webApiDtu;
5354
WebApiEventlogClass _webApiEventlog;
5455
WebApiFirmwareClass _webApiFirmware;
56+
WebApiGridProfileClass _webApiGridprofile;
5557
WebApiInverterClass _webApiInverter;
5658
WebApiLimitClass _webApiLimit;
5759
WebApiMaintenanceClass _webApiMaintenance;

include/WebApi_gridprofile.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
#pragma once
3+
4+
#include <ESPAsyncWebServer.h>
5+
6+
class WebApiGridProfileClass {
7+
public:
8+
void init(AsyncWebServer* server);
9+
void loop();
10+
11+
private:
12+
void onGridProfileStatus(AsyncWebServerRequest* request);
13+
14+
AsyncWebServer* _server;
15+
};

include/WebApi_ws_live.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,6 @@ class WebApiWsLiveClass {
2525
uint32_t _lastInvUpdateCheck = 0;
2626
uint32_t _lastWsCleanup = 0;
2727
uint32_t _newestInverterTimestamp = 0;
28+
29+
std::mutex _mutex;
2830
};

include/defaults.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
#define MQTT_LWT_ONLINE "online"
7575
#define MQTT_LWT_OFFLINE "offline"
7676
#define MQTT_PUBLISH_INTERVAL 5U
77+
#define MQTT_CLEAN_SESSION true
7778

7879
#define DTU_SERIAL 0x99978563412U
7980
#define DTU_POLL_INTERVAL 5U
@@ -95,6 +96,8 @@
9596
#define DISPLAY_CONTRAST 60U
9697
#define DISPLAY_LANGUAGE 0U
9798

99+
#define REACHABLE_THRESHOLD 2U
100+
98101
#define VEDIRECT_ENABLED false
99102
#define VEDIRECT_VERBOSE_LOGGING false
100103
#define VEDIRECT_UPDATESONLY true

lib/Hoymiles/src/Hoymiles.cpp

Lines changed: 67 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* Copyright (C) 2022 Thomas Basler and others
44
*/
55
#include "Hoymiles.h"
6+
#include "Utils.h"
67
#include "inverters/HMS_1CH.h"
78
#include "inverters/HMS_2CH.h"
89
#include "inverters/HMS_4CH.h"
@@ -12,18 +13,10 @@
1213
#include "inverters/HM_4CH.h"
1314
#include <Arduino.h>
1415

15-
#define HOY_SEMAPHORE_TAKE() \
16-
do { \
17-
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
18-
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)
19-
2016
HoymilesClass Hoymiles;
2117

2218
void HoymilesClass::init()
2319
{
24-
_xSemaphore = xSemaphoreCreateMutex();
25-
HOY_SEMAPHORE_GIVE(); // release before first use
26-
2720
_pollInterval = 0;
2821
_radioNrf.reset(new HoymilesRadio_NRF());
2922
_radioCmt.reset(new HoymilesRadio_CMT());
@@ -41,7 +34,7 @@ void HoymilesClass::initCMT(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8
4134

4235
void HoymilesClass::loop()
4336
{
44-
HOY_SEMAPHORE_TAKE();
37+
std::lock_guard<std::mutex> lock(_mutex);
4538
_radioNrf->loop();
4639
_radioCmt->loop();
4740

@@ -57,67 +50,90 @@ void HoymilesClass::loop()
5750
}
5851

5952
if (iv != nullptr && iv->getRadio()->isInitialized() && iv->getRadio()->isQueueEmpty()) {
60-
_messageOutput->print("Fetch inverter: ");
61-
_messageOutput->println(iv->serial(), HEX);
6253

63-
if (!iv->isReachable()) {
64-
iv->sendChangeChannelRequest();
65-
}
54+
if (iv->getEnablePolling() || iv->getEnableCommands()) {
55+
_messageOutput->print("Fetch inverter: ");
56+
_messageOutput->println(iv->serial(), HEX);
6657

67-
iv->sendStatsRequest();
58+
if (!iv->isReachable()) {
59+
iv->sendChangeChannelRequest();
60+
}
6861

69-
// Fetch event log
70-
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
71-
iv->sendAlarmLogRequest(force);
62+
iv->sendStatsRequest();
7263

73-
// Fetch limit
74-
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
75-
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
76-
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
77-
_messageOutput->println("Request SystemConfigPara");
78-
iv->sendSystemConfigParaRequest();
79-
}
64+
// Fetch event log
65+
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
66+
iv->sendAlarmLogRequest(force);
8067

81-
// Set limit if required
82-
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
83-
_messageOutput->println("Resend ActivePowerControl");
84-
iv->resendActivePowerControlRequest();
85-
}
68+
// Fetch limit
69+
if (((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
70+
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
71+
_messageOutput->println("Request SystemConfigPara");
72+
iv->sendSystemConfigParaRequest();
73+
}
8674

87-
// Set power status if required
88-
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
89-
_messageOutput->println("Resend PowerCommand");
90-
iv->resendPowerControlRequest();
91-
}
75+
// Set limit if required
76+
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
77+
_messageOutput->println("Resend ActivePowerControl");
78+
iv->resendActivePowerControlRequest();
79+
}
9280

93-
// Fetch dev info (but first fetch stats)
94-
if (iv->Statistics()->getLastUpdate() > 0) {
95-
bool invalidDevInfo = !iv->DevInfo()->containsValidData()
96-
&& iv->DevInfo()->getLastUpdateAll() > 0
97-
&& iv->DevInfo()->getLastUpdateSimple() > 0;
81+
// Set power status if required
82+
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
83+
_messageOutput->println("Resend PowerCommand");
84+
iv->resendPowerControlRequest();
85+
}
9886

99-
if (invalidDevInfo) {
100-
_messageOutput->println("DevInfo: No Valid Data");
87+
// Fetch dev info (but first fetch stats)
88+
if (iv->Statistics()->getLastUpdate() > 0) {
89+
bool invalidDevInfo = !iv->DevInfo()->containsValidData()
90+
&& iv->DevInfo()->getLastUpdateAll() > 0
91+
&& iv->DevInfo()->getLastUpdateSimple() > 0;
92+
93+
if (invalidDevInfo) {
94+
_messageOutput->println("DevInfo: No Valid Data");
95+
}
96+
97+
if ((iv->DevInfo()->getLastUpdateAll() == 0)
98+
|| (iv->DevInfo()->getLastUpdateSimple() == 0)
99+
|| invalidDevInfo) {
100+
_messageOutput->println("Request device info");
101+
iv->sendDevInfoRequest();
102+
}
101103
}
102104

103-
if ((iv->DevInfo()->getLastUpdateAll() == 0)
104-
|| (iv->DevInfo()->getLastUpdateSimple() == 0)
105-
|| invalidDevInfo) {
106-
_messageOutput->println("Request device info");
107-
iv->sendDevInfoRequest();
105+
// Fetch grid profile
106+
if (iv->Statistics()->getLastUpdate() > 0 && iv->GridProfile()->getLastUpdate() == 0) {
107+
iv->sendGridOnProFileParaRequest();
108108
}
109+
110+
_lastPoll = millis();
109111
}
110112

111113
if (++inverterPos >= getNumInverters()) {
112114
inverterPos = 0;
113115
}
116+
}
114117

115-
_lastPoll = millis();
118+
// Perform housekeeping of all inverters on day change
119+
int8_t currentWeekDay = Utils::getWeekDay();
120+
static int8_t lastWeekDay = -1;
121+
if (lastWeekDay == -1) {
122+
lastWeekDay = currentWeekDay;
123+
} else {
124+
if (currentWeekDay != lastWeekDay) {
125+
126+
for (auto& inv : _inverters) {
127+
if (inv->getZeroYieldDayOnMidnight()) {
128+
inv->Statistics()->zeroDailyData();
129+
}
130+
}
131+
132+
lastWeekDay = currentWeekDay;
133+
}
116134
}
117135
}
118136
}
119-
120-
HOY_SEMAPHORE_GIVE();
121137
}
122138

123139
std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, uint64_t serial)
@@ -195,9 +211,8 @@ void HoymilesClass::removeInverterBySerial(uint64_t serial)
195211
{
196212
for (uint8_t i = 0; i < _inverters.size(); i++) {
197213
if (_inverters[i]->serial() == serial) {
198-
HOY_SEMAPHORE_TAKE();
214+
std::lock_guard<std::mutex> lock(_mutex);
199215
_inverters.erase(_inverters.begin() + i);
200-
HOY_SEMAPHORE_GIVE();
201216
return;
202217
}
203218
}

0 commit comments

Comments
 (0)