Skip to content

Adding MQTT control and new weather features #81

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,15 +81,17 @@ Variables can be found inside `include/constants.h`.
```cpp
#pragma once

#define WIFI_HOSTNAME ""

#ifdef ESP8266
#define WIFI_SSID ""
#define WIFI_PASSWORD ""
#endif
#define WIFI_HOSTNAME ""

#define OTA_USERNAME ""
#define OTA_PASSWORD ""

#define LATITUDE ""
#define LONGITUDE ""

#define MQTTSERVERIP ""
```

also set username and password inside `upload.py`, if you want to use OTA Updates.
Expand Down
1 change: 1 addition & 0 deletions include/PluginManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class Plugin

virtual void teardown();
virtual void websocketHook(DynamicJsonDocument &request);
virtual void mqttHook(String topic, int message);
virtual void setup() = 0;
virtual void loop();
virtual const char *getName() const = 0;
Expand Down
8 changes: 3 additions & 5 deletions include/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,15 @@
#ifdef ENABLE_SERVER
// https://github.com/nayarsystems/posix_tz_db/blob/master/zones.json
#define NTP_SERVER "de.pool.ntp.org"
#define TZ_INFO "CET-1CEST,M3.5.0,M10.5.0/3"
#define TZ_INFO "GMT0BST,M3.5.0/1,M10.5.0"
#endif

#define COLS 16
#define ROWS 16

// set your city or coords (https://github.com/chubin/wttr.in)
#define WEATHER_LOCATION "Hamburg"
// weather update frequency (minutes)
#define WEATHER_UPDATE_FREQ 10

// name of WiFi created by the device if no known WiFi is available
#define WIFI_MANAGER_SSID "Ikea Display Setup WiFi"

// use ALL of the following to use static IP config
/*
Expand Down
20 changes: 20 additions & 0 deletions include/mqtt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#pragma once

#include <PubSubClient.h>
#include "secrets.h"
#include "websocket.h"
#include "storage.h"
#include "screen.h"

#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif

extern WiFiClient espClient;
extern PubSubClient MQTTclient;

void mqttCallback(char* topic, byte* payload, unsigned int length);

void mqttSetup();

void mqttReconnect();
33 changes: 17 additions & 16 deletions include/plugins/WeatherPlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,32 @@
#endif
#include <ArduinoJson.h>
#include "PluginManager.h"
#include "secrets.h"

class WeatherPlugin : public Plugin
{
private:
unsigned long lastUpdate = 0;
long lastUpdate = 0;
bool tick = true;
bool weatherSettingsLoaded = false;
int weatherTime; //number of hours or days in the future
int weatherMode; //0 for current, 1 for hourly, 2 for daily
HTTPClient http;

std::vector<int> thunderCodes = {200, 386, 389, 392, 395};
std::vector<int> cloudyCodes = {119, 122};
std::vector<int> partyCloudyCodes = {116};
std::vector<int> clearCodes = {113};
std::vector<int> fogCodes = {143, 248, 260};
std::vector<int> rainCodes = {
176, 293, 296, 299, 302,
305, 308, 311, 314, 353,
356, 359, 386, 389, 263,
266, 281, 284, 185};
std::vector<int> snowCodes = {
179, 227, 323, 326, 329,
332, 335, 338, 368, 371,
392, 395, 230, 350};
std::vector<int> thunderCodes = {95,96,99};
std::vector<int> cloudyCodes = {3};
std::vector<int> partyCloudyCodes = {1,2};
std::vector<int> clearCodes = {0};
std::vector<int> fogCodes = {45,48};
std::vector<int> rainCodes = {51,53,55,56,57,61,63,65,66,67,80,81,82};
std::vector<int> snowCodes = {71,73,75,77,85,86};

public:
void update();
void mqttHook(String topic, int message);
void getUpdate();
void parseUpdate();
void setup() override;
void loop() override;
const char *getName() const override;
void websocketHook(DynamicJsonDocument &request) override;
};
1 change: 1 addition & 0 deletions src/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ int Plugin::getId() const
void Plugin::teardown() {}
void Plugin::loop() {}
void Plugin::websocketHook(DynamicJsonDocument &request) {}
void Plugin::mqttHook(String topic, int message) {}

PluginManager::PluginManager() : nextPluginId(1) {}

Expand Down
83 changes: 28 additions & 55 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,97 +1,58 @@
#include <Arduino.h>
#include <SPI.h>

#ifdef ESP32
#include <WiFiManager.h>
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#include <WiFi.h>
#include <IPAddress.h>
#include <ESPmDNS.h>
#endif
#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif

#include "PluginManager.h"

#include "plugins/BreakoutPlugin.h"
#include "plugins/CirclePlugin.h"
#include "plugins/DrawPlugin.h"
#include "plugins/FireworkPlugin.h"
#include "plugins/BreakoutPlugin.h"
#include "plugins/SnakePlugin.h"
#include "plugins/GameOfLifePlugin.h"
#include "plugins/StarsPlugin.h"
#include "plugins/LinesPlugin.h"
#include "plugins/CirclePlugin.h"
#include "plugins/RainPlugin.h"
#include "plugins/SnakePlugin.h"
#include "plugins/StarsPlugin.h"
#include "plugins/FireworkPlugin.h"

#ifdef ENABLE_SERVER
#include "plugins/AnimationPlugin.h"
#include "plugins/BigClockPlugin.h"
#include "plugins/ClockPlugin.h"
#include "plugins/WeatherPlugin.h"
#include "plugins/AnimationPlugin.h"
#include "mqtt.h"
#endif

#include "asyncwebserver.h"
#include "websocket.h"
#include "secrets.h"
#include "ota.h"
#include "webserver.h"
#include "screen.h"
#include "secrets.h"
#include "websocket.h"

unsigned long previousMillis = 0;
unsigned long interval = 30000;

PluginManager pluginManager;
SYSTEM_STATUS currentStatus = NONE;
#ifdef ESP32
WiFiManager wifiManager;
#endif

unsigned long lastConnectionAttempt = 0;
const unsigned long connectionInterval = 10000;

#ifdef ESP32
void connectToWiFi()
{

// if a WiFi setup AP was started, reboot is required to clear routes
bool wifiWebServerStarted = false;
wifiManager.setWebServerCallback(
[&wifiWebServerStarted]()
{ wifiWebServerStarted = true; });

wifiManager.setHostname(WIFI_HOSTNAME);
wifiManager.autoConnect(WIFI_MANAGER_SSID);

if (MDNS.begin(WIFI_HOSTNAME))
{
MDNS.addService("http", "tcp", 80);
MDNS.setInstanceName(WIFI_HOSTNAME);
}
else
{
Serial.println("Could not start mDNS!");
}

if (wifiWebServerStarted)
{
// Reboot required, otherwise wifiManager server interferes with our server
Serial.println("Done running WiFi Manager webserver - rebooting");
ESP.restart();
}

lastConnectionAttempt = millis();
}
#endif

#ifdef ESP8266
void connectToWiFi()
{
Serial.println("Connecting to Wi-Fi...");

// Delete old config
WiFi.disconnect(true);

#if defined(IP_ADDRESS) && defined(GWY) && defined(SUBNET) && defined(DNS1) && \
defined(DNS2)
#if defined(IP_ADDRESS) && defined(GWY) && defined(SUBNET) && defined(DNS1) && defined(DNS2)
auto ip = IPAddress();
ip.fromString(IP_ADDRESS);

Expand Down Expand Up @@ -127,15 +88,25 @@ void connectToWiFi()
{
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());

#ifdef ESP32
if(MDNS.begin(WIFI_HOSTNAME)) {
MDNS.addService("http", "tcp", 80);
MDNS.setInstanceName(WIFI_HOSTNAME);
} else {
Serial.println("Could not start mDNS!");
}
#endif
}
else
{
Serial.println("\nFailed to connect to Wi-Fi. Please check credentials.");
}

lastConnectionAttempt = millis();

mqttSetup();
}
#endif

void setup()
{
Expand Down Expand Up @@ -185,6 +156,8 @@ void loop()
{
pluginManager.runActivePlugin();

MQTTclient.loop();

if (WiFi.status() != WL_CONNECTED && millis() - lastConnectionAttempt > connectionInterval)
{
Serial.println("Lost connection to Wi-Fi. Reconnecting...");
Expand Down
63 changes: 63 additions & 0 deletions src/mqtt.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <PubSubClient.h>
#include "secrets.h"
#include "PluginManager.h"
#include "mqtt.h"
#include "plugins/WeatherPlugin.h"

#ifdef ESP8266
#include <ESP8266WiFi.h>
#endif
#ifdef ESP32
#endif

WiFiClient espClient;
PubSubClient MQTTclient(espClient);

void mqttCallback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
String message;
for (int i = 0; i < length; i++) {
//Serial.print((char)payload[i]);
message += String((char)payload[i]);
}
if (topic == "Obegraensad/mode")
{
pluginManager.setActivePluginById(message.toInt());
} else {
pluginManager.getActivePlugin()->mqttHook(topic, message.toInt());
}
Serial.print(message);
Serial.println();
}

void mqttSetup(){
MQTTclient.setServer(MQTTSERVERIP, 1883);
MQTTclient.setCallback(mqttCallback);
mqttReconnect();
}

void mqttReconnect() {
// Loop until we're reconnected
while (!MQTTclient.connected()) {
Serial.print("Attempting MQTT connection...");
// Create a random client ID
String clientId = "ESPClient-";
clientId += String(random(0xffff), HEX);
// Attempt to connect
if (MQTTclient.connect(clientId.c_str())) {
Serial.println("connected");
MQTTclient.subscribe("Obegraensad/mode");
MQTTclient.subscribe("Obegraensad/weatherMode");
MQTTclient.subscribe("Obegraensad/weatherTime");
} else {
Serial.print("failed, rc=");
Serial.print(MQTTclient.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}

Loading