0.前言
去年(2013年)2月第一次接触yeelink平台,当时该平台已经运行了一些时间也吸引了不少极客。试想自己也将投身IoT(物联网)行业,就花了些时间研究了它。陆陆续续使用和研究了一年,大致围绕两个问题展开——1.yeelink平台如何使用,2.如何构造一个功能简单些的yeelink平台。
【PHP学习笔记——索引博文】
本文将讨论如何构造一个简单restful架构平台(该平台有点像yeelink,不过功能比yeelink少的多),并结合树莓派实现LED的远程控制(网络控制)。构建一个RESTFul平台涉及到很多知识,通过以下链接提供一些学习资料。
【1】Slim——简单的 PHP5 框架可用来创建 RESTful 的 Web 应用
【2】MySQL——关系型数据库管理系统
【3】RedBean——用 NoSQL 的语法来使用 ORM 框架
【4】JSON——轻量级的数据交换格式
【5】cURL——利用URL语法在命令行方式下工作的开源文件传输工具
如果亲爱的读者想快速入门也可以看看我的博客文章。
【1】Slim——【PHP再学习4—— slim框架学习和使用】
【2】cURL——【cURL 学习笔记——结合yeelink平台】【cURL安装和使用笔记】
【3】JSON——【cJSON学习笔记】
【4】树莓派——【树莓派学习笔记——yeelink 远程控制LED】
【2014年3月补充】
【1】如果您想获得本篇博文的源代码, 请点击这里 【CSDN代码仓库】
【2】整理完本篇博文之后,修改了部分API函数并在GitHub建立了代码仓库,如果本博文对您有用请点击这里 【GitHub
Clone】
【3】如果想更深入一些例如部署到云平台中,请访问我的京东云擎—— 【应用】,相关代码仓库请猛击这里 【京东代码仓库】
1.REST风格API
在HTTP协议中定义了多种动作或者方法,这些方法具有不同的含义。
【GET 获取】【POST 创建】【PUT 更新】【DELTE
删除】
为了更好的理解以上的方法,下面结合LED远程控制举个例子。假设在数据库中已经保存了家庭中的LED设备信息,这些设备信息包括LED编号,LED设备描述和当前状态(打开或关闭)等,例如位于客厅的LED处于打开状态。
可通过GET方法 获得某个LED设备的信息或者全部LED的信息。这些LED灯具有一个唯一的编号,例如客厅的LED灯编号为1,那么/leds/1就是编号为1的LED设备的唯一URI(可理解为网址)。通过这样类似的方法使每个LED设备具有网址,可通过该网址访问LED。通过GET方法可获得LED设备的所有信息,这些信息可通过JSON格式描述,例如:
[{"id":1,"description":"raspberry pi IO1","status":"off"},{"id":2,"description":"raspberry pi IO2","status":"on"}]
可通过POST方法 创建一个新LED,新增加的LED具体信息可使用JSON格式描述,例如:
{"description":"add a new led","status":"off"}
可通过PUT方法 更新LED信息,而具体内容用JSON格式描述,例如:
{“status”:"on"}
对于LED网络控制,REST API设计如下:
GET /leds 返回所有的LED信息
POST /leds 增加一个LED设备
GET /leds/id 返回编号为id的LED设备信息
PUT /leds/id 更新编号为id的LED设备信息
2.数据库准备
2.1 修改mysql密码
【PHP再学习4—— slim框架学习和使用】一文中推荐使用wampserver,该软件为集成安装包包括了PHP和MySQL,在使用mySQL之前最好修改默认密码,可参考博文【修改mysql密码(博主:幸好我是程序猿)】
(2.1或2.2操作也可使用phpMyAdmin)
2.1 新建LED设备表
使用mysql控制台,进入mysql数据库(输入use mysql,mysql为数据库的名称——安装wampserver后的一个默认数据库)。建立一个LED设备表,该表具有编号ID、描述description、状态status 字段,主键为id且自动增长(插入该数据表时
id写写入0或者不写,id编号会自动增长)。
CREATE TABLE IF NOT EXISTS `leds` (
id int(11) NOT NULL AUTO_INCREMENT,
description text NOT NULL,
status text NOT NULL,
PRIMARY KEY (id)
) DEFAULT CHARSET=utf8;
【小提示】
【1】选择数据库 use <databs_name>;
【2】查看表的结构 desc <table_name>;
【3】删除表 drop table <table_name>;
【4】id的数据类型为int(11),千万别以为int的长度为11位,int(11)只是一种int的表达方式。
2.2 插入设备内容
可在MySQL控制台输入以下内容,插入两条数据:
INSERT INTO leds (id, description , status) VALUES (1, 'raspberry pi pcf8574-IO1','on');
INSERT INTO leds (id, description , status) VALUES (2, 'raspberry pi pcf8574-IO2','off');
3.GET方法获得所有LED信息
使用GET方法或的所有LED状态——GET /leds。
返回LED状态,使用JSON数据包描述。
【代码片段】
<?php
require 'rb.php';
require 'Slim/Slim.php';
\Slim\Slim::registerAutoloader();
// 初始化数据库连接
R::setup('mysql:host=localhost;dbname=mysql','root','<your password>');
R::freeze(true);
$app = new \Slim\Slim();
// GET /leds
$app->get('/leds', function () use ($app) {
// 查找所有设备
$led_array = R::getAll('select * from leds');
$app->response()->header('Content-Type', 'application/json');
// 按照JSON格式输出
echo json_encode( $led_array , JSON_NUMERIC_CHECK);
});
$app->run();
?>
【代码解释】
【1】 require 'rb.php'; 载入redbean,请把rb.php放在www根目录 。
【2】R::setup('mysql:host=localhost;dbname=mysql','root','<your password>');R::freeze(true);载入数据库,填入数据库的名称和密码。
【3】$led_array = R::getAll('select * from leds'); 查询数据库获得LED数据包的所有内容,getAll返回一个索引数组 。
【4】echo json_encode( $led_array , JSON_NUMERIC_CHECK); 请注意mysql的整形转到PHP时将变为string,如果没有JSON_NUMERIC_CHECK选项 ,那可能会获得{“id”:"1",....},这肯定不是你所愿意看到的。
【简单测试】
可通过浏览器,cURL工具,浏览器HTTP插件进行测试。
图1 使用浏览器获得所有LED信息
4. GET方法获得单个LED信息
【代码片段】
// GET /leds/:id
$app->get('/leds/:id', function ($id) use ($app) {
try {
// 查询数据库,只返回status状态
$led_single = R::getRow('select status from leds where id = :id',array(':id'=>$id));
if ($led_single) {
$app->response()->header('Content-Type', 'application/json');
// 按照JSON格式输出
echo json_encode( $led_single, JSON_NUMERIC_CHECK);
}
else {
$app->response()->status(404);
}
}
catch (ResourceNotFoundException $e) {
$app->response()->status(404);
}
catch (Exception $e) {
$app->response()->status(400);
$app->response()->header('X-Status-Reason', $e->getMessage());
}
});
【代码解释】
【1】$app->get('/leds/:id', function ($id) use ($app) id作为参数,可以输入数字1或2等。
【2】$led_single = R::getRow('select status from leds where id = :id',array(':id'=>$id));
select status from leds where id = :id 为SQL查询语句,和一般的SQL语句不同的是出现:id,array(':id'=>$id)该语句实现了SQL语句中的:id和输入参数id的绑定关系 。在这里只查询status内容,其他内容忽略。
【3】echo json_encode( $led_single, JSON_NUMERIC_CHECK); JSON格式输出,请主意使用JSON_NUMERIC_CHECK选项。
【简单测试】
使用curl工具测试,在windows 控制台中输入以下命令:
curlhttp://localhost/leds/1
图2 使用cURL工具获得单个LED信息
5. PUT更新单个LED信息
【代码片段】
$app->put('/leds/:id', function ($id) use ($app) {
try {
// 获得HTTP请求中的JSON数据包
$request = $app->request();
$body = $request->getBody();
$input = json_decode($body);
// 查找编号为ID的记录
$led = R::findOne('leds', 'id=?', array($id));
// 重新修改status状态,并保存
if ($led) {
$led->status = (string)$input->status;
R::store($led);
} else {
throw new ResourceNotFoundException();
}
} catch (ResourceNotFoundException $e) {
$app->response()->status(404);
} catch (Exception $e) {
$app->response()->status(400);
$app->response()->header('X-Status-Reason', $e->getMessage());
}
});
【代码分析】
【1】获得HTTP请求中的内容并进行解码,json_decode总是返回一个PHP对象而不是数组,所有后面对于input的操作需要使用->符号。
$request = $app->request();
$body = $request->getBody();
$input = json_decode($body);
【2】$led = R::findOne('leds', 'id=?', array($id)); R::findOne总是返回一个对象,后面的操作需要使用->符号。
【3】$led->status = (string)$input->status; 修改status。
【4】R::store($led); 重新存储led信息。
【简单测试】
使用cURL工具测试,请求的内容为{"status":"off"},请求的方法为PUT。在windows控制台下输入以下命令:
curl -i --request PUT --data "{\"status\":\"on\"}" http://localhost/leds/1
注意:1)由于该HTTP负载并没有返回值,所有curl指令中加入-i选项,意为显示HTTP响应首部。
2)PUT方法必须大写。
图3 使用cURL更新单个LED状态
图5 测试结果LED状态发生改变
7.其他遐想
本文只是想阐述REST框架的创建和使用,树莓派的使用并不是本文的重点(树莓派让我扩展了知识面)。除了树莓派之外还可以使用其他设备“享用”这个REST服务,例如
arduino平台——入门简单,加上ENC28J60可替代本文树莓派的功能。
STM32平台——【Yeelink平台使用——远程控制 RT Thread + LwIP+
STM32】简单修改该博客中的代码便可实现树莓派远程控制一样的功能,但是使用STM32平台需要更多的嵌入式方面的知识。
8.参考资料
【1】 【Create REST applications with the
Slim micro-framework】
【2】 【RESTful services
with jQuery, PHP and the Slim Framework】
【3】 yeelink API文档
9.关于我自己
本人是一名嵌入式工程师,专注于物联网领域。虽然是一名嵌入式工程师,但是由于物联网的多领域交叉性,不得不让自己多学一些WEB方面的知识。对于工程师来说学习新的知识绝对是有必要的,工程师没过过去只有去创造 。
Email:xukai19871105@126.com
运维网声明
1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网 享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com