物联网实践之——一步一步"徒手"建立智能家具远程控制系统

首先非常感谢,上篇文章中一些前辈的指导,其中一些意见让我获益匪浅!

关于物联网,我觉得灵魂还是在软件上,前端的各种硬件联网标准一旦形成也就没啥事了,更多的仍然是数据的存储,分析。其实,物联网说白了更是一种数据服务一条龙。从数据的采集到数据的传送以及数据的存储和处理。数据的传送就不用说了,属于通信的范畴,属于宽带和三大运营商的领地,数据的的采集属嵌入式的范畴,数据的存储可能一般的程序员和DBA就可以搞定,最有核心的部分就是数据的分析了,只可惜做数据挖掘和大数据处理的,大都是博士和硕士级别的吧!所以做为一名普通的二本毕业生,我准备将目标锁定在嵌入式的方向,准确的说是嵌入式软件开发工程师。

一直以来常常张口物联网,闭口智能家具,终于在最后的时间里,付出了实践,做了一个基于嵌入式Linux的智能家具远程控制系统,当然系统在不断的完善,目前已经实现了远程控制和环境信息实时上传的功能。希望各路大牛,多拍板砖,多提指导性意见。

本文的主要目标是展示系统的服务器,关于嵌入式环境搭建/驱动的编写,不详细说明。

在实现智能家居控制系统之前,我们需要搭建一个人机交互界面,这里我主要采用了HTML页面,也就是最终实现的目标是,人们可以在有网络的地方登陆位于家里的嵌入式WEB服务器,然后通过这些网页来进行用电器的操控,同时,也可以将家里的实时环境值传送到HTML页面,你可以远程查看居室内的环境信息,远程为家人打开空气净化器或者是空调。

STEP 0:开发准备

宿主机:Ubuntu操作系统

开发板:FriendlyARM mini2440

驱动程序:LED驱动,温度传感器驱动

相关技术准备:Socket编程/HTTP协议/JavaScript

STEP 1:实现WEB服务器

嵌入式虽然小,但还是有一批开源的服务器是可供选择的,比如大名鼎鼎的boa,小巧强悍。我在最开始的时候也是选择移植boa服务器作为智能家具的服务器,但是后来在添加家具控制模块和温度传输模块的时候觉得很不方便,于是呼就决定手动打造一个服务器,虽然和boa相差十万里,但是学到的东西也更多,而且对web的机理有了更深刻的认识,觉的作为一个学习者,值了。

在徒手开发服务器之前,你必须要知道,web底层的工作机理,说到这里有一个段子,有一次我去面试,岗位是java web,boss问我你对web有什么认识,我随口一说:“其实web说到底就是socket和http”,后来在一次聚餐的时候boss给我说:“当听到一个还未毕业的学生对web能有如此认识,感到很意外,所以即使你没有经验我也还是会雇佣的。”看来,有时候吹牛逼真的很管用,哈哈。

虽然是吹牛逼,但web的实质的确是socket和http协议,浏览器端我不清楚也就不乱说了,但是我擦浏览器里面一定有个socket来和我们的服务器进行通信。接下来详细说说我们的服务器端,服务器要想和浏览器取得通信,首先需要建立一个socket,然后就是传统的网络编程,但是要注意,服务器和浏览器进行“对话时”,使用的是“HTTP”语言。也就是说web的实质是HTML+SOCKET+浏览器。然而socket又是tcp/ip协议的程序实现层,因此web的实质就是html+TCP/IP+浏览器。然而HTML的实质又是文件,因此web的实质又是 文件+TCP/IP+浏览器(文件翻译器(特殊文件翻译器))。关于浏览器我是在研究的不多,不敢乱说。

因此,总结成一句话就是:“WEB就是向一台被称为服务器的计算机上请求文件,服务器将指定文件发送到浏览器,然后浏览器解析文件并展示的一个过程”。

        server_sockfd=socket(AF_INET,SOCK_STREAM,0);
        if(server_sockfd<0)
        {       printf("create socket failed!\n");
                exit(EXIT_FAILURE);
        }
        memset(&server_addr,0,sizeof(server_addr));
        server_addr.sin_family=AF_INET;
        server_addr.sin_port=htons(PORT);
        server_addr.sin_addr.s_addr=INADDR_ANY;

        if(bind(server_sockfd,(struct sockaddr*)&server_addr,sizeof(server_addr))!=0){
                printf("bind error!\n");
                exit(EXIT_FAILURE);
        }

经过上面的操作,已经为服务器创建了一个socket,也为socket绑定ip地址和端口,这样一来,就为我们的服务器在茫茫的网络海洋中有了准确的定位。
关于socket和sockaddr_in,我一直是这样理解的,一个socket相当于一部手机,如果你想别人能够打通你的手机,首先你要有一个SIM卡,而这个sockaddr_in则相当于sim卡,一旦和你手机绑定后,别人(客户端)就可以向你发起呼叫。
接下来就是socket编程的一般步骤,Listen和accpect,相当于你的手机装上了SIM卡并且打开了手机,等待别人的呼叫。

client_sockfd=accept(server_sockfd,(struct sockaddr*)&client_addr,&addr_len);

accpect函数实现阻塞程序的继续进行,直到有客户端发起请求,当有客户端发起请求的话,accpect函数返回这个链接的描述符号。返回的结果代表客户端与服务器的链接描述,下面可以直接用这个描述符来代表已经建立的链接关系。

进行到此时,好比一个人拨通了你的电话并且你接听了电话,此刻你们的链接建立了。你可以用耳朵贴在话筒上听那人说了些什么,在我们的程序里你同样可以用recv来接听客户端都发送了那些请求。
int recv_len=recv(client_sockfd,buffer,sizeof(buffer),0);
其中,buffer代表接收到客户端请求信息以及该客户端的相关信息。仿佛那人给你说的那些话。
关于buffer会是什么内容,相信没有接触过的人都很好奇,我也一样,于是乎打印了出来(前提是我在浏览器地址栏输入了http:127.0.0.1:8000/main.html):

GET /main.html HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:34.0) Gecko/20100101 Firefox/34.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Connection: keep-alive

接下来就发现了这些有意思的东西(不要笑我,我真的是小白),第一次看见这东西真的很惊奇。看到了这里我瞬间明白了很多东西:
1 如果我又一个服务器,我能知道,那些ip访问了我的服务器,访问了多少次,地理位置在哪里。
2 我知道了他用的什么浏览器
3 我知道了他的主机是什么系统,还有有关本次链接使用的语言/编码方式/链接类型。。。

其实,我们最关心的就是第一句,第一句是它(客户端)想GET main.html;意思是浏览器想向服务器请求main.html。

好了,如果你想在浏览器成功展示出main.html,你需要将main.html整个文件发送给客户端,但是请注意第一句“GET /main.html HTTP/1.1”,有没有发现它们有着特殊的形式,这就是WEB的语言吧,暂且这样称呼它。如果我们直接调用write函数将main.html发送给客户端,客户端会不会觉得太迷茫,它会觉得发了一坨什么东西,因此在这里服务器也要以类似的形式首先给浏览器发送一段类似的文字然后将整个main.html文件发送过去:
HTTP/1.1 200 OK\r\n
Conten-Type:html\r\n
发送main.html的完成代码如下:

 1 sprintf(buffer,"HTTP/1.1 200 OK\r\n" 2                    "Conten-Type:%s\r\n" 3                    "\r\n",mine_type);
 4 int file_length=strlen(buffer);
 5 do{
 6          if(write(socket_fd,buffer,file_length)<0){
 7                      close(fd);
 8                      break;
 9                                                    }
10    }while((file_length=read(fd,buffer,sizeof(buffer)))>0);

其中mine_type为文件的类型,比如jif,png,html等等。
至此,一个完整的会话就完成了,一个超级无敌简易的网页浏览器也就搞定了。

STEP2:智能家具控制模块


严格的说,这是web服务器的扩展模块,就是这个服务器不仅能够提供网页的文件资源,还可以调用驱动来进行硬件的操作。
比如要进行灯光控制,在html页面里有一个灯泡的图片按钮,当点击按钮的时候,用JavaScript想后台发送制定的请求内容,比如发送请求内容为:“myled.cgi”,注意这里的后缀不代表请求一个cgi的文件,因为服务器是自己的写的自己解析的,想代表什么自己说了算,就tm这么任性和这么爽!这里我指定它代表灯光控制部分。

1  int recv_len=recv(client_sockfd,buffer,sizeof(buffer),0);
2  printf("*****%d bytes recved!***********\n",recv_len);
3  p_buffer=buffer;
4  if(0==strncmp("GET /myled.cgi",buffer,14))
5  {
6       printf("hello,heat nan!\n");
7       send_light_cmd(p_buffer,client_sockfd);
8
9  }

以上的代码,我首先判断它请求的操作是否为灯光操作,如果是则将这些信息作为参数传递给灯光模块处理。
关于灯光模块分为两个部分,一个部分是确定对那个灯进行操作,第二个部分是执行硬件操作,如果是用电器的开关 ,则主要是设置与用电器绑定的IO口电平。

STEP3:实时环境信息模块


关于实时环境信息模块和智能家具控制模块如出一辙,首先当用户进入环境信息界面,ajax主动向服务器每10s发送一次温度请求,服务器接受到指令后,马上调用温度传感器驱动采集一次温度,然后将温度传递到前端的html页面,如此让用户每隔10ms看到家里的温度一次,也算实时吧!
至此,一个家居远程控制系统就算完成了,不能叫系统吧!此时感觉如此之小 ,叫个小demo吧!

此时此刻,家里的电器确实是连上网了,应该可以叫做“物联网了吧!”
如果将采集的温度值不断的和设定喜好温度值作比较从而让程序自动控制空调和地暖的开关,这应该叫“智能家居了吧!”。

然而,这应该是现实的物联网;
理想的物联网应该是这样:

你的空调会受到一个巨大的数据平台做支持,这个数据平台分别连接了最权威的健康机构,可以提供不同时节/不同时间段最健康的温度,你的空调会和你的手机相互通信,手机会告诉空调,孩子主人距离家里10公里,请你立马工作。空调应当会有记忆功能,分别记住主人在不同时段,不同季节最喜爱的温度,你的空调应当和你的手环相连,当你在左手跟着右手一个慢动作的时候,手环会向空调发出指令,孩子主人心跳加速,体温上升,速度降温,从而不会让你大汗淋漓。
如果当这一天真的来临,请叫他真正的物联网时代吧!

时间: 2024-08-28 13:37:58

物联网实践之——一步一步"徒手"建立智能家具远程控制系统的相关文章

一步一步跟我学习lucene(9)---lucene搜索之拼写检查和相似度查询提示(spellcheck)

suggest应用场景 用户的输入行为是不确定的,而我们在写程序的时候总是想让用户按照指定的内容或指定格式的内容进行搜索,这里就要进行人工干预用户输入的搜索条件了:我们在用百度谷歌等搜索引擎的时候经常会看到按键放下的时候直接会提示用户是否想搜索某些相关的内容,恰好lucene在开发的时候想到了这一点,lucene提供的suggest包正是用来解决上述问题的. suggest包联想词相关介绍 suggest包提供了lucene的自动补全或者拼写检查的支持: 拼写检查相关的类在org.apache.

Rhythmk 一步一步学 JAVA (21) JAVA 多线程

1.JAVA多线程简单示例 1.1 .Thread  集成接口 Runnable 1.2 .线程状态,可以通过  Thread.getState()获取线程状态: New (新创建) Runnable (可以运行) Blocked  (被阻塞) Waiting  (等待) Timed waiting (计时等待) Terminated  (被终止) ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27

大流量网站性能优化:一步一步打造一个适合自己的BigRender插件(转)

BigRender 当一个网站越来越庞大,加载速度越来越慢的时候,开发者们不得不对其进行优化,谁愿意访问一个需要等待 10 秒,20 秒才能出现的网页呢? 常见的也是相对简单易行的一个优化方案是 图片的延迟加载.一个庞大的页面,有时我们并不会滚动去看下面的内容,这样就浪费了非首屏部分的渲染,而这些无用的渲染,不仅包括图片,还包括其他的 DOM 元素,甚至一些 js/css(某些js/css 是根据模块请求的,比如一些 ajax),理论上,每增加一个 DOM,都会增加渲染的时间.有没有办法能使得

【转】朱兆祺带你一步一步学习嵌入式(连载)

原文网址:http://bbs.elecfans.com/jishu_357014_2_1.html#comment_top  从最初涉及嵌入式Linux开始到现在,深深的知道嵌入式的每一步学习都是举步维艰.从去年11月份开始,我就着手整理各种学习资料,希望推动嵌入式学习的前进贡献自己微不足道的一份力量.从去年到现在,将C语言的学习经验整理成<攻破C语言笔试与机试陷阱及难点>(现在仍在更新),这份资料已经在电子发烧友论坛的单片机论坛连载(http://bbs.elecfans.com/jish

值得我们深入研究和学习:从零开始一步一步搭建坚不可摧的Web系统主流架构

本文标签: Web系统主流架构 搭建Web系统架构 缓存服务器 数据库架构   技术型初创公司  互联网杂谈 主题简介: 1.网站系统架构当前现状 2.Web系统主流架构解析 3.互联网技术团队初期组建经验分享 本文主要结合我之前在海尔电商平台和现在公司的一些实际架构经验,综合实际情况和个人的理解,跟大家分享一下搭建Web系统的一些常用的技术架构和应用技巧. 首先要跟大家探讨一个问题,就是当前传统IT企业或是传统企业的IT系统目前的系统架构是怎样的呢? 就我所经历的NEC软件.海尔集团.青岛航空

一步一步跟我学习lucene(14)---lucene搜索之facet查询原理和facet查询实例

Facet说明 我们在浏览网站的时候,经常会遇到按某一类条件查询的情况,这种情况尤以电商网站最多,以天猫商城为例,我们选择某一个品牌,系统会将该品牌对应的商品展示出来,效果图如下: 如上图,我们关注的是品牌,选购热点等方面,对于类似的功能我们用lucene的term查询当然可以,但是在数据量特别大的情况下还用普通查询来实现显然会因为FSDirectory.open等耗时的操作造成查询效率的低下,同时普通查询是全部document都扫描一遍,这样显然造成了查询效率低: lucene提供了facet

一步一步跟我学习lucene(7)---lucene搜索之IndexSearcher构建过程

最近一直在写一步一步跟我学习lucene系列(http://blog.csdn.net/wuyinggui10000/article/category/3173543),个人的博客也收到了很多的访问量,谢谢大家的关注,这也是对我个人的一个激励,O(∩_∩)O哈哈~,个人感觉在博客的编写过程中自己收获了很多,我会一直继续下去,在工作的过程中自己也会写出更多类似系列的博客,也算是对自己只是的一种积累: IndexSearcher 搜索引擎的构建分为索引内容和查询索引两个大方面,这里要介绍的是luce

教你一步一步部署.net免费空间OpenShift系列之一------帐号注册和验证

前几天有博友发布了一篇文章<一键部署mono 免费空间支持ASP.NET MVC 再也不担心伙食费换空间了>,支持MVC3和域名绑定,觉得不错,于是自己实践了一下,发现自己实际遇到的问题真不少,而且网上的关于此空间的帖子要么千篇一律,要么语焉不详,现总结为图文教程系列 帐号注册和验证 打开https://www.openshift.com/products/pricing,出现三种选择,前2种是免费的,建议选择第二个. 点击Create one跳转到创建用户界面 看到如下信息,填写邮箱和密码,

一步一步点亮Led

1.了解物理特性 点亮LED的关键在于电压差 2.查阅原理图了解板载LED的硬件接法 方法:可以利用PDF文档的搜索功能(搜索LED即可,在底板搜索) 可知:有4颗正极接3.3V,负极分别接SoC上面的引脚(即引脚低电平亮),另外一个开机常亮. 3个SoC引脚是知道的,另外在核心板上查看pwmtout1可知引脚为GPD0_1,如下图 GPD0表示端口号,后面的1是引脚号 3.查阅数据手册 当我们想要编程操控GPIO来操作LED时,需要通读一下数据手册关于GPIO的部分 我们要操作的硬件为LED,