Compare commits

..

44 Commits

Author SHA1 Message Date
a04958033e implement button 2017-01-20 22:59:33 +01:00
67120c4c35 fix states 2017-01-20 22:59:25 +01:00
132cdac6ad remove unused variable 2016-12-23 23:13:47 +01:00
c83dc44f83 establish hardwareLoop() 2016-12-23 00:03:36 +01:00
23d3c314c2 deconfigure button 2016-12-23 00:02:50 +01:00
9bf2ed09aa use pin 13 as wifi indicator 2016-12-17 21:33:50 +01:00
e59d3d0f73 first version with working relay function 2016-12-14 23:14:17 +01:00
7fd1d56eae first version, just reacting to the button 2016-12-13 23:47:54 +01:00
b8d4e9fef8 added BBQ hardware 2016-12-13 22:18:07 +01:00
bfd74e61a1 add function that gets called before homie initialization 2016-05-21 19:19:24 +02:00
6d0cf8f786 make handler functions public 2016-05-21 19:17:03 +02:00
7169be9882 enable having two led channels 2016-05-19 10:44:20 +02:00
1526ae98bd new hardware: witty with DHT22, infrared receiver and transmitter 2016-05-18 10:31:58 +02:00
3a7c87298c new hardware: witty with DHT22, infrared receiver and transmitter 2016-05-18 10:31:16 +02:00
2a10b67fe2 added hardware configuration for witty with DHT22 2016-05-18 09:42:06 +02:00
311e92a240 uppercase names 2016-05-18 09:08:35 +02:00
933c94e7e5 improve configuration of name and version 2016-05-18 09:04:10 +02:00
9cffc34073 split hardware configuration to modules 2016-05-18 08:53:58 +02:00
7a79f1ca12 new device type: led 2016-05-17 23:55:41 +02:00
783286849a renamed LED to RGB, since that's what it is 2016-05-17 22:14:03 +02:00
e15a65c69d publish color after fading 2016-04-27 21:40:33 +02:00
17d862049e refactor function to set led 2016-04-27 21:33:58 +02:00
99dd1918fc implement fading 2016-04-27 21:24:55 +02:00
d9d2ccd9bf new device: pushbutton 2016-04-24 12:17:15 +02:00
99ce953de3 don't retain volatile values 2016-04-23 01:44:56 +02:00
9b9e8db96a wait a moment if DHT can't be reached 2016-04-23 00:14:39 +02:00
41793dd3c4 note about contributions 2016-04-22 23:18:00 +02:00
48f01a5542 included readme 2016-04-22 23:08:44 +02:00
03ff2a8aa4 added license 2016-04-22 22:59:40 +02:00
d5bdd4305c tell where the libraries are from 2016-04-22 22:45:45 +02:00
0294f2f5c4 remove preprocessor stuff 2016-04-22 22:42:18 +02:00
d79d445a3e replace preprocessor syntax 2016-04-22 22:32:36 +02:00
50c38f4060 split C code into header- and implementation-files 2016-04-22 22:26:52 +02:00
2970dad868 implemented IR transmission via MQTT 2016-04-21 11:33:48 +02:00
1301947c7a let the library handle initialization 2016-04-21 09:31:34 +02:00
f595ac746f create and subscribe transmission handler 2016-04-20 22:45:47 +02:00
e01e13cd9f first test transmitting IR 2016-04-20 22:34:15 +02:00
0d85404ba4 fixed circuit pin descriptions 2016-04-20 21:56:24 +02:00
5b398f1de4 reformat, to ease configuration 2016-04-20 10:34:46 +02:00
c9168bb1fd added some fritzing documentation 2016-04-20 00:33:18 +02:00
e63aedccf6 switch around some pins 2016-04-20 00:29:07 +02:00
f12580cd8e actually receive ir signals 2016-04-18 11:58:37 +02:00
5691267905 added new device type IrRx (infrared receiver) 2016-04-18 11:34:44 +02:00
7cafe6cccb elegant array handling 2016-04-11 21:09:31 +02:00
29 changed files with 930 additions and 219 deletions

4
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,4 @@
# 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 Normal file
View File

@ -0,0 +1,21 @@
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.

7
README.md Normal file
View File

@ -0,0 +1,7 @@
# 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.

BIN
doc/circuit.fzz Normal file

Binary file not shown.

BIN
doc/circuit_bb.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 396 KiB

View File

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

24
things/DeviceButton.cpp Normal file
View File

@ -0,0 +1,24 @@
#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");
}
}

18
things/DeviceButton.h Normal file
View File

@ -0,0 +1,18 @@
#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");
};

67
things/DeviceDht.cpp Normal file
View File

@ -0,0 +1,67 @@
#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,9 +1,8 @@
#ifndef DEVICEDHT_H
#define DEVICEDHT_H
#pragma once
#include "Device.h"
#include <Homie.h>
#include <DHT.h> // https://github.com/adafruit/DHT-sensor-library
#include <DHT.h> // https://github.com/adafruit/DHT-sensor-library
class DeviceDht : public Device {
public:
@ -26,70 +25,3 @@ class DeviceDht : public Device {
HomieNode temperatureNode{"temperature", "temperature"};
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

23
things/DeviceIrRx.cpp Normal file
View File

@ -0,0 +1,23 @@
#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
}
}

22
things/DeviceIrRx.h Normal file
View File

@ -0,0 +1,22 @@
#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");
};

81
things/DeviceIrTx.cpp Normal file
View File

@ -0,0 +1,81 @@
#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;
}

20
things/DeviceIrTx.h Normal file
View File

@ -0,0 +1,20 @@
#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");
};

27
things/DeviceLdr.cpp Normal file
View File

@ -0,0 +1,27 @@
#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,5 +1,4 @@
#ifndef DEVICELDR_H
#define DEVICELDR_H
#pragma once
#include "Device.h"
#include <Homie.h>
@ -19,31 +18,3 @@ class DeviceLdr : public Device {
int ldr = 0;
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

100
things/DeviceLed.cpp Normal file
View File

@ -0,0 +1,100 @@
#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,100 +1,30 @@
#ifndef DEVICELED_H
#define DEVICELED_H
#pragma once
#include "Device.h"
#include <Homie.h>
class DeviceLed : public Device {
public:
inline DeviceLed(byte ledRed, byte ledGreen, byte ledBlue) {
pinRed = ledRed;
pinGreen = ledGreen;
pinBlue = ledBlue;
inline DeviceLed(byte ledPin, char* ledName):ledNode(ledName, "led") {
pinLed = ledPin;
nameLed = ledName;
}
virtual void deviceSetup();
virtual void deviceRegister();
virtual void deviceLoop();
private:
byte pinRed;
byte pinGreen;
byte pinBlue;
int led_red = 0;
int led_green = 0;
int led_blue = 0;
bool ledOnHandler(String value);
bool ledColorHandler(String message);
HomieNode ledNode{"led", "rgb"};
bool ledBrightnessHandler(String message);
bool ledFadeHandler(String message);
private:
byte pinLed;
char* nameLed;
int brightness = 0;
bool fading = false;
int fade_from, fade_to;
unsigned long fade_start = 0;
unsigned long fade_end = 0;
float progress_last = 0;
void setLed(int value);
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

34
things/DeviceRelay.cpp Normal file
View File

@ -0,0 +1,34 @@
#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;
}

21
things/DeviceRelay.h Normal file
View File

@ -0,0 +1,21 @@
#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;
};

128
things/DeviceRgb.cpp Normal file
View File

@ -0,0 +1,128 @@
#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;
}

36
things/DeviceRgb.h Normal file
View File

@ -0,0 +1,36 @@
#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"};
};

46
things/HardwareH801wifi.h Normal file
View File

@ -0,0 +1,46 @@
/*
* 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() {};

54
things/HardwareSonoff.h Normal file
View File

@ -0,0 +1,54 @@
/*
* 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;
}
};

34
things/HardwareWitty.h Normal file
View File

@ -0,0 +1,34 @@
/*
* 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() {};

34
things/HardwareWittyBbq.h Normal file
View File

@ -0,0 +1,34 @@
/*
* 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() {};

41
things/HardwareWittyDht.h Normal file
View File

@ -0,0 +1,41 @@
/*
* 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

@ -0,0 +1,52 @@
/*
* 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,44 +1,31 @@
#include <Homie.h> // https://github.com/marvinroger/homie-esp8266
#include <Homie.h> // https://github.com/marvinroger/homie-esp8266
#include "DeviceLed.h"
#include "DeviceLdr.h"
#include "DeviceDht.h"
#include "HardwareWitty.h"
//#include "HardwareWittyDht.h"
//#include "HardwareWittyDhtIrRxTx.h"
//#include "HardwareWittyBbq.h"
//#include "HardwareH801wifi.h"
//#include "HardwareSonoff.h"
// 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];
const char* FWVERSION = "1.0.0";
void setupHandler() {
for (int i = 0; i < 2; i++) {
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) {
devices[i]->deviceSetup();
}
}
void loopHandler() {
for (int i = 0; i < 2; i++) {
hardwareLoop();
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) {
devices[i]->deviceLoop();
}
}
void setup() {
Homie.setFirmware("things", "1.0.0");
devices[0] = &deviceLed;
devices[1] = &deviceLdr;
//devices[2] = &deviceDht;
for (int i = 0; i < 2; i++) {
hardwareSetup();
Homie.setFirmware(FWNAME, FWVERSION);
for (int i = 0; i < sizeof(devices) / sizeof(*devices); i++) {
devices[i]->deviceRegister();
}
Homie.setSetupFunction(setupHandler);