Compare commits

..

No commits in common. "master" and "rschaten/modularize" have entirely different histories.

29 changed files with 219 additions and 930 deletions

View File

@ -1,4 +0,0 @@
# Contributing to Things
If you want to participate -- write code, file bugs, etc. -- just tell me. I
will create an account for you so you can work in this project.

21
LICENSE
View File

@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2016 Ronald Schaten
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,7 +0,0 @@
# Things
This project provides a framework to build sensor and actuator devices, based
on the relatively cheap ESP8266 chip. Simple devices can be distributed around
the house. They connect to a MQTT broker via WiFi network. New sensor values
are published as MQTT messages, and actuators subscribe to certain topics to
receive commands via MQTT.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 396 KiB

View File

@ -1,4 +1,5 @@
#pragma once #ifndef DEVICE_H
#define DEVICE_H
class Device { class Device {
public: public:
@ -7,3 +8,5 @@ class Device {
virtual void deviceRegister() = 0; virtual void deviceRegister() = 0;
virtual void deviceLoop() = 0; virtual void deviceLoop() = 0;
}; };
#endif

View File

@ -1,24 +0,0 @@
#include "DeviceButton.h"
void DeviceButton::deviceSetup() {
pinMode(pin, INPUT);
}
void DeviceButton::deviceRegister() {
Homie.registerNode(buttonNode);
}
void DeviceButton::deviceLoop() {
for (int i = 0; i < 3; i++) {
if (digitalRead(pin) == state) {
return;
}
delay(10);
}
state = !state;
Serial.print("button: ");
Serial.println(state);
if (!Homie.setNodeProperty(buttonNode, "state", String(state), false)) {
Serial.println("Sending failed");
}
}

View File

@ -1,18 +0,0 @@
#pragma once
#include "Device.h"
#include <Homie.h>
class DeviceButton : public Device {
public:
inline DeviceButton(byte buttonPin) {
pin = buttonPin;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
private:
byte pin;
bool state = LOW;
HomieNode buttonNode = HomieNode("button", "button");
};

View File

@ -1,67 +0,0 @@
#include "DeviceDht.h"
void DeviceDht::deviceSetup() {
pinMode(pin, INPUT);
dht.begin();
}
void DeviceDht::deviceRegister() {
Homie.registerNode(humidityNode);
Homie.registerNode(temperatureNode);
Homie.registerNode(heatindexNode);
}
// compare float values
bool isEqual(float a, float b, float epsilon=0.001) {
return fabs(a - b) <= epsilon * fabs(a);
}
void DeviceDht::deviceLoop() {
if (millis() - lastSentDHT >= INTERVAL_DHT * 1000UL || lastSentDHT == 0) {
float previousHumidity = humidity;
float previousTemperature = temperature;
float previousHeatindex = heatindex;
humidity = dht.readHumidity(); // read humidity as a percent
temperature = dht.readTemperature(); // read temperature as Celsius
heatindex = dht.computeHeatIndex(temperature, humidity, false);
// check if any reads failed and exit early
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
delay(500);
return;
}
if (!isEqual(humidity, previousHumidity)) {
Serial.print("humidity: ");
Serial.println(humidity);
if (!Homie.setNodeProperty(humidityNode, "value", String(humidity), false)) {
Serial.println("Sending failed");
}
} else {
Serial.println("humidity unchanged");
}
if (!isEqual(temperature, previousTemperature)) {
Serial.print("temperature: ");
Serial.println(temperature);
if (!Homie.setNodeProperty(temperatureNode, "value", String(temperature), false)) {
Serial.println("Sending failed");
}
} else {
Serial.println("temperature unchanged");
}
if (!isEqual(heatindex, previousHeatindex)) {
Serial.print("heatindex: ");
Serial.println(heatindex);
if (!Homie.setNodeProperty(heatindexNode, "value", String(heatindex), false)) {
Serial.println("Sending failed");
}
} else {
Serial.println("heatindex unchanged");
}
lastSentDHT = millis();
}
}

View File

@ -1,4 +1,5 @@
#pragma once #ifndef DEVICEDHT_H
#define DEVICEDHT_H
#include "Device.h" #include "Device.h"
#include <Homie.h> #include <Homie.h>
@ -25,3 +26,70 @@ class DeviceDht : public Device {
HomieNode temperatureNode{"temperature", "temperature"}; HomieNode temperatureNode{"temperature", "temperature"};
HomieNode heatindexNode{"heatindex", "heatindex"}; HomieNode heatindexNode{"heatindex", "heatindex"};
}; };
void DeviceDht::deviceSetup() {
pinMode(pin, INPUT);
dht.begin();
}
void DeviceDht::deviceRegister() {
Homie.registerNode(humidityNode);
Homie.registerNode(temperatureNode);
Homie.registerNode(heatindexNode);
}
// compare float values
bool isEqual(float a, float b, float epsilon=0.001) {
return fabs(a - b) <= epsilon * fabs(a);
}
void DeviceDht::deviceLoop() {
if (millis() - lastSentDHT >= INTERVAL_DHT * 1000UL || lastSentDHT == 0) {
float previousHumidity = humidity;
float previousTemperature = temperature;
float previousHeatindex = heatindex;
humidity = dht.readHumidity(); // read humidity as a percent
temperature = dht.readTemperature(); // read temperature as Celsius
heatindex = dht.computeHeatIndex(temperature, humidity, false);
// check if any reads failed and exit early
if (isnan(humidity) || isnan(temperature)) {
Serial.println("Failed to read from DHT sensor!");
return;
}
if (!isEqual(humidity, previousHumidity)) {
Serial.print("humidity: ");
Serial.println(humidity);
if (!Homie.setNodeProperty(humidityNode, "value", String(humidity), true)) {
Serial.println("Sending failed");
}
} else {
Serial.println("humidity unchanged");
}
if (!isEqual(temperature, previousTemperature)) {
Serial.print("temperature: ");
Serial.println(temperature);
if (!Homie.setNodeProperty(temperatureNode, "value", String(temperature), true)) {
Serial.println("Sending failed");
}
} else {
Serial.println("temperature unchanged");
}
if (!isEqual(heatindex, previousHeatindex)) {
Serial.print("heatindex: ");
Serial.println(heatindex);
if (!Homie.setNodeProperty(heatindexNode, "value", String(heatindex), true)) {
Serial.println("Sending failed");
}
} else {
Serial.println("heatindex unchanged");
}
lastSentDHT = millis();
}
}
#endif

View File

@ -1,23 +0,0 @@
#include "DeviceIrRx.h"
void DeviceIrRx::deviceSetup() {
// pinMode(pin_irrx, INPUT); // this is done by enableIRIn()
irrecv.enableIRIn();
pinMode(pin_power, OUTPUT);
digitalWrite(pin_power, HIGH);
}
void DeviceIrRx::deviceRegister() {
Homie.registerNode(irRxNode);
}
void DeviceIrRx::deviceLoop() {
if (irrecv.decode(&results)) {
Serial.print("IR-Rx: ");
Serial.println(results.value, HEX);
if (!Homie.setNodeProperty(irRxNode, "value", String(results.value), false)) {
Serial.println("Sending failed");
}
irrecv.resume(); // Receive the next value
}
}

View File

@ -1,22 +0,0 @@
#pragma once
#include "Device.h"
#include <Homie.h>
#include <IRremoteESP8266.h> // https://github.com/markszabo/IRremoteESP8266
class DeviceIrRx : public Device {
public:
inline DeviceIrRx(byte irrxPin, byte powerPin):irrecv(irrxPin) {
pin_irrx = irrxPin;
pin_power = powerPin;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
private:
byte pin_irrx;
byte pin_power;
IRrecv irrecv;
decode_results results;
HomieNode irRxNode = HomieNode("irrx", "irrx");
};

View File

@ -1,81 +0,0 @@
#include "DeviceIrTx.h"
void DeviceIrTx::deviceSetup() {
// pinMode(pin_irtx, OUTPUT); // this is done by begin()
irsend.begin();
}
bool DeviceIrTx::irTxHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
unsigned long data = 0;
int nbits = 0;
if (json_in.containsKey("data")) {
data = json_in["data"];
}
if (json_in.containsKey("nbits")) {
nbits = json_in["nbits"];
}
if (json_in.containsKey("protocol")) {
String protocol = json_in["protocol"];
protocol.toUpperCase();
Serial.print("IR-Tx: sending ");
Serial.print(data);
Serial.print(" (");
Serial.print(nbits);
Serial.print(") via ");
Serial.print(protocol);
Serial.println(" Protocol");
for (int i = 0; i < 5; i++) {
if (protocol == "NEC") {
irsend.sendNEC(data, nbits);
} else if (protocol == "SONY") {
irsend.sendSony(data, nbits);
} else if (protocol == "RC5") {
irsend.sendRC5(data, nbits);
} else if (protocol == "RC6") {
irsend.sendRC6(data, nbits);
} else if (protocol == "DISH") {
irsend.sendDISH(data, nbits);
} else if (protocol == "SHARP") {
irsend.sendSharp(data, nbits);
} else if (protocol == "PANASONIC") {
irsend.sendPanasonic(data, nbits);
/* JVC needs a repeat parameter, will be implemented if necessary
} else if (protocol == "JVC") {
int repeat = 0;
irsend.sendJVC(data, nbits, repeat);
*/
/* Sanyo and Mitsubishi aren't implemented in the library
} else if (protocol == "SANYO") {
irsend.sendSanyo(data, nbits);
} else if (protocol == "MITSUBISHI") {
irsend.sendMitsubishi(data, nbits);
*/
} else if (protocol == "SAMSUNG") {
irsend.sendSAMSUNG(data, nbits);
} else if (protocol == "LG") {
irsend.sendLG(data, nbits);
} else if (protocol == "WHYNTER") {
irsend.sendLG(data, nbits);
} else {
Serial.println("IR protocol not implemented");
}
delay(40);
}
}
} else {
Serial.println("parsing of JSON failed");
}
return true;
}
void DeviceIrTx::deviceRegister() {
irTxNode.subscribe("irtx", [this](String value) { return irTxHandler(value); });
Homie.registerNode(irTxNode);
}
void DeviceIrTx::deviceLoop() {
return;
}

View File

@ -1,20 +0,0 @@
#pragma once
#include "Device.h"
#include <Homie.h>
#include <IRremoteESP8266.h> // https://github.com/markszabo/IRremoteESP8266
class DeviceIrTx : public Device {
public:
inline DeviceIrTx(byte irtxPin):irsend(irtxPin) {
pin_irtx = irtxPin;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
private:
byte pin_irtx;
IRsend irsend;
bool irTxHandler(String message);
HomieNode irTxNode = HomieNode("irtx", "irtx");
};

View File

@ -1,27 +0,0 @@
#include "DeviceLdr.h"
void DeviceLdr::deviceSetup() {
pinMode(pin, INPUT);
}
void DeviceLdr::deviceRegister() {
Homie.registerNode(ldrNode);
}
void DeviceLdr::deviceLoop() {
if (millis() - lastSentLDR >= INTERVAL_LDR * 1000UL || lastSentLDR == 0) {
int ldr_new = analogRead(pin);
if (ldr_new != ldr) {
ldr = ldr_new;
float ldr_float = map(ldr, 0, 1023, 0, 10000) / 100.0;
Serial.print("LDR: ");
Serial.println(ldr_float);
if (!Homie.setNodeProperty(ldrNode, "value", String(ldr_float), false)) {
Serial.println("Sending failed");
}
} else {
Serial.println("LDR value unchanged");
}
lastSentLDR = millis();
}
}

View File

@ -1,4 +1,5 @@
#pragma once #ifndef DEVICELDR_H
#define DEVICELDR_H
#include "Device.h" #include "Device.h"
#include <Homie.h> #include <Homie.h>
@ -18,3 +19,31 @@ class DeviceLdr : public Device {
int ldr = 0; int ldr = 0;
HomieNode ldrNode = HomieNode("ldr", "ldr"); HomieNode ldrNode = HomieNode("ldr", "ldr");
}; };
void DeviceLdr::deviceSetup() {
pinMode(pin, INPUT);
}
void DeviceLdr::deviceRegister() {
Homie.registerNode(ldrNode);
}
void DeviceLdr::deviceLoop() {
if (millis() - lastSentLDR >= INTERVAL_LDR * 1000UL || lastSentLDR == 0) {
int ldr_new = analogRead(pin);
if (ldr_new != ldr) {
ldr = ldr_new;
float ldr_float = map(ldr, 0, 1023, 0, 10000) / 100.0;
Serial.print("LDR: ");
Serial.println(ldr_float);
if (!Homie.setNodeProperty(ldrNode, "value", String(ldr_float), true)) {
Serial.println("Sending failed");
}
} else {
Serial.println("LDR value unchanged");
}
lastSentLDR = millis();
}
}
#endif

View File

@ -1,100 +0,0 @@
#include "DeviceLed.h"
void DeviceLed::setLed(int value) {
analogWrite(pinLed, value);
}
void DeviceLed::publishStatus() {
DynamicJsonBuffer json_outBuffer;
JsonObject& json_out = json_outBuffer.createObject();
json_out["brightness"] = brightness;
String response;
json_out.printTo(response);
Serial.print("led state: ");
Serial.println(response);
Homie.setNodeProperty(ledNode, "brightness", response);
}
void DeviceLed::deviceSetup() {
pinMode(pinLed, OUTPUT);
setLed(brightness);
}
bool DeviceLed::ledOnHandler(String value) {
if (value == "true") {
setLed(brightness);
Homie.setNodeProperty(ledNode, "on", "true");
Serial.println("led is on");
} else if (value == "false") {
setLed(0);
Homie.setNodeProperty(ledNode, "on", "false");
Serial.println("led is off");
} else {
return false;
}
return true;
}
bool DeviceLed::ledBrightnessHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
if (json_in.containsKey("brightness")) {
brightness = json_in["brightness"];
}
setLed(brightness);
} else {
Serial.println("parsing of JSON failed");
}
publishStatus();
return true;
}
bool DeviceLed::ledFadeHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
fade_from = brightness;
if (json_in.containsKey("brightness")) {
fade_to = json_in["brightness"];
} else {
fade_to = brightness;
}
fade_start = millis();
if (json_in.containsKey("seconds")) {
fade_end = fade_start + 1000 * (int)json_in["seconds"];
} else {
fade_end = 0;
}
fading = true;
} else {
Serial.println("parsing of JSON failed");
}
return true;
}
void DeviceLed::deviceRegister() {
ledNode.subscribe("on", [this](String value) { return ledOnHandler(value); });
ledNode.subscribe("brightness", [this](String value) { return ledBrightnessHandler(value); });
ledNode.subscribe("fade", [this](String value) { return ledFadeHandler(value); });
Homie.registerNode(ledNode);
}
void DeviceLed::deviceLoop() {
if (fading) {
if (fade_end > millis()) {
float progress = 1.0 * (millis() - fade_start) / (fade_end - fade_start);
if ((int)(progress * 100) != (int)(progress_last * 100)) {
brightness = fade_from + (fade_to - fade_from) * progress;
setLed(brightness);
progress_last = progress;
}
} else {
brightness = fade_to;
setLed(brightness);
publishStatus();
fading = false;
}
}
return;
}

View File

@ -1,30 +1,100 @@
#pragma once #ifndef DEVICELED_H
#define DEVICELED_H
#include "Device.h" #include "Device.h"
#include <Homie.h> #include <Homie.h>
class DeviceLed : public Device { class DeviceLed : public Device {
public: public:
inline DeviceLed(byte ledPin, char* ledName):ledNode(ledName, "led") { inline DeviceLed(byte ledRed, byte ledGreen, byte ledBlue) {
pinLed = ledPin; pinRed = ledRed;
nameLed = ledName; pinGreen = ledGreen;
pinBlue = ledBlue;
} }
virtual void deviceSetup(); virtual void deviceSetup();
virtual void deviceRegister(); virtual void deviceRegister();
virtual void deviceLoop(); virtual void deviceLoop();
bool ledOnHandler(String value);
bool ledBrightnessHandler(String message);
bool ledFadeHandler(String message);
private: private:
byte pinLed; byte pinRed;
char* nameLed; byte pinGreen;
int brightness = 0; byte pinBlue;
bool fading = false; int led_red = 0;
int fade_from, fade_to; int led_green = 0;
unsigned long fade_start = 0; int led_blue = 0;
unsigned long fade_end = 0; bool ledOnHandler(String value);
float progress_last = 0; bool ledColorHandler(String message);
void setLed(int value); HomieNode ledNode{"led", "rgb"};
void publishStatus();
HomieNode ledNode;
}; };
void DeviceLed::deviceSetup() {
pinMode(pinRed, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinBlue, OUTPUT);
analogWrite(pinRed, led_red);
analogWrite(pinGreen, led_green);
analogWrite(pinBlue, led_blue);
}
bool DeviceLed::ledOnHandler(String value) {
if (value == "true") {
analogWrite(pinRed, led_red);
analogWrite(pinGreen, led_green);
analogWrite(pinBlue, led_blue);
Homie.setNodeProperty(ledNode, "on", "true");
Serial.println("led is on");
} else if (value == "false") {
analogWrite(pinRed, 0);
analogWrite(pinGreen, 0);
analogWrite(pinBlue, 0);
Homie.setNodeProperty(ledNode, "on", "false");
Serial.println("led is off");
} else {
return false;
}
return true;
}
bool DeviceLed::ledColorHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
if (json_in.containsKey("red")) {
led_red = json_in["red"];
analogWrite(pinRed, led_red);
}
if (json_in.containsKey("green")) {
led_green = json_in["green"];
analogWrite(pinGreen, led_green);
}
if (json_in.containsKey("blue")) {
led_blue = json_in["blue"];
analogWrite(pinBlue, led_blue);
}
} else {
Serial.println("parsing of JSON failed");
}
DynamicJsonBuffer json_outBuffer;
JsonObject& json_out = json_outBuffer.createObject();
json_out["red"] = led_red;
json_out["green"] = led_green;
json_out["blue"] = led_blue;
String response;
json_out.printTo(response);
Serial.print("led state: ");
Serial.println(response);
Homie.setNodeProperty(ledNode, "color", response);
return true;
}
void DeviceLed::deviceRegister() {
ledNode.subscribe("on", [this](String value) { return ledOnHandler(value); });
ledNode.subscribe("color", [this](String value) { return ledColorHandler(value); });
Homie.registerNode(ledNode);
}
void DeviceLed::deviceLoop() {
return;
}
#endif

View File

@ -1,34 +0,0 @@
#include "DeviceRelay.h"
void DeviceRelay::setRelay(bool value) {
digitalWrite(pinRelay, value);
}
void DeviceRelay::deviceSetup() {
pinMode(pinRelay, OUTPUT);
setRelay(HIGH);
}
bool DeviceRelay::relayOnHandler(String value) {
if (value == "true") {
setRelay(LOW);
Homie.setNodeProperty(relayNode, "on", "true");
Serial.println("relay is on");
} else if (value == "false") {
setRelay(HIGH);
Homie.setNodeProperty(relayNode, "on", "false");
Serial.println("relay is off");
} else {
return false;
}
return true;
}
void DeviceRelay::deviceRegister() {
relayNode.subscribe("on", [this](String value) { return relayOnHandler(value); });
Homie.registerNode(relayNode);
}
void DeviceRelay::deviceLoop() {
return;
}

View File

@ -1,21 +0,0 @@
#pragma once
#include "Device.h"
#include <Homie.h>
class DeviceRelay : public Device {
public:
inline DeviceRelay(byte relayPin, char* relayName):relayNode(relayName, "relay") {
pinRelay = relayPin;
nameRelay = relayName;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
bool relayOnHandler(String value);
private:
byte pinRelay;
char* nameRelay;
void setRelay(bool value);
HomieNode relayNode;
};

View File

@ -1,128 +0,0 @@
#include "DeviceRgb.h"
void DeviceRgb::setRgb(int red, int green, int blue) {
analogWrite(pinRed, red);
analogWrite(pinGreen, green);
analogWrite(pinBlue, blue);
}
void DeviceRgb::publishStatus() {
DynamicJsonBuffer json_outBuffer;
JsonObject& json_out = json_outBuffer.createObject();
json_out["red"] = rgb_red;
json_out["green"] = rgb_green;
json_out["blue"] = rgb_blue;
String response;
json_out.printTo(response);
Serial.print("rgb state: ");
Serial.println(response);
Homie.setNodeProperty(rgbNode, "color", response);
}
void DeviceRgb::deviceSetup() {
pinMode(pinRed, OUTPUT);
pinMode(pinGreen, OUTPUT);
pinMode(pinBlue, OUTPUT);
setRgb(rgb_red, rgb_green, rgb_blue);
}
bool DeviceRgb::rgbOnHandler(String value) {
if (value == "true") {
setRgb(rgb_red, rgb_green, rgb_blue);
Homie.setNodeProperty(rgbNode, "on", "true");
Serial.println("rgb is on");
} else if (value == "false") {
setRgb(0, 0, 0);
Homie.setNodeProperty(rgbNode, "on", "false");
Serial.println("rgb is off");
} else {
return false;
}
return true;
}
bool DeviceRgb::rgbColorHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
if (json_in.containsKey("red")) {
rgb_red = json_in["red"];
}
if (json_in.containsKey("green")) {
rgb_green = json_in["green"];
}
if (json_in.containsKey("blue")) {
rgb_blue = json_in["blue"];
}
setRgb(rgb_red, rgb_green, rgb_blue);
} else {
Serial.println("parsing of JSON failed");
}
publishStatus();
return true;
}
bool DeviceRgb::rgbFadeHandler(String message) {
DynamicJsonBuffer json_inBuffer;
JsonObject& json_in = json_inBuffer.parseObject(message);
if (json_in.success()) {
fade_from_red = rgb_red;
if (json_in.containsKey("red")) {
fade_to_red = json_in["red"];
} else {
fade_to_red = rgb_red;
}
fade_from_green = rgb_green;
if (json_in.containsKey("green")) {
fade_to_green = json_in["green"];
} else {
fade_to_green = rgb_green;
}
fade_from_blue = rgb_blue;
if (json_in.containsKey("blue")) {
fade_to_blue = json_in["blue"];
} else {
fade_to_blue = rgb_blue;
}
fade_start = millis();
if (json_in.containsKey("seconds")) {
fade_end = fade_start + 1000 * (int)json_in["seconds"];
} else {
fade_end = 0;
}
fading = true;
} else {
Serial.println("parsing of JSON failed");
}
return true;
}
void DeviceRgb::deviceRegister() {
rgbNode.subscribe("on", [this](String value) { return rgbOnHandler(value); });
rgbNode.subscribe("color", [this](String value) { return rgbColorHandler(value); });
rgbNode.subscribe("fade", [this](String value) { return rgbFadeHandler(value); });
Homie.registerNode(rgbNode);
}
void DeviceRgb::deviceLoop() {
if (fading) {
if (fade_end > millis()) {
float progress = 1.0 * (millis() - fade_start) / (fade_end - fade_start);
if ((int)(progress * 100) != (int)(progress_last * 100)) {
rgb_red = fade_from_red + (fade_to_red - fade_from_red) * progress;
rgb_green = fade_from_green + (fade_to_green - fade_from_green) * progress;
rgb_blue = fade_from_blue + (fade_to_blue - fade_from_blue) * progress;
setRgb(rgb_red, rgb_green, rgb_blue);
progress_last = progress;
}
} else {
rgb_red = fade_to_red;
rgb_green = fade_to_green;
rgb_blue = fade_to_blue;
setRgb(rgb_red, rgb_green, rgb_blue);
publishStatus();
fading = false;
}
}
return;
}

View File

@ -1,36 +0,0 @@
#pragma once
#include "Device.h"
#include <Homie.h>
class DeviceRgb : public Device {
public:
inline DeviceRgb(byte rgbRed, byte rgbGreen, byte rgbBlue) {
pinRed = rgbRed;
pinGreen = rgbGreen;
pinBlue = rgbBlue;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
private:
byte pinRed;
byte pinGreen;
byte pinBlue;
int rgb_red = 0;
int rgb_green = 0;
int rgb_blue = 0;
bool fading = false;
int fade_from_red, fade_to_red;
int fade_from_green, fade_to_green;
int fade_from_blue, fade_to_blue;
unsigned long fade_start = 0;
unsigned long fade_end = 0;
float progress_last = 0;
void setRgb(int red, int green, int blue);
void publishStatus();
bool rgbOnHandler(String value);
bool rgbColorHandler(String message);
bool rgbFadeHandler(String message);
HomieNode rgbNode{"rgb", "rgb"};
};

View File

@ -1,46 +0,0 @@
/*
* H801 WiFi
* off-the-shelf RGBWW led wifi controller
*
* Settings in IDE:
* - Board: "Generic ESP8266 Module"
* - Flash Size: "1M (64k SPIFFS)"
* - Upload Speed: "1152200"
*/
#include "DeviceLed.h"
#include "DeviceRgb.h"
const char* FWNAME = "things@H801wifi";
const byte PIN_LED1 = 14;
const byte PIN_LED2 = 4;
DeviceLed deviceLedW1(PIN_LED1, "white1");
DeviceLed deviceLedW2(PIN_LED2, "white2");
const byte PIN_RGB_RED = 15;
const byte PIN_RGB_GREEN = 13;
const byte PIN_RGB_BLUE = 12;
DeviceRgb deviceRgb(PIN_RGB_RED, PIN_RGB_GREEN, PIN_RGB_BLUE);
Device* devices[] = {
&deviceLedW1,
&deviceLedW2,
&deviceRgb,
};
void hardwareSetup() {
pinMode(PIN_LED1, OUTPUT);
pinMode(PIN_LED2, OUTPUT);
pinMode(PIN_RGB_RED, OUTPUT);
pinMode(PIN_RGB_GREEN, OUTPUT);
pinMode(PIN_RGB_BLUE, OUTPUT);
analogWrite(PIN_LED1, 100);
analogWrite(PIN_LED2, 0);
analogWrite(PIN_RGB_RED, 0);
analogWrite(PIN_RGB_GREEN, 0);
analogWrite(PIN_RGB_BLUE, 0);
deviceLedW1.ledBrightnessHandler("{\"brightness\":100}");
}
void hardwareLoop() {};

View File

@ -1,54 +0,0 @@
/*
* Sonoff
* off-the-shelf wifi relay module
*
* Settings in IDE:
* - Board: "Generic ESP8266 Module"
* - Flash Size: "1M (64k SPIFFS)"
* - Upload Speed: "1152200"
*/
#include "DeviceRelay.h"
const char* FWNAME = "things@Sonoff";
bool state = LOW;
bool switched = false;
const byte PIN_BUTTON = 0;
const byte PIN_RELAY = 12;
DeviceRelay deviceRelay(PIN_RELAY, "relay");
const byte PIN_LED = 13;
Device* devices[] = {
&deviceRelay,
};
void hardwareSetup() {
Homie.setLedPin(PIN_LED, HIGH);
pinMode(PIN_BUTTON, INPUT);
pinMode(PIN_RELAY, OUTPUT);
digitalWrite(PIN_RELAY, HIGH);
};
void hardwareLoop() {
digitalWrite(PIN_LED, !state);
for (int i = 0; i < 3; i++) {
if (digitalRead(PIN_BUTTON) == HIGH) {
switched = false;
return;
}
delay(10);
}
if (!switched) {
state = !state;
if (state) {
deviceRelay.relayOnHandler("true");
} else {
deviceRelay.relayOnHandler("false");
}
switched = true;
}
};

View File

@ -1,34 +0,0 @@
/*
* Witty Cloud
* development board, featuring RGB LED, LDR and a button
*
* Settings in IDE:
* - Board: "WeMos D1 R2 & mini"
*/
#include "DeviceRgb.h"
#include "DeviceLdr.h"
#include "DeviceButton.h"
const char* FWNAME = "things@Witty";
const byte PIN_RGB_RED = D8;
const byte PIN_RGB_GREEN = D6;
const byte PIN_RGB_BLUE = D7;
DeviceRgb deviceRgb(PIN_RGB_RED, PIN_RGB_GREEN, PIN_RGB_BLUE);
const byte PIN_LDR = A0;
DeviceLdr deviceLdr(PIN_LDR);
const byte PIN_BUTTON = D2;
DeviceButton deviceButton(PIN_BUTTON);
Device* devices[] = {
&deviceRgb,
&deviceLdr,
&deviceButton,
};
void hardwareSetup() {};
void hardwareLoop() {};

View File

@ -1,34 +0,0 @@
/*
* Witty Cloud
* development board, featuring RGB LED, LDR and a button
*
* Settings in IDE:
* - Board: "WeMos D1 R2 & mini"
*/
#include "DeviceRgb.h"
#include "DeviceLdr.h"
#include "DeviceButton.h"
const char* FWNAME = "things@Witty";
const byte PIN_RGB_RED = D8;
const byte PIN_RGB_GREEN = D6;
const byte PIN_RGB_BLUE = D7;
DeviceRgb deviceRgb(PIN_RGB_RED, PIN_RGB_GREEN, PIN_RGB_BLUE);
const byte PIN_LDR = A0;
DeviceLdr deviceLdr(PIN_LDR);
const byte PIN_BUTTON = D2;
DeviceButton deviceButton(PIN_BUTTON);
Device* devices[] = {
&deviceRgb,
&deviceLdr,
&deviceButton,
};
void hardwareSetup() {};
void hardwareLoop() {};

View File

@ -1,41 +0,0 @@
/*
* Witty Cloud
* development board, featuring RGB LED, LDR and a button
* added hardware: DHT22 temperature and humidity sensor
*
* Settings in IDE:
* - Board: "WeMos D1 R2 & mini"
*/
#include "DeviceRgb.h"
#include "DeviceLdr.h"
#include "DeviceButton.h"
#include "DeviceDht.h"
const char* FWNAME = "things@WittyDht";
const byte PIN_RGB_RED = D8;
const byte PIN_RGB_GREEN = D6;
const byte PIN_RGB_BLUE = D7;
DeviceRgb deviceRgb(PIN_RGB_RED, PIN_RGB_GREEN, PIN_RGB_BLUE);
const byte PIN_LDR = A0;
DeviceLdr deviceLdr(PIN_LDR);
const byte PIN_BUTTON = D2;
DeviceButton deviceButton(PIN_BUTTON);
const byte PIN_DHT = D5;
const byte TYPE_DHT = DHT22;
DeviceDht deviceDht(PIN_DHT, TYPE_DHT);
Device* devices[] = {
&deviceRgb,
&deviceLdr,
&deviceButton,
&deviceDht,
};
void hardwareSetup() {};
void hardwareLoop() {};

View File

@ -1,52 +0,0 @@
/*
* Witty Cloud
* development board, featuring RGB LED, LDR and a button
* added hardware: DHT22 temperature and humidity sensor, and infrared receiver and transmitter
*
* Settings in IDE:
* - Board: "WeMos D1 R2 & mini"
*/
#include "DeviceRgb.h"
#include "DeviceLdr.h"
#include "DeviceButton.h"
#include "DeviceDht.h"
#include "DeviceIrRx.h"
#include "DeviceIrTx.h"
const char* FWNAME = "things@WittyDhtIrRxTx";
const byte PIN_RGB_RED = D8;
const byte PIN_RGB_GREEN = D6;
const byte PIN_RGB_BLUE = D7;
DeviceRgb deviceRgb(PIN_RGB_RED, PIN_RGB_GREEN, PIN_RGB_BLUE);
const byte PIN_LDR = A0;
DeviceLdr deviceLdr(PIN_LDR);
const byte PIN_BUTTON = D2;
DeviceButton deviceButton(PIN_BUTTON);
const byte PIN_DHT = D5;
const byte TYPE_DHT = DHT22;
DeviceDht deviceDht(PIN_DHT, TYPE_DHT);
const byte PIN_IRRX = D1;
const byte PIN_POWER = D0;
DeviceIrRx deviceIrRx(PIN_IRRX, PIN_POWER);
const byte PIN_IRTX = D2;
DeviceIrTx deviceIrTx(PIN_IRTX);
Device* devices[] = {
&deviceRgb,
&deviceLdr,
//&deviceButton,
&deviceDht,
&deviceIrRx,
&deviceIrTx,
};
void hardwareSetup() {};
void hardwareLoop() {};

View File

@ -1,31 +1,44 @@
#include <Homie.h> // https://github.com/marvinroger/homie-esp8266 #include <Homie.h> // https://github.com/marvinroger/homie-esp8266
#include "HardwareWitty.h" #include "DeviceLed.h"
//#include "HardwareWittyDht.h" #include "DeviceLdr.h"
//#include "HardwareWittyDhtIrRxTx.h" #include "DeviceDht.h"
//#include "HardwareWittyBbq.h"
//#include "HardwareH801wifi.h"
//#include "HardwareSonoff.h"
const char* FWVERSION = "1.0.0"; // HAS_LED
#define PIN_LED_RED D8
#define PIN_LED_GREEN D6
#define PIN_LED_BLUE D7
DeviceLed deviceLed(PIN_LED_RED, PIN_LED_GREEN, PIN_LED_BLUE);
// HAS_LDR
#define PIN_LDR A0
DeviceLdr deviceLdr(PIN_LDR);
// HAS_DHT
#define PIN_DHT D4
#define TYPE_DHT DHT22
DeviceDht deviceDht(PIN_DHT, TYPE_DHT);
Device * devices[3];
void setupHandler() { void setupHandler() {
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) { for (int i = 0; i < 2; i++) {
devices[i]->deviceSetup(); devices[i]->deviceSetup();
} }
} }
void loopHandler() { void loopHandler() {
hardwareLoop(); for (int i = 0; i < 2; i++) {
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) {
devices[i]->deviceLoop(); devices[i]->deviceLoop();
} }
} }
void setup() { void setup() {
hardwareSetup(); Homie.setFirmware("things", "1.0.0");
Homie.setFirmware(FWNAME, FWVERSION); devices[0] = &deviceLed;
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) { devices[1] = &deviceLdr;
//devices[2] = &deviceDht;
for (int i = 0; i < 2; i++) {
devices[i]->deviceRegister(); devices[i]->deviceRegister();
} }
Homie.setSetupFunction(setupHandler); Homie.setSetupFunction(setupHandler);