Compare commits

...

3 commits

Author SHA1 Message Date
ee81edbcd2 exclude light sensor calls on unsupported devices
add mqtt default host define
2024-12-06 11:08:55 +01:00
adf6b38bfb add will message on <device>/status topic, so status is always available even when offline.
add wifi/bssid topic to track which AP is connected
fix reconnect breaking out of loop
2024-12-04 15:44:02 +01:00
67f1d03919 add mqtt module 2024-12-02 15:03:28 +01:00
7 changed files with 162 additions and 2 deletions

View file

@ -42,6 +42,7 @@ lib_deps =
https://github.com/dsbaars/GxEPD2#universal_pin
https://github.com/tzapu/WiFiManager.git#v2.0.17
rblb/Nostrduino@1.2.8
knolleary/PubSubClient@2.8
[env:lolin_s3_mini]
extends = btclock_base

View file

@ -92,6 +92,12 @@ void setup()
setupBitaxeFetchTask();
}
if (preferences.getBool("mqttEnabled", DEFAULT_MQTT_ENABLED))
{
setupMqtt();
setupMqttTask();
}
setupButtonTask();
setupOTA();

View file

@ -29,6 +29,7 @@
#include "PCA9685.h"
#include "BH1750.h"
#endif
#include "lib/mqtt.hpp"
#define NTP_SERVER "pool.ntp.org"
#define DEFAULT_TIME_OFFSET_SECONDS 3600

View file

@ -56,6 +56,10 @@
#define DEFAULT_BITAXE_ENABLED false
#define DEFAULT_BITAXE_HOSTNAME "bitaxe1"
#define DEFAULT_MQTT_ENABLED false
#define DEFAULT_MQTT_HOST ""
#define DEFAULT_MQTT_ROOTTOPIC "home/"
#define DEFAULT_ZAP_NOTIFY_ENABLED false
#define DEFAULT_ZAP_NOTIFY_PUBKEY "b5127a08cf33616274800a4387881a9f98e04b9c37116e92de5250498635c422"
#define DEFAULT_LED_FLASH_ON_ZAP true

131
src/lib/mqtt.cpp Normal file
View file

@ -0,0 +1,131 @@
#include "mqtt.hpp"
TaskHandle_t mqttTaskHandle = NULL;
WiFiClient wifiClient;
PubSubClient client(wifiClient);
// avoid circular deps, just forward declare externs used here.
#ifdef HAS_FRONTLIGHT
bool hasLightLevel();
float getLightLevel();
#endif
String getMyHostname();
void onMqttCallback(char* topic, byte* payload, unsigned int length)
{
Serial.println("MQTT message arrived");
}
const String getDeviceTopic()
{
const String hostname = getMyHostname();
const String rootTopic = preferences.getString("mqttRootTopic", DEFAULT_MQTT_ROOTTOPIC);
String fullTopic = rootTopic;
if (!rootTopic.endsWith("/") && rootTopic != "")
{
fullTopic += "/";
}
fullTopic += hostname + "/";
return String(fullTopic);
}
boolean connectMqtt()
{
const String willTopic = getDeviceTopic() + "status";
boolean result = client.connect("btclockClient", willTopic.c_str(), 0, true, "offline");
if (!result)
{
Serial.println("[MQTT] could not connect");
return result;
}
publish("status", "online", true);
return result;
}
void setupMqtt()
{
const String host = preferences.getString("mqttHost", DEFAULT_MQTT_HOST);
if (host == "")
{
Serial.println("[MQTT] host not set");
return;
}
Serial.print("[MQTT] host: ");
Serial.println(host.c_str());
IPAddress addr((uint32_t)0);
if(!WiFi.hostByName(host.c_str(), addr))
{
Serial.println("[MQTT] host lookup fail");
return;
}
client.setServer(addr, 1883);
client.setCallback(onMqttCallback);
connectMqtt();
}
void mqttTask(void *pvParameters)
{
int t=0;
while (1)
{
client.loop();
vTaskDelay(pdMS_TO_TICKS(1000));
if (t++ % 10 == 0)
{
if (!client.connected())
{
// reconnect
if (!connectMqtt())
continue;
}
#ifdef HAS_FRONTLIGHT
if (hasLightLevel())
{
std::string lux_s = std::to_string(static_cast<int>(std::round(getLightLevel())));
publish("sensors/lux", lux_s.c_str());
}
#endif
if (WiFi.isConnected())
{
int8_t rssi = WiFi.RSSI();
std::string rssi_s = std::to_string(static_cast<int>(rssi));
publish("wifi/rssi", rssi_s.c_str());
publish("wifi/bssid", WiFi.BSSIDstr().c_str());
}
std::string heap_free_s = std::to_string(static_cast<int>(ESP.getFreeHeap()));
publish("mem/heap_free", heap_free_s.c_str());
std::string heap_size_s = std::to_string(static_cast<int>(ESP.getHeapSize()));
publish("mem/heap_size", heap_size_s.c_str());
}
}
}
void setupMqttTask()
{
xTaskCreate(mqttTask, "mqttTask", 8192, NULL, 10, &mqttTaskHandle);
}
void publish(const char *topic, const char *value)
{
publish(topic, value, false);
}
void publish(const char *topic, const char *value, boolean retain)
{
if (!client.connected())
{
Serial.println("[MQTT] not connected");
return;
}
const String fullTopic = getDeviceTopic() + topic;
if (!client.publish(fullTopic.c_str(), value, retain))
{
Serial.println("[MQTT] could not write");
}
}

10
src/lib/mqtt.hpp Normal file
View file

@ -0,0 +1,10 @@
#pragma once
#include <Arduino.h>
#include "lib/shared.hpp"
#include "PubSubClient.h"
void setupMqtt();
void setupMqttTask();
void publish(const char *topic, const char *value);
void publish(const char *topic, const char *value, boolean retain);

View file

@ -510,7 +510,10 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
settings["timePerScreen"].as<uint>() * 60);
}
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey", "nostrRelay", "bitaxeHostname", "nostrZapPubkey", "httpAuthUser", "httpAuthPass", "gitReleaseUrl"};
String strSettings[] = {"hostnamePrefix", "mempoolInstance", "nostrPubKey",
"nostrRelay", "bitaxeHostname", "nostrZapPubkey",
"httpAuthUser", "httpAuthPass", "gitReleaseUrl",
"mqttHost", "mqttRootTopic"};
for (String setting : strSettings)
{
@ -546,7 +549,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
"mdnsEnabled", "otaEnabled", "stealFocus",
"mcapBigChar", "useSatsSymbol", "useBlkCountdown",
"suffixPrice", "disableLeds", "ownDataSource",
"mowMode", "suffixShareDot",
"mowMode", "suffixShareDot", "mqttEnabled",
"flAlwaysOn", "flDisable", "flFlashOnUpd",
"mempoolSecure", "useNostr", "bitaxeEnabled",
"nostrZapNotify", "stagingSource", "httpAuthEnabled"};
@ -711,6 +714,10 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
root["bitaxeEnabled"] = preferences.getBool("bitaxeEnabled", DEFAULT_BITAXE_ENABLED);
root["bitaxeHostname"] = preferences.getString("bitaxeHostname", DEFAULT_BITAXE_HOSTNAME);
root["mqttEnabled"] = preferences.getBool("mqttEnabled", DEFAULT_MQTT_ENABLED);
root["mqttHost"] = preferences.getString("mqttHost", "");
root["mqttRootTopic"] = preferences.getString("mqttRootTopic", DEFAULT_MQTT_ROOTTOPIC);
root["httpAuthEnabled"] = preferences.getBool("httpAuthEnabled", DEFAULT_HTTP_AUTH_ENABLED);
root["httpAuthUser"] = preferences.getString("httpAuthUser", DEFAULT_HTTP_AUTH_USERNAME);
root["httpAuthPass"] = preferences.getString("httpAuthPass", DEFAULT_HTTP_AUTH_PASSWORD);