码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2016-06-15 16:09:32      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

小优入网实现

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() ");

    }
}

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

标签:

原文地址:http://blog.csdn.net/wukangbao1988/article/details/51679868

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!