乐鑫技术交流
直播中

陈超

7年用户 874经验值
私信 关注
[问答]

HomeAssistant的MQTT草图回调失败的原因?怎么解决?

我根据其他人的出色工作拼凑了一个草图,让我可以监控传感器和控制继电器以及我家周围各种节点上的 IR 发射器,这些节点通过 MQTT 连接到 HomeAssistant (home-assistant.io)。
一切正常……有一段时间了。但是没有明显的原因,执行器的回调停止工作。我仍然从传感器获得“心跳”(调试尝试的一部分)和读数,但我无法再控制继电器或 IR Blaster。没有错误消息(如您​​所见,我尝试在所有地方插入消息进行调试)。
仅供参考,调试仍然失败并且串行连接已关闭。
完整代码如下。提前致谢。对不起,如果我可怕的代码冒犯了你的眼睛。
代码:全选// Utilises:
// - 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
  }
}



               


                        

更多回帖

×
20
完善资料,
赚取积分