Added mqttclass
This commit is contained in:
parent
c5cbf0da8a
commit
7f477f5cc8
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"mqtt":
|
||||
{
|
||||
"server": "192.168.1.80",
|
||||
"port": 1883,
|
||||
"username": "simon",
|
||||
"password": "bajsa123",
|
||||
"id": ""
|
||||
},
|
||||
"lora":
|
||||
{
|
||||
"frequency": 433775000,
|
||||
"spreadingFactor": 12,
|
||||
"signalBandwidth": 125000,
|
||||
"codingRate4": 5,
|
||||
"power": 20
|
||||
}
|
||||
}
|
||||
|
|
@ -13,6 +13,10 @@ platform = espressif32
|
|||
board = ttgo-lora32-v1
|
||||
framework = arduino
|
||||
monitor_speed = 115200
|
||||
build_flags =
|
||||
-D DEBUG
|
||||
lib_deps =
|
||||
https://github.com/tzapu/WiFiManager.git
|
||||
bblanchon/ArduinoJson@^7.0.4
|
||||
peterus/esp-logger@^1.0.0
|
||||
knolleary/PubSubClient@^2.8
|
||||
|
|
|
|||
|
|
@ -0,0 +1,149 @@
|
|||
#include <ArduinoJson.h>
|
||||
#include <SPIFFS.h>
|
||||
#include "config.hpp"
|
||||
#include "logger.h"
|
||||
|
||||
extern logging::Logger logger;
|
||||
|
||||
Config::Config()
|
||||
{
|
||||
_filePath = "/config.json";
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Init config");
|
||||
if (!SPIFFS.begin(false))
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "SPIFFS Mount Failed");
|
||||
return;
|
||||
}
|
||||
readFile(SPIFFS, _filePath.c_str());
|
||||
}
|
||||
|
||||
void Config::readFile(fs::FS &fs, const char *fileName)
|
||||
{
|
||||
JsonDocument data;
|
||||
File configFile = fs.open(fileName, "r");
|
||||
DeserializationError error = deserializeJson(data, configFile);
|
||||
if (error)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to read file, using default configuration");
|
||||
}
|
||||
|
||||
MqttConfig mqtt;
|
||||
mqtt.server = data["mqtt"]["server"].as<String>();
|
||||
mqtt.port = data["mqtt"]["port"].as<int>();
|
||||
mqtt.username = data["mqtt"]["username"].as<String>();
|
||||
mqtt.password = data["mqtt"]["password"].as<String>();
|
||||
mqtt.id = data["mqtt"]["id"].as<String>();
|
||||
|
||||
LoraConfig lora;
|
||||
lora.frequency = data["lora"]["frequency"].as<long>();
|
||||
lora.spreadingFactor = data["lora"]["spreadingFactor"].as<int>();
|
||||
lora.signalBandwidth = data["lora"]["signalBandwidth"].as<long>();
|
||||
lora.codingRate4 = data["lora"]["codingRate4"].as<int>();
|
||||
lora.power = data["lora"]["power"].as<int>();
|
||||
logConfigInfo(data);
|
||||
configFile.close();
|
||||
|
||||
mqttConfig = mqtt;
|
||||
loraConfig = lora;
|
||||
|
||||
isConfigLoaded = true;
|
||||
|
||||
}
|
||||
|
||||
void Config::writeData()
|
||||
{
|
||||
JsonDocument doc;
|
||||
|
||||
JsonObject mqttJson = doc["mqtt"].to<JsonObject>();
|
||||
mqttJson["server"] = this->mqttConfig.server;
|
||||
mqttJson["port"] = this->mqttConfig.port;
|
||||
mqttJson["username"] = this->mqttConfig.username;
|
||||
mqttJson["password"] = this->mqttConfig.password;
|
||||
mqttJson["id"] = this->mqttConfig.id;
|
||||
mqttJson["topic"] = this->mqttConfig.topic;
|
||||
|
||||
JsonObject lora = doc["lora"].to<JsonObject>();
|
||||
lora["frequency"] = 433775000;
|
||||
lora["spreadingFactor"] = 12;
|
||||
lora["signalBandwidth"] = 125000;
|
||||
lora["codingRate4"] = 5;
|
||||
lora["power"] = 20;
|
||||
|
||||
// Delete existing file, otherwise the configuration is appended to the file
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Write DATA to file");
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Server: " + String(this->mqttConfig.server)).c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Port: " + String(this->mqttConfig.port)).c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Username: " + String(this->mqttConfig.username)).c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Password: " + String(this->mqttConfig.password)).c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("ID: " + String(this->mqttConfig.id)).c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", ("Topic: " + String(this->mqttConfig.topic)).c_str());
|
||||
|
||||
|
||||
SPIFFS.remove(_filePath);
|
||||
File configFile = SPIFFS.open(_filePath.c_str(), "w");
|
||||
if (!configFile)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to open file for writing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Serialize the JSON document to the file
|
||||
if (serializeJson(doc, configFile) == 0)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "CONFIG", "Failed to write to file");
|
||||
}
|
||||
|
||||
logConfigInfo(doc);
|
||||
// Close the file
|
||||
configFile.close();
|
||||
}
|
||||
|
||||
void Config::logConfigInfo(JsonDocument& doc) {
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", "Logging configuration data:");
|
||||
|
||||
JsonObject rootJson = doc.as<JsonObject>();
|
||||
|
||||
// Iterate over each key-value pair at the root level
|
||||
for (auto kvp : rootJson) {
|
||||
String key = kvp.key().c_str();
|
||||
String value;
|
||||
|
||||
// Get the value associated with the key
|
||||
const JsonVariant& jsonValue = kvp.value();
|
||||
|
||||
// Check the type of the JSON value and convert it to a string accordingly
|
||||
if (jsonValue.is<String>()) {
|
||||
value = jsonValue.as<String>();
|
||||
} else if (jsonValue.is<int>()) {
|
||||
value = String(jsonValue.as<int>());
|
||||
} else if (jsonValue.is<long>()) {
|
||||
value = String(jsonValue.as<long>());
|
||||
} else if (jsonValue.is<bool>()) {
|
||||
value = jsonValue.as<bool>() ? "true" : "false";
|
||||
} else if (jsonValue.is<JsonArray>() || jsonValue.is<JsonObject>()) {
|
||||
JsonDocument tempJson;
|
||||
tempJson.set(jsonValue);
|
||||
serializeJson(tempJson, value);
|
||||
} else if (jsonValue.isNull()) {
|
||||
value = "null";
|
||||
} else {
|
||||
value = "Unsupported data type";
|
||||
}
|
||||
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "CONFIG", (key + ": " + value).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
void MqttConfig::setMqtt(const String &server, const int &port, const String &username, const String &password, const String &topic)
|
||||
{
|
||||
this->server = server;
|
||||
this->port = port;
|
||||
this->username = username;
|
||||
this->password = password;
|
||||
this->topic = topic;
|
||||
}
|
||||
|
||||
void MqttConfig::setId(const String &id)
|
||||
{
|
||||
this->id = id;
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
|
||||
class MqttConfig {
|
||||
public:
|
||||
String server;
|
||||
int port;
|
||||
String username;
|
||||
String password;
|
||||
String id;
|
||||
String topic;
|
||||
void setId(const String& id);
|
||||
void setMqtt(const String& server, const int& port, const String& username, const String& password, const String& topic);
|
||||
};
|
||||
|
||||
class LoraConfig {
|
||||
public:
|
||||
long frequency;
|
||||
int spreadingFactor;
|
||||
long signalBandwidth;
|
||||
int codingRate4;
|
||||
int power;
|
||||
};
|
||||
|
||||
class Config {
|
||||
public:
|
||||
bool isConfigLoaded = false;
|
||||
MqttConfig mqttConfig;
|
||||
LoraConfig loraConfig;
|
||||
Config();
|
||||
void writeData();
|
||||
void setMqttConfig(const String& server, const int& port, const String& username, const String& password, const String& topic) {
|
||||
mqttConfig.setMqtt(server, port, username, password, topic);
|
||||
}
|
||||
void setMqttId(const String& id){
|
||||
mqttConfig.setId(id);
|
||||
}
|
||||
|
||||
void logConfigInfo(JsonDocument& configJson);
|
||||
private:
|
||||
void readFile(fs::FS &fs, const char *fileName);
|
||||
String _filePath;
|
||||
};
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
|
@ -1,92 +1,92 @@
|
|||
|
||||
#include <logger.h>
|
||||
#include "wifi.hpp"
|
||||
#include "mqtt.hpp"
|
||||
#include "config.hpp"
|
||||
|
||||
#include <WiFi.h>
|
||||
|
||||
Config config;
|
||||
WiFiServer server(80);
|
||||
|
||||
// Assign output variables to GPIO pins
|
||||
const int output5 = 25;
|
||||
WiFiClient wclient;
|
||||
Mqtt mqtt(wclient);
|
||||
|
||||
#define TRIGGER_PIN 0
|
||||
void checkButton();
|
||||
|
||||
bool portalRunning = false;
|
||||
logging::Logger logger;
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
|
||||
#ifndef DEBUG
|
||||
logger.setDebugLevel(logging::LoggerLevel::LOGGER_LEVEL_INFO);
|
||||
#endif
|
||||
pinMode(TRIGGER_PIN, INPUT);
|
||||
|
||||
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
|
||||
// Setup Serial monitor
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
WiFi.mode(WIFI_STA);
|
||||
config = Config();
|
||||
|
||||
setupWifi("island_temp");
|
||||
server.begin();
|
||||
while (!config.isConfigLoaded)
|
||||
{
|
||||
delay(10);
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MAIN", "COnfig not loaded yet...");
|
||||
}
|
||||
delay(100);
|
||||
setupWifi("island_temp", false);
|
||||
|
||||
mqtt.mqttSetup();
|
||||
// server.begin();
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
WiFiClient client = server.available(); // Listen for incoming clients
|
||||
|
||||
mqtt.mqttRun();
|
||||
if (portalRunning)
|
||||
{
|
||||
wm.process();
|
||||
}
|
||||
mqtt.mqttPublish("test/sensor", "123");
|
||||
checkButton();
|
||||
}
|
||||
|
||||
if (client)
|
||||
{ // If a new client connects,
|
||||
Serial.println("New Client."); // print a message out in the serial port
|
||||
String currentLine = ""; // make a String to hold incoming data from the client
|
||||
while (client.connected())
|
||||
{ // loop while the client's connected
|
||||
if (client.available())
|
||||
{ // if there's bytes to read from the client,
|
||||
char c = client.read(); // read a byte, then
|
||||
Serial.write(c); // print it out the serial monitor
|
||||
header += c;
|
||||
if (c == '\n')
|
||||
{ // if the byte is a newline character
|
||||
// if the current line is blank, you got two newline characters in a row.
|
||||
// that's the end of the client HTTP request, so send a response:
|
||||
if (currentLine.length() == 0)
|
||||
{
|
||||
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
|
||||
// and a content-type so the client knows what's coming, then a blank line:
|
||||
client.println("HTTP/1.1 200 OK");
|
||||
client.println("Content-type:text/html");
|
||||
client.println("Connection: close");
|
||||
client.println();
|
||||
void checkButton()
|
||||
{
|
||||
// check for button press
|
||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
||||
{
|
||||
// poor mans debounce/press-hold, code not ideal for production
|
||||
delay(50);
|
||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Button Pressed once, wait 3s");
|
||||
// still holding button for 3000 ms
|
||||
delay(3000); // reset delay hold
|
||||
if (digitalRead(TRIGGER_PIN) == LOW)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Button Pressed, Starting Portal");
|
||||
wm.startWebPortal();
|
||||
portalRunning = true;
|
||||
}
|
||||
|
||||
// Display the HTML web page
|
||||
client.println("<!DOCTYPE html><html>");
|
||||
client.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
|
||||
client.println("<link rel=\"icon\" href=\"data:,\">");
|
||||
// CSS to style the on/off buttons
|
||||
// Feel free to change the background-color and font-size attributes to fit your preferences
|
||||
client.println("<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}");
|
||||
client.println(".button { background-color: #195B6A; border: none; color: white; padding: 16px 40px;");
|
||||
client.println("text-decoration: none; font-size: 30px; margin: 2px; cursor: pointer;}");
|
||||
client.println(".button2 {background-color: #77878A;}</style></head>");
|
||||
// start portal w delay
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "Starting config portal");
|
||||
Serial.println("Starting config portal");
|
||||
wm.setConfigPortalTimeout(120);
|
||||
|
||||
// Web Page Heading
|
||||
client.println("<body><h1>ESP8266 Web Server</h1>");
|
||||
|
||||
// Display current state, and ON/OFF buttons for GPIO 5
|
||||
// If the output5State is off, it displays the ON button
|
||||
client.println("</body></html>");
|
||||
|
||||
// The HTTP response ends with another blank line
|
||||
client.println();
|
||||
// Break out of the while loop
|
||||
break;
|
||||
}
|
||||
else
|
||||
{ // if you got a newline, then clear currentLine
|
||||
currentLine = "";
|
||||
}
|
||||
}
|
||||
else if (c != '\r')
|
||||
{ // if you got anything else but a carriage return character,
|
||||
currentLine += c; // add it to the end of the currentLine
|
||||
}
|
||||
if (!wm.startConfigPortal("island_temp"))
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "failed to connect or hit timeout");
|
||||
delay(3000);
|
||||
// ESP.restart();
|
||||
}
|
||||
else
|
||||
{
|
||||
// if you get here you have connected to the WiFi
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Main", "connected...yeey :)");
|
||||
}
|
||||
}
|
||||
// Clear the header variable
|
||||
header = "";
|
||||
// Close the connection
|
||||
client.stop();
|
||||
Serial.println("Client disconnected.");
|
||||
Serial.println("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
#include "mqtt.hpp"
|
||||
#include "config.hpp"
|
||||
#include <PubSubClient.h>
|
||||
#include "logger.h"
|
||||
|
||||
extern logging::Logger logger;
|
||||
|
||||
extern Config config;
|
||||
|
||||
Mqtt::Mqtt(WiFiClient& wifiClient) : mqttClient(wifiClient) {}
|
||||
|
||||
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)
|
||||
{
|
||||
// strcpy(mqttHost, config.mqtt.server.c_str());
|
||||
String message = "MqttServer: " + config.mqttConfig.server + ", MqttPort: " + config.mqttConfig.port;
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
||||
IPAddress mqttServerIP;
|
||||
if(mqttServerIP.fromString(config.mqttConfig.server)){
|
||||
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", mqttServerIP.toString().c_str());
|
||||
mqttClient.setServer(mqttServerIP, config.mqttConfig.port);
|
||||
}else{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT Invalid IP address format %s", config.mqttConfig.server);
|
||||
}
|
||||
mqttClient.setCallback(callback);
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "MQTT config is not set");
|
||||
}
|
||||
}
|
||||
|
||||
void Mqtt::mqttRun()
|
||||
{
|
||||
delay(100);
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "MQTT RUN");
|
||||
if (WiFi.status() == WL_CONNECTED && !mqttClient.loop()) {
|
||||
mqttReconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void Mqtt::mqttReconnect()
|
||||
{
|
||||
int retryCount = 0;
|
||||
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Attempting MQTT connection...");
|
||||
// Loop until we're reconnected
|
||||
|
||||
while (!mqttClient.connected() && retryCount < 10)
|
||||
{
|
||||
// Attempt to connect
|
||||
String mqttId = config.mqttConfig.id;
|
||||
if (mqttId.isEmpty())
|
||||
{
|
||||
mqttId = "ESP32-";
|
||||
mqttId += String(random(0xffff), HEX);
|
||||
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Set ID: %s", mqttId );
|
||||
config.setMqttId(mqttId);
|
||||
config.writeData();
|
||||
}
|
||||
if (ESP.getFreeHeap() < 5000) { // Check for minimum heap space
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Not enough heap space for MQTT connection");
|
||||
return;
|
||||
}
|
||||
|
||||
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", "Password: %s", config.mqttConfig.password.c_str());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT CONFIG", "ID: %s", config.mqttConfig.id.c_str());
|
||||
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "HEAP: %d", ESP.getFreeHeap());
|
||||
if (mqttClient.connect(mqttId.c_str(), "simon", "bajsa123"))
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "connected");
|
||||
String topic = config.mqttConfig.topic;
|
||||
if (topic.isEmpty())
|
||||
{
|
||||
topic = config.mqttConfig.id;
|
||||
}
|
||||
mqttClient.subscribe(topic.c_str());
|
||||
String message = "Subscribe to: " + topic;
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", message.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "MQTT", "Not connected to mqtt, try again in 5 s.");
|
||||
// Wait 5 seconds before retrying
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
// Check if we're connected after the loop
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
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];
|
||||
// Write payload to String
|
||||
strncpy(message, (char *)payload, length);
|
||||
// Nullify last character to eliminate garbage at end
|
||||
message[length] = '\0';
|
||||
|
||||
// Create correct object
|
||||
|
||||
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){
|
||||
if (mqttClient.connected()) {
|
||||
mqttClient.publish(topic, payload);
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "MQTT", "Published message to %s: %s", topic, payload);
|
||||
} else {
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_ERROR, "MQTT", "Failed to publish message. MQTT client not connected.");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef MQTT_H
|
||||
#define MQTT_H
|
||||
|
||||
#include "wifi.hpp"
|
||||
#include "config.hpp"
|
||||
#include <WiFi.h>
|
||||
#include <PubSubClient.h>
|
||||
|
||||
|
||||
class Mqtt {
|
||||
public:
|
||||
Mqtt(WiFiClient& wifiClient);
|
||||
void mqttSetup();
|
||||
void mqttRun();
|
||||
void mqttPublish(const char* topic, const char* payload);
|
||||
private:
|
||||
void mqttReconnect();
|
||||
static void callback(char *topic, uint8_t *payload, unsigned int length);
|
||||
PubSubClient mqttClient;
|
||||
};
|
||||
|
||||
#endif /* MQTT_H */
|
||||
|
|
@ -1,205 +1,148 @@
|
|||
#include "wifi.hpp"
|
||||
#include <logger.h>
|
||||
|
||||
WiFiManager wm;
|
||||
|
||||
extern Config config;
|
||||
extern logging::Logger logger;
|
||||
// Flag for saving data
|
||||
bool shouldSaveConfig = false;
|
||||
|
||||
// Variables to hold data from custom textboxes
|
||||
char testString[50] = "test value";
|
||||
int testNumber = 1234;
|
||||
char mqtt_server[40];
|
||||
int mqtt_port = 1883;
|
||||
char mqtt_username[34] = "";
|
||||
char mqtt_password[34] = "";
|
||||
char mqtt_topic[34] = "";
|
||||
|
||||
// Variable to store the HTTP request
|
||||
String header;
|
||||
|
||||
void setupWifi(const char *setupWifi)
|
||||
void setupWifi(const char *setupWifi, bool resetOnStart)
|
||||
{
|
||||
// Change to true when testing to force configuration every time we run
|
||||
bool forceConfig = false;
|
||||
|
||||
bool spiffsSetup = loadConfigFile();
|
||||
if (!spiffsSetup)
|
||||
{
|
||||
Serial.println(F("Forcing config mode as there is no saved config"));
|
||||
forceConfig = true;
|
||||
}
|
||||
|
||||
// Reset settings (only for development)
|
||||
// wm.resetSettings();
|
||||
|
||||
// Set config save notify callback
|
||||
wm.setSaveConfigCallback(saveConfigCallback);
|
||||
|
||||
// Set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
|
||||
wm.setAPCallback(configModeCallback);
|
||||
|
||||
// Custom elements
|
||||
|
||||
// Text box (String) - 50 characters maximum
|
||||
WiFiManagerParameter custom_text_box("key_text", "Enter your string here", testString, 50);
|
||||
|
||||
// Need to convert numerical input to string to display the default value.
|
||||
char convertedValue[6];
|
||||
sprintf(convertedValue, "%d", testNumber);
|
||||
|
||||
// Text box (Number) - 7 characters maximum
|
||||
WiFiManagerParameter custom_text_box_num("key_num", "Enter your number here", convertedValue, 7);
|
||||
|
||||
// Add all defined parameters
|
||||
wm.addParameter(&custom_text_box);
|
||||
wm.addParameter(&custom_text_box_num);
|
||||
|
||||
if (forceConfig)
|
||||
// Run if we need a configuration
|
||||
{
|
||||
if (!wm.startConfigPortal(setupWifi))
|
||||
// Change to true when testing to force configuration every time we run
|
||||
bool forceConfig = false;
|
||||
wm.setConfigPortalTimeout(60);
|
||||
// Reset settings (only for development)
|
||||
if (resetOnStart)
|
||||
{
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
// reset and try again, or maybe put it to deep sleep
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
wm.resetSettings();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wm.autoConnect(setupWifi))
|
||||
|
||||
// Set config save notify callback
|
||||
wm.setSaveConfigCallback(saveConfigCallback);
|
||||
|
||||
// Set callback that gets called when connecting to previous WiFi fails, and enters Access Point mode
|
||||
wm.setAPCallback(configModeCallback);
|
||||
|
||||
// Custom elements
|
||||
WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
|
||||
WiFiManagerParameter custom_mqtt_username("username", "mqtt username", mqtt_username, 50);
|
||||
WiFiManagerParameter custom_mqtt_password("password", "mqtt password", mqtt_password, 50);
|
||||
WiFiManagerParameter custom_mqtt_topic("topic", "mqtt topic", mqtt_topic, 50);
|
||||
|
||||
// Text box (String) - 50 characters maximum
|
||||
WiFiManagerParameter custom_text_box("key_text", "Enter your string here", testString, 50);
|
||||
|
||||
// Need to convert numerical input to string to display the default value.
|
||||
char convertedValue[6];
|
||||
sprintf(convertedValue, "%d", testNumber);
|
||||
|
||||
// Text box (Number) - 7 characters maximum
|
||||
WiFiManagerParameter custom_text_box_num("key_num", "Enter your number here", convertedValue, 7);
|
||||
char convertedMqttPort[6];
|
||||
sprintf(convertedMqttPort, "%d", mqtt_port);
|
||||
WiFiManagerParameter custom_mqtt_port("port", "mqtt port", convertedMqttPort, 6);
|
||||
|
||||
// Add all defined parameters
|
||||
wm.addParameter(&custom_text_box);
|
||||
wm.addParameter(&custom_text_box_num);
|
||||
wm.addParameter(&custom_mqtt_server);
|
||||
wm.addParameter(&custom_mqtt_port);
|
||||
wm.addParameter(&custom_mqtt_username);
|
||||
wm.addParameter(&custom_mqtt_password);
|
||||
wm.addParameter(&custom_mqtt_topic);
|
||||
|
||||
if (forceConfig)
|
||||
// Run if we need a configuration
|
||||
{
|
||||
Serial.println("failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
// if we still have not connected restart and try all over again
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
if (!wm.startConfigPortal(setupWifi))
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
// reset and try again, or maybe put it to deep sleep
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!wm.autoConnect(setupWifi))
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_WARN, "Wifi", "failed to connect and hit timeout");
|
||||
delay(3000);
|
||||
// if we still have not connected restart and try all over again
|
||||
ESP.restart();
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, we are connected to the WiFi
|
||||
// If we get here, we are connected to the WiFi
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.print("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "");
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "WiFi connected");
|
||||
String message = "IP address: " + String(WiFi.localIP());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
||||
|
||||
// Lets deal with the user config values
|
||||
// Lets deal with the user config values
|
||||
|
||||
// Copy the string value
|
||||
strncpy(testString, custom_text_box.getValue(), sizeof(testString));
|
||||
Serial.print("testString: ");
|
||||
Serial.println(testString);
|
||||
// Copy the string value
|
||||
strncpy(testString, custom_text_box.getValue(), sizeof(testString));
|
||||
Serial.print("testString: ");
|
||||
Serial.println(testString);
|
||||
|
||||
// Convert the number value
|
||||
testNumber = atoi(custom_text_box_num.getValue());
|
||||
Serial.print("testNumber: ");
|
||||
Serial.println(testNumber);
|
||||
// Convert the number value
|
||||
testNumber = atoi(custom_text_box_num.getValue());
|
||||
Serial.print("testNumber: ");
|
||||
Serial.println(testNumber);
|
||||
|
||||
// Save the custom parameters to FS
|
||||
if (shouldSaveConfig)
|
||||
{
|
||||
saveConfigFile();
|
||||
}
|
||||
mqtt_port = atoi(custom_mqtt_port.getValue());
|
||||
strncpy(mqtt_server, custom_mqtt_server.getValue(), sizeof(mqtt_server));
|
||||
strncpy(mqtt_username, custom_mqtt_username.getValue(), sizeof(mqtt_username));
|
||||
strncpy(mqtt_password, custom_mqtt_password.getValue(), sizeof(mqtt_password));
|
||||
strncpy(mqtt_topic, custom_mqtt_topic.getValue(), sizeof(mqtt_topic));
|
||||
|
||||
|
||||
// Save the custom parameters to FS
|
||||
if (shouldSaveConfig)
|
||||
{
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Save config");
|
||||
saveConfigFile();
|
||||
}
|
||||
}
|
||||
|
||||
void saveConfigCallback()
|
||||
// Callback notifying us of the need to save configuration
|
||||
{
|
||||
Serial.println("Should save config");
|
||||
shouldSaveConfig = true;
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Should save config");
|
||||
shouldSaveConfig = true;
|
||||
}
|
||||
|
||||
|
||||
void configModeCallback(WiFiManager *myWiFiManager)
|
||||
// Called when config mode launched
|
||||
{
|
||||
Serial.println("Entered Configuration Mode");
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Entered Configuration Mode");
|
||||
|
||||
String message = "Config SSID: " + String(myWiFiManager->getConfigPortalSSID());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
||||
|
||||
Serial.print("Config SSID: ");
|
||||
Serial.println(myWiFiManager->getConfigPortalSSID());
|
||||
|
||||
Serial.print("Config IP Address: ");
|
||||
Serial.println(WiFi.softAPIP());
|
||||
|
||||
message = "Config IP Address: " + String(WiFi.softAPIP());
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", message.c_str());
|
||||
}
|
||||
|
||||
|
||||
bool loadConfigFile()
|
||||
// Load existing configuration file
|
||||
{
|
||||
// Uncomment if we need to format filesystem
|
||||
// SPIFFS.format();
|
||||
|
||||
// Read configuration from FS json
|
||||
Serial.println("Mounting File System...");
|
||||
|
||||
// May need to make it begin(true) first time you are using SPIFFS
|
||||
if (SPIFFS.begin(false) || SPIFFS.begin(true))
|
||||
{
|
||||
Serial.println("mounted file system");
|
||||
if (SPIFFS.exists(JSON_CONFIG_FILE))
|
||||
{
|
||||
// The file exists, reading and loading
|
||||
Serial.println("reading config file");
|
||||
File configFile = SPIFFS.open(JSON_CONFIG_FILE, "r");
|
||||
if (configFile)
|
||||
{
|
||||
Serial.println("Opened configuration file");
|
||||
size_t size = configFile.size();
|
||||
// Allocate a buffer to store contents of the file.
|
||||
std::unique_ptr<char[]> buf(new char[size]);
|
||||
|
||||
configFile.readBytes(buf.get(), size);
|
||||
JsonDocument doc;
|
||||
auto deserializeError = deserializeJson(doc, buf.get());
|
||||
serializeJson(doc, Serial);
|
||||
// JsonObject& json = jsonBuffer.parseObject(buf.get());
|
||||
// json.printTo(Serial);
|
||||
if (!deserializeError)
|
||||
{
|
||||
Serial.println("Parsing JSON");
|
||||
strcpy(testString, doc["testString"]);
|
||||
testNumber = doc["testNumber"].as<int>();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("failed to load json config");
|
||||
}
|
||||
configFile.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
Serial.println("Missing Json file");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void saveConfigFile()
|
||||
// Save Config in JSON format
|
||||
{
|
||||
Serial.println(F("Saving configuration..."));
|
||||
|
||||
// Create a JSON document
|
||||
JsonDocument json;
|
||||
json["testString"] = testString;
|
||||
json["testNumber"] = testNumber;
|
||||
|
||||
// Open config file
|
||||
File configFile = SPIFFS.open(JSON_CONFIG_FILE, "w");
|
||||
if (!configFile)
|
||||
{
|
||||
// Error, file did not open
|
||||
Serial.println("failed to open config file for writing");
|
||||
}
|
||||
|
||||
// Serialize JSON data to write to file
|
||||
serializeJsonPretty(json, Serial);
|
||||
if (serializeJson(json, configFile) == 0)
|
||||
{
|
||||
// Error writing file
|
||||
Serial.println(F("Failed to write to file"));
|
||||
}
|
||||
// Close file
|
||||
configFile.close();
|
||||
logger.log(logging::LoggerLevel::LOGGER_LEVEL_INFO, "Wifi", "Saving configuration...");
|
||||
config.setMqttConfig(mqtt_server, mqtt_port, mqtt_username, mqtt_password, mqtt_topic);
|
||||
config.writeData();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,22 +9,16 @@
|
|||
#include <WiFi.h>
|
||||
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
|
||||
#include <ArduinoJson.h>
|
||||
#include "config.hpp"
|
||||
|
||||
|
||||
extern WiFiManager wm;
|
||||
|
||||
// Flag for saving data
|
||||
extern bool shouldSaveConfig;
|
||||
|
||||
// JSON configuration file
|
||||
#define JSON_CONFIG_FILE "/test_config.json"
|
||||
// Variables to hold data from custom textboxes
|
||||
extern char testString[50] ;
|
||||
extern int testNumber;
|
||||
|
||||
// Variable to store the HTTP request
|
||||
extern String header;
|
||||
|
||||
void setupWifi(const char *apName);
|
||||
void setupWifi(const char *apName, bool resetOnStart);
|
||||
void saveConfigCallback();
|
||||
void configModeCallback(WiFiManager *myWiFiManager);
|
||||
bool loadConfigFile();
|
||||
|
|
|
|||
|
|
@ -110,3 +110,20 @@ void loop() {
|
|||
|
||||
// delay(3000);
|
||||
}
|
||||
|
||||
|
||||
/* Calc battery:
|
||||
float voltage = analogRead(35) / 4096.0 * 7.46;
|
||||
uint8_t percentage = 100;
|
||||
if (voltage > 1) {
|
||||
// Only display if there is a valid reading
|
||||
Serial.println("Voltage = " + String(voltage));
|
||||
percentage = 2836.9625 * pow(voltage, 4) - 43987.4889 * pow(voltage, 3) + 255233.8134 * pow(voltage, 2) - 656689.7123 * voltage + 632041.7303;
|
||||
if (voltage >= 4.20) percentage = 100;
|
||||
if (voltage <= 3.50) percentage = 0;
|
||||
Serial.println("Percentage = " + String(percentage));
|
||||
}
|
||||
|
||||
|
||||
|
||||
*/
|
||||
Loading…
Reference in New Issue