mqtt + admin ui + cycle FIX
This commit is contained in:
parent
801b99a3a7
commit
b6ea584a4b
111
index.html
111
index.html
@ -55,29 +55,55 @@
|
|||||||
.state {
|
.state {
|
||||||
}
|
}
|
||||||
|
|
||||||
.countdown {
|
.topic {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stateOn {
|
.stateOn {
|
||||||
background-color: palegreen;
|
background-color: #7aca7a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.stateOff {
|
.stateOff {
|
||||||
background-color: indianred;
|
background-color: #ae4d4d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.switchOn {
|
.switchOn {
|
||||||
|
border-radius: 0.5em;
|
||||||
|
filter: brightness(50%);
|
||||||
background-color: palegreen;
|
background-color: palegreen;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switchOn_Active {
|
||||||
|
z-index: 9999;
|
||||||
|
filter: brightness(120%);
|
||||||
|
box-shadow: 0 0 5px #006400, 0 0 10px #228B22, 0 0 20px #32CD32;
|
||||||
|
}
|
||||||
|
|
||||||
.switchOff {
|
.switchOff {
|
||||||
|
border-radius: 0.5em;
|
||||||
|
filter: brightness(50%);
|
||||||
background-color: indianred;
|
background-color: indianred;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switchOff_Active {
|
||||||
|
z-index: 9999;
|
||||||
|
filter: brightness(120%);
|
||||||
|
box-shadow: 0 0 5px #8B0000, 0 0 10px #B22222, 0 0 20px #FF4500;
|
||||||
|
}
|
||||||
|
|
||||||
.switchCycle {
|
.switchCycle {
|
||||||
|
border-radius: 0.5em;
|
||||||
|
filter: brightness(50%);
|
||||||
background-color: lightskyblue;
|
background-color: lightskyblue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.switchCycle_Active {
|
||||||
|
z-index: 9999;
|
||||||
|
filter: brightness(120%);
|
||||||
|
box-shadow: 0 0 5px #00008B, 0 0 10px #1E90FF, 0 0 20px #00BFFF;
|
||||||
|
}
|
||||||
|
|
||||||
.config {
|
.config {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
@ -91,6 +117,10 @@
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adminHidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
@media (min-width: 1000px) {
|
@media (min-width: 1000px) {
|
||||||
body {
|
body {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
@ -107,7 +137,16 @@
|
|||||||
|
|
||||||
<div id="relayList"></div>
|
<div id="relayList"></div>
|
||||||
|
|
||||||
|
<button id="admin" onclick="toggleAdmin()">Admin</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
let admin = false;
|
||||||
|
|
||||||
|
function toggleAdmin() {
|
||||||
|
admin = !admin;
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
const title = document.getElementById("title");
|
const title = document.getElementById("title");
|
||||||
const relayList = document.getElementById("relayList");
|
const relayList = document.getElementById("relayList");
|
||||||
|
|
||||||
@ -115,10 +154,6 @@
|
|||||||
return `http://10.42.0.204/${path}`;
|
return `http://10.42.0.204/${path}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setState(index, value) {
|
|
||||||
set("state", index, value ? 'true' : 'false');
|
|
||||||
}
|
|
||||||
|
|
||||||
function set(key, index, value) {
|
function set(key, index, value) {
|
||||||
request(`${key}${index}=${encodeURIComponent(value)}`);
|
request(`${key}${index}=${encodeURIComponent(value)}`);
|
||||||
}
|
}
|
||||||
@ -133,15 +168,10 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function updateState(relayTag, state) {
|
function updateState(relayTag, state) {
|
||||||
const tag = relayTag.getElementsByClassName("state")[0];
|
|
||||||
if (state) {
|
if (state) {
|
||||||
tag.classList.add("stateOn");
|
|
||||||
tag.classList.remove("stateOff");
|
|
||||||
relayTag.classList.add("stateOn");
|
relayTag.classList.add("stateOn");
|
||||||
relayTag.classList.remove("stateOff");
|
relayTag.classList.remove("stateOff");
|
||||||
} else {
|
} else {
|
||||||
tag.classList.add("stateOff");
|
|
||||||
tag.classList.remove("stateOn");
|
|
||||||
relayTag.classList.add("stateOff");
|
relayTag.classList.add("stateOff");
|
||||||
relayTag.classList.remove("stateOn");
|
relayTag.classList.remove("stateOn");
|
||||||
}
|
}
|
||||||
@ -153,10 +183,12 @@
|
|||||||
const DAY = (24 * HOUR);
|
const DAY = (24 * HOUR);
|
||||||
|
|
||||||
function countdownString(relayData, millis) {
|
function countdownString(relayData, millis) {
|
||||||
const rest = Math.ceil((millis - relayData.stateMillis - (Date.now() - dataAge)) / SECOND) * SECOND;
|
const rest = Math.ceil((millis - relayData.stateAgeMillis - (Date.now() - dataAge)) / SECOND) * SECOND;
|
||||||
if (millis <= 0 || (relayData.onCount === 0 && !relayData.state)) {
|
const cycle = relayData.onCount !== 0 && relayData.onMillis > 0 && relayData.offMillis > 0;
|
||||||
|
if (millis <= 0 || (!cycle && !relayData.state)) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
const days = rest / DAY;
|
const days = rest / DAY;
|
||||||
const hours = rest / HOUR;
|
const hours = rest / HOUR;
|
||||||
const minutes = rest / MINUTE;
|
const minutes = rest / MINUTE;
|
||||||
@ -204,13 +236,37 @@
|
|||||||
title.innerText = data.hostname;
|
title.innerText = data.hostname;
|
||||||
for (let index = 0; index < data.relays.length; index++) {
|
for (let index = 0; index < data.relays.length; index++) {
|
||||||
const relayData = data.relays[index];
|
const relayData = data.relays[index];
|
||||||
const relay = document.getElementById("relay" + index) || create(index);
|
const relayTag = document.getElementById("relay" + index) || create(index);
|
||||||
updateValue(relay, "name", "input", relayData.name);
|
updateValue(relayTag, "name", "input", relayData.name);
|
||||||
updateState(relay, relayData.state);
|
updateValue(relayTag, "topic", "input", relayData.topic);
|
||||||
updateCountdown(relay, relayData);
|
updateState(relayTag, relayData.state);
|
||||||
updateValue(relay, "onMillis", "input", relayData.onMillis);
|
updateCountdown(relayTag, relayData);
|
||||||
updateValue(relay, "offMillis", "input", relayData.offMillis);
|
updateValue(relayTag, "onMillis", "input", relayData.onMillis);
|
||||||
updateValue(relay, "initial", "select", relayData.initial);
|
updateValue(relayTag, "offMillis", "input", relayData.offMillis);
|
||||||
|
updateValue(relayTag, "initial", "select", relayData.initial);
|
||||||
|
|
||||||
|
const cycle = relayData.onCount !== 0 && relayData.onMillis > 0 && relayData.offMillis > 0;
|
||||||
|
|
||||||
|
const switchOn = relayTag.getElementsByClassName("switchOn")[0];
|
||||||
|
if (!cycle && relayData.state) {
|
||||||
|
switchOn.classList.add("switchOn_Active");
|
||||||
|
} else {
|
||||||
|
switchOn.classList.remove("switchOn_Active");
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchOff = relayTag.getElementsByClassName("switchOff")[0];
|
||||||
|
if (!cycle && !relayData.state) {
|
||||||
|
switchOff.classList.add("switchOff_Active");
|
||||||
|
} else {
|
||||||
|
switchOff.classList.remove("switchOff_Active");
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchCycle = relayTag.getElementsByClassName("switchCycle")[0];
|
||||||
|
if (cycle) {
|
||||||
|
switchCycle.classList.add("switchCycle_Active");
|
||||||
|
} else {
|
||||||
|
switchCycle.classList.remove("switchCycle_Active");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -276,9 +332,11 @@
|
|||||||
const header = newDiv(relay, "flex");
|
const header = newDiv(relay, "flex");
|
||||||
newInput(relayIndex, header, "name", "name", "text");
|
newInput(relayIndex, header, "name", "name", "text");
|
||||||
newDiv(header, "countdown");
|
newDiv(header, "countdown");
|
||||||
newDiv(header, "state");
|
|
||||||
|
|
||||||
const config = newDiv(relay, "flex");
|
const topicDiv = newDiv(relay, "flex admin adminHidden");
|
||||||
|
newInput(relayIndex, topicDiv, "topic", "topic", "text");
|
||||||
|
|
||||||
|
const config = newDiv(relay, "flex admin adminHidden");
|
||||||
newInput(relayIndex, config, "config onMillis", "onMillis", "number");
|
newInput(relayIndex, config, "config onMillis", "onMillis", "number");
|
||||||
newInput(relayIndex, config, "config offMillis", "offMillis", "number");
|
newInput(relayIndex, config, "config offMillis", "offMillis", "number");
|
||||||
newSelect(relayIndex, config, "config initial", "initial", [["OFF", "Init: Aus"], ["ON", "Init: Ein"], ["CYCLE", "Init: Zyklus"]]);
|
newSelect(relayIndex, config, "config initial", "initial", [["OFF", "Init: Aus"], ["ON", "Init: Ein"], ["CYCLE", "Init: Zyklus"]]);
|
||||||
@ -300,6 +358,13 @@
|
|||||||
const relayData = data.relays[index];
|
const relayData = data.relays[index];
|
||||||
const relayTag = document.getElementById("relay" + index) || create(index);
|
const relayTag = document.getElementById("relay" + index) || create(index);
|
||||||
updateCountdown(relayTag, relayData);
|
updateCountdown(relayTag, relayData);
|
||||||
|
for (let element of document.getElementsByClassName("admin")) {
|
||||||
|
if (admin) {
|
||||||
|
element.classList.remove("adminHidden");
|
||||||
|
} else {
|
||||||
|
element.classList.add("adminHidden");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ upload_speed = 921600
|
|||||||
monitor_speed = 115200
|
monitor_speed = 115200
|
||||||
build.filesystem = littlefs
|
build.filesystem = littlefs
|
||||||
lib_deps = bblanchon/ArduinoJson @ 7.4.2
|
lib_deps = bblanchon/ArduinoJson @ 7.4.2
|
||||||
|
knolleary/PubSubClient
|
||||||
|
|
||||||
[env:Sonoff4ChPro]
|
[env:Sonoff4ChPro]
|
||||||
platform = ${common.platform}
|
platform = ${common.platform}
|
||||||
@ -24,6 +25,9 @@ board = esp32dev
|
|||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
upload_speed = ${common.upload_speed}
|
upload_speed = ${common.upload_speed}
|
||||||
monitor_speed = ${common.monitor_speed}
|
monitor_speed = ${common.monitor_speed}
|
||||||
|
build_type = debug
|
||||||
|
debug_tool = esp-prog
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
build.filesystem = ${common.build.filesystem}
|
build.filesystem = ${common.build.filesystem}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
build_flags = -D Sonoff4ChPro -D ESP32_TESTBOARD -D CORE_DEBUG_LEVEL=0
|
build_flags = -D Sonoff4ChPro -D ESP32_TESTBOARD -D CORE_DEBUG_LEVEL=0
|
||||||
@ -45,6 +49,9 @@ board = esp32dev
|
|||||||
framework = ${common.framework}
|
framework = ${common.framework}
|
||||||
upload_speed = ${common.upload_speed}
|
upload_speed = ${common.upload_speed}
|
||||||
monitor_speed = ${common.monitor_speed}
|
monitor_speed = ${common.monitor_speed}
|
||||||
|
build_type = debug
|
||||||
|
debug_tool = esp-prog
|
||||||
|
monitor_filters = esp32_exception_decoder
|
||||||
build.filesystem = ${common.build.filesystem}
|
build.filesystem = ${common.build.filesystem}
|
||||||
lib_deps = ${common.lib_deps}
|
lib_deps = ${common.lib_deps}
|
||||||
build_flags = -D GosundSP111 -D ESP32_TESTBOARD -D CORE_DEBUG_LEVEL=0
|
build_flags = -D GosundSP111 -D ESP32_TESTBOARD -D CORE_DEBUG_LEVEL=0
|
||||||
31
src/Output.h
31
src/Output.h
@ -27,15 +27,20 @@ protected:
|
|||||||
|
|
||||||
unsigned long stateMillis = 0;
|
unsigned long stateMillis = 0;
|
||||||
|
|
||||||
|
virtual void publish() {
|
||||||
|
// nothing
|
||||||
|
}
|
||||||
|
|
||||||
void _write(const bool wanted) {
|
void _write(const bool wanted) {
|
||||||
const auto current = get();
|
const auto current = get();
|
||||||
if (wanted != current) {
|
if (wanted != current) {
|
||||||
|
digitalWrite(pin, wanted ^ inverted ? HIGH : LOW);
|
||||||
|
publish();
|
||||||
if (logState) {
|
if (logState) {
|
||||||
Serial.printf("[RELAY] \"%s\" = %s\n", name.c_str(), wanted ? "ON" : "OFF");
|
Serial.printf("[RELAY] \"%s\" = %s\n", name.c_str(), wanted ? "ON" : "OFF");
|
||||||
}
|
}
|
||||||
stateMillis = millis();
|
stateMillis = millis();
|
||||||
}
|
}
|
||||||
digitalWrite(pin, wanted ^ inverted ? HIGH : LOW);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _applyInitial() {
|
void _applyInitial() {
|
||||||
@ -117,30 +122,6 @@ public:
|
|||||||
offMillis = value;
|
offMillis = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
Initial getInitial() const {
|
|
||||||
return initial;
|
|
||||||
}
|
|
||||||
|
|
||||||
long getOnCount() const {
|
|
||||||
return onCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long getOnMillis() const {
|
|
||||||
return onMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long getOffMillis() const {
|
|
||||||
return offMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned long getStateMillis() const {
|
|
||||||
return millis() - stateMillis;
|
|
||||||
}
|
|
||||||
|
|
||||||
String getName() const {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
34
src/Relay.h
34
src/Relay.h
@ -3,22 +3,28 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Output.h"
|
#include "Output.h"
|
||||||
|
#include "mqtt.h"
|
||||||
|
|
||||||
class Relay final : public Output {
|
class Relay final : public Output {
|
||||||
|
|
||||||
String nameFallback;
|
String nameFallback;
|
||||||
|
|
||||||
|
String topicFallback;
|
||||||
|
|
||||||
|
String topic;
|
||||||
|
|
||||||
const uint8_t index;
|
const uint8_t index;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Relay(const uint8_t index, const char *name, const uint8_t pin, const bool inverted, const bool logState) : Output(name, pin, inverted, logState), nameFallback(name), index(index) {
|
Relay(const uint8_t index, const String &topic, const char *name, const uint8_t pin, const bool inverted, const bool logState) : Output(name, pin, inverted, logState), nameFallback(name), topicFallback(topic), topic(topic), index(index) {
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() override {
|
void setup() override {
|
||||||
Output::setup();
|
Output::setup();
|
||||||
Output::setName(configRead(path("name"), nameFallback));
|
Output::setName(configRead(path("name"), nameFallback));
|
||||||
|
topic = configRead(path("topic"), topicFallback);
|
||||||
Output::setInitial(configRead(path("initial"), INITIAL_OFF));
|
Output::setInitial(configRead(path("initial"), INITIAL_OFF));
|
||||||
Output::setOnMillis(configRead(path("onMillis"), 0L));
|
Output::setOnMillis(configRead(path("onMillis"), 0L));
|
||||||
Output::setOffMillis(configRead(path("offMillis"), 0L));
|
Output::setOffMillis(configRead(path("offMillis"), 0L));
|
||||||
@ -27,7 +33,12 @@ public:
|
|||||||
|
|
||||||
void setName(const String &value) override {
|
void setName(const String &value) override {
|
||||||
Output::setName(value);
|
Output::setName(value);
|
||||||
configWrite(path("name"), nameFallback, value, false);
|
configWrite(path("name"), nameFallback, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setTopic(const String &value) {
|
||||||
|
topic = value;
|
||||||
|
configWrite(path("topic"), topicFallback, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setInitial(const Initial value) override {
|
void setInitial(const Initial value) override {
|
||||||
@ -45,6 +56,17 @@ public:
|
|||||||
configWrite(path("offMillis"), 0L, value);
|
configWrite(path("offMillis"), 0L, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void json(const JsonObject json) const {
|
||||||
|
json["name"] = name;
|
||||||
|
json["topic"] = topic;
|
||||||
|
json["state"] = get();
|
||||||
|
json["stateAgeMillis"] = millis() - stateMillis;
|
||||||
|
json["initial"] = initialToString(initial);
|
||||||
|
json["onCount"] = onCount;
|
||||||
|
json["onMillis"] = onMillis;
|
||||||
|
json["offMillis"] = offMillis;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
String path(const char *name) const {
|
String path(const char *name) const {
|
||||||
@ -53,6 +75,14 @@ private:
|
|||||||
return String(path);
|
return String(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
void publish() override {
|
||||||
|
JsonDocument doc;
|
||||||
|
json(doc.to<JsonObject>());
|
||||||
|
mqttPublish(topic, doc);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
26
src/http.cpp
26
src/http.cpp
@ -18,13 +18,19 @@ WebServer server(80);
|
|||||||
|
|
||||||
bool httpRunning = false;
|
bool httpRunning = false;
|
||||||
|
|
||||||
void httpRelay(const int index, Output &relay) {
|
void httpRelay(const int index, Relay &relay) {
|
||||||
const auto nameKey = String("name") + index;
|
const auto nameKey = String("name") + index;
|
||||||
if (server.hasArg(nameKey)) {
|
if (server.hasArg(nameKey)) {
|
||||||
const auto name = server.arg(nameKey);
|
const auto name = server.arg(nameKey);
|
||||||
relay.setName(name);
|
relay.setName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto topicKey = String("topic") + index;
|
||||||
|
if (server.hasArg(topicKey)) {
|
||||||
|
const auto topic = server.arg(topicKey);
|
||||||
|
relay.setTopic(topic);
|
||||||
|
}
|
||||||
|
|
||||||
const auto stateKey = String("state") + index;
|
const auto stateKey = String("state") + index;
|
||||||
if (server.hasArg(stateKey)) {
|
if (server.hasArg(stateKey)) {
|
||||||
const auto state = server.arg(stateKey);
|
const auto state = server.arg(stateKey);
|
||||||
@ -66,26 +72,16 @@ void httpRelay(const int index, Output &relay) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void httpRelayJson(const Output &relay, const JsonObject json) {
|
|
||||||
json["name"] = relay.getName();
|
|
||||||
json["state"] = relay.get();
|
|
||||||
json["stateMillis"] = relay.getStateMillis();
|
|
||||||
json["initial"] = initialToString(relay.getInitial());
|
|
||||||
json["onCount"] = relay.getOnCount();
|
|
||||||
json["onMillis"] = relay.getOnMillis();
|
|
||||||
json["offMillis"] = relay.getOffMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
void httpStatus() {
|
void httpStatus() {
|
||||||
JsonDocument json;
|
JsonDocument json;
|
||||||
json["hostname"] = WiFi.getHostname();
|
json["hostname"] = WiFi.getHostname();
|
||||||
|
|
||||||
const auto relays = json["relays"].to<JsonArray>();
|
const auto relays = json["relays"].to<JsonArray>();
|
||||||
httpRelayJson(relay0, relays.add<JsonObject>());
|
relay0.json(relays.add<JsonObject>());
|
||||||
#ifdef Sonoff4ChPro
|
#ifdef Sonoff4ChPro
|
||||||
httpRelayJson(relay1, relays.add<JsonObject>());
|
relay1.json(relays.add<JsonObject>());
|
||||||
httpRelayJson(relay2, relays.add<JsonObject>());
|
relay2.json(relays.add<JsonObject>());
|
||||||
httpRelayJson(relay3, relays.add<JsonObject>());
|
relay3.json(relays.add<JsonObject>());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
String response;
|
String response;
|
||||||
|
|||||||
14
src/io.cpp
14
src/io.cpp
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
Button button0(13, true, true, [](const ButtonEvent event) { buttonCallback(relay0, event); });
|
Button button0(13, true, true, [](const ButtonEvent event) { buttonCallback(relay0, event); });
|
||||||
|
|
||||||
Relay relay0(0, "RELAY #0", 15, false, true);
|
Relay relay0(0, "fallback/relay0", "RELAY #0", 15, false, true);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -20,8 +20,6 @@ Relay relay0(0, "RELAY #0", 15, false, true);
|
|||||||
#define STATUS_INVERT true
|
#define STATUS_INVERT true
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Output status("Status", 13, true, false);
|
|
||||||
|
|
||||||
Button button0(0, true, true, [](const ButtonEvent event) { buttonCallback(relay0, event); });
|
Button button0(0, true, true, [](const ButtonEvent event) { buttonCallback(relay0, event); });
|
||||||
|
|
||||||
Button button1(9, true, true, [](const ButtonEvent event) { buttonCallback(relay1, event); });
|
Button button1(9, true, true, [](const ButtonEvent event) { buttonCallback(relay1, event); });
|
||||||
@ -30,13 +28,13 @@ Button button2(10, true, true, [](const ButtonEvent event) { buttonCallback(rela
|
|||||||
|
|
||||||
Button button3(14, true, true, [](const ButtonEvent event) { buttonCallback(relay3, event); });
|
Button button3(14, true, true, [](const ButtonEvent event) { buttonCallback(relay3, event); });
|
||||||
|
|
||||||
Relay relay0(0, "RELAY #0", 12, false, true);
|
Relay relay0(0, "fallback/relay0", "RELAY #0", 12, false, true);
|
||||||
|
|
||||||
Relay relay1(1, "RELAY #1", 5, false, true);
|
Relay relay1(1, "fallback/relay1", "RELAY #1", 5, false, true);
|
||||||
|
|
||||||
Relay relay2(2, "RELAY #2", 4, false, true);
|
Relay relay2(2, "fallback/relay2", "RELAY #2", 4, false, true);
|
||||||
|
|
||||||
Relay relay3(3, "RELAY #3", 15, false, true);
|
Relay relay3(3, "fallback/relay3", "RELAY #3", 15, false, true);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -45,7 +43,7 @@ Relay relay3(3, "RELAY #3", 15, false, true);
|
|||||||
#define STATUS_INVERT false
|
#define STATUS_INVERT false
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Output status("Status", STATUS_PIN, STATUS_INVERT, true);
|
Output status("Status", STATUS_PIN, STATUS_INVERT, false);
|
||||||
|
|
||||||
void buttonCallback(Output &output, const ButtonEvent event) {
|
void buttonCallback(Output &output, const ButtonEvent event) {
|
||||||
if (event == BUTTON_PRESSED) {
|
if (event == BUTTON_PRESSED) {
|
||||||
|
|||||||
60
src/mqtt.cpp
Normal file
60
src/mqtt.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "mqtt.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <WiFiClient.h>
|
||||||
|
|
||||||
|
#include "PubSubClient.h"
|
||||||
|
|
||||||
|
WiFiClient wifiClient;
|
||||||
|
|
||||||
|
PubSubClient client(wifiClient);
|
||||||
|
|
||||||
|
bool mqttShouldConnect = false;
|
||||||
|
|
||||||
|
unsigned long mqttLast = 0;
|
||||||
|
|
||||||
|
void mqttSetup() {
|
||||||
|
mqttShouldConnect = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqttLoop() {
|
||||||
|
if (client.loop()) {
|
||||||
|
if (!mqttShouldConnect) {
|
||||||
|
client.disconnect();
|
||||||
|
Serial.println("[MQTT] Stopped.");
|
||||||
|
}
|
||||||
|
} else if (mqttShouldConnect) {
|
||||||
|
const auto host = configRead("/mqtt/host", "", false);
|
||||||
|
if (host == "") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (mqttLast == 0 || millis() - mqttLast >= 3000) {
|
||||||
|
const auto id = configRead("/mqtt/id", "test", false);
|
||||||
|
const auto user = configRead("/mqtt/user", "", false);
|
||||||
|
const auto pass = configRead("/mqtt/pass", "", false, true);
|
||||||
|
const auto port = configRead("/mqtt/port", 1883L, false);
|
||||||
|
mqttLast = max(1UL, millis());
|
||||||
|
client.setServer(host.c_str(), port);
|
||||||
|
Serial.printf("[MQTT] Connecting: %s:%ld\n", host.c_str(), port);
|
||||||
|
if (client.connect(id.c_str(), user.c_str(), pass.c_str())) {
|
||||||
|
Serial.printf("[MQTT] Connected.\n");
|
||||||
|
} else {
|
||||||
|
Serial.printf("[MQTT] Failed to connect.\n");
|
||||||
|
}
|
||||||
|
delay(500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqttStop() {
|
||||||
|
mqttShouldConnect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mqttPublish(const String &topic, const JsonDocument &json) {
|
||||||
|
if (!mqttShouldConnect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
char buffer[256];
|
||||||
|
const auto size = serializeJson(json, buffer);
|
||||||
|
client.publish(topic.c_str(), buffer, size);
|
||||||
|
}
|
||||||
14
src/mqtt.h
Normal file
14
src/mqtt.h
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
#ifndef MQTT_H
|
||||||
|
#define MQTT_H
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
|
||||||
|
void mqttSetup();
|
||||||
|
|
||||||
|
void mqttLoop();
|
||||||
|
|
||||||
|
void mqttStop();
|
||||||
|
|
||||||
|
void mqttPublish(const String &topic, const JsonDocument &json);
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -42,10 +42,12 @@ void wifiLoop() {
|
|||||||
if (wifiConnected) {
|
if (wifiConnected) {
|
||||||
if (connected) {
|
if (connected) {
|
||||||
httpLoop();
|
httpLoop();
|
||||||
|
mqttLoop();
|
||||||
} else {
|
} else {
|
||||||
Serial.printf("[WiFi] Disconnected!\n");
|
Serial.printf("[WiFi] Disconnected!\n");
|
||||||
ArduinoOTA.end();
|
ArduinoOTA.end();
|
||||||
httpStop();
|
httpStop();
|
||||||
|
mqttStop();
|
||||||
wifiConnect();
|
wifiConnect();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -54,6 +56,7 @@ void wifiLoop() {
|
|||||||
Serial.printf("[WiFi] Connected \"%s\" as \"%s\" (%s)\n", WiFi.SSID().c_str(), WiFi.getHostname(), WiFi.localIP().toString().c_str());
|
Serial.printf("[WiFi] Connected \"%s\" as \"%s\" (%s)\n", WiFi.SSID().c_str(), WiFi.getHostname(), WiFi.localIP().toString().c_str());
|
||||||
ArduinoOTA.begin();
|
ArduinoOTA.begin();
|
||||||
httpSetup();
|
httpSetup();
|
||||||
|
mqttSetup();
|
||||||
} else if (wifiLast == 0 || millis() - wifiLast >= 10000) {
|
} else if (wifiLast == 0 || millis() - wifiLast >= 10000) {
|
||||||
if (wifiLast > 0) {
|
if (wifiLast > 0) {
|
||||||
Serial.printf("[WiFi] Timeout!\n");
|
Serial.printf("[WiFi] Timeout!\n");
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user