|
飞比物联网培训教程--"玩转物联网"之四、web网页控制Zigbee电灯(B/S模式)
该系列文章已经全部更新至“飞比云百科知识库(FBee Cloud WIKI)”中,建议到以下网址阅读:http://www.fbeecloud.com/wiki
这是很好玩的一步:把自己的传感器用网页画出来,放在自己的服务器上,别人可以登录你的网站,查看你传感器的值;或者把自己的“电灯”放在网页上,别人可以来开关。当然,“别人”一定事先要征求你的同意才可以这样做,否则你卧室的灯,一会就有人来开一下,这样的“高科技”估计没人愿意要!
而且这种B/S模式的最大好处就是只要有一个浏览器(Brower)就可以了,不需要装别的软件,而且不管你用的是电脑,PAD还是手机,是windows、iOS或者是Android的操作系统。
我们重新来回顾下“飞比云”平台的拓扑结构中,用户自建服务器的位置(注意下图红色边框部分):
![](http://bbs.feibit.com/data/attachment/forum/201210/13/121530ig192fg1vjzlzxfa.png)
也就是说,您自己的web服务器需要和“飞比云服务平台”建立双向的通信:将传感器数据反映在网页上;同时将用户通过网页发送的控制指令传递给飞比云。要实现这个功能,需要借助html语言与java script脚本,另外需要用到Ajax与JSON技术。作为网页编程技术在物联网中的应用,这里我们不过分地深入到细节,仅了解下基本的原理和实现技巧。
步骤和以前一样,对于我们这些“画家”,第一步仍然是构思,然后只是用不同的画笔画相同的图而已。
注:以下内容需要在保证您已经完成了前面的硬件安装与C/S模式的实验,并打开节点的前提下进行。
一、用html语言实现基本的界面
1、构思中的界面--http://fbeecloud.svfree.net
2、基本界面的html实现- <!DOCTYPE html>
- <html>
- <head>
- </head>
- <body>
- <script type="text/javascript">
- //界面加载时初始化界面
- window.onload=function()
- {
- //电灯状态
- document.getElementById("IMG").src="on.png";
- document.getElementById("txtHint").innerHTML = "电灯状态";
- //控制指令发送状态
- document.getElementById("ctRspStr").innerHTML = "控制指令发送状态";
- }
- </script>
- <div id="D">
- <img id="IMG"/>
- <br />
- </div>
- <div id="txtHint"><b></b></div>
- <p></p>
- <button type="button1" style="background:#FFFF99;width:100px; height:40px" onclick="">开灯</button>
- <button type="button2" style="background:#FFFF99;width:100px; height:40px" onclick="">关灯</button>
- <div id="ctRspStr"><b></b></div>
- </body>
- </html>
复制代码 把这段代码保存成index.html,并且将on.png和off.png两个文件放到同一目录下。
这里面除了一个加载时运行到的java script函数外,其它的都是最基本的html代码,这里不再赘述,仅强调这里的三个变量的传递:- //界面加载时初始化界面
- window.onload=function()
- {
- //电灯状态
- document.getElementById("IMG").src="on.png";
- document.getElementById("txtHint").innerHTML = "电灯状态";
- //控制指令发送状态
- document.getElementById("ctRspStr").innerHTML = "控制指令发送状态";
- }
复制代码 这里做了三个事情:设置了电灯的图片(IMG);“电灯状态”字符(txtHint)与“控制指令发送状态”字符(ctRspStr)。这里之所以没有直接写到html代码中,是因为后续的代码中,我们需要让它们“动”起来。
3、自建web服务器,并上传代码
这段内容实际上如果展开来讲,内容蛮复杂。但这类的教程随处可见,我们不去重复了,仅说明几个关键点:
首先,需要自建一个可供别人浏览的web服务器,可以用IIS等工具用自己的电脑来搭建;但更容易的方式是找一个空间服务商,把网页内容通过FTP上传即可实现浏览。由于我们暂时只是拿来演示,这里推荐一个国内的免费空间-http://www.3v.cm/(免费的空间现在越来越难找了,截止笔者发稿时,这个空间经测试可用,但如果想做一个稳定的网站,这点钱还是应该花的)。
在上述网站申请了免费空间后,会得到FTP 的地址、用户名、密码,还有一个xxxx.svfree.net这样一个二级域名。然后,找一个FTP软件(比如FlashFXP),将前面的index.html, on.png, off.png等三个文件上传至空间根目录。
在浏览器中输入您的二级域名,是不是就可以看到构想中的界面了?这实际上已经成功为我们后面的功能做了一个“外壳”。
二、如何让自建web服务器从飞比云服务平台上获取传感器数据
1、首先,看下飞比云的数据下载API
http://www.feibit.com/get.php?us ... 11111&upDataCur
这条指令将返回当前一条数据的内容,其中userID和userKey要替换成您自己的。
如果您在上述章节“B/S与C/S模式下网络控制Zigbee电灯(二)-C/S模式”中已经实现的相关的实验内容,并且把灯的状态每几秒种向飞比云汇报成功后,通过在浏览器输入这个地址,则可以每几秒钟看到这个数据在更新。
2、在自己的web服务器中获取传感器数据
这里涉及到两个不同域名的服务器之间访问的问题,比较常见的作法是使用jQuery进行交互,当然jQuery的内容此处也不进行详解,仅分析下如下交互代码:- //从飞比云服务器获取JSON格式的传感数据
- function getFBeeCloudMsg()
- {
- $.getJSON("http://www.feibit.com/get.php?userID=40&userKey=111111111111111&upDataCur&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_data = data.format;
- //进行界面更新
- document.getElementById("txtHint").innerHTML = FBee_cloud_data;
- });
-
- //1秒钟刷新
- window.setTimeout(getFBeeCloudMsg, 1000);
- }
复制代码 此处,每运行一次getFBeeCloudMsg函数,则向飞比云获取了一次userID为40的用户的当前传感器数据,采用的指令中:
$.getJSON("http://www.feibit.com/get.php?userID=40&userKey=111111111111111&upDataCur&callback=?",
最后的callback为“回调函数”,即“用户web服务器”收到“飞比云服务器”的回应数据后,所调用的函数。此函数实体为:- FBee_cloud_data = data.format; //获取飞比云回馈数据
- //进行界面更新
- document.getElementById("txtHint").innerHTML = FBee_cloud_data;
复制代码 另外,window.setTimeout(getFBeeCloudMsg, 1000);这句代码保证了web服务器每秒钟向飞比云请求一次数据。
完整代码如下:- <!DOCTYPE html>
- <html>
- <head>
- <script src="http://code.jquery.com/jquery-1.5.js"></script>
- <script type="text/javascript">
- //全局变量
- var FBee_cloud_data; //传感数据
- //从飞比云服务器获取JSON格式的传感数据
- function getFBeeCloudMsg()
- {
- $.getJSON("http://www.feibit.com/get.php?userID=40&userKey=111111111111111&upDataCur&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_data = data.format;
- //进行界面更新
- document.getElementById("txtHint").innerHTML = FBee_cloud_data;
- });
-
- //1秒钟刷新
- window.setTimeout(getFBeeCloudMsg, 1000);
- }
- </script>
-
- </head>
- <body>
- <script type="text/javascript">
- //界面加载时初始化界面
- window.onload=function()
- {
- //电灯状态
- document.getElementById("IMG").src="on.png";
- //document.getElementById("txtHint").innerHTML = "电灯状态";
- //控制指令发送状态
- //document.getElementById("ctRspStr").innerHTML = "控制指令发送状态";
- getFBeeCloudMsg();
- }
- </script>
- <div id="D">
- <img id="IMG"/>
- <br />
- </div>
- <div id="txtHint"><b></b></div>
- <p></p>
- <button type="button1" style="background:#FFFF99;width:100px; height:40px" onclick="">开灯</button>
- <button type="button2" style="background:#FFFF99;width:100px; height:40px" onclick="">关灯</button>
- <div id="ctRspStr"><b></b></div>
- </body>
- </html>
复制代码 同样,保存为index.html并上传至您个人服务器,更新后发现网页中的数据,已经可以随着传感节点的变化在发生变化。
三、如何对获取的源数据进行解码,并更新界面
1、首先按“飞比云传感协议V2.0”文档,分析一下上述步骤二中所下载到的数据格式,并相应确认解码算法。以FB0799C0010130000323D065这组数据为例:
FB:协议头
07:数据长度(红色)
99C0:短地址
0101:一个开关量,值为1
300003:userID号为0003
23D0:rssi值为D0
65:“异或”检验和
为简化起见,我们仅采用在整个数据包中搜索是否有“0101”确认电灯为“打开”状态;搜索“0100”代表“关闭”状态。当然这种算法不够严谨,此处仅为演示如何来实现功能,用户可自行深入Java Script的编程部分。
2、获取传感数据后,进行处理:- function processData()
- {
- var IndexOfData;
- var sensorData;
- var dataLen;
- IndexOfData = FBee_cloud_data.indexOf("=")+1; //查找数据开始位
-
- //process data, eg: FB05DED03000030101C3(DK) FB0799C0010130000323D065(FBee)
- sensorData = FBee_cloud_data.substring(IndexOfData);
- dataLen = sensorData.substr(3,1);
- node_shortAddr = sensorData.substr(4,4);
- sensorData = sensorData.substr(8,dataLen*2);
-
- if (sensorData.indexOf("0100")>=0)
- {
- document.getElementById("IMG").src="off.png";
- document.getElementById("txtHint").innerHTML = "The light is OFF.";
- }
- else if (sensorData.indexOf("0101")>=0)
- {
- document.getElementById("IMG").src="on.png";
- document.getElementById("txtHint").innerHTML = "The light is ON.";
- }
- else
- {
- document.getElementById("txtHint").innerHTML = sensorData;
- }
- }
复制代码 3、完整代码
更新至服务器后,可以观察到界面中的电灯的状态图片会随着送上来的“反馈”数据不同而变化。可以通过FIT Explorer软件,本地控制灯的开关后,通过网页来观察其变化。- <!DOCTYPE html>
- <html>
- <head>
- <script src="http://code.jquery.com/jquery-1.5.js"></script>
- <script type="text/javascript">
- //全局变量
- var FBee_cloud_data; //传感数据
- var node_shortAddr;
- //获取传感数据后,进行处理
- function processData()
- {
- var IndexOfData;
- var sensorData;
- var dataLen;
- IndexOfData = FBee_cloud_data.indexOf("=")+1;
-
- //process data, eg: FB05DED03000030101C3(DK) FB0799C0010130000323D065(FBee)
- sensorData = FBee_cloud_data.substring(IndexOfData);
- dataLen = sensorData.substr(3,1);
- node_shortAddr = sensorData.substr(4,4);
- sensorData = sensorData.substr(8,dataLen*2);
-
- if (sensorData.indexOf("0100")>=0)
- {
- document.getElementById("IMG").src="off.png";
- document.getElementById("txtHint").innerHTML = "The light is OFF.";
- }
- else if (sensorData.indexOf("0101")>=0)
- {
- document.getElementById("IMG").src="on.png";
- document.getElementById("txtHint").innerHTML = "The light is ON.";
- }
- else
- {
- document.getElementById("txtHint").innerHTML = sensorData;
- }
- }
- //从飞比云服务器获取JSON格式的传感数据
- function getFBeeCloudMsg()
- {
- $.getJSON("http://www.feibit.com/get.php?userID=40&userKey=111111111111111&upDataCur&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_data = data.format;
- //进行界面更新
- processData();
- });
-
- //1秒钟刷新
- window.setTimeout(getFBeeCloudMsg, 1000);
- }
- </script>
-
- </head>
- <body>
- <script type="text/javascript">
- //界面加载时初始化界面
- window.onload=function()
- {
- //电灯状态
- document.getElementById("IMG").src="on.png";
- //document.getElementById("txtHint").innerHTML = "电灯状态";
- //控制指令发送状态
- //document.getElementById("ctRspStr").innerHTML = "控制指令发送状态";
- getFBeeCloudMsg();
- }
- </script>
- <div id="D">
- <img id="IMG"/>
- <br />
- </div>
- <div id="txtHint"><b></b></div>
- <p></p>
- <button type="button1" style="background:#FFFF99;width:100px; height:40px" onclick="">开灯</button>
- <button type="button2" style="background:#FFFF99;width:100px; height:40px" onclick="">关灯</button>
- <div id="ctRspStr"><b></b></div>
- </body>
- </html>
复制代码 至此,B/S模式下的采集部分已经完成!
四、关于反向控制
1、首先,通过API模式测试下飞比云服务平台的反控功能:
http://www.feibit.com/ctput.php? ... nData=CTO1%2099C000
这条指令控制短地址为99C0的节点,第一个可控IO口的电平状态为0,其中userID和userKey要替换成您自己的,%20代表空格。
分别用CTO1 99C001与CTO1 99C000两条指令试一下,是否在输入不同的参数并确认后,节点LED灯的状态发生了变化?
注:采用开发板和FBee模块底板,这里的LED控制状态有所不同,开发板为低有效,即发送CTO1 xxxx00时打开LED灯,相反为关;而FBee模块底板状态刚好相反,所以在设置发送指令时,此处应该尤为注意!
2、如何通过web页向飞比云服务器发送控制指令
实际上原理与采集数据的获取完全相同,只是API的参数做了小小的修改,换成了下行控制指令API,核心处理函数如下:- //向飞比云服务器发送控制指令
- function sendFBeeCloudCmd(cmdStr)
- {
- FBee_cloud_cmd = cmdStr;
- $.getJSON("http://www.feibit.com/ctput.php?userID=40&userKey=111111111111111&downData="+cmdStr+"&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_cmd_rsp = data.format;
- //返回控制结果
- displayCtrlRsp();
- });
- }
复制代码 然后,设置不同的按钮对应发出的控制指令:- <button type="button1" style="background:#FFFF99;width:100px; height:40px" onclick="sendFBeeCloudCmd('CTO1%20'+node_shortAddr+'00')">开灯</button>
- <button type="button2" style="background:#FFFF99;width:100px; height:40px" onclick="sendFBeeCloudCmd('CTO1%20'+node_shortAddr+'01')">关灯</button>
复制代码 注:此处node_shortAddr为从采集数据中所获取的“短地址”数据,所以即使短地址发生变化,控制指令仍可准确地控制相应的节点。
3、完整代码如下:- <!DOCTYPE html>
- <html>
- <head>
- <script src="http://code.jquery.com/jquery-1.5.js"></script>
- <script type="text/javascript">
- //全局变量
- var FBee_cloud_data; //传感数据
- var FBee_cloud_cmd; //控制指令
- var FBee_cloud_cmd_rsp; //控制指令回复
- var node_shortAddr;
- //获取传感数据后,进行处理
- function processData()
- {
- var IndexOfData;
- var sensorData;
- var dataLen;
- IndexOfData = FBee_cloud_data.indexOf("=")+1;
-
- //process data, eg: FB05DED03000030101C3(DK) FB0799C0010130000323D065(FBee)
- sensorData = FBee_cloud_data.substring(IndexOfData);
- dataLen = sensorData.substr(3,1);
- node_shortAddr = sensorData.substr(4,4);
- sensorData = sensorData.substr(8,dataLen*2);
-
- if (sensorData.indexOf("0100")>=0)
- {
- document.getElementById("IMG").src="off.png";
- document.getElementById("txtHint").innerHTML = "The light is OFF.";
- }
- else if (sensorData.indexOf("0101")>=0)
- {
- document.getElementById("IMG").src="on.png";
- document.getElementById("txtHint").innerHTML = "The light is ON.";
- }
- else
- {
- document.getElementById("txtHint").innerHTML = sensorData;
- }
- }
- //显示控制指令发送结果
- function displayCtrlRsp()
- {
- var command = FBee_cloud_cmd.substr(11,2);
- //CTO1 XXXX01
- if (command=="01")
- {
- document.getElementById("ctRspStr").innerHTML = "Successfully send TURN OFF command to FBee Cloud!";
- }
- else if (command=="00")
- {
- document.getElementById("ctRspStr").innerHTML = "Successfully send TURN ON command to FBee Cloud!";
- }
- else
- {
- document.getElementById("ctRspStr").innerHTML = FBee_cloud_cmd_rsp;
- }
- }
- </script>
- <script>
- //从飞比云服务器获取JSON格式的传感数据
- function getFBeeCloudMsg()
- {
- $.getJSON("http://www.feibit.com/get.php?userID=40&userKey=111111111111111&upDataCur&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_data = data.format;
- //进行界面更新
- processData();
- });
-
- //1秒钟刷新
- window.setTimeout(getFBeeCloudMsg, 1000);
- }
- //向飞比云服务器发送控制指令
- function sendFBeeCloudCmd(cmdStr)
- {
- FBee_cloud_cmd = cmdStr;
- $.getJSON("http://www.feibit.com/ctput.php?userID=40&userKey=111111111111111&downData="+cmdStr+"&callback=?",
- {
- foo: "bar",
- format: "json"
- },
- function(data) {
- FBee_cloud_cmd_rsp = data.format;
- //返回控制结果
- displayCtrlRsp();
- });
- }
- </script>
- </head>
- <body>
- <script type="text/javascript">
- //界面加载时即周期性获取传感数据
- window.onload=function()
- {
- getFBeeCloudMsg();
- }
- </script>
- <div id="D">
- <img id="IMG"/>
- <br />
- </div>
- <div id="txtHint"><b></b></div>
- <p></p>
- <button type="button1" style="background:#FFFF99;width:100px; height:40px" onclick="sendFBeeCloudCmd('CTO1%20'+node_shortAddr+'00')">开灯</button>
- <button type="button2" style="background:#FFFF99;width:100px; height:40px" onclick="sendFBeeCloudCmd('CTO1%20'+node_shortAddr+'01')">关灯</button>
- <div id="ctRspStr"><b></b></div>
- </body>
- </html>
复制代码 更新至服务器中,用电脑、PAD或者手机不同的方式,享受您的“Zigbee远程电灯”之旅吧!
好了,只剩下最后一个疑点没有揭开了,那就是为什么我们一直把Zigbee电灯的userID号设为0003?如果您有Android的平板电脑或者手机,到www.feibit.com/fit.apk这个地址下载一个“飞比云客户端”的软件,输入用户名、密码,打开界面后,点击里面的电灯,再看下您节点上的LED灯是否也跟着变化了呢?
这就是userID=0003的原因:我们已经做过一个基于android的客户端软件,但目前还不能用户自行更改设置,还只是一个demo,但它的功能会慢慢向电脑版的FIT靠拢!
<<小记>>:至此,一个小小的电灯已经完成了它从“采集”到“控制”,从“本地”到“互联网”,从“电脑”到“移动嵌入式设备”各个方面的功能。当然,这只是“飞比云服务平台”的B/S与C/S模式下的一个小的侧面,但是它打开了潘多拉的盒子,因为互联网的应用可以说是无限的:短信、微博、微信,各种各样的已经成熟的互联网服务都可以与其进行接轨,在打通这个“物”联到“网”的通道后,接下来的故事才刚刚开始… …
飞比物联网培训教程--"玩转物联网"之一、前言及目录
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|