您的位置:首页 > 其它

智能家居通用管理平台(七) - 即插即用机制的设计

2014-07-25 16:27 267 查看
即插即用机制,对智能家居的推广,非常重要。没有她,老百姓估计不会使用。

好了,现在有了“智能冰箱”和它的驱动程序,SHM就可以使用它的SHDD来与冰箱交互了,并且是使用TCPIP协议通信。但还有一个环节没有解决,TCP通信需要知道通信端口。每个SHM都是使用不同的端口与设备通信,怎样约定通信端口?其次,为了安全起见,冰箱连接SHM,需要账号和密码,冰箱也可以自己决定,SHM是否是受信任的平台程序?如果不在我的授信列表中,可以拒绝连接到SHM。

这实际是一个设备即插即用的问题。冰箱买回来,第一次上电,它应该很快就能接入SHP平台,一般是几秒钟的时间,否则老百姓肯定骂娘。

现在流行的UPnP,是目前很多智能设备相互发现的机制。相关的文章很多,这里不做介绍。但它主要适用于点对点的通信方式(P2P)。SHP平台设计的PNP机制,不需要对现有网络做任何的改变,仅仅通过程序使用特定协议来完成设备交互。下图是SHP平台的设备发现和接入机制(转载请注明来源):



所以SHP 的PNP机制,实际上分两个阶段执行,分别在不同的程序中完成。目前的“冰箱”程序中,我们设

定3秒广播一次信息、15秒尝试连接SHM,所以第一次接入系统,在18秒内完成(如果设定连接时间间隔更

短,则接入更快)。下次冰箱重新上电再连接SHM 时,直接使用连接信息连接SHM,无需再次广播。只要

SHP在工作,一般瞬间就连接成功。

广播的协议,在考虑多种情况后,再严格规范。下面是目前“冰箱”程序PNP机制的部分代码:

#region PNP机制

private void btnBroadcast_Click(object sender, EventArgs e) //启动消息广播

{

//if (sockBroadcast == null) InitSockBroadcast();

if (btnBroadcast.Text == "启动消息广播")

{

InitSockBroadcast();

tmBroadcast.Start();

lbBCState.Text = "正在广播消息...";

btnBroadcast.Text = "停止消息广播";

BroadcastMessage();

}

else

{

if (tReceiveBroadcast != null) tReceiveBroadcast.Abort();

tmBroadcast.Stop();

btnBroadcast.Text = "启动消息广播";

lbBCState.Text = "停止广播消息";

}

}

private void tmBroadcast_Tick(object sender, EventArgs e) //定时广播

{

BroadcastMessage();

}

void BroadcastMessage() //广播设备系统本身的信息

{

stringJson json = new stringJson(SmartHomeChannel.SHFLAG);

//string hostname = Dns.GetHostName();

json.AddNameValume("product", "金鹰智能冰箱ESR2014"); //设备系统名称

json.AddNameValume("driver", "eaglesmartrefrigerator.dll"); //系统驱动程序

json.AddNameValume("downnet", "http://ionfox.com.cn/eaglesmartrefrigerator.dll"); //下载链接

json.AddNameValume("localip", LocalIP); //本机IP地址

json.AddNameValume("devid", "996"); //本设备系统的设备号

json.AddNameValume("time", DateTime.Now.ToLongTimeString()); //广播时间

byte[] data = json.GetBytes();

sockBroadcast.SendTo(data, iep);

nBCCount++;

lbBCCount.Text = nBCCount.ToString();

}

void InitSockBroadcast() //初始化广播

{

if (sockBroadcast != null)

{

sockBroadcast.Close();

sockBroadcast.Dispose();

}

sockBroadcast = new Socket(AddressFamily.InterNetwork, SocketType.Dgram,

ProtocolType.Udp);

iep = new IPEndPoint(IPAddress.Broadcast, (int)nBroadcastPort.Value);//255.255.255.255:50005

sockBroadcast.Bind(new IPEndPoint(IPAddress.Any, (int)nListenPort.Value)); //50006

ep = new IPEndPoint(IPAddress.Broadcast, (int)nListenPort.Value);

sockBroadcast.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, 1);

StartReceiveBroadcast();

}

Thread tReceiveBroadcast; //接收返回数据的线程

private void StartReceiveBroadcast() //启动接收广告消息

{

if (tReceiveBroadcast != null)

{

tReceiveBroadcast.Abort();

Thread.Sleep(50);

}

try

{

tReceiveBroadcast = new Thread(new ThreadStart(ListenBroadcast));

tReceiveBroadcast.Start();

//lbInfo.Text = "正在接收广播...";

//tmListen.Start();

}

catch

{

tReceiveBroadcast = null;

}

}

void ListenBroadcast() //监听广播信息,用于发现智能设备

{

while (true)

{

byte[] data = new byte[10240];

int recv = sockBroadcast.ReceiveFrom(data, ref ep);

if (recv == 0) continue;

stringJson json = stringJson.ConvertBytesTostringJson(data, SmartHomeChannel.SHFLAG);

this.Invoke(new OnProcessBroadcast(ProcessBroadcast), json); //处理接收到服务器回传的数据

}

}

public delegate void OnProcessBroadcast(stringJson json);

string[] AcceptedServer = new string[] { "金鹰智能家居平台","海尔U+智能家居系统","格力智能家居系统" };

void ProcessBroadcast(stringJson json) //处理接收到服务器回传的数据

{

txtInfo.Text = json.ToString();

string recieved = json.GetValume("recieved");

if (recieved == null) return; //1、没被服务器接受,继续广播

//2、判断是否可以接收连接邀请

string server = json.GetValume("server");

if (server == null) return; //意外

if (!AcceptedServer.Contains(server)) return; //服务器不在被信任的服务器列表中

//3、发送连接接收信息

SendInvitedMessage(json); //发送邀请函

//4、开始连接服务器平台(服务器启动SHM可能需要好几秒的时间)

StartConnettion(); //开始连接服务器

}

void SendInvitedMessage(stringJson json) //发送接收邀请信息

{

json.AddNameValume("time", DateTime.Now.ToLongTimeString()); //广播时间

json.AddNameValume("agreen", "ok"); //同意接收邀请

json.AddNameValume("stopbroadcast", "yes"); //停止广播

byte[] data = json.GetBytes();

sockBroadcast.SendTo(data, iep);

nBCCount++;

lbBCCount.Text = nBCCount.ToString();

Thread.Sleep(50);

setting.AppId =int.Parse(json.GetValume("appid")); //保存AppId等信息!

txtIP.Text = json.GetValume("serverip");

lbPort.Text = json.GetValume("port");

lbUser.Text = json.GetValume("user");

lbPassword.Text = json.GetValume("pass");

refrigerator.ServerIP = txtIP.Text;

refrigerator.User = lbUser.Text;

refrigerator.Passsword = lbPassword.Text;

refrigerator.nConnectPort = int.Parse(lbPort.Text);

refrigerator.SaveToFile();

this.Text = string.Format("模拟智能冰箱({0} - {1})", AppId, smarthomechannel.DevicePID);

setting.Save();

}

void StartConnettion() //开始连接服务器

{

if (tReceiveBroadcast != null)

tReceiveBroadcast.Abort();

tmBroadcast.Stop();

sockBroadcast.Close();

lbBCState.Text = "正在连接SHM:" + refrigerator.ServerIP;

if (!MakeConnection(refrigerator.ServerIP, refrigerator.nConnectPort.ToString())) return; //连接失败

lbBCState.Text = "连接SHM成功:" + refrigerator.ServerIP;

}

#endregion

突然觉得好累,写文章暂告一段落。着急写客户端程应用系统,也许在开发客户端程序的时候,有更多的体验,再与各位同行交流。


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐