You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

425 lines
11 KiB

//-----------------------------------------------------------------------------
// 2023 Ahoy, https://ahoydtu.de
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
//-----------------------------------------------------------------------------
#ifndef __APP_H__
#define __APP_H__
#include <Arduino.h>
#include <ArduinoJson.h>
#include "config/settings.h"
#include "defines.h"
#include "appInterface.h"
#include "hm/hmSystem.h"
#include "hm/hmRadio.h"
#if defined(ESP32)
#include "hms/hmsRadio.h"
#endif
#if defined(ENABLE_MQTT)
#include "publisher/pubMqtt.h"
#endif /*ENABLE_MQTT*/
#include "publisher/pubSerial.h"
#include "utils/crc.h"
#include "utils/dbg.h"
#include "utils/scheduler.h"
#include "utils/syslog.h"
#include "web/RestApi.h"
#if defined(ENABLE_HISTORY)
#include "plugins/history.h"
#endif /*ENABLE_HISTORY*/
#include "web/web.h"
#include "hm/Communication.h"
#if defined(ETHERNET)
#include "eth/ahoyeth.h"
#else /* defined(ETHERNET) */
#include "wifi/ahoywifi.h"
#include "utils/improv.h"
#endif /* defined(ETHERNET) */
#if defined(ENABLE_SIMULATOR)
#include "hm/simulator.h"
#endif /*ENABLE_SIMULATOR*/
#include <RF24.h> // position is relevant since version 1.4.7 of this library
// convert degrees and radians for sun calculation
#define SIN(x) (sin(radians(x)))
#define COS(x) (cos(radians(x)))
#define ASIN(x) (degrees(asin(x)))
#define ACOS(x) (degrees(acos(x)))
typedef HmSystem<MAX_NUM_INVERTERS> HmSystemType;
typedef Web<HmSystemType> WebType;
typedef RestApi<HmSystemType> RestApiType;
#if defined(ENABLE_MQTT)
typedef PubMqtt<HmSystemType> PubMqttType;
#endif /*ENABLE_MQTT*/
typedef PubSerial<HmSystemType> PubSerialType;
#if defined(ENABLE_HISTORY)
typedef HistoryData<HmSystemType> HistoryType;
#endif /*ENABLE_HISTORY*/
#if defined (ENABLE_SIMULATOR)
typedef Simulator<HmSystemType> SimulatorType;
#endif /*ENABLE_SIMULATOR*/
// PLUGINS
#if defined(PLUGIN_DISPLAY)
#include "plugins/Display/Display.h"
#include "plugins/Display/Display_data.h"
typedef Display<HmSystemType, Radio> DisplayType;
#endif
class app : public IApp, public ah::Scheduler {
public:
app();
~app() {}
void setup(void);
void loop(void);
void onNetwork(bool gotIp);
void regularTickers(void);
void handleIntr(void) {
mNrfRadio.handleIntr();
}
void* getRadioObj(bool nrf) {
if(nrf)
return (void*)&mNrfRadio;
else {
#ifdef ESP32
return (void*)&mCmtRadio;
#else
return NULL;
#endif
}
}
#ifdef ESP32
void handleHmsIntr(void) {
mCmtRadio.handleIntr();
}
#endif
uint32_t getUptime() {
return Scheduler::getUptime();
}
uint32_t getTimestamp() {
return Scheduler::mTimestamp;
}
uint64_t getTimestampMs() {
return ((uint64_t)Scheduler::mTimestamp * 1000) + (uint64_t)Scheduler::mTsMillis;
}
bool saveSettings(bool reboot) {
mShowRebootRequest = true; // only message on index, no reboot
mSavePending = true;
mSaveReboot = reboot;
if(reboot) {
ah::Scheduler::resetTicker();
}
once(std::bind(&app::tickSave, this), 3, "save");
return true;
}
void initInverter(uint8_t id) {
mSys.addInverter(id, [this](Inverter<> *iv) {
if((IV_MI == iv->ivGen) || (IV_HM == iv->ivGen))
iv->radio = &mNrfRadio;
#if defined(ESP32)
else if((IV_HMS == iv->ivGen) || (IV_HMT == iv->ivGen))
iv->radio = &mCmtRadio;
#endif
});
}
bool readSettings(const char *path) {
return mSettings.readSettings(path);
}
bool eraseSettings(bool eraseWifi = false) {
return mSettings.eraseSettings(eraseWifi);
}
bool getSavePending() {
return mSavePending;
}
bool getLastSaveSucceed() {
return mSettings.getLastSaveSucceed();
}
bool getShouldReboot() {
return mSaveReboot;
}
#if !defined(ETHERNET)
void scanAvailNetworks() {
mWifi.scanAvailNetworks();
}
bool getAvailNetworks(JsonObject obj) {
return mWifi.getAvailNetworks(obj);
}
void setupStation(void) {
mWifi.setupStation();
}
void setStopApAllowedMode(bool allowed) {
mWifi.setStopApAllowedMode(allowed);
}
String getStationIp(void) {
return mWifi.getStationIp();
}
#endif /* !defined(ETHERNET) */
void setRebootFlag() {
once(std::bind(&app::tickReboot, this), 3, "rboot");
}
const char *getVersion() {
return mVersion;
}
uint32_t getSunrise() {
return mSunrise;
}
uint32_t getSunset() {
return mSunset;
}
bool getSettingsValid() {
return mSettings.getValid();
}
bool getRebootRequestState() {
return mShowRebootRequest;
}
void setMqttDiscoveryFlag() {
#if defined(ENABLE_MQTT)
once(std::bind(&PubMqttType::sendDiscoveryConfig, &mMqtt), 1, "disCf");
#endif
}
bool getMqttIsConnected() {
#if defined(ENABLE_MQTT)
return mMqtt.isConnected();
#else
return false;
#endif
}
uint32_t getMqttTxCnt() {
#if defined(ENABLE_MQTT)
return mMqtt.getTxCnt();
#else
return 0;
#endif
}
uint32_t getMqttRxCnt() {
#if defined(ENABLE_MQTT)
return mMqtt.getRxCnt();
#else
return 0;
#endif
}
bool getProtection(AsyncWebServerRequest *request) {
return mWeb.isProtected(request);
}
bool getNrfEnabled(void) {
return mConfig->nrf.enabled;
}
bool getCmtEnabled(void) {
return mConfig->cmt.enabled;
}
uint8_t getNrfIrqPin(void) {
return mConfig->nrf.pinIrq;
}
uint8_t getCmtIrqPin(void) {
return mConfig->cmt.pinIrq;
}
uint32_t getTimezoneOffset() {
return mApi.getTimezoneOffset();
}
void getSchedulerInfo(uint8_t *max) {
getStat(max);
}
void getSchedulerNames(void) {
printSchedulers();
}
void setTimestamp(uint32_t newTime) {
DPRINT(DBG_DEBUG, F("setTimestamp: "));
DBGPRINTLN(String(newTime));
if(0 == newTime)
{
#if defined(ETHERNET)
mEth.updateNtpTime();
#else /* defined(ETHERNET) */
mWifi.getNtpTime();
#endif /* defined(ETHERNET) */
}
else
Scheduler::setTimestamp(newTime);
}
uint16_t getHistoryValue(uint8_t type, uint16_t i) {
#if defined(ENABLE_HISTORY)
return mHistory.valueAt((HistoryStorageType)type, i);
#else
return 0;
#endif
}
uint16_t getHistoryMaxDay() {
#if defined(ENABLE_HISTORY)
return mHistory.getMaximumDay();
#else
return 0;
#endif
}
private:
#define CHECK_AVAIL true
#define SKIP_YIELD_DAY true
void resetSystem(void);
void zeroIvValues(bool checkAvail = false, bool skipYieldDay = true);
void payloadEventListener(uint8_t cmd, Inverter<> *iv) {
#if !defined(AP_ONLY)
#if defined(ENABLE_MQTT)
if (mMqttEnabled)
mMqtt.payloadEventListener(cmd, iv);
#endif /*ENABLE_MQTT*/
#endif
#if defined(PLUGIN_DISPLAY)
if(mConfig->plugin.display.type != 0)
mDisplay.payloadEventListener(cmd);
#endif
updateLed();
}
void mqttSubRxCb(JsonObject obj);
void setupLed();
void updateLed();
void tickReboot(void) {
DPRINTLN(DBG_INFO, F("Rebooting..."));
ah::Scheduler::resetTicker();
WiFi.disconnect();
delay(200);
ESP.restart();
}
void tickSave(void) {
if(!mSettings.saveSettings())
mSaveReboot = false;
mSavePending = false;
if(mSaveReboot)
setRebootFlag();
}
void tickNtpUpdate(void);
#if defined(ETHERNET)
void onNtpUpdate(bool gotTime);
#endif /* defined(ETHERNET) */
void updateNtp(void);
void triggerTickSend() {
once(std::bind(&app::tickSend, this), 0, "tSend");
}
void tickCalcSunrise(void);
void tickIVCommunication(void);
void tickSun(void);
void tickSunrise(void);
void tickComm(void);
void tickSend(void);
void tickMinute(void);
void tickZeroValues(void);
void tickMidnight(void);
HmSystemType mSys;
HmRadio<> mNrfRadio;
Communication mCommunication;
bool mShowRebootRequest;
#if defined(ETHERNET)
ahoyeth mEth;
#else /* defined(ETHERNET) */
ahoywifi mWifi;
#endif /* defined(ETHERNET) */
WebType mWeb;
RestApiType mApi;
#ifdef ENABLE_SYSLOG
DbgSyslog mDbgSyslog;
#endif
//PayloadType mPayload;
//MiPayloadType mMiPayload;
PubSerialType mPubSerial;
#if !defined(ETHERNET)
//Improv mImprov;
#endif
#ifdef ESP32
CmtRadio<> mCmtRadio;
#endif
char mVersion[23];
settings mSettings;
settings_t *mConfig;
bool mSavePending;
bool mSaveReboot;
uint8_t mSendLastIvId;
bool mSendFirst;
bool mNetworkConnected;
// mqtt
#if defined(ENABLE_MQTT)
PubMqttType mMqtt;
#endif /*ENABLE_MQTT*/
bool mMqttReconnect;
bool mMqttEnabled;
// sun
int32_t mCalculatedTimezoneOffset;
uint32_t mSunrise, mSunset;
// plugins
#if defined(PLUGIN_DISPLAY)
DisplayType mDisplay;
DisplayData mDispData;
#endif
#if defined(ENABLE_HISTORY)
HistoryType mHistory;
#endif /*ENABLE_HISTORY*/
#if defined(ENABLE_SIMULATOR)
SimulatorType mSimulator;
#endif /*ENABLE_SIMULATOR*/
};
#endif /*__APP_H__*/