Android 局域网通信并实现控制设备的灯光

xiaoxiao2021-02-28  47

由于公司业务需求,近期要实现一个在同一局域网控制其他设备的功能。(就是手机端控制板子段骁龙410c的开发板) 其实设备只要能相互通信,就能很好的实现这种功能。可是在同一局域网,如何连接其他智能设备呢?-其实用过socket的朋友都知道,通过socket就能把两个设备连接起来,并实现实时的通信。因为socket 连接必须知道对方的IP,如果IP都不知道,两个设备还是不能同行。 所以获取设备IP就是我们首先要解决的问题。

(1)其实在局域网是可以允许设备发送广播的,我们宿主设备可以往局域网内发送一段广播。 (2)当被连接的设备收到我们的广播时,被连接设备就可以回复一个广播给我们的宿主设备。 (3)利用scoket短链接控制server端灯泡的亮度 第一步向局域网内发送一个广播:

//新开一个线程 client端 class SendMessage extends Thread { @Override public void run() { // Send message; while (!Thread.currentThread().isInterrupted()) { String mes = "IP"; //把message转成byte数组 byte[] buffer = mes.getBytes(); byte[] backbuff = new byte[2048]; //因为下面的socket。recevice()会阻塞当前线程,无法不断地往局域网发送广播。所server端 未打开APP或者处于关机状态建议把发送数据包的部分代码独立出来,不然server端接收不到广播。 try { Log.e("SEND", "ONE"); //利用java提供的DatagramSocket 进行操作,因为其可以存放数据包。 socket = new DatagramSocket(); //把message加入datagramsocket里。 DatagramPacket packet = new DatagramPacket(buffer, buffer.length, boardcastIp, UdpPort); //创建接受广播的packet DatagramPacket datagramPacket = new DatagramPacket(backbuff, backbuff.length); //发送广播 socket.send(packet); //在接收广播时,会阻塞当前的线程,一直等到超时,或接收到数据。 socket.receive(datagramPacket); String res = new String(datagramPacket.getData(), 0, datagramPacket.getLength()); Log.e("SEND", "&&"+res); if (res != null) { //把接收到的地址保存起来! saveIp.add(res); Message message = handler.obtainMessage(); message.what = 1; Bundle bundle = new Bundle(); bundle.putString("res", res); message.setData(bundle); handler.sendMessage(message); //如接收到结果,则把当前线程给结束。 SendMessage.this.interrupt(); } } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally { if (socket!=null){ //最后关闭Datagramsocket socket.close(); } } } } }

服务端的实现:主要是接收 client 发出的packet,随后发出一个packet(带有自己的ip信息)

//开启一个新线程,来接收局域网发来的消息: public class acceptUDP extends Thread { public DatagramSocket socket; @Override public void run() { try { //监听本机的端口 socket = new DatagramSocket(UdpPort); Log.i("WifiController", "***"); //创建一个buffer来接受client传过来的数据 byte[] buffer = new byte[2048]; DatagramPacket packet = new DatagramPacket(buffer, buffer.length); Log.i("WifiController", "***"); while (true) { //阻塞当前线程来接受数据 Log.i("WifiController", "%***%"); //接收局域网内的所有广播 socket.receive(packet); String re = new String(packet.getData(), 0, packet.getLength()); Log.i("WifiController", "&***&" + re); //对广播内容进行筛选 if (re.equalsIgnoreCase("IP")) { String back = Build.MODEL + "&" + address; Log.i("WifiController", back); // 把当前机子的IP通过广播发送到局域网中 DatagramPacket datagramPacket = new DatagramPacket(back.getBytes(), back.length(), packet.getSocketAddress()); socket.send(datagramPacket); Log.i("WifiController", "" + packet.getSocketAddress()); } } } catch (SocketException e) { e.printStackTrace(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (socket != null) { //最后关闭socket socket.isClosed(); } } } }

获取IP地址的操作就到此结束了;

控制阶段主要是通过socket通信来实现:

client:

public class Controll implements Runnable { private String whitch; private String code; public Controll(String whitch, String code) { this.whitch = whitch; this.code = code; } @Override public void run() { String ip = MainActivity.store.get(whitch); if (ip != null) { try { socket = new Socket(ip, PORT); socket.setSoTimeout(2000); PrintWriter printWriter = null; try { printWriter = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); } catch (IOException e) { e.printStackTrace(); } printWriter.println(code); Log.i("IP", socket.isConnected() + ""); } catch (IOException e) { e.printStackTrace(); } } } }

主要是创建多个socket短连接,并发送相应CODE,使服务端接收到相应的CODE之后做出相应Action:

Server:

//开启一个线程监听端口 class RecevieSocket extends Thread { @Override public void run() { Socket socket = null; try { serverSocket = new ServerSocket(PORT); } catch (IOException e) { e.printStackTrace(); } while (!Thread.currentThread().isInterrupted()) { try { socket = serverSocket.accept(); } catch (IOException e) { e.printStackTrace(); } Communication communication = new Communication(socket); communication.start(); } } } //开启一个线程接受相应的数据 class Communication extends Thread { private Socket socket; private BufferedReader input; private String code = null; public Communication(Socket socket) { this.socket = socket; try { this.input = new BufferedReader(new InputStreamReader(this.socket.getInputStream())); } catch (IOException e) { e.printStackTrace(); } } @Override public void run() { while (!Thread.currentThread().isInterrupted()) { Log.i("finderror", socket.isConnected() + ""); try { code = input.readLine(); } catch (IOException e) { e.printStackTrace(); } //相应的控制灯光操作: if (StringUtil.get(0, code, "@") != null) { switch (StringUtil.get(0, code, "@")) { case "close": Config.WriteData(Config.color, "0"); break; case "open": Config.WriteData(Config.color, "10"); break; case "red": Config.WriteData(Config.color, "1"); break; case "red_light": Config.WriteData(Config.color, "4"); break; case "green": Config.WriteData(Config.color, "3"); break; case "green_light": Config.WriteData(Config.color, "6"); break; case "blue": Config.WriteData(Config.color, "2"); break; case "blue_light": Config.WriteData(Config.color, "5"); break; case "white": Config.WriteData(Config.color, "10"); break; case "reserve_open": Calendar calendar = Calendar.getInstance(); long sys= System.currentTimeMillis(); calendar.setTimeInMillis(sys); calendar.set(Calendar.HOUR_OF_DAY,Integer.parseInt(StringUtil.get(3,code,"@"))); Log.i("close",StringUtil.get(3,code,"@")); calendar.set(Calendar.MINUTE,Integer.parseInt(StringUtil.get(4,code,"@"))); Log.i("close",StringUtil.get(4,code,"@")); Timer opentime =new Timer(); Log.i("close",(calendar.getTimeInMillis()-sys)+""); opentime.schedule(new TimerTask() { @Override public void run() { Log.i("result",StringUtil.get(1,code,"@")+"********"+StringUtil.get(2,code,"@")+"@@@@@@"+code); Config.WriteData(Config.color,StringUtil.get(1,code,"@")); Config.WriteData(Config.brightness,StringUtil.get(2,code,"@")); } },calendar.getTimeInMillis()-sys,(1000 * 60 * 60 * 24)); break; case "reserve_close": Calendar ca = Calendar.getInstance(); long system= System.currentTimeMillis(); ca.setTimeInMillis(system); ca.set(Calendar.HOUR_OF_DAY,Integer.parseInt(StringUtil.get(1,code,"@"))); ca.set(Calendar.MINUTE,Integer.parseInt(StringUtil.get(2,code,"@"))); Timer close =new Timer(); close.schedule(new TimerTask() { @Override public void run() { Config.WriteData(Config.color, "0"); } },ca.getTimeInMillis()-system, (1000 * 60 * 60 * 24)); break; case "brightness": Config.WriteData(Config.brightness, Integer.parseInt(StringUtil.get(1, code, "@")) * 10 + ""); break; } } } } }

Config.WriteData(Config.color, “0”);这句代码是对骁龙410c的开发板上的灯光进行控制。(往节点里些不同的数据!)

转载请注明原文地址: https://www.6miu.com/read-55371.html

最新回复(0)