Greenhouse: Input/Output instances: door, windows, light

This commit is contained in:
Patrick Haßel 2025-03-04 11:13:44 +01:00
parent 1732fce143
commit e2c102b16a
12 changed files with 169 additions and 48 deletions

View File

@ -20,7 +20,7 @@ void patrixSetup() {
httpSetup2(); httpSetup2();
} }
void patrixLoop() { void patrixLoop(const boolean mqttJustConnected) {
config.loop(); config.loop();
ds18b20.loop(); ds18b20.loop();

View File

@ -4,7 +4,6 @@
#include "http.h" #include "http.h"
#include "sensors.h" #include "sensors.h"
#include "../../patrix/mqtt.h"
void httpStatus(AsyncWebServerRequest* request) { void httpStatus(AsyncWebServerRequest* request) {
JsonDocument json; JsonDocument json;
@ -12,9 +11,9 @@ void httpStatus(AsyncWebServerRequest* request) {
json["temperature"] = greenhouseDHT22.getTemperature(); json["temperature"] = greenhouseDHT22.getTemperature();
json["relative"] = greenhouseDHT22.getRelative(); json["relative"] = greenhouseDHT22.getRelative();
json["absolute"] = greenhouseDHT22.getAbsolute(); json["absolute"] = greenhouseDHT22.getAbsolute();
json["door"] = door; json["door"] = door.getState();
json["windows"] = windows; json["windows"] = windows.getState();
json["light"] = light; json["light"] = light.getState();
AsyncResponseStream* stream = request->beginResponseStream("application/json"); AsyncResponseStream* stream = request->beginResponseStream("application/json");
serializeJson(json, *stream); serializeJson(json, *stream);
@ -22,12 +21,12 @@ void httpStatus(AsyncWebServerRequest* request) {
} }
void httpLightOn(AsyncWebServerRequest* request) { void httpLightOn(AsyncWebServerRequest* request) {
light = true; light.setState(true);
httpStatus(request); httpStatus(request);
} }
void httpLightOff(AsyncWebServerRequest* request) { void httpLightOff(AsyncWebServerRequest* request) {
light = false; light.setState(false);
httpStatus(request); httpStatus(request);
} }

View File

@ -7,11 +7,11 @@
#define WINDOWS_GPIO D6 #define WINDOWS_GPIO D6
#define LIGHT_GPIO D7 #define LIGHT_GPIO D7
bool door = false; Input door("greenhouse/door", DOOR_GPIO, true, "CLOSEABLE_BOOLEAN");
bool windows = false; Input windows("greenhouse/windows", WINDOWS_GPIO, true, "CLOSEABLE_BOOLEAN");
bool light = false; Output light("greenhouse/light", LIGHT_GPIO, true, "LIGHT_BOOLEAN");
TSL2561 greenhouseTSL("greenhouse"); TSL2561 greenhouseTSL("greenhouse");
@ -21,15 +21,14 @@ void sensorsSetup() {
pinMode(DOOR_GPIO, INPUT_PULLUP); pinMode(DOOR_GPIO, INPUT_PULLUP);
pinMode(WINDOWS_GPIO, INPUT_PULLUP); pinMode(WINDOWS_GPIO, INPUT_PULLUP);
pinMode(LIGHT_GPIO, OUTPUT); pinMode(LIGHT_GPIO, OUTPUT);
digitalWrite(LIGHT_GPIO, light ? LOW : HIGH);
greenhouseTSL.setup(); greenhouseTSL.setup();
greenhouseDHT22.setup(); greenhouseDHT22.setup();
} }
void sensorsLoop() { void sensorsLoop() {
door = digitalRead(DOOR_GPIO) == LOW; door.loop();
windows = digitalRead(WINDOWS_GPIO) == LOW; windows.loop();
digitalWrite(LIGHT_GPIO, light ? LOW : HIGH); light.loop();
greenhouseTSL.loop(); greenhouseTSL.loop();
greenhouseDHT22.loop(); greenhouseDHT22.loop();
} }

View File

@ -1,16 +1,18 @@
#ifdef NODE_GREENHOUSE
#ifndef SENSORS_H #ifndef SENSORS_H
#define SENSORS_H #define SENSORS_H
#ifdef NODE_GREENHOUSE
#include "patrix/DHT22.h" #include "patrix/DHT22.h"
#include "patrix/Input.h"
#include "patrix/Output.h"
#include "patrix/tsl2561.h" #include "patrix/tsl2561.h"
extern boolean door; extern Input door;
extern boolean windows; extern Input windows;
extern boolean light; extern Output light;
extern TSL2561 greenhouseTSL; extern TSL2561 greenhouseTSL;

View File

@ -25,13 +25,12 @@ public:
unsigned long intervalMs; unsigned long intervalMs;
explicit DHT22Sensor(String name, const int pin, const unsigned long interval_ms = 5000) : pin(pin), dht(pin, DHT22), name(std::move(name)), intervalMs(interval_ms) { explicit DHT22Sensor(String name, const int pin, const unsigned long intervalMs = 5000) : pin(pin), dht(pin, DHT22), name(std::move(name)), intervalMs(intervalMs) {
// //
} }
void setup() { void setup() {
dht.begin(); dht.begin();
last = millis();
} }
void loop() { void loop() {

62
src/patrix/Input.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef INPUT_H
#define INPUT_H
#include <Arduino.h>
#include "mqtt.h"
class Input {
const int pin;
const boolean inverted;
const char* unit;
unsigned long debounceMs;
unsigned long sendMs;
unsigned long lastRead = 0UL;
unsigned long lastSent = 0UL;
boolean state = false;
public:
const String name;
explicit Input(String name, const int pin, const boolean inverted, const char* unit, const unsigned long debounceMs = 500, const unsigned long sendMs = 5000) : pin(pin), inverted(inverted), unit(unit), debounceMs(debounceMs), sendMs(sendMs), name(std::move(name)) {
//
}
void setup() {
pinMode(pin, INPUT_PULLUP);
state = inverted ^ (digitalRead(pin) == HIGH);
}
void loop() {
const auto now = max(1UL, millis());
bool changed = false;
if (lastRead == 0 || now - lastRead >= debounceMs) {
lastRead = now;
const auto current = inverted ^ (digitalRead(pin) == HIGH);
changed = state != current;
state = current;
}
if (changed || lastSent == 0 || now - lastSent >= sendMs) {
lastSent = now;
mqttPublishValue(name, state, unit);
}
}
[[nodiscard]] boolean getState() const {
return state;
}
};
#endif

54
src/patrix/Output.h Normal file
View File

@ -0,0 +1,54 @@
#ifndef OUTPUT_H
#define OUTPUT_H
#include <Arduino.h>
#include "mqtt.h"
class Output {
const int pin;
const boolean inverted;
const char* unit;
unsigned long sendMs;
unsigned long lastSent = 0UL;
boolean state = false;
public:
const String name;
explicit Output(String name, const int pin, const boolean inverted, const char* unit, const unsigned long sendMs = 5000) : pin(pin), inverted(inverted), unit(unit), sendMs(sendMs), name(std::move(name)) {
//
}
void setup() const {
pinMode(pin, OUTPUT);
}
void loop() {
const auto now = max(1UL, millis());
const auto changed = state != (inverted ^ (digitalRead(pin) == HIGH));
if (changed || lastSent == 0 || now - lastSent >= sendMs) {
lastSent = now;
digitalWrite(pin, inverted ^ state);
mqttPublishValue(name, state, unit);
}
}
void setState(const boolean newState) {
this->state = newState;
}
[[nodiscard]] boolean getState() const {
return state;
}
};
#endif

View File

@ -17,7 +17,7 @@ public:
unsigned long intervalMs; unsigned long intervalMs;
explicit BME680(String name, const unsigned long interval_ms = 5000) : name(std::move(name)), intervalMs(interval_ms) { explicit BME680(String name, const unsigned long intervalMs = 5000) : name(std::move(name)), intervalMs(intervalMs) {
// //
} }

View File

@ -20,7 +20,7 @@ public:
unsigned long intervalMs; unsigned long intervalMs;
explicit BMP280_AHT20(String name, const unsigned long interval_ms = 5000) : name(std::move(name)), intervalMs(interval_ms) { explicit BMP280_AHT20(String name, const unsigned long intervalMs = 5000) : name(std::move(name)), intervalMs(intervalMs) {
// //
} }

View File

@ -63,6 +63,10 @@ void mqttDisconnect() {
mqtt.disconnect(); mqtt.disconnect();
} }
void mqttPublishValue(const String& name, const boolean value, const char* unit) {
mqttPublishValue(name, String(value ? "true" : "false"), unit);
}
void mqttPublishValue(const String& name, const int32_t value, const char* unit) { void mqttPublishValue(const String& name, const int32_t value, const char* unit) {
mqttPublishValue(name, String(value), unit); mqttPublishValue(name, String(value), unit);
} }

View File

@ -30,6 +30,8 @@ void mqttLoop();
void mqttDisconnect(); void mqttDisconnect();
void mqttPublishValue(const String& name, boolean value, const char* unit);
void mqttPublishValue(const String& name, int32_t value, const char* unit); void mqttPublishValue(const String& name, int32_t value, const char* unit);
void mqttPublishValue(const String& name, int64_t value, const char* unit); void mqttPublishValue(const String& name, int64_t value, const char* unit);

View File

@ -18,7 +18,7 @@ public:
unsigned long intervalMs; unsigned long intervalMs;
explicit TSL2561(String name, const uint8_t address = TSL2561_ADDR_FLOAT, const unsigned long interval_ms = 5000) : tsl(Adafruit_TSL2561_Unified(address)), name(std::move(name)), intervalMs(interval_ms) { explicit TSL2561(String name, const uint8_t address = TSL2561_ADDR_FLOAT, const unsigned long intervalMs = 5000) : tsl(Adafruit_TSL2561_Unified(address)), name(std::move(name)), intervalMs(intervalMs) {
// //
} }