前幾天做一個智能家居APP,硬件段使用的是ESP8266WIFI模塊,其實不管是WIFI模塊還是藍牙,通信都是同樣一個道理,獲取IP和端口來進行通信。
我是通過XCOM v2.0 發送信息,移動端接收信息后也可以發信息過去,界面如下(比較簡單自己寫就行)
這是個簡單的通信實現,當然也可以通過廣播UDP來獲取IP地址,這樣IP地址不用固定輸入,github的上的ESP8266-Sample注冊WiFi后也可以獲取到IP地址。
外網連接可以參照http://123.57.52.126/ ,與服務器123.57.52.126,端口3200,建立TCP連接,之后通過以下命令分別進行注冊、登陸(下圖)
大概步驟如下,感興趣可以自己研究:
APP端用戶名固定為“CKJ”和MAC地址中的第一個和最后兩個字符的組合
例如MAC地址為5c:cf:7f:88:ea:ca時,用戶名為CKJ5ceaca,這樣做是為了盡可能避免賬號沖突。
登陸完成后可通過{“re”:1}命令測試網關是否在線,如果網關在線,將會應答{“re”:1,“us”:”CKJ5ceaca”}。
外網通信時每一個發送出去的json前都必須加上d%username%,json里必須包含自己的賬號。其中user為網關用戶名內容,例如d%username{“re”:1,“us”:”CKJxxxxxx”}
對端收到的數據不包含前面的d%username%,只有json數據,可以直接解析。
其它的json數據和局域網下相同,與網關通信時必須建立TCP連接,UDP廣播只用於尋找網關。
遇到了一個小問題(不用通過XCOM v2.0發送json字符串的跳過)
與硬件通信肯定免不了解析Json,使用Gson解析簡單方便,在解析過程中遇到了一個坑爹的問題,解析出錯了(;′⌒`),我在電腦輸入下面字符串{\"name\":\"John\", \"age\":20,\"grade\":{\"course\":\"English\",\"score\":100,\"level\":\"A\"}}
\"是代表 "這個符號,所以我就從XCOM v2.0發送上面字符串過來,解析失敗。。。后來debug發現發送過來的信息是直接當字符串處理,不會再轉義,也就\"是代表\",
所以只需發送下面格式信息即可解析
接下來是是代碼,代碼比較容易,連接局域網(WIFI或者熱點都行) 這里的代碼是基於知道硬件ip和port上的,當然你也可以通過UDP廣播去獲取ip和port。
Socket連接也屬於網絡連接,必須放在子線程中。 注意在清單文件配置網絡和WIFI權限
new Thread(){ @Override public void run() { super.run(); byte[] msgBuffer = null; String text = "---------Hello World---------- "; try { msgBuffer = text.getBytes("GB2312"); clientSocket = new Socket("192.168.191.2", 3001); outStrean = clientSocket.getOutputStream(); outStrean.write(msgBuffer); } catch (IOException e) { e.printStackTrace(); } } }.start();
接收信息代碼(接收硬件端發過來的信息):
public class ReceiveThread extends Thread { private InputStream inStrean = null; private byte[] buf; private String str = null; public ReceiveThread(Socket s) { try { this.inStrean = s.getInputStream(); } catch (IOException e) { e.printStackTrace(); } } //將輸入流轉化為字符串 @Override public void run() { super.run(); while (!stop) { this.buf = new byte[1024]; try { this.inStrean.read(this.buf); } catch (IOException e) { e.printStackTrace(); } try { this.str = new String(this.buf, "GB2312").trim(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } Message msg = new Message();
//將獲取到的字符串str通過sendMessage發送出去 msg.obj = str; mHandle.sendMessage(msg); } } }
接收sendMessage發過來的數據並解析
private Handler mHandle = new Handler() { @Override public void handleMessage(Message msg) { String jsonString = msg.obj.toString(); System.out.println("顯示接收到的json字符串"+ jsonString); //若接收的不是json格式字符,不需要解析,不然奔潰掉 if(jsonString != "") { Json(jsonString); } } };