rdz_ttgo_sonde/RX_FSK/src/conn-mqtt.cpp

150 wiersze
3.9 KiB
C++

#include "../features.h"
#if FEATURE_MQTT
#include "../core.h"
#include <Arduino.h>
#include "conn-mqtt.h"
#include <WiFi.h>
#include <AsyncMqttClient.h>
#include <ESPmDNS.h>
#include "json.h"
extern const char *version_name;
extern const char *version_id;
/* configuration paramters are in the config, no need to duplicate :-)
{"mqtt.active", 0, &sonde.config.mqtt.active},
{"mqtt.id", 63, &sonde.config.mqtt.id},
{"mqtt.host", 63, &sonde.config.mqtt.host},
{"mqtt.port", 0, &sonde.config.mqtt.port},
{"mqtt.username", 63, &sonde.config.mqtt.username},
{"mqtt.password", 63, &sonde.config.mqtt.password},
{"mqtt.prefix", 63, &sonde.config.mqtt.prefix},
*/
TimerHandle_t mqttReconnectTimer;
extern t_wifi_state wifi_state;
/* Global initalization (on TTGO startup) */
void MQTT::init() {
}
// Internal helper function for netsetup
void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
/* Network initialization (as soon as network becomes available) */
void MQTT::netsetup() {
if (!sonde.config.mqtt.active)
return;
if (strlen(sonde.config.mqtt.host)==0)
return;
WiFi.hostByName(sonde.config.mqtt.host, this->ip);
Serial.println("[MQTT] pubsub client");
mqttClient.setServer(ip, sonde.config.mqtt.port);
snprintf(clientID, 20, "%s%04d", sonde.config.mqtt.id, (int)random(0, 1000));
clientID[20] = 0;
Serial.print(clientID);
mqttClient.setClientId(clientID);
if (strlen(sonde.config.mqtt.password) > 0) {
mqttClient.setCredentials(sonde.config.mqtt.username, sonde.config.mqtt.password);
}
}
void MQTT::updateSonde( SondeInfo *si ) {
if(!sonde.config.mqtt.active)
return;
if(1 /*connected*/) {
Serial.println("Sending sonde info via MQTT");
// TODO: Check if si is good / fresh
publishPacket(si);
}
}
void MQTT::updateStation( PosInfo *pi ) {
if(!sonde.config.mqtt.active)
return;
unsigned long now = millis();
if ( (lastMqttUptime == 0) || (now - lastMqttUptime > 60000) ) {
publishUptime();
lastMqttUptime = now;
}
}
String MQTT::getStatus() {
return String("");
}
// Internal (private) functions
int MQTT::connectToMqtt() {
if(mqttClient.connected())
return 1;
if(wifi_state != WIFI_CONNECTED)
return 0;
Serial.println("MQTT not connected, connecting....");
mqttClient.connect();
return 1;
}
void MQTT::publishUptime()
{
// ensure we've got connection
if(!connectToMqtt())
return;
Serial.println("[MQTT] writing");
char payload[256];
// maybe TODO: Use dynamic position if GPS is available?
// rxlat, rxlon only if not empty
snprintf(payload, 256, "{\"uptime\": %lu, \"user\": \"%s\", ", millis(), sonde.config.mqtt.username);
if( !isnan(sonde.config.rxlat) && !isnan(sonde.config.rxlon) ) {
snprintf(payload, 256, "%s\"rxlat\": %.5f, \"rxlon\": %.5f, ", payload, sonde.config.rxlat, sonde.config.rxlon);
}
snprintf(payload, 256, "%s\"SW\": \"%s\", \"VER\": \"%s\"}", payload, version_name, version_id);
Serial.println(payload);
char topic[128];
snprintf(topic, 128, "%s%s", sonde.config.mqtt.prefix, "uptime");
mqttClient.publish(topic, 1, 1, payload);
}
void MQTT::publishPacket(SondeInfo *si)
{
SondeData *s = &(si->d);
// ensure we've got connection
if(!connectToMqtt())
return;
char payload[1024];
payload[0] = '{';
int n = sonde2json(payload+1, 1023, si);
if(n<0) {
// ERROR
Serial.println("publishPacket: sonde2json failed, string too long");
}
strcat(payload, "}"); // terminate payload string
char topic[128];
snprintf(topic, 128, "%s%s", sonde.config.mqtt.prefix, "packet");
Serial.print(payload);
mqttClient.publish(topic, 1, 1, payload);
}
MQTT connMQTT;
#endif