Add SimpleRGB subsystem
This commit is contained in:
parent
0e01a7de9b
commit
914f3fdcb8
273
multi-esp.ino
273
multi-esp.ino
|
@ -4,6 +4,7 @@
|
||||||
#include <RCSwitch.h>
|
#include <RCSwitch.h>
|
||||||
#include <BH1750.h>
|
#include <BH1750.h>
|
||||||
#include <Wire.h>
|
#include <Wire.h>
|
||||||
|
#include <RGBConverter.h>
|
||||||
#include "secrets.h"
|
#include "secrets.h"
|
||||||
|
|
||||||
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
||||||
|
@ -17,6 +18,7 @@ const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
|
||||||
//const PROGMEM char* MQTT_PASSWORD = "[Redacted]";
|
//const PROGMEM char* MQTT_PASSWORD = "[Redacted]";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// RFSOCKET subsystem mqtt topic components
|
// RFSOCKET subsystem mqtt topic components
|
||||||
const char* MQTT_RFSOCKET_SUBSYSTEM = "rfsockets/";
|
const char* MQTT_RFSOCKET_SUBSYSTEM = "rfsockets/";
|
||||||
const char* MQTT_RFSOCKET_STATE_TOPIC = "/status";
|
const char* MQTT_RFSOCKET_STATE_TOPIC = "/status";
|
||||||
|
@ -37,6 +39,21 @@ const char* MQTT_BH1750_STATE_TOPIC = "/status";
|
||||||
unsigned long last_bh1750_publish = millis();
|
unsigned long last_bh1750_publish = millis();
|
||||||
|
|
||||||
|
|
||||||
|
// SimpleRGB subsystem
|
||||||
|
const PROGMEM uint8_t RGB_LIGHT_RED_PIN = 14; //D5
|
||||||
|
const PROGMEM uint8_t RGB_LIGHT_GREEN_PIN = 12; //D6
|
||||||
|
const PROGMEM uint8_t RGB_LIGHT_BLUE_PIN = 15; //D8
|
||||||
|
|
||||||
|
const char* MQTT_SIMPLERGB_SUBSYSTEM = "simplergb/";
|
||||||
|
const char* MQTT_SIMPLERGB_LOCATION = "livingroom_window";
|
||||||
|
|
||||||
|
const char* MQTT_SIMPLERGB_STATE_TOPIC = "/light/status";
|
||||||
|
const char* MQTT_SIMPLERGB_COMMAND_TOPIC = "/light/switch";
|
||||||
|
const char* MQTT_SIMPLERGB_BRIGHTNESS_STATE_TOPIC = "/brightness/status";
|
||||||
|
const char* MQTT_SIMPLERGB_BRIGHTNESS_COMMAND_TOPIC = "/brightness/set";
|
||||||
|
const char* MQTT_SIMPLERGB_RGB_STATE_TOPIC = "/rgb/status";
|
||||||
|
const char* MQTT_SIMPLERGB_RGB_COMMAND_TOPIC = "/rgb/set";
|
||||||
|
|
||||||
|
|
||||||
WiFiClient wifiClient;
|
WiFiClient wifiClient;
|
||||||
PubSubClient client(wifiClient);
|
PubSubClient client(wifiClient);
|
||||||
|
@ -44,6 +61,17 @@ PubSubClient client(wifiClient);
|
||||||
RCSwitch mySwitch = RCSwitch();
|
RCSwitch mySwitch = RCSwitch();
|
||||||
BH1750 lightMeter;
|
BH1750 lightMeter;
|
||||||
|
|
||||||
|
RGBConverter colorConverter;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t red;
|
||||||
|
uint8_t green;
|
||||||
|
uint8_t blue;
|
||||||
|
bool powered;
|
||||||
|
} SimpleRGBStrip;
|
||||||
|
|
||||||
|
SimpleRGBStrip simpleRGBStrip = (SimpleRGBStrip) {0, 0, 0, false};
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* channel; // First DIP set
|
char* channel; // First DIP set
|
||||||
|
@ -70,6 +98,94 @@ PowerSocket sockets[] = {
|
||||||
int numofsockets = sizeof(sockets)/sizeof(sockets[0]);
|
int numofsockets = sizeof(sockets)/sizeof(sockets[0]);
|
||||||
|
|
||||||
|
|
||||||
|
// function called to adapt the brightness and the color of the led
|
||||||
|
void setColorHSV(double hue, double saturation, double value) {
|
||||||
|
hue += 1.0/(360.0*4);
|
||||||
|
if(hue >= 1.0) {
|
||||||
|
hue = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte rgb[] = {0.0, 0.0, 0.0};
|
||||||
|
colorConverter.hsvToRgb(hue, saturation, value, rgb);
|
||||||
|
setColorRGB(rgb[0], rgb[1], rgb[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setColorRGB(uint8_t red, uint8_t green, uint8_t blue) {
|
||||||
|
analogWrite(RGB_LIGHT_RED_PIN, (1.0/255.0)*red*1023);
|
||||||
|
analogWrite(RGB_LIGHT_GREEN_PIN, (1.0/255.0)*green*1023);
|
||||||
|
analogWrite(RGB_LIGHT_BLUE_PIN, (1.0/255.0)*blue*1023);
|
||||||
|
|
||||||
|
simpleRGBStrip.red = red;
|
||||||
|
simpleRGBStrip.green = green;
|
||||||
|
simpleRGBStrip.blue = blue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//// function called to publish the state of the led (on/off)
|
||||||
|
void publishRGBState() {
|
||||||
|
char topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_STATE_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_STATE_TOPIC);
|
||||||
|
|
||||||
|
if (simpleRGBStrip.powered) {
|
||||||
|
client.publish(topic, LIGHT_ON, true);
|
||||||
|
} else {
|
||||||
|
client.publish(topic, LIGHT_OFF, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function called to publish the brightness of the led (0-100)
|
||||||
|
void publishRGBBrightness() {
|
||||||
|
char topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_STATE_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_BRIGHTNESS_STATE_TOPIC);
|
||||||
|
|
||||||
|
double hsv[] = {0.0, 0.0, 0.0};
|
||||||
|
colorConverter.rgbToHsv(simpleRGBStrip.red, simpleRGBStrip.green, simpleRGBStrip.blue, hsv);
|
||||||
|
char brightness[3];
|
||||||
|
itoa(hsv[2] * 100, brightness, 10);
|
||||||
|
|
||||||
|
client.publish(topic, brightness, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// function called to publish the colors of the led (xx(x),xx(x),xx(x))
|
||||||
|
void publishRGBColor() {
|
||||||
|
char *separator = ",";
|
||||||
|
char red[8];
|
||||||
|
char green[8];
|
||||||
|
char blue[8];
|
||||||
|
itoa(simpleRGBStrip.red, red, 10);
|
||||||
|
itoa(simpleRGBStrip.green, green, 10);
|
||||||
|
itoa(simpleRGBStrip.blue, blue, 10);
|
||||||
|
|
||||||
|
char payload[11];
|
||||||
|
strcpy(payload, red);
|
||||||
|
strcat(payload, separator);
|
||||||
|
strcat(payload, green);
|
||||||
|
strcat(payload, separator);
|
||||||
|
strcat(payload, blue);
|
||||||
|
|
||||||
|
char topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_STATE_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(topic, MQTT_SIMPLERGB_RGB_STATE_TOPIC);
|
||||||
|
client.publish(topic, payload, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// function called to measure and publish the state of the BH1750
|
// function called to measure and publish the state of the BH1750
|
||||||
void publishBH1750State() {
|
void publishBH1750State() {
|
||||||
uint16_t lux = lightMeter.readLightLevel();
|
uint16_t lux = lightMeter.readLightLevel();
|
||||||
|
@ -119,6 +235,102 @@ void setSocketState(byte socketIdx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handler for mqtt messages arriving on that subsystems topic
|
||||||
|
void subsystem_simplergb(char *topic_ptr, String payload) {
|
||||||
|
const char* delimiter = "/";
|
||||||
|
topic_ptr = strtok(NULL, delimiter);
|
||||||
|
if (topic_ptr != NULL) {
|
||||||
|
char *location = topic_ptr;
|
||||||
|
if(strcmp(location, "livingroom_window") == 0) {
|
||||||
|
topic_ptr = strtok(NULL, "");
|
||||||
|
char *command = topic_ptr;
|
||||||
|
if(strcmp(command, "light/switch") == 0) {
|
||||||
|
Serial.println("Command: light");
|
||||||
|
if (payload.equals(String(LIGHT_ON))) {
|
||||||
|
if (simpleRGBStrip.powered != true) {
|
||||||
|
simpleRGBStrip.powered = true;
|
||||||
|
setColorRGB(simpleRGBStrip.red, simpleRGBStrip.green, simpleRGBStrip.blue);
|
||||||
|
publishRGBState();
|
||||||
|
}
|
||||||
|
} else if (payload.equals(String(LIGHT_OFF))) {
|
||||||
|
if (simpleRGBStrip.powered != false) {
|
||||||
|
simpleRGBStrip.powered = false;
|
||||||
|
setColorRGB(0, 0, 0);
|
||||||
|
publishRGBState();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Serial.print("Unknown payload received: ");
|
||||||
|
Serial.println(payload);
|
||||||
|
Serial.println("Ignoring it…\n");
|
||||||
|
}
|
||||||
|
} else if(strcmp(command, "brightness/set") == 0) {
|
||||||
|
Serial.println("Command: brightness");
|
||||||
|
uint8_t brightness = payload.toInt();
|
||||||
|
if (brightness >= 0 && brightness <= 100) {
|
||||||
|
Serial.print("Parsed brightness value of: ");
|
||||||
|
Serial.println(brightness);
|
||||||
|
double hsv[] = {0.0, 0.0, 0.0};
|
||||||
|
colorConverter.rgbToHsv(simpleRGBStrip.red, simpleRGBStrip.green, simpleRGBStrip.blue, hsv);
|
||||||
|
setColorHSV(hsv[0], hsv[1], (1.0/100.0) * brightness);
|
||||||
|
|
||||||
|
publishRGBBrightness();
|
||||||
|
} else {
|
||||||
|
Serial.print("Parsed invalid brightness value of: ");
|
||||||
|
Serial.println(brightness);
|
||||||
|
}
|
||||||
|
} else if(strcmp(command, "rgb/set") == 0) {
|
||||||
|
Serial.println("Command: rgb");
|
||||||
|
uint8_t rgb[] = {0, 0, 0};
|
||||||
|
parseRGBPayload(payload, rgb);
|
||||||
|
setColorRGB(rgb[0], rgb[1], rgb[2]);
|
||||||
|
publishRGBColor();
|
||||||
|
} else {
|
||||||
|
Serial.print("Unknown command \"");
|
||||||
|
Serial.print(command);
|
||||||
|
Serial.println("\" in topic found. Ignoring…");
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
Serial.print("Unknown location: ");
|
||||||
|
Serial.println(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void parseRGBPayload(String payload, uint8_t rgb[]) {
|
||||||
|
Serial.print("String payload: ");
|
||||||
|
Serial.println(payload);
|
||||||
|
char payload_c[10];
|
||||||
|
payload.toCharArray(payload_c, 10);
|
||||||
|
char *payload_ptr;
|
||||||
|
|
||||||
|
const char* delimiter = ",";
|
||||||
|
int red;
|
||||||
|
int green;
|
||||||
|
int blue;
|
||||||
|
payload_ptr = strtok(payload_c, delimiter);
|
||||||
|
|
||||||
|
uint8_t color_idx = 0;
|
||||||
|
while(payload_ptr != NULL) {
|
||||||
|
int color = atoi(payload_ptr);
|
||||||
|
payload_ptr = strtok(NULL, delimiter);
|
||||||
|
if(color_idx < sizeof(rgb)/sizeof(uint8_t)) {
|
||||||
|
rgb[color_idx] = color;
|
||||||
|
Serial.print("Setting color idx: ");
|
||||||
|
Serial.print(color_idx);
|
||||||
|
Serial.print(" with value ");
|
||||||
|
Serial.println(color);
|
||||||
|
}
|
||||||
|
color_idx++;
|
||||||
|
}
|
||||||
|
Serial.print("Parsed colors: ");
|
||||||
|
Serial.print(" red: ");
|
||||||
|
Serial.print(rgb[0]);
|
||||||
|
Serial.print(" green: ");
|
||||||
|
Serial.print(rgb[1]);
|
||||||
|
Serial.print(" blue: ");
|
||||||
|
Serial.println(rgb[2]);
|
||||||
|
}
|
||||||
|
|
||||||
// handler for mqtt messages arriving on that subsystems topic
|
// handler for mqtt messages arriving on that subsystems topic
|
||||||
void subsystem_rfsockets(char *topic_ptr, String payload) {
|
void subsystem_rfsockets(char *topic_ptr, String payload) {
|
||||||
const char* delimiter = "/";
|
const char* delimiter = "/";
|
||||||
|
@ -173,7 +385,11 @@ void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
|
||||||
Serial.print("Found subsystem: ");
|
Serial.print("Found subsystem: ");
|
||||||
Serial.println(subsystem);
|
Serial.println(subsystem);
|
||||||
if(strcmp(subsystem, "rfsockets") == 0) {
|
if(strcmp(subsystem, "rfsockets") == 0) {
|
||||||
|
Serial.println("Selecting subsystem rfsockets");
|
||||||
subsystem_rfsockets(topic_ptr, payload);
|
subsystem_rfsockets(topic_ptr, payload);
|
||||||
|
} else if(strcmp(subsystem, "simplergb") == 0) {
|
||||||
|
Serial.println("Selecting subsystem simplergb");
|
||||||
|
subsystem_simplergb(topic_ptr, payload);
|
||||||
} else {
|
} else {
|
||||||
Serial.print("Unknown subsystem \"");
|
Serial.print("Unknown subsystem \"");
|
||||||
Serial.print(subsystem);
|
Serial.print(subsystem);
|
||||||
|
@ -195,12 +411,19 @@ void reconnect() {
|
||||||
// Attempt to connect
|
// Attempt to connect
|
||||||
if (client.connect(MQTT_CLIENT_ID)) {
|
if (client.connect(MQTT_CLIENT_ID)) {
|
||||||
Serial.println("INFO: connected");
|
Serial.println("INFO: connected");
|
||||||
|
publishRGBState();
|
||||||
|
publishRGBColor();
|
||||||
|
publishRGBBrightness();
|
||||||
for (int i = 0; i < numofsockets; i++) {
|
for (int i = 0; i < numofsockets; i++) {
|
||||||
publishSocketState(i);
|
publishSocketState(i);
|
||||||
}
|
}
|
||||||
for (int i = 0; i < numofsockets; i++) {
|
for (int i = 0; i < numofsockets; i++) {
|
||||||
char *socket_name = sockets[i].name;
|
char *socket_name = sockets[i].name;
|
||||||
char topic[strlen(MQTT_RFSOCKET_SUBSYSTEM) + strlen(MQTT_RFSOCKET_COMMAND_TOPIC) + strlen(socket_name)];
|
char topic[
|
||||||
|
strlen(MQTT_RFSOCKET_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_RFSOCKET_COMMAND_TOPIC) +
|
||||||
|
strlen(socket_name)
|
||||||
|
];
|
||||||
strcpy(topic, MQTT_RFSOCKET_SUBSYSTEM);
|
strcpy(topic, MQTT_RFSOCKET_SUBSYSTEM);
|
||||||
strcat(topic, socket_name);
|
strcat(topic, socket_name);
|
||||||
strcat(topic, MQTT_RFSOCKET_COMMAND_TOPIC);
|
strcat(topic, MQTT_RFSOCKET_COMMAND_TOPIC);
|
||||||
|
@ -210,6 +433,48 @@ void reconnect() {
|
||||||
Serial.println("\"");
|
Serial.println("\"");
|
||||||
client.subscribe(topic);
|
client.subscribe(topic);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char simplergb_topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_COMMAND_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(simplergb_topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(simplergb_topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(simplergb_topic, MQTT_SIMPLERGB_COMMAND_TOPIC);
|
||||||
|
|
||||||
|
Serial.print("INFO: subscribing to topic \"");
|
||||||
|
Serial.print(simplergb_topic);
|
||||||
|
Serial.println("\"");
|
||||||
|
client.subscribe(simplergb_topic);
|
||||||
|
|
||||||
|
char simplergb_b_topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_BRIGHTNESS_COMMAND_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(simplergb_b_topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(simplergb_b_topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(simplergb_b_topic, MQTT_SIMPLERGB_BRIGHTNESS_COMMAND_TOPIC);
|
||||||
|
|
||||||
|
Serial.print("INFO: subscribing to topic \"");
|
||||||
|
Serial.print(simplergb_b_topic);
|
||||||
|
Serial.println("\"");
|
||||||
|
client.subscribe(simplergb_b_topic);
|
||||||
|
|
||||||
|
char simplergb_rgb_topic[
|
||||||
|
strlen(MQTT_SIMPLERGB_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_SIMPLERGB_LOCATION) +
|
||||||
|
strlen(MQTT_SIMPLERGB_RGB_COMMAND_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(simplergb_rgb_topic, MQTT_SIMPLERGB_SUBSYSTEM);
|
||||||
|
strcat(simplergb_rgb_topic, MQTT_SIMPLERGB_LOCATION);
|
||||||
|
strcat(simplergb_rgb_topic, MQTT_SIMPLERGB_RGB_COMMAND_TOPIC);
|
||||||
|
|
||||||
|
Serial.print("INFO: subscribing to topic \"");
|
||||||
|
Serial.print(simplergb_rgb_topic);
|
||||||
|
Serial.println("\"");
|
||||||
|
client.subscribe(simplergb_rgb_topic);
|
||||||
} else {
|
} else {
|
||||||
Serial.print("ERROR: failed, rc=");
|
Serial.print("ERROR: failed, rc=");
|
||||||
Serial.print(client.state());
|
Serial.print(client.state());
|
||||||
|
@ -217,6 +482,7 @@ void reconnect() {
|
||||||
// Wait 5 seconds before retrying
|
// Wait 5 seconds before retrying
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,6 +574,11 @@ void setup() {
|
||||||
Wire.begin();
|
Wire.begin();
|
||||||
lightMeter.begin();
|
lightMeter.begin();
|
||||||
|
|
||||||
|
// setup rgb light outputs
|
||||||
|
pinMode(RGB_LIGHT_BLUE_PIN, OUTPUT);
|
||||||
|
pinMode(RGB_LIGHT_RED_PIN, OUTPUT);
|
||||||
|
pinMode(RGB_LIGHT_GREEN_PIN, OUTPUT);
|
||||||
|
|
||||||
// init the MQTT connection
|
// init the MQTT connection
|
||||||
client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
|
client.setServer(MQTT_SERVER_IP, MQTT_SERVER_PORT);
|
||||||
client.setCallback(callback);
|
client.setCallback(callback);
|
||||||
|
|
Loading…
Reference in a new issue