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

    即插即用机制,对智能家居的推广,非常重要。没有她,老百姓估计不会使用。

    好了,现在有了“智能冰箱”和它的驱动程序,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
突然觉得好累,写文章暂告一段落。着急写客户端程应用系统,也许在开发客户端程序的时候,有更多的体验,再与各位同行交流。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值