分享

DIY:使用云计算平台快速搭建嵌入式互联网通信模型

 共同成长888 2015-07-19

DIY:使用云计算平台快速搭建嵌入式互联网通信模型 

对于一个DIYer来说,想用嵌入式实现互联网通信(比如WEB网页浏览,智能家居远程控制等)这样的功能,最头痛的不是嵌入式部分的设计,而是服务器端的搭建,首先遇到的就是私有IP访问的问题,除非你能申请到一个固定IP,让嵌入式内部写入这个固定IP来进行访问,不过DIY一般都没有这样的条件,服务器端的IP地址是动态变化的,你只能使用动态IP+NAT穿透,这样就必须使用域名来访问,有一种方法是申请花生壳动态域名绑定,但是这种绑定一般需要 ADSL+有动态域名绑定功能的路由器;另外,就算搞定了服务器访问的问题,接下来你还得使用各种服务器端编程脚本为服务器编程,总之就是麻烦重重,自己搭建服务器很难做到稳定的访问质量以及良好的模型设计。


我找到了一种方法能够一秒解决上面的问题:使用云计算平台技术!直接把服务器放置到云端,每个嵌入式设备都相当于客户端连接到云端,用户也通过WEB浏览器或手机APP访问云端,这样的技术能够使通信模型的设计难度大大降低,并且成本很低,很适合DIY设计。我已经使用这种技术成功设计了一个GPS跟踪器,可以使用浏览器实时查看设备的具体位置,使用百度地图显示出来,接下来就一一描述这一设计流程。




如上图所示,GPS设备负责实时采集地理坐标,并通过一个GPRS模块接入互联网,实时将坐标传送到服务器,服务器接收到坐标之后在缓存中刷新,用户在浏览器(PC或手机或PAD浏览器都可以)中访问服务器的WEB页面,在浏览器中显示地图,完成这一追踪过程。按照一般的做法,需要一台实体的服务器,你可以使用你的PC主机当服务器,但这台主机需要24小时不间断运行,并且假设你的主机网络接入是ADSL,你还需要去申请一个域名,以便让GPRS设备和任意浏览器都能访问到你的服务器,如果你是校内网,那就基本没戏了,因为校内网是经过多层路由的,无法进行外问NAT穿透,也就无法让外部访问到你的主机。


我使用云计算平台技术PK掉了实体服务器,GPRS设备和用户浏览器可以在任意时间任意地点轻松访问到服务器。什么叫云计算平台?其实就是一个服务器群,你只需要拥有一个应用账号,将服务器代码上传到你的云空间,不需要知道你的代码具体运行在什么地方,甚至连提供商都不知道它到底放在哪里,这就是云的概念。目前国外大型的云有谷歌、亚马逊、微软等公司,国内的有新浪、百度、盛大等,最好用的是谷歌,但...GFW,你懂的,国内访问谷歌很不稳定,经常会被查封,所以国外产品基本没有选择的希望。再看国内,个人觉得目前做得比较好的是新浪,已经推出一整套解决方案,并且已经有各种应用在其上面,百度云比较麻烦,现在还不是很成熟,并且在其上面开发应用需要得到其邀请码,综合考虑我使用了新浪云,官网地址:http://sae.sina.com.cn/ 



新浪云(Sina App Engine简称SAE)使用七层沙箱模型,提供了PHP、JAVA、PYTHON等编程语言,但是目前只开放了PHP,JAVA和PYTHON正在测试无法使用,我选择了PHP;SAE里面提供了大量你所需要的服务,包括SQL数据库,MEMCACHE,Storage大容量存储等,足够开发一般的 WEB应用。


PHP是一种在服务器端执行的脚本语言,适用于制作动态页面,语言风格类似C语言,浏览器申请PHP页面的时候服务器会将PHP页面里面的PHP语句执行然后生成标准的HTML文档发向浏览器,在本地编写PHP需要在PC布置PHP环境,绝大多数环境都使用"LAMP"架构,即:LINUX操作系统+APACHE服务器+MYSQL数据库+PHP脚本,当然也可以在WINDOWS里面开发,可以在WINDOWS里面安装APACHE服务器,亦可以使用WINDOWS的IIS服务。我选择使用LAMP环境,在UBUNTU里面安装了APACHE,在UBUNTU里面将代码测试完毕之后使用SVN工具将代码上传到云空间,上传流程在SAE的官网有详细的教程可供参考:http://sae.sina.com.cn/?m=devcenter&catId=20

在UBUNTU里面使用命令行打开gedit编辑器即可开始编写你的PHP代码




在APACHE中设置根目录为你的PHP代码所在目录,将文件类型设置为PHP,浏览器访问本机的时候即可执行PHP代码,我测试写了一行PHP代码如下,向屏幕打开“hello world”



在本机浏览器中访问:localhost/test.php即可即得访页面:



表示环境布置成功,接下来可以尽情编写你的PHP代码了!

/****************************************************网络编程方面一系列关键技术点*********************************************/

A,如何向服务器上传GPS坐标
向服务器上传信息,首先需要确定一种网络通信协议,如果是自己搭建实体服务器,则可自由选择各种协议,比如面向数据报类型的UDP,面向连接的TCP等等,但是在云平台中,因为云平台是一种用于WEB的服务,目前仅开放了HTTP协议,用户仅可以通过80端口利用HTTP跟服务器通信,所以嵌入式设备必须实现一个HTTP通信协议并用按照HTTP协议以及WEB支持的数据交换格式AJAX技术进行坐标上传。

HTTP 协议基于文本传输,客户端使用“GET”、"POST"等方法进行请求,关于HTTP的更多详细资料可百度搜索,本文仅针对"GET"进行描述;“GET”主要用于用户向服务器请求一个页面,没错,所有的HTTP通信都是要由客户端首先发起访问的,服务器端响应用户需求并返回页面之后立刻断开链接,客户端再次请求页面需要再次连接。那如何使用
“GET”上传数据呢?你打开一个普通页面的时候经过可以看到输入栏里面的网址后面会带一长串数据,那些数据就是浏览器向服务器上传的参数,比如你在百度搜索的首页输入框里面输入“HTTP”点击搜索,会发现网址栏会变成:http://www.baidu.com/s?wd=HTTP&rsv_spt=1&issp=1&rsv_bp=0&ie=utf-8&tn=baiduhome_pg&rsv_sug3=2&rsv_sug=0&rsv_sug4=299&rsv_sug1=1并且页面跳转到搜索结果,这串URL中从“?”号后面开始即为一个"GET"的请求参数,根据不同,需要参数的页面请求会事先定义好每个参数并且接收客户端的参数进行解析并返回相应的结果,你可以试试打开一个空白页面并输入:http://www.baidu.com/s?wd=HTTP 页面会跳转到百度对“HTTP”的搜索结果,这时你就人工完成了一次附带参数的“GET”请求。

根据这种原理,我在服务器中编写了一个页面用于测试GET参数是否成功工作


页面接收一个名字为test的请求,判断该参数是否等于2013,如果是则返回right,否则返回you are wrong,在浏览器中输入localhost/gettest.php?test=2013返回正确。所以使用GET来上传数据是可行的。

B,服务器如何保存GPS坐标
服务器在执行完一个PHP页面之后将销毁页面中所有变量,PHP是动态脚本,在PHP中没有所谓的“全局变量”,想保存接收到的数据必须另想办法。有一种方法是创建一个数据库,每次将数据更新到数据库中,但是要在这种小型应用中使用数据库未免太大材小用了,可以使用memcache来保存,SAE中支持 memcache服务:http://sae.sina.com.cn/?m=devcenter&catId=201 memcache是一个缓存区,可以保存临时数据但不会随着页面消失,而且速度高于sql,在SAE中使用memcache必须向在该应用中开通memcache服务,并且在设置中声明你所需要的变量名字,这些在SAE官网中均有介绍

C,如何显示地图
显示地图需要另外一种脚本语言:javascript,javascript是一种在浏览器端执行的脚本编程语言,很多网页地图如谷歌、百度、高德等都提供了API代码供你在网页里使用,只要在你的网页中包含了其js源,即可在网页中正常调用地图并显示。谷歌,shit,又是因为GFW,谷歌很不稳定,基本没戏,使用百度地图吧,百度开发者中心官网提供了详细的教程教你如何简单地使用百度地图API http://developer.baidu.com/map/ 里面提供了一份基本的调用代码,在你的页面中包含它就可以正常使用,当然了,前提是你需要有一点基础。



GPS 设备定时向云平台递交坐标信息,云平台刷新保存到memcache;浏览器在打开页面之后开始绘制地图,并定时向云平台的一个PHP页面申请实时坐标,刷新显示到浏览器中;整个网络工作框架就大致如此。PK掉了实体服务器!是不是瞬间感觉到让你的设计接入网络部分容易多了?没错,这就是云时代,它来了,别再想着自己折腾自己的电脑当服务器了,当然了,这些网络编程语言以及技术基本得懂。

/******************************接下来是嵌入式系统一系列关键技术点****************************************/

硬件框架图


主要由三部分构成,一个MCU,一个GPS模块,一个GPRS模块;MCU负责采集GPS坐标并转换成符合百度所需要的格式,GPRS模块打开连接并向服务器上传坐标。MCU采用STM32F103C8T6来做,具有20KB内存,128KB FLASH存储,72MHz主频,够我挥霍了。GPS模块采用TELIT JN3模块,输出标准NMEA格式的坐标信息,首次搜星30秒左右,可电池保存数据。GPRS模块采用QUECTEL M50模块,通过串口与MCU通信,使用AT指令集格式。

硬件部分架构很简单,就不上传照片了,下面主要是描述嵌入式编程方面的技术点。

A,UC/OS III嵌入式实时操作系统 
要完成这样一个系统编程,虽说应用不大型,但如果使用裸机编程,会使代码变得臃肿,不利于移植和新应用的加入,既然MCU资源都这么足了,跑个OS kernel是必须的了。选择了UC/OS III内核,与UC/OS II的区别是增加了时间片轮询调度算法,可以让多个任务处于同一层优先级进行时间片轮转运行。在
UC/OS III进行模块化设计,在底层为GPS和GPRS模块设计好一个驱动模型,封装之后向上层应用提供API函数调用。

B,GPRS驱动模型
GPRS 模块使用AT指令集进行通信,功能包括通话、短信、GPRS接入;如果只是完成一个互联网访问的功能,是很简单的,但要做到稳定却很有难度,比如网络通信中突然遇到无信号的时候会中断传输,这时候MCU需要侦测出来并做处理,在超时之后命令模块断开并重连,并且这部分超时等待必须不能影响到操作系统中其他应用程序对GPRS驱动的访问。我使用三个线程来完成一个GPRS的驱动任务,结构如下:


对模块的操作都是基于AT指令集,经过对指令集的功能进行分类之后可分为两大类,一类属于操作型指令,只返回“OK”或者"ERROR",这类封装成一个统一的函数进行调用,另一类属于返回具体数据,需要对具体的指令进行单独处理;整个通信模型都是基于这种分类操作的思想进行设计。

数据接收线程负责接收模块的数据,来自模块的数据又分为两种类型,一种是普通的命令返回,开头和结尾都带有回车+新行符,一种是网络的二进制数据返回,这种直接返回具体的数据;接收线程必须能识别到这两种类别,并且根据当前的工作状态将接收到的回应通过UC/OS III提供的邮箱功能分别送往不同的队列,即完成一次接收过程。

网络通信线程专门负责处理GPRS事务,包括TCP/UDP连接,发送,接收等功能,我在系统中将这些功能封装成类socket接口的形式,以便于与PC编程环境相似,降低应用层的开发难度,比如一个连接API:
 

void GPRS_Connect(GSM_GPRS_STRUCTURE *psStr ,
GPRS_ACCESS_MODE AccessMode ,
GPRS_ACCESS_PROL_TYPE ProlType,
CPU_CHAR *ConnectAddr ,
CPU_CHAR *ConnectPort ,
GPRS_ERR_CODE *GPRSErrCode)

这个函数用于打开一条TCP/UDP连接,该函数接收一个
GSM_GPRS_STRUCTURE结构体指针,这个结构定义如下:
/*
 * @type struct
 * @name GSM_GPRS_STRUCTURE
 */
typedef struct{

 
/* the No of the connect point*/
CPU_CHAR GPRSConnectPointNo ;

 
/* the type of network access mode*/
GPRS_ACCESS_MODE GPRSAccessMode;

 
/* the type of access protocol*/
        GPRS_ACCESS_PROL_TYPE GPRSAccessProlType;

 
/* the address to access*/
CPU_CHAR *GPRSAccessAddr ;

 
CPU_CHAR *GPRSAccessPort ;

 
GPRSStatusCode ConnectStatusCode ;

 
OS_Q qGPRSRequestMsg ;

 
OS_Q qGPRSRecMsg ;

 
}GSM_GPRS_STRUCTURE;

结构体包含一个GPRS模块网络连接点号,一个GPRS访问模式标志字节用于标志该连接是用IP地址还是域名访问,一个协议类型标志字节用于标志该连接是用 TCP还是UDP进行连接,接下来是访问地址,端口号,连接状态,最后附带两个消息邮箱队列,一个用于请求事务,一个用于接收网络数据。用于标志状态的字节均使用枚举类型来表示,这样可以使整个结构看起来很明确,看其名字就知道其作用,以及其有限个状态的类别。

该函数中最后需要一个很重要的参数: 
GPRS_ERR_CODE *GPRSErrCode 用于返回函数的操作结果码,这个结果很重要,因为应用程序在进行一个连接的时候,模块此时可能处于无信号状态,也有可能SIM卡无话费、GPRS服务无开启、该连接已存在等多种情况导致连接不成功,应用程序需要知道连接的结果才能进行下一步处理,这个返回的结果码向应用程序提供了连接的结果,让应用程序可以知道状态,其定义使用枚举类型,如下:
 

/*
 * @type enum
 * @name GPRS_ERR_CODE
 */
typedef enum{

 
/*0 no error连接成功*/
GPRS_ERR_None = 0 ,

 
/*1 the GPRS connect pond have no enougth space模块的连接池已满*/
GPRS_ERR_ConPondFull ,

 
/*2 fail to start the GPRS serviceGPRS服务开启失败*/
GPRS_ERR_ServiceStartFail ,

 
/*3 fail to refresh the GPRS net status刷新网络状态失败*/
GPRS_ERR_RefreshNetStatusFail ,

 
/*4 TE is in calling模块正在通话中,无法连接*/
GPRS_ERR_Calling ,

 
/*5 GSM have no register网络未注册*/
GPRS_ERR_GSMNoRegister ,

 
/*6 GPRS no service无GPRS服务*/
GPRS_ERR_GPRSNoService ,

 
/*7 the connect have aready连接已存在*/
GPRS_ERR_ConnectAlreadyExs ,

 
/*8 couldn't to set the access mode无法设置访问模式*/
GPRS_ERR_SetAccessModeFail ,

 
/*9 couldn't to malloc the memory申请内存失败*/
GPRS_ERR_MallocMemFail  ,

 
/*10 the instruction to the TE is error指令错误*/
GPRS_ERR_InsError ,

 
/*11 fail to connect to the enternet无法连接到互联网*/
GPRS_ERR_ConnectFail ,

 
/*12 the connect is closed连接已关闭*/
GPRS_ERR_ConnectClosed  ,

 
/*13 wait time out超时*/
GPRS_ERR_TimeOut ,

 
/*14 fail to send发送失败*/
GPRS_ERR_SendFail  

 

}GPRS_ERR_CODE; 

如上所示,在整个系统中,绝大多数函数都会返回一个操作结果码用于告知调用者函数执行的结果,基于这种机制,可以使程序在调试阶段很简单,及时修改BUG,在正常应用阶段保证高度的稳定性。

C,HTTP网页请求
模块只提供TCP连接功能,这需要我们自己使用TCP来封装一个HTTP协议,本应用很简单,只需要向服务器端索取一个带参数的页面即可,但有一点需要警惕,SAE使用HTTP1.1协议,并且在后面需要HTTP文本中需要带一个HOST参数,该参数后面设置为你需要访问的应用的域名:
首先打开一条TCP连接,我申请了一个个人应用,域名为:defensorhsb.sinaapp.com,使用80端口连接:
 

GPRS_Connect(&ConnectTest ,
GPRS_ACCESS_MODE_DN ,
GPRS_ACCESS_PROL_TCP ,
"defensorhsb.sinaapp.com" ,
"80" , 
&GPRSErrCode) ;

 
连接成功之后接下来需要发送数据,需要组装一条标准的HTTP报文,如:GET /updateloc.php?id=2013&lat=0&lng=0 HTTP/1.1\r\nHOST:defensorhsb.sinaapp.com\r\n\r\n,其中lat参数为纬度值,lng为经度值,服务器接收之后解析成功将会返回ok,如果格式失败将会返回error(ok和error是我自己的PHP页面中定义的),如果收到OK,表示坐标已成功上传到服务器,嵌入式端的工作完成了!为了达到实时效果,需要嵌入式设备每隔一定时间递交坐标。

/*********************************************************************** 最终效果*******************************************************************************/

最后我使用javascript开源库写了一个个人主页,在个人主页里面设置一个链接指向我的地图页面,在任意时间任意地点访问我的主页都能够显示出我的设备的具体位置!

这是我的个人主页地址:http://defensorhsb.sinaapp.com   

因为是调用开源Js库的关系,可能首页访问会有点慢,可以直接访问 http://defensorhsb.sinaapp.com/index.php 进入地图页面,速度很快
 

首页效果如下:


点击“玩玩看”菜单里面的“看看我在哪里”即可跳转到我的地图页面:


地图中显示的位置即是我家那边的位置:


一个GPS定位设备就这样DIY出来了!你可以在任何地方任何时间使用任何设备访问到你的页面!!!!!!!!!
 
就这样,一个嵌入式+互联网的通信模型就搭建完成了,而且这个服务器成本很低,我现在在新浪进行了实名认证,这样一个应用每天只需要5个云豆租金(100云豆=1RMB),算下来一个月只需要3毛钱租金,如果你的访问量不大,个人玩玩的话,这个成本确实很低很低了,但如果访问量大就另外计算了,具体资费可到 SAE官网查看。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多