标签:
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() ");
}
}
标签:
原文地址:http://blog.csdn.net/wukangbao1988/article/details/51679868