Skip to content

Commit

Permalink
Merge branch 'development'
Browse files Browse the repository at this point in the history
  • Loading branch information
helgeerbe committed Sep 18, 2023
2 parents 4e489fe + 9d6b459 commit 4d0f958
Show file tree
Hide file tree
Showing 67 changed files with 1,164 additions and 618 deletions.
22 changes: 13 additions & 9 deletions include/Configuration.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include <Arduino.h>
#include <cstdint>

#define CONFIG_FILENAME "/config.json"
#define CONFIG_VERSION 0x00011900 // 0.1.24 // make sure to clean all after change
Expand Down Expand Up @@ -54,6 +54,9 @@ struct INVERTER_CONFIG_T {
bool Poll_Enable_Night;
bool Command_Enable;
bool Command_Enable_Night;
uint8_t ReachableThreshold;
bool ZeroRuntimeDataIfUnrechable;
bool ZeroYieldDayOnMidnight;
CHANNEL_CONFIG_T channel[INV_MAX_CHAN_COUNT];
};

Expand All @@ -72,18 +75,18 @@ struct POWERMETER_HTTP_PHASE_CONFIG_T {

struct CONFIG_T {
uint32_t Cfg_Version;
uint Cfg_SaveCount;
uint32_t Cfg_SaveCount;

char WiFi_Ssid[WIFI_MAX_SSID_STRLEN + 1];
char WiFi_Password[WIFI_MAX_PASSWORD_STRLEN + 1];
byte WiFi_Ip[4];
byte WiFi_Netmask[4];
byte WiFi_Gateway[4];
byte WiFi_Dns1[4];
byte WiFi_Dns2[4];
uint8_t WiFi_Ip[4];
uint8_t WiFi_Netmask[4];
uint8_t WiFi_Gateway[4];
uint8_t WiFi_Dns1[4];
uint8_t WiFi_Dns2[4];
bool WiFi_Dhcp;
char WiFi_Hostname[WIFI_MAX_HOSTNAME_STRLEN + 1];
uint WiFi_ApTimeout;
uint32_t WiFi_ApTimeout;

char Ntp_Server[NTP_MAX_SERVER_STRLEN + 1];
char Ntp_Timezone[NTP_MAX_TIMEZONE_STRLEN + 1];
Expand All @@ -95,7 +98,7 @@ struct CONFIG_T {
bool Mqtt_Enabled;
char Mqtt_Hostname[MQTT_MAX_HOSTNAME_STRLEN + 1];
bool Mqtt_VerboseLogging;
uint Mqtt_Port;
uint32_t Mqtt_Port;
char Mqtt_Username[MQTT_MAX_USERNAME_STRLEN + 1];
char Mqtt_Password[MQTT_MAX_PASSWORD_STRLEN + 1];
char Mqtt_Topic[MQTT_MAX_TOPIC_STRLEN + 1];
Expand All @@ -104,6 +107,7 @@ struct CONFIG_T {
char Mqtt_LwtValue_Online[MQTT_MAX_LWTVALUE_STRLEN + 1];
char Mqtt_LwtValue_Offline[MQTT_MAX_LWTVALUE_STRLEN + 1];
uint32_t Mqtt_PublishInterval;
bool Mqtt_CleanSession;

INVERTER_CONFIG_T Inverter[INV_MAX_COUNT];

Expand Down
16 changes: 8 additions & 8 deletions include/Datastore.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,16 @@ class DatastoreClass {
float getTotalDcIrradiation();

// Amount of relevant digits for yield total
unsigned int getTotalAcYieldTotalDigits();
uint32_t getTotalAcYieldTotalDigits();

// Amount of relevant digits for yield total
unsigned int getTotalAcYieldDayDigits();
uint32_t getTotalAcYieldDayDigits();

// Amount of relevant digits for AC power
unsigned int getTotalAcPowerDigits();
uint32_t getTotalAcPowerDigits();

// Amount of relevant digits for DC power
unsigned int getTotalDcPowerDigits();
uint32_t getTotalDcPowerDigits();

// True, if at least one inverter is reachable
bool getIsAtLeastOneReachable();
Expand Down Expand Up @@ -68,10 +68,10 @@ class DatastoreClass {
float _totalDcPowerIrradiation = 0;
float _totalDcIrradiationInstalled = 0;
float _totalDcIrradiation = 0;
unsigned int _totalAcYieldTotalDigits = 0;
unsigned int _totalAcYieldDayDigits = 0;
unsigned int _totalAcPowerDigits = 0;
unsigned int _totalDcPowerDigits = 0;
uint32_t _totalAcYieldTotalDigits = 0;
uint32_t _totalAcYieldDayDigits = 0;
uint32_t _totalAcPowerDigits = 0;
uint32_t _totalDcPowerDigits = 0;
bool _isAtLeastOneReachable = false;
bool _isAtLeastOneProducing = false;
bool _isAllEnabledProducing = false;
Expand Down
1 change: 1 addition & 0 deletions include/MqttHandleInverter.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "Configuration.h"
#include <Hoymiles.h>
#include <TimeoutHelper.h>
#include <espMqttClient.h>

class MqttHandleInverterClass {
Expand Down
8 changes: 4 additions & 4 deletions include/NetworkSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ class NetworkSettingsClass {
void NetworkEvent(WiFiEvent_t event);
bool adminEnabled = true;
bool forceDisconnection = false;
int adminTimeoutCounter = 0;
int adminTimeoutCounterMax = 0;
int connectTimeoutTimer = 0;
int connectRedoTimer = 0;
uint32_t adminTimeoutCounter = 0;
uint32_t adminTimeoutCounterMax = 0;
uint32_t connectTimeoutTimer = 0;
uint32_t connectRedoTimer = 0;
uint32_t lastTimerCall = 0;
const byte DNS_PORT = 53;
IPAddress apIp;
Expand Down
4 changes: 2 additions & 2 deletions include/SunPosition.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ class SunPositionClass {
SunSet _sun;
bool _isDayPeriod = true;
bool _isSunsetAvailable = true;
uint _sunriseMinutes = 0;
uint _sunsetMinutes = 0;
uint32_t _sunriseMinutes = 0;
uint32_t _sunsetMinutes = 0;

uint32_t _lastUpdate = 0;
bool _isValidInfo = false;
Expand Down
2 changes: 2 additions & 0 deletions include/WebApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "WebApi_dtu.h"
#include "WebApi_eventlog.h"
#include "WebApi_firmware.h"
#include "WebApi_gridprofile.h"
#include "WebApi_inverter.h"
#include "WebApi_limit.h"
#include "WebApi_maintenance.h"
Expand Down Expand Up @@ -52,6 +53,7 @@ class WebApiClass {
WebApiDtuClass _webApiDtu;
WebApiEventlogClass _webApiEventlog;
WebApiFirmwareClass _webApiFirmware;
WebApiGridProfileClass _webApiGridprofile;
WebApiInverterClass _webApiInverter;
WebApiLimitClass _webApiLimit;
WebApiMaintenanceClass _webApiMaintenance;
Expand Down
15 changes: 15 additions & 0 deletions include/WebApi_gridprofile.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once

#include <ESPAsyncWebServer.h>

class WebApiGridProfileClass {
public:
void init(AsyncWebServer* server);
void loop();

private:
void onGridProfileStatus(AsyncWebServerRequest* request);

AsyncWebServer* _server;
};
2 changes: 2 additions & 0 deletions include/WebApi_ws_live.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ class WebApiWsLiveClass {
uint32_t _lastInvUpdateCheck = 0;
uint32_t _lastWsCleanup = 0;
uint32_t _newestInverterTimestamp = 0;

std::mutex _mutex;
};
3 changes: 3 additions & 0 deletions include/defaults.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
#define MQTT_LWT_ONLINE "online"
#define MQTT_LWT_OFFLINE "offline"
#define MQTT_PUBLISH_INTERVAL 5U
#define MQTT_CLEAN_SESSION true

#define DTU_SERIAL 0x99978563412U
#define DTU_POLL_INTERVAL 5U
Expand All @@ -95,6 +96,8 @@
#define DISPLAY_CONTRAST 60U
#define DISPLAY_LANGUAGE 0U

#define REACHABLE_THRESHOLD 2U

#define VEDIRECT_ENABLED false
#define VEDIRECT_VERBOSE_LOGGING false
#define VEDIRECT_UPDATESONLY true
Expand Down
119 changes: 67 additions & 52 deletions lib/Hoymiles/src/Hoymiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Copyright (C) 2022 Thomas Basler and others
*/
#include "Hoymiles.h"
#include "Utils.h"
#include "inverters/HMS_1CH.h"
#include "inverters/HMS_2CH.h"
#include "inverters/HMS_4CH.h"
Expand All @@ -12,18 +13,10 @@
#include "inverters/HM_4CH.h"
#include <Arduino.h>

#define HOY_SEMAPHORE_TAKE() \
do { \
} while (xSemaphoreTake(_xSemaphore, portMAX_DELAY) != pdPASS)
#define HOY_SEMAPHORE_GIVE() xSemaphoreGive(_xSemaphore)

HoymilesClass Hoymiles;

void HoymilesClass::init()
{
_xSemaphore = xSemaphoreCreateMutex();
HOY_SEMAPHORE_GIVE(); // release before first use

_pollInterval = 0;
_radioNrf.reset(new HoymilesRadio_NRF());
_radioCmt.reset(new HoymilesRadio_CMT());
Expand All @@ -41,7 +34,7 @@ void HoymilesClass::initCMT(int8_t pin_sdio, int8_t pin_clk, int8_t pin_cs, int8

void HoymilesClass::loop()
{
HOY_SEMAPHORE_TAKE();
std::lock_guard<std::mutex> lock(_mutex);
_radioNrf->loop();
_radioCmt->loop();

Expand All @@ -57,67 +50,90 @@ void HoymilesClass::loop()
}

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

if (!iv->isReachable()) {
iv->sendChangeChannelRequest();
}
if (iv->getEnablePolling() || iv->getEnableCommands()) {
_messageOutput->print("Fetch inverter: ");
_messageOutput->println(iv->serial(), HEX);

iv->sendStatsRequest();
if (!iv->isReachable()) {
iv->sendChangeChannelRequest();
}

// Fetch event log
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
iv->sendAlarmLogRequest(force);
iv->sendStatsRequest();

// Fetch limit
if ((iv->SystemConfigPara()->getLastLimitRequestSuccess() == CMD_NOK)
|| ((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
_messageOutput->println("Request SystemConfigPara");
iv->sendSystemConfigParaRequest();
}
// Fetch event log
bool force = iv->EventLog()->getLastAlarmRequestSuccess() == CMD_NOK;
iv->sendAlarmLogRequest(force);

// Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend ActivePowerControl");
iv->resendActivePowerControlRequest();
}
// Fetch limit
if (((millis() - iv->SystemConfigPara()->getLastUpdateRequest() > HOY_SYSTEM_CONFIG_PARA_POLL_INTERVAL)
&& (millis() - iv->SystemConfigPara()->getLastUpdateCommand() > HOY_SYSTEM_CONFIG_PARA_POLL_MIN_DURATION))) {
_messageOutput->println("Request SystemConfigPara");
iv->sendSystemConfigParaRequest();
}

// Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend PowerCommand");
iv->resendPowerControlRequest();
}
// Set limit if required
if (iv->SystemConfigPara()->getLastLimitCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend ActivePowerControl");
iv->resendActivePowerControlRequest();
}

// Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0) {
bool invalidDevInfo = !iv->DevInfo()->containsValidData()
&& iv->DevInfo()->getLastUpdateAll() > 0
&& iv->DevInfo()->getLastUpdateSimple() > 0;
// Set power status if required
if (iv->PowerCommand()->getLastPowerCommandSuccess() == CMD_NOK) {
_messageOutput->println("Resend PowerCommand");
iv->resendPowerControlRequest();
}

if (invalidDevInfo) {
_messageOutput->println("DevInfo: No Valid Data");
// Fetch dev info (but first fetch stats)
if (iv->Statistics()->getLastUpdate() > 0) {
bool invalidDevInfo = !iv->DevInfo()->containsValidData()
&& iv->DevInfo()->getLastUpdateAll() > 0
&& iv->DevInfo()->getLastUpdateSimple() > 0;

if (invalidDevInfo) {
_messageOutput->println("DevInfo: No Valid Data");
}

if ((iv->DevInfo()->getLastUpdateAll() == 0)
|| (iv->DevInfo()->getLastUpdateSimple() == 0)
|| invalidDevInfo) {
_messageOutput->println("Request device info");
iv->sendDevInfoRequest();
}
}

if ((iv->DevInfo()->getLastUpdateAll() == 0)
|| (iv->DevInfo()->getLastUpdateSimple() == 0)
|| invalidDevInfo) {
_messageOutput->println("Request device info");
iv->sendDevInfoRequest();
// Fetch grid profile
if (iv->Statistics()->getLastUpdate() > 0 && iv->GridProfile()->getLastUpdate() == 0) {
iv->sendGridOnProFileParaRequest();
}

_lastPoll = millis();
}

if (++inverterPos >= getNumInverters()) {
inverterPos = 0;
}
}

_lastPoll = millis();
// Perform housekeeping of all inverters on day change
int8_t currentWeekDay = Utils::getWeekDay();
static int8_t lastWeekDay = -1;
if (lastWeekDay == -1) {
lastWeekDay = currentWeekDay;
} else {
if (currentWeekDay != lastWeekDay) {

for (auto& inv : _inverters) {
if (inv->getZeroYieldDayOnMidnight()) {
inv->Statistics()->zeroDailyData();
}
}

lastWeekDay = currentWeekDay;
}
}
}
}

HOY_SEMAPHORE_GIVE();
}

std::shared_ptr<InverterAbstract> HoymilesClass::addInverter(const char* name, uint64_t serial)
Expand Down Expand Up @@ -195,9 +211,8 @@ void HoymilesClass::removeInverterBySerial(uint64_t serial)
{
for (uint8_t i = 0; i < _inverters.size(); i++) {
if (_inverters[i]->serial() == serial) {
HOY_SEMAPHORE_TAKE();
std::lock_guard<std::mutex> lock(_mutex);
_inverters.erase(_inverters.begin() + i);
HOY_SEMAPHORE_GIVE();
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Hoymiles/src/Hoymiles.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class HoymilesClass {
std::unique_ptr<HoymilesRadio_NRF> _radioNrf;
std::unique_ptr<HoymilesRadio_CMT> _radioCmt;

SemaphoreHandle_t _xSemaphore;
std::mutex _mutex;

uint32_t _pollInterval = 0;
bool _verboseLogging = true;
Expand Down
15 changes: 15 additions & 0 deletions lib/Hoymiles/src/Utils.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright (C) 2023 Thomas Basler and others
*/
#include "Utils.h"
#include <time.h>

uint8_t Utils::getWeekDay()
{
time_t raw;
struct tm info;
time(&raw);
localtime_r(&raw, &info);
return info.tm_mday;
}
Loading

0 comments on commit 4d0f958

Please sign in to comment.