這是畢業設計做的一個小項目,實現了一個利用QQ機器人控制arduino開關燈的物聯網應用,論文設計中考慮了多種情況,用到了很多東西,還實現了一個DSL文法解析引擎,用來做語義判斷,這裡我們不介紹這麼多,只做一個最簡單的實現。
所需物料:
- Arduino開發板
- W5100網路通訊模組
- 網線等基礎條件物料
- 一個LED發光二極體或者繼電器模組
通訊及控制流程程
控制流程程圖
簡單解釋:
User發送Control Command到Web Server,W5100輪詢Web Server,得到的結果返回給Arduino,程式根據結果執行開關LED/繼電器等操作。
注意要點
Web Server可以沒有公網IP,但是要保證能讓W5100和QQ Robot Framework訪問到。
整體設計
一些廢話
web server本來是用php/python實現的,但是要交付給使用者(老師)還需要使用者安裝python或php,考慮使用pyinstaller打包,但是效果不是很好,所以改成使用golang,直接給一個二進位打包檔案即可,其實golang也不是最優方案,因為這個web server需要的功能非常簡單,用c/cpp寫一個也行,甚至還考慮了powershell。
Web Server功能及設計
根據傳入的token驗證請求,然後改變一個全域變數,以便Arduino根據該變數做相應控制動作。
/*1. 程式運行後會在0.0.0.0開啟80連接埠,請運行前確保80連接埠未被佔用且在防火牆白名單2. 原始電平為03. GET http://{host}/console.txt得到指令狀態4. GET http://{host}/change?level={0,1}&token=arduino_project_demo修改狀態*/package mainimport ( "fmt" "net/http" "time")var level = "0"var token = "arduino_project_demo"func console(w http.ResponseWriter, r *http.Request) { fmt.Printf(time.Now().Format("2006-01-02 15:04:05")) fmt.Println(" ", r.RemoteAddr, " ", r.Method, r.RequestURI, "200", r.Proto) fmt.Fprintf(w, level)}func change(w http.ResponseWriter, r *http.Request) { fmt.Printf(time.Now().Format("2006-01-02 15:04:05")) fmt.Println(" ", r.RemoteAddr, " ", r.Method, r.RequestURI, "200", r.Proto) r.ParseForm() get_token := r.Form.Get("token") if get_token != token { fmt.Fprintf(w, "token error!") } else { get_level := r.Form.Get("level") if get_level == "0" || get_level == "1" { level = get_level fmt.Fprintf(w, "success!") } else { fmt.Fprintf(w, "level error!") } }}func index(w http.ResponseWriter, r *http.Request) { if r.URL.Path != "/" { w.WriteHeader(404) w.Write([]byte("404")) fmt.Printf(time.Now().Format("2006-01-02 15:04:05")) fmt.Println(" ", r.RemoteAddr, " ", r.Method, r.RequestURI, "404", " ", r.Proto) } else { w.Write([]byte("index")) fmt.Printf(time.Now().Format("2006-01-02 15:04:05")) fmt.Println(" ", r.RemoteAddr, " ", r.Method, r.RequestURI, "200", r.Proto) }}func main() { fmt.Println("ListenAndServe: 80") http.HandleFunc("/", index) http.HandleFunc("/console.txt", console) //設定訪問的路由 http.HandleFunc("/change", change) //設定訪問的路由 http.ListenAndServe(":80", nil) //設定監聽的連接埠}
QQ Robot
使用酷Q機器人架構,用易語言(真難用,一堆槽點~)做外掛程式開發,功能就是根據User的指令發送相對應的HTTP 要求,也是很簡單的程式,由於該語言原始碼是二進位檔案,無法貼出相應代碼。
Arduino代碼
簡單來說就是定時訪問web server然後根據返回結果做出對應的高低電平控制。
#include <SPI.h>#include <Ethernet.h>byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; // 不要和區域網路中的其它裝置MAC地址衝突,一般不需要修改char server[] = "x.x.x.x"; //改成伺服器的IPIPAddress ip(192, 168, 0, 101); //Arduino的IP地址,不要和區域網路中的其它裝置IP地址衝突EthernetClient client;void setup() { pinMode(6, OUTPUT); //Arduino的引腳,另一端接GND,不要接反 Serial.begin(9600); while (!Serial) { ; } if (Ethernet.begin(mac) == 0) { Serial.println("使用DHCP配置網路失敗!"); Ethernet.begin(mac, ip); } delay(1000); Serial.println("串連中...");}void loop() { if (client.connect(server, 80)) { client.println("GET /console.txt HTTP/1.1"); client.println("Connection: close"); client.println(); Serial.println("get over"); } else { Serial.println("connect failed"); } delay(1000); //必須有的延時時間,否則串連失敗 String console; while (client.available()) { char c = client.read(); console = console + c; } Serial.println("console的值是:"); Serial.print(console); if (console.endsWith("0")) { digitalWrite(6, LOW); //和前面的一致 } else { digitalWrite(6, HIGH); //和前面的一致 } if (!client.connected()) { Serial.println("connect stop"); client.stop(); } delay(100); //延時時間,可以微調,讓響應更快,或者更慢.}
展示
圖片都在手機上,有時間貼出來。
結論
現在一些arduino物聯網設計應用動不動就要用一些第三方平台,流程比較繁雜,其實很簡單的幾段代碼就能做出一個控制應用,同理,我們也可以把QQ換成、簡訊、Telegram,做出更複雜的東西,例如:澆花,開關門鎖等等。