【Android開發—智能家居系列】(四):UDP通訊發送指令

來源:互聯網
上載者:User

標籤:包括   test   產品   equals   param   link   case   err   .net   

思路回顧

【1】手機串連WIFI模組
【2】UDP通訊對WIFI模組發送指令,以和WIFI模組保持串連狀態
【3】UDP通訊對WIFI模組發送指令,讓其搜尋可用的無線網,返回WIFI列表
【4】發送指令,讓WIFI模組接入指定路由
【5】手機連線路由
【6】發送指令,獲得WIFI模組的動態IP地址

UDP通訊線程類
package com.jczb.smartlife.common;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.InetSocketAddress;import java.net.SocketException;import java.net.UnknownHostException;import android.os.Handler;import android.os.Message;import com.jczb.smartlife.common.Tool;public class GetInfoThread extends Thread {    private Handler handler;    private DatagramSocket socket;    private int msgType;    private final String IP = "255.255.255.255";//廣播位址    private int PORT = 26000;    /**     * 48899連接埠:C32x系列的連接埠,使用者可以用AT指令更改     * 49000連接埠:除C32x系列,其他WIFI模組的連接埠     * 1902連接埠:有人掌控寶系列產品的連接埠     */    private int targetPort = 49000 ;    private boolean receive = true;    /**     *      * @param handler 傳入監聽此線程的Handler     * @param intMsg 傳入監聽的訊息類型     */    public GetInfoThread(Handler handler,int msgType) {        this.handler = handler;        this.msgType=msgType;        init();    }    public void init(){        try {            socket = new DatagramSocket(null);            socket.setBroadcast(true);            socket.setReuseAddress(true);            socket.bind(new InetSocketAddress(PORT));        } catch (SocketException e) {            e.printStackTrace();            sendErrorMsg("Search Thread init fail");            return;        }     }    public void run() {        if (socket == null) {            return;        }        try {            byte[] data = new byte[1024];            //建立一個空的DatagramPacket對象            DatagramPacket revPacket = new DatagramPacket(data, data.length);            while (receive) {                //服務端接收資料                socket.receive(revPacket);                if(null!=handler){                    byte[] realData = new byte[revPacket.getLength()];                    System.arraycopy(data, 0, realData,0, realData.length);                    Message msg =handler.obtainMessage(msgType,realData);                    handler.sendMessage(msg);                }            }        } catch (Exception e) {            e.printStackTrace();            socket.close();        }    }    public void close() {        if (socket == null)            return;        socket.close();    }    private void sendErrorMsg(String info){    }    /**     * 發送資料     * @param msg     */    public void sendMsg(byte[] msg) {        if (socket != null) {            try {                System.out.println("targetPort------------------->"+targetPort);                DatagramPacket sendPacket = new DatagramPacket(msg, msg.length,                        InetAddress.getByName(IP), targetPort);                socket.send(sendPacket);            } catch (UnknownHostException e) {                e.printStackTrace();                System.out.println("發送失敗");            } catch (IOException e) {                e.printStackTrace();                System.out.println("發送失敗");            }        }    }    public void setReceive(boolean receive) {        this.receive = receive;    }    public void setTargetPort(int targetPort) {        this.targetPort = targetPort;    }    public void setMsgType(int msgType){        this.msgType=msgType;    }}

 

發送訊息的線程類
/**     * 發送訊息的隊列,每次發送資料時,只需要調用putMsg(byte[] data)方法     *      * @author usr_liujinqi     *      */    private class SendMsgThread extends Thread {        // 發送訊息的隊列        private Queue<byte[]> sendMsgQuene = new LinkedList<byte[]>();        // 是否發送訊息        private boolean send = true;        private GetInfoThread ss;        public SendMsgThread(GetInfoThread ss) {            this.ss = ss;        }        public synchronized void putMsg(byte[] msg) {            // 喚醒線程            if (sendMsgQuene.size() == 0)                notify();            sendMsgQuene.offer(msg);        }        public void run() {            synchronized (this) {                while (send) {                    // 當隊列裡的訊息發送完畢後,線程等待                    while (sendMsgQuene.size() > 0) {                        byte[] msg = sendMsgQuene.poll();                        if (ss != null)                            ss.sendMsg(msg);                    }                    try {                        wait();                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                }            }        }        public void setSend(boolean send) {            this.send = send;        }    }

 

應用

【舉例】發送搜尋WIFI模組的指令

//1.使用者獲得溫控器中WIFI模組的WIFI模組的IP地址,MAC地址,模組名稱的指令        private final byte[] getInfoCode=new byte[]{(byte)0x48,0x46,0x2D,0x41,0x31,0x31,0x41,0x53,0x53,0x49,0x53,0x54,0x48,0x52,0x45,0x41,0x44};    public static final int REC_Module=0x04;//搜尋WIFI模組的資訊(包括IP、Mac、名稱)//執行個體化一個線程,使用者獲得模組資訊(IP,Mac,名稱)        //參數為監聽為此線程的Handler,以及接收成功後,給Handler發送的訊息類型        getInfoThread = new GetInfoThread(handler,Tool.REC_Module);        getInfoThread.start();        //發送訊息的線程        smt = new SendMsgThread(getInfoThread);        smt.start();        //設定發送的目的連接埠號碼        getInfoThread.setTargetPort(Integer.parseInt("48899"));             smt.putMsg(getInfoCode);

 

WIFI模組在接收到指令後,就會回複資訊,以下的Handler就是針對回複過來的資訊進行解析處理等操作。

//處理訊息的Handler    private Handler handler= new Handler() {        public void handleMessage(Message msg) {            switch (msg.what) {            case Tool.REC_Module:// 解析接收到的資料                //設定發送的目的連接埠號碼                getInfoThread.setTargetPort(Integer.parseInt("48899"));                 getInfoThread.setMsgType(Tool.REC_OK);                smt.putMsg(okCode);                SetServer();                SetDHCP();                byte[] data = (byte[]) msg.obj;                //將十進位的資料轉化成十六進位資料                String strTemp= Tool.bytesToHexString(data);                //將十六進位的字串去掉空格之後進行解析                String strdecode=Tool.DecodeHex(strTemp.replace(" ", ""));                //取出IP,Mac地址,模組名稱                decodeIP(strdecode);                Toast.makeText(ConnectWifiActivity.this, "獲得WIFI模組名稱成功!"+ModuleName, Toast.LENGTH_SHORT).show();                break;            case Tool.REC_Server:                byte[] dataServer = (byte[])msg.obj;                //將十進位的資料轉化成十六進位資料                String strServer= Tool.bytesToHexString(dataServer);                if("2b 6f 6b 0d 0a 0d 0a ".equals(strServer)){                    Toast.makeText(ConnectWifiActivity.this, "設定伺服器成功!", Toast.LENGTH_SHORT).show();                }                break;            case Tool.REC_SSID:                byte[] dataSSID=(byte[])msg.obj;                Tool.bytesToHexString(dataSSID);                decodeData(dataSSID);                break;            case Tool.REC_AT:                byte[] dataID = (byte[]) msg.obj;                //將十進位的資料轉化成十六進位資料                String strTempID= Tool.bytesToHexString(dataID);                //將十六進位的字串去掉空格之後進行解析                String strdecodeID=Tool.DecodeHex(strTempID.replace(" ", ""));                break;            case Tool.REC_DHCP:                byte[] dataDHCP = (byte[])msg.obj;                //將十進位的資料轉化成十六進位資料                String strDHCP= Tool.bytesToHexString(dataDHCP);                if("2b 6f 6b 0d 0a 0d 0a ".equals(strDHCP)){                    Toast.makeText(ConnectWifiActivity.this, "設定DHCP網路參數成功!", Toast.LENGTH_SHORT).show();                }                break;            default:                byte[] data1 = (byte[]) msg.obj;                //將十進位的資料轉化成十六進位資料                String strTemp1= Tool.bytesToHexString(data1);                Toast.makeText(ConnectWifiActivity.this, strTemp1, Toast.LENGTH_SHORT).show();                break;            }        }    };

 

總結

  凡是需要對WIFI模組發送指令的,就需要用到上述的兩個線程類,還有一個對返回資訊進行處理的Handler。只是發送的指令的code不一樣,如上述表示的是搜尋WIFI模組的十六進位的指令。不管WIFI模組在AP模式下還是STA模式,通訊的最開始步驟都是先搜尋模組,然後獲得它的IP和Mac之後,立即回複+ok指令,就可以保持串連狀態。

Demo下載

UDP通訊發送指令Demo

【Android開發—智能家居系列】(四):UDP通訊發送指令

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.