Works with HA
This commit is contained in:
parent
34154d716d
commit
dab36592a6
|
|
@ -36,3 +36,4 @@
|
||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
schematic/water_temp/water_temp-backups/*
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ monitor_speed = 115200
|
||||||
build_flags =
|
build_flags =
|
||||||
-D DEBUG
|
-D DEBUG
|
||||||
-D MOCK_LORA
|
-D MOCK_LORA
|
||||||
|
-D MQTT_MAX_PACKET_SIZE=1024
|
||||||
lib_deps =
|
lib_deps =
|
||||||
https://github.com/tzapu/WiFiManager.git
|
https://github.com/tzapu/WiFiManager.git
|
||||||
bblanchon/ArduinoJson@^7.0.4
|
bblanchon/ArduinoJson@^7.0.4
|
||||||
|
|
|
||||||
|
|
@ -24,14 +24,9 @@ void LoraHandler::setup()
|
||||||
spi = new SPIClass(VSPI);
|
spi = new SPIClass(VSPI);
|
||||||
spi->begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
spi->begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);
|
||||||
|
|
||||||
// Create SX1278 instance
|
// --- FIX APPLIED HERE ---
|
||||||
radio = new SX1278(new SPIDriver(spi, LORA_CS));
|
Module* mod = new Module(LORA_CS, LORA_IRQ, LORA_RST, RADIOLIB_NC, *spi);
|
||||||
|
radio = new SX1278(mod);
|
||||||
// Configure RXEN/TXEN pins
|
|
||||||
pinMode(LORA_RXEN, OUTPUT);
|
|
||||||
pinMode(LORA_TXEN, OUTPUT);
|
|
||||||
digitalWrite(LORA_RXEN, LOW);
|
|
||||||
digitalWrite(LORA_TXEN, LOW);
|
|
||||||
|
|
||||||
// Initialize LoRa module
|
// Initialize LoRa module
|
||||||
int state = radio->begin();
|
int state = radio->begin();
|
||||||
|
|
@ -82,7 +77,6 @@ void LoraHandler::setup()
|
||||||
String currentLoRainfo = "LoRa Freq: " + String(freq) + " / SF:" + String(config.loraConfig.spreadingFactor) + " / CR: " + String(config.loraConfig.codingRate4);
|
String currentLoRainfo = "LoRa Freq: " + String(freq) + " / SF:" + String(config.loraConfig.spreadingFactor) + " / CR: " + String(config.loraConfig.codingRate4);
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", currentLoRainfo.c_str());
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "LoRa", currentLoRainfo.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ReceivedLoRaPacket LoraHandler::receivePacket()
|
ReceivedLoRaPacket LoraHandler::receivePacket()
|
||||||
{
|
{
|
||||||
ReceivedLoRaPacket receivedLoraPacket;
|
ReceivedLoRaPacket receivedLoraPacket;
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,6 @@
|
||||||
#define LORA_CS 18 // CS --> NSS
|
#define LORA_CS 18 // CS --> NSS
|
||||||
#define LORA_RST 14
|
#define LORA_RST 14
|
||||||
#define LORA_IRQ 26 // IRQ --> DIO0
|
#define LORA_IRQ 26 // IRQ --> DIO0
|
||||||
#define LORA_RXEN 2 // RX Enable
|
|
||||||
#define LORA_TXEN 13 // TX Enable
|
|
||||||
|
|
||||||
struct ReceivedLoRaPacket {
|
struct ReceivedLoRaPacket {
|
||||||
String text;
|
String text;
|
||||||
|
|
|
||||||
|
|
@ -53,12 +53,10 @@ void loop()
|
||||||
{
|
{
|
||||||
ReceivedLoRaPacket packet = lora.receivePacket();
|
ReceivedLoRaPacket packet = lora.receivePacket();
|
||||||
|
|
||||||
// Process received LoRa packet
|
|
||||||
if (!packet.text.isEmpty())
|
if (!packet.text.isEmpty())
|
||||||
{
|
{
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Processing LoRa packet: %s", packet.text.c_str());
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Processing LoRa packet: %s", packet.text.c_str());
|
||||||
|
|
||||||
// Try to parse JSON payload from sender
|
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
DeserializationError error = deserializeJson(doc, packet.text);
|
DeserializationError error = deserializeJson(doc, packet.text);
|
||||||
|
|
||||||
|
|
@ -70,26 +68,15 @@ void loop()
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Parsed - Temp: %.2f, Battery: %d, Boot: %d, Update: %d", temp, battery, boot, update);
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MAIN", "Parsed - Temp: %.2f, Battery: %d, Boot: %d, Update: %d", temp, battery, boot, update);
|
||||||
|
|
||||||
// Publish to MQTT with Home Assistant format
|
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
mqtt.publishSensorData(temp, packet.rssi, battery);
|
mqtt.publishSensorData(temp, packet.rssi, battery);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MAIN", "Failed to parse JSON: %s", error.c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
packet.rssi = 0;
|
|
||||||
packet.snr = 0.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (WiFi.status() == WL_CONNECTED) { // Check WiFi connection
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
IPAddress ip = WiFi.localIP();
|
IPAddress ip = WiFi.localIP();
|
||||||
String line0 = "IP: " + ip.toString();
|
String line0 = "IP: " + ip.toString();
|
||||||
display.show_message(line0.c_str(), 0);
|
display.show_message(line0.c_str(), 0);
|
||||||
} else {
|
} else {
|
||||||
// Optional: Display message indicating WiFi not connected
|
|
||||||
display.show_message("WiFi not connected", 0);
|
display.show_message("WiFi not connected", 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -100,14 +87,19 @@ void loop()
|
||||||
display.show_message(line2.c_str(), 2);
|
display.show_message(line2.c_str(), 2);
|
||||||
|
|
||||||
display.show_message("Data received OK", 3);
|
display.show_message("Data received OK", 3);
|
||||||
|
} else {
|
||||||
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MAIN", "Failed to parse JSON: %s", error.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Keep MQTT connection alive
|
// Kör MQTT-klientens loop
|
||||||
mqtt.mqttRun();
|
mqtt.mqttRun();
|
||||||
|
|
||||||
sleep(5);
|
// FIX: Ändra från 100ms till 1000ms (1 sekund).
|
||||||
|
// Detta förhindrar att ESP32:an kraschar/tappar WiFi av logg-spamming,
|
||||||
|
// men är tillräckligt snabbt för att inte missa LoRa-paket.
|
||||||
|
delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void checkButton()
|
void checkButton()
|
||||||
{
|
{
|
||||||
// check for button press
|
// check for button press
|
||||||
|
|
|
||||||
|
|
@ -9,21 +9,19 @@ extern Config config;
|
||||||
|
|
||||||
Mqtt::Mqtt(WiFiClient& wifiClient) : mqttClient(wifiClient) {
|
Mqtt::Mqtt(WiFiClient& wifiClient) : mqttClient(wifiClient) {
|
||||||
deviceId = "water_temp_receiver";
|
deviceId = "water_temp_receiver";
|
||||||
baseTopic = "homeassistant/sensor/water_temp";
|
// FIX 1: Låt bas-topic ligga helt fritt på roten, UTAN "homeassistant/".
|
||||||
|
// Det är hit din data (temperatur, rssi, batteri) kommer att skickas.
|
||||||
|
baseTopic = "water_temp_receiver";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::mqttSetup()
|
void Mqtt::mqttSetup()
|
||||||
{
|
{
|
||||||
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
|
||||||
if (config.mqttConfig.server.length() > 0)
|
if (config.mqttConfig.server.length() > 0)
|
||||||
{
|
{
|
||||||
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
||||||
IPAddress mqttServerIP;
|
IPAddress mqttServerIP;
|
||||||
if(mqttServerIP.fromString(config.mqttConfig.server)){
|
if(mqttServerIP.fromString(config.mqttConfig.server)){
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", mqttServerIP.toString().c_str());
|
|
||||||
mqttClient.setServer(mqttServerIP, config.mqttConfig.port);
|
mqttClient.setServer(mqttServerIP, config.mqttConfig.port);
|
||||||
}else{
|
}else{
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT Invalid IP address format %s", config.mqttConfig.server);
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT Invalid IP address format %s", config.mqttConfig.server);
|
||||||
|
|
@ -48,34 +46,22 @@ void Mqtt::mqttRun()
|
||||||
void Mqtt::mqttReconnect()
|
void Mqtt::mqttReconnect()
|
||||||
{
|
{
|
||||||
int retryCount = 0;
|
int retryCount = 0;
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Attempting MQTT connection...");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Attempting MQTT connection...");
|
||||||
// Loop until we're reconnected
|
|
||||||
|
|
||||||
while (!mqttClient.connected() && retryCount < 10)
|
while (!mqttClient.connected() && retryCount < 10)
|
||||||
{
|
{
|
||||||
// Attempt to connect
|
|
||||||
String mqttId = config.mqttConfig.id;
|
String mqttId = config.mqttConfig.id;
|
||||||
if (mqttId.isEmpty())
|
if (mqttId.isEmpty())
|
||||||
{
|
{
|
||||||
mqttId = "ESP32-";
|
mqttId = "ESP32-";
|
||||||
mqttId += String(random(0xffff), HEX);
|
mqttId += String(random(0xffff), HEX);
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Set ID: %s", mqttId );
|
|
||||||
config.setMqttId(mqttId);
|
config.setMqttId(mqttId);
|
||||||
config.writeData();
|
config.writeData();
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Server: %s", config.mqttConfig.server.c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Port: %d", config.mqttConfig.port);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "Username: %s", config.mqttConfig.username.c_str());
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "ID: %s", config.mqttConfig.id.c_str());
|
|
||||||
|
|
||||||
if (mqttClient.connect(mqttId.c_str(), config.mqttConfig.username.c_str(), config.mqttConfig.password.c_str()))
|
if (mqttClient.connect(mqttId.c_str(), config.mqttConfig.username.c_str(), config.mqttConfig.password.c_str()))
|
||||||
{
|
{
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "connected");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "connected");
|
||||||
|
|
||||||
// Setup Home Assistant Discovery on successful connection
|
|
||||||
setupHomeAssistantDiscovery();
|
setupHomeAssistantDiscovery();
|
||||||
|
|
||||||
String topic = config.mqttConfig.topic;
|
String topic = config.mqttConfig.topic;
|
||||||
|
|
@ -84,90 +70,120 @@ void Mqtt::mqttReconnect()
|
||||||
topic = config.mqttConfig.id;
|
topic = config.mqttConfig.id;
|
||||||
}
|
}
|
||||||
mqttClient.subscribe(topic.c_str());
|
mqttClient.subscribe(topic.c_str());
|
||||||
String message = "Subscribe to: " + topic;
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MQTT", "Not connected to mqtt, try again in 5 s.");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MQTT", "Not connected to mqtt, try again in 5 s.");
|
||||||
// Wait 5 seconds before retrying
|
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
|
retryCount++;
|
||||||
}
|
}
|
||||||
// Check if we're connected after the loop
|
|
||||||
if (!mqttClient.connected()) {
|
if (!mqttClient.connected()) {
|
||||||
// Connection failed after maximum retries
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to connect to MQTT broker after 10 retries");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to connect to MQTT broker after 10 retries");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::setupHomeAssistantDiscovery()
|
void Mqtt::setupHomeAssistantDiscovery()
|
||||||
{
|
{
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Setting up Home Assistant MQTT Discovery");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Setting up Home Assistant MQTT Discovery using char buffers");
|
||||||
|
|
||||||
// Temperature sensor discovery
|
// Skapa fasta teckenbuffertar för ämnen (topics) och JSON-data
|
||||||
|
char topicBuffer[128];
|
||||||
|
char jsonBuffer[512]; // 512 bytes räcker gott och väl för denna JSON
|
||||||
|
|
||||||
|
// Vi låter alla sensorer lyssna på den gemensamma JSON-strängen på /state
|
||||||
|
// Bygg upp strängarna med snabba snprintf istället för dynamiska String-objekt
|
||||||
|
char sharedStateTopic[64];
|
||||||
|
char availTopic[64];
|
||||||
|
snprintf(sharedStateTopic, sizeof(sharedStateTopic), "%s/state", baseTopic.c_str());
|
||||||
|
snprintf(availTopic, sizeof(availTopic), "%s/availability", baseTopic.c_str());
|
||||||
|
|
||||||
|
// 1. Temperature sensor discovery
|
||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc; // I v7 använder man bara JsonDocument, inte DynamicJsonDocument
|
||||||
doc["name"] = "Water Temperature";
|
doc["name"] = "Water Temperature";
|
||||||
doc["unique_id"] = "water_temp_temperature";
|
|
||||||
|
// Bygg unikt ID i en temporär buffert
|
||||||
|
char uniqueId[64];
|
||||||
|
snprintf(uniqueId, sizeof(uniqueId), "%s_temperature", deviceId.c_str());
|
||||||
|
doc["unique_id"] = uniqueId;
|
||||||
|
|
||||||
doc["unit_of_measurement"] = "°C";
|
doc["unit_of_measurement"] = "°C";
|
||||||
doc["device_class"] = "temperature";
|
doc["device_class"] = "temperature";
|
||||||
doc["state_topic"] = baseTopic + "/temperature";
|
doc["state_class"] = "measurement";
|
||||||
doc["availability_topic"] = baseTopic + "/availability";
|
doc["state_topic"] = sharedStateTopic;
|
||||||
|
doc["value_template"] = "{{ value_json.temperature }}";
|
||||||
|
doc["availability_topic"] = availTopic;
|
||||||
|
|
||||||
|
// I ArduinoJson v7 skapar man nästlade objekt direkt så här:
|
||||||
JsonObject device = doc["device"].to<JsonObject>();
|
JsonObject device = doc["device"].to<JsonObject>();
|
||||||
device["identifiers"][0] = deviceId;
|
device["identifiers"][0] = deviceId;
|
||||||
device["name"] = "Water Temperature Sensor";
|
device["name"] = "Water Temperature Sensor";
|
||||||
device["model"] = "Water Temp v1";
|
device["model"] = "Water Temp v1";
|
||||||
device["manufacturer"] = "DIY";
|
device["manufacturer"] = "DIY";
|
||||||
|
|
||||||
String payload;
|
// Serialisera direkt till vår fasta char-buffert
|
||||||
serializeJson(doc, payload);
|
serializeJson(doc, jsonBuffer, sizeof(jsonBuffer));
|
||||||
String topic = baseTopic + "/temperature/config";
|
|
||||||
mqttPublish(topic.c_str(), payload.c_str());
|
// Bygg config-topic och publicera
|
||||||
|
snprintf(topicBuffer, sizeof(topicBuffer), "homeassistant/sensor/%s/temperature/config", deviceId.c_str());
|
||||||
|
mqttPublishRetained(topicBuffer, jsonBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// RSSI sensor discovery
|
// 2. RSSI sensor discovery
|
||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["name"] = "LoRa RSSI";
|
doc["name"] = "LoRa RSSI";
|
||||||
doc["unique_id"] = "water_temp_rssi";
|
|
||||||
|
char uniqueId[64];
|
||||||
|
snprintf(uniqueId, sizeof(uniqueId), "%s_rssi", deviceId.c_str());
|
||||||
|
doc["unique_id"] = uniqueId;
|
||||||
|
|
||||||
doc["unit_of_measurement"] = "dBm";
|
doc["unit_of_measurement"] = "dBm";
|
||||||
doc["device_class"] = "signal_strength";
|
doc["device_class"] = "signal_strength";
|
||||||
doc["state_topic"] = baseTopic + "/rssi";
|
doc["state_class"] = "measurement";
|
||||||
doc["availability_topic"] = baseTopic + "/availability";
|
doc["state_topic"] = sharedStateTopic;
|
||||||
|
doc["value_template"] = "{{ value_json.rssi }}";
|
||||||
|
doc["availability_topic"] = availTopic;
|
||||||
|
|
||||||
JsonObject device = doc["device"].to<JsonObject>();
|
JsonObject device = doc["device"].to<JsonObject>();
|
||||||
device["identifiers"][0] = deviceId;
|
device["identifiers"][0] = deviceId;
|
||||||
|
device["name"] = "Water Temperature Sensor";
|
||||||
|
|
||||||
String payload;
|
serializeJson(doc, jsonBuffer, sizeof(jsonBuffer));
|
||||||
serializeJson(doc, payload);
|
|
||||||
String topic = baseTopic + "/rssi/config";
|
snprintf(topicBuffer, sizeof(topicBuffer), "homeassistant/sensor/%s/rssi/config", deviceId.c_str());
|
||||||
mqttPublish(topic.c_str(), payload.c_str());
|
mqttPublishRetained(topicBuffer, jsonBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Battery level discovery
|
// 3. Battery level discovery
|
||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["name"] = "Sender Battery";
|
doc["name"] = "Sender Battery";
|
||||||
doc["unique_id"] = "water_temp_battery";
|
|
||||||
|
char uniqueId[64];
|
||||||
|
snprintf(uniqueId, sizeof(uniqueId), "%s_battery", deviceId.c_str());
|
||||||
|
doc["unique_id"] = uniqueId;
|
||||||
|
|
||||||
doc["unit_of_measurement"] = "%";
|
doc["unit_of_measurement"] = "%";
|
||||||
doc["device_class"] = "battery";
|
doc["device_class"] = "battery";
|
||||||
doc["state_topic"] = baseTopic + "/battery";
|
doc["state_class"] = "measurement";
|
||||||
doc["availability_topic"] = baseTopic + "/availability";
|
doc["state_topic"] = sharedStateTopic;
|
||||||
|
doc["value_template"] = "{{ value_json.battery }}";
|
||||||
|
doc["availability_topic"] = availTopic;
|
||||||
|
|
||||||
JsonObject device = doc["device"].to<JsonObject>();
|
JsonObject device = doc["device"].to<JsonObject>();
|
||||||
device["identifiers"][0] = deviceId;
|
device["identifiers"][0] = deviceId;
|
||||||
|
device["name"] = "Water Temperature Sensor";
|
||||||
|
|
||||||
String payload;
|
serializeJson(doc, jsonBuffer, sizeof(jsonBuffer));
|
||||||
serializeJson(doc, payload);
|
|
||||||
String topic = baseTopic + "/battery/config";
|
snprintf(topicBuffer, sizeof(topicBuffer), "homeassistant/sensor/%s/battery/config", deviceId.c_str());
|
||||||
mqttPublish(topic.c_str(), payload.c_str());
|
mqttPublishRetained(topicBuffer, jsonBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set availability to online
|
// Sätt enheten till "online" med retain
|
||||||
String availTopic = baseTopic + "/availability";
|
mqttPublishRetained(availTopic, "online");
|
||||||
mqttPublish(availTopic.c_str(), "online");
|
|
||||||
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Home Assistant Discovery setup complete");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Home Assistant Discovery setup complete");
|
||||||
}
|
}
|
||||||
|
|
@ -197,7 +213,7 @@ void Mqtt::publishSensorData(float temp, int rssi, int battery)
|
||||||
String payload = String(battery);
|
String payload = String(battery);
|
||||||
mqttPublish(topic.c_str(), payload.c_str());
|
mqttPublish(topic.c_str(), payload.c_str());
|
||||||
|
|
||||||
// Also publish combined JSON
|
// Kombinerad JSON-statustopic
|
||||||
{
|
{
|
||||||
JsonDocument doc;
|
JsonDocument doc;
|
||||||
doc["temperature"] = serialized(String(temp, 2));
|
doc["temperature"] = serialized(String(temp, 2));
|
||||||
|
|
@ -213,17 +229,11 @@ void Mqtt::publishSensorData(float temp, int rssi, int battery)
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::callback(char *topic, uint8_t *payload, unsigned int length)
|
void Mqtt::callback(char *topic, uint8_t *payload, unsigned int length)
|
||||||
// Not implemented yet. Just for debug
|
|
||||||
{
|
{
|
||||||
// Create spot in memory for message
|
|
||||||
char message[length + 1];
|
char message[length + 1];
|
||||||
// Write payload to String
|
|
||||||
strncpy(message, (char *)payload, length);
|
strncpy(message, (char *)payload, length);
|
||||||
// Nullify last character to eliminate garbage at end
|
|
||||||
message[length] = '\0';
|
message[length] = '\0';
|
||||||
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Received: %s From: %s", message, topic);
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Received: %s", message);
|
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "From: %s", topic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mqtt::mqttPublish(const char* topic, const char* payload){
|
void Mqtt::mqttPublish(const char* topic, const char* payload){
|
||||||
|
|
@ -234,3 +244,12 @@ void Mqtt::mqttPublish(const char* topic, const char* payload){
|
||||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to publish message. MQTT client not connected.");
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to publish message. MQTT client not connected.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mqtt::mqttPublishRetained(const char* topic, const char* payload) {
|
||||||
|
if (mqttClient.connected()) {
|
||||||
|
mqttClient.publish(topic, payload, true);
|
||||||
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Published RETAINED message to %s", topic);
|
||||||
|
} else {
|
||||||
|
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to publish retained message. Not connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
#include "wifi.hpp"
|
#include "wifi.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
#define MQTT_MAX_PACKET_SIZE 1024
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -13,6 +14,7 @@ class Mqtt {
|
||||||
void mqttSetup();
|
void mqttSetup();
|
||||||
void mqttRun();
|
void mqttRun();
|
||||||
void mqttPublish(const char* topic, const char* payload);
|
void mqttPublish(const char* topic, const char* payload);
|
||||||
|
void mqttPublishRetained(const char* topic, const char* payload);
|
||||||
void publishTemperature(float temp);
|
void publishTemperature(float temp);
|
||||||
void publishRSSI(int rssi);
|
void publishRSSI(int rssi);
|
||||||
void publishSensorData(float temp, int rssi, int battery);
|
void publishSensorData(float temp, int rssi, int battery);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue