Browse Source

improved mqtt

removed wrong "inverter type can't be detected!" messages
repaired NTP and static IP #459
MQTT status about availability and produce are retain messages now
pull/467/head
lumapu 2 years ago
parent
commit
0a5833e6ec
  1. 41
      src/config/settings.h
  2. 2
      src/defines.h
  3. 2
      src/hm/hmSystem.h
  4. 11
      src/publisher/pubMqtt.h
  5. 29
      src/utils/helper.cpp
  6. 19
      src/utils/helper.h
  7. 4
      src/web/html/index.html
  8. 45
      src/web/web.cpp
  9. 9
      src/web/web.h
  10. 15
      src/web/webApi.cpp
  11. 6
      src/web/webApi.h

41
src/config/settings.h

@ -10,6 +10,7 @@
#include <LittleFS.h> #include <LittleFS.h>
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include "../utils/dbg.h" #include "../utils/dbg.h"
#include "../utils/helper.h"
#include "../defines.h" #include "../defines.h"
/** /**
@ -223,25 +224,6 @@ class settings {
return saveSettings(); 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: private:
void loadDefaults(bool wifi = true) { void loadDefaults(bool wifi = true) {
DPRINTLN(DBG_INFO, F("loadDefaults")); DPRINTLN(DBG_INFO, F("loadDefaults"));
@ -288,25 +270,26 @@ class settings {
void jsonWifi(JsonObject obj, bool set = false) { void jsonWifi(JsonObject obj, bool set = false) {
if(set) { if(set) {
char buf[16];
obj[F("ssid")] = mCfg.sys.stationSsid; obj[F("ssid")] = mCfg.sys.stationSsid;
obj[F("pwd")] = mCfg.sys.stationPwd; obj[F("pwd")] = mCfg.sys.stationPwd;
obj[F("dev")] = mCfg.sys.deviceName; obj[F("dev")] = mCfg.sys.deviceName;
obj[F("adm")] = mCfg.sys.adminPwd; obj[F("adm")] = mCfg.sys.adminPwd;
obj[F("ip")] = ip2Str(mCfg.sys.ip.ip); ah::ip2Char(mCfg.sys.ip.ip, buf); obj[F("ip")] = String(buf);
obj[F("mask")] = ip2Str(mCfg.sys.ip.mask); ah::ip2Char(mCfg.sys.ip.mask, buf); obj[F("mask")] = String(buf);
obj[F("dns1")] = ip2Str(mCfg.sys.ip.dns1); ah::ip2Char(mCfg.sys.ip.dns1, buf); obj[F("dns1")] = String(buf);
obj[F("dns2")] = ip2Str(mCfg.sys.ip.dns2); ah::ip2Char(mCfg.sys.ip.dns2, buf); obj[F("dns2")] = String(buf);
obj[F("gtwy")] = ip2Str(mCfg.sys.ip.gateway); ah::ip2Char(mCfg.sys.ip.gateway, buf); obj[F("gtwy")] = String(buf);
} else { } else {
snprintf(mCfg.sys.stationSsid, SSID_LEN, "%s", obj[F("ssid")].as<const char*>()); 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.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.deviceName, DEVNAME_LEN, "%s", obj[F("dev")].as<const char*>());
snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as<const char*>()); snprintf(mCfg.sys.adminPwd, PWD_LEN, "%s", obj[F("adm")].as<const char*>());
ip2Arr(mCfg.sys.ip.ip, obj[F("ip")]); ah::ip2Arr(mCfg.sys.ip.ip, obj[F("ip")].as<const char*>());
ip2Arr(mCfg.sys.ip.mask, obj[F("mask")]); ah::ip2Arr(mCfg.sys.ip.mask, obj[F("mask")].as<const char*>());
ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")]); ah::ip2Arr(mCfg.sys.ip.dns1, obj[F("dns1")].as<const char*>());
ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")]); ah::ip2Arr(mCfg.sys.ip.dns2, obj[F("dns2")].as<const char*>());
ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")]); ah::ip2Arr(mCfg.sys.ip.gateway, obj[F("gtwy")].as<const char*>());
} }
} }

2
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 43 #define VERSION_PATCH 44
//------------------------------------- //-------------------------------------
typedef struct { typedef struct {

2
src/hm/hmSystem.h

@ -70,7 +70,7 @@ class HmSystem {
break; break;
} }
} }
else else if(p->config->serial.u64 != 0ULL)
DPRINTLN(DBG_ERROR, F("inverter type can't be detected!")); DPRINTLN(DBG_ERROR, F("inverter type can't be detected!"));
p->init(); p->init();

11
src/publisher/pubMqtt.h

@ -111,7 +111,8 @@ class PubMqtt {
} }
void payloadEventListener(uint8_t cmd) { void payloadEventListener(uint8_t cmd) {
mSendList.push(cmd); if(mClient.connected()) // prevent overflow if MQTT broker is not reachable but set
mSendList.push(cmd);
} }
void setSubscriptionCb(subscriptionCb cb) { void setSubscriptionCb(subscriptionCb cb) {
@ -185,6 +186,7 @@ class PubMqtt {
void onWifiConnect(const WiFiEventStationModeGotIP& event) { void onWifiConnect(const WiFiEventStationModeGotIP& event) {
DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); DPRINTLN(DBG_VERBOSE, F("MQTT connecting"));
mClient.connect(); mClient.connect();
mEnReconnect = true;
} }
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) { void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
@ -197,6 +199,7 @@ class PubMqtt {
case SYSTEM_EVENT_STA_GOT_IP: case SYSTEM_EVENT_STA_GOT_IP:
DPRINTLN(DBG_VERBOSE, F("MQTT connecting")); DPRINTLN(DBG_VERBOSE, F("MQTT connecting"));
mClient.connect(); mClient.connect();
mEnReconnect = true;
break; break;
case SYSTEM_EVENT_STA_DISCONNECTED: case SYSTEM_EVENT_STA_DISCONNECTED:
@ -360,15 +363,15 @@ class PubMqtt {
(status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "", (status == MQTT_STATUS_AVAIL_NOT_PROD) ? "not " : "",
(status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "" : "producing" (status == MQTT_STATUS_NOT_AVAIL_NOT_PROD) ? "" : "producing"
); );
publish(topic, val); publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name); snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/available", iv->config->name);
snprintf(val, 40, "%d", status); snprintf(val, 40, "%d", status);
publish(topic, val); publish(topic, val, true);
snprintf(topic, 32 + MAX_NAME_LENGTH, "%s/last_success", iv->config->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);
publish(topic, val); publish(topic, val, true);
} }
// data // data

29
src/utils/helper.cpp

@ -0,0 +1,29 @@
//-----------------------------------------------------------------------------
// 2022 Ahoy, https://github.com/lumpapu/ahoy
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#include "helper.h"
namespace ah {
void ip2Arr(uint8_t ip[], const char *ipStr) {
memset(ip, 0, 4);
char *tmp = new char[strlen(ipStr)+1];
strncpy(tmp, ipStr, strlen(ipStr)+1);
char *p = strtok(tmp, ".");
uint8_t i = 0;
while(NULL != p) {
ip[i++] = atoi(p);
p = strtok(NULL, ".");
}
delete[] tmp;
}
// note: char *str needs to be at least 16 bytes long
void ip2Char(uint8_t ip[], char *str) {
if(0 == ip[0])
str[0] = '\0';
else
snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
}
}

19
src/utils/helper.h

@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// 2022 Ahoy, https://ahoydtu.de
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#ifndef __HELPER_H__
#define __HELPER_H__
#include <cstdint>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
namespace ah {
void ip2Arr(uint8_t ip[], const char *ipStr);
void ip2Char(uint8_t ip[], char *str);
}
#endif /*__HELPER_H__*/

4
src/web/html/index.html

@ -196,9 +196,9 @@
parseStat(obj["statistics"]); parseStat(obj["statistics"]);
parseIv(obj["inverter"]); parseIv(obj["inverter"]);
parseWarnInfo(obj["warnings"], obj["infos"]); parseWarnInfo(obj["warnings"], obj["infos"]);
document.getElementById("refresh").innerHTML = obj["refresh_interval"]; document.getElementById("refresh").innerHTML = 10;
if(exeOnce) { if(exeOnce) {
window.setInterval("getAjax('/api/index', parse)", obj["refresh_interval"] * 1000); window.setInterval("getAjax('/api/index', parse)", 10000);
exeOnce = false; exeOnce = false;
} }
} }

45
src/web/web.cpp

@ -11,6 +11,7 @@
#include "web.h" #include "web.h"
#include "../utils/ahoyTimer.h" #include "../utils/ahoyTimer.h"
#include "../utils/helper.h"
#include "html/h/index_html.h" #include "html/h/index_html.h"
#include "html/h/login_html.h" #include "html/h/login_html.h"
@ -343,28 +344,16 @@ void web::showSave(AsyncWebServerRequest *request) {
// static ip // static ip
if(request->arg("ipAddr") != "") { request->arg("ipAddr").toCharArray(buf, 20);
request->arg("ipAddr").toCharArray(buf, SSID_LEN); ah::ip2Arr(mConfig->sys.ip.ip, buf);
ip2Arr(mConfig->sys.ip.ip, buf); request->arg("ipMask").toCharArray(buf, 20);
if(request->arg("ipMask") != "") { ah::ip2Arr(mConfig->sys.ip.mask, buf);
request->arg("ipMask").toCharArray(buf, SSID_LEN); request->arg("ipDns1").toCharArray(buf, 20);
ip2Arr(mConfig->sys.ip.mask, buf); ah::ip2Arr(mConfig->sys.ip.dns1, buf);
} request->arg("ipDns2").toCharArray(buf, 20);
if(request->arg("ipDns1") != "") { ah::ip2Arr(mConfig->sys.ip.dns2, buf);
request->arg("ipDns1").toCharArray(buf, SSID_LEN); request->arg("ipGateway").toCharArray(buf, 20);
ip2Arr(mConfig->sys.ip.dns1, buf); ah::ip2Arr(mConfig->sys.ip.gateway, buf);
}
if(request->arg("ipDns2") != "") {
request->arg("ipDns2").toCharArray(buf, SSID_LEN);
ip2Arr(mConfig->sys.ip.dns2, buf);
}
if(request->arg("ipGateway") != "") {
request->arg("ipGateway").toCharArray(buf, SSID_LEN);
ip2Arr(mConfig->sys.ip.gateway, buf);
}
}
else
memset(&mConfig->sys.ip.ip, 0, 4);
// inverter // inverter
@ -437,12 +426,14 @@ void web::showSave(AsyncWebServerRequest *request) {
String addr = request->arg("mqttAddr"); String addr = request->arg("mqttAddr");
addr.trim(); addr.trim();
addr.toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN); addr.toCharArray(mConfig->mqtt.broker, MQTT_ADDR_LEN);
request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN);
if(request->arg("mqttPwd") != "{PWD}")
request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN);
request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN);
mConfig->mqtt.port = request->arg("mqttPort").toInt();
} }
else
mConfig->mqtt.broker[0] = '\0';
request->arg("mqttUser").toCharArray(mConfig->mqtt.user, MQTT_USER_LEN);
if(request->arg("mqttPwd") != "{PWD}")
request->arg("mqttPwd").toCharArray(mConfig->mqtt.pwd, MQTT_PWD_LEN);
request->arg("mqttTopic").toCharArray(mConfig->mqtt.topic, MQTT_TOPIC_LEN);
mConfig->mqtt.port = request->arg("mqttPort").toInt();
// serial console // serial console
if(request->arg("serIntvl") != "") { if(request->arg("serIntvl") != "") {

9
src/web/web.h

@ -64,15 +64,6 @@ class web {
void onSerial(AsyncWebServerRequest *request); void onSerial(AsyncWebServerRequest *request);
void onSystem(AsyncWebServerRequest *request); void onSystem(AsyncWebServerRequest *request);
void ip2Arr(uint8_t ip[], char *ipStr) {
char *p = strtok(ipStr, ".");
uint8_t i = 0;
while(NULL != p) {
ip[i++] = atoi(p);
p = strtok(NULL, ".");
}
}
#ifdef ENABLE_JSON_EP #ifdef ENABLE_JSON_EP
void showJson(void); void showJson(void);
#endif #endif

15
src/web/webApi.cpp

@ -332,13 +332,12 @@ void webApi::getSerial(JsonObject obj) {
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void webApi::getStaticIp(JsonObject obj) { void webApi::getStaticIp(JsonObject obj) {
if(mConfig->sys.ip.ip[0] != 0) { char buf[16];
obj[F("ip")] = ip2String(mConfig->sys.ip.ip); ah::ip2Char(mConfig->sys.ip.ip, buf); obj[F("ip")] = String(buf);
obj[F("mask")] = ip2String(mConfig->sys.ip.mask); ah::ip2Char(mConfig->sys.ip.mask, buf); obj[F("mask")] = String(buf);
obj[F("dns1")] = ip2String(mConfig->sys.ip.dns1); ah::ip2Char(mConfig->sys.ip.dns1, buf); obj[F("dns1")] = String(buf);
obj[F("dns2")] = ip2String(mConfig->sys.ip.dns2); ah::ip2Char(mConfig->sys.ip.dns2, buf); obj[F("dns2")] = String(buf);
obj[F("gateway")] = ip2String(mConfig->sys.ip.gateway); ah::ip2Char(mConfig->sys.ip.gateway, buf); obj[F("gateway")] = String(buf);
}
} }
@ -397,7 +396,7 @@ void webApi::getIndex(JsonObject obj) {
JsonArray warn = obj.createNestedArray(F("warnings")); JsonArray warn = obj.createNestedArray(F("warnings"));
if(!mApp->mSys->Radio.isChipConnected()) if(!mApp->mSys->Radio.isChipConnected())
warn.add(F("your NRF24 module can't be reached, check the wiring and pinout")); warn.add(F("your NRF24 module can't be reached, check the wiring and pinout"));
if(!mApp->mqttIsConnected()) if((!mApp->mqttIsConnected()) && (String(mConfig->mqtt.broker).length() > 0))
warn.add(F("MQTT is not connected")); warn.add(F("MQTT is not connected"));
JsonArray info = obj.createNestedArray(F("infos")); JsonArray info = obj.createNestedArray(F("infos"));

6
src/web/webApi.h

@ -63,12 +63,6 @@ class webApi {
return (int)(value * 1000 + 0.5) / 1000.0; return (int)(value * 1000 + 0.5) / 1000.0;
} }
String ip2String(uint8_t ip[]) {
char str[16];
snprintf(str, 16, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]);
return String(str);
}
AsyncWebServer *mSrv; AsyncWebServer *mSrv;
app *mApp; app *mApp;

Loading…
Cancel
Save