天天看點

esp8266單片機透傳_ESP8266通過MQTT接入Home Assistant

1.簡介

ESP8266是一款序列槽WiFi子產品,内部內建MCU能實作單片機之間序列槽通信, 這款子產品簡單易學,體積小,便于嵌入式開發。

本文介紹的是ESP8266系列中的ESP-01,這款晶片使用了3.3V的直流電源,體積小,功耗低,支援透傳,價格低,下圖是ESP8266的ESP-01系列,相應的還有ESP-02,03等等,它們使用的核心晶片都是相同的。

esp8266單片機透傳_ESP8266通過MQTT接入Home Assistant

ESP-01子產品

ESP8266官方提供的rom主要有兩個,一個是支援at指令修改參數的at系列rom,使用此rom時,可以使用at指令來設定晶片的大部分參數,同時也可将晶片設定為透傳模式,這樣ESP8266就相當于在網際網路和UART之間架起了一座橋梁。

另一個就是物聯網的rom了,此rom可以通過指令來控制ESP的部分GPIO,而且ESP8266也可以采集一些溫濕度傳感器的資料,然後發送到網際網路上。

2.方案

esp8266單片機透傳_ESP8266通過MQTT接入Home Assistant

ESP-01做為MQTT的用戶端,連接配接到MQTT Server, Home Assistant通過mqtt元件和MQTT Server通信,實作控制ESP-01的功能

3.硬體和開發環境

需要的硬體為:ESP-01子產品,繼電器子產品,運作Home Assistant的樹莓派一塊

esp8266單片機透傳_ESP8266通過MQTT接入Home Assistant

ESP-01和繼電器子產品

軟體:Arduino通過支援ESP8266的元件進行開發

4.代碼

4.1定義基本變量

#define SWITCH_ON     0  
           

定義了3個MQTT Topic:

TOPIC_CONFIG: 發送配置資訊用

TOPIC_COMMAND: 接收控制指令

TOPIC_STATE: 報告狀态用

4.2初始化

void setup() {
  Serial.begin(115200);
  setup_wifi();
  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);
  pinMode(PIN_SWITCH, OUTPUT);
}
           
void setup_wifi() {
  delay(100);
  WiFi.begin(ssid, password);           // 連接配接到WiFi網絡
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
  }
  Serial.println("WiFi connected");
  // Print the IP address
  Serial.println(WiFi.localIP());
  Serial.println(WiFi.macAddress());
}
           

4.3 接收MQTT消息的回調函數

void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived ["); 
  Serial.print(topic);   
  Serial.print("] ");

  set_str = "";
  for (int i = 0; i < length; i++) {
    set_str += (char)payload[i];
  }  

  String topic_str = topic;
  Serial.println(set_str);

  if (topic_str.equals(TOPIC_COMMAND)) {
    set_switch(set_str);
  }
}
           

4.4 Wifi和MQTT重新連接配接

void reconnect( ) {
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi is not connected, retry setup");
    setup_wifi();
  }
    
  while (!client.connected()) {
    Serial.println("MQTT connecting...");
    if (client.connect(client_id, mqtt_user, mqtt_password)) {              
      Serial.println("MQTT connect success.");  
      mqtt_config();
      client.subscribe(TOPIC_COMMAND);       
    } else {
      delay(5000);  
    }
  }
}
           

4.5 主循環

void loop() {

  if (!client.connected()) {
    reconnect();
  }
  client.loop();
    
  long now = millis();
  if (now - last_msg > 5000) {
    last_msg = now;
    pub_mqtt_state();
  }
  
  delay(100);  
}
           

4.6 設定開關狀态

char* get_state(){
  if (switch_value == SWITCH_ON) {
    return "ON";
  } else {
    return "OFF";
  }
}

boolean set_switch(String set_str) {
  client.publish(TOPIC_STATE, set_str.c_str()); 
  Serial.print("Recv command:");
  Serial.println(set_str.c_str());

  if (set_str.equals("ON")) {
    switch_value = SWITCH_ON;
  } else if (set_str.equals("OFF")){
    switch_value = SWITCH_OFF;
  } else {
    return false; 
  }

  digitalWrite(PIN_SWITCH, switch_value);
  pub_mqtt_state();
  return true;
}
           

4.7 釋出MQTT狀态和配置消息

void pub_mqtt_state() {
  if(switch_value == SWITCH_ON){
    client.publish(TOPIC_STATE, "ON");    
  } else {
    client.publish(TOPIC_STATE, "OFF");   
  }  
}

void mqtt_config() {
  String head = "{";
  String name_str = ""name": "" + String(device_name) + "", ";
  String cmd_topic = ""command_topic": "" + String(TOPIC_COMMAND) + "", ";
  String state_topic = ""state_topic": "" + String(TOPIC_STATE) + """;
  String end_str = "}";
  String config = "{" + name_str + ", " + state_topic + ", " + cmd_topic + "}";
  Serial.println(config.c_str());
  
  int msgLen = head.length() + name_str.length() + cmd_topic.length() + state_topic.length() + end_str.length();
  //發送長文本需要另外處理
  client.beginPublish(TOPIC_CONFIG, msgLen, false);
  client.print(head);
  client.print(name_str);
  client.print(cmd_topic);
  client.print(state_topic);
  client.print(end_str);
  client.endPublish();
}

           

注意:釋出長消息時,要做專門處理,通過client.beginPublish,client.endPublish();

5. Home Assistant配置

5.1 安裝MQTT Server

在運作Home Assistant的樹莓派上安裝MQTT Server, 選擇的版本是mosquitto

5.2 樹莓派配置

在Home Assistant的Web上,”配置”->"內建", 添加MQTT;

在configuration.yaml中配置:

switch: !include switchs.yaml
           

在switchs.yaml中定義mqtt開關:

- platform: mqtt
  name: "ESP-01 switch1"
  state_topic: "ESP-01/switch/state"
  command_topic: "ESP-01/switch/set"
  payload_on: "ON"
  payload_off: "OFF"
  state_on: "ON"
  state_off: "OFF"
  optimistic: false
  qos: 0
  retain: true
           

這樣,在Home Assistant的界面中就可以控制繼電器開啟和關閉了:

esp8266單片機透傳_ESP8266通過MQTT接入Home Assistant

6. 總結

可以把小米網關也接入到Home Assistant,這樣,通過小米的無線開關就可以直接控制ESP-01上的繼電器了。

感興趣的可以繼續通路

愛上制作-K12DIY​www.k12diy.com