knx, wifi, time, mqtt, http

This commit is contained in:
Patrick Haßel 2024-10-10 12:57:29 +02:00
parent 4867d92b62
commit 773b4b297b
14 changed files with 286 additions and 65 deletions

View File

@ -4,3 +4,4 @@ board = esp12e
framework = arduino
lib_deps = https://github.com/thorsten-gehrig/arduino-tpuart-knx-user-forum
https://github.com/knolleary/pubsubclient
https://github.com/me-no-dev/ESPAsyncWebServer

20
src/Group.cpp Normal file
View File

@ -0,0 +1,20 @@
#include "Group.h"
#include <mqtt.h>
Group groups[500];
Group *groupCache(KnxTelegram *telegram) {
for (auto &&group: groups) {
if ((group.main == 0 && group.mid == 0 && group.sub == 0) || (group.main == telegram->getTargetMainGroup() && group.mid == telegram->getTargetMiddleGroup() && group.sub == telegram->getTargetSubGroup())) {
group.main = telegram->getTargetMainGroup();
group.mid = telegram->getTargetMiddleGroup();
group.sub = telegram->getTargetSubGroup();
group.timestamp = time(nullptr);
group.value = static_cast<double>(telegram->get1ByteIntValue()) + telegram->get2ByteIntValue() + (telegram->get4BitDirectionValue() ? telegram->get4BitStepsValue() : -telegram->get4BitStepsValue()) + telegram->get2ByteFloatValue() + telegram->get4ByteFloatValue();
return &group;
}
}
mqttLogError("group cache full");
return nullptr;
}

View File

@ -1,6 +1,8 @@
#ifndef GROUP_H
#define GROUP_H
#include <KnxTpUart.h>
class Group {
public:
@ -11,18 +13,14 @@ public:
uint8_t sub = 0;
uint8_t dpt = 0;
time_t timestamp = 0;
static Group groups[500];
static void write(uint8_t main, uint8_t mid, uint8_t sub) {
for (auto group: groups) {
if (group.main == main && group.mid == mid && group.sub == sub) {
group.
}
}
}
double value = 0;
};
extern Group groups[];
Group *groupCache(KnxTelegram *telegram);
#endif

9
src/http.cpp Normal file
View File

@ -0,0 +1,9 @@
#include "http.h"
#include <ESPAsyncWebServer.h>
AsyncWebServer server(80);
void httpSetup() {
server.begin();
}

6
src/http.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef HTTP_H
#define HTTP_H
void httpSetup();
#endif

45
src/knx.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "knx.h"
#include "Group.h"
#include "wifi.h"
#include "time_.h"
#include "mqtt.h"
#include <KnxTpUart.h>
KnxTpUart knx(&Serial1, "15.15.20");
void sendGroup(Group *group);
void knxSetup() {
Serial1.begin(19200, SERIAL_8E1);
knx.uartReset();
knx.setListenToBroadcasts(true);
}
void knxLoop() {
if (knx.serialEvent() != KNX_TELEGRAM) {
return;
}
KnxTelegram *telegram = knx.getReceivedTelegram();
mqttLogInfo("received: %d/%d/%d", telegram->getTargetMainGroup(), telegram->getTargetMiddleGroup(), telegram->getTargetSubGroup());
Group *group = groupCache(telegram);
sendGroup(group);
}
void sendGroup(Group *group) {
if (group == nullptr || !isTimeSet() || !isWiFiConnected()) {
return;
}
correctTime(&group->timestamp);
char topic[64];
snprintf(topic, sizeof topic, "knx/group/%d/%d/%d", group->main, group->mid, group->sub);
char payload[128];
snprintf(payload, sizeof payload, "%d/%d/%d %lld %f", group->main, group->mid, group->sub, group->timestamp, group->value);
mqttPublish(topic, payload);
}

8
src/knx.h Normal file
View File

@ -0,0 +1,8 @@
#ifndef KNX_H
#define KNX_H
void knxSetup();
void knxLoop();
#endif

View File

@ -1,70 +1,25 @@
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <KnxTpUart.h>
#include <PubSubClient.h>
KnxTpUart knx(&Serial1, "15.15.20");
PubSubClient mqtt;
void knxSetup();
void knxLoop();
void mqttLoop();
void mqttSetup();
void wifiSetup();
#include "knx.h"
#include "wifi.h"
#include "time_.h"
#include "mqtt.h"
#include "http.h"
void setup() {
Serial.begin(112500);
delay(500);
Serial.begin(112500);
Serial.print("\n\n\nStartup\n");
knxSetup();
wifiSetup();
configTime("Europe/Berlin", "de.pool.ntp.org");
timeSetup();
mqttSetup();
}
void wifiSetup() {
WiFi.hostname("KnxEsp");
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
while (WiFi.localIP() == 0UL) {
delay(100);
}
httpSetup();
}
void loop() {
knxLoop();
wifiLoop();
timeLoop();
mqttLoop();
}
void mqttSetup() {
mqtt.setServer("10.0.0.50", 1883);
mqtt.setBufferSize(512);
}
void mqttLoop() {
if (!mqtt.loop()) {
if (!mqtt.connect(WiFi.hostname().c_str())) {
mqtt.disconnect();
}
}
}
void knxSetup() {
Serial1.begin(19200, SERIAL_8E1);
knx.uartReset();
knx.setListenToBroadcasts(true);
}
void knxLoop() {
auto type = knx.serialEvent();
if (type != KNX_TELEGRAM) {
return;
}
KnxTelegram *t = knx.getReceivedTelegram();
Serial.printf("%3d / %3d / %3d len=%d, bool=%d\n", t->getTargetMainGroup(), t->getTargetMiddleGroup(), t->getTargetSubGroup(), t->getPayloadLength(), t->getBool());
}

56
src/mqtt.cpp Normal file
View File

@ -0,0 +1,56 @@
#include "mqtt.h"
#include "wifi.h"
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
PubSubClient mqtt;
void mqttSetup() {
mqtt.setServer("10.0.0.50", 1883);
mqtt.setBufferSize(512);
}
void mqttLoop() {
if (!isWiFiConnected()) {
mqtt.disconnect();
} else if (!mqtt.loop()) {
if (!mqtt.connect(WiFi.hostname().c_str())) {
mqtt.disconnect();
}
}
}
void mqttPublish(const char *topic, const char *payload) {
mqtt.publish(topic, payload);
}
String getLogPrefix(const char *level) {
tm info{};
getLocalTime(&info);
char buffer[20];
snprintf(buffer, sizeof buffer, "%04d-%02d-%02d %02d:%02d:%02d %5s ", info.tm_year, info.tm_mon, info.tm_mday, info.tm_hour, info.tm_min, info.tm_sec, level);
return {buffer};
}
void mqttLog(const char *level, const char *format, va_list vl) {
char message[400];
vsnprintf(message, sizeof message, format, vl);
const String topic = String("knx/log/") + level;
const String payload = getLogPrefix(level) + message;
mqttPublish(topic.c_str(), payload.c_str());
}
void mqttLogInfo(const char *message, ...) {
va_list vl;
va_start(vl, message);
mqttLog("info", message, vl);
va_end(vl);
}
void mqttLogError(const char *message, ...) {
va_list vl;
va_start(vl, message);
mqttLog("og/error", message, vl);
va_end(vl);
}

14
src/mqtt.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef MQTT_H
#define MQTT_H
void mqttSetup();
void mqttLoop();
void mqttPublish(const char *topic, const char *payload);
void mqttLogInfo(const char *message, ...);
void mqttLogError(const char *message, ...);
#endif

36
src/time_.cpp Normal file
View File

@ -0,0 +1,36 @@
#include "time_.h"
#include <Arduino.h>
#define TIME_MIN 1728424800
bool hasTime = false;
time_t timeCorrection = 0;
void timeSetup() {
configTime("Europe/Berlin", "de.pool.ntp.org");
}
void timeLoop() {
if (hasTime) {
return;
}
const time_t now = time(nullptr);
if (now >= TIME_MIN) {
hasTime = true;
timeCorrection = now - timeCorrection;
} else {
timeCorrection = now;
}
}
bool isTimeSet() {
return hasTime;
}
void correctTime(time_t *t) {
if (*t > 0 && *t < TIME_MIN) {
*t += timeCorrection;
}
}

14
src/time_.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef MY_TIME_H
#define MY_TIME_H
#include <Arduino.h>
void timeSetup();
void timeLoop();
bool isTimeSet();
void correctTime(time_t *t);
#endif

45
src/wifi.cpp Normal file
View File

@ -0,0 +1,45 @@
#include "wifi.h"
#include <ESP8266WiFi.h>
#define WIFI_TIMEOUT_MILLIS 20000
unsigned long wifiConnectBegin = 0;
bool wifiConnected = false;
bool isWiFiConnected() {
return wifiConnected;
}
void wifiSetup() {
wifiConnected = false;
WiFi.disconnect();
yield();
wifiConnectBegin = millis();
Serial.print("connecting wifi...\n");
WiFi.hostname("KnxEsp");
WiFi.begin("HappyNet", "1Grausame!Sackratte7");
}
void wifiLoop() {
if (!wifiConnected) {
if (WiFi.localIP() == 0UL) {
if (millis() - wifiConnectBegin > WIFI_TIMEOUT_MILLIS) {
if (wifiConnectBegin != 0) {
Serial.print("wifi timeout\n");
}
wifiSetup();
}
} else {
Serial.print("wifi connected\n");
wifiConnected = true;
}
} else {
if (WiFi.localIP() == 0UL) {
Serial.print("wifi disconnected\n");
wifiSetup();
}
}
}

14
src/wifi.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef WIFI_H
#define WIFI_H
bool isWiFiConnected();
void wifiSetup();
void wifiLoop();
void timeLoop();
bool isTimeSet();
#endif