智能家居云平台设计

 

智能家居是未来家居的发展方向,其利用先进的网络技术、计算机技术和无线通信技术等将家居中的各种电子电气设备连接起来,统一管理、远程监控和资源共享,实现了高效、便利的生活环境。近些年互联网的迅猛发展,网络的稳定性、安全性和网络带宽都有了长足的发展,由互联网提供的各种服务已经深入到人们生活的方方面面,因此将智能家居系统同互联网结合起来,为用户提供远程控制服务,延伸智能家居系统的使用空间,已经成为智能家居系统发展的一种趋势。

基于此背景,本文设计了用于协作控制终端和智能家居网关实现智能家居远程监控功能的云平台。论文首先阐述了智能家居的概念及发展趋势,分析了智能家居云平台所涉及的关键技术。通过对无线智能家居系统结构的调研和了解,进行了智能家居云平台的需求分析。通过分析现有的较成熟的物联网云平台,并结合智能家居网关和控制终端的特点,最终确定了智能家居云平台的设计方案:采用应用层的HTTP协议作为通信协议,JSON格式作为云平台响应数据格式,通过PHP编程,实现了云平台的基本功能和RESTful风格的API然后,结合设计方案,开始搭建系统开发环境,进行数据库设计和系统环境配置。最终结合需求分析,在已搭建好的环境中,使用PHP完成智能家居云平台的功能设计。

 

关键词:智能家居,云平台,物联网

 


 

Abstract

The Smart Home is the future direction of home life. It takes advantage of networking technology, computer technology and wireless communication technology to connect all kinds of electronic and electrical equipment at home to realize the unified management, remote monitoring and resource share, making the life more efficient and more convenient. With the rapid development of Internet in recent years, the stability of the internet and network bandwidth had great development, the Internet provide all kinds of service of all aspects of people's lives, so smart home system combined with the Internet, to provide remote control service, extend the smart home system, use the space, it has become a development trending of smart home system.

Considering to this situation, the paper designs the smart home cloud platform used to assists control client and web control platform to implement the functionality of the remote control of smart home system. In this paper, we first introduce the basic concept and the development trending of Smart Home, and then analyze the related important technologies of the smart home cloud platform. By the research and understanding of the wireless smart home system, we execute the analysis of the demand of the smart home cloud platform. Through analyzing the stable cloud platform and combining the feature of smart home gateway and control client, we finally conclude the detailed design scheme of the platform: using HTTP protocol as communication protocol, JSON format as response data format, through PHP programming, implement all basic function of the Cloud Platform and RESTful style API. And combining the design scheme, we start building of the system development environment, designing the structure of the database and configuring the system. Finally, combining the analysis of the demand, in the built environment, use PHP to accomplish the functional design of the smart home cloud platform.

 

Keywords: Smart Home, Cloud Platform, Internet of Things

 

 

 

  ... I

Abstract. II

1 绪论... 1

1.1 课题背景及来源... 1

1.2 智能家居概述及研究现状... 1

1.3 智能家居云平台关键技术... 3

1.4 课题的研究目标与主要内容... 5

2 智能家居云平台设计方案与相关技术简介... 7

2.1 需求分析... 7

2.2 通信协议分析... 7

2.3 数据交互格式... 9

2.4 基本设计方案... 10

2.5 系统配置... 11

2.6 相关技术简介... 12

3 智能家居云平台系统设计... 17

3.1 数据库设计... 17

3.2 PHPRESTful API设计过程... 21

3.3 开发环境配置... 23

4. 智能家居云平台功能实现... 29

4.1 用户类... 29

4.2 设备类... 31

4.3 传感器类... 33

4.4 数据点类... 36

4.5 辅助接口... 40

5 系统测试及结果分析... 41

5.1 云平台系统测试要求... 41

5.2 云平台系统测试方法... 41

5.3 云平台请求和响应报文分析... 43

5.4 云平台测试结果... 45

5.5 云平台测试结果分析... 49

6 总结与展望... 50

6.1 工作过程总结... 50

6.2 不足及展望... 50

参考文献... 53

 

 

 

1 绪论

1.1 课题背景及来源

网络的广泛普及和通信技术的高速度发展,给如今的社会带来了数字化和信息化的改变。信息化从20世纪80年代开始就渗透到社会的各个领域并加快了各行各业的发展,如今科研、国防、商务、金融、企业管理和办公都已经离不开网络和信息技术。通过信息的传递实现社会、家居生活和人的融通,这是人们实现更高标准的生活的途径,也是信息社会发展的必然。

近年来,物联网成为全球关注的热点领域,被认为是继互联网之后最重大的科技创新。物联网通过射频识别(RFID)、红外感应器、全球定位系统、激光扫描器等信息传感设备,按约定的协议把任何物品与互联网连接起来进行信息交换和通讯,以实现智能化识别、定位、跟踪、监控和管理。

物联网是互联网的延伸,M2M是当前的主要应用。物联网的远景目标是把所有物品连接到互联网,组成一个超大的智能网络。通俗地说,物联网是让一切物品连上网络,物品之间可以直接对话和自动反应,这样人们可以在任何时间、任何地点、任意地了解到任何物品的状况,并且可以进行有效的控制。物联网的发展为智能家居引入了新的概念及发展空间,智能家居可以被看作是物联网的一种重要应用。

本课题来源于实际企业无线智能家居系统的需求。该系统致力于结合物联网技术及其它无线传输技术(ZigbeeRFIDWIFI、蓝牙),实现对智能家居设备的无线控制和智能管理。系统由智能家居设备、智能家居嵌入式网关、智能家居云平台、智能家居Web平台和智能家居控制终端(手机等智能设备)组成。

其中智能家居云平台作为数据存储与交换的平台,需要协同嵌入式网关和控制终端、Web平台进行数据传输与通信控制,实现对智能家居设备运行状况的记录,并辅助控制终端和Web平台完成对智能家居设备的远程控制。

 

1.2 智能家居概述及研究现状

智能家居概念的起源于20世纪80年代初,随着大量采用电子技术的家用电器面市,住宅电子化开始实现;80年代中期,将家用电器、通信设备与安全防范设备各自独立的功能综合为一体,又形成了住宅自动化概念;至80年代末,由于通信与信息技术的发展,出现了通过总线技术对住宅中各种通信、家电、安防设备进行监控与管理的商用系统,这在美国被称为Smart Home,也就是现在智能家居的原型。

当前的智能家居就是以住宅为平台,集网络通信、网络系统和自动化控制于一体,通过互联网技术将家庭设备联系成家庭网络,实现远程操控,为人们提供了舒适安全高效和便利的生活居住环境。

目前智能家居在欧美等发达国家得到广泛应用。但是从严格意义上来说,智能家居还是处于刚刚启动的探索阶段。美国的智能家居主要体现在追求舒适、豪华感和享受上,它是以数字技术改造而展开的,但非常消耗能源。日本的智能家居主要体现在注重功能、以人为本、环境保护与兼顾未来发展等几个方面。而且日本的智能家居还注重施工过程的集团化与规模化,在设计施工中大量采用新技术新材抖。德国的智能家居体现在注重基本的功能性和追求专项功能的开发等方面。韩国的智能家居得到政府的多项政策扶持,行政规定在首尔等大城市的新建的生活小区必须具备智能家居体系。中国智能家居的发展在经历了很长时间的探索阶段之后,国内的各具特点的智能家居系统也由各大家电巨头生产商和通信服务商纷纷推出。智能家居业得到国内各大城市的政府部门的大力扶持,将智能家居体系包含到城市发展规划中大大促进智能家居行业的发展。

智能家居行业热点一波又一波,万物互联互通(即IOEinternet of everything)成了当下智能化的标准。互联互通是指智能家居不受品牌,功能的约束,自动建立联系,收发数据信息,自动完成指令。实现这些功能的关键点是统一的云平台。虽然很早就有云平台建设,部分企业亦投身到云平台建设,但一直没有突破。

面对当下智能家居互联互通的新趋势,云平台作为信息储存传输的纽带,扮演着重要角色。云是物联网的基础,而统一的云平台可兼容各种先进技术,以满足客户需求为主,不受品牌的约束,集结各路优秀方案,在最短的时间内,使用户得到极致的体验。智能家居作为物联网的重要分支,智能家居的云平台也是物联网云平台的重要应用。

现今较成熟的物联网云平台有“Yeelink云平台”、“飞比云平台”和“Ninja Platform”等。这些云平台将API公开给开发者,为开发者提供数据处理和存储服务。而开发者通过给定的API,用相应的方法将自己的设备信息传递到云端进行处理,实现对设备的监控。

其中Ninja Platform以其自身的产品Ninja Block(智能家居网关)为核心,将智能家居设备通过Ninja Block组成一个统一的整体,再连接到Ninja Platform实现远程监控。Ninja Platform只支持自己的网关产品的接入,并且隐藏了网关与平台连接的细节,只是简单地提供一个接口用于连接。因为只支持自己的网关产品的接入,可以实现很多复杂的控制细节,并且这些完全由自身控制。因此,Ninja Platform在功能上显得十分丰富,逻辑也十分合理,安全性也做的很好,更接近于一个完善的商业产品。而其开放API的意义在于,使用Ninja Block的用户可以通过使用这些API进行自己的控制终端的开发,用于实现一些自己希望的功能和扩展。

相比Ninja Platform,国内的Yeelink云平台的功能显得有些简陋。但Yeelink云平台的特点还是很明显的:他是一个几乎完全开放的物联网云平台。虽然Yeelink云平台也有自己的设备提供,但它也支持其它设备的接入,这些接入的设备也不限制于家居网关。所有能够实现HTTP请求方法的设备,甚至一个实现HTTP请求的程序,都可以连接到Yeelink云平台,作为被控对象。Yeelink云平台的API显得更加抽象,所有具体的功能都抽象成对数据的操作。

 

1.3 智能家居云平台关键技术

云计算(英语:Cloud Computing),是一种基于互联网的计算方式,通过这种方式,共享的软硬件资源和信息可以按需求提供给计算机和其他设备。目前关于云计算系统没有统一的定义,云计算供应商根据自己企业业务推出相关的云计算战略。维基百科给云计算下的定义为:云计算将IT相关的能力以服务的方式提供给用户, 允许用户在不了解提供服务的技术、没有相关知识以及设备操作能力的情况下,通过Internet获取需要的服务[9]

云计算的基本原理是,通过虚拟化技术使计算分布在大量的分布式计算机上,这使得企业能够将资源切换到需要的应用上,根据需求访问计算机和存储系统。

我们可以把实际环境中的“云”提供的服务分为三大类。它们是:

软件即服务(Software as a serviceSaaS):SaaS应用是完全在“云”里(也就是说,一个Internet服务提供商的服务器上)运行的。其户内客户端(on-premises client)通常是一个浏览器或其他简易客户端。Salesforce可能是当前最知名的SaaS应用,不过除此以外也有许多其他应用。

附着服务(Attached services):每个户内应用(on-premises application)自身都有一定功能,它们可以不时地访问“云”里针对该应用提供的服务,以增强其功能。由于这些服务仅能为该特定应用所使用,所以可以认为它们是附着于该应用的。一个著名的消费级例子就是苹果公司的iTunes:其桌面应用可用于播放音乐等等,而附着服务令用户购买新的音频或视频内容成为可能。微软公司的Exchange托管服务是一个企业级例子,它可以为户内Exchange服务器增加基于“云”的垃圾邮件过滤、存档等服务。

云平台(Cloud platforms):所谓云平台,一般理解为云计算平台,为用户提供云计算服务。这种平台允许开发者们或是将写好的程序放在“云”里运行,或是使用“云”里提供的服务,或二者皆是。云平台提供基于“云”的服务,供开发者创建应用时采用。你不必构建自己的基础,你完全可以依靠云平台来创建新的SaaS应用。云平台的直接用户是开发者,而不是最终用户。

1.1 云计算架构

 

物联网被称为继计算机、互联网之后,世界信息产业的第三次浪潮。目前多个国家都在花巨资进行深入研究,物联网是由多项信息技术融合而成的新型技术体系。“物联网”的概念于1999年由麻省理工学院的Auto-ID实验室提出,将书籍、鞋、汽车部件等物体装上微小的识别装置,就可以时刻知道物体的位置、状态等信息,实现智能管理。

20051117日,在突尼斯举行的信息社会世界峰会(WSIS)上,国际电信联盟(ITU)发布了《ITU互联网报告2005:物联网》,正式提出了“物联网”的念。报告指出:无所不在的“物理网”通信时代即将来临,世界上所有的物体都可以通过互联网主动进行信息交换。射频识别技术(RFID)、无线传感器网络技术(WSN)、纳米技术、智能嵌入技术将得到更加广泛的应用。

可以认为,“物联网”(Internet of Things)是指将各种信息传感设备及系统,如传感器网络、射频标签阅读装置、条码与二维码设备、全球定位系统和其它基于物物通信模式(M2M)的短距无线自组织网络,通过各种接入网与互联网结合起来而形成的一个巨大智能网络。如果说互联网实现了人与人之间的交流,那么物联网可以实现人与物体的沟通和对话,也可以实现物体与物体互相间的连接和交互。

1.2 物联网概念模型

 

物联网就是互联网通过传感网络向物理世界的延伸,它的最终目标就是对物理世界进行智能化管理。物联网的这一使命,也决定了它必然要由一个大规模的计算平台作为支撑。由于云计算从本质上来说就是一个用于海量数据处理的计算平台,因此,云计算技术是物联网涵盖的技术范畴之一。随着物联网的发展,未来的物联网将势必产生海量数据,而传统的硬件架构服务器将很难满足数据管理和处理要求。如果将云计算运用到物联网的传输层与应用层,采用云计算的物联网,将会在很大程度上提高运行效率。可以说,如果把物联网当作一台主机的话,云计算就是它的CPU

云计算与物联网各自具备很多优势,如果把云计算平台与物联网结合起来,就构造成物联网云平台。该平台通过物联网技术将传感器连接到一起,再通过云计算的技术对数据进行分布式存储与处理,由此能克服大规模的数据存储与计算问题,完善了物联网的构成。就本课题而言,智能家居云平台在功能上更接近于物联网云平台。智能家居云平台将数据存储和处理服务置于云端,通过相应接口提供智能家居设备的相关监控服务。

 

1.4 课题的研究目标与主要内容

为了实现智能家居的远程控制,控制终端需要同家庭网关进行通信,将控制命令发送给网关。然而,每个家庭接入网络的类型不尽相同,在中国的家庭用户中则以ADSL技术为主。而且,由于ISP提供的接入服务也不尽相同,大多数家庭接入互联网时,使用的是服务商提供的动态IP。由于目标的IP地址动态变化,这会给控制终端同家庭网关的通信造成了很大的不便。

本课题提出的目的之一,就是通过为了建立云平台来克服这种不便,消除网络接入方式的不同而造成的差异,实现智能家居设备的远程管理和控制。

另一方面,为了智能家居Web控制平台的实现,也需要智能家居云平台的建设。如果将数据存储和处理置于智能家居网关内,或另外实现嵌入式服务器,毫无疑问将加大智能家居设备的成本,也加大了开发难度,不利于商业推广。而建立云平台之后,不仅利于Web平台的实现,还能将功能集中,方便系统开发与服务升级。只要保证云平台基本API不变,云平台内部的功能可以很方便的进行开发和升级。而对于嵌入式设备(智能家居网关等),一旦生产出来,由于硬件方面的限制,只能进行有限的软件更改;而一旦售出之后,更难进行全面系统的修正。

本课题中的智能家居云平台将结合HTTP协议使用PHP进行程序开发,实现最基本与核心的数据存储和处理,并完成系统的测试。

 

 

 

2 智能家居云平台设计方案与相关技术简介

2.1 需求分析

智能家居云平台是为了实现智能家居系统的远程监控而搭建的。智能家居网关必须接入互联网,并且按照一定的格式将被控设备的状态信息实时发送给云平台,才能保证信息的实时性。云平台处理数据之后,将之暂时保存在数据库中。当终端访问云平台时,云平台能够将设备的数据提供给终端,终端以可视化的形式展现给用户。云平台要求能接受终端发出的控制命令,将之保存并转发给家居网关,完成对设备的控制。

虽然该课题中的云平台并不是直接面向用户,但设计时也要为考虑到用户的需求,这样才能保证方案的可行性。

云平台要实现的最终的功能是对智能家居设备的监控:

(1)     接受智能家居网关发送设备的状态信息,并进行处理和存储;

(2)     接受控制终端的请求,返回设备的状态信息;

(3)     协调控制终端和智能家居网关之间控制命令的交互。

 

云平台更具体的功能则类似于一般的信息管理系统:

(1)     用户认证:设备都有自己的归属,用户只能控制自己的设备,只有通过认证之后才能查看和控制设备;

(2)     设备管理:应该允许用户自己添加需要的设备,移除不再需要的设备;

(3)     运行记录(或称历史记录):所有的监控系统都应该记录设备的运行状态。

对于开发者而言,为了运行维护的方便,错误日志功能是必须的。无论是记录在数据库中还是以文件的形式保存,都要能将相应的错误时间和错误信息记录下来,以供调试和测试时查看。

 

2.2 通信协议分析

网络协议是分层的,其中应用层协议主要是解决网络中通信双方应采用哪种数据传输规则来实现数据收发的,即定义了网络中两个通信进程之间交互数据应遵循的规则。大部分的应用层协议都是为了解决某一类具体应用而存在的。

在网络数据通信中,应用层常见的数据传输标准协议主要有:HTTPHypertext Transport Protocol,超文本传输协议),IMInstant Message,即时通信)协议,FTPFile Transfer Protocol,文件传输协议)协议,SMTPSimple Mail Transfer Protocol,邮件传输协议),远程登陆协议Telnet等。

文件传输协议FTP,主要用于解决异构网络中文件资源的传输,能够提供可靠的文件传输,消除不同操作系统或者不同文件系统互不兼容的缺点,从而实现文件资源的共享。

邮件传输协议SMTP,是为了解决实时通信的不足而产生的,传输层采用的协议是TCP协议,采用的默认端口是25,邮件发送和接收整个过程需要用到的邮件传送协议和POP3,其中前者主要完成将邮件上传至服务器和在服务器之间传送邮件,而后者主要完成接收端的接受任务。

远程登录协议Telnet主要用于实现本地用户登录远程系统,采用半双工的方式实现对远程资源的访问,本地客户端实现对远程主机的访问必须做到下列要求:本地客户端支持远程登陆协议、正确输入远程主机系统的IP地址、正确输入登录主机名称与登录密码。

即时通信协议IM,能够实现网络用户的实时通信,传输的数据包括文字、图片、视频、音频等。通信的过程是:客户端要完成注册并添加通信另一客户端为通信好友,随后才能进行双方的通信。比较著名的即时通信协议有:IMPPSIMPLEJabber/XMPP

超文本文档传输协议HTTP,定义了数据传输的格式和传输时应遵循的规则,传输层采用TCP面向无连接的方式进行数据传输的。该协议是通过请求应答机制来实现的,能够可靠的传输包括文档、图片、视频等所有数据。该协议多用于浏览器与WEB服务器之间的交互,在某些客户端软件中也经常使用。

在智能家居系统中,直接负责对家居设备的控制的是家庭网关。云平台则是为了实现控制的空间上的扩展而搭建,需要考虑的是怎么把网关处理的设备的信息简单高效的接收过来进行处理,又如何高效的将控制终端的控制命令简单高效的发送给网关处理。

智能家居系统中的家庭网关大多为嵌入式网关,并且已经移植TCP/IP协议,能通过发送HTTP报文与云平台进行通信。而控制终端设定为安卓手机,有专门的应用实现智能家居系统的监控,同云平台之间的通信也可以通过HTTP报文的实现。

这样,云平台以WEB服务器的方式进行开发可以带来很多便利。在初期的开发时,只需要专注于数据的处理和传输即可,不必去设计专门的WEB页面。虽然使用WEB技术实现用户界面很简单,但要使得界面交互良好,给用户带去完美的用户体验,则需要涉及很多网页方面的技术,如JavaScriptCSS等。在本课题中,重点在于云平台功能的实现,所以不涉及页面的设计。

云平台与控制终端和家庭网关之间的通信还可以通过socket编程来实现,而且在服务器实现socket通信的方式也有很多选择,JavaC语言都可以实现,甚至PHP也有socket的接口函数。使用socket,网关和终端与服务器之间建立的是长期的连接,实时性较好。

云平台以WEB服务的方式进行开发时,则可以通过网关定时发送HTTP报文的方法来更新云平台上记录的设备信息。通过调整改变发送报文的间隔,就可以达到不同的实时性的要求了。

 

2.3 数据交互格式

对于本课题的云平台而言,需要一种结构化的描述语言作为数据格式,用以承受结构明确的请求数据和返回数据。

通过调研现有的物联网云平台的设计方案以及API设计,能够发现现有的几个成熟的云平台都在使用JSON作为数据交互格式。并且在移动端的应用中,JSON也是作为数据交互格式被广泛使用。而XML同样作为一种功能强大的标记语言被广泛用在Web服务中,自然也是一种不错的选择。

 

JSONJavaScript Object Notation)是一种轻量级的数据交换格式。它是基于JavaScriptStandard ECMA-262 3rd Edition - December 1999)的一个子集。 JSON采用完全独立于语言的文本格式,但是也使用了类似于C语言家族的习惯(包括C, C++, C#, Java, JavaScript, Perl, Python等)。这些特性使JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成。

JSON 语法是 JavaScript 对象表示法语法的子集。JSON 数据的书写格式是:名称/值对。

名称/值对包括字段名称(在双引号中),后面写一个冒号,然后是值:"firstName" : "John"。这很容易理解,等价于这条 JavaScript 语句:firstName = "John"

JSON简单说就是JavaScript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构。

(1)     对象:对象在JavaScript中表示为“{}”括起来的内容,数据结构为 {keyvalue, keyvalue,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为 对象.key 获取属性值,这个属性值的类型可以是数字、字符串、数组、对象几种。

(2)     数组:数组在JavaScript中是中括号“[]”括起来的内容,数据结构为 ["java","javascript","vb",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是 数字、字符串、数组、对象几种。

 

XMLeXtensible Markup Language,可扩展标记语言,是一种标记语言。标记指计算机所能理解的信息符号,通过此种标记,计算机之间可以处理包含各种信息的文章等。XML设计用来传送及携带数据信息,不用来表现或展示数据,HTML语言则用来表现数据,所以XML用途的焦点是它说明数据是什么,以及携带数据信息。

 

JSONXML的比较:

(1)     编码难度:XML有丰富的编码工具,比如Dom4jJDom等,JSON也有提供的工具。在没有工具的情况下,相信熟练的开发人员一样能很快的写出想要的XML文档和JSON字符串,不过,XML文档要多很多结构上的字符。

(2)     可读性:XML有明显的优势,毕竟人类的语言更贴近这样的说明结构。JSON读起来更像一个数据块,读起来就比较费解了。不过,我们读起来费解的语言,恰恰是适合机器阅读。

(3)     有效数据率。JSON作为数据包格式传输的时候具有更高的效率。这是因为JSON不像XML那样需要有严格的闭合标签,这就让有效数据量与总数据包比大大提升,从而减少同等数据流量的情况下,网络的传输压力。

 

本课题搭建的云平台的主要任务是完成数据的处理、存储和转发。虽然,PHPXMLJSON这两种格式的数据都有支持,但在考虑数据传输效率的情况下,包含大量冗余标签的XML明显没有JSON方便。显然这也是其他物联网云平台选择JSON格式作为数据交互格式的重要原因之一。

 

2.4 基本设计方案

通过以上云平台需求和通信协议方面的分析,我们初步确定了以下的云平台设计方案:

(1)   智能家居网关和智能家居控制终端同云平台之间的通信协议使用应用层的HTTP协议,使用HTTP请求来向云平台请求服务(包括保存数据和发出控制命令等)。

(2)   云平台仅实现纯粹的数据处理服务,不涉及界面实现,提供统一的API接口,供智能家居网关、智能家居控制终端、智能家居Web控制平台使用。

(3)   云平台将使用PHP语言进行开发,使用JSON作为数据交互格式,来实现云平台各项功能。

 

以上设计方案的特点有:

(1)   对外而言,云平台提供的接口是一致的,访问的方式也是相同的。因此,云平台能同时支持B/S(智能家居Web控制平台)和C/S(智能家居远程控制终端)架构的开发。

(2)   使用HTTP协议作为通信协议,使用HTTP基本方法(GETPOSTPUTDELETE等)进行服务请求,不同平台访问API的方法具有一致性。

(3)   云平台仅负责数据处理,不涉及界面实现,使得各个控制平台都能根据自己的平台特点进行界面开发,而且不影响功能的实现。

 

2.5 系统配置

云平台处于云端,搭载于服务器中。现有的服务器为阿里云云服务提供的云服务器(ECS),操作系统为CentOS 6.3 64位,其他硬件配置略。服务器系统环境已经满足需求,不需要做任何更改。

根据之前确定的基本方案,云平台以HTTP协议为基础,以Web服务的形式实现,PHP编程开发。那么我们首先需要选择合适的Web服务器软件。因为确定了云平台的开发语言为PHP,则Web服务器软件只需从ApacheNginx之间选择一个即可。云平台数据的管理方面,则可以从OracleMySQL之间进行选择。

Apache的优势在于开源、稳定、模块丰富,缺点是有些臃肿,内存和CPU开销大,性能上有损耗,不如轻量级的Nginx服务器高效。在静态文件处理、PHP-CGI的支持、反向代理功能、前端Cache、维持连接等方面,Nginx都优于Apache。在Apache+PHPprefork)模式下,如果PHP处理慢或者前端压力很大的情况下,很容易出现Apache进程数飙升,从而拒绝服务的现象。Nginx处理请求是异步非阻塞的,而Apache则是阻塞型的,在高并发Nginx能保持低资源低消耗高性能。Nginx使用更少的资源,支持更多的并发连接,体现更高的效率,这点使 Nginx尤其受到虚拟主机提供商的欢迎。

考虑到云平台的特点,低消耗、高并发的Nginx服务器是比较理想的选择。

MySQL是一种关联数据库管理系统,关联数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。MySQL所使用的SQL语言是用于访问数据库的最常用标准化语言。MySQL软件采用了双授权政策,它分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型网站的开发都选择MySQL作为网站数据库。由于其社区版的性能卓越,搭配PHPApache可组成良好的开发环境。PHP中提供了一整套的MySQL函数,对MySQL进行了全方位的支持。

与其他的大型数据库例如OracleDB2SQL Server等相比,MySQL自有它的不足之处,但是这丝毫也没有减少它受欢迎的程度。对于一般的个人使用者和中小型企业来说,MySQL提供的功能已经绰绰有余,而且由于MySQL是开放源码软件,因此可以大大降低总体拥有成本。

由此,服务器软件配置的确定为,Nginx作为Web服务器,MySql作为数据库管理系统。

 

2.6 相关技术简介

2.6.1 HTTP协议简介

HTTPHypertext Transfer protocol,超文本传输协议)是在万维网上进行通信所使用的协议方案。HTTP 协议是应用层的协议,其著名的应用是用于Web浏览器和Web服务器之间的双工通信。

HTTP协议所提供的无连接是基于TCP的无连接,它要求客户端在启动一个请求时,需要先建立连接,等待服务器响应,请求完成以后,服务器不会继续维护该连接,也就不用耗费资源来保存历史记录,可以达到节约资源的目的。

HTTP协议具有较好的灵活性,处理速度能够满足超媒体系统的要求,因为它可以传输任何类型的数据,用户可以根据需要自己定义数据类型,再加上HTTP协议是无状态的协议,减少了HTTP冗余的信息,提高了系统的运行效率,并且客户端可以在浏览器上处理大量的数据,所以在需要连接服务器时,只需要发送较少的信息,就可以很快速的建立连接。

HTTP 协议是采用请求/响应模式的协议,它通过消息来实现客户端与服务器之间的信息交互,请求消息是客户端发送给服务器端用来请求发送数据的消息,响应消息是服务器接受到客户端提出的请求后返回给客户端的消息。

 

HTTP请求(request)的方法有GETPOSTPUTDELETEHEADTRACEOPTIONS。其中,GET方法通常用于请求服务器发送某个方法;HEAD方法与GET方法类似,但要求服务器只返回响应报文的首部(header);PUT方法通常用于添加一个新的资源或修改一个资源;POST方法起初用于向服务器输入数据,服务器接收数据后如何处理视具体而定;DELETE方法用于请求服务器删除某个资源;TRACE方法用于追踪数据报文的转发和修改;OPTIONS方法用于请求Web服务器告知其支持的方法。

HTTP响应(response)的内容是服务器接收客户端的HTTP请求之后的响应信息,具体内容视具体的请求方法、请求内容和服务器的功能而定。

HTTP请求的方法的功能并不是固定的,请求之后相应的内容也完全由服务器控制,可以根据服务器的功能自行设定,这正是HTTP协议灵活性的体现。

 

HTTP报文是简单的格式化数据块。每条报文都包含一条来自客户端的请求,或者一条来自服务器的响应。报文由三个部分组成:对报文进行描述的起始行(start line),包含属性的首部(header)块,以及可选的、包含数据的主体(body)部分。

所有的HTTP报文都可以分为两类:请求报文(request message)和响应报文(response message)。请求报文会向服务器请求一个动作,响应报文会将请求的结果返回客户端。请求和响应报文的基本报文结构相同,只有起始行的语法不同。

请求报文的格式:

<method> <request-URL> <version>

<headers>

<CR><LF>//空行

<entity-body>

响应报文的格式:

<version> <status> <reason-phrase>

<headers>

<CR><LF>//空行

<entity-body>

 

2.6.2 PHP语言简介

PHP(全称:PHPHypertext Preprocessor,即“PHP:超文本预处理器”),是一种被广泛应用的开源通用脚本语言,尤其适用于 Web 开发并可嵌入 HTML 中去。它的语法利用了 CJava Perl,易于学习。该语言的主要目标是允许 web 开发人员快速编写动态生成的 web 页面,但 PHP 的用途远不只于此[22]

PHP的应用范围相当广泛,尤其是在网页程序的开发上。一般来说PHP大多运行在网页服务器上,通过运行PHP代码来产生用户浏览的网页。PHP可以在多数的服务器和操作系统上运行,而且使用PHP完全是免费的。根据20074月的统计数据,PHP已经被安装在超过2000万个网站和100万台服务器上。

 

PHP源代码是可以直接读取的,即使放到服务器上运行也是一样。虽然让PHP多了弹性,但相对的会造成安全危机和性能下降的问题。

通过PHP编码器,可以保护PHP的源代码不被读取(对商业软件来说特别有需求),也可以提升运行的性能。有许多公司或团体开发PHP的编码器,将PHP程序编译成字节码(byte code),再通过服务器上安装对应的程序来运行PHP脚本。

除了通过编码器加速之外,PHP还可以通过动态的高速缓存机制来提升速度,加速工具有商业版的,例如Zend Platform,也有开放源代码的加速软件如eAcceleratorAPCXCache

模板引擎让PHP应用程序可以做逻辑和使用界面上的分离,让程序开发更容易进行,目前比较受欢迎的模板引擎是PHP官方开发的Smarty。不过模板引擎存在性能方面的争议,因为PHP本身就是一个模板引擎,使用模板引擎反而变成“重新发明了轮子”(reinventing the wheel)。模板引擎最主要的好处就是让不懂PHP代码的人也可以参与使用界面的开发,因为模板引擎的语言远比PHP简单。例如非常经典的MVC结构(模型-视图-控制)即是对模板引擎的最好应用,让PHP编程人员可以和HTML前端程序员分工合作。

PHP能做任何事。PHP主要是用于服务端的脚本程序,因此可以用PHP来完成任何其它的CGI程序能够完成的工作,例如收集表单数据,生成动态网页,或者发送/接收Cookies。但PHP的功能远不局限于此。

PHP脚本主要用于以下三个领域:

(1)     服务端脚本。这是 PHP最传统,也是最主要的目标领域。开展这项工作需要具备以下三点:PHP解析器(CGI或者服务器模块)、web服务器和web浏览器。需要在运行web服务器时,安装并配置PHP,然后,可以用web浏览器来访问PHP程序的输出,即浏览服务端的PHP页面。

(2)     命令行脚本。可以编写一段PHP脚本,并且不需要任何服务器或者浏览器来运行它。通过这种方式,仅仅只需要PHP解析器来执行。这种用法对于依赖cronUnix或者Linux环境)或者Task SchedulerWindows 环境)的日常运行的脚本来说是理想的选择。这些脚本也可以用来处理简单的文本。

(3)     编写桌面应用程序。对于有着图形界面的桌面应用程序来说,PHP或许不是一种最好的语言,但是如果用户非常精通PHP,并且希望在客户端应用程序中使用PHP的一些高级特性,可以利用PHP-GTK来编写这些程序。用这种方法,还可以编写跨平台的应用程序。

PHP能够在所有的主流操作系统上使用,包括 LinuxUnix的各种变种(包括 HP-UXSolarisOpenBSD)、Microsoft WindowsMac OS XRISC OS等。今天,PHP已经支持了大多数的web服务器,包括ApacheMicrosoft Internet Information ServerIIS)、Personal Web ServerPWS)、Netscape 以及iPlant serverOreilly Website Pro ServerCaudiumXitamiOmniHTTPd等。对于大多数的服务器,PHP提供了一个模块;还有一些PHP支持CGI标准,使得PHP能够作为CGI处理器来工作。

 

综上所述,使用PHP,可以自由地选择操作系统和Web服务器。同时,还可以在开发时选择使用面对过程和面对对象,或者两者混和的方式来开发。尽管PHP 4不支持OOP所有的标准,但很多代码仓库和大型的应用程序(包括PEAR库)仅使用OOP代码来开发。PHP 5弥补了PHP 4的这一弱点,引入了完全的对象模型。

 

2.6.3 RESTful架构简介

REST(英文:Representational State Transfer,中文:表现层状态转化)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格。

目前在三种主流的Web服务实现方案中,因为REST模式与复杂的SOAPXML-RPC相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。例如,Amazon.com提供接近REST风格的Web服务进行图书查找;雅虎提供的Web服务也是REST风格的。

REST是设计风格而不是标准。REST通常基于使用HTTPURI,和XML以及HTML这些现有的广泛流行的协议和标准。如果一个架构符合REST原则,就称它为RESTful架构。

REST的名称“表现层状态转化”中,省略了主语。“表现层”其实指的是“资源”(Resources)的“表现层”。

所谓“资源”,就是网络上的一个实体,或者说是网络上的一个具体信息。它可以是一段文本、一张图片、一首歌曲、一种服务,总之就是一个具体的实在。每种资源对应一个特定的URI。要获取这个资源,访问它的URI就可以。因此URI就成了每一个资源的地址或独一无二的识别符。对资源的操作包括获取、创建、修改和删除资源,这些操作正好对应HTTP协议提供的GETPOSTPUTDELETE方法。

资源是一种信息实体,它可以有很多种外在表现形式。我们把资源具体呈现出来的形式,叫做它的表现层 URI只代表资源的实体,不代表它的形式。HTTP请求的头信息中用AcceptContent-Type字段指定,这两个字段才是对表现层的描述。

通过操作资源的表现形式来操作资源。

互联网通信协议HTTP协议,是一个无状态协议。这意味着,所有的状态都保存在服务器端。因此,如果客户端想要操作服务器,必须通过某种手段,让服务器端发生"状态转化"State Transfer)。而这种转化是建立在表现层之上的,所以就是"表现层状态转化"

客户端用到的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GETPOSTPUTDELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源。

综合上面的解释,总结RESTful架构的要点:

(1)     每一个URI代表一种资源;

(2)     客户端和服务器之间,传递这种资源的某种表现层;

(3)     客户端通过四个HTTP方法,对服务器资源进行操作,实现“表现层状态转化”。

RESTful架构的优点:

(1)     可更高效利用缓存来提高响应速度

(2)     通讯本身的无状态性可以让不同的服务器的处理一系列请求中的不同请求,提高服务器的扩展性

(3)     浏览器即可作为客户端,简化软件需求

(4)     相对于其他叠加在HTTP协议之上的机制,REST的软件依赖性更小

(5)     不需要额外的资源发现机制

(6)     在软件技术演进中的长期的兼容性更好

 

在云平台设计过程中,使用RESTful API可以使接口的URI变得意义明确,结合HTTP方法来定义操作易于接受和理解,利于开发者对API的理解和使用,也方便自己后续的开发和修改。这也是大部分Web服务使用RESTful API的原因。

 


 

3 智能家居云平台系统设计

3.1 数据库设计

3.1.1 系统结构分析

对于实际的一个设备,可以有多个传感器,用来表示设备不同的状态;也可以有多个执行器,用来接受发出的控制命令。比如,对于无线智能家居系统中现有的可调颜色的RGB灯而言,它有一个开关型的传感器来获取灯的开关状态,一个用于保存RGB值的传感器来获取RGB灯的颜色。当然,RGB灯的开关和RGB值都是可控的,所以需要有两个执行器用于接受这两个设定值。

对于传感器而言,一般来说其值由智能家居网关获取并上传至云平台,而控制终端只有读取的权限;对于执行器而言,在远程控制时,一般由控制终端来上传设定值,发送控制命令,由智能家居网关读取值,执行控制命令。

由以上分析可知,对于传感器和执行器,一般都只有一方(智能家居网关或控制终端)写入数据,另一方读取数据。我们可以将传感器和执行器统一为传感器,但为之分配不同的类型,用来标记传感器类型的差别,由智能家居网关和控制终端负责根据其类型,进行不同的处理。

这样做的目的在于,作为一个面向后续开发的系统,充分保证智能家居网关和控制终端的灵活性。同时也弱化云平台系统的特异性,尽量使所有的操作统一,并退化为对数据的操作,方便功能的扩展。当然,在后续的面对客户的版本发布时,应该完善这些操作方面的限制。

数据点应该由时间戳和数值组成,同时还要有个字段标记数据点所属的传感器。对于不同类型的传感器,其值的类型和范围都会有差别,为了提高数据库空间的利用效率,可以将不同类型的传感器的数据点保存在不同的表中。

 

由此,智能家居系统中的基本结构可确定为:一个具体设备(device)由多个传感器(sensor)构成,每个传感器有自己的类型(type),每个传感器同时还有对应不同时间的多个数据点(datapoint)。每个具体的设备属于不同的用户(user),特定的用户只能操作属于自己的设备。

 

3.1.2 数据库E-R

经过初步的分析以及其它方面的补充,得出以下数据库E-R图:

3.1 数据库E-R

 

3.1.3 数据库表结构分析

数据类型说明(针对MySQL):

(1)     varchar(n):可变长度字符串,最长为n

(2)     int:整型,占4字节;

(3)     tinyint:整型(极小),占11字节。

特殊要求说明:

(1)     PKPrimary Key,主键;

(2)     FKForeign Key,外键;

(3)     AIAuto-Increment,自动递增;

(4)UNIQUE:唯一,在表中不能重复的值;

(5)     NOT NULL:非空。

 

(1)   用户表(tb_user

用于保存用户的基本信息。

4.1 用户表(tb_user)属性

列(column

数据类型

特殊要求

说明

id

int

PK, AI

用户ID

username

varchar(20)

UNIQUE, NOT NULL

用户名

password

varchar(100)

NOT NULL

密码密文

email

varchar(50)

UNIQUE, NOT NULL

验证邮箱

token

varchar(50)

NOT NULL

验证令牌

token_exptime

int

NOT NULL

令牌失效时间

regtime

int

NOT NULL

注册时间戳

status

tinylint

NOT NULL

状态:激活与否

apikey

varchar(100)

NOT NULL

APIKEY,用于授权API操作

about

varchar(200)

 

描述

用户密码(password)采用密文存储,采用不可逆的加密手段(MD5SHA1)进行加密。

验证邮箱(email)、验证令牌(token)、令牌失效时间(token_expire)、状态(status)用于用户注册的验证,该字段所涉及的功能主要用于Web控制平台。其中验证邮箱是唯一的,不能重复使用。

APIKEY用于API操作的授权,对API请求操作时必须在HTTP报文的首部(header)中设置相应的APIKEY,云平台才会认定请求合法,返回正确的数据。使用APIKEY进行授权是一种简单的方法,另一种更严谨的授权方法见详细的设计过程。

 

(2)   用户令牌表(tb_user_token

用于保存用户的令牌,该令牌在用户每次登陆时重新生成,并确保唯一,一定时间后会自动失效,需要重新登陆。

4.2 用户令牌表(tb_user_token)属性

列(column

数据类型

特殊要求

说明

user_id

int

NOT NULL, FK

用户ID

token

varchar(100)

NOT NULL, UNIQUE

用户令牌

deadline

int

NOT NULL

截止时间、失效时间

 

用户IDuser_id)是外键,引用用户表(tb_user)中的用户IDid)列。

用户令牌(token)是根据登陆时间以及其它信息生成的唯一的令牌,用于API操作的授权。

截止时间(int)的格式是时间戳,采用int型存储,为该令牌的失效时间。

 

(3)   设备表(tb_device

用于保存无线智能家居系统设备信息。

4.3 设备表(tb_device)属性

列(column

数据类型

特殊要求

说明

id

int

PK, AI

设备ID

name

varchar(50)

NOT NULL

设备名称

tags

varchar(50)

 

设备标签

locate

varchar(50)

 

设备位置

about

varchar(200)

 

描述

user_id

int

FK

用户ID

create_time

int

NOT NULL

创建时间

last_active

int

NOT NULL

最后活动时间

status

tinyint

NOT NULL

状态

创建时间(create_time)和最后活动时间(last_active)保存的都是时间戳

用户ID是外键,引用用户表(tb_user)中的用户IDid)列。

状态(status)列表征设备的删除状态,1代表正常,0代表删除。因为存在外键约束(来自传感器表(tb_sensor)的约束),所以不能直接删除。

 

(4)   传感器表(tb_sensor

用于保存无线智能家居系统设备所包含的传感器的信息,一个设备可能包含有多个传感器。

4.4 传感器表(tb_sensor)属性

列(column

数据类型

特殊要求

说明

id

int

PK, AI

传感器ID

name

varchar(50)

NOT NULL

传感器名称

tags

varchar(50)

 

传感器标签

type

int

FK

传感器类型ID

about

varchar(200)

 

描述

device_id

int

FK

设备ID

last_update

int

NOT NULL

更新时间

last_data

varchar(100)

 

最新数据

status

tinyint

NOT NULL

状态

 

更新时间(last_update)保存的是时间戳,表示最后一次上传数据的时间(而非传感器信息的修改时间);最新数据(last_data)保存的是最后一次上传的数据。

设备ID是外键,引用用户表(tb_device)中的设备IDid)列,表示传感器属于该设备。

传感器类型ID是外键,引用传感器类型表(tb_sensor_type)中的ID,表明该传感器的类型必须是一个已经存在的类型。

状态(status)列表征设备的删除状态,1代表正常,0代表删除。因为存在外键约束(来自数据点表(tb_datapoint)的约束),所以不能直接删除。

 

(5)   传感器类型表(tb_sensor_type

用于保存传感器的类型及描述,创建该表的目的在于方便扩展传感器类型。

4.5 传感器类型表(tb_sensor_type)属性

列(column

数据类型

特殊要求

说明

id

int

PK

传感器类型ID

name

varchar(50)

NOT NULL, UNIQUE

类型名称

description

varchar(255)

 

对该类型的描述

status

tinyint

NOT NULL

状态

 

状态(status)列表征传感器类型的停用状态,1代表正常,0代表停用。因为存在外键约束(来自传感器表(tb_sensor)的约束),所以不能直接删除。

 

(6)   数据点表(tb_datapoint_lite

用于保存传感器的数据,每一条记录都是某个传感器的某个时间点下的数据。

4.6 数据点表(tb_datapoint_lite)属性

列(column

数据类型

特殊要求

说明

id

int

PK, AI

数据点ID

sensor_id

int

FK

传感器ID

timestamp

int

NOT NULL

时间戳

value

varchar(255)

NOT NULL

数据值

 

传感器IDsensor_id)是外键,引用传感器表(tb_sensor)中的传感器IDid)列。

数据值(value)采用可变字符串保存数据点的值,可以存储任何类型的数据,这样可以将不同类型的传感器的数据点集中到一个表中。

 

3.2 PHPRESTful API设计过程

3.2.1 RESTful API请求和响应

所有的APIs都需要接收请求。对于一个RESTful API,需要一个定义好的URL规则。假定需要提供一个接口给网站上的用户。系统的URL结构可能类似于这样:api/users,或者api/users/[id],这取决于请求接口的操作类型。

同时,也需要考虑怎么样接收数据。近来一段时间,多使用JSON或者XML。从云平台的基本设计方案来看,系统已经确定使用JSON作为数据交互格式。JSON可以很好的和Javascript进行交互操作,同时PHP也可以很简单的通过json_encodejson_decode两个函数来对它进行编码和解码。

为了使系统的接口真正强健,设计时应该通过识别请求的内容类型(比如application/json或者application/xml)同时允许接收两种格式。但是,限制只接收一种类型的数据也是可以很好的被接受。

一个RESTful的响应主要包括两个主要部分:响应体和状态码。就像请求,大部分的REST响应通常是JSON或者XML格式,和请求类似,API使用者可以通过设置HTTP规范首部的"Accept"选项来规定自己做希望接收到的响应数据类型。如果一个API使用者希望接收到XML响应,他们仅仅需要发送一个包含类似于“Accept: application/xml”这样的头信息请求。

和请求有关的错误和其他重要的状态信息通过使用HTTP的状态码(status-code)和原因字段(reason-phrase)来输出。比如:假如一个API使用者提交数据(POST)到/api/users,需要返回一个成功创建的消息,此时可以简单的发送一个201状态码(201=Created)。如果失败了,服务器失败就发送一个500500=内部服务器错误),如果请求中断就发送一个400400=错误请求)。

 

在本课题的云平台设计方案中,默认使用并且暂时只支持JSON格式的响应数据,在使用API的时候仍然要将在HTTP请求报文的首部中设置“Accept: application/json”选项以确保以后云平台功能扩展时返回错误类型的响应数据。

云平台接受数据的形式根据HTTP请求方法不同略有差异。对于GETDELETE请求,附加参数附在URI后面,即通过GET方式传递的参数;对于POSTPUT请求,数据通过HTTP表单的形式传递过来,即“Content-Type: application/x-www-form-urlencoded”。

 

3.2.2 RESTful API URL及方法设置

现在初步定义RESTful API的功能,接口的功能和说明见下表4.6

4.6 API请求方法与功能定义

请求方法

URI/URL

功能

用户接口

POST

/api/login

用户登录,用户认证

GET

/api/user/<user_id>

获取用户的详细信息

PUT

/api/user/<user_id>

更改用户的详细信息

设备接口

GET

/api/devices

获取所有设备列表

POST

/api/devices

添加一个新的设备

GET

/api/device/<device_id>

获取设备的详细信息

PUT

/api/device/<device_id>

更改设备的详细信息

DELETE

/api/device/<device_id>

删除设备

传感器接口

GET

/api/sensors/<device_id>

获取指定设备下的所有传感器

POST

/api/sensors/<device_id>

在指定设备下添加一个新的传感器

GET

/api/sensor/<sensor_id>

获取传感器的详细信息

PUT

/api/sensor/<sensor_id>

更改传感器的详细信息

DELETE

/api/sensor/<sensor_id>

删除传感器

数据点接口

GET

/api/datapoints/<sensor_id>

获取指定传感器的数据点(多个)

POST

/api/ datapoints/<sensor_id>

为指定传感器创建数据点(多个)

GET

/api/datapoint/<sensor_id>

获取指定传感器的最新数据

POST

/api/datapoint/<sensor_id>

为指定传感器创建单个数据点

DELETE

/api/datapoint/<dp_id>

删除数据点(保留,暂不用)

 

3.2.3 确定PHP下开发RESTful API的详细方案

要使用PHP完成RESTful API的开发,需要完成以下几个方面的功能:

(1)处理请求信息:确定请求方法和请求参数;

(2)实现URL路由:根据请求的方法和URL,执行实现这个功能的函数;

(3)处理响应信息:控制HTTP响应报文的状态码、首部等信息,控制数据输出为指定的格式。

虽然只列出了三项,但其实这部分内容实现起来是很复杂且费时费力的。通过调研和分析,最终的出了比较快速高效的设计方案:

(1)使用基于MVC架构的PHP框架CodeIgniter来实现最基本的路由功能;

(2)使用框架内的第三方库函数rest-server来实现更完整的RESTful API

(3)使用编程实现系统内部的处理逻辑,处理输入,产生输出。

 

3.3 开发环境配置

3.3.1 LinuxNginxPHP的配置

为了在Nginx服务器中使用PHP,需要安装PHP-FPMPHP Fastcgi Process Manager)。假定所有软件都已经安装完毕,接下来就需要开始配置NginxPHP的配置参数了。

对于PHP的配置,找到PHP的配置文件php.ini,开始配置:

(1)     找到时区设置选项,设置“date.timezone = PRC”

(2)     开启MySql扩展库支持,取消前面的分号注释,即设置“extension=php_pdo_mysql.dll”

(3)     根据具体需要,开启其它扩展库。

对于PHP-FPM的配置,找到PHP-FPM的配置文件(根据安装方式不同位置、名称都可能不同)/etc/php-fpm.d/www.conf(默认安装时),设置PHP-FPM监听Unix Socket管道通信(to listen on a unix socket),并设置socket文件的地址。例如,“listen = /tmp/php-fpm.sock”。然后重启PHP-FPM即可。

对于Nginx的配置,可以新建一个配置文件cloud-platform.conf,用于单独保存云平台的配置,然后在Nginx的主配置中引入该配置文件(include)。

配置文件cloud-platform.conf示例及说明(使用#作为行注释):

server {
        listen       8000;#要使用的端口号
        server_name  cloud-platform;#如果没有域名,则随意设置,否则设置为域名

        location / { 
            root   /tmp/cloud-platform; 
            index  index.php;
        }
#针对PHP的设置
        location ~ \.php($|/) {
#设置服务器根目录,用于保存提供服务的页面
            root           /tmp/cloud-platform;
#使用Unix管道与php-fpm进行进程通信,使用之前在PHP-FPM中设置socket文件
            fastcgi_pass   unix:/tmp/php-fpm.sock;
            fastcgi_index  index.php;
            fastcgi_split_path_info ^(.+\.php)(.*)$;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            include        fastcgi_params;
        }
#针对CodeIgniter框架的设置,可以使得URL略去”index.php”
        if (!-e $request_filename) {
            rewrite ^/(.*)$ /index.php/$1 last;
            break;
        }
}

配置完成之后,运行Nginx的检测工具检查配置文件是否有效合法,(假设现在工作目录在Nginx的根目录中)运行:“./sbin/nginx -t”。检测通过之后,重启Nginx,然后测试虚拟主机是否工作正常,PHP文件是否正确解析。

 

更详细的配置选项,请查阅Nginx文档[20]以及PHP手册[22]

 

3.3.2 MySql开发配置

对于工程运用而言,云平台系统访问数据库都不会直接使用最高权限的root账户,因此我们需要新建一个为云平台专用的用户,并为它设置对应的权限。

(1)     在命令行下使用root帐户登录mysql,输入:”mysql –u root –p”,再输入root账户密码即可登录

(2)     创建新的用户(以用户名linpcloud,密码1234为例),输入:“create user linpcloud identified by '1234';”

(3)     创建工程用的数据库(以linpcloud为例),输入:“create database linpcloud;”

(4)     为用户linpcloud赋予数据库linpcloud的权限,输入:”grant all on linpcloud.* for 'linpcloud'@'%';”

(5)     使用以下指令查看用户的权限,输入:“show grants for linpcloud;”

 

在上面的配置中,我们为用户linpcloud分配了数据库linpcloud的所有权限。然而在工程开发完成之后,数据库结构不再变更时,整个工程对数据库只有基本的增删查改操作。从严格来讲,我们应该进一步限制这个账户的权限。但我们处于开发阶段,只要将该数据库所有权限分配给它即可。

 

更具体的设置方法及说明,请参阅MySql参考手册文档[21]

 

3.3.3 PHP框架CodeIgniter的配置

CodeIgniter 是一套给 PHP 网站开发者使用的应用程序开发框架和工具包。它提供一套丰富的标准库以及简单的接口和逻辑结构,其目的是使开发人员更快速地进行项目开发。使用 CodeIgniter 可以减少代码的编写量,并将你的精力投入到项目的创造性开发上。

CodeIgniter 生成的 URL 非常干净而且是对搜索引擎友好化的。不同于标准的“字符串查询”方法,CodeIgniter使用了“基于段”的方法:” example.com/news/article/345”

注意:“index.php 文件是被默认包含在 URL 中的,但是可以通过更改 .htaccess 文件来改变这个设置(通过Web服务器的配置来更改)。

3.2说明了CodeIgniter中数据流如何贯穿整个系统:

CodeIgniter 应用程序流程图

3.2 CodeIgniter数据流分析

(1)     index.php作为前端控制器,初始化运行CodeIgniter所需要的基本资源。

(2)     Router检查HTTP请求,以确定谁来处理请求。

(3)     如果缓存(Cache)文件存在,它将绕过通常的系统执行顺序,被直接发送给浏览器。

(4)     安全(Security)。应用程序控制器(Application Controller)装载之前,HTTP 请求和任何用户提交的数据将被过滤。

(5)     控制器(Controller)装载模型、核心库、辅助函数,以及任何处理特定请求所需的其它资源。

(6)     最终视图(View)渲染发送到Web浏览器中的内容。如果开启缓存(Caching),视图首先被缓存,所以将可用于以后的请求。

 

(1)   CodeIgniter的文件结构

解压后的文件结构如图3.3所示:

3.3 CodeIgniter的文件结构

其中,”index.php”CodeIgniter框架的入口文件。所有对系统的访问,虽然HTTP请求URL不同,其实都指向”index.php””index.php”文件中负责根据URL来确定需要调用哪个控制器、哪个方法,即实现URL的路由功能(还包括系统的初始化)。

“system”文件夹是CodeIgniter的核心文件,我们一般都不应该更改其中的文件内容(除非你打算修改框架)。“application”文件夹用于存放我们的应用程序(对于本课题,保存云平台系统主体)。

 

(2)   CodeIgniter的文件布局和系统配置

解压框架文件,将”application”文件夹重命名为”cloud-platform”,用于存放我们的应用(云平台系统的主体),然后将该文件夹放到自己的开发目录中去。

”index.php”文件复制到Nginx设置的虚拟主机根目录下,并修改该文件。

3.4 CodeIgniter文件布局的设置

将变量”$system_path”的值设定为框架的“system”文件夹的位置,将变量”$application_folder”的值设定为存放云平台的主体的文件夹“cloud-platform”的位置。

 

然后开始配置CodeIgniter中应用(application)的设置。

首先,将“rest-server”库的文件复制到“cloud-platform”文件夹内指定的子文件夹中。

其次,配置“cloud-platform”“config”子目录下的数据库设置文件“database.php”配置文件,将之设定为系统使用的数据库连接。

最后,配置“rest-server”库的变量。主要需要将返回数据的类型设定为JSON格式(参考云平台基本设计方案),禁用不需要的HTTP请求方法(HEADTRACEOPTIONS)。

更具体的配置,参考CodeIgniter的用户指引文档[23]

 


 

4. 智能家居云平台功能实现

接下来介绍智能家居云平台具体功能的开发过程,以及逐个的RESTful API的实现过程。

4.1 用户类

云平台核心功能的API请求都需要进行用户权限的确认,才能允许进一步的操作。而HTTP请求属于无连接、无状态的,根据RESTful API的要求,我们需要在HTTP报文中添加能够表示API用户状态的信息。

在云平台的数据库设计已经考虑到了这方面的问题,并且在用户表(tb_sensor)中添加了APIKEY字段(apikey),用来在HTTP报文中标识用户的身份和权限。

显然该字段在数据表中是唯一的(UNIQUE,数据库设计时已经实现该限制),这样才能标识某个特定的用户,而不至于产生冲突。在用户表(tb_sensor)中,还有两个字段也是有唯一性约束的,即用户IDid)和用户名(username),显然使用这两个字段也可以起到上述标识用户的作用。那么使用APIKEY的意义何在?

很显然,用户ID和用户名都应该是静态的,一经创建就不能够再更改了。那么使用APIKEY的用意也就很明显了:可以重新生成新的APIKEY。考虑到安全问题,如果使用静态的标识用来标识用户,很容易会遇到通过伪造HTTP请求报文从而实现盗用他人用户的状况。使用APIKEY的情况下,在一定的程度内能避免上述安全问题的发生。

更加完善的方案则是使用令牌来授权API访问权限:每次登录都生成一个唯一的令牌(token),一定时期之后失效。通过使用动态的标识手段,来提高安全性。

在云平台系统的设计中,我们保留了两种设计方案,但为了开发的方便,现阶段主要使用APIKEY进行标识,这样使用半静态的标识可以减少后期开发的麻烦。

HTTP报文首部中添加APIKEY字段,用来确认用户状态,进行API授权,如:”Apikey: 1a39ad4c87ba09ef861ead97f010df7b “

 

(1)   用户登录

请求方法:POST

请求URI/api/login

响应内容:基本的用户信息

设计方法:

使用基本的Web表单的形式将用户名和密码提交到云平台,由云平台查询数据库进行用户认证;认证成功,返回基本的用户信息(用户ID、用户名、APIKEY);认证失败返回失败提示信息。

 

(2)   用户信息获取

请求方法:GET

请求URI/api/user

响应内容:完整的用户信息

设计方法:

通过获取HTTP请求报文首部Apikey字段的值,确认用户身份,获取其信息,然后作为响应将之返回。

 

(3)   更改用户信息

请求方法:PUT

请求URI/api/user

响应内容:成功或失败的提示性信息

设计方法:

通过获取HTTP请求报文首部Apikey字段的值,确认用户身份及权限。如果没有权限,则直接返回错误信息。使用基本的Web表单的形式将用户信息提交到云平台,由云平台更新数据库内容,返回操作成功的提示信息。

 

(4)   重新生成APIKEY

请求方法:PUT

请求URI/api/apikeyr

响应内容:新的APIKEY

设计方法:

通过特定的函数生成新的APIKEY,并确保其唯一性,然后将之返回。生成新的APIKEY之后,原先的APIKEY将会失效。

生成新的APIKEY的算法:

$apikey = md5($user_id . time());

使用用户ID和当前时间戳组合成字符串再求MD5,这首先保证了求MD5的字符串每次都是不同的,因而APIKEY相同的概率极小。如果出现了相同,数据库设计时的唯一性约束会发生作用,导致APIKEY更新失败,返回错误信息。

 

因为接下来的API都需要通过APIKEY进行API授权,才能有操作权限。因此我们在设计时,将通过Apikey获取用户信息的一系列操作统一为一个共有函数,以简化之后的处理流程。

function _check_apikey()
{
    $apikey = $this->input->get_request_header('Apikey');//从HTTP请求报文首部获取APIKEY
    if ($apikey === FALSE)//简单的判断APIKEY是否设置
    {
        $this->response(array (
                'info' => 'http header `apikey` lost, please login agian'
        ), 400);
    }
$result = $this->user_model->get_info_by_apikey($apikey);//调用了用户模型下的函数
//只是使用了MVC架构,将数据库操作集中在了模型(Model)里面了
//相当于执行SQL语句:”SELECT * FROM tb_user WHERE apikey=’$apikey’”
    if ($result === FALSE)//数据库中没有找到APIKEY的情况
    {
        $this->response(array (
                'info' => '`apikey` not match, please login agian'
        ), 400);
    }
    return $result['id'];//返回用户ID
}

 

这部分功能处理流程都很简单,所以不过多说明。

 

4.2 设备类

设备和用户属于多对一的关系,即一个用户可以有多个设备,每个设备必然归属于某一个用户。因此在数据库设计中,设备表中使用了外键约束,用户IDuser_id)引用用户表(tb_user)中的用户IDid)栏。

对设备的操作都需要检查用户的权限:首先检查HTTP请求报文中的APIKEY,然后再检查操作的设备中的用户ID是否与之对应。不对应,就认为该设备不属于该用户,用户无法请求API进行操作。检查设备归属的函数也是常用的共有函数,这里给出其代码和注释:

function _check_device($device_id)
{
$user_id = $this->_check_apikey();
//首先调用已有的检查APIKEY的函数,并获取用户的ID
    
    $result = $this->device_model->get($device_id);//调用模型的方法获取设备信息
    if ($result === FALSE)//设备不存在的情况
    {
        $this->response(array (
                'info' => "device `$device_id` not found"
        ), 400);
    }
    if ($result['user_id'] != $user_id)//判断设备归属,如果不同返回错误信息
    {
        $this->response(array (
                'info' => "device `$device_id` out of your permission"
        ), 400);
    }
    return TRUE;//没有出错,返回TRUE
}

 

(1)   获取设备列表

请求方法:GET

请求URI/api/devices

响应内容:返回JSON格式的对象数组

设计方法:

首先调用公有函数_check_apikey()检查用户状态并获取用户ID,使用用户ID在设备表(tb_device)中查询所有属于该用户ID的设备,进行JSON编码后返回数据给用户。

 

(2)   添加新的设备

请求方法:POST

请求URI/api/devices

响应内容:成功或失败的提示性信息

设计方法:

首先调用公有函数_check_apikey()检查用户状态并获取用户ID。使用基本的Web表单的形式将设备信息提交到云平台,由云平台获取表单数据,在结合已获取的用户ID,进行数据库的插入操作,返回操作成功的提示信息。

 

(3)   获取设备信息

请求方法:GET

请求URI/api/device/<device_id>

响应内容:设备详细信息

设计方法:

首先调用公有函数_check_device()检查设备的归属,然后直接使用URI中的参数在数据库中查询该设备的信息。

 

(4)   更改设备信息

请求方法:PUT

请求URI/api/device/<device_id>

响应内容:成功或失败的提示信息

设计方法:

首先调用公有函数_check_device()检查设备的归属(同时也会确认设备的存在性)。使用基本的Web表单的形式将新的设备信息提交到云平台,由云平台获取表单数据,进行数据库的更新操作,返回操作成功的提示信息。

 

(5)   删除设备(停用设备)

请求方法:DELETE

请求URI/api/device/<device_id>

响应内容:成功或失败的提示信息

设计方法:

首先调用公有函数_check_device()检查设备的归属,再使用URI中的参数进行数据库的更新操作,将设备表中符合要求的一条记录的状态(status)列设为1,返回操作成功的提示信息。由于存在外键约束,不能直接删除设备。同时真正的系统中,对数据的删除都应小心操作,因为一旦删除无法恢复。因此使用状态(status)字段来表示设备的删除状态。因此,前面的API获取设备列表和获取设备信息功能中,查询数据库都要添加对状态(status)字段的判断。在用户看来已被删除(实际上在表中没有删除)的设备不应出现在列表中,也不能被获取详细信息,不能更改设备信息。

 

4.3 传感器类

传感器和设备属于多对一的关系,即一个设备可以包含多个传感器,每个传感器必然属于某一个设备。因此在数据库设计中,传感器表中也使用了外键约束,设备IDdevice_id)引用设备表(tb_device)中的设备IDid)栏。

创建传感器时应该指定该传感器所属于的设备(创建设备时,自动设置所属用户为API使用者),因此API虽大部分类似与设备类,但依旧有些许不同。

对于传感器的操作,权限和归属的检查同时也要深入到传感器的层次,同时也要检查传感器所属设备的归属。

function _check_sensor($sensor_id, $device_id = FALSE)
{
    $result = $this->sensor_model->get($sensor_id);//获取传感器信息
    if ($result === FALSE)//传感器不存在的情况
    {
        $this->response(array (
                'info' => "sensor `$sensor_id` not found!"
        ), 400);
    }
    //参数设备ID不为空时,判断传感器是否属于设备
    if ($device_id !== FALSE && $device_id != $result['device_id'])
    {
        $this->response(array (
                'info' => "sensor `$sensor_id` do not belong to device `$device_id`!"
        ), 400);
    }
    //检查传感器所属设备的权限,其中包含了对APIKEY的检查
    $this->_check_device($result['device_id']);
    //返回传感器的信息
    return $result;
}

 

(1)   获取传感器列表

请求方法:GET

请求URI/api/sensors/<device_id>

响应内容:返回JSON格式的对象数组

设计方法:

首先调用公有函数_check_device()检查设备状态,使用该设备ID在传感器表(tb_sensor)中查询所有属于该设备ID的传感器,进行JSON编码后返回数据。

 

(2)   添加传感器(向特定设备添加)

请求方法:POST

请求URI/api/sensors/<device_id>

响应内容:返回成功或失败的信息

设计方法:

首先调用公有函数_check_device()检查设备状态。使用基本的Web表单的形式将传感器信息提交到云平台,由云平台获取表单数据,在结合已有的URI参数设备ID,进行数据库的插入操作,返回操作成功的提示信息。

 

(3)   获取传感器信息

请求方法:GET

请求URI/api/sensor/<sensor_id>

响应内容:返回传感器详细信息

设计方法:

首先调用公有函数_check_sensor()检查传感器状态,再直接查询该传感器的信息,并返回数据。

 

(4)   更改传感器信息

请求方法:PUT

请求URI/api/sensor/<sensor_id>

响应内容:返回成功或失败的信息

设计方法:

首先调用公有函数_check_sensor()检查传感器状态。使用基本的Web表单的形式将传感器信息提交到云平台,由云平台获取表单数据,进行数据库的更新操作,返回操作成功的提示信息。

 

(5)   删除传感器

请求方法:DELETE

请求URI/api/sensor/<sensor_id>

响应内容:返回成功或失败的信息

设计方法:

首先调用公有函数_check_sensor()检查传感器的状态,其它处理类似于设备的删除操作,不直接删除记录,只是将记录标记为已删除。

 

4.4 数据点类

数据点和传感器属于多对一的关系,即一个传感器可以有多个数据点,每个数据必然归属于某一个传感器。因此在数据库设计中,数据点表中也使用了外键约束,传感器IDsensor_id)引用传感器表(tb_sensor)中的传感器IDid)栏。

数据点的字段有四项:编号(id)、传感器IDsensor_id)、时间戳(timestamp)、值(value)。

对于数据点的数据库设计曾经有多种方案,最终暂时采取了最简单、最直接的一种设计方案:只使用一个表保存不同类型数据传感器的数据,并且使用可变长度字符串(varchar)直接保存数值。这样设计的优点在于,数据点的插入和查询都比较简单,并且数值的类型几乎没有限制,传感器的值甚至可以使用一个字符串(一句话)。但缺点也很明显:首先,传感器类型的区分就没有太多意义了;存储空间的使用效率可能会比较低。

MySql中,对于可变字符串(varchar)而言,真实占用的空间为字符串的实际长度n+1 Byte。对于开关量,以01表示的话,则每个值需要占用2 Bytes;对于整型数值,位数n越长,占用Byte数就越多,为n+1 Bytes;对于浮点数来说,以两位整数、两位小数为例,需要占6 Bytes

总的来说,只有在数值为位数较少的整型时,才勉强占用空间略小;其它情况下,都多占了很多的存储空间。

 

另一种设计方案则是为每种数据类型的传感器设计不同的表存储数据。如开关量,将value列设为布尔型;整型数值,将value列设为int型;浮点型数值,将value列设为float型。这样的确充分利用了存储空间,但在某些功能的设计时遇到了很大的麻烦,尤其是批量上传数据、批量获取数据时。故而,这种数据库设计方案被置为保留方案,暂时使用最方便的方案。

 

(1)   创建数据点

请求方法:POST

请求URI/api/datapoint/<sensor_id>

响应内容:返回成功或失败的信息

设计方法:

首先调用公有函数_check_sensor()检查传感器状态和权限。使用基本的Web表单的形式将数据点信息提交到云平台,由云平台获取表单数据,在结合已有的URI参数传感器ID,进行数据库的插入操作,返回操作成功的提示信息。

该功能的数据库操作涉及3个表:数据点表(tb_datapoint_lite)、传感器表(tb_sensor)、设备表(tb_device)。在创建数据点的时候,时间戳使用的是服务器自动生成的时间戳,不需要再单独上传。在为传感器创建数据点的时候,我们认为传感器数据得到更新,于是同时更新传感器表(tb_sensor)中的最禁更新时间(last_update)和最近数据(last_data)为数据点的时间戳和数据值。同时,我们认为设备是活动的,于是将设备表中的活动时间(last_acitve)设置为当前时间戳。至此,创建数据点及其连带的操作才算完成。

 

(2)   获取传感器最新数据点

请求方法:GET

请求URI/api/datapoint/<sensor_id>

响应内容:返回时间戳和数据

设计方法:

首先调用公有函数_check_sensor()检查传感器状态和权限,然后直接从传感器表中读出最近(最新)的数据和时间戳,并返回。

 

(3)   批量上传数据点(网关用)

请求方法:POST

请求URI/api/datapoints/<device_id>

响应内容:成功或失败的信息

设计方法:

该功能主要面向智能家居网关开发,用于批量上传某个设备内所有传感器的数据。这个操作只会修改URI中指定的设备的最后活动时间(不是根据传感器再来判断更新哪个设备)。因为数据处理比较复杂,所以对网关上传数据时有一定的要求:上传时在URI中指定传感器所属设备,上传数据的所有传感器都应属于该设备,否则不会为它创建数据点;上传数据时依然使用表单的形式,设置json值为要提交的数据的JSON字符串(即将数据组织成JSON数据再通过表单传递过来)。

处理流程为:

调用公有函数_check_device()检查用户权限。云平台接受通过表单传递过来的JSON数组,对之进行解析成PHP索引数组。遍历数组每一个元素,然后组织出两个数组:一个用于批量更新传感器表的数据,一个用于批量插入数据点。执行SQL语句,返回结果。

程序代码如下:

public function datapoints_post($device_id = FALSE)
{
    if ($this->post('json') == FALSE)//获取表单中的JSON字符串
    {
        $this->response(array (
                'info' => 'Field `json` required'
        ), 400);
    }
    if($device_id != FALSE)//更新设备的最后活动时间(last_active)
    {
        $time = time();
        $sql = "UPDATE tb_device SET last_active='$time' WHERE id='$device_id'";
        $this->db->query($sql);
    }
    //组织插入数据和更新数据
    $json_array = json_decode($this->post('json'), 'array');
    $insert_data = array();
    $update_data = array();
    foreach($json_array as $row)
    {//we should check every sensor_id in the further, validation and unique
        $insert_data[] = array(
                'sensor_id' => $row['sensor_id'],
                'timestamp' => time(),
                'value' => $row['value']
        );
        $update_data[] = array(
                'id' => $row['sensor_id'],
                'last_data' => $row['value'],
                'last_update' => time()
        );
    }
    
    $this->db->update_batch('tb_sensor', $update_data, 'id');//批量更新
    $this->db->insert_batch('tb_datapoint_lite', $insert_data);//批量插入
    
    $this->response(array (
            'info' => 'Datapoint created success'
    ), 200);
}

 

(4)   批量获取数据

请求方法:GET

请求URI/api/datapoints/<type>/<id>

响应内容:JSON格式的对象数组

设计方法:

<type>=device时,<id>代表的是设备ID,该接口用于获取某个设备下所有传感器的最新数据;当<type>=sensor时,<id>代表的是传感器ID,该接口用于获取某个传感器的历史数据。

代码如下:

public function datapoints_get($type, $id) {
    if(strtoupper($type) == 'DEVICE') { //获取某个设备下所有传感器的最新数据
        $this->_check_device($id);//检查设备的状态和权限
        $sql = "SELECT id, last_update, last_data FROM tb_sensor WHERE device_id = $id AND `status` = 1";
        $result = $this->db->query($sql);
        $data = $result->result_array();
        $this->response($data, 200);
    }
    else if(strtoupper($type) == 'SENSOR') { //获取某个传感器的历史数据
        $this->_check_sensor($id); //检查传感器的状态和权限
        $end = time();//结束时间,默认为当前时间
        $start = $end - 60*60;//开始时间,默认为当前时间的一小时前
        $interval = 60;//获取数据的时间间隔

        if($this->get('start') != FALSE)//检查参数(GET参数)
            $start = $this->get('start');
        if($this->get('end') != FALSE)
            $start = $this->get('end');
        if($this->get('interval') != FALSE)
            $start = $this->get('interval');
        $sql = "SELECT * FROM tb_datapoint_lite WHERE `sensor_id`=$id AND `timestamp` BETWEEN $start AND $end AND (`timestamp`-$start)%$interval<=30 ORDER BY `timestamp` ASC";//查询语句
        $result = $this->db->query($sql);
        $data = $result->result_array();
        $this->response($data, 200);
    }
    else {
        $this->response(array (
                'info' => 'Lost parameter `$type`'
        ), 400);
    }
}

通过一定时间间隔获取数据的SQL语句分析:

SELECT * FROM tb_datapoint_lite WHERE `sensor_id`=$id AND `timestamp` BETWEEN $start AND $end AND (`timestamp`-$start)%$interval<=30 ORDER BY `timestamp` ASC

 

核心在于,将数据点的时间戳减去开始时间,然后与时间间隔取余,然后与系统要求的上传数据的最小时间间隔(30s)比较。如果取余之后,小于30s,则取出该记录。加入采用默认的时间间隔60s,且数据上传间隔正好是30s,那么160s内,显然取余之后,只会有一个数据符合要求,达到60s取一个点的要求。对于时间间隔,如果小于30s,显然所有的点都会被取出来。

 

4.5 辅助接口

该类接口主要提供一些辅助功能,包括提供云平台基本的测试接口。

现有的辅助接口及设计说明如下:

 

(1)   获取MD5

请求方法:GET

请求URI/helper/md5/<string>

响应内容:JSON格式的对象,包括所求字符串的MD5

设计方法:

直接使用PHPMD5函数对参数进行求取MD5的运算,然后返回数据。

 

(2)   获取时间戳

请求方法:GET

请求URI/helper/timestamp/<timestamp>

响应内容:JSON格式的对象数组,包括当前时间戳,和格式化之后的时间字符串

设计方法:

参数为可选参数,如果不指定参数timstamp的值,则默认使用PHP函数time()获取当前时间戳,再使用date()函数将之格式化,将两个数据返回。

 


 

5 系统测试及结果分析

5.1 云平台系统测试要求

本课题中云平台的设计主要负责数据的存储和处理,没有涉及用户界面的实现,我们将结合设计方案,通过以下方面对云平台功能进行测试和评估:

(1)云平台响应报文结构和内容:访问云平台API查看HTTP响应报文结构和内容是否符合设计时的要求(以JSON格式返回数据);

(2)云平台功能实现状况:访问云平台指定功能的API,通过查看HTTP响应报文和对比数据库记录的变化评估系统功能实现结果;

(3)云平台权限控制:通过跨越权限的API操作,评估云平台的权限控制是否正常,错误信息输出是否正常;

(4)云平台错误控制:通过大量的测试,检查是否有遗漏的未捕捉的错误。

 

5.2 云平台系统测试方法

为了完成云平台API的测试,需要一个能够快速高效组织HTTP请求报文,并发送HTTP请求的工具。通过调研,我们选择了使用GoogleChrome浏览器结合其扩展应用Postman – REST Client来进行测试,通过Chrome浏览器开发者工具获取更详细的HTTP请求报文(Request Message)和响应报文(Response Message)的具体内容。

 

下面是以云平台中用户类的登录API进行测试的实例。在示例中,我们展示了使用Postman进行RESTful API测试的基本方法,以及使用Chrome浏览器开发者工具获取完整的请求报文和响应报文的方法。

 

使用Wireshark可以通过网卡从硬件底层捕捉HTTP请求报文,这些报文一般来说都会与通过浏览器开发者工具获取的报文相同。虽然使用Wireshark可以进行捕捉更加真实完整的报文(搭载HTTP报文的TCP报文、IP报文,甚至于以太网数据帧),但其使用可能就没有使用浏览器工具那么简洁方便。但在非浏览器中(如Java程序或PHP-CLI模式的测试)测试云平台API时,就需要用到这个工具了,所以在这里也进行了简单的介绍。

5.1 Postman-REST Client界面

5.2 Google Chrome浏览器开发者工具

5.3 Wireshark抓包界面

5.3 云平台请求和响应报文分析

(1)     典型的无授权的API请求

适用于访问辅助类API和用户类的登录API。这类API在使用时,不需设置自定义的首部“Apikey”

例如,用户登录的请求实例

请求报文:

POST /api/login HTTP/1.1
Host: 218.244.138.146:8000
Accept: application/json
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

username=linpcloud&password=1234

(2)     带有APIKEYAPI请求

适用于访问所有需要进行权限判定的API

例如,获取用户信息的请求实例

请求报文:

GET /api/user HTTP/1.1
Host: 218.244.138.146:8000
Accept: application/json
Apikey: 1a39ad4c87ba09ef861ead97f010df7b
Cache-Control: no-cache

(3)     带有表单数据的API请求

适用于使用HTTP POSTPUT方法访问需要提交数据的API。这类API在使用时,需设置的首部” Content-Type: application/x-www-form-urlencoded”,并在请求正文中加入表单数据(键值对)。

例如,修改设备信息的请求实例

请求报文:

PUT /api/device/10003 HTTP/1.1
Host: 192.168.207.1
Accept: application/json
Apikey: 1a39ad4c87ba09ef861ead97f010df7b
Cache-Control: no-cache
Content-Type: application/x-www-form-urlencoded

name=device+from+Postman&tags=any+tags%3F&locate=Wuhan&about=This+is+a+device+created+by+Postman&user_id=10000

(4)     正常的API响应

200为状态码返回的HTTP响应,这标志着该API工作正常,返回了正确的数据。

例如,登录成功的响应实例。

响应报文:

HTTP/1.1 200 OK
Server: nginx/1.4.7
Date: Thu, 29 May 2014 15:38:02 GMT
Content-Type: application/json
Content-Length: 104
Connection: keep-alive
X-Powered-By: PHP/5.3.3

{"info":"Login Success","id":"10000","username":"linpcloud","apikey":"1a39ad4c87ba09ef861ead97f010df7b"}

(5)     已捕捉到错误的响应

适用于云平台系统设计时已经考虑到的可能出现的错误,并且进行了处理的情况。在该情况下,以400作为状态码返回响应信息,并在响应主体中包含了错误信息。

例如,登录时密码错误的情况的响应。

响应报文:

HTTP/1.1 400 Bad Request
Date: Thu, 29 May 2014 16:42:19 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.10
X-Powered-By: PHP/5.5.10
Content-Length: 53
Connection: close
Content-Type: application/json

{"info":"Login Fail: password or username incorrect"}

(6)     其它的错误响应

可能是PHP程序致命错误导致的错误信息输出,抑或CodeIgniter框架内部路由功能等环境出错。由于错误出现在云平台系统之外,云平台无法控制其输出。故而对于响应状态码不是200400的响应,我们认定为系统外的错误,云平台系统无法给出具体的信息。

例如,rest-server库无法找到方法时的响应。

响应报文:

HTTP/1.1 404 Not Found
Date: Thu, 29 May 2014 16:47:49 GMT
Server: Apache/2.4.9 (Win64) PHP/5.5.10
X-Powered-By: PHP/5.5.10
Content-Length: 42
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: application/json

{"status":false,"error":"Unknown method."}

5.4 云平台测试结果

云平台所有基本功能接口均已测试通过,但可能也存在遗漏的BUG,这需要在更多、更完善的测试之后才能够发现并修正。

因为论文篇幅有限,不可能将所有的测试实例及测试结果都罗列出来,故只给出几个重要模块的测试结果。

 

(1)     登录成功的响应结果

响应正文(格式化之后的JSON):

{
    "info": "Login Success",
    "id": "10000",
    "username": "linpcloud",
    "apikey": "1a39ad4c87ba09ef861ead97f010df7b"
}

 

(2)     获取设备列表成功的响应结果

响应正文(格式化之后的JSON):对象数组。

结果类似的还有获取传感器列表成功时的响应。

[
    {
        "id": "10008",
        "name": "RGB Light",
        "tags": "none",
        "about": "带颜色的LED灯,RGB颜色可调,亮度可调,附带开关",
        "locate": "Wuhan",
        "user_id": "10000",
        "create_time": "1399861186",
        "last_active": "1399861186"
    },
    {
        "id": "10009",
        "name": "Normal Light",
        "tags": "none",
        "about": "Normal light with a switch only.",
        "locate": "武汉",
        "user_id": "10000",
        "create_time": "1399861676",
        "last_active": "1399861676",
        "status": "1"
    }

]

 

(3)     获取单个设备信息的响应

响应正文(格式化之后的JSON):

{
    "id": "10008",
    "name": "RGB Light",
    "tags": "none",
    "about": "带颜色的LED灯,RGB颜色可调,亮度可调,附带开关",
    "locate": "Wuhan",
    "user_id": "10000",
    "create_time": "1399861186",
    "last_active": "1399861186",
    "status": "1"
}

(4)     创建设备成功的响应

响应正文:

{
    "info": "Create Device `10021` success",
    "device_id": 10021
}

(5)     删除设备成功的响应

响应正文:

{
    "info": "Delete device `10021` success"
}

(6)     获取单个设备所有传感器数据的响应

响应正文:

[
    {
        "id": "100005",
        "last_update": "1400502382",
        "last_data": "ffffff"
    },
    {
        "id": "100006",
        "last_update": "1400502382",
        "last_data": "30%"
    },
    {
        "id": "100007",
        "last_update": "1400502382",
        "last_data": "1"
    },
    {
        "id": "100009",
        "last_update": "1400595887",
        "last_data": "hello world"
    }
]

 

(7)     获取单个传感器的历史数据的响应

响应正文:

[
    {
        "id": "1017",
        "sensor_id": "100005",
        "timestamp": "1399906977",
        "value": "66ffcc"
    },
    {
        "id": "1023",
        "sensor_id": "100005",
        "timestamp": "1399907025",
        "value": "66ffcc"
    }
]

 

5.5 云平台测试结果分析

云平台的基本功能已经实现,并且具备了基础的错误控制能力以及错误信息提示功能,能够以JSON格式返回请求的数据,并且完成对设备、传感器的添加、查看、修改和删除功能。

本课题中的云平台的设计方案中并没有涉及界面的实现,而且就无线智能家居系统而言,控制界面的实现完全由控制终端和Web控制平台自主实现。该课题中的云平台仅负责完成数据的处理、存储与请求,负责协调控制终端、Web控制平台与智能家居网关之间的数据交互。所以,在云平台基础功能测试通过,能够返回正确的数据之后,我们认定该智能家居云平台基本方案设计已经完成。

对于无线智能家居系统而言,接下来需要智能家居网关、控制终端和Web平台实现同云平台的数据提交和获取,然后实例化设备,实现对实际设备的控制。

 


 

6 总结与展望

6.1 工作过程总结

本课题中智能家居云平台的设计更多地参考了Yeelink云平台的设计,将所有的操作抽象化为对数据的操作,待到系统开发完成后再进行设备和功能的标准化和实例化。云平台面向的用户群为开发者,为无线智能家居系统后期开发服务,将提供详细的API接口文档及说明。课题中主要完成了以下工作:

(1)     通过对两个较成熟的物联网云平台(Ninja PlatformYeelink云平台)的API文档的分析和解读,并结合无线智能家居系统自身的需求,确定了云平台的设计思想和基本设计方案:使用HTTP协议作为通信协议,JSON格式作为数据交互格式(暂时只用做返回数据格式),PHP作为编程语言,实现RESTful架构的API

(2)     确定了基于PHP框架的RESTful API基本开发流程。通过现实中智能家居系统的结构分析,还有对物联网云平台结构的研究,再配合云平台的需求分析、功能需求,完成了数据库结构的设计,建立数据库。然后依据PHPRESTful API的开发过程,结合PHP框架CodeIgniter和扩展库rest-server完成云平台各功能及API的设计。

(3)     通过合理的测试方法对云平台API进行了系统的测试,修复云平台系统BUG,完善云平台系统结构,并且结合测试结果,编写云平台API的说明文档。

 

最终,我们完成了智能家居云平台的设计,实现了论文中确定的实现目标,得到了一个用于支撑无线智能家居系统的远程控制功能的数据处理平台,编写了云平台的API说明文档,供给智能家居远程控制终端和Web控制平台使用。

 

6.2 不足及展望

虽然,本课题中的云平台已经设计完成,并且能正常运作。但因为云平台涉及内容不少,而且存在跨平台的数据交互以及API请求,故而设计方案中还有部分功能没有完善,而且测试案例也不够全面,可能存在某些尚未处理的BUG。这些问题需要在之后进行进一步的考虑和设计,才能得到解决。现阶段的工作完成之后,云平台已知的一些缺陷和不足有以下几点:

(1)   数据的安全性

使用普通HTTP报文传递的数据是透明的,我们通过抓包获取了HTTP报文之后,就可以获取报文中传递的内容。例如登录接口使用POST方法,用户名与密码都直接包含在请求报文内。为了保证数据的安全性,一般来说会使用HTTPS协议。但因为涉及跨平台的请求,我不确定在网关、控制终端访问使用HTTPS协议的接口时,是否会出现某些错误。

(2)   测试的局限性

由于无线智能家居系统没有完全实现,我们没有使用实际的设备来测试云平台的接口,云平台只测试了基本的数据提交和返回是否正确。也没有对多并发的请求进行测试,因此在实际使用中,出现很多请求时,云平台系统的稳定性并没有确切保证。

(3)   数据库结构的优化

在设计过程中,进行功能设计的时候,我们结合具体功能的要求多次修改了数据库结构。为了方便系统的实现,我们优先采用了简单有效的实现方法,数据库结构也相对简单。在下一步完善系统功能时,需要对数据库结构进行修正与完善,确保结构的合理性和完备性。

 

总而言之,本课题的智能家居云平台设计虽已完成,但与成熟的物联网云平台还有很大的差距,仍有许多待改进的方面。但云平台最核心的功能已经完成,已经可以使用其API进行控制终端和Web控制平台的开发。

 


 参考文献

[1] 张金家. 智能家居集成技术平台系统分析[J]. 智能建筑与城市信息, 2003(12): 22~25

[2] 李忠成. 智能仓储物联网的设计与实现[J]. 计算机系统应用, 2011(07): 16~18

[3] 查珑珑. 浅析物联网智能家居发展[J]. 科技信息, 2012(25): 42~43

[4] 童晓渝, 房秉毅, 张云勇. 物联网智能家居发展分析[J]. 移动通信, 2010(09): 16~20

[5] 巩元鹏. 基于XMPP协议的智能家居远程控制系统研究设计[D]. 中国海洋大学, 2012

[6] 王秀珍. 基于Web方式的智能家居远程监控系统的设计与实现[D]. 南京邮电大学, 2012

[7] 魏振春, 韩江洪, 张建军, 张利. 智能家居远程控制系统的设计[J]. 合肥工业大学学报(自然科学版). 2005(07): 752~754

[8] 陈康, 郑纬民. 云计算:系统实例与研究现状[J]. 软件学报, 2009(05): 1337~1348

[9] 陈全, 邓倩妮. 云计算及其关键技术[J]. 计算机应用, 2009(09): 2562~2567

[10] 张建勋, 古志民, 郑超. 云计算研究进展综述[J]. 计算机应用研究, 2010(02): 429~433

[11] 薛宏全, 杨琳. 嵌入式智能家居系统连入Internet的研究和实现[J]. 现代电子技术, 2007(13): 175~177

[12] Fielding R T. Architectural styles and the design of network-based software architectures[D]. University of California, 2000.

[13] Satio T, Tomoda I, Takabatake Y, et al. Home gateway architecture and its implementation. IEEE Transactions on Consumer Electronics. 2000

[14] 潘凯华. PHP从入门到精通[M]. 北京:清华大学出版社, 2010

[15] David Gourley, Brian Totty. HTTP权威指南[M]. 北京: 人民邮电出版社, 2012(09)

[16] W.Jason Gilmore. PHPMySQL 5程序设计[M]. 北京: 人民邮电出版社, 2007(01)

[17] Hypertext Transfer Protocol--HTTP/1.1. http://www.w3.org/Protocols/rfc2616/rfc2616.html

[18] Apache HttpClient 4.3.3 API. http://hc.apache.org/httpcomponents-client-4.3.x/httpclient/apidocs/index.html

[19] Google Gson 2.2.4 API. http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html

[20] Nginx Documentation. http://nginx.org/en/docs/index.html

[21] MySQL 5.6 Reference Manual. http://dev.mysql.com/doc/refman/5.7/en/

[22] PHP Manuel. http://www.php.net/manual/en/

[23] CodeIgniter User Guide Version 2.1.4. http://ellislab.com/codeigniter/user-guide/

[24] CodeIgniter Rest Server Introduction. https://github.com/philsturgeon/codeigniter-restserver

[25] Yeelink API文档. http://www.yeelink.net/developer/api

[26] Ninja Blocks API. http://docs.ninja.is/

 





附件列表

 

posted @ 2015-10-18 10:47  FeMiner  阅读(14480)  评论(0编辑  收藏  举报