initial commit
This commit is contained in:
parent
ecb23567ae
commit
d00b1d843c
Binary file not shown.
Binary file not shown.
Binary file not shown.
After Width: | Height: | Size: 123 KiB |
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
.______ .______ __ __ __ __ ___ __ __ .___________. ______ .___ ___. ___ .___________. __ ______ .__ __.
|
||||
| _ \ | _ \ | | | | | | | | / \ | | | | | | / __ \ | \/ | / \ | || | / __ \ | \ | |
|
||||
| |_) | | |_) | | | | | | |__| | / ^ \ | | | | `---| |----`| | | | | \ / | / ^ \ `---| |----`| | | | | | | \| |
|
||||
| _ < | / | | | | | __ | / /_\ \ | | | | | | | | | | | |\/| | / /_\ \ | | | | | | | | | . ` |
|
||||
| |_) | | |\ \-.| `--' | | | | | / _____ \ | `--' | | | | `--' | | | | | / _____ \ | | | | | `--' | | |\ |
|
||||
|______/ | _| `.__| \______/ |__| |__| /__/ \__\ \______/ |__| \______/ |__| |__| /__/ \__\ |__| |__| \______/ |__| \__|
|
||||
|
||||
Thanks much to @corbanmailloux for providing a great framework for implementing flash/fade with HomeAssistant https://github.com/corbanmailloux/esp-mqtt-rgb-led
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <DHT.h>
|
||||
#include <PubSubClient.h>
|
||||
#include <ESP8266mDNS.h>
|
||||
#include <WiFiUdp.h>
|
||||
#include <ArduinoOTA.h>
|
||||
#include <ArduinoJson.h>
|
||||
|
||||
|
||||
|
||||
/************ WIFI and MQTT INFORMATION (CHANGE THESE FOR YOUR SETUP) ******************/
|
||||
#define wifi_ssid "YourSSID" //type your WIFI information inside the quotes
|
||||
#define wifi_password "YourWIFIpassword"
|
||||
#define mqtt_server "your.mqtt.server.ip"
|
||||
#define mqtt_user "yourMQTTusername"
|
||||
#define mqtt_password "yourMQTTpassword"
|
||||
#define mqtt_port 1883
|
||||
|
||||
|
||||
/************* MQTT TOPICS (change these topics as you wish) **************************/
|
||||
#define light_state_topic "bruh/sensornode1"
|
||||
#define light_set_topic "bruh/sensornode1/set"
|
||||
|
||||
const char* on_cmd = "ON";
|
||||
const char* off_cmd = "OFF";
|
||||
|
||||
|
||||
|
||||
/**************************** FOR OTA **************************************************/
|
||||
#define SENSORNAME "sensornode1"
|
||||
#define OTApassword "bruh"
|
||||
int OTAport = 8266;
|
||||
|
||||
|
||||
|
||||
/**************************** PIN DEFINITIONS ********************************************/
|
||||
const int redPin = D1;
|
||||
const int greenPin = D2;
|
||||
const int bluePin = D3;
|
||||
#define PIRPIN D5
|
||||
#define DHTPIN D7
|
||||
#define DHTTYPE DHT22
|
||||
#define LDRPIN A0
|
||||
|
||||
|
||||
|
||||
/**************************** SENSOR DEFINITIONS *******************************************/
|
||||
float ldrValue;
|
||||
int LDR;
|
||||
float calcLDR;
|
||||
float diffLDR = 25;
|
||||
|
||||
float diffTEMP = 0.2;
|
||||
float tempValue;
|
||||
|
||||
float diffHUM = 1;
|
||||
float humValue;
|
||||
|
||||
int pirValue;
|
||||
int pirStatus;
|
||||
String motionStatus;
|
||||
|
||||
char message_buff[100];
|
||||
|
||||
int calibrationTime = 0;
|
||||
|
||||
const int BUFFER_SIZE = 300;
|
||||
|
||||
|
||||
|
||||
/******************************** GLOBALS for fade/flash *******************************/
|
||||
byte red = 255;
|
||||
byte green = 255;
|
||||
byte blue = 255;
|
||||
byte brightness = 255;
|
||||
|
||||
byte realRed = 0;
|
||||
byte realGreen = 0;
|
||||
byte realBlue = 0;
|
||||
|
||||
bool stateOn = false;
|
||||
|
||||
bool startFade = false;
|
||||
unsigned long lastLoop = 0;
|
||||
int transitionTime = 0;
|
||||
bool inFade = false;
|
||||
int loopCount = 0;
|
||||
int stepR, stepG, stepB;
|
||||
int redVal, grnVal, bluVal;
|
||||
|
||||
bool flash = false;
|
||||
bool startFlash = false;
|
||||
int flashLength = 0;
|
||||
unsigned long flashStartTime = 0;
|
||||
byte flashRed = red;
|
||||
byte flashGreen = green;
|
||||
byte flashBlue = blue;
|
||||
byte flashBrightness = brightness;
|
||||
|
||||
|
||||
|
||||
WiFiClient espClient;
|
||||
PubSubClient client(espClient);
|
||||
DHT dht(DHTPIN, DHTTYPE);
|
||||
|
||||
|
||||
|
||||
/********************************** START SETUP*****************************************/
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
pinMode(PIRPIN, INPUT);
|
||||
pinMode(DHTPIN, INPUT);
|
||||
pinMode(LDRPIN, INPUT);
|
||||
|
||||
Serial.begin(115200);
|
||||
delay(10);
|
||||
|
||||
ArduinoOTA.setPort(OTAport);
|
||||
|
||||
ArduinoOTA.setHostname(SENSORNAME);
|
||||
|
||||
ArduinoOTA.setPassword((const char *)OTApassword);
|
||||
|
||||
Serial.print("calibrating sensor ");
|
||||
for (int i = 0; i < calibrationTime; i++) {
|
||||
Serial.print(".");
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
Serial.println("Starting Node named " + String(SENSORNAME));
|
||||
|
||||
|
||||
setup_wifi();
|
||||
|
||||
client.setServer(mqtt_server, mqtt_port);
|
||||
client.setCallback(callback);
|
||||
|
||||
|
||||
ArduinoOTA.onStart([]() {
|
||||
Serial.println("Starting");
|
||||
});
|
||||
ArduinoOTA.onEnd([]() {
|
||||
Serial.println("\nEnd");
|
||||
});
|
||||
ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) {
|
||||
Serial.printf("Progress: %u%%\r", (progress / (total / 100)));
|
||||
});
|
||||
ArduinoOTA.onError([](ota_error_t error) {
|
||||
Serial.printf("Error[%u]: ", error);
|
||||
if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed");
|
||||
else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed");
|
||||
else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed");
|
||||
else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed");
|
||||
else if (error == OTA_END_ERROR) Serial.println("End Failed");
|
||||
});
|
||||
ArduinoOTA.begin();
|
||||
Serial.println("Ready");
|
||||
Serial.print("IPess: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/********************************** START SETUP WIFI*****************************************/
|
||||
void setup_wifi() {
|
||||
|
||||
delay(10);
|
||||
Serial.println();
|
||||
Serial.print("Connecting to ");
|
||||
Serial.println(wifi_ssid);
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(wifi_ssid, wifi_password);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
|
||||
Serial.println("");
|
||||
Serial.println("WiFi connected");
|
||||
Serial.println("IP address: ");
|
||||
Serial.println(WiFi.localIP());
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START CALLBACK*****************************************/
|
||||
void callback(char* topic, byte* payload, unsigned int length) {
|
||||
Serial.print("Message arrived [");
|
||||
Serial.print(topic);
|
||||
Serial.print("] ");
|
||||
|
||||
char message[length + 1];
|
||||
for (int i = 0; i < length; i++) {
|
||||
message[i] = (char)payload[i];
|
||||
}
|
||||
message[length] = '\0';
|
||||
Serial.println(message);
|
||||
|
||||
if (!processJson(message)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (stateOn) {
|
||||
// Update lights
|
||||
realRed = map(red, 0, 255, 0, brightness);
|
||||
realGreen = map(green, 0, 255, 0, brightness);
|
||||
realBlue = map(blue, 0, 255, 0, brightness);
|
||||
}
|
||||
else {
|
||||
realRed = 0;
|
||||
realGreen = 0;
|
||||
realBlue = 0;
|
||||
}
|
||||
|
||||
startFade = true;
|
||||
inFade = false; // Kill the current fade
|
||||
|
||||
sendState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START PROCESS JSON*****************************************/
|
||||
bool processJson(char* message) {
|
||||
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.parseObject(message);
|
||||
|
||||
if (!root.success()) {
|
||||
Serial.println("parseObject() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (root.containsKey("state")) {
|
||||
if (strcmp(root["state"], on_cmd) == 0) {
|
||||
stateOn = true;
|
||||
}
|
||||
else if (strcmp(root["state"], off_cmd) == 0) {
|
||||
stateOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
// If "flash" is included, treat RGB and brightness differently
|
||||
if (root.containsKey("flash")) {
|
||||
flashLength = (int)root["flash"] * 1000;
|
||||
|
||||
if (root.containsKey("brightness")) {
|
||||
flashBrightness = root["brightness"];
|
||||
}
|
||||
else {
|
||||
flashBrightness = brightness;
|
||||
}
|
||||
|
||||
if (root.containsKey("color")) {
|
||||
flashRed = root["color"]["r"];
|
||||
flashGreen = root["color"]["g"];
|
||||
flashBlue = root["color"]["b"];
|
||||
}
|
||||
else {
|
||||
flashRed = red;
|
||||
flashGreen = green;
|
||||
flashBlue = blue;
|
||||
}
|
||||
|
||||
flashRed = map(flashRed, 0, 255, 0, flashBrightness);
|
||||
flashGreen = map(flashGreen, 0, 255, 0, flashBrightness);
|
||||
flashBlue = map(flashBlue, 0, 255, 0, flashBrightness);
|
||||
|
||||
flash = true;
|
||||
startFlash = true;
|
||||
}
|
||||
else { // Not flashing
|
||||
flash = false;
|
||||
|
||||
if (root.containsKey("color")) {
|
||||
red = root["color"]["r"];
|
||||
green = root["color"]["g"];
|
||||
blue = root["color"]["b"];
|
||||
}
|
||||
|
||||
if (root.containsKey("brightness")) {
|
||||
brightness = root["brightness"];
|
||||
}
|
||||
|
||||
if (root.containsKey("transition")) {
|
||||
transitionTime = root["transition"];
|
||||
}
|
||||
else {
|
||||
transitionTime = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START SEND STATE*****************************************/
|
||||
void sendState() {
|
||||
StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
|
||||
|
||||
JsonObject& root = jsonBuffer.createObject();
|
||||
|
||||
root["state"] = (stateOn) ? on_cmd : off_cmd;
|
||||
JsonObject& color = root.createNestedObject("color");
|
||||
color["r"] = red;
|
||||
color["g"] = green;
|
||||
color["b"] = blue;
|
||||
|
||||
|
||||
root["brightness"] = brightness;
|
||||
root["humidity"] = (String)humValue;
|
||||
root["motion"] = (String)motionStatus;
|
||||
root["ldr"] = (String)LDR;
|
||||
root["temperature"] = (String)tempValue;
|
||||
|
||||
|
||||
char buffer[root.measureLength() + 1];
|
||||
root.printTo(buffer, sizeof(buffer));
|
||||
|
||||
Serial.println(buffer);
|
||||
client.publish(light_state_topic, buffer, true);
|
||||
}
|
||||
|
||||
|
||||
/********************************** START SET COLOR *****************************************/
|
||||
void setColor(int inR, int inG, int inB) {
|
||||
analogWrite(redPin, inR);
|
||||
analogWrite(greenPin, inG);
|
||||
analogWrite(bluePin, inB);
|
||||
|
||||
Serial.println("Setting LEDs:");
|
||||
Serial.print("r: ");
|
||||
Serial.print(inR);
|
||||
Serial.print(", g: ");
|
||||
Serial.print(inG);
|
||||
Serial.print(", b: ");
|
||||
Serial.println(inB);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START RECONNECT*****************************************/
|
||||
void reconnect() {
|
||||
// Loop until we're reconnected
|
||||
while (!client.connected()) {
|
||||
Serial.print("Attempting MQTT connection...");
|
||||
// Attempt to connect
|
||||
if (client.connect(SENSORNAME, mqtt_user, mqtt_password)) {
|
||||
Serial.println("connected");
|
||||
client.subscribe(light_set_topic);
|
||||
setColor(0, 0, 0);
|
||||
sendState();
|
||||
} else {
|
||||
Serial.print("failed, rc=");
|
||||
Serial.print(client.state());
|
||||
Serial.println(" try again in 5 seconds");
|
||||
// Wait 5 seconds before retrying
|
||||
delay(5000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START CHECK SENSOR **********************************/
|
||||
bool checkBoundSensor(float newValue, float prevValue, float maxDiff) {
|
||||
return newValue < prevValue - maxDiff || newValue > prevValue + maxDiff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/********************************** START MAIN LOOP***************************************/
|
||||
void loop() {
|
||||
|
||||
ArduinoOTA.handle();
|
||||
|
||||
if (!client.connected()) {
|
||||
reconnect();
|
||||
}
|
||||
client.loop();
|
||||
|
||||
|
||||
if (!inFade) {
|
||||
|
||||
float newTempValue = dht.readTemperature(true);
|
||||
float newHumValue = dht.readHumidity();
|
||||
|
||||
//PIR CODE
|
||||
pirValue = digitalRead(PIRPIN); //read state of the
|
||||
|
||||
if (pirValue == LOW && pirStatus != 1) {
|
||||
motionStatus = "standby";
|
||||
sendState();
|
||||
pirStatus = 1;
|
||||
}
|
||||
|
||||
else if (pirValue == HIGH && pirStatus != 2) {
|
||||
motionStatus = "motion detected";
|
||||
sendState();
|
||||
pirStatus = 2;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
if (checkBoundSensor(newTempValue, tempValue, diffTEMP)) {
|
||||
tempValue = newTempValue;
|
||||
sendState();
|
||||
}
|
||||
|
||||
if (checkBoundSensor(newHumValue, humValue, diffHUM)) {
|
||||
humValue = newHumValue;
|
||||
sendState();
|
||||
}
|
||||
|
||||
|
||||
int newLDR = analogRead(LDRPIN);
|
||||
|
||||
if (checkBoundSensor(newLDR, LDR, diffLDR)) {
|
||||
LDR = newLDR;
|
||||
sendState();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (flash) {
|
||||
if (startFlash) {
|
||||
startFlash = false;
|
||||
flashStartTime = millis();
|
||||
}
|
||||
|
||||
if ((millis() - flashStartTime) <= flashLength) {
|
||||
if ((millis() - flashStartTime) % 1000 <= 500) {
|
||||
setColor(flashRed, flashGreen, flashBlue);
|
||||
}
|
||||
else {
|
||||
setColor(0, 0, 0);
|
||||
// If you'd prefer the flashing to happen "on top of"
|
||||
// the current color, uncomment the next line.
|
||||
// setColor(realRed, realGreen, realBlue);
|
||||
}
|
||||
}
|
||||
else {
|
||||
flash = false;
|
||||
setColor(realRed, realGreen, realBlue);
|
||||
}
|
||||
}
|
||||
|
||||
if (startFade) {
|
||||
// If we don't want to fade, skip it.
|
||||
if (transitionTime == 0) {
|
||||
setColor(realRed, realGreen, realBlue);
|
||||
|
||||
redVal = realRed;
|
||||
grnVal = realGreen;
|
||||
bluVal = realBlue;
|
||||
|
||||
startFade = false;
|
||||
}
|
||||
else {
|
||||
loopCount = 0;
|
||||
stepR = calculateStep(redVal, realRed);
|
||||
stepG = calculateStep(grnVal, realGreen);
|
||||
stepB = calculateStep(bluVal, realBlue);
|
||||
|
||||
inFade = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (inFade) {
|
||||
startFade = false;
|
||||
unsigned long now = millis();
|
||||
if (now - lastLoop > transitionTime) {
|
||||
if (loopCount <= 1020) {
|
||||
lastLoop = now;
|
||||
|
||||
redVal = calculateVal(stepR, redVal, loopCount);
|
||||
grnVal = calculateVal(stepG, grnVal, loopCount);
|
||||
bluVal = calculateVal(stepB, bluVal, loopCount);
|
||||
|
||||
setColor(redVal, grnVal, bluVal); // Write current values to LED pins
|
||||
|
||||
Serial.print("Loop count: ");
|
||||
Serial.println(loopCount);
|
||||
loopCount++;
|
||||
}
|
||||
else {
|
||||
inFade = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**************************** START TRANSITION FADER *****************************************/
|
||||
// From https://www.arduino.cc/en/Tutorial/ColorCrossfader
|
||||
/* BELOW THIS LINE IS THE MATH -- YOU SHOULDN'T NEED TO CHANGE THIS FOR THE BASICS
|
||||
|
||||
The program works like this:
|
||||
Imagine a crossfade that moves the red LED from 0-10,
|
||||
the green from 0-5, and the blue from 10 to 7, in
|
||||
ten steps.
|
||||
We'd want to count the 10 steps and increase or
|
||||
decrease color values in evenly stepped increments.
|
||||
Imagine a + indicates raising a value by 1, and a -
|
||||
equals lowering it. Our 10 step fade would look like:
|
||||
|
||||
1 2 3 4 5 6 7 8 9 10
|
||||
R + + + + + + + + + +
|
||||
G + + + + +
|
||||
B - - -
|
||||
|
||||
The red rises from 0 to 10 in ten steps, the green from
|
||||
0-5 in 5 steps, and the blue falls from 10 to 7 in three steps.
|
||||
|
||||
In the real program, the color percentages are converted to
|
||||
0-255 values, and there are 1020 steps (255*4).
|
||||
|
||||
To figure out how big a step there should be between one up- or
|
||||
down-tick of one of the LED values, we call calculateStep(),
|
||||
which calculates the absolute gap between the start and end values,
|
||||
and then divides that gap by 1020 to determine the size of the step
|
||||
between adjustments in the value.
|
||||
*/
|
||||
int calculateStep(int prevValue, int endValue) {
|
||||
int step = endValue - prevValue; // What's the overall gap?
|
||||
if (step) { // If its non-zero,
|
||||
step = 1020 / step; // divide by 1020
|
||||
}
|
||||
|
||||
return step;
|
||||
}
|
||||
|
||||
/* The next function is calculateVal. When the loop value, i,
|
||||
reaches the step size appropriate for one of the
|
||||
colors, it increases or decreases the value of that color by 1.
|
||||
(R, G, and B are each calculated separately.)
|
||||
*/
|
||||
int calculateVal(int step, int val, int i) {
|
||||
if ((step) && i % step == 0) { // If step is non-zero and its time to change a value,
|
||||
if (step > 0) { // increment the value if step is positive...
|
||||
val += 1;
|
||||
}
|
||||
else if (step < 0) { // ...or decrement it if step is negative
|
||||
val -= 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Defensive driving: make sure val stays in the range 0-255
|
||||
if (val > 255) {
|
||||
val = 255;
|
||||
}
|
||||
else if (val < 0) {
|
||||
val = 0;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
mqtt:
|
||||
broker: your.mqtt.ip.address
|
||||
port: 1883
|
||||
client_id: home-assistant-1
|
||||
username: YOURUSERNAME
|
||||
password: YOURPASSWORD
|
||||
|
||||
|
||||
light:
|
||||
- platform: mqtt_json
|
||||
name: "SN1 LED"
|
||||
state_topic: "bruh/sensornode1"
|
||||
command_topic: "bruh/sensornode1/set"
|
||||
brightness: true
|
||||
flash: true
|
||||
rgb: true
|
||||
optimistic: false
|
||||
qos: 0
|
||||
|
||||
|
||||
sensor:
|
||||
- platform: mqtt
|
||||
state_topic: "bruh/sensornode1"
|
||||
name: "SN1 Humidity"
|
||||
unit_of_measurement: "%"
|
||||
value_template: '{{ value_json.humidity | round(1) }}'
|
||||
|
||||
- platform: mqtt
|
||||
state_topic: "bruh/sensornode1"
|
||||
name: "SN1 LDR"
|
||||
unit_of_measurement: "LUX"
|
||||
value_template: '{{ value_json.ldr }}'
|
||||
|
||||
- platform: mqtt
|
||||
state_topic: "bruh/sensornode1"
|
||||
name: "SN1 PIR"
|
||||
value_template: '{{ value_json.motion }}'
|
||||
|
||||
- platform: mqtt
|
||||
state_topic: "bruh/sensornode1"
|
||||
name: "SN1 Temperature"
|
||||
unit_of_measurement: "°F"
|
||||
value_template: '{{ value_json.temperature | round(1) }}'
|
||||
|
||||
|
||||
group:
|
||||
sensor_node_1_card:
|
||||
name: Sensor Node 1
|
||||
entities:
|
||||
- sensor.sn1_temperature
|
||||
- sensor.sn1_humidity
|
||||
- sensor.sn1_ldr
|
||||
- sensor.sn1_pir
|
||||
- light.sn1_led
|
Loading…
Reference in New Issue