我根据其他人的出色工作拼凑了一个草图,让我可以监控传感器和控制继电器以及我家周围各种节点上的 IR 发射器,这些节点通过 MQTT 连接到 HomeAssistant (home-assistant.io)。
一切正常……有一段时间了。但是没有明显的原因,执行器的回调停止工作。我仍然从传感器获得“心跳”(调试尝试的一部分)和读数,但我无法再控制继电器或 IR Blaster。没有错误消息(如您所见,我尝试在所有地方插入消息进行调试)。
仅供参考,调试仍然失败并且串行连接已关闭。
完整代码如下。提前致谢。对不起,如果我可怕的代码冒犯了你的眼睛。
代码:
全选// U
tilises:
// - PubSubClient by Nick ‘O Leary
// - DHT sensor library by Adafruit
// Name this node - sets mqtt addresses
#define NODE_NAME "livingroom"
// Activate components - comment out to deactivate
//#define PIR_ACTIVE
//#define DHT_ACTIVE
//#define RELAY_ACTIVE
#define IRBLASTER_ACTIVE
#define HEARTBEAT
//#define SWITCH
// Debug mode ?
#define DEBUG
// Core library definitions and settings
#include
#include
#define wifi_ssid "xxxxxxxxxx"
#define wifi_password "xxxxxxxxxx"
#define mqtt_server "192.168.xx.xx"
#define mqtt_user "xxxxxxxxxx"
#define mqtt_password "xxxxxxxxxx"
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
float diff = 1.0;
// Temp and humidity sensor
#ifdef DHT_ACTIVE
#include
#define humidity_topic NODE_NAME "/sensor/humidity"
#define temperature_topic NODE_NAME "/sensor/temperature"
#define DHTTYPE DHT22
#define DHTPIN 14 // D5
float temp = 0.0;
float hum = 0.0;
DHT dht(DHTPIN, DHTTYPE, 11); // 11 works fine for ESP8266
#endif
// PIR
#ifdef PIR_ACTIVE
#define pir_topic "livingroom/sensor/pir"
#define PIRPIN D6
#define LEDPIN 13
int pirState = LOW; // we start, assuming no motion detected
int pir = 0; // variable for reading the pin status
#endif
// IR Blaster
#ifdef IRBLASTER_ACTIVE
#include
#include
#define ir_message NODE_NAME "/control/irb"
#define ir_state NODE_NAME "/control/irb/state"
int khz = 38; // 38kHz carrier frequency for both NEC and Samsung
IRsend irsend(2); //an IR led is connected to GPI0 2 (pin D4 on NodeMCU)
#endif
// 4-way Relay
#ifdef RELAY_ACTIVE
#define relay_zero NODE_NAME "/control/relay/0"
#define zero_state NODE_NAME "/control/relay/0/state"
#define relay_one NODE_NAME "/control/relay/1"
#define one_state NODE_NAME "/control/relay/1/state"
#define relay_two NODE_NAME "/control/relay/2"
#define two_state NODE_NAME "/control/relay/2/state"
#define relay_three NODE_NAME "/control/relay/3"
#define three_state NODE_NAME "/control/relay/3/state"
int r_zero_state = 0;
int r_one_state = 0;
int r_two_state = 0;
int r_three_state = 0;
int r_zero_test = 0;
int r_one_test = 0;
int r_two_test = 0;
int r_three_test = 0;
#endif
// Heartbeat
#ifdef HEARTBEAT
#define heartbeat NODE_NAME "/heartbeat"
#endif
// Switch
#ifdef SWITCH
#define switchchan NODE_NAME "/sensor/switch"
int switchstate = 0;
int switchread = 0;
#endif
void setup() {
Serial.begin(115200);
#ifdef DHT_ACTIVE
dht.begin(); // start the temp and humidity sensor
#endif
#ifdef IRBLASTER_ACTIVE
irsend.begin(); // start the irblaster
#endif
#ifdef PIR_ACTIVE
pinMode(PIRPIN, INPUT); // set the PIR Pin as an inout
#endif
// prepare GPIO for relay
#ifdef RELAY_ACTIVE
pinMode(D0, OUTPUT); // GPIO 16
pinMode(D1, OUTPUT); // GPIO 5
pinMode(D2, OUTPUT); // GPIO 4
pinMode(D3, OUTPUT); // GPIO 0
digitalWrite(D0, 1);
digitalWrite(D1, 1);
digitalWrite(D2, 1);
digitalWrite(D3, 1);
#endif
// Switch
#ifdef SWITCH
pinMode(D7, INPUT);
#endif
// get the core stuff started
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
#ifdef RELAY_ACTIVE
// Share current relay status
client.publish(zero_state, "1", true);
client.publish(one_state, "1", true);
client.publish(two_state, "1", true);
client.publish(three_state, "1", true);
#endif
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
#ifdef DEBUG
Serial.println();
Serial.print("Connecting to ");
Serial.println(wifi_ssid);
#endif
WiFi.mode(WIFI_STA);
WiFi.begin(wifi_ssid, wifi_password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
#ifdef DEBUG
Serial.print(".");
#endif
}
#ifdef DEBUG
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
#endif
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
#ifdef DEBUG
Serial.print("Attempting MQTT connection...");
#endif
// Attempt to connect
if (client.connect("ESP8266Client", mqtt_user, mqtt_password)) {
#ifdef RELAY_ACTIVE
client.subscribe(relay_zero);
client.subscribe(relay_one);
client.subscribe(relay_two);
client.subscribe(relay_three);
#endif
#ifdef IRBLASTER_ACTIVE
client.subscribe(ir_message);
#endif
} else {
#ifdef DEBUG
Serial.println("");
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
#endif
delay(5000);
}
}
}
#ifdef DHT_ACTIVE
bool checkBound(float newValue, float prevValue, float maxDiff) {
return !isnan(newValue) &&
(newValue < prevValue - maxDiff || newValue > prevValue + maxDiff);
}
#endif
#ifdef IRBLASTER_ACTIVE
void blastir(byte* payload) {
String statmessage = "unset";
int val = payload[0];
int instr = payload[0] - '0';
switch (instr) {
case 0:
irsend.sendNEC(0xFF02FD,32);
#ifdef DEBUG
statmessage = "Lights On/Off Command sent";
#endif
delay(1);
break;
case 1:
irsend.sendNEC(0xFF1AE5,32);
#ifdef DEBUG
statmessage = "Red light command sent";
#endif
delay(1);
break;
case 2:
irsend.sendNEC(0xFF9A65,32);
#ifdef DEBUG
statmessage = "Green lights command sent";
#endif
delay(1);
break;
case 3:
irsend.sendNEC(0xFF22DD,32);
#ifdef DEBUG
statmessage = "White lights command sent";
#endif
delay(1);
break;
case 4:
irsend.sendNEC(0xFF30CF,32);
#ifdef DEBUG
statmessage = "DIY 1 command sent";
#endif
delay(1);
break;
default:
#ifdef DEBUG
statmessage = "Could not match string";
#endif
break;
}
#ifdef DEBUG
client.publish(ir_state, String(statmessage).c_str(), true);
Serial.println(statmessage);
#endif
delay(10);
}
#endif
#ifdef RELAY_ACTIVE
void relayswitch(byte* payload, String topicstring) {
#ifdef DEBUG
Serial.println("Relayswitch function called");
#endif
int val = int(payload[0]);
char port;
int portloc = topicstring.length() - 1;
#ifdef DEBUG
Serial.print("Port location: ");
Serial.println(portloc);
#endif
port = topicstring.charAt(portloc);
int iport = port - '0';
int ival = val - '0';
#ifdef DEBUG
Serial.print("Port: ");
Serial.println(port);
Serial.print("iPort: ");
Serial.println(iport);
#endif
switch(iport) {
case 0:
digitalWrite(D0, ival);
r_zero_state = ival;
#ifdef DEBUG
Serial.print("Switching Relay One to:");
Serial.println(ival);
#endif
client.publish(zero_state, String(ival).c_str(), true);
delay(1);
break;
case 1:
digitalWrite(D1, ival);
r_one_state = ival;
#ifdef DEBUG
Serial.print("Switching Relay Two to:");
Serial.println(ival);
#endif
client.publish(one_state, String(ival).c_str(), true);
delay(1);
break;
case 2 :
digitalWrite(D2, ival);
r_two_state = ival;
#ifdef DEBUG
Serial.print("Switching Relay Three to:");
Serial.println(ival);
#endif
client.publish(two_state, String(ival).c_str(), true);
delay(1);
break;
case 3 :
digitalWrite(D3, ival);
r_three_state = ival;
#ifdef DEBUG
Serial.print("Switching Relay Four to:");
Serial.println(ival);
#endif
client.publish(three_state, String(ival).c_str(), true);
delay(1);
break;
default:
Serial.println("Could not match string");
break;
}
}
#endif
void callback(char* topic, byte* payload, unsigned int length) {
#ifdef DEBUG
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i = 0; i < length; i++) {
Serial.print((char)payload
);
}
Serial.println();
#endif
String topicstring(topic);
int stripstart = String(NODE_NAME).length()+1;
int stripstop = String(NODE_NAME).length()+4;
#ifdef DEBUG
Serial.println(topicstring.substring(stripstart,stripstop));
#endif
if(topicstring.substring(stripstart,stripstop) == "con") {
int funcstart = String(NODE_NAME).length()+9;
int funcstop = String(NODE_NAME).length()+12;
String func = topicstring.substring(funcstart,funcstop);
#ifdef DEBUG
Serial.print("Func = ");
Serial.println(func);
#endif
if(func == "rel") {
#ifdef RELAY_ACTIVE
relayswitch(payload, topicstring);
#endif
delay(1);
}
if(func == "irb") {
#ifdef IRBLASTER_ACTIVE
blastir(payload);
#endif
delay(1);
}
}
delay(10);
}
#ifdef PIR_ACTIVE
void pir_state() {
pir = digitalRead(PIRPIN);
if (pir == HIGH) { // check if the input is HIGH
digitalWrite(LEDPIN, HIGH); // turn LED ON
if (pirState == LOW) {
// we have just turned on
#ifdef DEBUG
Serial.println("Motion detected!");
#endif
client.publish(pir_topic, "1", true);
// We only want to print on the output change, not state
pirState = HIGH;
}
} else {
digitalWrite(LEDPIN, LOW); // turn LED OFF
if (pirState == HIGH){
// we have just turned off
#ifdef DEBUG
Serial.println("Motion ended!");
#endif
client.publish(pir_topic, "0", true);
// We only want to print on the output change, not state
pirState = LOW;
}
}
delay(10);
}
#endif
#ifdef DHT_ACTIVE
void dhtread() {
float newTemp = dht.readTemperature();
float newHum = dht.readHumidity();
if (checkBound(newTemp, temp, diff)) {
temp = newTemp;
#ifdef DEBUG
Serial.print("New temperature:");
Serial.println(String(temp).c_str());
#endif
client.publish(temperature_topic, String(temp).c_str(), false);
}
if (checkBound(newHum, hum, diff)) {
hum = newHum;
#ifdef DEBUG
Serial.print("New humidity:");
Serial.println(String(hum).c_str());
#endif
client.publish(humidity_topic, String(hum).c_str(), false);
}
delay(10);
}
#endif
#ifdef SWITCH
void switchfunc(){
switchread = digitalRead(D7);
if(switchread != switchstate) {
client.publish(switchchan, String(switchstate).c_str(), true);
#ifdef DEBUG
Serial.print("Switch flipped to ");
Serial.println(switchstate);
#endif
switchstate = switchread;
delay(10);
}
}
#endif
void loop() {
if (!client.connected()) {
reconnect();
}
delay(1000);
client.loop();
// Serial.println("In loop");
long now = millis();
if (now - lastMsg > 10000) {
lastMsg = now;
#ifdef HEARTBEAT
client.publish(heartbeat, "1", false);
#endif
#ifdef DEBUG
Serial.println("Reading...");
#endif
#ifdef PIR_ACTIVE
pir_state();
#endif
#ifdef DHT_ACTIVE
dhtread();
#endif
#ifdef SWITCH
switchfunc();
#endif
}
}