Intigrate rfsockets subsystem support

This enables the nodemcu to listen for multiple topics. First comes
the subsystem which is then followed by parameters for that specific
subsystem.

For 433MHz sockets this subsystem is called "rfsockets". It operates
on "rfsockets/<socket_name>/(status|switch)" wher it accepts and
reports with either "ON" or "OFF" as payloads. The subsystem therefore
complies with the Home Assistant mqtt component.
This commit is contained in:
sqozz 2018-07-13 00:02:55 +02:00
parent 1ac1ce1be1
commit 0356892526

View file

@ -11,7 +11,7 @@ RCSwitch mySwitch = RCSwitch();
typedef struct {
char* channel;
char* id;
String name;
char name[255];
bool powered;
uint8_t type; // 0=DIP, 1=Learned
int on_code;
@ -42,11 +42,11 @@ const PROGMEM uint16_t MQTT_SERVER_PORT = 1883;
// MQTT: topics
const char* MQTT_LIGHT_STATE_TOPIC = "balcony/hanging_lamp/status";
const char* MQTT_LIGHT_COMMAND_TOPIC = "balcony/hanging_lamp/switch";
//// MQTT: topics
//const char* MQTT_LIGHT_STATE_TOPIC = "balcony/hanging_lamp/status";
//const char* MQTT_LIGHT_COMMAND_TOPIC = "balcony/hanging_lamp/switch";
const char* MQTT_RFSOCKET_STATE_BASE = "rfsockets/";
const char* MQTT_RFSOCKET_SUBSYSTEM = "rfsockets/";
const char* MQTT_RFSOCKET_STATE_TOPIC = "/status";
const char* MQTT_RFSOCKET_COMMAND_TOPIC = "/switch";
@ -54,25 +54,27 @@ const char* MQTT_RFSOCKET_COMMAND_TOPIC = "/switch";
const char* LIGHT_ON = "ON";
const char* LIGHT_OFF = "OFF";
//const PROGMEM uint8_t LED_PIN = 5;
boolean m_light_state = false; // light is turned off by default
WiFiClient wifiClient;
PubSubClient client(wifiClient);
// function called to publish the state of the light (on/off)
void publishLightState() {
if (m_light_state) {
client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_ON, true);
void publishLightState(int socketIdx) {
char *socket_name = sockets[socketIdx].name;
char topic[strlen(MQTT_RFSOCKET_SUBSYSTEM) + strlen(MQTT_RFSOCKET_STATE_TOPIC) + strlen(socket_name)];
strcpy(topic, MQTT_RFSOCKET_SUBSYSTEM);
strcat(topic, socket_name);
strcat(topic, MQTT_RFSOCKET_STATE_TOPIC);
if (sockets[socketIdx].powered) {
client.publish(topic, LIGHT_ON, true);
} else {
client.publish(MQTT_LIGHT_STATE_TOPIC, LIGHT_OFF, true);
client.publish(topic, LIGHT_OFF, true);
}
}
// function called to turn on/off the light
void setLightState() {
byte socketIdx = 7;
if (m_light_state) {
void setLightState(byte socketIdx) {
if (sockets[socketIdx].powered) {
setSocket(socketIdx, true);
Serial.println("INFO: Turn light on...");
} else {
@ -90,22 +92,54 @@ void callback(char* p_topic, byte* p_payload, unsigned int p_length) {
}
// handle message topic
if (String(MQTT_LIGHT_COMMAND_TOPIC).equals(p_topic)) {
// test if the payload is equal to "ON" or "OFF"
if (payload.equals(String(LIGHT_ON))) {
if (m_light_state != true) {
m_light_state = true;
setLightState();
publishLightState();
}
} else if (payload.equals(String(LIGHT_OFF))) {
if (m_light_state != false) {
m_light_state = false;
setLightState();
publishLightState();
}
}
}
Serial.print("Got a message on topic: ");
Serial.println(p_topic);
char *topic_ptr;
const char* delimiter = "/";
topic_ptr = strtok(p_topic, delimiter);
if (topic_ptr != NULL) {
char *subsystem = topic_ptr;
Serial.print("Found subsystem: ");
Serial.println(subsystem);
topic_ptr = strtok(NULL, delimiter);
if (topic_ptr != NULL) {
char *name = topic_ptr;
Serial.print("Found socket name: ");
Serial.println(name);
int socketIdx = findSocketIndex(name);
Serial.print("Found socket index ");
Serial.println(socketIdx);
// We only listen on the command channel so no further splitting needed
if (payload.equals(String(LIGHT_ON))) {
if (sockets[socketIdx].powered != true) {
sockets[socketIdx].powered = true;
setLightState(socketIdx);
publishLightState(socketIdx);
}
} else if (payload.equals(String(LIGHT_OFF))) {
if (sockets[socketIdx].powered != false) {
sockets[socketIdx].powered = false;
setLightState(socketIdx);
publishLightState(socketIdx);
}
} else {
Serial.print("Unknown payload received: ");
Serial.println(payload);
Serial.println("Ignoring it…\n");
}
} else {
Serial.print("Got topic without delimiter (");
Serial.print(delimiter);
Serial.print("), topic was:");
Serial.println(p_topic);
}
} else {
Serial.print("Got topic without delimiter (");
Serial.print(delimiter);
Serial.print("), topic was:");
Serial.println(p_topic);
}
}
void reconnect() {
@ -115,10 +149,21 @@ void reconnect() {
// Attempt to connect
if (client.connect(MQTT_CLIENT_ID)) {
Serial.println("INFO: connected");
// Once connected, publish an announcement...
publishLightState();
// ... and resubscribe
client.subscribe(MQTT_LIGHT_COMMAND_TOPIC);
for (int i = 0; i < numofsockets; i++) {
publishLightState(i);
}
for (int i = 0; i < numofsockets; i++) {
char *socket_name = sockets[i].name;
char topic[strlen(MQTT_RFSOCKET_SUBSYSTEM) + strlen(MQTT_RFSOCKET_COMMAND_TOPIC) + strlen(socket_name)];
strcpy(topic, MQTT_RFSOCKET_SUBSYSTEM);
strcat(topic, socket_name);
strcat(topic, MQTT_RFSOCKET_COMMAND_TOPIC);
Serial.print("INFO: subscribing to topic \"");
Serial.print(topic);
Serial.println("\"");
client.subscribe(topic);
}
} else {
Serial.print("ERROR: failed, rc=");
Serial.print(client.state());
@ -171,10 +216,13 @@ bool setSocket(int socketIdx, bool newStatus) {
return success;
}
int findSocketIndex(String name) {
int findSocketIndex(char *name) {
for (int socketIdx = 0; socketIdx < numofsockets; socketIdx++) {
PowerSocket canidateSocket = sockets[socketIdx];
if (canidateSocket.name == name) {
if (strcmp(canidateSocket.name, name) == 0) {
Serial.print(canidateSocket.name);
Serial.print(" equals ");
Serial.println(name);
return socketIdx;
}
}
@ -195,7 +243,6 @@ void setup() {
Serial.println("Enable transmission while waiting on wifi");
mySwitch.enableTransmit(2);
delay(1000);
setLightState();
Serial.print("Transmission enabled, waiting for wifi now.");
// Wait for connection