mirror of
https://github.com/lumapu/ahoy.git
synced 2025-05-24 22:36:10 +02:00
first draft version, callback and subscription not included
This commit is contained in:
parent
4c52e9c307
commit
22715a1a4a
6 changed files with 247 additions and 186 deletions
|
@ -27,6 +27,10 @@ void app::setup(uint32_t timeout) {
|
||||||
mSettings.getPtr(mConfig);
|
mSettings.getPtr(mConfig);
|
||||||
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false")));
|
DPRINTLN(DBG_INFO, F("Settings valid: ") + String((mSettings.getValid()) ? F("true") : F("false")));
|
||||||
|
|
||||||
|
#if !defined(AP_ONLY)
|
||||||
|
mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset);
|
||||||
|
#endif
|
||||||
|
|
||||||
mWifi = new ahoywifi(mConfig);
|
mWifi = new ahoywifi(mConfig);
|
||||||
mWifi->setup(timeout, mSettings.getValid());
|
mWifi->setup(timeout, mSettings.getValid());
|
||||||
|
|
||||||
|
@ -39,7 +43,6 @@ void app::setup(uint32_t timeout) {
|
||||||
mPayload.enableSerialDebug(mConfig->serial.debug);
|
mPayload.enableSerialDebug(mConfig->serial.debug);
|
||||||
#if !defined(AP_ONLY)
|
#if !defined(AP_ONLY)
|
||||||
if (mConfig->mqtt.broker[0] > 0) {
|
if (mConfig->mqtt.broker[0] > 0) {
|
||||||
mMqtt.setup(&mConfig->mqtt, mConfig->sys.deviceName, mVersion, mSys, &mUtcTimestamp, &mSunrise, &mSunset);
|
|
||||||
mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1));
|
mPayload.addListener(std::bind(&PubMqttType::payloadEventListener, &mMqtt, std::placeholders::_1));
|
||||||
addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt));
|
addListener(EVERY_SEC, std::bind(&PubMqttType::tickerSecond, &mMqtt));
|
||||||
addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt));
|
addListener(EVERY_MIN, std::bind(&PubMqttType::tickerMinute, &mMqtt));
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
#define VERSION_MAJOR 0
|
#define VERSION_MAJOR 0
|
||||||
#define VERSION_MINOR 5
|
#define VERSION_MINOR 5
|
||||||
#define VERSION_PATCH 40
|
#define VERSION_PATCH 42
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
|
@ -36,7 +36,8 @@ lib_deps =
|
||||||
https://github.com/yubox-node-org/ESPAsyncWebServer
|
https://github.com/yubox-node-org/ESPAsyncWebServer
|
||||||
nrf24/RF24
|
nrf24/RF24
|
||||||
paulstoffregen/Time
|
paulstoffregen/Time
|
||||||
knolleary/PubSubClient
|
https://github.com/bertmelis/espMqttClient#v1.3.3
|
||||||
|
;knolleary/PubSubClient
|
||||||
bblanchon/ArduinoJson
|
bblanchon/ArduinoJson
|
||||||
;esp8266/DNSServer
|
;esp8266/DNSServer
|
||||||
;esp8266/EEPROM
|
;esp8266/EEPROM
|
||||||
|
|
|
@ -15,115 +15,94 @@
|
||||||
#include "../utils/dbg.h"
|
#include "../utils/dbg.h"
|
||||||
#include "../utils/ahoyTimer.h"
|
#include "../utils/ahoyTimer.h"
|
||||||
#include "../config/config.h"
|
#include "../config/config.h"
|
||||||
#include <PubSubClient.h>
|
#include <espMqttClient.h>
|
||||||
#include <ArduinoJson.h>
|
#include <ArduinoJson.h>
|
||||||
#include "../defines.h"
|
#include "../defines.h"
|
||||||
#include "../hm/hmSystem.h"
|
#include "../hm/hmSystem.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define QOS_0 0
|
||||||
|
|
||||||
|
//https://bert.emelis.net/espMqttClient/
|
||||||
|
|
||||||
template<class HMSYSTEM>
|
template<class HMSYSTEM>
|
||||||
class PubMqtt {
|
class PubMqtt {
|
||||||
public:
|
public:
|
||||||
PubMqtt() {
|
PubMqtt() {
|
||||||
mClient = new PubSubClient(mEspClient);
|
|
||||||
mAddressSet = false;
|
|
||||||
|
|
||||||
mLastReconnect = 0;
|
|
||||||
mTxCnt = 0;
|
mTxCnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
~PubMqtt() { }
|
~PubMqtt() { }
|
||||||
|
|
||||||
void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *sunrise, uint32_t *sunset) {
|
void setup(cfgMqtt_t *cfg_mqtt, const char *devName, const char *version, HMSYSTEM *sys, uint32_t *utcTs, uint32_t *sunrise, uint32_t *sunset) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("PubMqtt.h:setup"));
|
mCfgMqtt = cfg_mqtt;
|
||||||
mAddressSet = true;
|
|
||||||
|
|
||||||
mCfg_mqtt = cfg_mqtt;
|
|
||||||
mDevName = devName;
|
mDevName = devName;
|
||||||
|
mVersion = version;
|
||||||
mSys = sys;
|
mSys = sys;
|
||||||
mUtcTimestamp = utcTs;
|
mUtcTimestamp = utcTs;
|
||||||
mSunrise = sunrise;
|
mSunrise = sunrise;
|
||||||
mSunset = sunset;
|
mSunset = sunset;
|
||||||
|
|
||||||
mClient->setServer(mCfg_mqtt->broker, mCfg_mqtt->port);
|
mHWifiCon = WiFi.onStationModeGotIP(std::bind(&PubMqtt::onWifiConnect, this, std::placeholders::_1));
|
||||||
mClient->setBufferSize(MQTT_MAX_PACKET_SIZE);
|
mHWifiDiscon = WiFi.onStationModeDisconnected(std::bind(&PubMqtt::onWifiDisconnect, this, std::placeholders::_1));
|
||||||
|
|
||||||
setCallback(std::bind(&PubMqtt<HMSYSTEM>::cbMqtt, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
|
||||||
|
|
||||||
sendMsg("version", version);
|
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
|
||||||
sendMsg("device", devName);
|
mClient.setCredentials(mCfgMqtt->user, mCfgMqtt->pwd);
|
||||||
sendMsg("uptime", "0");
|
mClient.setClientId(mDevName); // TODO: add mac?
|
||||||
|
mClient.setServer(mCfgMqtt->broker, mCfgMqtt->port);
|
||||||
|
mClient.onConnect(std::bind(&PubMqtt::onConnect, this, std::placeholders::_1));
|
||||||
|
mClient.onDisconnect(std::bind(&PubMqtt::onDisconnect, this, std::placeholders::_1));
|
||||||
|
mClient.onSubscribe(std::bind(&PubMqtt::onSubscribe, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3));
|
||||||
|
mClient.onPublish(std::bind(&PubMqtt::onPublish, this, std::placeholders::_1));
|
||||||
|
//mClient.setWill
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if(mAddressSet)
|
mClient.loop();
|
||||||
mClient->loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickerSecond() {
|
void tickerSecond() {
|
||||||
if(mAddressSet) {
|
|
||||||
if(!mClient->connected())
|
|
||||||
reconnect();
|
|
||||||
}
|
|
||||||
sendIvData();
|
sendIvData();
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickerMinute() {
|
void tickerMinute() {
|
||||||
if(mAddressSet) {
|
char val[12];
|
||||||
char val[40];
|
snprintf(val, 12, "%ld", millis() / 1000);
|
||||||
snprintf(val, 40, "%ld", millis() / 1000);
|
publish("uptime", val);
|
||||||
sendMsg("uptime", val);
|
publish("wifi_rssi", String(WiFi.RSSI()).c_str());
|
||||||
|
|
||||||
sendMsg("wifi_rssi", String(WiFi.RSSI()).c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void tickerHour() {
|
void tickerHour() {
|
||||||
if(mAddressSet) {
|
publish("sunrise", String(*mSunrise).c_str(), true);
|
||||||
sendMsg("sunrise", String(*mSunrise).c_str());
|
publish("sunset", String(*mSunset).c_str(), true);
|
||||||
sendMsg("sunset", String(*mSunset).c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCallback(MQTT_CALLBACK_SIGNATURE) {
|
void publish(const char *subTopic, const char *payload, bool retained = false) {
|
||||||
mClient->setCallback(callback);
|
char topic[MQTT_TOPIC_LEN + 2];
|
||||||
|
snprintf(topic, (MQTT_TOPIC_LEN + 2), "%s/%s", mCfgMqtt->topic, subTopic);
|
||||||
|
mClient.publish(topic, QOS_0, retained, payload);
|
||||||
|
mTxCnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMsg(const char *topic, const char *msg) {
|
void subscribe(const char *subTopic) {
|
||||||
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:sendMsg"));
|
char topic[MQTT_TOPIC_LEN + 20];
|
||||||
if(mAddressSet) {
|
snprintf(topic, (MQTT_TOPIC_LEN + 20), "%s/%s", mCfgMqtt->topic, subTopic);
|
||||||
char top[66];
|
mClient.subscribe(topic, QOS_0);
|
||||||
snprintf(top, 66, "%s/%s", mCfg_mqtt->topic, topic);
|
|
||||||
sendMsg2(top, msg, false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendMsg2(const char *topic, const char *msg, boolean retained) {
|
inline bool isConnected() {
|
||||||
if(mAddressSet) {
|
return mClient.connected();
|
||||||
if(!mClient->connected())
|
|
||||||
reconnect();
|
|
||||||
if(mClient->connected())
|
|
||||||
mClient->publish(topic, msg, retained);
|
|
||||||
mTxCnt++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isConnected(bool doRecon = false) {
|
inline uint32_t getTxCnt(void) {
|
||||||
//DPRINTLN(DBG_VERBOSE, F("mqtt.h:isConnected"));
|
return mTxCnt;
|
||||||
if(!mAddressSet)
|
|
||||||
return false;
|
|
||||||
if(doRecon && !mClient->connected())
|
|
||||||
reconnect();
|
|
||||||
return mClient->connected();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void payloadEventListener(uint8_t cmd) {
|
void payloadEventListener(uint8_t cmd) {
|
||||||
mSendList.push(cmd);
|
mSendList.push(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t getTxCnt(void) {
|
|
||||||
return mTxCnt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sendMqttDiscoveryConfig(const char *topic) {
|
void sendMqttDiscoveryConfig(const char *topic) {
|
||||||
DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig"));
|
DPRINTLN(DBG_VERBOSE, F("sendMqttDiscoveryConfig"));
|
||||||
|
|
||||||
|
@ -165,8 +144,7 @@ class PubMqtt {
|
||||||
doc["stat_cla"] = stateCls;
|
doc["stat_cla"] = stateCls;
|
||||||
|
|
||||||
serializeJson(doc, buffer);
|
serializeJson(doc, buffer);
|
||||||
sendMsg2(discoveryTopic, buffer, true);
|
publish(discoveryTopic, buffer, true);
|
||||||
// DPRINTLN(DBG_INFO, F("mqtt sent"));
|
|
||||||
doc.clear();
|
doc.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,7 +154,69 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reconnect(void) {
|
void onWifiConnect(const WiFiEventStationModeGotIP& event) {
|
||||||
|
DPRINTLN(DBG_VERBOSE, F("MQTT connecting"));
|
||||||
|
mClient.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
|
||||||
|
DPRINTLN(DBG_WARN, F("TODO: MQTT reconnect!"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void onConnect(bool sessionPreset) {
|
||||||
|
DPRINTLN(DBG_INFO, F("MQTT connected"));
|
||||||
|
|
||||||
|
publish("version", mVersion, true);
|
||||||
|
publish("device", mDevName, true);
|
||||||
|
publish("uptime", "0");
|
||||||
|
|
||||||
|
subscribe("devcontrol/#"); // TODO: register onMessage callback!
|
||||||
|
}
|
||||||
|
|
||||||
|
void onDisconnect(espMqttClientTypes::DisconnectReason reason) {
|
||||||
|
DBGPRINT(F("MQTT disconnected, reason: "));
|
||||||
|
switch (reason) {
|
||||||
|
case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED:
|
||||||
|
DBGPRINTLN(F("TCP disconnect"));
|
||||||
|
break;
|
||||||
|
case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION:
|
||||||
|
DBGPRINTLN(F("wrong protocol version"));
|
||||||
|
break;
|
||||||
|
case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED:
|
||||||
|
DBGPRINTLN(F("identifier rejected"));
|
||||||
|
break;
|
||||||
|
case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE:
|
||||||
|
DBGPRINTLN(F("broker unavailable"));
|
||||||
|
break;
|
||||||
|
case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS:
|
||||||
|
DBGPRINTLN(F("malformed credentials"));
|
||||||
|
break;
|
||||||
|
case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED:
|
||||||
|
DBGPRINTLN(F("not authorized"));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DBGPRINTLN(F("unknown"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onSubscribe(uint16_t packetId, const espMqttClientTypes::SubscribeReturncode* codes, size_t len) {
|
||||||
|
DPRINTLN(DBG_INFO, F("MQTT Subscribe"));
|
||||||
|
Serial.print(" packetId: ");
|
||||||
|
Serial.println(packetId);
|
||||||
|
for (size_t i = 0; i < len; ++i) {
|
||||||
|
Serial.print(" qos: ");
|
||||||
|
Serial.println(static_cast<uint8_t>(codes[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void onPublish(uint16_t packetId) {
|
||||||
|
Serial.println("Publish acknowledged.");
|
||||||
|
Serial.print(" packetId: ");
|
||||||
|
Serial.println(packetId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*void reconnect(void) {
|
||||||
DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect"));
|
DPRINTLN(DBG_DEBUG, F("mqtt.h:reconnect"));
|
||||||
DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) );
|
DPRINTLN(DBG_DEBUG, F("MQTT mClient->_state ") + String(mClient->state()) );
|
||||||
|
|
||||||
|
@ -190,27 +230,27 @@ class PubMqtt {
|
||||||
if(strlen(mDevName) > 0) {
|
if(strlen(mDevName) > 0) {
|
||||||
// der Server und der Port müssen neu gesetzt werden,
|
// der Server und der Port müssen neu gesetzt werden,
|
||||||
// da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat.
|
// da ein MQTT_CONNECTION_LOST -3 die Werte zerstört hat.
|
||||||
mClient->setServer(mCfg_mqtt->broker, mCfg_mqtt->port);
|
mClient->setServer(mCfgMqtt->broker, mCfgMqtt->port);
|
||||||
mClient->setBufferSize(MQTT_MAX_PACKET_SIZE);
|
mClient->setBufferSize(MQTT_MAX_PACKET_SIZE);
|
||||||
|
|
||||||
char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte
|
char lwt[MQTT_TOPIC_LEN + 7 ]; // "/uptime" --> + 7 byte
|
||||||
snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfg_mqtt->topic);
|
snprintf(lwt, MQTT_TOPIC_LEN + 7, "%s/uptime", mCfgMqtt->topic);
|
||||||
|
|
||||||
if((strlen(mCfg_mqtt->user) > 0) && (strlen(mCfg_mqtt->pwd) > 0))
|
if((strlen(mCfgMqtt->user) > 0) && (strlen(mCfgMqtt->pwd) > 0))
|
||||||
resub = mClient->connect(mDevName, mCfg_mqtt->user, mCfg_mqtt->pwd, lwt, 0, false, "offline");
|
resub = mClient->connect(mDevName, mCfgMqtt->user, mCfgMqtt->pwd, lwt, 0, false, "offline");
|
||||||
else
|
else
|
||||||
resub = mClient->connect(mDevName, lwt, 0, false, "offline");
|
resub = mClient->connect(mDevName, lwt, 0, false, "offline");
|
||||||
// ein Subscribe ist nur nach einem connect notwendig
|
// ein Subscribe ist nur nach einem connect notwendig
|
||||||
if(resub) {
|
if(resub) {
|
||||||
char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte
|
char topic[MQTT_TOPIC_LEN + 13 ]; // "/devcontrol/#" --> + 6 byte
|
||||||
// ToDo: "/devcontrol/#" is hardcoded
|
// ToDo: "/devcontrol/#" is hardcoded
|
||||||
snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfg_mqtt->topic);
|
snprintf(topic, MQTT_TOPIC_LEN + 13, "%s/devcontrol/#", mCfgMqtt->topic);
|
||||||
DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic));
|
DPRINTLN(DBG_INFO, F("subscribe to ") + String(topic));
|
||||||
mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#"
|
mClient->subscribe(topic); // subscribe to mTopic + "/devcontrol/#"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
const char *getFieldDeviceClass(uint8_t fieldId) {
|
const char *getFieldDeviceClass(uint8_t fieldId) {
|
||||||
uint8_t pos = 0;
|
uint8_t pos = 0;
|
||||||
|
@ -234,7 +274,6 @@ class PubMqtt {
|
||||||
if(mSendList.empty())
|
if(mSendList.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
isConnected(true); // really needed? See comment from HorstG-57 #176
|
|
||||||
char topic[32 + MAX_NAME_LENGTH], val[40];
|
char topic[32 + MAX_NAME_LENGTH], val[40];
|
||||||
float total[4];
|
float total[4];
|
||||||
bool sendTotal = false;
|
bool sendTotal = false;
|
||||||
|
@ -267,15 +306,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"
|
||||||
);
|
);
|
||||||
sendMsg(topic, val);
|
publish(topic, val);
|
||||||
|
|
||||||
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);
|
||||||
sendMsg(topic, val);
|
publish(topic, val);
|
||||||
|
|
||||||
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);
|
||||||
sendMsg(topic, val);
|
publish(topic, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// data
|
// data
|
||||||
|
@ -283,7 +322,7 @@ class PubMqtt {
|
||||||
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->config->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);
|
publish(topic, val);
|
||||||
|
|
||||||
// calculate total values for RealTimeRunData_Debug
|
// calculate total values for RealTimeRunData_Debug
|
||||||
if (mSendList.front() == RealTimeRunData_Debug) {
|
if (mSendList.front() == RealTimeRunData_Debug) {
|
||||||
|
@ -332,127 +371,127 @@ class PubMqtt {
|
||||||
}
|
}
|
||||||
snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
|
snprintf(topic, 32 + MAX_NAME_LENGTH, "total/%s", fields[fieldId]);
|
||||||
snprintf(val, 40, "%.3f", total[i]);
|
snprintf(val, 40, "%.3f", total[i]);
|
||||||
sendMsg(topic, val);
|
publish(topic, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void cbMqtt(char *topic, byte *payload, unsigned int length) {
|
// void cbMqtt(char *topic, byte *payload, unsigned int length) {
|
||||||
// callback handling on subscribed devcontrol topic
|
// // callback handling on subscribed devcontrol topic
|
||||||
DPRINTLN(DBG_INFO, F("cbMqtt"));
|
// DPRINTLN(DBG_INFO, F("cbMqtt"));
|
||||||
// subcribed topics are mTopic + "/devcontrol/#" where # is <inverter_id>/<subcmd in dec>
|
// // subcribed topics are mTopic + "/devcontrol/#" where # is <inverter_id>/<subcmd in dec>
|
||||||
// eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt
|
// // eg. mypvsolar/devcontrol/1/11 with payload "400" --> inverter 1 active power limit 400 Watt
|
||||||
const char *token = strtok(topic, "/");
|
// const char *token = strtok(topic, "/");
|
||||||
while (token != NULL) {
|
// while (token != NULL) {
|
||||||
if (strcmp(token, "devcontrol") == 0) {
|
// if (strcmp(token, "devcontrol") == 0) {
|
||||||
token = strtok(NULL, "/");
|
// token = strtok(NULL, "/");
|
||||||
uint8_t iv_id = std::stoi(token);
|
// uint8_t iv_id = std::stoi(token);
|
||||||
|
//
|
||||||
|
// if (iv_id >= 0 && iv_id <= MAX_NUM_INVERTERS) {
|
||||||
|
// Inverter<> *iv = mSys->getInverterByPos(iv_id);
|
||||||
|
// if (NULL != iv) {
|
||||||
|
// if (!iv->devControlRequest) { // still pending
|
||||||
|
// token = strtok(NULL, "/");
|
||||||
|
//
|
||||||
|
// switch (std::stoi(token)) {
|
||||||
|
// // Active Power Control
|
||||||
|
// case ActivePowerContr:
|
||||||
|
// token = strtok(NULL, "/"); // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string
|
||||||
|
// if (token == NULL) // default via mqtt ommit the LimitControlMode
|
||||||
|
// iv->powerLimit[1] = AbsolutNonPersistent;
|
||||||
|
// else
|
||||||
|
// iv->powerLimit[1] = std::stoi(token);
|
||||||
|
// if (length <= 5) { // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed?
|
||||||
|
// if (iv->powerLimit[1] >= AbsolutNonPersistent && iv->powerLimit[1] <= RelativPersistent) {
|
||||||
|
// iv->devControlCmd = ActivePowerContr;
|
||||||
|
// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); // THX to @silversurfer
|
||||||
|
// /*if (iv->powerLimit[1] & 0x0001)
|
||||||
|
// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("%"));
|
||||||
|
// else
|
||||||
|
// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));*/
|
||||||
|
//
|
||||||
|
// DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + String(iv->powerLimit[1] & 0x0001) ? F("%") : F("W"));
|
||||||
|
// }
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// } else {
|
||||||
|
// DPRINTLN(DBG_INFO, F("Invalid mqtt payload recevied: ") + String((char *)payload));
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // Turn On
|
||||||
|
// case TurnOn:
|
||||||
|
// iv->devControlCmd = TurnOn;
|
||||||
|
// DPRINTLN(DBG_INFO, F("Turn on inverter ") + String(iv->id));
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // Turn Off
|
||||||
|
// case TurnOff:
|
||||||
|
// iv->devControlCmd = TurnOff;
|
||||||
|
// DPRINTLN(DBG_INFO, F("Turn off inverter ") + String(iv->id));
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // Restart
|
||||||
|
// case Restart:
|
||||||
|
// iv->devControlCmd = Restart;
|
||||||
|
// DPRINTLN(DBG_INFO, F("Restart inverter ") + String(iv->id));
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // Reactive Power Control
|
||||||
|
// case ReactivePowerContr:
|
||||||
|
// iv->devControlCmd = ReactivePowerContr;
|
||||||
|
// if (true) { // if (std::stoi((char*)payload) > 0) error handling powerlimit needed?
|
||||||
|
// iv->devControlCmd = ReactivePowerContr;
|
||||||
|
// iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length));
|
||||||
|
// iv->powerLimit[1] = 0x0000; // if reactivepower limit is set via external interface --> set it temporay
|
||||||
|
// DPRINTLN(DBG_DEBUG, F("Reactivepower limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // Set Power Factor
|
||||||
|
// case PFSet:
|
||||||
|
// // iv->devControlCmd = PFSet;
|
||||||
|
// // uint16_t power_factor = std::stoi(strtok(NULL, "/"));
|
||||||
|
// DPRINTLN(DBG_INFO, F("Set Power Factor not implemented for inverter ") + String(iv->id));
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// // CleanState lock & alarm
|
||||||
|
// case CleanState_LockAndAlarm:
|
||||||
|
// iv->devControlCmd = CleanState_LockAndAlarm;
|
||||||
|
// DPRINTLN(DBG_INFO, F("CleanState lock & alarm for inverter ") + String(iv->id));
|
||||||
|
// iv->devControlRequest = true;
|
||||||
|
// break;
|
||||||
|
//
|
||||||
|
// default:
|
||||||
|
// DPRINTLN(DBG_INFO, "Not implemented");
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// token = strtok(NULL, "/");
|
||||||
|
// }
|
||||||
|
// DPRINTLN(DBG_INFO, F("app::cbMqtt finished"));
|
||||||
|
// }
|
||||||
|
|
||||||
if (iv_id >= 0 && iv_id <= MAX_NUM_INVERTERS) {
|
espMqttClient mClient;
|
||||||
Inverter<> *iv = mSys->getInverterByPos(iv_id);
|
cfgMqtt_t *mCfgMqtt;
|
||||||
if (NULL != iv) {
|
WiFiEventHandler mHWifiCon, mHWifiDiscon;
|
||||||
if (!iv->devControlRequest) { // still pending
|
|
||||||
token = strtok(NULL, "/");
|
|
||||||
|
|
||||||
switch (std::stoi(token)) {
|
|
||||||
// Active Power Control
|
|
||||||
case ActivePowerContr:
|
|
||||||
token = strtok(NULL, "/"); // get ControlMode aka "PowerPF.Desc" in DTU-Pro Code from topic string
|
|
||||||
if (token == NULL) // default via mqtt ommit the LimitControlMode
|
|
||||||
iv->powerLimit[1] = AbsolutNonPersistent;
|
|
||||||
else
|
|
||||||
iv->powerLimit[1] = std::stoi(token);
|
|
||||||
if (length <= 5) { // if (std::stoi((char*)payload) > 0) more error handling powerlimit needed?
|
|
||||||
if (iv->powerLimit[1] >= AbsolutNonPersistent && iv->powerLimit[1] <= RelativPersistent) {
|
|
||||||
iv->devControlCmd = ActivePowerContr;
|
|
||||||
iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length)); // THX to @silversurfer
|
|
||||||
/*if (iv->powerLimit[1] & 0x0001)
|
|
||||||
DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("%"));
|
|
||||||
else
|
|
||||||
DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));*/
|
|
||||||
|
|
||||||
DPRINTLN(DBG_INFO, F("Power limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + String(iv->powerLimit[1] & 0x0001) ? F("%") : F("W"));
|
|
||||||
}
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
} else {
|
|
||||||
DPRINTLN(DBG_INFO, F("Invalid mqtt payload recevied: ") + String((char *)payload));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Turn On
|
|
||||||
case TurnOn:
|
|
||||||
iv->devControlCmd = TurnOn;
|
|
||||||
DPRINTLN(DBG_INFO, F("Turn on inverter ") + String(iv->id));
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Turn Off
|
|
||||||
case TurnOff:
|
|
||||||
iv->devControlCmd = TurnOff;
|
|
||||||
DPRINTLN(DBG_INFO, F("Turn off inverter ") + String(iv->id));
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Restart
|
|
||||||
case Restart:
|
|
||||||
iv->devControlCmd = Restart;
|
|
||||||
DPRINTLN(DBG_INFO, F("Restart inverter ") + String(iv->id));
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Reactive Power Control
|
|
||||||
case ReactivePowerContr:
|
|
||||||
iv->devControlCmd = ReactivePowerContr;
|
|
||||||
if (true) { // if (std::stoi((char*)payload) > 0) error handling powerlimit needed?
|
|
||||||
iv->devControlCmd = ReactivePowerContr;
|
|
||||||
iv->powerLimit[0] = std::stoi(std::string((char *)payload, (unsigned int)length));
|
|
||||||
iv->powerLimit[1] = 0x0000; // if reactivepower limit is set via external interface --> set it temporay
|
|
||||||
DPRINTLN(DBG_DEBUG, F("Reactivepower limit for inverter ") + String(iv->id) + F(" set to ") + String(iv->powerLimit[0]) + F("W"));
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
// Set Power Factor
|
|
||||||
case PFSet:
|
|
||||||
// iv->devControlCmd = PFSet;
|
|
||||||
// uint16_t power_factor = std::stoi(strtok(NULL, "/"));
|
|
||||||
DPRINTLN(DBG_INFO, F("Set Power Factor not implemented for inverter ") + String(iv->id));
|
|
||||||
break;
|
|
||||||
|
|
||||||
// CleanState lock & alarm
|
|
||||||
case CleanState_LockAndAlarm:
|
|
||||||
iv->devControlCmd = CleanState_LockAndAlarm;
|
|
||||||
DPRINTLN(DBG_INFO, F("CleanState lock & alarm for inverter ") + String(iv->id));
|
|
||||||
iv->devControlRequest = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DPRINTLN(DBG_INFO, "Not implemented");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
token = strtok(NULL, "/");
|
|
||||||
}
|
|
||||||
DPRINTLN(DBG_INFO, F("app::cbMqtt finished"));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t *mSunrise, *mSunset;
|
uint32_t *mSunrise, *mSunset;
|
||||||
WiFiClient mEspClient;
|
|
||||||
PubSubClient *mClient;
|
|
||||||
HMSYSTEM *mSys;
|
HMSYSTEM *mSys;
|
||||||
uint32_t *mUtcTimestamp;
|
uint32_t *mUtcTimestamp;
|
||||||
|
|
||||||
bool mAddressSet;
|
|
||||||
cfgMqtt_t *mCfg_mqtt;
|
|
||||||
const char *mDevName;
|
|
||||||
uint32_t mLastReconnect;
|
|
||||||
uint32_t mTxCnt;
|
uint32_t mTxCnt;
|
||||||
std::queue<uint8_t> mSendList;
|
std::queue<uint8_t> mSendList;
|
||||||
|
|
||||||
|
const char *mDevName, *mVersion;
|
||||||
|
//uint32_t mLastReconnect;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__PUB_MQTT_H__*/
|
#endif /*__PUB_MQTT_H__*/
|
||||||
|
|
|
@ -32,6 +32,8 @@ ahoywifi::ahoywifi(settings_t *config) {
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
void ahoywifi::setup(uint32_t timeout, bool settingValid) {
|
void ahoywifi::setup(uint32_t timeout, bool settingValid) {
|
||||||
|
//wifiConnectHandler = WiFi.onStationModeGotIP(std::bind(&ahoywifi::onConnect, this, std::placeholders::_1));
|
||||||
|
//wifiDisconnectHandler = WiFi.onStationModeDisconnected(std::bind(&ahoywifi::onDisconnect, this, std::placeholders::_1));
|
||||||
|
|
||||||
#ifdef FB_WIFI_OVERRIDDEN
|
#ifdef FB_WIFI_OVERRIDDEN
|
||||||
mStationWifiIsDef = false;
|
mStationWifiIsDef = false;
|
||||||
|
@ -287,3 +289,15 @@ void ahoywifi::sendNTPpacket(IPAddress& address) {
|
||||||
mUdp->write(buf, NTP_PACKET_SIZE);
|
mUdp->write(buf, NTP_PACKET_SIZE);
|
||||||
mUdp->endPacket();
|
mUdp->endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
/*void ahoywifi::onConnect(const WiFiEventStationModeGotIP& event) {
|
||||||
|
Serial.println("Connected to Wi-Fi.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
void ahoywifi::onDisconnect(const WiFiEventStationModeDisconnected& event) {
|
||||||
|
Serial.println("Disconnected from Wi-Fi.");
|
||||||
|
}*/
|
||||||
|
|
|
@ -33,11 +33,15 @@ class ahoywifi {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void sendNTPpacket(IPAddress& address);
|
void sendNTPpacket(IPAddress& address);
|
||||||
|
//void onConnect(const WiFiEventStationModeGotIP& event);
|
||||||
|
//void onDisconnect(const WiFiEventStationModeDisconnected& event);
|
||||||
|
|
||||||
settings_t *mConfig;
|
settings_t *mConfig;
|
||||||
|
|
||||||
DNSServer *mDns;
|
DNSServer *mDns;
|
||||||
WiFiUDP *mUdp; // for time server
|
WiFiUDP *mUdp; // for time server
|
||||||
|
//WiFiEventHandler wifiConnectHandler;
|
||||||
|
//WiFiEventHandler wifiDisconnectHandler;
|
||||||
|
|
||||||
uint32_t mWifiStationTimeout;
|
uint32_t mWifiStationTimeout;
|
||||||
uint32_t mNextTryTs;
|
uint32_t mNextTryTs;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue