智能家居通用管理平台(三)-通信方式和数据结构



    一谈到智能家居设备,特别是智能家电,都默认为他们使用WIFI与移动设备(如智能手机)交互。确实,这种方式优点很多,速度快、容量大、传输距离较远。特别是现代家庭,几乎都有 WIFI无线通信网络。硬件成本也大幅下降,可以预测,未来的智能家电,特别是对能耗没有要求的设备(如智能空调、智能冰箱、智能电视),应该是上上之选。蓝牙通信,实质没有变化,用的2.4G频率,只是协议复杂,稳定性较好一点,但传输距离不如人意,如果是别墅豪宅使用,通信就有些问题。
    对能耗要求高的设备系统,基本采用 ZigBee网络组网,最后通过协调器对外交互。现在的通用做法是,把协调器和网关设备集成在一起,把协调器的串口通信转换为TCP/IP方式。这样,对外而言,整个ZigBee网络的设备,看成是一个WIFI智能设备系统。当然,在SHP平台上,也可以直接把协调器的串口通信数据送到家庭服务器,由监控程序SHM负责处理。
    还有很多的智能设备,可能是通过有线的RS485方式通信,简单可靠,能降低设备成本。如智能电表、智能水表、气表。虽说是智能设备,其实“智能化”程度并不高。大部分采用主从通信方式。其状态的获取,得靠监控程序主动去联系获取。为此, SHP专门为这些非智能化设备的接入提供了通用的处理机制。参见ISmartHome中的InitComm接口说明。
    现代家庭,拥有的电脑不止一台,平板、手机可能人手一个。在电脑上,有许多和家庭有关的应用,如家庭影院系统,背景音乐系统,家庭理财软件,这些基本是纯的软件系统。能否把它们也设计成一个设备,统一纳入SHP的管理之下。如果可行,你能想象,那是多么的爽心:用一个手机,在一个APP中就能随心所欲的监控这些软件。还可以与家人聊天,了解正在播放什么电影、播放哪些音乐。 SHP可以接入虚拟设备系统。方法很简单,为这些“设备”编写一个“驱动程序”,使用TCP/IP或进程间通信(IPC)的方式与监控程序SHM交互。使用IPC通信的方式,主要是虚拟设备系统与服务器运行在同一台电脑上运行的情况下使用,比如你也不想专门配一台电脑来做背景音乐系统吧,把音乐系统安装在服务器电脑上即可。
    三种主要通信方式在SHP上都得到了实现,并可以配置。下图是有关窗口通信的配置界面。

     这是对一个非智能设备通信的设置。采用了主从通信方式,更新周期是5秒。这个串口通信对象会传递给驱动程序使用。该对象的定义如下:
namespace SmartHomeMonitor
{
    public class CommParameter
    {
        #region 属性定义
        public string BaudRate { get; set; }
        public string DataBits { get; set; }
        public string ReadTimeout { get; set; }
        public string Parity { get; set; }
        public string StopBits { get; set; }
        public string Handshake { get; set; }
        public string ComportName { get; set; }
        public bool DTR { get; set; }
        public bool RTS { get; set; }
        //public bool bMasterSlave { get; set; }  //主从通信方式否
        //public int Interval { get; set; }    //通信间隔时间

        private string FileName;         //配置文件名
        #endregion
        public CommParameter()  //缺省构造函数
        {
            FileName = "commport.xml";
            //bMasterSlave = true;
            //Interval = 30;  //半分钟通信一次
            InitPara();
        }
        public CommParameter(string _FileName) //带参数,指定参数文件
        {
            FileName=_FileName;
            InitPara();
            LoadParameters();
        }
        private void InitPara() //初始化串口通信参数
        {
            BaudRate = "9600";
            DataBits = "8";
            ReadTimeout = "-1";
            Parity = "无";
            StopBits = "1";
            Handshake = "无";
            ComportName = "COM1";
            DTR = false;
            RTS = false;
        }
        public void LoadParameters() //从文件载入参数
        {
            if (!File.Exists(FileName)) return; //配置文件不存在

            CommParameter tmp = new CommParameter(); //不带参数的构造函数
            //配置文件存在
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(CommParameter));
            try
            {
                using (FileStream stream = File.Open(FileName, FileMode.Open))
                {
                    tmp = xmlSerializer.Deserialize(stream) as CommParameter;
                    //复制过去
                    this.BaudRate = tmp.BaudRate;
                    this.ComportName = tmp.ComportName;
                    this.DataBits = tmp.DataBits;
                    this.DTR = tmp.DTR;
                    this.Handshake = tmp.Handshake;
                    this.Parity = tmp.Parity;
                    this.StopBits = tmp.StopBits;
                    this.ReadTimeout = tmp.ReadTimeout;
                    this.RTS = tmp.RTS;
                    return ;
                }
            }
            catch
            {
                return;
            }
        }
        public void Save()  //保存通信参数信息到文件
        {
            using (FileStream stream = File.Create(FileName))
            {
                XmlSerializer ser = new XmlSerializer(typeof(CommParameter));
                ser.Serialize(stream, this);
                stream.Close();
            }
        }

        public static Parity GetParity(string Paritystring)
        {
            if (Paritystring == "无") return System.IO.Ports.Parity.None;
            else if (Paritystring == "奇") return System.IO.Ports.Parity.Odd;
            else if (Paritystring == "偶") return System.IO.Ports.Parity.Even;
            else if (Paritystring == "掩码") return System.IO.Ports.Parity.Mark;
            else if (Paritystring == "空格") return System.IO.Ports.Parity.Space;
            else return System.IO.Ports.Parity.None;
        }
        public static StopBits GetStipBits(string cbStopBitsText)
        {
            if (cbStopBitsText == "1") return System.IO.Ports.StopBits.One;
            else if (cbStopBitsText == "2") return System.IO.Ports.StopBits.Two;
            else if (cbStopBitsText == "1.5") return System.IO.Ports.StopBits.OnePointFive;
            else return System.IO.Ports.StopBits.One;
        }
        public static Handshake GetHandshake(string cbHandshakeText)
        {
            if (cbHandshakeText == "无") return System.IO.Ports.Handshake.None;
            else if (cbHandshakeText == "XOnXOff") return

System.IO.Ports.Handshake.XOnXOff;
            else if (cbHandshakeText == "请求发送") return

System.IO.Ports.Handshake.RequestToSend;
            else if (cbHandshakeText == "请求发送XONXOFF") return

System.IO.Ports.Handshake.RequestToSendXOnXOff;
            else return System.IO.Ports.Handshake.None;
        }    
    }
}
    由于串口设备,大部分是单片机系统,实现复杂的数据格式通信有困难,所以它与SHM的交互,信息的解释,都由其驱动程序做转换,因此都是专用的数据格式。
    对于智能门锁这样的设备,使用TCP/IP通信协议工作。我们对其通信端口做了设置。另外,为了防止未授权设备随意访问监控程序SHM,还设置了密码和账号验证,在PNP章节在介绍这个机制的实现。连接后必须验证密码,否则断开连接。下图是对智能门锁TCP/IP通信的设置。由于未使用串口通信,我们取消了他的串口通信方式。设备信息,门锁会自动发送过来,所以“主从通信方式”也取消了。

    由于此类通信,是未来的主流。SHP专门写了一个对象来帮助简化TCP/IP通信。以下是该对象的部分内容(内容较多,省略了)。
using HomeLibrary.ShareMemory;
using HomeLibrary.Json;
using HomeLibrary.Type;
namespace SmartHomeMonitor
{
    public delegate void OnTextReceived(TextReceivedEventArgs<string> e);
    public delegate void OnDataReceived(TextReceivedEventArgs<byte[]> e);
    public class TextReceivedEventArgs<T> : EventArgs
    {
        public TextReceivedEventArgs(ConnectClient tcpClient, T datagram)
        {
            TcpClient = tcpClient;
            Datagram = datagram;
        }
        public ConnectClient TcpClient { get; private set; }
        public T Datagram { get; private set; }
    }

    public class ConnectClient
    {
        int MaxBufferSize = 0x100000;  //1M
        public event OnTextReceived OnTcpTextReceived;
        public event OnDataReceived OnTcpDataReceived;
        public bool Connected { get { return m_tcpClient.Client.Connected; } }
        List<ConnectClient> Clients;

        public TcpClient m_tcpClient;
        public Int32 flag;
        public string IP;
        public string rights;   //权限字符串,可用于各种目的
        public string User;     //登记用户名
        public bool canComunication;  //是否可以正常通信了
        public int illComunication;   //非法通信次数,当减为0时,断开连接;
        NetworkStream ns;
        Encoding encoding = Encoding.Default;
        public ConnectClient(TcpClient tc, int TimeoutMs, int _Flag,Encoding encoding,

        List<ConnectClient> Clients)
        {  …… }

        ......
   }
}
     为了规范各厂家设备数据通信格式,我们设计了有一个通用通信数据对象stringJson,它比目前在互联网通信中流行的Json 结构简单,但更加灵活。其实质是维护着一个字典结构Dictionary<string, byte[]>, 由于“值”是字节数组,可以存储任意内容。该对象提供了很多方法来简化使用字典对象。下面的是它的全部内容,免费开放。
namespace HomeLibrary.Json
{
    public class stringJson
    {
       public Dictionary<string, byte[]> mDictionary = null;
       Int32 flag = 0xAA11;  //某公司通信的标志,不是的,不处理

       public stringJson()
       {
           mDictionary = new Dictionary<string, byte[]>();
           flag = SmartHomeChannel.SHFLAG;  //我们智能家居系统的标志
       }
       public stringJson(Int32 _flag)
       {
           mDictionary = new Dictionary<string, byte[]>();
           flag = _flag;
       }

       public void Clear()
       {
           if (mDictionary != null)
               mDictionary.Clear();
       }
       public void AddNameValume(string name,string valume)
       {
           mDictionary[name] = Encoding.UTF8.GetBytes(valume);
       }
       public void AddNameValume(string name, char[] valume)
       {
           mDictionary[name] = Encoding.UTF8.GetBytes(valume);
       }
       public void AddNameValume(string name, Stream valume)
       {
           byte[] buffer=new Byte[valume.Length];
           valume.Read(buffer,0,(int)valume.Length);
           mDictionary[name] = buffer;
       }
       public void AddNameValume(string name, byte[] valume)
       {
           mDictionary[name] = valume;
       }

       public void DeleteName(string Name)
       {
           if (mDictionary.Keys.Contains(Name))
               mDictionary.Remove(Name);
       }

       public string GetValume(string Name)
       {
           if (mDictionary.Keys.Contains(Name))
           {
               char[] s = Encoding.UTF8.GetChars(mDictionary[Name]);
               return new string(s);
           }
           else return null;
       }
       public byte[] GetValumeArray(string Name)
       {
           if (mDictionary.Keys.Contains(Name))
               return mDictionary[Name];
           else return null;
       }

       public string[] GetNames()
       {
           return mDictionary.Keys.ToArray(); 
       }

       public override string ToString()
       {
           string result = "";
           foreach (string Name in mDictionary.Keys)
           {
               result += Name + "=" + GetValume(Name) + "\r\n";
           }
           return result;
       }
       //根据编码返回便于发送的字节数组
       public byte[] GetBytes()
       {
           MemoryStream stream = new MemoryStream();
           BinaryWriter bw = new BinaryWriter(stream,Encoding.UTF8);  //二进制写入:2015-5修改by吴志辉
           //---先写入标志
           bw.Write(flag);     // 4字节
           bw.Write((int)0);   // 先写入一个占位符,表示整个字节流的长度 4字节
           //---首先写入字典的条目数
           bw.Write(mDictionary.Count);     //先写入长度 4字节
           foreach (string Name in mDictionary.Keys)
           {
               bw.Write(Name);  //先写入键名
               byte[] buffer = mDictionary[Name];  //键值
               bw.Write(buffer.Length);            //先写入键值的长度
               stream.Write(buffer, 0, buffer.Length);  //再写入数据
           }
           //byte[] result = stream.ToArray();
           bw.Seek(sizeof(Int32), SeekOrigin.Begin);
           bw.Write((int)stream.Length);   // 最后先写入整个字节流的长度 4字节
           bw.Seek((int)stream.Length, SeekOrigin.Begin); //必须重新定位到最后!
           byte[] result = stream.ToArray();
           bw.Close();
           bw.Dispose();
           stream.Dispose();
           return result;
       }

       public void ReadFromBytes(byte[] buffer, Int32 _flag)
       {
           mDictionary.Clear();
           if (buffer.Length < 8) return;            //有问题,至少8个字节长度
           MemoryStream stream = new MemoryStream();
           stream.Write(buffer, 0, buffer.Length);      //转移到流中处理
           stream.Position = 0;
           BinaryReader br = new BinaryReader(stream, Encoding.UTF8);  //二进制流读取:2015-5修改by吴志辉
           //---首先读取标志 
           int len = br.ReadInt32();
           #region 合法性检查
           if (_flag != len)
           {
               br.Close();
               br.Dispose();
               stream.Dispose();
               return;   //非系统通信数据或乱码、断码
           }
           len = br.ReadInt32();            //总的字节数
           if (buffer.Length < len)          //长度不对,直接退出
           {
               br.Close();
               br.Dispose();
               stream.Dispose();
               return;   //非系统通信数据或乱码、断码
           }
           #endregion
           int counts = br.ReadInt32();            //---首先读取字节中包含字典的条目数counts    
           int count = 0;
           try
           {
               while (count < counts)
               {
                   count++;
                   string Name = br.ReadString();         //键名
                   len = br.ReadInt32();                  //键值的长度
                   byte[] destBuffer = br.ReadBytes(len);
                   mDictionary[Name] = destBuffer;   //添加一个项
               }
           }
           catch { }
           br.Close();
           br.Dispose();
           stream.Dispose();
       }
       public static stringJson ConvertBytesTostringJson(byte[] buffer,Int32 _flag)
       {
           if (buffer.Length<8) return null;            //有问题,至少8个字节长度
           MemoryStream stream = new MemoryStream();
           stream.Write(buffer, 0, buffer.Length);      //转移到流中处理
           stream.Position = 0;
           BinaryReader br = new BinaryReader(stream, Encoding.UTF8);  //二进制流读取:2015-5修改by吴志辉
           //---首先读取标志 
           int len = br.ReadInt32();
           #region 合法性检查
           if (_flag != len)
           {
               br.Close();
               br.Dispose();
               stream.Dispose();
               return null;   //非系统通信数据或乱码、断码
           }
           len = br.ReadInt32();            //总的字节数
           if (buffer.Length< len)          //长度不对,直接退出
           {
               br.Close();
               br.Dispose();
               stream.Dispose();
               return null;   //非系统通信数据或乱码、断码
           }
           #endregion
           int counts = br.ReadInt32();            //---首先读取字节中包含字典的条目数counts    
           int count = 0;
           stringJson json = new stringJson(_flag);
           try
           {
               while (count < counts)
               {
                   count++;
                   string Name = br.ReadString();         //键名
                   len = br.ReadInt32();                  //键值的长度
                   byte[] destBuffer = br.ReadBytes(len);
                   json.mDictionary[Name] = destBuffer;   //添加一个项
               }
           }
           catch { }
           br.Close();
           br.Dispose();
           stream.Dispose();
           return json;  //返回stringJson结构
       }
    }
}
    在大量的网络通信任务中都使用该数据结构,如果您对SHP感兴趣,必须了解其使用方法。在进程间通信,也使用了该对象。
    本节内容较多了,介绍到此。下节继续介绍SHP的进程间通信机制。



 



中国电博会 2020第十九届北京国际智能家居博览会 2020 Th19 Beijing International Smart Home Expo 时间:2020年06月30日-7月2日 地点:北京亦创国际会展中心(中国智造2025展示中心) 批准单位:中华人民共和国商务部 主办单位:中国消费电子协会、森展展览集团 协办单位:创智能机器人产业研究院、北京信息产业协会 北京电子电器协会 新闻机构:千龙网 PP聚力 手机之家 美通社 承办单位:森展国际展览有限公司 <<<市场前景: 2020中国成亚洲最大智能家居市场   近年来中国已经成为全球增长的关键推动力之一。首先,整体经济的快速增长带来家庭收入水平增加;其次,中国成为全球最大的互联网市场。这两大因素使得智能家居市场快速发展。 中国或将在2020年前成为亚洲最大的智能家居市场,全球智能家居的整体规模将由目前的100亿美元增长至500亿美元,并有望在2030年增至4000亿美元。到2030年,亚洲市场销售额将超过1150亿美元,占据全球市场25%以上的份额。 <<<展会概况: 北京国际智能家居博览会(以下简称CEE)是森展国际展览有限公司旗下的知名展览品牌,系第十九届北京电博会主题展之一,于2002年创办,行业号称630北京智能家居展,CEE是亚洲顶尖的高新技术产品及解决方案的展示平台之一,旨在打造具有国际水平和影响力的行业盛会,最前沿的新技术、新产品、新应用、新理念将在CEE得到集中展示,打造更具前瞻性的“智慧生活 全球平台”每年6月在北京举行,已连续成功举办18届。 作为中国智能家居展会的风向标,第十八届北京国际智能家居博览会(CEE 2019)吸引了全球50362名参会人员亲临CEE体验各种创新技术和产品,36个国家和地区的 600 +参展公司展示了26大产品类别,展览面积突破38000㎡无论从展出规模还是买家数量都创历届新高。 CEE2019吸引了国际知名参展企业有珠海格力、欧姆龙中国、中国航天、卓立能科技、YOOZ、指芯智能、科士达股份、麦杰科技、新宝电器、中国有赞、钱客多、飞利浦、朗通科技、西人马、艾宝沃、赛瓦科技、驿通智能、蜂鸟创新、壹傲智能、视贝科技、知伴科技、熊猫刷牙、日立丰、未来智能、阿妞科技、京东X、欣视达、新日升、麒麟智能、星、联想集团、中信、纽文等知名企业,为展商和专业观众献上了一场专业性与参与性高度融合的行业交流盛宴。 展会有北京TVB、中央四套、人民日报、中国日报、第一财经日报、华尔街日报及新华网、新浪、搜狐、腾讯、网易、凤凰、中国网、人民网等国内外上百家媒体报道。 第十九届北京国际智能家居博览会(CEE2020),将于2020年6月30日-7月2日继续在北京亦创国际会展中心举办,欢迎您届时参观参展! <<<展馆优势: 亦创国际会展中心作为北京“中国智造2025”的长期展示中心,以“会、展、赛、创”有机融合为特色,已然形成京南最具特色的高端产业国际展示、交流平台。 亦创国际会展中心依托于智能机器人产业新高地——亦创智能机器人创新园,承接着中国目前智能机器人领域规格最高规模最大的国际性行业盛会——世界机器人大会。作为“制造业皇冠上的明珠”,智能机器人已成为世界各国推动工业革命的主力军,亦创国际会展中心以亦创智能机器人创新园为基础,打造全球机器人展示交流中心、技术和产品交易中心,为构建首都高精尖经济结构提供重要支撑。 <<<观众类别: CEE会的参会人员主要来自中国以及亚洲各地的消费科技行业,包括9720名高管、16029名采购人员,以及其他国际买家、连锁商超、百货公司、投资加盟商、零售商、分销商、金融、医疗、工程师、教育、政府部门、投资、孵化机构、媒体、科研机构、大众消费者、工程研发者、市场分析师、行业协会具有影响力的人士以及全球知名企业C级别以上的高层管理人员。将亲身感受到CEE在推动创新以及帮助企业进行品牌推广方面 所带来的巨大影响。 <<<企业荣誉: 为了鼓励企业科技创新,树立国内高端电子产品诚信品牌,打造高端电子产品形象,促进行业健康发展。北京国际智能家居博览会组委会,拟评选出一批诚信经营、技术先进、品质优良的品牌企业及产品,并与博览会期间颁发荣誉奖项。 本届展会设置奖项内容:(参展商资质审核通过即获得评选资格) ◇北京国际智能家居博览会金奖 ◇优秀企业家奖 ◇科技创新奖 ◇十大创新型智能产品 ◇物联网应用奖 ◇自拟奖项:企业可根据产品自身优势和定位自拟奖项 <<<展会优势: ◆中国唯一由商务部批准的国家级智能家居专业性展示平台; ◆100多家海内外协会保驾护航,买家数量&高品质保证; ◆同期举办重量级峰会、政策法规宣讲会、新技术新产品发布会、科技创新系列评奖活动等,会议精彩多元化,并让您面对面接触行业前沿动态; ◆38000 ㎡展览面积、600+行业品牌、36+国家和地区、70000 名专业观众 ; ◆国际性权威主办、专业展会运作、丰富的展会资源、权威的专业论坛以及展商“一对一”买家组织优势,创造全球联通中外消费电子产业交流、融合、发展、共赢的行业盛会。 <<<展品类别: ◆整体智能家居: 控制主机、电器控制系统、智能照明控制系统、智能遮阳系统、暖通空调系统、智能家居软件、家庭网络系统、智能面板/插座、智能睡眠与健康监测、智能硬件产品、花草自动浇灌、家庭机器人、云平台等 ◆智能安全防护: 智能门锁、防盗报警系统、视频监控系统、家居布线系统、自动抄表、智能(电子)猫眼、智能摄像头、报警探测器等 ◆智能娱乐产品: 家庭背景音乐系统、家庭影院系统、智能路由器、智能盒子、智能音响等 ◆智慧社区: 社区主机、楼宇对讲系统、智慧养老、智能门禁系统等 ◆智能生活科技: 智能晾衣架、智能扫地机、智能遥控器、智能电视、智能厨卫、家庭净化器、智能灯、智能投影仪、智能坐便器、智能按摩椅等 <<<参展程序: 1、展位安排将以“先申请、先付款、先确认”的原则。填写申请及合约表,加盖公章后传真或邮寄至组委会,申请表一经签字盖章后同具合同效力,传真或复印件有效。 2、递交参展申请表后五个工作日内请将参展费款项汇入组委会逾期展位将不予保留。 3、组委会收到参展申请表及参展款项后,于一周内回复展位预订确认函,并于2020年6月1日前发出《参展指南》。 4.组委会根据会场的整体效果和安全消防的需要,有权调整部分已确认展位。 <<<会务联络: 北京国际智能家居博览会组委会办公室 地 址:北京市朝阳区朝阳路71号锐城国际大厦9层 邮编:100123 企业 QQ:2853630956 会务联络:秦 姗 137 1682 0023 电子邮件:qs@senexpo.cn 项目网站:www.ciftiscn.com
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值