Android利用Socket与硬件通信之智能家居APP
前几天做一个智能家居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); } } };