小优机器人WIFI+SSDP入网具体实现

来源:互联网 发布:网络投资小项目 编辑:程序博客网 时间:2024/05/21 10:16

小优入网实现

1. 小优响应设备查询服务
当小优连接网络时,开启一个SSDP后台服务后,除了向局域网广播通知自己存在,还创建了一个广播监听线程,当收到智能网关发来的设备查询服务广播时,如下:
SEARCH * HTTP/1.1
HOST: 239.255.255.250:1900
MAN: “ssdp:discover”
MX: 120
ST: ssdp:all
广播监听线程会立刻响应查询服务,发送小优存在广告通知,信息内容跟入网时发的一样,如下:
NOTIFY * HTTP/1.1
Host: 239.255.255.250:1900
NT: urn:schemas-upnp-org:device:CanbotRobot:1
NTS: ssdp:alive
USN:uuid:Upnp-KL-U03S-1_0-04e67647e222::urn:schemas-upnp-org:device:CanbotRobot
Cache-Control: max-age = 1800
通过收到的设备查询服务广播,小优可以获取智能网关的ip地址,为接下来的通信提供目标地址,最后当网络断开时,会停止SSDP后台服务,再次连接网络时再启动。
2. 小优端声控指令转字符串
小优端获取到声音指令后,转化为字符串,对字符串做判断比较,是否符合本地指令,符合的就本地处理,不符合的字符串,就把它发送到智能网关处理。
这里写图片描述
小优端核心代码如下:
LanSend类主要实现ssdp加入多播组、监听发现服务并单播响应信息

import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.MulticastSocket;import android.content.Context;import android.util.Log;public class LanSend {     /**      * @param args      * @throws Exception       */     //广播地址     private static final String BROADCAST_IP = SSDPUtils.ADDRESS;//广播IP        private static final int BROADCAST_INT_PORT = SSDPUtils.PORT;   // 不同的port对应不同的socket发送端和接收端        MulticastSocket broadSocket ;//用于接收广播信息        public static boolean work=false;//循环监听因子        InetAddress broadAddress ;//广播地址        //DatagramSocket数据报Socket         DatagramSocket sender ;//数据流套接字 相当于码头,用于发送信息        private Context context;//      private InetSocketAddress mMulticastGroup;     public LanSend(Context contex) {      try {          this.context=contex;      //初始化       broadSocket=new MulticastSocket(BROADCAST_INT_PORT); //多播Socket//     mMulticastGroup = new InetSocketAddress(SSDPUtils.ADDRESS, SSDPUtils.PORT);       broadAddress = InetAddress.getByName(BROADCAST_IP);//获取网络多播地址       sender = new DatagramSocket();      } catch (Exception e) {       // TODO: handle exception       System.out.println("*****lanSend初始化失败*****"+e.toString());      }     }    public void join() {       try{          Log.e("LanSend", "join");       broadSocket.joinGroup(broadAddress); //把套接字socket加入到组播地址,这样就能接收到组播信息       new Thread(new GetPacket()).start(); //新建一个线程,用于循环侦听端口信息      }catch (Exception e) {       // TODO: handle exception       System.out.println("*****加入组播失败*****");      }     }     //广播发送查找在线用户     void sendGetUserMsg() {            byte[] b=new byte[1024];            DatagramPacket packet;  //数据包,相当于集装箱,封装信息            try{             b = SSDPUtils.buildSSDPSearchString().getBytes();               packet = new DatagramPacket(b, b.length, broadAddress, BROADCAST_INT_PORT); //广播信息到指定端口             sender.send(packet);//单播信息会给目标主机             System.out.println("*****已发送请求*****");                   }catch (Exception e) {       System.out.println("*****查找出错*****");      }        }     //当局域网内的在线机子收到广播信息时响应并向发送广播的ip地址(此处广播自己的存在来响应)主机发送返还信息,达到交换信息的目的     void returnUserMsg(String mac){      byte[] b=new byte[1024];      DatagramPacket packet;      try {       b=SSDPUtils.buildSSDPAliveString(mac).getBytes();       packet = new DatagramPacket(b,b.length,broadAddress, BROADCAST_INT_PORT);       sender.send(packet);       System.out.print("发送信息成功!");      } catch (Exception e) {       // TODO: handle exception       System.out.println("*****发送返还信息失败*****"+e);      }     }     //当局域网内的在线机子收到广播信息时响应并向发送广播的ip地址主机发送返还信息,达到交换信息的目的     void returnUserMsg(String mac,InetAddress inetaddress,int port){         byte[] b=new byte[1024];         DatagramPacket packet;         try {             b=SSDPUtils.buildSSDPAliveString(mac).getBytes();             packet = new DatagramPacket(b,b.length,inetaddress, port);             sender.send(packet);             System.out.print("发送信息成功!");         } catch (Exception e) {             // TODO: handle exception             System.out.println("*****发送返还信息失败*****"+e);         }     }     //当局域网某机子下线是需要广播发送下线通知     void offLine(){      byte[] b=new byte[1024];      DatagramPacket packet;      try {       b=SSDPUtils.buildSSDPByebyeString().getBytes();       packet = new DatagramPacket(b,b.length,broadAddress, BROADCAST_INT_PORT);       sender.send(packet);       System.out.println("*****已离线*****");      } catch (Exception e) {       // TODO: handle exception       System.out.println("*****离线异常*****");      }     }     class GetPacket implements Runnable {  //新建的线程,用于侦听,packet数据包      public void run() {          DatagramPacket inPacket;          work=true;       String[] message;       while(work){        try {             Log.e("LanSend", "GetPacket while");             inPacket=new DatagramPacket(new byte[1024], 1024);              broadSocket.receive(inPacket);     //接收广播信息并将信息封装到inPacket中//            inPacket.getData()//             message=new String(inPacket.getData(),0,inPacket.getLength()).split("@");  //获取信息,并切割头部,判断是何种信息(find--上线,retn--回答,offl--下线)           String data=new String(inPacket.getData()).trim();           if (data!=null) {               String socketAddress=inPacket.getSocketAddress().toString();               String[] datas=data.split(SSDPUtils.NEWLINE);               for (int i = 0; i < datas.length; i++) {                   Log.e("LanSend", "datas["+i+"] =  "+datas[i]);                   if (datas[i].trim().equalsIgnoreCase("ST: ssdp:all")) {                        Log.e("ALIVE", "response");                    String mac=SSDPUtils.getUserId(context);                    InetAddress sourceip=inPacket.getAddress();                    int port=inPacket.getPort();                    returnUserMsg(mac,sourceip,port);                    break;                }            }               Log.e("LanSend", "收到的数据包的 data :"+data+"    数据包的socketAddress:"+socketAddress);               System.out.println("收到的数据包的 data :"+data+"    数据包的socketAddress:"+socketAddress);        }          } catch (Exception e) {         // TODO: handle exception         System.out.println("线程出错 "+e);        }       }      }     }    }

SSDPUtils 为SSDP工具类,主要实现小优ssdp信息的生成

import android.content.Context;import android.net.wifi.WifiInfo;import android.net.wifi.WifiManager;import android.util.Log;/** * Created by florent.noel on 6/14/13. */public class SSDPUtils {    private static String TAG = SSDPUtils.class.getName();    public static final String ADDRESS = "239.255.255.250";    public static final int PORT = 1900;    public static final int MAX_REPLY_TIME = 5;    public static final int MSG_TIMEOUT = MAX_REPLY_TIME * 1000 + 1000;    public static final String STRING_MSEARCH = "M-SEARCH * HTTP/1.1";    public static final String NOTIFY_MSEARCH = "NOTIFY * HTTP/1.1";//    public static final String STRING_RootDevice = "ST: upnp:rootdevice";    public static final String STRING_AllDevice = "ST: ssdp:all";    public static final String NEWLINE = "\r\n";    public static final String MAN = "Man:\"ssdp:discover\"";    public static String LOCATION_TEXT = "LOCATION: http://";    public static String buildSSDPSearchString(){        StringBuilder content = new StringBuilder();        content.append(STRING_MSEARCH).append(NEWLINE);        content.append("Host: " + ADDRESS + ":" + PORT).append(NEWLINE);        content.append(MAN).append(NEWLINE);        content.append("MX: " + MAX_REPLY_TIME).append(NEWLINE);        content.append(STRING_AllDevice).append(NEWLINE);        content.append(NEWLINE);        Log.e(TAG, content.toString());        return content.toString();    }    /**     * 方法描述:获取本地userId方法    * @param   String app_name    * @return     * @see RobotUtil    */    public static String getUserId(Context context) {        WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);        if (!wifi.isWifiEnabled()) {            wifi.setWifiEnabled(true);        }        WifiInfo info = wifi.getConnectionInfo();        String mac = info.getMacAddress();        if(mac==null)        {            if (!wifi.isWifiEnabled()) {                wifi.setWifiEnabled(true);            }            long starttime = System.currentTimeMillis();            while(true&&System.currentTimeMillis()-starttime<5000){                    try {                        Thread.sleep(1000);                    } catch (InterruptedException e) {                        e.printStackTrace();                    }                     info = wifi.getConnectionInfo();                     mac = info.getMacAddress();                     if(mac!=null)                     {                         break;                     }            }            if (mac==null) {                Log.e("getUserId","getUserId失败 ");                return null;            }        }        Log.e("getUserId","getUserId "+mac);        String str=mac.replace(":", "");//      StringBuffer a = new StringBuffer(mac);//      a.deleteCharAt(2).deleteCharAt(4).deleteCharAt(6).deleteCharAt(8)//              .deleteCharAt(10);//      mac = a.toString();        return str;    }    /**     * NOTIFY * HTTP/1.1        ST: urn: schemas-upnp-org:device: 设备名称:1        HOST: 239.255.255.250:1900        EXT:        CACHE-CONTROL: max-age=1800        LOCATION: http://127.0.0.1:8008/ssdp/device-desc.xml        CONFIGID.UPNP.ORG: 7339        BOOTID.UPNP.ORG: 7339        USN: uuid: Upnp-设备系列号-设备识别号::urn:schemas-upnp-org:device:设备名称     */    public static String buildSSDPAliveString(String mac){        StringBuilder content = new StringBuilder();//      content.append("HTTP/1.1 200 OK").append(NEWLINE);        content.append(NOTIFY_MSEARCH).append(NEWLINE);        content.append("ST: urn:schemas-upnp-org:device:设备名称:1").append(NEWLINE);        content.append("Host: " + ADDRESS + ":" + PORT).append(NEWLINE);        content.append("Cache-Control: max-age=1800").append(NEWLINE);        content.append("CONFIGID.UPNP.ORG: 7339").append(NEWLINE);        content.append("BOOTID.UPNP.ORG: 7339").append(NEWLINE);        content.append("USN: uuid:Upnp-设备系列号-"+mac+"::urn:schemas-upnp-org:device:设备名称").append(NEWLINE);        content.append(NEWLINE);    /**     *  NOTIFY * HTTP/1.1        ST: urn: schemas-upnp-org:device: 设备名称:1        HOST: 239.255.255.250:1900        EXT:        CACHE-CONTROL: max-age=1800        LOCATION: http://127.0.0.1:8008/ssdp/device-desc.xml        CONFIGID.UPNP.ORG: 7339        BOOTID.UPNP.ORG: 7339        USN: uuid: Upnp-设备系列号-设备识别号::urn:schemas-upnp-org:device:设备名称     */        Log.e(TAG, content.toString());        return content.toString();    }    public static String buildSSDPByebyeString(){        StringBuilder content = new StringBuilder();        content.append(NOTIFY_MSEARCH).append(NEWLINE);        content.append("Host: " + ADDRESS + ":" + PORT).append(NEWLINE);        content.append("NT: someunique:idscheme3").append(NEWLINE);        content.append("NTS: ssdp:byebye").append(NEWLINE);        content.append("USN: someunique:idscheme3").append(NEWLINE);        content.append(NEWLINE);        Log.e(TAG, content.toString());        return content.toString();    }    public static String parseIP(String msearchAnswer){        String ip = "0.0.0.0";        //find the index of "LOCATION: http://"        int loactionLinePos = msearchAnswer.indexOf(LOCATION_TEXT);        if(loactionLinePos != -1){            //position the index right after "LOCATION: http://"            loactionLinePos += LOCATION_TEXT.length();            //find the next semi-colon (would be the one that separate IP from PORT nr)            int locColon = msearchAnswer.indexOf(":", loactionLinePos);            //grab IP            ip = msearchAnswer.substring(loactionLinePos, locColon);        }        return ip;    }}

HuaweiSmartGateway 类主要实现ServerSocket,并对声控结果指令、智能网关指令信息的处理

import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.File;import java.io.IOException;import java.net.ServerSocket;import java.net.Socket;import org.json.JSONException;import org.json.JSONObject;import android.R.integer;import android.app.Dialog;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.media.MediaPlayer.OnCompletionListener;import android.net.Uri;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.speech.tts.TextToSpeech;import android.speech.tts.TextToSpeech.OnInitListener;import android.speech.tts.TextToSpeech.OnUtteranceCompletedListener;import android.util.Log;import android.view.LayoutInflater;import android.view.View;import android.view.WindowManager;import android.widget.TextView;import android.widget.Toast;import com.unisrobot.rsk.MainApplication;import com.unisrobot.rsk.R;import com.unisrobot.rsk.preference.ConstUtils;import com.unisrobot.rsk.util.Logger;public class HuaweiSmartGateway {     //广播地址     private static final String TAG = "HuaweiSmartGateway";        public static final String ACTION_HEALTH_MANAGEMENT_DATA="识别string";        public static final String ACTION_SMARTHOME_CMD="识别string2";        private static final int BROADCAST_INT_PORT = SSDPUtils.PORT;   // 不同的port对应不同的socket发送端和接收端        public static String responseMsg;//成功返回智能家居的执行成功结果,小优播放的文本语音(测试用)        public static String speakresponseMsg=null;//成功返回智能家居的执行成功结果,保存用,小优播放的文本语音(测试用)        private Context mContext;        private LanSend lSend;        private TextToSpeech mTextToSpeech;        private MyReceiver mReceiverResult;        private Dialog dialog;        Handler mHander = new Handler() {            public void handleMessage(Message msg) {                switch (msg.what) {                case 4:                    Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();                    break;                case 5://                  Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();                    String str=(String)msg.obj;                    if (str!=null&&!str.isEmpty()) {                        createDialog((String)msg.obj);                    }                    break;                case 6://                  Toast.makeText(mContext, (String)msg.obj, Toast.LENGTH_SHORT).show();                    String str2=(String)msg.obj;                    if (str2!=null&&!str2.isEmpty()) {                        createDialog((String)msg.obj);                    }                    int rs=msg.arg1;                    if (rs!=0) {                        playhuaweiVoice2(mContext, rs);                    }                    break;                }            }        };     public HuaweiSmartGateway(Context contex) {         this.mContext=contex;     }    public void init() {        if (mTextToSpeech==null) {            mTextToSpeech = new TextToSpeech(mContext, new OnInitListener() {                @Override                public void onInit(int status) {                    // TODO Auto-generated method stub                }            });            mTextToSpeech.setOnUtteranceCompletedListener(new OnUtteranceCompletedListener() {                @Override                public void onUtteranceCompleted(String utteranceId) {                    cancelDialog();                    // TODO Auto-generated method stub//                  startvoice();                }            });        }        //针对华为智能网关        SSDPNotify();        initServerSocket();        registerResult();    }    public void destroy(){//      mHander.removeMessages(6);        unRegisterBroadcastResult();    }    private void registerResult() {        if (mReceiverResult == null) {            mReceiverResult = new MyReceiver();        }        Logger.d(TAG, "注册---识别结果广播");        IntentFilter filter = new IntentFilter();        filter.addAction(ACTION_HEALTH_MANAGEMENT_DATA);        filter.addAction(ACTION_SMARTHOME_CMD);        mContext.registerReceiver(mReceiverResult, filter);    }    private void unRegisterBroadcastResult() {        if (mReceiverResult != null) {            Logger.d(TAG, "反注册---识别结果广播");            mContext.unregisterReceiver(mReceiverResult);        }    }    /**     * 创建内容提示框     * @param tip     */    public void createDialog(String tip){        if (dialog==null) {            dialog = new Dialog(mContext,R.style.dialog);            LayoutInflater layoutInflater = LayoutInflater.from(mContext);            View viewDialog = layoutInflater.inflate(                    R.layout.dialog_center3, null);            TextView tv = (TextView)viewDialog.findViewById(R.id.tv_dialogcenter);            tv.setText(tip);            dialog.setContentView(viewDialog);            dialog.setCanceledOnTouchOutside(false);//          dialog.setCancelable(false);            dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);            dialog.show();        }    }    /**     * 取消提示框     */    public void cancelDialog(){        if (dialog!=null) {            if (dialog.isShowing()) {                dialog.cancel();            }            dialog=null;        }    }    /**     * 监听ssdp查询服务     */    public void SSDPNotify(){        if (lSend==null) {            try {                lSend=new LanSend(mContext);                lSend.join();     //加入组播,并创建线程侦听              } catch (Exception e) {               System.out.println("*****加入组播失败*****");              }        }    }    /**     * 初始化小优端ServerSocket     */    private ServerSocket mServerSocket;    private Socket socket;    public void initServerSocket(){        if (mServerSocket==null) {            new Thread() {                public void run() {                    try {                        mServerSocket = new ServerSocket(socket通信端口号);                        while (true) {                            Log.e(TAG, "111111111");                            socket=mServerSocket.accept();                            handle(socket);                        }                    } catch (IOException e) {                        e.printStackTrace();                    }                };            }.start();        }    }    DataOutputStream out   ;    private DataInputStream mDataInputStream;    private MediaPlayer mphw;    void handle(Socket socket) throws IOException {        Log.e("myrobotSocket", "new socket");        try {             out = new DataOutputStream(socket.getOutputStream());            mDataInputStream = new DataInputStream(                    socket.getInputStream());            while (true) {                Log.e("myrobotSocket", "true");            final   String cmd = mDataInputStream.readUTF();            JSONObject jsonO2 = new JSONObject(cmd) ;            String type=jsonO2.getString("type");            String action_cmd=jsonO2.getString("action_cmd");            Log.e("myrobotSocket", "type : "+type+"  ::: cmd : "+action_cmd);            if (type!=null&&!type.isEmpty()&&action_cmd!=null&&!action_cmd.isEmpty()) {                Message msg=new Message();                msg.what=4;                msg.obj="type : "+type+"  ::: cmd : "+action_cmd;                mHander.sendMessage(msg);            }            if("001".equals(type)){                if (action_cmd.contains("0X")) {                    int action = Integer.valueOf(action_cmd.replace("0X", ""), 16);                    MainApplication.getInstance().sendActionCmd((byte) action);                }else if(action_cmd.contains("0x")){                    int action = Integer.valueOf(action_cmd.replace("0x", ""), 16);                    MainApplication.getInstance().sendActionCmd((byte) action);                }            }else if("002".equals(type)) {//播放插件响应,返回结果                JSONObject jsonCMD = new JSONObject(action_cmd) ;                String rsp=jsonCMD.getString("rsp");                String content=jsonCMD.getString("content");                if (content!=null&&!content.equals("")&&!content.isEmpty()) {                    boolean blplay=false;                    int resid = 0;//                  Turn on the living room lights.//                  Turn off the living room lights.                    if (content.equals("success")&&speakresponseMsg!=null&&!speakresponseMsg.equals("")) {                        if (speakresponseMsg.contains("turn on")&&speakresponseMsg.contains("living room")                                &&speakresponseMsg.contains("light")) {                            blplay=true;                            resid=R.raw.livingroom_on;                            content="The living room lights have been turned on.";                        }else if (speakresponseMsg.contains("turn off")&&speakresponseMsg.contains("living room")                                &&speakresponseMsg.contains("light")) {                            blplay=true;                            resid=R.raw.livingroom_off;                            content="The living room lights have been turned off.";                        }else {                            content=speakresponseMsg;                        }                    }                    else if (content.equals("ALARM_DOOR_OPEN")) {                        blplay=true;                        resid=R.raw.door_open2;//                      content="欢迎光临智慧沃家体验馆!";//                      createDialog(content);//                      playhuaweiVoice2(mContext, resid);//                      continue;//                      content="Warning! The door is open.";                    }                    else if (content.equals("ALARM_DOOR_CLOSE")) {                        blplay=false;                        content="";//                      blplay=true;//                      resid=R.raw.door_close;//                      content="The door is closed.";                    }                    else if (content.equals("ALARM_FALL")) {//老人看护,有人跌倒                        blplay=true;                        resid=R.raw.someone_felldown;                        content="Warning! Someone fell down.";                    }                    if (content!=null&&!content.isEmpty()) {                        Message msg=new Message();                        msg.what=4;                        msg.obj=content;                        mHander.sendMessage(msg);                    }                    if (blplay) {                        if (content!=null&&!content.isEmpty()) {                            if (content.equals("ALARM_DOOR_OPEN")) {                                content="欢迎光临智慧沃家体验馆!";                                Message msg=new Message();                                msg.what=6;                                msg.obj=content;                                msg.arg1=resid;                                mHander.sendMessage(msg);//                              mHander.sendMessageDelayed(msg, 6*1000);                            }else {                                Message msg=new Message();                                msg.what=5;                                msg.obj=content;                                mHander.sendMessage(msg);//                              createDialog(content);                                if (resid!=0) {                                    playhuaweiVoice(mContext, resid);                                }                            }                        }                    }else {                        if (mTextToSpeech!=null) {                            if (content!=null&&!content.isEmpty()) {                                Log.e("myrobotSocket", "type : "+type+"  :mTextToSpeech : "+content);                                 mTextToSpeech.speak(content, TextToSpeech.QUEUE_FLUSH, null);                            }                        }                    }                }                }            }//          }        } catch (IOException e) {            e.printStackTrace();            Log.e(TAG, "" + e.toString());            out.close();            mDataInputStream.close();            socket.close();        } catch (JSONException e) {            // TODO Auto-generated catch block            e.printStackTrace();            out.close();            mDataInputStream.close();            socket.close();        }    }    /**     * 播放华为定制的语音2     * @param mContext     * @param resid     */    public void playhuaweiVoice2(final Context mContext,int resid){        if (mphw != null) {            mphw.release();            mphw = null;        }        if (mphw == null) {            mphw = MediaPlayer.create(mContext, resid);            mphw.start();            mphw.setOnCompletionListener(new OnCompletionListener() {                @Override                public void onCompletion(MediaPlayer mp2) {                    // TODO Auto-generated method stub                    if(mphw!=null){                        mphw.release();                        mphw=null;                    }                    cancelDialog();//                  String path=Environment.getExternalStorageDirectory()+"/ai/qnqn/myrobot/uushow/action/roundDance.mp3";//                  File file=new File(path);//                  if (file.exists()) {//                      Uri uri=Uri.parse(path);//                      mphw = MediaPlayer.create(mContext, uri);//                      if (mphw!=null) {//                          mphw.start();//                          mphw.setOnCompletionListener(new OnCompletionListener() {//                              @Override//                              public void onCompletion(MediaPlayer mp) {//                                  // TODO Auto-generated method stub//                                  if(mphw!=null){//                                      mphw.release();//                                      mphw=null;//                                  }//                                  cancelDialog();//                              }//                          });//                          int action = Integer.valueOf("2B", 16);//                          MainApplication.getInstance().sendActionCmd((byte) action);//                          MainApplication.getInstance().sendActionCmd((byte) action);//                          //                      }else {//                          cancelDialog();//                      }//                  }else {//                      cancelDialog();//                  }//                  startvoice();//                  handler.sendEmptyMessage(rtcode);                }            });        }    }    /**     * 播放华为定制的语音     * @param mContext     * @param resid     */    public void playhuaweiVoice(Context mContext,int resid){        if (mphw != null) {            mphw.release();            mphw = null;        }        if (mphw == null) {            mphw = MediaPlayer.create(mContext, resid);            mphw.start();            mphw.setOnCompletionListener(new OnCompletionListener() {                @Override                public void onCompletion(MediaPlayer mp2) {                    // TODO Auto-generated method stub                    if(mphw!=null){                        mphw.release();                        mphw=null;                    }                    cancelDialog();//                  startvoice();//                  handler.sendEmptyMessage(rtcode);                }            });        }    }    class MyReceiver extends BroadcastReceiver    {        @Override        public void onReceive(Context context, Intent intent) {            String action = intent.getAction();            Log.e(TAG, "onReceive  " + action);            if (ACTION_HEALTH_MANAGEMENT_DATA.equals(action)) {//上报健康管理数据                if (out!=null&&socket!=null) {                        try{                            socket.sendUrgentData(0xFF);//发送一个字节判断是否为空,此字节服务端会自动舍弃                            String  healthData=intent.getStringExtra("health_data");                            Log.e(TAG, "healthData =  " + healthData);                            JSONObject datajs=new JSONObject();                            JSONObject healthjs=new JSONObject(healthData.trim());                            datajs.put("datatype", "health_data");                            datajs.put("datacontent", healthjs);                            String device=healthjs.getString("device").trim();                            Log.e(TAG, "device =  " + device);                            if (device.equals("BloodPressure")) {                                out.writeUTF(datajs.toString());                                out.flush();//                              Toast.makeText(mContext, "上传血压数据成功", Toast.LENGTH_SHORT).show();                            }                            else if(device.equals("Temperature")){                                out.writeUTF(datajs.toString());                                out.flush();                                Log.e("myrobotSocket", "healthData =  " + healthData);                                Log.e("myrobotSocket", "datajs =  " + datajs.toString());//                              Toast.makeText(mContext, "上传体温数据成功", Toast.LENGTH_SHORT).show();                            }                            else if(device.equals("Weighting")){                                out.writeUTF(datajs.toString());                                out.flush();                            }                            return;                            }catch(Exception ex){                                Toast.makeText(mContext, "网关不通,上传数据失败", Toast.LENGTH_SHORT).show();                            return;                            }                    }else {                        Toast.makeText(mContext, "socket=null,上传数据失败", Toast.LENGTH_SHORT).show();                        return;                }            }else if(ACTION_SMARTHOME_CMD.equals(action)) {//智能家居命令上报                if (out!=null&&socket!=null) {                    try{                        socket.sendUrgentData(0xFF);//发送一个字节判断是否为空,此字节服务端会自动舍弃                        String  smarthomeCMD=intent.getStringExtra("smarthome_cmd");                        Log.e(TAG, "smarthomeCMD =  " + smarthomeCMD);                        JSONObject smarthomejs=new JSONObject();                        smarthomejs.put("datatype", "smarthome_data");                        smarthomejs.put("datacontent", smarthomeCMD.trim());                            out.writeUTF(smarthomejs.toString());                            out.flush();//                          Toast.makeText(mContext, "上报智能家居指令成功", Toast.LENGTH_SHORT).show();                            Intent  i= new Intent(ConstUtils.ACTION_SMARTHOME_CMD_HANDLE_EXCEPTION) ;                            mContext.sendBroadcast(i);//                          startvoice();                        return;                        }catch(Exception ex){                            ex.printStackTrace();                            Toast.makeText(mContext, "网关不通,上报智能家居指令失败", Toast.LENGTH_SHORT).show();                            Intent  i= new Intent(ConstUtils.ACTION_SMARTHOME_CMD_HANDLE_EXCEPTION) ;                            mContext.sendBroadcast(i);//                          startvoice();                        return;                        }                }else {                    Toast.makeText(mContext, "socket=null,上报智能家居指令失败", Toast.LENGTH_SHORT).show();                    Intent  i= new Intent(ConstUtils.ACTION_SMARTHOME_CMD_HANDLE_EXCEPTION) ;                    mContext.sendBroadcast(i);//                  startvoice();                    return;                    }            }                }    } ;    }

智能网关小优驱动插件实现

3. 智能网关插件上报指令信息
智能网关插件收到小优端、手机端、其他智能设备发过来字符串信息,就对其进行语义分析,如果能跟智能网关上的事件信息匹配上,把此事件上报给智能网关处理,否则不上报。
这里写图片描述
核心代码如下(其中部分代码为华为Openlife平台提供):
CanbotDeviceListener 类为小优的设备监听类,起一个循环测试线程,每隔6秒测试一次socket是否通,不通重连,监听到设备端发来的事件信息并作出处理

import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.net.Socket;import java.net.UnknownHostException;import org.json.JSONObject;import com.huawei.smarthome.api.event.IDeviceEventListener;import com.huawei.smarthome.driver.IDeviceService;import com.huawei.smarthome.driver.ip.AbstractSsdpDeviceDriverAdapter;import com.huawei.smarthome.log.LogService;import com.huawei.smarthome.log.LogServiceFactory;/** * <div class="English"> * 设备监听器,当机器人上线时与机器人进行连接 * </div> *  * <div class="Chinese"> *  * </div> * <br> * @author Lixin * @since NetOpen 1.0 * 2015年12月30日 */public class CanbotDeviceListener implements IDeviceEventListener{    //日志服务,用于调试时打印日志    final private static LogService LOGGER = LogServiceFactory.getLogService(CanbotDeviceListener.class);    public boolean towork=false;    public boolean towork2=false;    //ssdp设备驱动    private AbstractSsdpDeviceDriverAdapter adapter;    private IDeviceService deviceService;    private Socket client;    private DataOutputStream out;    private DataInputStream in;    public CanbotDeviceListener(AbstractSsdpDeviceDriverAdapter adapter,IDeviceService deviceService)    {        this.adapter = adapter;        this.deviceService=deviceService;    }    @Override    public void deviceAdded(JSONObject device)    {    }    @Override    public void deviceRemoved(JSONObject device)    {    }    @Override    public void deviceOnlined(JSONObject device)    {        LOGGER.d("deviceOnlined,device:{0}", device);        //得到机器人sn和ip        String sn = device.optJSONObject("basic").optString("sn");        String ip = adapter.getDeviceIp(sn);        LOGGER.d("device sn={0};ip={1}", sn,ip);        towork2=true;        //建立和机器人的连接        start(ip,sn);        if (!towork) {            towork=true;             new Thread(new Runnable() {                public void run() {                    while (towork) {                        try {                            Thread.sleep(6*1000);//每隔6秒检测一次                            testSocket(ip,sn);                        } catch (InterruptedException e) {                            // TODO Auto-generated catch block                            e.printStackTrace();                            break;                        }                    }                }            }).start();        }    }    @Override    public void deviceOfflined(JSONObject device)    {        // TODO Auto-generated method stub        towork=false;        towork2=false;    }    @Override    public void deviceAlarmed(JSONObject device, String alarmName, JSONObject parameter)    {    }    @Override    public void deviceProerptyChanged(JSONObject device, String dataClass, String propertyName, Object value)    {        LOGGER.d("deviceProerptyChanged,device:{0},dataClass:{1},propertyName:{2},value:{3}", device,dataClass,propertyName,value);    }    public void start(String ip ,String sn) {        if(!towork2){            return;        }        try {            client = new Socket(ip, socket通信端口);            out = new DataOutputStream(client.getOutputStream());            in=new DataInputStream(client.getInputStream());            //??先测试用此句            LOGGER.d("send cmd 0x01");            sendActionCmd(sn,ip,"0x01","001");            new Thread(new Runnable()             {                public void run()                 {                    while (towork2)                     {                        LOGGER.d("receive : read data");                        String data;                        try {                            data = in.readUTF();                            LOGGER.d("receive : " + data);                            JSONObject datajs=new JSONObject(data.trim());                            String datatype=datajs.getString("datatype");                            if (datatype.equals("health_data"))                             {                                JSONObject contentjs=datajs.getJSONObject("datacontent");                                String device=contentjs.getString("device");                                JSONObject deviceDatajs=contentjs.getJSONObject("deviceData");                                //收到的上报数据为血压计数据                                if (device.equals("BloodPressure"))                                 {                                    //得到血压计上报的数据                                    String mac=deviceDatajs.getString("MAC");                                    String type=deviceDatajs.getString("type");                                    //舒张压                                    String dbp =deviceDatajs.getString("DBP");                                    //收缩压                                    String sbp =deviceDatajs.getString("SBP");                                    LOGGER.d("sn:{0},type:{1},dbp:{2},sbp:{3}",mac,type,dbp,sbp);                                    reportBloodDeviceData(mac, type, Integer.parseInt(dbp), Integer.parseInt(sbp));                                    JSONObject rspmsg=new JSONObject();                                    rspmsg.put("rsp", "健康响应");                                    rspmsg.put("content", "已成功上传血压数据");                                    sendActionCmd(sn,ip, rspmsg.toString(), "002");                                }                                //收到的上报数据为体重秤数据                                else if(device.equals("Weighting"))                                {                                    String weight=deviceDatajs.getString("weight");                                    String mac=deviceDatajs.getString("MAC");                                    reportWeighingDeviceData(mac, Float.parseFloat(weight));                                    JSONObject rspmsg=new JSONObject();                                    rspmsg.put("rsp", "健康响应");                                    rspmsg.put("content", "已成功上传体重数据");                                    sendActionCmd(sn,ip, rspmsg.toString(), "002");                                }                            }                             else if(datatype.equals("smarthome_data"))                            {                                String smarthome_cmd=datajs.getString("datacontent").trim();                                if (smarthome_cmd!=null&&!smarthome_cmd.equals("")&&!smarthome_cmd.isEmpty()) {                                     JSONObject robotClassData = new JSONObject(smarthome_cmd);                                    deviceService.reportDeviceAlarm(sn, "VOICE_CMD_EVENT", robotClassData);                                    /*JSONObject rspmsg=new JSONObject();                                    rspmsg.put("rsp", "智能家居响应");                                    rspmsg.put("content", "控制成功");                                    sendActionCmd(sn,ip, rspmsg.toString(), "002");*/                                }                                else                                 {                                    JSONObject rspmsg=new JSONObject();                                    rspmsg.put("rsp", "智能家居响应");                                    rspmsg.put("content", "指令为空");                                    sendActionCmd(sn,ip, rspmsg.toString(), "002");                                }                            }                        } catch (IOException e) {                            LOGGER.e("IOException:", e);                            deviceService.reportDeviceOffline(sn, "uurobot");//                          towork2=false;                            break;                        }                    }                }            }).start();        } catch (UnknownHostException e) {            LOGGER.e("UnknownHostException:", e);        } catch (IOException e) {            LOGGER.e("IOException:", e);        }    }    public void sendActionCmd(String sn,String ip,String cmd,String type) {        if (out==null) {            start(ip,sn);            LOGGER.d("out==null xiaoyou lose ");            return;        }        if (client!=null) {            try{                client.sendUrgentData(0xFF);//发送一个字节判断是否为空,此字节服务端会自动舍弃                }catch(Exception ex){                start(ip,sn);                LOGGER.d("socket close xiaoyou lose ");                return;                }        }else {            start(ip,sn);            LOGGER.d("client==null xiaoyou lose ");            return;        }        try {            JSONObject jsonO = new JSONObject();            jsonO.put("type", type);            jsonO.put("action_cmd", cmd);            out.writeUTF(jsonO.toString());            out.flush();            LOGGER.d("send " + cmd);        } catch (IOException e) {            LOGGER.e("IOException:", e);        }    }    public void testSocket(String ip,String sn) {//测试socket是否通,不通重连        if (out==null) {            start(ip,sn);            LOGGER.d("out==null xiaoyou lose ");            return;        }        if (client!=null) {            try{                client.sendUrgentData(0xFF);//发送一个字节判断是否为空,此字节服务端会自动舍弃            }catch(Exception ex){                start(ip,sn);                LOGGER.d("socket close xiaoyou lose ");                return;            }        }else {            start(ip,sn);            LOGGER.d("client==null xiaoyou lose ");            return;        }    }     /**     * <div class="English"> </div>     * <div class="Chinese">上报血压仪数据,上报数据之前先上报上线 </div>     * @param sn     * @param type 类别     * @param dbp 舒张压     * @param sbp 收缩压     */    private void reportBloodDeviceData(String sn,String type,int dbp,int sbp)    {        deviceService.reportDeviceOnline(sn, "uurobot_bloodDevice");        JSONObject data = new JSONObject();        JSONObject bloodDevice = new JSONObject();        bloodDevice.put("diastolicPressure", dbp);        bloodDevice.put("systolicPressure", sbp);        JSONObject uurobot_bloodDevice = new JSONObject();        uurobot_bloodDevice.put("result", type);        data.put("uurobot_bloodDevice", uurobot_bloodDevice);        data.put("bloodDevice", bloodDevice);        LOGGER.d("sn:{0},data:{1}", sn,data);        deviceService.reportDeviceProperty(sn, "uurobot_bloodDevice", data);    }    /**     * <div class="English"> </div>     * <div class="Chinese">上报体重秤数据,上报数据之前先上报上线 </div>     * @param sn     * @param weight 体重     */    private void reportWeighingDeviceData(String sn,float weight)    {        deviceService.reportDeviceOnline(sn, "uurobot_weighingDevice");        deviceService.reportDeviceProperty(sn, "uurobot_weighingDevice", "weighingDevice","weight",weight);    }}

CanbotRobotDriver 类为小优设备驱动类,此类会初始化小优设备监听器,并执行事件的响应doAction

import org.json.JSONObject;import com.huawei.smarthome.api.event.IDeviceEventService;import com.huawei.smarthome.api.exception.ActionException;import com.huawei.smarthome.driver.ip.AbstractSsdpDeviceDriverAdapter;import com.huawei.smarthome.localapi.ServiceApi;import com.huawei.smarthome.log.LogService;import com.huawei.smarthome.log.LogServiceFactory;/** * Title:        iManager NetOpen V100R001C00<br> * Description:  ssdp发现模式设备驱动<br> * Copyright:    Copyright (c) 1988-2015<br> * Company:      Huawei Tech. Co., Ltd<br>   * @author       h00210095 * @version      1.0  2015-10-19 */public class CanbotRobotDriver extends AbstractSsdpDeviceDriverAdapter{    final private static LogService LOGGER = LogServiceFactory.getLogService(CanbotRobotDriver.class);    private CanbotDeviceListener canbotDeviceListener;    @Override    public JSONObject doAction(String sn, String commmand, JSONObject params, String deviceClass)            throws ActionException    {        LOGGER.i("sn:" + sn + ",commmand:" + commmand + ",params:" + params + ",deviceClass:" + deviceClass);        //ssdp设备是IP设备,先校验IP        String ip = this.getDeviceIp(sn);        if ("uurobot".equalsIgnoreCase(deviceClass) && ip != null && !"".equals(ip))        {            String cmd = null;            String type= null;            // 腿部指令            if ("moveLeg".equals(commmand))             {                type="001";                String param=params.getString("direction");                {                    if(param.equals("front"))                    {                        cmd = "0X8a";                    }                    else if(param.equals("back"))                    {                        cmd = "0x8b";                    }                    else if(param.equals("left"))                    {                        cmd = "0x03";                    }                    else if(param.equals("right"))                    {                        cmd = "0x04";                    }                }            }            // 头部指令            else if ("moveHead".equals(commmand))             {                type="001";                String param=params.getString("direction");                {                    if(param.equals("up"))                    {                        cmd = "0X0a";                    }                    else if(param.equals("down"))                    {                       cmd = "0X0b";                    }                    else if(param.equals("left"))                    {                       cmd = "0X07";                    }                    else if(param.equals("right"))                    {                        cmd = "0X06";                    }                    else if(param.equals("reset"))                    {                        cmd = "0X09";                    }                }            }            // 关闭关命            else if ("reportMsg".equals(commmand))             {                type="002";                String param=params.getString("msg");                if(param.equals("result"))                {                    String content=params.getString("content");                    LOGGER.i("content:" + content);                    JSONObject rspmsg=new JSONObject();                    rspmsg.put("rsp", "result");                    rspmsg.put("content", content);                    cmd=rspmsg.toString();//                  cmd="0X0a";                }                else if(param.equals("alarm"))//此处响应智能家居控制,以后还需要改                {                    String alarmName=params.getJSONObject("content").getString("alarmName");                    LOGGER.i("alarmName:" + alarmName);                    JSONObject rspmsg=new JSONObject();                    rspmsg.put("rsp", "alarm");                    rspmsg.put("content", alarmName);                    cmd=rspmsg.toString();                }                else if(param.equals("message"))                {//                  cmd="0X07";                }            }            if (cmd!=null&&type!=null) {                canbotDeviceListener.sendActionCmd(sn,ip, cmd,type);           }        }        else        {            throw new ActionException(-1, "couldn't find device class " + deviceClass);        }        return null;    }/** * 初始化服务端口,并读取端口信息 */    @Override    public void init()    {         //得到其他设备并且驱动//        IDeviceManageService deviceManageService = ServiceApi.getService(IDeviceManageService.class, null);//        deviceManageService.doAction(sn, action, parameter, deviceClass)        //添加监听器,机器人上线时与机器人建立连接        IDeviceEventService service = ServiceApi.getService(IDeviceEventService.class, null);        canbotDeviceListener=new CanbotDeviceListener(this,deviceService);        service.addDeviceListener("uurobot",canbotDeviceListener);        LOGGER.d("init() ");    }}
2 0
原创粉丝点击