#include #include #include #include /* * 這支程式為 Sonoff basic R2 韌體 * MQTT 通訊 */ const char* ssid = "Asia"; const char* password = "23323456"; const char* mqttServer = "broker.emqx.io"; // MQTT - Host const char* mqttUserName = ""; // MQTT - Username const char* mqttPwd = ""; // MQTT - Password const char* clientID = "switch-12345"; // MQTT - Client ID const char* topic_sub = "arduino/status"; // MQTT - Tpoic(控制開關) //UUID uint8_t MAC_ADDR[6]; char UUID[18]; //Sonoff int relayPin = 12; // 繼電器 int ledPin = 13; // LED int btnPin = 0; // 按鈕 //Status int temp_status = -1; // 目前狀態 int change_status = 0; // 預計改變的狀態 int lastButtonState; // 按鈕上一狀態 int currentButtonState; // 按鈕目前狀態 char json[25]; unsigned long prevMillis = 0; // 暫存經過時間(毫秒) const long interval = 3000; // 上傳資料的間隔時間(毫秒) String msgStr = ""; // 暫存MQTT訊息字串 WiFiClient espClient; PubSubClient client(espClient); void setup_wifi() { delay(10); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.println("WiFi connected"); } void mqtt_reconnect() { while (!client.connected()) { if (client.connect(clientID, mqttUserName, mqttPwd)) { Serial.println("MQTT connected"); // 訂閱控制指令(每次重新連線都要重新訂閱) // 接收廣播 client.subscribe("arduino/public/power"); // 接收個別控制 client.subscribe(("arduino/" + String(UUID) + "/power").c_str()); // 發出[上線]狀態 client.publish( "arduino/status", ("{\"UUID\": \"" + String(UUID) + "\", \"status\": \"online\"}").c_str() ); } else { Serial.print("failed, rc = "); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); delay(5000); // 等5秒之後再重試 } } } void setup() { // 初始化 USB UART Serial.begin(9600); // UUID WiFi.macAddress(MAC_ADDR); for (int i = 0; i < sizeof(MAC_ADDR); ++i) { sprintf(UUID, "%s%02X", UUID, MAC_ADDR[i]); } Serial.println("uuid = " + String(UUID)); // 初始化 輸出 pinMode(btnPin, INPUT); pinMode(relayPin, OUTPUT); pinMode(ledPin, OUTPUT); currentButtonState = digitalRead(btnPin); // 初始化 WIFI setup_wifi(); // 初始化 MQTT client.setServer(mqttServer, 1883); client.setCallback(callback); //收到訂閱訊息 } void loop() { if (!client.connected()) { mqtt_reconnect(); } client.loop(); // 按鈕事件 lastButtonState = currentButtonState; currentButtonState = digitalRead(btnPin); if(lastButtonState == HIGH && currentButtonState == LOW) { change_status = !change_status; } // 改變開關狀態 if (temp_status != change_status) { temp_status = change_status; if(change_status == 0) { digitalWrite(relayPin, HIGH); digitalWrite(ledPin, HIGH); Serial.println("switch off"); // 發出[關閉]狀態 client.publish( "arduino/status", ("{\"UUID\": \"" + String(UUID) + "\", \"type\": \"switch\", \"status\": \"off\"}").c_str() ); } else { digitalWrite(relayPin, LOW); digitalWrite(ledPin, LOW); Serial.println("switch on"); // 發出[開啟]狀態 client.publish( "arduino/status", ("{\"UUID\": \"" + String(UUID) + "\", \"type\": \"switch\", \"status\": \"on\"}").c_str() ); } } delay(30); } void callback(char* topic, byte* payload, unsigned int length) { const int BUFFER_SIZE = JSON_OBJECT_SIZE(3); StaticJsonDocument jsonDoc; DeserializationError error = deserializeJson(jsonDoc, payload); if (!error) { //控制開關 if (jsonDoc.containsKey("Setswitch")) { if(jsonDoc["Setswitch"].as() == 0 || jsonDoc["Setswitch"].as() == 1) { int power = jsonDoc["Setswitch"]; Serial.println("Setswitch:" + String(power)); change_status = power; } } } }