Add BH1750 subsystem
Currently the subsystem only supports one single sensor. It publishes its state to lightsensor/livingroom_window/status every 5 seconds.
This commit is contained in:
parent
0e0a10ae7b
commit
0e01a7de9b
167
multi-esp.ino
167
multi-esp.ino
|
@ -2,20 +2,57 @@
|
||||||
#include <WiFiClient.h>
|
#include <WiFiClient.h>
|
||||||
#include <PubSubClient.h>
|
#include <PubSubClient.h>
|
||||||
#include <RCSwitch.h>
|
#include <RCSwitch.h>
|
||||||
|
#include <BH1750.h>
|
||||||
|
#include <Wire.h>
|
||||||
#include "secrets.h"
|
#include "secrets.h"
|
||||||
|
|
||||||
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
#define MQTT_VERSION MQTT_VERSION_3_1_1
|
||||||
|
|
||||||
|
// General MQTT settings
|
||||||
|
const PROGMEM char* MQTT_CLIENT_ID = "multi-esp";
|
||||||
|
const PROGMEM char* MQTT_SERVER_IP = "10.42.0.3";
|
||||||
|
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
|
||||||
|
// TODO: check if needed?
|
||||||
|
//const PROGMEM char* MQTT_USER = "[Redacted]";
|
||||||
|
//const PROGMEM char* MQTT_PASSWORD = "[Redacted]";
|
||||||
|
|
||||||
|
|
||||||
|
// RFSOCKET subsystem mqtt topic components
|
||||||
|
const char* MQTT_RFSOCKET_SUBSYSTEM = "rfsockets/";
|
||||||
|
const char* MQTT_RFSOCKET_STATE_TOPIC = "/status";
|
||||||
|
const char* MQTT_RFSOCKET_COMMAND_TOPIC = "/switch";
|
||||||
|
|
||||||
|
// payloads by default (on/off)
|
||||||
|
const char* LIGHT_ON = "ON";
|
||||||
|
const char* LIGHT_OFF = "OFF";
|
||||||
|
|
||||||
|
|
||||||
|
// BH1750 subsystem mqtt topic components
|
||||||
|
// TODO: implement support for multiple sensors.
|
||||||
|
// (BH1750 can talk on two different i²c addr)
|
||||||
|
const char* MQTT_BH1750_SUBSYSTEM = "lightsensor/";
|
||||||
|
const char* MQTT_BH1750_LOCATION = "livingroom_window";
|
||||||
|
const char* MQTT_BH1750_STATE_TOPIC = "/status";
|
||||||
|
|
||||||
|
unsigned long last_bh1750_publish = millis();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WiFiClient wifiClient;
|
||||||
|
PubSubClient client(wifiClient);
|
||||||
|
|
||||||
RCSwitch mySwitch = RCSwitch();
|
RCSwitch mySwitch = RCSwitch();
|
||||||
|
BH1750 lightMeter;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
char* channel;
|
char* channel; // First DIP set
|
||||||
char* id;
|
char* id; // Second DIP set
|
||||||
char name[255];
|
char name[255]; // human readable name (included in mqtt topic)
|
||||||
bool powered;
|
bool powered; // last known power state of socket
|
||||||
uint8_t type; // 0=DIP, 1=Learned
|
uint8_t type; // 0=DIP, 1=Learned
|
||||||
int on_code;
|
int on_code; // ON code for self learning sockets (according to trained remote)
|
||||||
int off_code;
|
int off_code; // Same as above but for OFF
|
||||||
} PowerSocket;
|
} PowerSocket;
|
||||||
|
|
||||||
// see struct for description of fields
|
// see struct for description of fields
|
||||||
|
@ -32,43 +69,47 @@ PowerSocket sockets[] = {
|
||||||
|
|
||||||
int numofsockets = sizeof(sockets)/sizeof(sockets[0]);
|
int numofsockets = sizeof(sockets)/sizeof(sockets[0]);
|
||||||
|
|
||||||
// MQTT: ID, server IP, port, username and password
|
|
||||||
const PROGMEM char* MQTT_CLIENT_ID = "multi-esp";
|
// function called to measure and publish the state of the BH1750
|
||||||
const PROGMEM char* MQTT_SERVER_IP = "10.42.0.3";
|
void publishBH1750State() {
|
||||||
const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
|
uint16_t lux = lightMeter.readLightLevel();
|
||||||
// TODO: check if needed?
|
char lux_string[10];
|
||||||
//const PROGMEM char* MQTT_USER = "[Redacted]";
|
itoa(lux, lux_string, 10);
|
||||||
//const PROGMEM char* MQTT_PASSWORD = "[Redacted]";
|
char topic[
|
||||||
|
strlen(MQTT_BH1750_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_BH1750_LOCATION) +
|
||||||
|
strlen(MQTT_BH1750_STATE_TOPIC)
|
||||||
|
];
|
||||||
|
strcpy(topic, MQTT_BH1750_SUBSYSTEM);
|
||||||
|
strcat(topic, MQTT_BH1750_LOCATION);
|
||||||
|
strcat(topic, MQTT_BH1750_STATE_TOPIC);
|
||||||
|
|
||||||
|
client.publish(topic, lux_string, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const char* MQTT_RFSOCKET_SUBSYSTEM = "rfsockets/";
|
|
||||||
const char* MQTT_RFSOCKET_STATE_TOPIC = "/status";
|
|
||||||
const char* MQTT_RFSOCKET_COMMAND_TOPIC = "/switch";
|
|
||||||
|
|
||||||
// payloads by default (on/off)
|
// function called to publish the state of the rfsockets (on/off)
|
||||||
const char* LIGHT_ON = "ON";
|
void publishSocketState(int socketIdx) {
|
||||||
const char* LIGHT_OFF = "OFF";
|
|
||||||
|
|
||||||
WiFiClient wifiClient;
|
|
||||||
PubSubClient client(wifiClient);
|
|
||||||
|
|
||||||
// function called to publish the state of the light (on/off)
|
|
||||||
void publishLightState(int socketIdx) {
|
|
||||||
char *socket_name = sockets[socketIdx].name;
|
char *socket_name = sockets[socketIdx].name;
|
||||||
char topic[strlen(MQTT_RFSOCKET_SUBSYSTEM) + strlen(MQTT_RFSOCKET_STATE_TOPIC) + strlen(socket_name)];
|
char topic[
|
||||||
|
strlen(MQTT_RFSOCKET_SUBSYSTEM) +
|
||||||
|
strlen(MQTT_RFSOCKET_STATE_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_STATE_TOPIC);
|
strcat(topic, MQTT_RFSOCKET_STATE_TOPIC);
|
||||||
|
|
||||||
if (sockets[socketIdx].powered) {
|
if (sockets[socketIdx].powered) {
|
||||||
client.publish(topic, LIGHT_ON, true);
|
client.publish(topic, LIGHT_ON, true);
|
||||||
} else {
|
} else {
|
||||||
client.publish(topic, LIGHT_OFF, true);
|
client.publish(topic, LIGHT_OFF, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// function called to turn on/off the light
|
// function called to turn on/off the rfsockets
|
||||||
void setLightState(byte socketIdx) {
|
void setSocketState(byte socketIdx) {
|
||||||
if (sockets[socketIdx].powered) {
|
if (sockets[socketIdx].powered) {
|
||||||
setSocket(socketIdx, true);
|
setSocket(socketIdx, true);
|
||||||
Serial.println("INFO: Turn light on...");
|
Serial.println("INFO: Turn light on...");
|
||||||
|
@ -78,6 +119,7 @@ void setLightState(byte socketIdx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 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 = "/";
|
||||||
topic_ptr = strtok(NULL, delimiter);
|
topic_ptr = strtok(NULL, delimiter);
|
||||||
|
@ -92,14 +134,14 @@ void subsystem_rfsockets(char *topic_ptr, String payload) {
|
||||||
if (payload.equals(String(LIGHT_ON))) {
|
if (payload.equals(String(LIGHT_ON))) {
|
||||||
if (sockets[socketIdx].powered != true) {
|
if (sockets[socketIdx].powered != true) {
|
||||||
sockets[socketIdx].powered = true;
|
sockets[socketIdx].powered = true;
|
||||||
setLightState(socketIdx);
|
setSocketState(socketIdx);
|
||||||
publishLightState(socketIdx);
|
publishSocketState(socketIdx);
|
||||||
}
|
}
|
||||||
} else if (payload.equals(String(LIGHT_OFF))) {
|
} else if (payload.equals(String(LIGHT_OFF))) {
|
||||||
if (sockets[socketIdx].powered != false) {
|
if (sockets[socketIdx].powered != false) {
|
||||||
sockets[socketIdx].powered = false;
|
sockets[socketIdx].powered = false;
|
||||||
setLightState(socketIdx);
|
setSocketState(socketIdx);
|
||||||
publishLightState(socketIdx);
|
publishSocketState(socketIdx);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.print("Unknown payload received: ");
|
Serial.print("Unknown payload received: ");
|
||||||
|
@ -145,15 +187,16 @@ void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handles initial connection and reconnect in case of failures
|
||||||
void reconnect() {
|
void reconnect() {
|
||||||
// Loop until we're reconnected
|
// Loop until we're reconnected
|
||||||
while (!client.connected()) {
|
while (!client.connected()) {
|
||||||
Serial.println("INFO: Attempting MQTT connection...");
|
Serial.println("INFO: Attempting MQTT connection...");
|
||||||
// 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");
|
||||||
for (int i = 0; i < numofsockets; i++) {
|
for (int i = 0; i < numofsockets; i++) {
|
||||||
publishLightState(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;
|
||||||
|
@ -167,14 +210,14 @@ void reconnect() {
|
||||||
Serial.println("\"");
|
Serial.println("\"");
|
||||||
client.subscribe(topic);
|
client.subscribe(topic);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Serial.print("ERROR: failed, rc=");
|
Serial.print("ERROR: failed, rc=");
|
||||||
Serial.print(client.state());
|
Serial.print(client.state());
|
||||||
Serial.println("DEBUG: try again in 5 seconds");
|
Serial.println("DEBUG: try again in 5 seconds");
|
||||||
// Wait 5 seconds before retrying
|
// Wait 5 seconds before retrying
|
||||||
delay(5000);
|
delay(5000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setSocket(int socketIdx, bool newStatus) {
|
bool setSocket(int socketIdx, bool newStatus) {
|
||||||
|
@ -261,14 +304,24 @@ void setup() {
|
||||||
Serial.print("IP address: ");
|
Serial.print("IP address: ");
|
||||||
Serial.println(WiFi.localIP());
|
Serial.println(WiFi.localIP());
|
||||||
|
|
||||||
|
// setup bh1750 sensor
|
||||||
|
Wire.begin();
|
||||||
|
lightMeter.begin();
|
||||||
|
|
||||||
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
if (!client.connected()) {
|
if (!client.connected()) {
|
||||||
reconnect();
|
reconnect();
|
||||||
}
|
}
|
||||||
client.loop();
|
client.loop();
|
||||||
|
|
||||||
|
if(abs(millis() - last_bh1750_publish) >= 5000){
|
||||||
|
Serial.println("Publishing BH1750 state");
|
||||||
|
publishBH1750State();
|
||||||
|
last_bh1750_publish = millis();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue