mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-24 06:16:11 +02:00
convertion to littfs storage - not complete
This commit is contained in:
parent
56cfffbcd8
commit
faa28ce1a8
22 changed files with 666 additions and 746 deletions
3
src/.vscode/settings.json
vendored
3
src/.vscode/settings.json
vendored
|
@ -20,4 +20,7 @@
|
||||||
|
|
||||||
// https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
// https://clang.llvm.org/docs/ClangFormatStyleOptions.html
|
||||||
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}",
|
"C_Cpp.clang_format_fallbackStyle": "{ BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 0}",
|
||||||
|
"files.associations": {
|
||||||
|
"typeinfo": "cpp"
|
||||||
|
},
|
||||||
}
|
}
|
216
src/app.cpp
216
src/app.cpp
|
@ -13,33 +13,27 @@
|
||||||
#include "utils/sun.h"
|
#include "utils/sun.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
app::app() {
|
void app::setup(uint32_t timeout) {
|
||||||
Serial.begin(115200);
|
Serial.begin(115200);
|
||||||
DPRINTLN(DBG_VERBOSE, F("app::app"));
|
while (!Serial)
|
||||||
mEep = new eep();
|
yield();
|
||||||
|
|
||||||
resetSystem();
|
resetSystem();
|
||||||
loadDefaultConfig();
|
mSettings.setup();
|
||||||
|
mSettings.getPtr(mConfig);
|
||||||
|
|
||||||
|
mWifi = new ahoywifi(mConfig);
|
||||||
|
|
||||||
mWifi = new ahoywifi(this, &mSysConfig, &mConfig);
|
|
||||||
mSys = new HmSystemType();
|
mSys = new HmSystemType();
|
||||||
mSys->enableDebug();
|
mSys->enableDebug();
|
||||||
mShouldReboot = false;
|
mShouldReboot = false;
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
mWifi->setup(timeout, mSettings.getValid());
|
||||||
void app::setup(uint32_t timeout) {
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("app::setup"));
|
|
||||||
|
|
||||||
mWifiSettingsValid = checkEEpCrc(ADDR_START, ADDR_WIFI_CRC, ADDR_WIFI_CRC);
|
mSys->setup(mConfig->nrf.amplifierPower, mConfig->nrf.pinIrq, mConfig->nrf.pinCe, mConfig->nrf.pinCs);
|
||||||
mSettingsValid = checkEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT) - (ADDR_START_SETTINGS)), ADDR_SETTINGS_CRC);
|
mSys->addInverters(&mConfig->inst);
|
||||||
loadEEpconfig();
|
|
||||||
|
|
||||||
mWifi->setup(timeout, mWifiSettingsValid);
|
|
||||||
|
|
||||||
mSys->setup(mConfig.amplifierPower, mConfig.pinIrq, mConfig.pinCe, mConfig.pinCs);
|
|
||||||
mPayload.setup(mSys);
|
mPayload.setup(mSys);
|
||||||
mPayload.enableSerialDebug(mConfig.serialDebug);
|
mPayload.enableSerialDebug(mConfig->serial.debug);
|
||||||
#ifndef AP_ONLY
|
#ifndef AP_ONLY
|
||||||
setupMqtt();
|
setupMqtt();
|
||||||
if(mMqttActive)
|
if(mMqttActive)
|
||||||
|
@ -47,11 +41,12 @@ void app::setup(uint32_t timeout) {
|
||||||
#endif
|
#endif
|
||||||
setupLed();
|
setupLed();
|
||||||
|
|
||||||
mWebInst = new web(this, &mSysConfig, &mConfig, &mStat, mVersion);
|
|
||||||
|
mWebInst = new web(this, mConfig, &mStat, mVersion);
|
||||||
mWebInst->setup();
|
mWebInst->setup();
|
||||||
mWebInst->setProtection(strlen(mConfig.password) != 0);
|
mWebInst->setProtection(strlen(mConfig->sys.adminPwd) != 0);
|
||||||
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettingsValid) ? F("true") : F("false")));
|
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false")));
|
||||||
DPRINTLN(DBG_INFO, F("EEprom storage size: 0x") + String(ADDR_SETTINGS_CRC, HEX));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -88,7 +83,7 @@ void app::loop(void) {
|
||||||
|
|
||||||
if (mFlagSendDiscoveryConfig) {
|
if (mFlagSendDiscoveryConfig) {
|
||||||
mFlagSendDiscoveryConfig = false;
|
mFlagSendDiscoveryConfig = false;
|
||||||
mMqtt.sendMqttDiscoveryConfig(mConfig.mqtt.topic);
|
mMqtt.sendMqttDiscoveryConfig(mConfig->mqtt.topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
mSys->Radio.loop();
|
mSys->Radio.loop();
|
||||||
|
@ -104,7 +99,7 @@ void app::loop(void) {
|
||||||
|
|
||||||
if (mSys->Radio.checkPaketCrc(p->packet, &len, p->rxCh)) {
|
if (mSys->Radio.checkPaketCrc(p->packet, &len, p->rxCh)) {
|
||||||
// process buffer only on first occurrence
|
// process buffer only on first occurrence
|
||||||
if (mConfig.serialDebug) {
|
if (mConfig->serial.debug) {
|
||||||
DPRINT(DBG_INFO, "RX " + String(len) + "B Ch" + String(p->rxCh) + " | ");
|
DPRINT(DBG_INFO, "RX " + String(len) + "B Ch" + String(p->rxCh) + " | ");
|
||||||
mSys->Radio.dumpBuf(NULL, p->packet, len);
|
mSys->Radio.dumpBuf(NULL, p->packet, len);
|
||||||
}
|
}
|
||||||
|
@ -119,23 +114,23 @@ void app::loop(void) {
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
if (rxRdy)
|
if (rxRdy)
|
||||||
mPayload.process(true, mConfig.maxRetransPerPyld, &mStat);
|
mPayload.process(true, mConfig->nrf.maxRetransPerPyld, &mStat);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mMqttActive)
|
if (mMqttActive)
|
||||||
mMqtt.loop();
|
mMqtt.loop();
|
||||||
|
|
||||||
if (ah::checkTicker(&mTicker, 1000)) {
|
if (ah::checkTicker(&mTicker, 1000)) {
|
||||||
if (mUtcTimestamp > 946684800 && mConfig.sunLat && mConfig.sunLon && (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 != (mLatestSunTimestamp + mCalculatedTimezoneOffset) / 86400) { // update on reboot or midnight
|
if (mUtcTimestamp > 946684800 && mConfig->sun.lat && mConfig->sun.lon && (mUtcTimestamp + mCalculatedTimezoneOffset) / 86400 != (mLatestSunTimestamp + mCalculatedTimezoneOffset) / 86400) { // update on reboot or midnight
|
||||||
if (!mLatestSunTimestamp) { // first call: calculate time zone from longitude to refresh at local midnight
|
if (!mLatestSunTimestamp) { // first call: calculate time zone from longitude to refresh at local midnight
|
||||||
mCalculatedTimezoneOffset = (int8_t)((mConfig.sunLon >= 0 ? mConfig.sunLon + 7.5 : mConfig.sunLon - 7.5) / 15) * 3600;
|
mCalculatedTimezoneOffset = (int8_t)((mConfig->sun.lon >= 0 ? mConfig->sun.lon + 7.5 : mConfig->sun.lon - 7.5) / 15) * 3600;
|
||||||
}
|
}
|
||||||
ah::calculateSunriseSunset(mUtcTimestamp, mCalculatedTimezoneOffset, mConfig.sunLat, mConfig.sunLon, &mSunrise, &mSunset);
|
ah::calculateSunriseSunset(mUtcTimestamp, mCalculatedTimezoneOffset, mConfig->sun.lat, mConfig->sun.lon, &mSunrise, &mSunset);
|
||||||
mLatestSunTimestamp = mUtcTimestamp;
|
mLatestSunTimestamp = mUtcTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mConfig.serialShowIv) {
|
if (mConfig->serial.showIv) {
|
||||||
if (++mSerialTicker >= mConfig.serialInterval) {
|
if (++mSerialTicker >= mConfig->serial.interval) {
|
||||||
mSerialTicker = 0;
|
mSerialTicker = 0;
|
||||||
char topic[30], val[10];
|
char topic[30], val[10];
|
||||||
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
for (uint8_t id = 0; id < mSys->getNumInverters(); id++) {
|
||||||
|
@ -146,7 +141,7 @@ void app::loop(void) {
|
||||||
DPRINTLN(DBG_INFO, "Inverter: " + String(id));
|
DPRINTLN(DBG_INFO, "Inverter: " + String(id));
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
if (0.0f != iv->getValue(i, rec)) {
|
if (0.0f != iv->getValue(i, rec)) {
|
||||||
snprintf(topic, 30, "%s/ch%d/%s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
snprintf(topic, 30, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||||
snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec));
|
snprintf(val, 10, "%.3f %s", iv->getValue(i, rec), iv->getUnit(i, rec));
|
||||||
DPRINTLN(DBG_INFO, String(topic) + ": " + String(val));
|
DPRINTLN(DBG_INFO, String(topic) + ": " + String(val));
|
||||||
}
|
}
|
||||||
|
@ -159,15 +154,15 @@ void app::loop(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++mSendTicker >= mConfig.sendInterval) {
|
if (++mSendTicker >= mConfig->nrf.sendInterval) {
|
||||||
mSendTicker = 0;
|
mSendTicker = 0;
|
||||||
|
|
||||||
if (mUtcTimestamp > 946684800 && (!mConfig.sunDisNightCom || !mLatestSunTimestamp || (mUtcTimestamp >= mSunrise && mUtcTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
|
if (mUtcTimestamp > 946684800 && (!mConfig->sun.disNightCom || !mLatestSunTimestamp || (mUtcTimestamp >= mSunrise && mUtcTimestamp <= mSunset))) { // Timestamp is set and (inverter communication only during the day if the option is activated and sunrise/sunset is set)
|
||||||
if (mConfig.serialDebug)
|
if (mConfig->serial.debug)
|
||||||
DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX));
|
DPRINTLN(DBG_DEBUG, F("Free heap: 0x") + String(ESP.getFreeHeap(), HEX));
|
||||||
|
|
||||||
if (!mSys->BufCtrl.empty()) {
|
if (!mSys->BufCtrl.empty()) {
|
||||||
if (mConfig.serialDebug)
|
if (mConfig->serial.debug)
|
||||||
DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill()));
|
DPRINTLN(DBG_DEBUG, F("recbuf not empty! #") + String(mSys->BufCtrl.getFill()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,7 +175,7 @@ void app::loop(void) {
|
||||||
|
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
if (!mPayload.isComplete(iv))
|
if (!mPayload.isComplete(iv))
|
||||||
mPayload.process(false, mConfig.maxRetransPerPyld, &mStat);
|
mPayload.process(false, mConfig->nrf.maxRetransPerPyld, &mStat);
|
||||||
|
|
||||||
if (!mPayload.isComplete(iv)) {
|
if (!mPayload.isComplete(iv)) {
|
||||||
if (0 == mPayload.getMaxPacketId(iv))
|
if (0 == mPayload.getMaxPacketId(iv))
|
||||||
|
@ -189,9 +184,9 @@ void app::loop(void) {
|
||||||
mStat.rxFail++;
|
mStat.rxFail++;
|
||||||
|
|
||||||
iv->setQueuedCmdFinished(); // command failed
|
iv->setQueuedCmdFinished(); // command failed
|
||||||
if (mConfig.serialDebug)
|
if (mConfig->serial.debug)
|
||||||
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
|
DPRINTLN(DBG_INFO, F("enqueued cmd failed/timeout"));
|
||||||
if (mConfig.serialDebug) {
|
if (mConfig->serial.debug) {
|
||||||
DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") ");
|
DPRINT(DBG_INFO, F("(#") + String(iv->id) + ") ");
|
||||||
DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")");
|
DPRINTLN(DBG_INFO, F("no Payload received! (retransmits: ") + String(mPayload.getRetransmits(iv)) + ")");
|
||||||
}
|
}
|
||||||
|
@ -201,13 +196,13 @@ void app::loop(void) {
|
||||||
mPayload.request(iv);
|
mPayload.request(iv);
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
if (mConfig.serialDebug) {
|
if (mConfig->serial.debug) {
|
||||||
DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status()));
|
DPRINTLN(DBG_DEBUG, F("app:loop WiFi WiFi.status ") + String(WiFi.status()));
|
||||||
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->serial.u64, HEX));
|
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Requesting Inv SN ") + String(iv->config->serial.u64, HEX));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (iv->devControlRequest) {
|
if (iv->devControlRequest) {
|
||||||
if (mConfig.serialDebug)
|
if (mConfig->serial.debug)
|
||||||
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
|
DPRINTLN(DBG_INFO, F("(#") + String(iv->id) + F(") Devcontrol request ") + String(iv->devControlCmd) + F(" power limit ") + String(iv->powerLimit[0]));
|
||||||
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
|
mSys->Radio.sendControlPacket(iv->radioId.u64, iv->devControlCmd, iv->powerLimit);
|
||||||
mPayload.setTxCmd(iv, iv->devControlCmd);
|
mPayload.setTxCmd(iv, iv->devControlCmd);
|
||||||
|
@ -221,7 +216,7 @@ void app::loop(void) {
|
||||||
mRxTicker = 0;
|
mRxTicker = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (mConfig.serialDebug)
|
} else if (mConfig->serial.debug)
|
||||||
DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!"));
|
DPRINTLN(DBG_WARN, F("Time not set or it is night time, therefore no communication to the inverter!"));
|
||||||
yield();
|
yield();
|
||||||
|
|
||||||
|
@ -284,130 +279,13 @@ void app::resetSystem(void) {
|
||||||
memset(&mStat, 0, sizeof(statistics_t));
|
memset(&mStat, 0, sizeof(statistics_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void app::loadDefaultConfig(void) {
|
|
||||||
memset(&mSysConfig, 0, sizeof(sysConfig_t));
|
|
||||||
memset(&mConfig, 0, sizeof(config_t));
|
|
||||||
snprintf(mVersion, 12, "%d.%d.%d", VERSION_MAJOR, VERSION_MINOR, VERSION_PATCH);
|
|
||||||
|
|
||||||
snprintf(mSysConfig.deviceName, DEVNAME_LEN, "%s", DEF_DEVICE_NAME);
|
|
||||||
|
|
||||||
// wifi
|
|
||||||
snprintf(mSysConfig.stationSsid, SSID_LEN, "%s", FB_WIFI_SSID);
|
|
||||||
snprintf(mSysConfig.stationPwd, PWD_LEN, "%s", FB_WIFI_PWD);
|
|
||||||
|
|
||||||
// password
|
|
||||||
snprintf(mConfig.password, PWD_LEN, "%s", GUI_DEF_PASSWORD);
|
|
||||||
|
|
||||||
// nrf24
|
|
||||||
mConfig.sendInterval = SEND_INTERVAL;
|
|
||||||
mConfig.maxRetransPerPyld = DEF_MAX_RETRANS_PER_PYLD;
|
|
||||||
mConfig.pinCs = DEF_CS_PIN;
|
|
||||||
mConfig.pinCe = DEF_CE_PIN;
|
|
||||||
mConfig.pinIrq = DEF_IRQ_PIN;
|
|
||||||
mConfig.amplifierPower = DEF_AMPLIFIERPOWER & 0x03;
|
|
||||||
|
|
||||||
// status LED
|
|
||||||
mConfig.led.led0 = DEF_LED0_PIN;
|
|
||||||
mConfig.led.led1 = DEF_LED1_PIN;
|
|
||||||
|
|
||||||
// ntp
|
|
||||||
snprintf(mConfig.ntpAddr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME);
|
|
||||||
mConfig.ntpPort = DEF_NTP_PORT;
|
|
||||||
|
|
||||||
// Latitude + Longitude
|
|
||||||
mConfig.sunLat = 0.0;
|
|
||||||
mConfig.sunLon = 0.0;
|
|
||||||
mConfig.sunDisNightCom = false;
|
|
||||||
|
|
||||||
// mqtt
|
|
||||||
snprintf(mConfig.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER);
|
|
||||||
mConfig.mqtt.port = DEF_MQTT_PORT;
|
|
||||||
snprintf(mConfig.mqtt.user, MQTT_USER_LEN, "%s", DEF_MQTT_USER);
|
|
||||||
snprintf(mConfig.mqtt.pwd, MQTT_PWD_LEN, "%s", DEF_MQTT_PWD);
|
|
||||||
snprintf(mConfig.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC);
|
|
||||||
|
|
||||||
// serial
|
|
||||||
mConfig.serialInterval = SERIAL_INTERVAL;
|
|
||||||
mConfig.serialShowIv = false;
|
|
||||||
mConfig.serialDebug = false;
|
|
||||||
|
|
||||||
// Disclaimer
|
|
||||||
mConfig.disclaimer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void app::loadEEpconfig(void) {
|
|
||||||
DPRINTLN(DBG_INFO, F("loadEEpconfig"));
|
|
||||||
|
|
||||||
if (mWifiSettingsValid)
|
|
||||||
mEep->read(ADDR_CFG_SYS, (uint8_t *)&mSysConfig, CFG_SYS_LEN);
|
|
||||||
if (mSettingsValid) {
|
|
||||||
mEep->read(ADDR_CFG, (uint8_t *)&mConfig, CFG_LEN);
|
|
||||||
|
|
||||||
mSendTicker = mConfig.sendInterval;
|
|
||||||
mSerialTicker = 0;
|
|
||||||
|
|
||||||
// inverter
|
|
||||||
uint64_t invSerial;
|
|
||||||
char name[MAX_NAME_LENGTH + 1] = {0};
|
|
||||||
uint16_t modPwr[4];
|
|
||||||
Inverter<> *iv;
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
|
||||||
mEep->read(ADDR_INV_ADDR + (i * 8), &invSerial);
|
|
||||||
mEep->read(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), name, MAX_NAME_LENGTH);
|
|
||||||
mEep->read(ADDR_INV_CH_PWR + (i * 2 * 4), modPwr, 4);
|
|
||||||
if (0ULL != invSerial) {
|
|
||||||
iv = mSys->addInverter(name, invSerial, modPwr);
|
|
||||||
if (NULL != iv) { // will run once on every dtu boot
|
|
||||||
for (uint8_t j = 0; j < 4; j++) {
|
|
||||||
mEep->read(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
|
||||||
iv = mSys->getInverterByPos(i, false);
|
|
||||||
if (NULL != iv)
|
|
||||||
mPayload.reset(iv, mUtcTimestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void app::saveValues(void) {
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("app::saveValues"));
|
|
||||||
|
|
||||||
mEep->write(ADDR_CFG_SYS, (uint8_t *)&mSysConfig, CFG_SYS_LEN);
|
|
||||||
mEep->write(ADDR_CFG, (uint8_t *)&mConfig, CFG_LEN);
|
|
||||||
Inverter<> *iv;
|
|
||||||
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
|
||||||
iv = mSys->getInverterByPos(i, false);
|
|
||||||
mEep->write(ADDR_INV_ADDR + (i * 8), iv->serial.u64);
|
|
||||||
mEep->write(ADDR_INV_NAME + (i * MAX_NAME_LENGTH), iv->name, MAX_NAME_LENGTH);
|
|
||||||
// max channel power / name
|
|
||||||
for (uint8_t j = 0; j < 4; j++) {
|
|
||||||
mEep->write(ADDR_INV_CH_PWR + (i * 2 * 4) + (j * 2), iv->chMaxPwr[j]);
|
|
||||||
mEep->write(ADDR_INV_CH_NAME + (i * 4 * MAX_NAME_LENGTH) + j * MAX_NAME_LENGTH, iv->chName[j], MAX_NAME_LENGTH);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateCrc();
|
|
||||||
|
|
||||||
// update sun
|
|
||||||
mLatestSunTimestamp = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::setupMqtt(void) {
|
void app::setupMqtt(void) {
|
||||||
if (mSettingsValid) {
|
if (mConfig->mqtt.broker[0] > 0)
|
||||||
if (mConfig.mqtt.broker[0] > 0)
|
|
||||||
mMqttActive = true;
|
mMqttActive = true;
|
||||||
|
|
||||||
if(mMqttActive)
|
if(mMqttActive)
|
||||||
mMqtt.setup(&mConfig.mqtt, mSysConfig.deviceName, mVersion, mSys, &mUtcTimestamp);
|
mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -417,26 +295,26 @@ void app::setupLed(void) {
|
||||||
* PIN ---- |<----- 3.3V
|
* PIN ---- |<----- 3.3V
|
||||||
*
|
*
|
||||||
* */
|
* */
|
||||||
if(mConfig.led.led0 != 0xff) {
|
if(mConfig->led.led0 != 0xff) {
|
||||||
pinMode(mConfig.led.led0, OUTPUT);
|
pinMode(mConfig->led.led0, OUTPUT);
|
||||||
digitalWrite(mConfig.led.led0, HIGH); // LED off
|
digitalWrite(mConfig->led.led0, HIGH); // LED off
|
||||||
}
|
}
|
||||||
if(mConfig.led.led1 != 0xff) {
|
if(mConfig->led.led1 != 0xff) {
|
||||||
pinMode(mConfig.led.led1, OUTPUT);
|
pinMode(mConfig->led.led1, OUTPUT);
|
||||||
digitalWrite(mConfig.led.led1, HIGH); // LED off
|
digitalWrite(mConfig->led.led1, HIGH); // LED off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void app::updateLed(void) {
|
void app::updateLed(void) {
|
||||||
if(mConfig.led.led0 != 0xff) {
|
if(mConfig->led.led0 != 0xff) {
|
||||||
Inverter<> *iv = mSys->getInverterByPos(0);
|
Inverter<> *iv = mSys->getInverterByPos(0);
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
if(iv->isProducing(mUtcTimestamp, rec))
|
if(iv->isProducing(mUtcTimestamp, rec))
|
||||||
digitalWrite(mConfig.led.led0, LOW); // LED on
|
digitalWrite(mConfig->led.led0, LOW); // LED on
|
||||||
else
|
else
|
||||||
digitalWrite(mConfig.led.led0, HIGH); // LED off
|
digitalWrite(mConfig->led.led0, HIGH); // LED off
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
93
src/app.h
93
src/app.h
|
@ -7,15 +7,12 @@
|
||||||
#define __APP_H__
|
#define __APP_H__
|
||||||
|
|
||||||
#include "utils/dbg.h"
|
#include "utils/dbg.h"
|
||||||
#include "Arduino.h"
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <RF24.h>
|
#include <RF24.h>
|
||||||
#include <RF24_config.h>
|
#include <RF24_config.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
#include "config/eep.h"
|
#include "config/settings.h"
|
||||||
#include "defines.h"
|
#include "defines.h"
|
||||||
#include "utils/crc.h"
|
#include "utils/crc.h"
|
||||||
#include "utils/ahoyTimer.h"
|
#include "utils/ahoyTimer.h"
|
||||||
|
@ -42,7 +39,7 @@ class web;
|
||||||
|
|
||||||
class app {
|
class app {
|
||||||
public:
|
public:
|
||||||
app();
|
app() {}
|
||||||
~app() {}
|
~app() {}
|
||||||
|
|
||||||
void setup(uint32_t timeout);
|
void setup(uint32_t timeout);
|
||||||
|
@ -55,9 +52,17 @@ class app {
|
||||||
void scanAvailNetworks(void);
|
void scanAvailNetworks(void);
|
||||||
void getAvailNetworks(JsonObject obj);
|
void getAvailNetworks(JsonObject obj);
|
||||||
|
|
||||||
|
void saveSettings(void) {
|
||||||
|
DPRINTLN(DBG_INFO, "a");
|
||||||
|
mSettings.saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eraseSettings(bool eraseWifi = false) {
|
||||||
|
return mSettings.eraseSettings(eraseWifi);
|
||||||
|
}
|
||||||
|
|
||||||
uint8_t getIrqPin(void) {
|
uint8_t getIrqPin(void) {
|
||||||
return mConfig.pinIrq;
|
return mConfig->nrf.pinIrq;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t Serial2u64(const char *val) {
|
uint64_t Serial2u64(const char *val) {
|
||||||
|
@ -122,26 +127,8 @@ class app {
|
||||||
return mLatestSunTimestamp;
|
return mLatestSunTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void eraseSettings(bool all = false) {
|
|
||||||
//DPRINTLN(DBG_VERBOSE, F("main.h:eraseSettings"));
|
|
||||||
uint8_t buf[64];
|
|
||||||
uint16_t addr = (all) ? ADDR_START : ADDR_START_SETTINGS;
|
|
||||||
uint16_t end;
|
|
||||||
|
|
||||||
memset(buf, 0xff, 64);
|
|
||||||
do {
|
|
||||||
end = addr + 64;
|
|
||||||
if(end > (ADDR_SETTINGS_CRC + 2))
|
|
||||||
end = (ADDR_SETTINGS_CRC + 2);
|
|
||||||
DPRINTLN(DBG_DEBUG, F("erase: 0x") + String(addr, HEX) + " - 0x" + String(end, HEX));
|
|
||||||
mEep->write(addr, buf, (end-addr));
|
|
||||||
addr = end;
|
|
||||||
} while(addr < (ADDR_SETTINGS_CRC + 2));
|
|
||||||
mEep->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool mqttIsConnected(void) { return mMqtt.isConnected(); }
|
inline bool mqttIsConnected(void) { return mMqtt.isConnected(); }
|
||||||
inline bool getSettingsValid(void) { return mSettingsValid; }
|
inline bool getSettingsValid(void) { return mSettings.getValid(); }
|
||||||
inline bool getRebootRequestState(void) { return mShowRebootRequest; }
|
inline bool getRebootRequestState(void) { return mShowRebootRequest; }
|
||||||
inline uint32_t getMqttTxCnt(void) { return mMqtt.getTxCnt(); }
|
inline uint32_t getMqttTxCnt(void) { return mMqtt.getTxCnt(); }
|
||||||
|
|
||||||
|
@ -151,57 +138,12 @@ class app {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void resetSystem(void);
|
void resetSystem(void);
|
||||||
void loadDefaultConfig(void);
|
|
||||||
void loadEEpconfig(void);
|
|
||||||
|
|
||||||
void setupMqtt(void);
|
void setupMqtt(void);
|
||||||
|
|
||||||
void setupLed(void);
|
void setupLed(void);
|
||||||
void updateLed(void);
|
void updateLed(void);
|
||||||
|
|
||||||
void processPayload(bool retransmit);
|
|
||||||
|
|
||||||
inline uint16_t buildEEpCrc(uint32_t start, uint32_t length) {
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("main.h:buildEEpCrc"));
|
|
||||||
uint8_t buf[32];
|
|
||||||
uint16_t crc = 0xffff;
|
|
||||||
uint8_t len;
|
|
||||||
|
|
||||||
while(length > 0) {
|
|
||||||
len = (length < 32) ? length : 32;
|
|
||||||
mEep->read(start, buf, len);
|
|
||||||
crc = ah::crc16(buf, len, crc);
|
|
||||||
start += len;
|
|
||||||
length -= len;
|
|
||||||
}
|
|
||||||
return crc;
|
|
||||||
}
|
|
||||||
|
|
||||||
void updateCrc(void) {
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("app::updateCrc"));
|
|
||||||
uint16_t crc;
|
|
||||||
|
|
||||||
crc = buildEEpCrc(ADDR_START, ADDR_WIFI_CRC);
|
|
||||||
DPRINTLN(DBG_DEBUG, F("new Wifi CRC: ") + String(crc, HEX));
|
|
||||||
mEep->write(ADDR_WIFI_CRC, crc);
|
|
||||||
|
|
||||||
crc = buildEEpCrc(ADDR_START_SETTINGS, ((ADDR_NEXT) - (ADDR_START_SETTINGS)));
|
|
||||||
DPRINTLN(DBG_DEBUG, F("new Settings CRC: ") + String(crc, HEX));
|
|
||||||
mEep->write(ADDR_SETTINGS_CRC, crc);
|
|
||||||
|
|
||||||
mEep->commit();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool checkEEpCrc(uint32_t start, uint32_t length, uint32_t crcPos) {
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("main.h:checkEEpCrc"));
|
|
||||||
DPRINTLN(DBG_DEBUG, F("start: ") + String(start) + F(", length: ") + String(length));
|
|
||||||
uint16_t crcRd, crcCheck;
|
|
||||||
crcCheck = buildEEpCrc(start, length);
|
|
||||||
mEep->read(crcPos, &crcRd);
|
|
||||||
DPRINTLN(DBG_DEBUG, "CRC RD: " + String(crcRd, HEX) + " CRC CALC: " + String(crcCheck, HEX));
|
|
||||||
return (crcCheck == crcRd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void stats(void) {
|
void stats(void) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("main.h:stats"));
|
DPRINTLN(DBG_VERBOSE, F("main.h:stats"));
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
|
@ -228,11 +170,6 @@ class app {
|
||||||
uint32_t mNtpRefreshTicker;
|
uint32_t mNtpRefreshTicker;
|
||||||
uint32_t mNtpRefreshInterval;
|
uint32_t mNtpRefreshInterval;
|
||||||
|
|
||||||
|
|
||||||
bool mWifiSettingsValid;
|
|
||||||
bool mSettingsValid;
|
|
||||||
|
|
||||||
eep *mEep;
|
|
||||||
uint32_t mUtcTimestamp;
|
uint32_t mUtcTimestamp;
|
||||||
bool mUpdateNtp;
|
bool mUpdateNtp;
|
||||||
|
|
||||||
|
@ -240,10 +177,10 @@ class app {
|
||||||
|
|
||||||
ahoywifi *mWifi;
|
ahoywifi *mWifi;
|
||||||
web *mWebInst;
|
web *mWebInst;
|
||||||
sysConfig_t mSysConfig;
|
|
||||||
config_t mConfig;
|
|
||||||
char mVersion[12];
|
char mVersion[12];
|
||||||
PayloadType mPayload;
|
PayloadType mPayload;
|
||||||
|
settings mSettings;
|
||||||
|
settings_t *mConfig;
|
||||||
|
|
||||||
uint16_t mSendTicker;
|
uint16_t mSendTicker;
|
||||||
uint8_t mSendLastIvId;
|
uint8_t mSendLastIvId;
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
// If the next line is uncommented, Ahoy will stay in access point mode all the time
|
// If the next line is uncommented, Ahoy will stay in access point mode all the time
|
||||||
//#define AP_ONLY
|
//#define AP_ONLY
|
||||||
|
|
||||||
// protection of the GUI by password
|
|
||||||
#define GUI_DEF_PASSWORD ""
|
|
||||||
|
|
||||||
// timeout for automatic logoff (20 minutes)
|
// timeout for automatic logoff (20 minutes)
|
||||||
#define LOGOUT_TIMEOUT (20 * 60 * 60)
|
#define LOGOUT_TIMEOUT (20 * 60 * 60)
|
||||||
|
|
||||||
|
@ -121,6 +118,11 @@
|
||||||
// default MQTT topic
|
// default MQTT topic
|
||||||
#define DEF_MQTT_TOPIC "inverter"
|
#define DEF_MQTT_TOPIC "inverter"
|
||||||
|
|
||||||
|
// discovery prefix
|
||||||
|
#define MQTT_DISCOVERY_PREFIX "homeassistant"
|
||||||
|
|
||||||
|
// reconnect delay
|
||||||
|
#define MQTT_RECONNECT_DELAY 5000
|
||||||
|
|
||||||
#if __has_include("config_override.h")
|
#if __has_include("config_override.h")
|
||||||
#include "config_override.h"
|
#include "config_override.h"
|
||||||
|
|
161
src/config/eep.h
161
src/config/eep.h
|
@ -1,161 +0,0 @@
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
|
||||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef __EEP_H__
|
|
||||||
#define __EEP_H__
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
#include <EEPROM.h>
|
|
||||||
#ifdef ESP32
|
|
||||||
#include <nvs_flash.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class eep {
|
|
||||||
public:
|
|
||||||
eep() {
|
|
||||||
|
|
||||||
#ifdef ESP32
|
|
||||||
if(!EEPROM.begin(4096)) {
|
|
||||||
nvs_flash_init();
|
|
||||||
EEPROM.begin(4096);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
EEPROM.begin(4096);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
~eep() {
|
|
||||||
EEPROM.end();
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, char *str, uint8_t length) {
|
|
||||||
for(uint8_t i = 0; i < length; i ++) {
|
|
||||||
*(str++) = (char)EEPROM.read(addr++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, float *value) {
|
|
||||||
uint8_t *p = (uint8_t*)value;
|
|
||||||
for(uint8_t i = 0; i < 4; i ++) {
|
|
||||||
*(p++) = (uint8_t)EEPROM.read(addr++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, bool *value) {
|
|
||||||
uint8_t intVal = 0x00;
|
|
||||||
intVal = EEPROM.read(addr++);
|
|
||||||
*value = (intVal == 0x01);
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint8_t *value) {
|
|
||||||
*value = (EEPROM.read(addr++));
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint8_t data[], uint16_t length) {
|
|
||||||
for(uint16_t i = 0; i < length; i ++) {
|
|
||||||
*(data++) = EEPROM.read(addr++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint16_t *value) {
|
|
||||||
*value = (EEPROM.read(addr++) << 8);
|
|
||||||
*value |= (EEPROM.read(addr++));
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint16_t data[], uint16_t length) {
|
|
||||||
for(uint16_t i = 0; i < length; i ++) {
|
|
||||||
*(data) = (EEPROM.read(addr++) << 8);
|
|
||||||
*(data++) |= (EEPROM.read(addr++));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint32_t *value) {
|
|
||||||
*value = (EEPROM.read(addr++) << 24);
|
|
||||||
*value |= (EEPROM.read(addr++) << 16);
|
|
||||||
*value |= (EEPROM.read(addr++) << 8);
|
|
||||||
*value |= (EEPROM.read(addr++));
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint32_t addr, uint64_t *value) {
|
|
||||||
read(addr, (uint32_t *)value);
|
|
||||||
*value <<= 32;
|
|
||||||
uint32_t tmp;
|
|
||||||
read(addr+4, &tmp);
|
|
||||||
*value |= tmp;
|
|
||||||
/**value = (EEPROM.read(addr++) << 56);
|
|
||||||
*value |= (EEPROM.read(addr++) << 48);
|
|
||||||
*value |= (EEPROM.read(addr++) << 40);
|
|
||||||
*value |= (EEPROM.read(addr++) << 32);
|
|
||||||
*value |= (EEPROM.read(addr++) << 24);
|
|
||||||
*value |= (EEPROM.read(addr++) << 16);
|
|
||||||
*value |= (EEPROM.read(addr++) << 8);
|
|
||||||
*value |= (EEPROM.read(addr++));*/
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, const char *str, uint8_t length) {
|
|
||||||
for(uint8_t i = 0; i < length; i ++) {
|
|
||||||
EEPROM.write(addr++, str[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint8_t data[], uint16_t length) {
|
|
||||||
for(uint16_t i = 0; i < length; i ++) {
|
|
||||||
EEPROM.write(addr++, data[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, float value) {
|
|
||||||
uint8_t *p = (uint8_t*)&value;
|
|
||||||
for(uint8_t i = 0; i < 4; i ++) {
|
|
||||||
EEPROM.write(addr++, p[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, bool value) {
|
|
||||||
uint8_t intVal = (value) ? 0x01 : 0x00;
|
|
||||||
EEPROM.write(addr++, intVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint8_t value) {
|
|
||||||
EEPROM.write(addr++, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint16_t value) {
|
|
||||||
EEPROM.write(addr++, (value >> 8) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value ) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint16_t data[], uint16_t length) {
|
|
||||||
for(uint16_t i = 0; i < length; i ++) {
|
|
||||||
EEPROM.write(addr++, (data[i] >> 8) & 0xff);
|
|
||||||
EEPROM.write(addr++, (data[i] ) & 0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint32_t value) {
|
|
||||||
EEPROM.write(addr++, (value >> 24) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 16) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 8) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value ) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint32_t addr, uint64_t value) {
|
|
||||||
EEPROM.write(addr++, (value >> 56) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 48) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 40) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 32) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 24) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 16) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value >> 8) & 0xff);
|
|
||||||
EEPROM.write(addr++, (value ) & 0xff);
|
|
||||||
}
|
|
||||||
|
|
||||||
void commit(void) {
|
|
||||||
EEPROM.commit();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /*__EEP_H__*/
|
|
407
src/config/settings.h
Normal file
407
src/config/settings.h
Normal file
|
@ -0,0 +1,407 @@
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// 2022 Ahoy, https://ahoydtu.de
|
||||||
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef __SETTINGS_H__
|
||||||
|
#define __SETTINGS_H__
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <LittleFS.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include "../utils/dbg.h"
|
||||||
|
#include "../defines.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* More info:
|
||||||
|
* https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html#flash-layout
|
||||||
|
* */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t ip[4]; // ip address
|
||||||
|
uint8_t mask[4]; // sub mask
|
||||||
|
uint8_t dns1[4]; // dns 1
|
||||||
|
uint8_t dns2[4]; // dns 2
|
||||||
|
uint8_t gateway[4]; // standard gateway
|
||||||
|
} cfgIp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char deviceName[DEVNAME_LEN];
|
||||||
|
char adminPwd[PWD_LEN];
|
||||||
|
|
||||||
|
// wifi
|
||||||
|
char stationSsid[SSID_LEN];
|
||||||
|
char stationPwd[PWD_LEN];
|
||||||
|
|
||||||
|
cfgIp_t ip;
|
||||||
|
} cfgSys_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t sendInterval;
|
||||||
|
uint8_t maxRetransPerPyld;
|
||||||
|
uint8_t pinCs;
|
||||||
|
uint8_t pinCe;
|
||||||
|
uint8_t pinIrq;
|
||||||
|
uint8_t amplifierPower;
|
||||||
|
} cfgNrf24_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char addr[NTP_ADDR_LEN];
|
||||||
|
uint16_t port;
|
||||||
|
} cfgNtp_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float lat;
|
||||||
|
float lon;
|
||||||
|
bool disNightCom; // disable night communication
|
||||||
|
} cfgSun_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t interval;
|
||||||
|
bool showIv;
|
||||||
|
bool debug;
|
||||||
|
} cfgSerial_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t led0; // first LED pin
|
||||||
|
uint8_t led1; // second LED pin
|
||||||
|
} cfgLed_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char broker[MQTT_ADDR_LEN];
|
||||||
|
uint16_t port;
|
||||||
|
char user[MQTT_USER_LEN];
|
||||||
|
char pwd[MQTT_PWD_LEN];
|
||||||
|
char topic[MQTT_TOPIC_LEN];
|
||||||
|
} cfgMqtt_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enabled;
|
||||||
|
char name[MAX_NAME_LENGTH];
|
||||||
|
serial_u serial;
|
||||||
|
uint16_t chMaxPwr[4];
|
||||||
|
char chName[4][MAX_NAME_LENGTH];
|
||||||
|
} cfgIv_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool enabled;
|
||||||
|
cfgIv_t iv[MAX_NUM_INVERTERS];
|
||||||
|
} cfgInst_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
cfgSys_t sys;
|
||||||
|
cfgNrf24_t nrf;
|
||||||
|
cfgNtp_t ntp;
|
||||||
|
cfgSun_t sun;
|
||||||
|
cfgSerial_t serial;
|
||||||
|
cfgMqtt_t mqtt;
|
||||||
|
cfgLed_t led;
|
||||||
|
cfgInst_t inst;
|
||||||
|
} settings_t;
|
||||||
|
|
||||||
|
class settings {
|
||||||
|
public:
|
||||||
|
settings() {}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
DPRINTLN(DBG_INFO, F("Initializing FS .."));
|
||||||
|
|
||||||
|
mValid = false;
|
||||||
|
|
||||||
|
LittleFSConfig cfg;
|
||||||
|
cfg.setAutoFormat(false);
|
||||||
|
LittleFS.setConfig(cfg);
|
||||||
|
|
||||||
|
if(!LittleFS.begin()) {
|
||||||
|
DPRINTLN(DBG_INFO, F(".. format .."));
|
||||||
|
LittleFS.format();
|
||||||
|
if(LittleFS.begin())
|
||||||
|
DPRINTLN(DBG_INFO, F(".. success"));
|
||||||
|
else
|
||||||
|
DPRINTLN(DBG_INFO, F(".. failed"));
|
||||||
|
|
||||||
|
}
|
||||||
|
else
|
||||||
|
DPRINTLN(DBG_INFO, F(" .. done"));
|
||||||
|
|
||||||
|
readSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
// should be used before OTA
|
||||||
|
void stop() {
|
||||||
|
LittleFS.end();
|
||||||
|
DPRINTLN(DBG_INFO, F("FS stopped"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void getPtr(settings_t *&cfg) {
|
||||||
|
cfg = &mCfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getValid(void) {
|
||||||
|
return mValid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void getInfo(uint32_t *used, uint32_t *size) {
|
||||||
|
FSInfo info;
|
||||||
|
LittleFS.info(info);
|
||||||
|
*used = info.usedBytes;
|
||||||
|
*size = info.totalBytes;
|
||||||
|
|
||||||
|
DPRINTLN(DBG_INFO, F("-- FILESYSTEM INFO --"));
|
||||||
|
DPRINTLN(DBG_INFO, String(info.usedBytes) + F(" of ") + String(info.totalBytes) + F(" used"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void readSettings(void) {
|
||||||
|
loadDefaults();
|
||||||
|
File fp = LittleFS.open("/settings.json", "r");
|
||||||
|
if(!fp)
|
||||||
|
DPRINTLN(DBG_WARN, F("failed to load json, using default config"));
|
||||||
|
else {
|
||||||
|
DynamicJsonDocument json(8192);
|
||||||
|
DeserializationError err = deserializeJson(json, fp);
|
||||||
|
if(!err) {
|
||||||
|
mValid = true;
|
||||||
|
JsonObject root = json.to<JsonObject>();
|
||||||
|
jsonWifi(root["wifi"]);
|
||||||
|
jsonNrf(root["nrf"]);
|
||||||
|
jsonNtp(root["ntp"]);
|
||||||
|
jsonSun(root["sun"]);
|
||||||
|
jsonSerial(root["serial"]);
|
||||||
|
jsonMqtt(root["mqtt"]);
|
||||||
|
jsonLed(root["led"]);
|
||||||
|
jsonInst(root["inst"]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println(F("failed to parse json, using default config"));
|
||||||
|
}
|
||||||
|
|
||||||
|
fp.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saveSettings(void) {
|
||||||
|
DPRINTLN(DBG_INFO, F("save settings"));
|
||||||
|
File fp = LittleFS.open("/settings.json", "w");
|
||||||
|
if(!fp) {
|
||||||
|
DPRINTLN(DBG_ERROR, F("can't open settings file!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DynamicJsonDocument json(8192);
|
||||||
|
JsonObject root = json.to<JsonObject>();
|
||||||
|
jsonWifi(root["wifi"], true);
|
||||||
|
jsonNrf(root["nrf"], true);
|
||||||
|
jsonNtp(root["ntp"], true);
|
||||||
|
jsonSun(root["sun"], true);
|
||||||
|
jsonSerial(root["serial"], true);
|
||||||
|
jsonMqtt(root["mqtt"], true);
|
||||||
|
jsonLed(root["led"], true);
|
||||||
|
jsonInst(root["inst"], true);
|
||||||
|
|
||||||
|
if(0 == serializeJson(root, fp)) {
|
||||||
|
DPRINTLN(DBG_ERROR, F("can't write settings file!"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool eraseSettings(bool eraseWifi = false) {
|
||||||
|
loadDefaults(eraseWifi);
|
||||||
|
return saveSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
String ip2Str(uint8_t ip[]) {
|
||||||
|
return String(ip[0]) + F(".")
|
||||||
|
+ String(ip[1]) + F(".")
|
||||||
|
+ String(ip[2]) + F(".")
|
||||||
|
+ String(ip[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ip2Arr(uint8_t ip[], const char *ipStr) {
|
||||||
|
char *tmp = new char[strlen(ipStr)];
|
||||||
|
strncpy(tmp, ipStr, strlen(ipStr));
|
||||||
|
char *p = strtok(tmp, ".");
|
||||||
|
uint8_t i = 0;
|
||||||
|
while(NULL != p) {
|
||||||
|
ip[i++] = atoi(p);
|
||||||
|
p = strtok(NULL, ".");
|
||||||
|
}
|
||||||
|
delete[] tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void loadDefaults(bool wifi = true) {
|
||||||
|
DPRINTLN(DBG_INFO, F("loadDefaults"));
|
||||||
|
|
||||||
|
memset(&mCfg, 0, sizeof(settings_t));
|
||||||
|
snprintf(mCfg.sys.stationSsid, SSID_LEN, FB_WIFI_SSID);
|
||||||
|
snprintf(mCfg.sys.stationPwd, PWD_LEN, FB_WIFI_PWD);
|
||||||
|
snprintf(mCfg.sys.deviceName, DEVNAME_LEN, DEF_DEVICE_NAME);
|
||||||
|
|
||||||
|
mCfg.nrf.sendInterval = SEND_INTERVAL;
|
||||||
|
mCfg.nrf.maxRetransPerPyld = DEF_MAX_RETRANS_PER_PYLD;
|
||||||
|
mCfg.nrf.pinCs = DEF_CS_PIN;
|
||||||
|
mCfg.nrf.pinCe = DEF_CE_PIN;
|
||||||
|
mCfg.nrf.pinIrq = DEF_IRQ_PIN;
|
||||||
|
mCfg.nrf.amplifierPower = DEF_AMPLIFIERPOWER & 0x03;
|
||||||
|
|
||||||
|
snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", DEF_NTP_SERVER_NAME);
|
||||||
|
mCfg.ntp.port = DEF_NTP_PORT;
|
||||||
|
|
||||||
|
mCfg.sun.lat = 0.0;
|
||||||
|
mCfg.sun.lon = 0.0;
|
||||||
|
mCfg.sun.disNightCom = false;
|
||||||
|
|
||||||
|
mCfg.serial.interval = SERIAL_INTERVAL;
|
||||||
|
mCfg.serial.showIv = false;
|
||||||
|
mCfg.serial.debug = false;
|
||||||
|
|
||||||
|
mCfg.mqtt.port = DEF_MQTT_PORT;
|
||||||
|
snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", DEF_MQTT_BROKER);
|
||||||
|
snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", DEF_MQTT_USER);
|
||||||
|
snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", DEF_MQTT_PWD);
|
||||||
|
snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", DEF_MQTT_TOPIC);
|
||||||
|
|
||||||
|
mCfg.led.led0 = DEF_LED0_PIN;
|
||||||
|
mCfg.led.led1 = DEF_LED1_PIN;
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonWifi(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("ssid")] = mCfg.sys.stationSsid;
|
||||||
|
obj[F("pwd")] = mCfg.sys.stationPwd;
|
||||||
|
obj[F("dev")] = mCfg.sys.deviceName;
|
||||||
|
obj[F("adm")] = mCfg.sys.adminPwd;
|
||||||
|
obj[F("ip")] = ip2Str(mCfg.sys.ip.ip);
|
||||||
|
obj[F("mask")] = ip2Str(mCfg.sys.ip.mask);
|
||||||
|
obj[F("dns1")] = ip2Str(mCfg.sys.ip.dns1);
|
||||||
|
obj[F("dns2")] = ip2Str(mCfg.sys.ip.dns2);
|
||||||
|
obj[F("gtwy")] = ip2Str(mCfg.sys.ip.gateway);
|
||||||
|
} else {
|
||||||
|
snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as<const char*>());
|
||||||
|
snprintf(mCfg.sys.stationPwd, PWD_LEN, "%s", obj[F("pwd")].as<const char*>());
|
||||||
|
snprintf(mCfg.sys.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as<const char*>());
|
||||||
|
snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as<const char*>());
|
||||||
|
ip2Arr(mCfg.sys.ip.ip, obj[F("ip")]);
|
||||||
|
ip2Arr(mCfg.sys.ip.mask, obj[F("mask")]);
|
||||||
|
ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")]);
|
||||||
|
ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")]);
|
||||||
|
ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonNrf(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("intvl")] = mCfg.nrf.sendInterval;
|
||||||
|
obj[F("maxRetry")] = mCfg.nrf.maxRetransPerPyld;
|
||||||
|
obj[F("cs")] = mCfg.nrf.pinCs;
|
||||||
|
obj[F("ce")] = mCfg.nrf.pinCe;
|
||||||
|
obj[F("irq")] = mCfg.nrf.pinIrq;
|
||||||
|
obj[F("pwr")] = mCfg.nrf.amplifierPower;
|
||||||
|
} else {
|
||||||
|
mCfg.nrf.sendInterval = obj[F("intvl")];
|
||||||
|
mCfg.nrf.maxRetransPerPyld = obj[F("maxRetry")];
|
||||||
|
mCfg.nrf.pinCs = obj[F("cs")];
|
||||||
|
mCfg.nrf.pinCe = obj[F("ce")];
|
||||||
|
mCfg.nrf.pinIrq = obj[F("irq")];
|
||||||
|
mCfg.nrf.amplifierPower = obj[F("pwr")];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonNtp(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("addr")] = mCfg.ntp.addr;
|
||||||
|
obj[F("port")] = mCfg.ntp.port;
|
||||||
|
} else {
|
||||||
|
snprintf(mCfg.ntp.addr, NTP_ADDR_LEN, "%s", obj[F("addr")].as<const char*>());
|
||||||
|
mCfg.ntp.port = obj[F("port")];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonSun(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("lat")] = mCfg.sun.lat;
|
||||||
|
obj[F("lon")] = mCfg.sun.lon;
|
||||||
|
obj[F("dis")] = mCfg.sun.disNightCom;
|
||||||
|
} else {
|
||||||
|
mCfg.sun.lat = obj[F("lat")];
|
||||||
|
mCfg.sun.lon = obj[F("lon")];
|
||||||
|
mCfg.sun.disNightCom = obj[F("dis")];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonSerial(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("intvl")] = mCfg.serial.interval;
|
||||||
|
obj[F("show")] = mCfg.serial.showIv;
|
||||||
|
obj[F("debug")] = mCfg.serial.debug;
|
||||||
|
} else {
|
||||||
|
mCfg.serial.interval = obj[F("intvl")];
|
||||||
|
mCfg.serial.showIv = obj[F("show")];
|
||||||
|
mCfg.serial.debug = obj[F("debug")];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonMqtt(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj[F("broker")] = mCfg.mqtt.broker;
|
||||||
|
obj[F("port")] = mCfg.mqtt.port;
|
||||||
|
obj[F("user")] = mCfg.mqtt.user;
|
||||||
|
obj[F("pwd")] = mCfg.mqtt.pwd;
|
||||||
|
obj[F("topic")] = mCfg.mqtt.topic;
|
||||||
|
} else {
|
||||||
|
mCfg.mqtt.port = obj[F("port")];
|
||||||
|
snprintf(mCfg.mqtt.broker, MQTT_ADDR_LEN, "%s", obj[F("broker")].as<const char*>());
|
||||||
|
snprintf(mCfg.mqtt.user, MQTT_USER_LEN, "%s", obj[F("user")].as<const char*>());
|
||||||
|
snprintf(mCfg.mqtt.pwd, MQTT_PWD_LEN, "%s", obj[F("pwd")].as<const char*>());
|
||||||
|
snprintf(mCfg.mqtt.topic, MQTT_TOPIC_LEN, "%s", obj[F("topic")].as<const char*>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonLed(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj["0"] = mCfg.led.led0;
|
||||||
|
obj["1"] = mCfg.led.led1;
|
||||||
|
} else {
|
||||||
|
mCfg.led.led0 = obj["0"];
|
||||||
|
mCfg.led.led1 = obj["1"];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonInst(JsonObject obj, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj["en"] = mCfg.inst.enabled;
|
||||||
|
} else {
|
||||||
|
mCfg.inst.enabled = obj["en"];
|
||||||
|
}
|
||||||
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
|
jsonIv(obj["iv"][i], mCfg.inst.iv[i], set);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void jsonIv(JsonObject obj, cfgIv_t cfg, bool set = false) {
|
||||||
|
if(set) {
|
||||||
|
obj["en"] = cfg.enabled;
|
||||||
|
obj["name"] = cfg.name;
|
||||||
|
obj["serial"] = cfg.serial.u64;
|
||||||
|
for(uint8_t i = 0; i < 4; i++) {
|
||||||
|
obj["chPwr"][i] = cfg.chMaxPwr[i];
|
||||||
|
obj["chName"][i] = cfg.chName[i];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cfg.enabled = obj["en"];
|
||||||
|
snprintf(cfg.name, MAX_NAME_LENGTH, "%s", obj[F("name")].as<const char*>());
|
||||||
|
cfg.serial.u64 = obj["serial"];
|
||||||
|
for(uint8_t i = 0; i < 4; i++) {
|
||||||
|
cfg.chMaxPwr[i] = obj["chPwr"][i];
|
||||||
|
snprintf(cfg.chName[i], MAX_NAME_LENGTH, "%s", obj["chName"][i].as<const char*>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
settings_t mCfg;
|
||||||
|
bool mValid;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /*__SETTINGS_H__*/
|
150
src/defines.h
150
src/defines.h
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 35
|
#define VERSION_PATCH 36
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -63,6 +63,11 @@ typedef enum {
|
||||||
RelativPersistent = 257UL // 0x0101
|
RelativPersistent = 257UL // 0x0101
|
||||||
} PowerLimitControlType;
|
} PowerLimitControlType;
|
||||||
|
|
||||||
|
union serial_u {
|
||||||
|
uint64_t u64;
|
||||||
|
uint8_t b[8];
|
||||||
|
};
|
||||||
|
|
||||||
#define MIN_SERIAL_INTERVAL 5
|
#define MIN_SERIAL_INTERVAL 5
|
||||||
#define MIN_SEND_INTERVAL 15
|
#define MIN_SEND_INTERVAL 15
|
||||||
#define MIN_MQTT_INTERVAL 60
|
#define MIN_MQTT_INTERVAL 60
|
||||||
|
@ -78,116 +83,14 @@ typedef enum {
|
||||||
#define SSID_LEN 32
|
#define SSID_LEN 32
|
||||||
#define PWD_LEN 64
|
#define PWD_LEN 64
|
||||||
#define DEVNAME_LEN 16
|
#define DEVNAME_LEN 16
|
||||||
#define CRC_LEN 2 // uint16_t
|
|
||||||
#define DISCLAIMER_LEN 1
|
|
||||||
#define STATIC_IP_LEN 16 // 4x uint32_t
|
|
||||||
#define STATUS_LED_LEN 2 // 2x uint8_t
|
|
||||||
|
|
||||||
#define INV_ADDR_LEN MAX_NUM_INVERTERS * 8 // uint64_t
|
|
||||||
#define INV_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH // char[]
|
|
||||||
#define INV_CH_CH_PWR_LEN MAX_NUM_INVERTERS * 2 * 4 // uint16_t (4 channels)
|
|
||||||
#define INV_CH_CH_NAME_LEN MAX_NUM_INVERTERS * MAX_NAME_LENGTH * 4 // (4 channels)
|
|
||||||
#define INV_INTERVAL_LEN 2 // uint16_t
|
|
||||||
#define INV_MAX_RTRY_LEN 1 // uint8_t
|
|
||||||
#define INV_ENABLED_LEN 1 // uint8_t
|
|
||||||
|
|
||||||
#define CFG_SUN_LEN 9 // 2x float(4+4) + bool(1)
|
|
||||||
|
|
||||||
#define NTP_ADDR_LEN 32 // DNS Name
|
#define NTP_ADDR_LEN 32 // DNS Name
|
||||||
|
|
||||||
#define MQTT_ADDR_LEN 32 // DNS Name
|
#define MQTT_ADDR_LEN 32 // DNS Name
|
||||||
#define MQTT_USER_LEN 16
|
#define MQTT_USER_LEN 16
|
||||||
#define MQTT_PWD_LEN 32
|
#define MQTT_PWD_LEN 32
|
||||||
#define MQTT_TOPIC_LEN 32
|
#define MQTT_TOPIC_LEN 64
|
||||||
#define MQTT_DISCOVERY_PREFIX "homeassistant"
|
|
||||||
#define MQTT_MAX_PACKET_SIZE 384
|
#define MQTT_MAX_PACKET_SIZE 384
|
||||||
#define MQTT_RECONNECT_DELAY 5000
|
|
||||||
|
|
||||||
#pragma pack(push) // push current alignment to stack
|
|
||||||
#pragma pack(1) // set alignment to 1 byte boundary
|
|
||||||
typedef struct {
|
|
||||||
char broker[MQTT_ADDR_LEN];
|
|
||||||
uint16_t port;
|
|
||||||
char user[MQTT_USER_LEN];
|
|
||||||
char pwd[MQTT_PWD_LEN];
|
|
||||||
char topic[MQTT_TOPIC_LEN];
|
|
||||||
} mqttConfig_t;
|
|
||||||
#pragma pack(pop) // restore original alignment from stack
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct {
|
|
||||||
char deviceName[DEVNAME_LEN];
|
|
||||||
|
|
||||||
// wifi
|
|
||||||
char stationSsid[SSID_LEN];
|
|
||||||
char stationPwd[PWD_LEN];
|
|
||||||
} sysConfig_t;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct {
|
|
||||||
uint8_t ip[4]; // ip address
|
|
||||||
uint8_t mask[4]; // sub mask
|
|
||||||
uint8_t dns[4]; // dns
|
|
||||||
uint8_t gateway[4]; // standard gateway
|
|
||||||
} staticIp_t;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct {
|
|
||||||
uint8_t led0; // first led pin
|
|
||||||
uint8_t led1; // second led pin
|
|
||||||
} statusLed_t;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
#pragma pack(push)
|
|
||||||
#pragma pack(1)
|
|
||||||
typedef struct {
|
|
||||||
// protection
|
|
||||||
char password[PWD_LEN];
|
|
||||||
|
|
||||||
// nrf24
|
|
||||||
uint16_t sendInterval;
|
|
||||||
uint8_t maxRetransPerPyld;
|
|
||||||
uint8_t pinCs;
|
|
||||||
uint8_t pinCe;
|
|
||||||
uint8_t pinIrq;
|
|
||||||
uint8_t amplifierPower;
|
|
||||||
|
|
||||||
// Disclaimer
|
|
||||||
bool disclaimer;
|
|
||||||
|
|
||||||
// ntp
|
|
||||||
char ntpAddr[NTP_ADDR_LEN];
|
|
||||||
uint16_t ntpPort;
|
|
||||||
|
|
||||||
// mqtt
|
|
||||||
mqttConfig_t mqtt;
|
|
||||||
|
|
||||||
// sun
|
|
||||||
float sunLat;
|
|
||||||
float sunLon;
|
|
||||||
bool sunDisNightCom; // disable night communication
|
|
||||||
|
|
||||||
// serial
|
|
||||||
uint16_t serialInterval;
|
|
||||||
bool serialShowIv;
|
|
||||||
bool serialDebug;
|
|
||||||
|
|
||||||
// static ip
|
|
||||||
staticIp_t staticIp;
|
|
||||||
|
|
||||||
// status LED(s)
|
|
||||||
statusLed_t led;
|
|
||||||
} config_t;
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t rxFail;
|
uint32_t rxFail;
|
||||||
|
@ -196,41 +99,4 @@ typedef struct {
|
||||||
uint32_t frmCnt;
|
uint32_t frmCnt;
|
||||||
} statistics_t;
|
} statistics_t;
|
||||||
|
|
||||||
|
|
||||||
#define CFG_MQTT_LEN MQTT_ADDR_LEN + 2 + MQTT_USER_LEN + MQTT_PWD_LEN +MQTT_TOPIC_LEN
|
|
||||||
#define CFG_SYS_LEN DEVNAME_LEN + SSID_LEN + PWD_LEN
|
|
||||||
#define CFG_LEN PWD_LEN + 7 + DISCLAIMER_LEN + NTP_ADDR_LEN + 2 + CFG_MQTT_LEN + CFG_SUN_LEN + 4 + STATIC_IP_LEN + STATUS_LED_LEN
|
|
||||||
|
|
||||||
#define ADDR_START 0
|
|
||||||
#define ADDR_CFG_SYS ADDR_START
|
|
||||||
#define ADDR_WIFI_CRC ADDR_CFG_SYS + CFG_SYS_LEN
|
|
||||||
#define ADDR_START_SETTINGS ADDR_WIFI_CRC + CRC_LEN
|
|
||||||
|
|
||||||
#define ADDR_CFG ADDR_START_SETTINGS
|
|
||||||
#define ADDR_CFG_INVERTER ADDR_CFG + CFG_LEN
|
|
||||||
|
|
||||||
#define ADDR_INV_ADDR ADDR_CFG_INVERTER
|
|
||||||
#define ADDR_INV_NAME ADDR_INV_ADDR + INV_ADDR_LEN
|
|
||||||
#define ADDR_INV_CH_PWR ADDR_INV_NAME + INV_NAME_LEN
|
|
||||||
#define ADDR_INV_CH_NAME ADDR_INV_CH_PWR + INV_CH_CH_PWR_LEN
|
|
||||||
#define ADDR_INV_INTERVAL ADDR_INV_CH_NAME + INV_CH_CH_NAME_LEN
|
|
||||||
#define ADDR_INV_MAX_RTRY ADDR_INV_INTERVAL + INV_INTERVAL_LEN
|
|
||||||
#define ADDR_INV_ENABLED ADDR_INV_MAX_RTRY + INV_MAX_RTRY_LEN
|
|
||||||
|
|
||||||
#define ADDR_NEXT ADDR_INV_MAX_RTRY + INV_ENABLED_LEN
|
|
||||||
|
|
||||||
|
|
||||||
#define ADDR_SETTINGS_CRC ADDR_NEXT + 2
|
|
||||||
|
|
||||||
#if(ADDR_SETTINGS_CRC <= ADDR_NEXT)
|
|
||||||
#pragma error "address overlap! (ADDR_SETTINGS_CRC="+ ADDR_SETTINGS_CRC +", ADDR_NEXT="+ ADDR_NEXT +")"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if(ADDR_SETTINGS_CRC >= 4096 - CRC_LEN)
|
|
||||||
#pragma error "EEPROM size exceeded! (ADDR_SETTINGS_CRC="+ ADDR_SETTINGS_CRC +", CRC_LEN="+ CRC_LEN +")"
|
|
||||||
#pragma error "Configure less inverters? (MAX_NUM_INVERTERS=" + MAX_NUM_INVERTERS +")"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif /*__DEFINES_H__*/
|
#endif /*__DEFINES_H__*/
|
||||||
|
|
|
@ -9,13 +9,6 @@
|
||||||
#include "../utils/dbg.h"
|
#include "../utils/dbg.h"
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
|
||||||
union serial_u {
|
|
||||||
uint64_t u64;
|
|
||||||
uint8_t b[8];
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// units
|
// units
|
||||||
enum {UNIT_V = 0, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT, UNIT_VAR, UNIT_NONE};
|
enum {UNIT_V = 0, UNIT_A, UNIT_W, UNIT_WH, UNIT_KWH, UNIT_HZ, UNIT_C, UNIT_PCT, UNIT_VAR, UNIT_NONE};
|
||||||
const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", ""};
|
const char* const units[] = {"V", "A", "W", "Wh", "kWh", "Hz", "°C", "%", "var", ""};
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "hmDefines.h"
|
#include "hmDefines.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include "../config/settings.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* For values which are of interest and not transmitted by the inverter can be
|
* For values which are of interest and not transmitted by the inverter can be
|
||||||
|
@ -104,8 +105,8 @@ const calcFunc_t<T> calcFunctions[] = {
|
||||||
template <class REC_TYP>
|
template <class REC_TYP>
|
||||||
class Inverter {
|
class Inverter {
|
||||||
public:
|
public:
|
||||||
|
cfgIv_t *config; // stored settings
|
||||||
uint8_t id; // unique id
|
uint8_t id; // unique id
|
||||||
char name[MAX_NAME_LENGTH]; // human readable name, eg. "HM-600.1"
|
|
||||||
uint8_t type; // integer which refers to inverter type
|
uint8_t type; // integer which refers to inverter type
|
||||||
uint16_t alarmMesIndex; // Last recorded Alarm Message Index
|
uint16_t alarmMesIndex; // Last recorded Alarm Message Index
|
||||||
uint16_t fwVersion; // Firmware Version from Info Command Request
|
uint16_t fwVersion; // Firmware Version from Info Command Request
|
||||||
|
@ -113,15 +114,12 @@ class Inverter {
|
||||||
float actPowerLimit; // actual power limit
|
float actPowerLimit; // actual power limit
|
||||||
uint8_t devControlCmd; // carries the requested cmd
|
uint8_t devControlCmd; // carries the requested cmd
|
||||||
bool devControlRequest; // true if change needed
|
bool devControlRequest; // true if change needed
|
||||||
serial_u serial; // serial number as on barcode
|
|
||||||
serial_u radioId; // id converted to modbus
|
serial_u radioId; // id converted to modbus
|
||||||
uint8_t channels; // number of PV channels (1-4)
|
uint8_t channels; // number of PV channels (1-4)
|
||||||
record_t<REC_TYP> recordMeas; // structure for measured values
|
record_t<REC_TYP> recordMeas; // structure for measured values
|
||||||
record_t<REC_TYP> recordInfo; // structure for info values
|
record_t<REC_TYP> recordInfo; // structure for info values
|
||||||
record_t<REC_TYP> recordConfig; // structure for system config values
|
record_t<REC_TYP> recordConfig; // structure for system config values
|
||||||
record_t<REC_TYP> recordAlarm; // structure for alarm values
|
record_t<REC_TYP> recordAlarm; // structure for alarm values
|
||||||
uint16_t chMaxPwr[4]; // maximum power of the modules (Wp)
|
|
||||||
char chName[4][MAX_NAME_LENGTH]; // human readable name for channels
|
|
||||||
String lastAlarmMsg;
|
String lastAlarmMsg;
|
||||||
bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null)
|
bool initialized; // needed to check if the inverter was correctly added (ESP32 specific - union types are never null)
|
||||||
|
|
||||||
|
@ -185,8 +183,6 @@ class Inverter {
|
||||||
initAssignment(&recordConfig, SystemConfigPara);
|
initAssignment(&recordConfig, SystemConfigPara);
|
||||||
initAssignment(&recordAlarm, AlarmData);
|
initAssignment(&recordAlarm, AlarmData);
|
||||||
toRadioId();
|
toRadioId();
|
||||||
memset(name, 0, MAX_NAME_LENGTH);
|
|
||||||
memset(chName, 0, MAX_NAME_LENGTH * 4);
|
|
||||||
initialized = true;
|
initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -484,10 +480,10 @@ class Inverter {
|
||||||
void toRadioId(void) {
|
void toRadioId(void) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId"));
|
DPRINTLN(DBG_VERBOSE, F("hmInverter.h:toRadioId"));
|
||||||
radioId.u64 = 0ULL;
|
radioId.u64 = 0ULL;
|
||||||
radioId.b[4] = serial.b[0];
|
radioId.b[4] = config->serial.b[0];
|
||||||
radioId.b[3] = serial.b[1];
|
radioId.b[3] = config->serial.b[1];
|
||||||
radioId.b[2] = serial.b[2];
|
radioId.b[2] = config->serial.b[2];
|
||||||
radioId.b[1] = serial.b[3];
|
radioId.b[1] = config->serial.b[3];
|
||||||
radioId.b[0] = 0x01;
|
radioId.b[0] = 0x01;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -583,8 +579,8 @@ static T calcIrradiation(Inverter<> *iv, uint8_t arg0) {
|
||||||
if(NULL != iv) {
|
if(NULL != iv) {
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC, rec);
|
uint8_t pos = iv->getPosByChFld(arg0, FLD_PDC, rec);
|
||||||
if(iv->chMaxPwr[arg0-1] > 0)
|
if(iv->config->chMaxPwr[arg0-1] > 0)
|
||||||
return iv->getValue(pos, rec) / iv->chMaxPwr[arg0-1] * 100.0f;
|
return iv->getValue(pos, rec) / iv->config->chMaxPwr[arg0-1] * 100.0f;
|
||||||
}
|
}
|
||||||
return 0.0;
|
return 0.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,18 @@ class HmSystem {
|
||||||
Radio.setup(&BufCtrl, ampPwr, irqPin, cePin, csPin);
|
Radio.setup(&BufCtrl, ampPwr, irqPin, cePin, csPin);
|
||||||
}
|
}
|
||||||
|
|
||||||
INVERTERTYPE *addInverter(const char *name, uint64_t serial, uint16_t chMaxPwr[]) {
|
void addInverters(cfgInst_t *config) {
|
||||||
|
Inverter<> *iv;
|
||||||
|
for (uint8_t i = 0; i < MAX_NUM_INVERTERS; i++) {
|
||||||
|
if (0ULL != config->iv[i].serial.u64) {
|
||||||
|
iv = addInverter(&config->iv[i]);
|
||||||
|
if (NULL != iv)
|
||||||
|
DPRINTLN(DBG_INFO, "added inverter " + String(iv->config->serial.u64, HEX));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
INVERTERTYPE *addInverter(cfgIv_t *config) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:addInverter"));
|
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:addInverter"));
|
||||||
if(MAX_INVERTER <= mNumInv) {
|
if(MAX_INVERTER <= mNumInv) {
|
||||||
DPRINT(DBG_WARN, F("max number of inverters reached!"));
|
DPRINT(DBG_WARN, F("max number of inverters reached!"));
|
||||||
|
@ -45,18 +56,17 @@ class HmSystem {
|
||||||
}
|
}
|
||||||
INVERTERTYPE *p = &mInverter[mNumInv];
|
INVERTERTYPE *p = &mInverter[mNumInv];
|
||||||
p->id = mNumInv;
|
p->id = mNumInv;
|
||||||
p->serial.u64 = serial;
|
p->config = config;
|
||||||
memcpy(p->chMaxPwr, chMaxPwr, (4*2));
|
DPRINT(DBG_VERBOSE, "SERIAL: " + String(p->config->serial.b[5], HEX));
|
||||||
DPRINT(DBG_VERBOSE, "SERIAL: " + String(p->serial.b[5], HEX));
|
DPRINTLN(DBG_VERBOSE, " " + String(p->config->serial.b[4], HEX));
|
||||||
DPRINTLN(DBG_VERBOSE, " " + String(p->serial.b[4], HEX));
|
if(p->config->serial.b[5] == 0x11) {
|
||||||
if(p->serial.b[5] == 0x11) {
|
switch(p->config->serial.b[4]) {
|
||||||
switch(p->serial.b[4]) {
|
|
||||||
case 0x21: p->type = INV_TYPE_1CH; break;
|
case 0x21: p->type = INV_TYPE_1CH; break;
|
||||||
case 0x41: p->type = INV_TYPE_2CH; break;
|
case 0x41: p->type = INV_TYPE_2CH; break;
|
||||||
case 0x61: p->type = INV_TYPE_4CH; break;
|
case 0x61: p->type = INV_TYPE_4CH; break;
|
||||||
default:
|
default:
|
||||||
DPRINT(DBG_ERROR, F("unknown inverter type: 11"));
|
DPRINT(DBG_ERROR, F("unknown inverter type: 11"));
|
||||||
DPRINTLN(DBG_ERROR, String(p->serial.b[4], HEX));
|
DPRINTLN(DBG_ERROR, String(p->config->serial.b[4], HEX));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,8 +74,6 @@ class HmSystem {
|
||||||
DPRINTLN(DBG_ERROR, F("inverter type can't be detected!"));
|
DPRINTLN(DBG_ERROR, F("inverter type can't be detected!"));
|
||||||
|
|
||||||
p->init();
|
p->init();
|
||||||
uint8_t len = (uint8_t)strlen(name);
|
|
||||||
strncpy(p->name, name, (len > MAX_NAME_LENGTH) ? MAX_NAME_LENGTH : len);
|
|
||||||
|
|
||||||
mNumInv ++;
|
mNumInv ++;
|
||||||
return p;
|
return p;
|
||||||
|
@ -76,10 +84,10 @@ class HmSystem {
|
||||||
INVERTERTYPE *p;
|
INVERTERTYPE *p;
|
||||||
for(uint8_t i = 0; i < mNumInv; i++) {
|
for(uint8_t i = 0; i < mNumInv; i++) {
|
||||||
p = &mInverter[i];
|
p = &mInverter[i];
|
||||||
if((p->serial.b[3] == buf[0])
|
if((p->config->serial.b[3] == buf[0])
|
||||||
&& (p->serial.b[2] == buf[1])
|
&& (p->config->serial.b[2] == buf[1])
|
||||||
&& (p->serial.b[1] == buf[2])
|
&& (p->config->serial.b[1] == buf[2])
|
||||||
&& (p->serial.b[0] == buf[3]))
|
&& (p->config->serial.b[0] == buf[3]))
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -89,7 +97,7 @@ class HmSystem {
|
||||||
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:getInverterByPos"));
|
DPRINTLN(DBG_VERBOSE, F("hmSystem.h:getInverterByPos"));
|
||||||
if(pos >= MAX_INVERTER)
|
if(pos >= MAX_INVERTER)
|
||||||
return NULL;
|
return NULL;
|
||||||
else if((mInverter[pos].initialized && mInverter[pos].serial.u64 != 0ULL) || false == check)
|
else if((mInverter[pos].initialized && mInverter[pos].config->serial.u64 != 0ULL) || false == check)
|
||||||
return &mInverter[pos];
|
return &mInverter[pos];
|
||||||
else
|
else
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -10,12 +10,13 @@
|
||||||
|
|
||||||
[platformio]
|
[platformio]
|
||||||
src_dir = .
|
src_dir = .
|
||||||
|
include_dir = .
|
||||||
|
|
||||||
[env]
|
[env]
|
||||||
framework = arduino
|
framework = arduino
|
||||||
|
board_build.filesystem = littlefs
|
||||||
|
|
||||||
build_flags =
|
;build_flags =
|
||||||
-include "config.h"
|
|
||||||
; ;;;;; Possible Debug options ;;;;;;
|
; ;;;;; Possible Debug options ;;;;;;
|
||||||
; https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level
|
; https://docs.platformio.org/en/latest/platforms/espressif8266.html#debug-level
|
||||||
;-DDEBUG_ESP_PORT=Serial
|
;-DDEBUG_ESP_PORT=Serial
|
||||||
|
@ -43,6 +44,7 @@ lib_deps =
|
||||||
;esp8266/SPI
|
;esp8266/SPI
|
||||||
;esp8266/Ticker
|
;esp8266/Ticker
|
||||||
|
|
||||||
|
|
||||||
[env:esp8266-release]
|
[env:esp8266-release]
|
||||||
platform = espressif8266
|
platform = espressif8266
|
||||||
board = esp12e
|
board = esp12e
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
// 2022 Ahoy, https://ahoydtu.de
|
||||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
// 2022 Ahoy, https://ahoydtu.de
|
||||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -124,7 +124,7 @@
|
||||||
});
|
});
|
||||||
document.getElementById("scroll").addEventListener("click", function() {
|
document.getElementById("scroll").addEventListener("click", function() {
|
||||||
mAutoScroll = !mAutoScroll;
|
mAutoScroll = !mAutoScroll;
|
||||||
this.value = (mAutoScroll) ? "autoscroll" : "manual scoll";
|
this.value = (mAutoScroll) ? "autoscroll" : "manual scroll";
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!!window.EventSource) {
|
if (!!window.EventSource) {
|
||||||
|
|
|
@ -67,8 +67,10 @@
|
||||||
<input type="text" name="ipAddr" class="text" maxlength="15" />
|
<input type="text" name="ipAddr" class="text" maxlength="15" />
|
||||||
<label for="ipMask">Submask</label>
|
<label for="ipMask">Submask</label>
|
||||||
<input type="text" name="ipMask" class="text" maxlength="15" />
|
<input type="text" name="ipMask" class="text" maxlength="15" />
|
||||||
<label for="ipDns">DNS</label>
|
<label for="ipDns1">DNS 1</label>
|
||||||
<input type="text" name="ipDns" class="text" maxlength="15" />
|
<input type="text" name="ipDns1" class="text" maxlength="15" />
|
||||||
|
<label for="ipDns2">DNS 2</label>
|
||||||
|
<input type="text" name="ipDns2" class="text" maxlength="15" />
|
||||||
<label for="ipGateway">Gateway</label>
|
<label for="ipGateway">Gateway</label>
|
||||||
<input type="text" name="ipGateway" class="text" maxlength="15" />
|
<input type="text" name="ipGateway" class="text" maxlength="15" />
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
@ -332,7 +334,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
function parseStaticIp(obj) {
|
function parseStaticIp(obj) {
|
||||||
for(var i of [["ipAddr", "ip"], ["ipMask", "mask"], ["ipDns", "dns"], ["ipGateway", "gateway"]])
|
for(var i of [["ipAddr", "ip"], ["ipMask", "mask"], ["ipDns1", "dns1"], ["ipDns2", "dns2"], ["ipGateway", "gateway"]])
|
||||||
if(null != obj[i[1]])
|
if(null != obj[i[1]])
|
||||||
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
document.getElementsByName(i[0])[0].value = obj[i[1]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
|
// 2022 Ahoy, https://ahoydtu.de
|
||||||
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -21,9 +21,9 @@
|
||||||
#include "../utils/ahoyTimer.h"
|
#include "../utils/ahoyTimer.h"
|
||||||
#include "../config/config.h"
|
#include "../config/config.h"
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
|
#include <ArduinoJson.h>
|
||||||
#include "../defines.h"
|
#include "../defines.h"
|
||||||
#include "../hm/hmSystem.h"
|
#include "../hm/hmSystem.h"
|
||||||
#include <ArduinoJson.h>
|
|
||||||
|
|
||||||
template<class HMSYSTEM>
|
template<class HMSYSTEM>
|
||||||
class mqtt {
|
class mqtt {
|
||||||
|
@ -34,18 +34,16 @@ class mqtt {
|
||||||
|
|
||||||
mLastReconnect = 0;
|
mLastReconnect = 0;
|
||||||
mTxCnt = 0;
|
mTxCnt = 0;
|
||||||
|
|
||||||
memset(mDevName, 0, DEVNAME_LEN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~mqtt() { }
|
~mqtt() { }
|
||||||
|
|
||||||
void setup(mqttConfig_t *cfg, const char *devname, const char *version, HMSYSTEM *sys, uint32_t *utcTs) {
|
void setup(cfgMqtt_t *cfg, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("mqtt.h:setup"));
|
DPRINTLN(DBG_VERBOSE, F("mqtt.h:setup"));
|
||||||
mAddressSet = true;
|
mAddressSet = true;
|
||||||
|
|
||||||
snprintf(mDevName, DEVNAME_LEN, "%s", devname);
|
|
||||||
mCfg = cfg;
|
mCfg = cfg;
|
||||||
|
mDevName = devName;
|
||||||
mSys = sys;
|
mSys = sys;
|
||||||
mUtcTimestamp = utcTs;
|
mUtcTimestamp = utcTs;
|
||||||
|
|
||||||
|
@ -55,7 +53,7 @@ class mqtt {
|
||||||
setCallback(std::bind(&mqtt<HMSYSTEM>::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
setCallback(std::bind(&mqtt<HMSYSTEM>::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
|
||||||
sendMsg("version", version);
|
sendMsg("version", version);
|
||||||
sendMsg("device", devname);
|
sendMsg("device", devName);
|
||||||
sendMsg("uptime", "0");
|
sendMsg("uptime", "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,8 +74,8 @@ class mqtt {
|
||||||
void sendMsg(const char *topic, const char *msg) {
|
void sendMsg(const char *topic, const char *msg) {
|
||||||
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:sendMsg"));
|
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:sendMsg"));
|
||||||
if(mAddressSet) {
|
if(mAddressSet) {
|
||||||
char top[64];
|
char top[66];
|
||||||
snprintf(top, 64, "%s/%s", mCfg->topic, topic);
|
snprintf(top, 66, "%s/%s", mCfg->topic, topic);
|
||||||
sendMsg2(top, msg, false);
|
sendMsg2(top, msg, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,22 +116,22 @@ class mqtt {
|
||||||
if (NULL != iv) {
|
if (NULL != iv) {
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
DynamicJsonDocument deviceDoc(128);
|
DynamicJsonDocument deviceDoc(128);
|
||||||
deviceDoc["name"] = iv->name;
|
deviceDoc["name"] = iv->config->name;
|
||||||
deviceDoc["ids"] = String(iv->serial.u64, HEX);
|
deviceDoc["ids"] = String(iv->config->serial.u64, HEX);
|
||||||
deviceDoc["cu"] = F("http://") + String(WiFi.localIP().toString());
|
deviceDoc["cu"] = F("http://") + String(WiFi.localIP().toString());
|
||||||
deviceDoc["mf"] = "Hoymiles";
|
deviceDoc["mf"] = "Hoymiles";
|
||||||
deviceDoc["mdl"] = iv->name;
|
deviceDoc["mdl"] = iv->config->name;
|
||||||
JsonObject deviceObj = deviceDoc.as<JsonObject>();
|
JsonObject deviceObj = deviceDoc.as<JsonObject>();
|
||||||
DynamicJsonDocument doc(384);
|
DynamicJsonDocument doc(384);
|
||||||
|
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
if (rec->assign[i].ch == CH0) {
|
if (rec->assign[i].ch == CH0) {
|
||||||
snprintf(name, 32, "%s %s", iv->name, iv->getFieldName(i, rec));
|
snprintf(name, 32, "%s %s", iv->config->name, iv->getFieldName(i, rec));
|
||||||
} else {
|
} else {
|
||||||
snprintf(name, 32, "%s CH%d %s", iv->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
snprintf(name, 32, "%s CH%d %s", iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||||
}
|
}
|
||||||
snprintf(stateTopic, 64, "%s/%s/ch%d/%s", topic, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
snprintf(stateTopic, 64, "%s/%s/ch%d/%s", topic, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||||
snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
snprintf(discoveryTopic, 64, "%s/sensor/%s/ch%d_%s/config", MQTT_DISCOVERY_PREFIX, iv->config->name, rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||||
snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec));
|
snprintf(uniq_id, 32, "ch%d_%s", rec->assign[i].ch, iv->getFieldName(i, rec));
|
||||||
const char *devCls = getFieldDeviceClass(rec->assign[i].fieldId);
|
const char *devCls = getFieldDeviceClass(rec->assign[i].fieldId);
|
||||||
const char *stateCls = getFieldStateClass(rec->assign[i].fieldId);
|
const char *stateCls = getFieldStateClass(rec->assign[i].fieldId);
|
||||||
|
@ -141,7 +139,7 @@ class mqtt {
|
||||||
doc["name"] = name;
|
doc["name"] = name;
|
||||||
doc["stat_t"] = stateTopic;
|
doc["stat_t"] = stateTopic;
|
||||||
doc["unit_of_meas"] = iv->getUnit(i, rec);
|
doc["unit_of_meas"] = iv->getUnit(i, rec);
|
||||||
doc["uniq_id"] = String(iv->serial.u64, HEX) + "_" + uniq_id;
|
doc["uniq_id"] = String(iv->config->serial.u64, HEX) + "_" + uniq_id;
|
||||||
doc["dev"] = deviceObj;
|
doc["dev"] = deviceObj;
|
||||||
doc["exp_aft"] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
doc["exp_aft"] = MQTT_INTERVAL + 5; // add 5 sec if connection is bad or ESP too slow @TODO: stimmt das wirklich als expire!?
|
||||||
if (devCls != NULL)
|
if (devCls != NULL)
|
||||||
|
@ -248,7 +246,7 @@ class mqtt {
|
||||||
if (MQTT_STATUS_AVAIL_PROD == status)
|
if (MQTT_STATUS_AVAIL_PROD == status)
|
||||||
status = MQTT_STATUS_AVAIL_NOT_PROD;
|
status = MQTT_STATUS_AVAIL_NOT_PROD;
|
||||||
}
|
}
|
||||||
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->name);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available_text", iv->config->name);
|
||||||
snprintf(val, 40, "%s%s%s%s",
|
snprintf(val, 40, "%s%s%s%s",
|
||||||
(status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not yet " : "",
|
(status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "not yet " : "",
|
||||||
"available and ",
|
"available and ",
|
||||||
|
@ -257,11 +255,11 @@ class mqtt {
|
||||||
);
|
);
|
||||||
sendMsg(topic, val);
|
sendMsg(topic, val);
|
||||||
|
|
||||||
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->name);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
|
||||||
snprintf(val, 40, "%d", status);
|
snprintf(val, 40, "%d", status);
|
||||||
sendMsg(topic, val);
|
sendMsg(topic, val);
|
||||||
|
|
||||||
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->name);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->name);
|
||||||
snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000);
|
snprintf(val, 40, "%i", iv->getLastTs(rec) * 1000);
|
||||||
sendMsg(topic, val);
|
sendMsg(topic, val);
|
||||||
}
|
}
|
||||||
|
@ -269,7 +267,7 @@ class mqtt {
|
||||||
// data
|
// data
|
||||||
if(iv->isAvailable(*mUtcTimestamp, rec)) {
|
if(iv->isAvailable(*mUtcTimestamp, rec)) {
|
||||||
for (uint8_t i = 0; i < rec->length; i++) {
|
for (uint8_t i = 0; i < rec->length; i++) {
|
||||||
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/ch%d/%s", iv->config->name, rec->assign[i].ch, fields[rec->assign[i].fieldId]);
|
||||||
snprintf(val, 40, "%.3f", iv->getValue(i, rec));
|
snprintf(val, 40, "%.3f", iv->getValue(i, rec));
|
||||||
sendMsg(topic, val);
|
sendMsg(topic, val);
|
||||||
|
|
||||||
|
@ -435,8 +433,8 @@ class mqtt {
|
||||||
uint32_t *mUtcTimestamp;
|
uint32_t *mUtcTimestamp;
|
||||||
|
|
||||||
bool mAddressSet;
|
bool mAddressSet;
|
||||||
mqttConfig_t *mCfg;
|
cfgMqtt_t *mCfg;
|
||||||
char mDevName[DEVNAME_LEN];
|
const char *mDevName;
|
||||||
uint32_t mLastReconnect;
|
uint32_t mLastReconnect;
|
||||||
uint32_t mTxCnt;
|
uint32_t mTxCnt;
|
||||||
std::queue<uint8_t> mSendList;
|
std::queue<uint8_t> mSendList;
|
||||||
|
|
104
src/web/web.cpp
104
src/web/web.cpp
|
@ -26,15 +26,14 @@
|
||||||
const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1"};
|
const char* const pinArgNames[] = {"pinCs", "pinCe", "pinIrq", "pinLed0", "pinLed1"};
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
web::web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) {
|
web::web(app *main, settings_t *config, statistics_t *stat, char version[]) {
|
||||||
mMain = main;
|
mMain = main;
|
||||||
mSysCfg = sysCfg;
|
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mStat = stat;
|
mStat = stat;
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
mWeb = new AsyncWebServer(80);
|
mWeb = new AsyncWebServer(80);
|
||||||
mEvts = new AsyncEventSource("/events");
|
mEvts = new AsyncEventSource("/events");
|
||||||
mApi = new webApi(mWeb, main, sysCfg, config, stat, version);
|
mApi = new webApi(mWeb, main, config, stat, version);
|
||||||
|
|
||||||
mProtected = true;
|
mProtected = true;
|
||||||
mLogoutTimeout = 0;
|
mLogoutTimeout = 0;
|
||||||
|
@ -151,7 +150,7 @@ void web::onLogin(AsyncWebServerRequest *request) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("onLogin"));
|
DPRINTLN(DBG_VERBOSE, F("onLogin"));
|
||||||
|
|
||||||
if(request->args() > 0) {
|
if(request->args() > 0) {
|
||||||
if(String(request->arg("pwd")) == String(mConfig->password)) {
|
if(String(request->arg("pwd")) == String(mConfig->sys.adminPwd)) {
|
||||||
mProtected = false;
|
mProtected = false;
|
||||||
request->redirect("/");
|
request->redirect("/");
|
||||||
}
|
}
|
||||||
|
@ -260,7 +259,7 @@ void web::showErase(AsyncWebServerRequest *request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
DPRINTLN(DBG_VERBOSE, F("showErase"));
|
DPRINTLN(DBG_VERBOSE, F("showErase"));
|
||||||
mMain->eraseSettings();
|
mMain->eraseSettings(false);
|
||||||
onReboot(request);
|
onReboot(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,9 +276,11 @@ void web::showFactoryRst(AsyncWebServerRequest *request) {
|
||||||
int refresh = 3;
|
int refresh = 3;
|
||||||
if(request->args() > 0) {
|
if(request->args() > 0) {
|
||||||
if(request->arg("reset").toInt() == 1) {
|
if(request->arg("reset").toInt() == 1) {
|
||||||
mMain->eraseSettings(true);
|
|
||||||
content = F("factory reset: success\n\nrebooting ... ");
|
|
||||||
refresh = 10;
|
refresh = 10;
|
||||||
|
if(mMain->eraseSettings(true))
|
||||||
|
content = F("factory reset: success\n\nrebooting ... ");
|
||||||
|
else
|
||||||
|
content = F("factory reset: failed\n\nrebooting ... ");
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
content = F("factory reset: aborted");
|
content = F("factory reset: aborted");
|
||||||
|
@ -328,48 +329,52 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
// general
|
// general
|
||||||
if(request->arg("ssid") != "")
|
if(request->arg("ssid") != "")
|
||||||
request->arg("ssid").toCharArray(mSysCfg->stationSsid, SSID_LEN);
|
request->arg("ssid").toCharArray(mConfig->sys.stationSsid, SSID_LEN);
|
||||||
if(request->arg("pwd") != "{PWD}")
|
if(request->arg("pwd") != "{PWD}")
|
||||||
request->arg("pwd").toCharArray(mSysCfg->stationPwd, PWD_LEN);
|
request->arg("pwd").toCharArray(mConfig->sys.stationPwd, PWD_LEN);
|
||||||
if(request->arg("device") != "")
|
if(request->arg("device") != "")
|
||||||
request->arg("device").toCharArray(mSysCfg->deviceName, DEVNAME_LEN);
|
request->arg("device").toCharArray(mConfig->sys.deviceName, DEVNAME_LEN);
|
||||||
if(request->arg("adminpwd") != "{PWD}") {
|
if(request->arg("adminpwd") != "{PWD}") {
|
||||||
request->arg("adminpwd").toCharArray(mConfig->password, PWD_LEN);
|
request->arg("adminpwd").toCharArray(mConfig->sys.adminPwd, PWD_LEN);
|
||||||
mProtected = (strlen(mConfig->password) > 0);
|
mProtected = (strlen(mConfig->sys.adminPwd) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// static ip
|
// static ip
|
||||||
if(request->arg("ipAddr") != "") {
|
if(request->arg("ipAddr") != "") {
|
||||||
request->arg("ipAddr").toCharArray(buf, SSID_LEN);
|
request->arg("ipAddr").toCharArray(buf, SSID_LEN);
|
||||||
ip2Arr(mConfig->staticIp.ip, buf);
|
ip2Arr(mConfig->sys.ip.ip, buf);
|
||||||
if(request->arg("ipMask") != "") {
|
if(request->arg("ipMask") != "") {
|
||||||
request->arg("ipMask").toCharArray(buf, SSID_LEN);
|
request->arg("ipMask").toCharArray(buf, SSID_LEN);
|
||||||
ip2Arr(mConfig->staticIp.mask, buf);
|
ip2Arr(mConfig->sys.ip.mask, buf);
|
||||||
}
|
}
|
||||||
if(request->arg("ipDns") != "") {
|
if(request->arg("ipDns1") != "") {
|
||||||
request->arg("ipDns").toCharArray(buf, SSID_LEN);
|
request->arg("ipDns1").toCharArray(buf, SSID_LEN);
|
||||||
ip2Arr(mConfig->staticIp.dns, buf);
|
ip2Arr(mConfig->sys.ip.dns1, buf);
|
||||||
|
}
|
||||||
|
if(request->arg("ipDns2") != "") {
|
||||||
|
request->arg("ipDns2").toCharArray(buf, SSID_LEN);
|
||||||
|
ip2Arr(mConfig->sys.ip.dns2, buf);
|
||||||
}
|
}
|
||||||
if(request->arg("ipGateway") != "") {
|
if(request->arg("ipGateway") != "") {
|
||||||
request->arg("ipGateway").toCharArray(buf, SSID_LEN);
|
request->arg("ipGateway").toCharArray(buf, SSID_LEN);
|
||||||
ip2Arr(mConfig->staticIp.gateway, buf);
|
ip2Arr(mConfig->sys.ip.gateway, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
memset(&mConfig->staticIp, 0, sizeof(staticIp_t));
|
memset(&mConfig->sys.ip.ip, 0, 4);
|
||||||
|
|
||||||
|
|
||||||
// inverter
|
// inverter
|
||||||
Inverter<> *iv;
|
/*Inverter<> *iv;
|
||||||
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
for(uint8_t i = 0; i < MAX_NUM_INVERTERS; i ++) {
|
||||||
iv = mMain->mSys->getInverterByPos(i, false);
|
iv = mMain->mSys->getInverterByPos(i, false);
|
||||||
// address
|
// address
|
||||||
request->arg("inv" + String(i) + "Addr").toCharArray(buf, 20);
|
request->arg("inv" + String(i) + "Addr").toCharArray(buf, 20);
|
||||||
if(strlen(buf) == 0)
|
if(strlen(buf) == 0)
|
||||||
memset(buf, 0, 20);
|
memset(buf, 0, 20);
|
||||||
iv->serial.u64 = mMain->Serial2u64(buf);
|
iv->config->serial.u64 = mMain->Serial2u64(buf);
|
||||||
switch(iv->serial.b[4]) {
|
switch(iv->config->serial.b[4]) {
|
||||||
case 0x21: iv->type = INV_TYPE_1CH; iv->channels = 1; break;
|
case 0x21: iv->type = INV_TYPE_1CH; iv->channels = 1; break;
|
||||||
case 0x41: iv->type = INV_TYPE_2CH; iv->channels = 2; break;
|
case 0x41: iv->type = INV_TYPE_2CH; iv->channels = 2; break;
|
||||||
case 0x61: iv->type = INV_TYPE_4CH; iv->channels = 4; break;
|
case 0x61: iv->type = INV_TYPE_4CH; iv->channels = 4; break;
|
||||||
|
@ -377,59 +382,53 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// name
|
// name
|
||||||
request->arg("inv" + String(i) + "Name").toCharArray(iv->name, MAX_NAME_LENGTH);
|
request->arg("inv" + String(i) + "Name").toCharArray(iv->config->name, MAX_NAME_LENGTH);
|
||||||
|
|
||||||
// max channel power / name
|
// max channel power / name
|
||||||
for(uint8_t j = 0; j < 4; j++) {
|
for(uint8_t j = 0; j < 4; j++) {
|
||||||
iv->chMaxPwr[j] = request->arg("inv" + String(i) + "ModPwr" + String(j)).toInt() & 0xffff;
|
iv->config->chMaxPwr[j] = request->arg("inv" + String(i) + "ModPwr" + String(j)).toInt() & 0xffff;
|
||||||
request->arg("inv" + String(i) + "ModName" + String(j)).toCharArray(iv->chName[j], MAX_NAME_LENGTH);
|
request->arg("inv" + String(i) + "ModName" + String(j)).toCharArray(iv->config->chName[j], MAX_NAME_LENGTH);
|
||||||
}
|
}
|
||||||
iv->initialized = true;
|
iv->initialized = true;
|
||||||
}
|
}*/
|
||||||
if(request->arg("invInterval") != "")
|
if(request->arg("invInterval") != "")
|
||||||
mConfig->sendInterval = request->arg("invInterval").toInt();
|
mConfig->nrf.sendInterval = request->arg("invInterval").toInt();
|
||||||
if(request->arg("invRetry") != "")
|
if(request->arg("invRetry") != "")
|
||||||
mConfig->maxRetransPerPyld = request->arg("invRetry").toInt();
|
mConfig->nrf.maxRetransPerPyld = request->arg("invRetry").toInt();
|
||||||
|
|
||||||
// Disclaimer
|
|
||||||
if(request->arg("disclaimer") != "")
|
|
||||||
mConfig->disclaimer = strcmp("true", request->arg("disclaimer").c_str()) == 0 ? true : false;
|
|
||||||
DPRINTLN(DBG_INFO, request->arg("disclaimer").c_str());
|
|
||||||
|
|
||||||
// pinout
|
// pinout
|
||||||
uint8_t pin;
|
uint8_t pin;
|
||||||
for(uint8_t i = 0; i < 5; i ++) {
|
for(uint8_t i = 0; i < 5; i ++) {
|
||||||
pin = request->arg(String(pinArgNames[i])).toInt();
|
pin = request->arg(String(pinArgNames[i])).toInt();
|
||||||
switch(i) {
|
switch(i) {
|
||||||
default: mConfig->pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break;
|
default: mConfig->nrf.pinCs = ((pin != 0xff) ? pin : DEF_CS_PIN); break;
|
||||||
case 1: mConfig->pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break;
|
case 1: mConfig->nrf.pinCe = ((pin != 0xff) ? pin : DEF_CE_PIN); break;
|
||||||
case 2: mConfig->pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break;
|
case 2: mConfig->nrf.pinIrq = ((pin != 0xff) ? pin : DEF_IRQ_PIN); break;
|
||||||
case 3: mConfig->led.led0 = pin; break;
|
case 3: mConfig->led.led0 = pin; break;
|
||||||
case 4: mConfig->led.led1 = pin; break;
|
case 4: mConfig->led.led1 = pin; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// nrf24 amplifier power
|
// nrf24 amplifier power
|
||||||
mConfig->amplifierPower = request->arg("rf24Power").toInt() & 0x03;
|
mConfig->nrf.amplifierPower = request->arg("rf24Power").toInt() & 0x03;
|
||||||
|
|
||||||
// ntp
|
// ntp
|
||||||
if(request->arg("ntpAddr") != "") {
|
if(request->arg("ntpAddr") != "") {
|
||||||
request->arg("ntpAddr").toCharArray(mConfig->ntpAddr, NTP_ADDR_LEN);
|
request->arg("ntpAddr").toCharArray(mConfig->ntp.addr, NTP_ADDR_LEN);
|
||||||
mConfig->ntpPort = request->arg("ntpPort").toInt() & 0xffff;
|
mConfig->ntp.port = request->arg("ntpPort").toInt() & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
// sun
|
// sun
|
||||||
if(request->arg("sunLat") == "" || (request->arg("sunLon") == "")) {
|
if(request->arg("sunLat") == "" || (request->arg("sunLon") == "")) {
|
||||||
mConfig->sunLat = 0.0;
|
mConfig->sun.lat = 0.0;
|
||||||
mConfig->sunLon = 0.0;
|
mConfig->sun.lon = 0.0;
|
||||||
mConfig->sunDisNightCom = false;
|
mConfig->sun.disNightCom = false;
|
||||||
} else {
|
} else {
|
||||||
mConfig->sunLat = request->arg("sunLat").toFloat();
|
mConfig->sun.lat = request->arg("sunLat").toFloat();
|
||||||
mConfig->sunLon = request->arg("sunLon").toFloat();
|
mConfig->sun.lon = request->arg("sunLon").toFloat();
|
||||||
mConfig->sunDisNightCom = (request->arg("sunDisNightCom") == "on");
|
mConfig->sun.disNightCom = (request->arg("sunDisNightCom") == "on");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// mqtt
|
// mqtt
|
||||||
if(request->arg("mqttAddr") != "") {
|
if(request->arg("mqttAddr") != "") {
|
||||||
String addr = request->arg("mqttAddr");
|
String addr = request->arg("mqttAddr");
|
||||||
|
@ -444,15 +443,14 @@ void web::showSave(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
// serial console
|
// serial console
|
||||||
if(request->arg("serIntvl") != "") {
|
if(request->arg("serIntvl") != "") {
|
||||||
mConfig->serialInterval = request->arg("serIntvl").toInt() & 0xffff;
|
mConfig->serial.interval = request->arg("serIntvl").toInt() & 0xffff;
|
||||||
|
|
||||||
mConfig->serialDebug = (request->arg("serDbg") == "on");
|
mConfig->serial.debug = (request->arg("serDbg") == "on");
|
||||||
mConfig->serialShowIv = (request->arg("serEn") == "on");
|
mConfig->serial.showIv = (request->arg("serEn") == "on");
|
||||||
// Needed to log TX buffers to serial console
|
// Needed to log TX buffers to serial console
|
||||||
mMain->mSys->Radio.mSerialDebug = mConfig->serialDebug;
|
mMain->mSys->Radio.mSerialDebug = mConfig->serial.debug;
|
||||||
}
|
}
|
||||||
|
mMain->saveSettings();
|
||||||
mMain->saveValues();
|
|
||||||
|
|
||||||
if(request->arg("reboot") == "on")
|
if(request->arg("reboot") == "on")
|
||||||
onReboot(request);
|
onReboot(request);
|
||||||
|
@ -701,7 +699,7 @@ void web::showMetrics(void) {
|
||||||
String metrics;
|
String metrics;
|
||||||
char headline[80];
|
char headline[80];
|
||||||
|
|
||||||
snprintf(headline, 80, "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mVersion, mSysCfg->deviceName);
|
snprintf(headline, 80, "ahoy_solar_info{version=\"%s\",image=\"\",devicename=\"%s\"} 1", mVersion, mconfig->sys.deviceName);
|
||||||
metrics += "# TYPE ahoy_solar_info gauge\n" + String(headline) + "\n";
|
metrics += "# TYPE ahoy_solar_info gauge\n" + String(headline) + "\n";
|
||||||
|
|
||||||
for(uint8_t id = 0; id < mMain->mSys->getNumInverters(); id++) {
|
for(uint8_t id = 0; id < mMain->mSys->getNumInverters(); id++) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ class webApi;
|
||||||
|
|
||||||
class web {
|
class web {
|
||||||
public:
|
public:
|
||||||
web(app *main, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]);
|
web(app *main, settings_t *config, statistics_t *stat, char version[]);
|
||||||
~web() {}
|
~web() {}
|
||||||
|
|
||||||
void setup(void);
|
void setup(void);
|
||||||
|
@ -85,8 +85,7 @@ class web {
|
||||||
bool mProtected;
|
bool mProtected;
|
||||||
uint32_t mLogoutTimeout;
|
uint32_t mLogoutTimeout;
|
||||||
|
|
||||||
config_t *mConfig;
|
settings_t *mConfig;
|
||||||
sysConfig_t *mSysCfg;
|
|
||||||
statistics_t *mStat;
|
statistics_t *mStat;
|
||||||
char *mVersion;
|
char *mVersion;
|
||||||
app *mMain;
|
app *mMain;
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
#include "webApi.h"
|
#include "webApi.h"
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
webApi::webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]) {
|
webApi::webApi(AsyncWebServer *srv, app *app, settings_t *config, statistics_t *stat, char version[]) {
|
||||||
mSrv = srv;
|
mSrv = srv;
|
||||||
mApp = app;
|
mApp = app;
|
||||||
mSysCfg = sysCfg;
|
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
mStat = stat;
|
mStat = stat;
|
||||||
mVersion = version;
|
mVersion = version;
|
||||||
|
@ -143,8 +142,8 @@ void webApi::onDwnldSetup(AsyncWebServerRequest *request) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getSysInfo(JsonObject obj) {
|
void webApi::getSysInfo(JsonObject obj) {
|
||||||
obj[F("ssid")] = mSysCfg->stationSsid;
|
obj[F("ssid")] = mConfig->sys.stationSsid;
|
||||||
obj[F("device_name")] = mSysCfg->deviceName;
|
obj[F("device_name")] = mConfig->sys.deviceName;
|
||||||
obj[F("version")] = String(mVersion);
|
obj[F("version")] = String(mVersion);
|
||||||
obj[F("build")] = String(AUTO_GIT_HASH);
|
obj[F("build")] = String(AUTO_GIT_HASH);
|
||||||
obj[F("ts_uptime")] = mApp->getUptime();
|
obj[F("ts_uptime")] = mApp->getUptime();
|
||||||
|
@ -153,8 +152,7 @@ void webApi::getSysInfo(JsonObject obj) {
|
||||||
obj[F("ts_sunset")] = mApp->getSunset();
|
obj[F("ts_sunset")] = mApp->getSunset();
|
||||||
obj[F("ts_sun_upd")] = mApp->getLatestSunTimestamp();
|
obj[F("ts_sun_upd")] = mApp->getLatestSunTimestamp();
|
||||||
obj[F("wifi_rssi")] = WiFi.RSSI();
|
obj[F("wifi_rssi")] = WiFi.RSSI();
|
||||||
obj[F("disclaimer")] = mConfig->disclaimer;
|
obj[F("pwd_set")] = (strlen(mConfig->sys.adminPwd) > 0);
|
||||||
obj[F("pwd_set")] = (strlen(mConfig->password) > 0);
|
|
||||||
#if defined(ESP32)
|
#if defined(ESP32)
|
||||||
obj[F("esp_type")] = F("ESP32");
|
obj[F("esp_type")] = F("ESP32");
|
||||||
#else
|
#else
|
||||||
|
@ -221,19 +219,19 @@ void webApi::getInverterList(JsonObject obj) {
|
||||||
if(NULL != iv) {
|
if(NULL != iv) {
|
||||||
JsonObject obj2 = invArr.createNestedObject();
|
JsonObject obj2 = invArr.createNestedObject();
|
||||||
obj2[F("id")] = i;
|
obj2[F("id")] = i;
|
||||||
obj2[F("name")] = String(iv->name);
|
obj2[F("name")] = String(iv->config->name);
|
||||||
obj2[F("serial")] = String(iv->serial.u64, HEX);
|
obj2[F("serial")] = String(iv->config->serial.u64, HEX);
|
||||||
obj2[F("channels")] = iv->channels;
|
obj2[F("channels")] = iv->channels;
|
||||||
obj2[F("version")] = String(iv->fwVersion);
|
obj2[F("version")] = String(iv->fwVersion);
|
||||||
|
|
||||||
for(uint8_t j = 0; j < iv->channels; j ++) {
|
for(uint8_t j = 0; j < iv->channels; j ++) {
|
||||||
obj2[F("ch_max_power")][j] = iv->chMaxPwr[j];
|
obj2[F("ch_max_power")][j] = iv->config->chMaxPwr[j];
|
||||||
obj2[F("ch_name")][j] = iv->chName[j];
|
obj2[F("ch_name")][j] = iv->config->chName[j];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
obj[F("interval")] = String(mConfig->sendInterval);
|
obj[F("interval")] = String(mConfig->nrf.sendInterval);
|
||||||
obj[F("retries")] = String(mConfig->maxRetransPerPyld);
|
obj[F("retries")] = String(mConfig->nrf.maxRetransPerPyld);
|
||||||
obj[F("max_num_inverters")] = MAX_NUM_INVERTERS;
|
obj[F("max_num_inverters")] = MAX_NUM_INVERTERS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,23 +248,23 @@ void webApi::getMqtt(JsonObject obj) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getNtp(JsonObject obj) {
|
void webApi::getNtp(JsonObject obj) {
|
||||||
obj[F("addr")] = String(mConfig->ntpAddr);
|
obj[F("addr")] = String(mConfig->ntp.addr);
|
||||||
obj[F("port")] = String(mConfig->ntpPort);
|
obj[F("port")] = String(mConfig->ntp.port);
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getSun(JsonObject obj) {
|
void webApi::getSun(JsonObject obj) {
|
||||||
obj[F("lat")] = mConfig->sunLat ? String(mConfig->sunLat, 5) : "";
|
obj[F("lat")] = mConfig->sun.lat ? String(mConfig->sun.lat, 5) : "";
|
||||||
obj[F("lon")] = mConfig->sunLat ? String(mConfig->sunLon, 5) : "";
|
obj[F("lon")] = mConfig->sun.lat ? String(mConfig->sun.lon, 5) : "";
|
||||||
obj[F("disnightcom")] = mConfig->sunDisNightCom;
|
obj[F("disnightcom")] = mConfig->sun.disNightCom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getPinout(JsonObject obj) {
|
void webApi::getPinout(JsonObject obj) {
|
||||||
obj[F("cs")] = mConfig->pinCs;
|
obj[F("cs")] = mConfig->nrf.pinCs;
|
||||||
obj[F("ce")] = mConfig->pinCe;
|
obj[F("ce")] = mConfig->nrf.pinCe;
|
||||||
obj[F("irq")] = mConfig->pinIrq;
|
obj[F("irq")] = mConfig->nrf.pinIrq;
|
||||||
obj[F("led0")] = mConfig->led.led0;
|
obj[F("led0")] = mConfig->led.led0;
|
||||||
obj[F("led1")] = mConfig->led.led1;
|
obj[F("led1")] = mConfig->led.led1;
|
||||||
}
|
}
|
||||||
|
@ -274,25 +272,26 @@ void webApi::getPinout(JsonObject obj) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getRadio(JsonObject obj) {
|
void webApi::getRadio(JsonObject obj) {
|
||||||
obj[F("power_level")] = mConfig->amplifierPower;
|
obj[F("power_level")] = mConfig->nrf.amplifierPower;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getSerial(JsonObject obj) {
|
void webApi::getSerial(JsonObject obj) {
|
||||||
obj[F("interval")] = (uint16_t)mConfig->serialInterval;
|
obj[F("interval")] = (uint16_t)mConfig->serial.interval;
|
||||||
obj[F("show_live_data")] = mConfig->serialShowIv;
|
obj[F("show_live_data")] = mConfig->serial.showIv;
|
||||||
obj[F("debug")] = mConfig->serialDebug;
|
obj[F("debug")] = mConfig->serial.debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void webApi::getStaticIp(JsonObject obj) {
|
void webApi::getStaticIp(JsonObject obj) {
|
||||||
if(mConfig->staticIp.ip[0] != 0) {
|
if(mConfig->sys.ip.ip[0] != 0) {
|
||||||
obj[F("ip")] = ip2String(mConfig->staticIp.ip);
|
obj[F("ip")] = ip2String(mConfig->sys.ip.ip);
|
||||||
obj[F("mask")] = ip2String(mConfig->staticIp.mask);
|
obj[F("mask")] = ip2String(mConfig->sys.ip.mask);
|
||||||
obj[F("dns")] = ip2String(mConfig->staticIp.dns);
|
obj[F("dns1")] = ip2String(mConfig->sys.ip.dns1);
|
||||||
obj[F("gateway")] = ip2String(mConfig->staticIp.gateway);
|
obj[F("dns2")] = ip2String(mConfig->sys.ip.dns2);
|
||||||
|
obj[F("gateway")] = ip2String(mConfig->sys.ip.gateway);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,7 +313,7 @@ void webApi::getMenu(JsonObject obj) {
|
||||||
obj["link"][6] = "/update";
|
obj["link"][6] = "/update";
|
||||||
obj["name"][7] = "System";
|
obj["name"][7] = "System";
|
||||||
obj["link"][7] = "/system";
|
obj["link"][7] = "/system";
|
||||||
if(strlen(mConfig->password) > 0) {
|
if(strlen(mConfig->sys.adminPwd) > 0) {
|
||||||
obj["name"][8] = "-";
|
obj["name"][8] = "-";
|
||||||
obj["name"][9] = "Logout";
|
obj["name"][9] = "Logout";
|
||||||
obj["link"][9] = "/logout";
|
obj["link"][9] = "/logout";
|
||||||
|
@ -327,7 +326,7 @@ void webApi::getIndex(JsonObject obj) {
|
||||||
getMenu(obj.createNestedObject(F("menu")));
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
getSysInfo(obj.createNestedObject(F("system")));
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
getStatistics(obj.createNestedObject(F("statistics")));
|
getStatistics(obj.createNestedObject(F("statistics")));
|
||||||
obj["refresh_interval"] = mConfig->sendInterval;
|
obj["refresh_interval"] = mConfig->nrf.sendInterval;
|
||||||
|
|
||||||
JsonArray inv = obj.createNestedArray(F("inverter"));
|
JsonArray inv = obj.createNestedArray(F("inverter"));
|
||||||
Inverter<> *iv;
|
Inverter<> *iv;
|
||||||
|
@ -337,7 +336,7 @@ void webApi::getIndex(JsonObject obj) {
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
JsonObject invObj = inv.createNestedObject();
|
JsonObject invObj = inv.createNestedObject();
|
||||||
invObj[F("id")] = i;
|
invObj[F("id")] = i;
|
||||||
invObj[F("name")] = String(iv->name);
|
invObj[F("name")] = String(iv->config->name);
|
||||||
invObj[F("version")] = String(iv->fwVersion);
|
invObj[F("version")] = String(iv->fwVersion);
|
||||||
invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp(), rec);
|
invObj[F("is_avail")] = iv->isAvailable(mApp->getTimestamp(), rec);
|
||||||
invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp(), rec);
|
invObj[F("is_producing")] = iv->isProducing(mApp->getTimestamp(), rec);
|
||||||
|
@ -387,7 +386,7 @@ void webApi::getLive(JsonObject obj) {
|
||||||
getMenu(obj.createNestedObject(F("menu")));
|
getMenu(obj.createNestedObject(F("menu")));
|
||||||
getSysInfo(obj.createNestedObject(F("system")));
|
getSysInfo(obj.createNestedObject(F("system")));
|
||||||
JsonArray invArr = obj.createNestedArray(F("inverter"));
|
JsonArray invArr = obj.createNestedArray(F("inverter"));
|
||||||
obj["refresh_interval"] = mConfig->sendInterval;
|
obj["refresh_interval"] = mConfig->nrf.sendInterval;
|
||||||
|
|
||||||
uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q};
|
uint8_t list[] = {FLD_UAC, FLD_IAC, FLD_PAC, FLD_F, FLD_PF, FLD_T, FLD_YT, FLD_YD, FLD_PDC, FLD_EFF, FLD_Q};
|
||||||
|
|
||||||
|
@ -398,7 +397,7 @@ void webApi::getLive(JsonObject obj) {
|
||||||
if(NULL != iv) {
|
if(NULL != iv) {
|
||||||
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug);
|
||||||
JsonObject obj2 = invArr.createNestedObject();
|
JsonObject obj2 = invArr.createNestedObject();
|
||||||
obj2[F("name")] = String(iv->name);
|
obj2[F("name")] = String(iv->config->name);
|
||||||
obj2[F("channels")] = iv->channels;
|
obj2[F("channels")] = iv->channels;
|
||||||
obj2[F("power_limit_read")] = round3(iv->actPowerLimit);
|
obj2[F("power_limit_read")] = round3(iv->actPowerLimit);
|
||||||
obj2[F("last_alarm")] = String(iv->lastAlarmMsg);
|
obj2[F("last_alarm")] = String(iv->lastAlarmMsg);
|
||||||
|
@ -415,7 +414,7 @@ void webApi::getLive(JsonObject obj) {
|
||||||
}
|
}
|
||||||
|
|
||||||
for(uint8_t j = 1; j <= iv->channels; j ++) {
|
for(uint8_t j = 1; j <= iv->channels; j ++) {
|
||||||
obj2[F("ch_names")][j] = String(iv->chName[j-1]);
|
obj2[F("ch_names")][j] = String(iv->config->chName[j-1]);
|
||||||
JsonArray cur = ch.createNestedArray();
|
JsonArray cur = ch.createNestedArray();
|
||||||
for (uint8_t k = 0; k < 6; k++) {
|
for (uint8_t k = 0; k < 6; k++) {
|
||||||
switch(k) {
|
switch(k) {
|
||||||
|
|
|
@ -16,7 +16,7 @@ class app;
|
||||||
|
|
||||||
class webApi {
|
class webApi {
|
||||||
public:
|
public:
|
||||||
webApi(AsyncWebServer *srv, app *app, sysConfig_t *sysCfg, config_t *config, statistics_t *stat, char version[]);
|
webApi(AsyncWebServer *srv, app *app, settings_t *config, statistics_t *stat, char version[]);
|
||||||
|
|
||||||
void setup(void);
|
void setup(void);
|
||||||
void loop(void);
|
void loop(void);
|
||||||
|
@ -72,8 +72,7 @@ class webApi {
|
||||||
AsyncWebServer *mSrv;
|
AsyncWebServer *mSrv;
|
||||||
app *mApp;
|
app *mApp;
|
||||||
|
|
||||||
config_t *mConfig;
|
settings_t *mConfig;
|
||||||
sysConfig_t *mSysCfg;
|
|
||||||
statistics_t *mStat;
|
statistics_t *mStat;
|
||||||
char *mVersion;
|
char *mVersion;
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
ahoywifi::ahoywifi(app *main, sysConfig_t *sysCfg, config_t *config) {
|
ahoywifi::ahoywifi(settings_t *config) {
|
||||||
mMain = main;
|
|
||||||
mSysCfg = sysCfg;
|
|
||||||
mConfig = config;
|
mConfig = config;
|
||||||
|
|
||||||
mDns = new DNSServer();
|
mDns = new DNSServer();
|
||||||
|
@ -34,18 +32,17 @@ ahoywifi::ahoywifi(app *main, sysConfig_t *sysCfg, config_t *config) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ahoywifi::setup(uint32_t timeout, bool settingValid) {
|
void ahoywifi::setup(uint32_t timeout, bool settingValid) {
|
||||||
|
|
||||||
#ifdef FB_WIFI_OVERRIDDEN
|
#ifdef FB_WIFI_OVERRIDDEN
|
||||||
mStationWifiIsDef = false;
|
mStationWifiIsDef = false;
|
||||||
#else
|
#else
|
||||||
mStationWifiIsDef = (strncmp(mSysCfg->stationSsid, FB_WIFI_SSID, 14) == 0);
|
mStationWifiIsDef = (strncmp(mConfig->sys.stationSsid, FB_WIFI_SSID, 14) == 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mWifiStationTimeout = timeout;
|
mWifiStationTimeout = timeout;
|
||||||
#ifndef AP_ONLY
|
#ifndef AP_ONLY
|
||||||
if(false == mApActive)
|
if(false == mApActive)
|
||||||
mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout);
|
mApActive = (mStationWifiIsDef) ? true : setupStation(mWifiStationTimeout);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(!settingValid) {
|
if(!settingValid) {
|
||||||
DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup"));
|
DPRINTLN(DBG_WARN, F("your settings are not valid! check [IP]/setup"));
|
||||||
mApActive = true;
|
mApActive = true;
|
||||||
|
@ -58,7 +55,7 @@ void ahoywifi::setup(uint32_t timeout, bool settingValid) {
|
||||||
DPRINTLN(DBG_INFO, F("Welcome to AHOY!"));
|
DPRINTLN(DBG_INFO, F("Welcome to AHOY!"));
|
||||||
DPRINT(DBG_INFO, F("\npoint your browser to http://"));
|
DPRINT(DBG_INFO, F("\npoint your browser to http://"));
|
||||||
if(mApActive)
|
if(mApActive)
|
||||||
DBGPRINTLN(F("192.168.1.1"));
|
DBGPRINTLN(F("192.168.4.1"));
|
||||||
else
|
else
|
||||||
DBGPRINTLN(WiFi.localIP().toString());
|
DBGPRINTLN(WiFi.localIP().toString());
|
||||||
DPRINTLN(DBG_INFO, F("to configure your device"));
|
DPRINTLN(DBG_INFO, F("to configure your device"));
|
||||||
|
@ -142,20 +139,21 @@ bool ahoywifi::setupStation(uint32_t timeout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFi.mode(WIFI_STA);
|
WiFi.mode(WIFI_STA);
|
||||||
if(mConfig->staticIp.ip[0] != 0) {
|
if(mConfig->sys.ip.ip[0] != 0) {
|
||||||
IPAddress ip(mConfig->staticIp.ip);
|
IPAddress ip(mConfig->sys.ip.ip);
|
||||||
IPAddress mask(mConfig->staticIp.mask);
|
IPAddress mask(mConfig->sys.ip.mask);
|
||||||
IPAddress dns(mConfig->staticIp.dns);
|
IPAddress dns1(mConfig->sys.ip.dns1);
|
||||||
IPAddress gateway(mConfig->staticIp.gateway);
|
IPAddress dns2(mConfig->sys.ip.dns2);
|
||||||
if(!WiFi.config(ip, gateway, mask, dns))
|
IPAddress gateway(mConfig->sys.ip.gateway);
|
||||||
|
if(!WiFi.config(ip, gateway, mask, dns1, dns2))
|
||||||
DPRINTLN(DBG_ERROR, F("failed to set static IP!"));
|
DPRINTLN(DBG_ERROR, F("failed to set static IP!"));
|
||||||
}
|
}
|
||||||
WiFi.begin(mSysCfg->stationSsid, mSysCfg->stationPwd);
|
WiFi.begin(mConfig->sys.stationSsid, mConfig->sys.stationPwd);
|
||||||
if(String(mSysCfg->deviceName) != "")
|
if(String(mConfig->sys.deviceName) != "")
|
||||||
WiFi.hostname(mSysCfg->deviceName);
|
WiFi.hostname(mConfig->sys.deviceName);
|
||||||
|
|
||||||
delay(2000);
|
delay(2000);
|
||||||
DPRINTLN(DBG_INFO, F("connect to network '") + String(mSysCfg->stationSsid) + F("' ..."));
|
DPRINTLN(DBG_INFO, F("connect to network '") + String(mConfig->sys.stationSsid) + F("' ..."));
|
||||||
while (WiFi.status() != WL_CONNECTED) {
|
while (WiFi.status() != WL_CONNECTED) {
|
||||||
delay(100);
|
delay(100);
|
||||||
if(cnt % 40 == 0)
|
if(cnt % 40 == 0)
|
||||||
|
@ -197,8 +195,8 @@ time_t ahoywifi::getNtpTime(void) {
|
||||||
uint8_t buf[NTP_PACKET_SIZE];
|
uint8_t buf[NTP_PACKET_SIZE];
|
||||||
uint8_t retry = 0;
|
uint8_t retry = 0;
|
||||||
|
|
||||||
WiFi.hostByName(mConfig->ntpAddr, timeServer);
|
WiFi.hostByName(mConfig->ntp.addr, timeServer);
|
||||||
mUdp->begin(mConfig->ntpPort);
|
mUdp->begin(mConfig->ntp.port);
|
||||||
|
|
||||||
sendNTPpacket(timeServer);
|
sendNTPpacket(timeServer);
|
||||||
|
|
||||||
|
|
|
@ -7,21 +7,19 @@
|
||||||
#define __AHOYWIFI_H__
|
#define __AHOYWIFI_H__
|
||||||
|
|
||||||
#include "../utils/dbg.h"
|
#include "../utils/dbg.h"
|
||||||
|
#include <Arduino.h>
|
||||||
// NTP
|
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#include <TimeLib.h>
|
#include <TimeLib.h>
|
||||||
#include <DNSServer.h>
|
#include <DNSServer.h>
|
||||||
|
#include "ESPAsyncWebServer.h"
|
||||||
|
|
||||||
#include "../defines.h"
|
#include "../config/settings.h"
|
||||||
|
|
||||||
#include "../app.h"
|
|
||||||
|
|
||||||
class app;
|
class app;
|
||||||
|
|
||||||
class ahoywifi {
|
class ahoywifi {
|
||||||
public:
|
public:
|
||||||
ahoywifi(app *main, sysConfig_t *sysCfg, config_t *config);
|
ahoywifi(settings_t *config);
|
||||||
~ahoywifi() {}
|
~ahoywifi() {}
|
||||||
|
|
||||||
void setup(uint32_t timeout, bool settingValid);
|
void setup(uint32_t timeout, bool settingValid);
|
||||||
|
@ -36,9 +34,7 @@ class ahoywifi {
|
||||||
private:
|
private:
|
||||||
void sendNTPpacket(IPAddress& address);
|
void sendNTPpacket(IPAddress& address);
|
||||||
|
|
||||||
config_t *mConfig;
|
settings_t *mConfig;
|
||||||
sysConfig_t *mSysCfg;
|
|
||||||
app *mMain;
|
|
||||||
|
|
||||||
DNSServer *mDns;
|
DNSServer *mDns;
|
||||||
WiFiUDP *mUdp; // for time server
|
WiFiUDP *mUdp; // for time server
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue