`
hulianwang2014
  • 浏览: 718937 次
文章分类
社区版块
存档分类
最新评论
  • bcworld: 排版成这样,一点看的欲望都没有了
    jfinal

PHP再学习5——RESTFul框架 远程控制LED

 
阅读更多

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语法在命令行方式下工作的开源文件传输工具

如果亲爱的读者想快速入门也可以看看我的博客文章。
【3】JSON——【cJSON学习笔记

【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 控制台中输入以下命令:
图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状态

图4 编号为1的LED状态发生改变

6.树莓派 实现LED网络控制
亲爱的朋友,如果您还不熟悉树莓派的话,可以参考:
通过树莓派实现网络控制的方法也非常简单,树莓派不停的向服务器(在局域网中,IP为192.168.1.100)发送GET请求,服务器查询数据库以JSON格式返回LED信息,树莓派根据JSON数据包的内容控制LED灯,on为点亮,off为熄灭。
【1】树莓派发送HTTP请求 GET /leds/1
【2】服务器返回HTTP响应 {“status”:"off"}或{“status”:"on"}
【3】树莓派根据status控制LED设备

【代码片段】
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import smbus
import RPi.GPIO as GPIO
import time
# 打开 /dev/i2c-1
bus = smbus.SMBus(1)
# 设备URI
apiurl = 'http://192.168.1.100/leds/1'
while True:
  #发送请求
  r = requests.get(apiurl)
  # 打印内容
  print(r.text)
  # 响应转换内容为字典形式
  # 转换为字典类型 请注意 2.7.4版本使用r.json()
  led = r.json
  # {'value':'xx'} on打开状态,off关闭状态
  if led['status'] == 'on':
    print("led on")
    bus.write_byte( 0x20 , 1 )
  else:
    print("led off")
    bus.write_byte( 0x20 , 0 )
  # 延时5S
  time.sleep(5)

【代码测试】
由于没有做前端,所有只能通过cURL指令改变LED的status。改变数据库中LED的status之后,树莓派上扩展板的真实LED状态便会发生变化。前端控制页面请期待后续博文。

图5 测试结果LED状态发生改变

7.其他遐想
本文只是想阐述REST框架的创建和使用,树莓派的使用并不是本文的重点(树莓派让我扩展了知识面)。除了树莓派之外还可以使用其他设备“享用”这个REST服务,例如
arduino平台——入门简单,加上ENC28J60可替代本文树莓派的功能。
STM32平台——【Yeelink平台使用——远程控制 RT Thread + LwIP+ STM32】简单修改该博客中的代码便可实现树莓派远程控制一样的功能,但是使用STM32平台需要更多的嵌入式方面的知识。


8.参考资料

9.关于我自己
本人是一名嵌入式工程师,专注于物联网领域。虽然是一名嵌入式工程师,但是由于物联网的多领域交叉性,不得不让自己多学一些WEB方面的知识。对于工程师来说学习新的知识绝对是有必要的,工程师没过过去只有去创造
Email:xukai19871105@126.com

分享到:
评论

相关推荐

    基于thinkphp5的restful接口框架TPR

    【基于ThinkPHP5的RESTful接口框架TPR详解】 RESTful接口已经成为现代Web服务开发的主流,它强调了资源的概念,通过HTTP方法(GET、POST、PUT、DELETE等)来操作资源,使得API设计更加清晰、简洁。ThinkPHP5是一款...

    PHP的RESTful框架Tonic.zip

    Tonic 是一个开源的 PHP RESTful Web 应用开发框架。 标签:Tonic Web框架

    物联网系统设计方案及对策及对策——RESTful.doc

    物联网的应用广泛,包括设备管理、家庭自动化、远程控制、定位服务等。最小物联网系统作为基础平台,允许用户存储和控制物体信息,同时也支持物体间的相互操作。 RESTful是一种网络应用程序的设计风格和开发方式,...

    go 实现Restful框架

    go 实现Restful风格,这种风格设计让后端和前端更加友好交流,前端一看请求就知道这个api是做什么的,根本就不需要看文档,现在很多企业都在使用Restful风格设计。从Web服务客户端接收到请求后,Resource Request ...

    cpp-RestbedC11异步RESTful框架

    Restbed 是一个基于 C++11 的开源框架,专门设计用于构建异步 RESTful 服务。这个框架由 Corvusoft 公司开发,旨在提供轻量级、高性能且易于使用的解决方案,帮助开发者快速实现 REST API。在 C++ 开发领域,Restbed...

    PHP实例开发源码——ZenTaoPHP php框架发布正式版.zip

    【PHP实例开发源码——ZenTaoPHP php框架发布正式版】 ZenTaoPHP是一款基于PHP语言的开源框架,主要用于企业级的项目管理、产品管理、研发管理等业务流程的构建。这个压缩包包含了ZenTaoPHP框架的源代码,为开发者...

    Django Restful 框架设计规范 - 英文原文

    描述:“Django Restful 框架设计规范 - 英文原文,作为Restful框架设计的规范参考”,进一步明确了文档的作用——作为开发者设计和实现Restful风格API时的参考标准。这对于那些希望构建高质量、易于维护和扩展的API...

    PHP实例开发源码——DoitPHP 轻量级PhP框架 MySql专业版.zip

    2. **路由系统**:框架中的路由机制允许开发者灵活定义URL结构,将请求分发到相应的控制器和方法,便于实现RESTful API设计。 3. **数据库操作**:集成MySql专业版,提供简便的数据库操作接口,支持SQL语句的执行、...

    安卓Android源码——在Android远程上传以及下载图片---XFire框架.zip

    本资源“安卓Android源码——在Android远程上传以及下载图片---XFire框架.zip”提供了一个基于XFire框架实现的解决方案。XFire是一款轻量级的Java Web服务库,它为Android开发者提供了方便快捷的方式来处理网络通信...

    基于restful框架jersey

    ### 基于RESTful框架Jersey的知识点详解 #### 一、Jersey RESTful框架简介 Jersey RESTful框架是一款开源的RESTful框架,它实现了JAX-RS(JSR 311 & JSR 339)规范。JAX-RS是一种Java API,用于开发RESTful web...

    PHP实例开发源码——Xataface php网站框架生成器.zip

    【PHP实例开发源码——Xataface php网站框架生成器.zip】是一个包含PHP源代码的压缩包,主要用于演示和学习如何使用Xataface这一PHP框架来构建网站。Xataface是一个开源的工具,它允许开发者快速地为MySQL数据库创建...

    Node.js-基于koa2的restful后端框架

    5. **项目结构**:一般来说,一个基于Koa2的RESTful项目会包含以下几个部分:路由配置(routes)、中间件(middleware)、模型(models,用于定义数据库结构)、控制器(controllers,处理业务逻辑)、配置文件...

    restful接口框架

    Restful接口框架是一种广泛应用于Web服务开发的设计模式,它遵循REST(Representational State Transfer,表现层状态转移)架构约束,以实现简洁、可扩展且无状态的API接口。在这个名为"interface_frame_demo"的项目...

    tp5框架开发的restful API接口自动生成文档源码.zip

    在本文中,我们将深入探讨基于ThinkPHP5(简称TP5)框架开发RESTful API接口以及如何自动生成相关文档。RESTful API设计模式已经成为现代Web服务的主流,它以资源为中心,通过HTTP方法来操作资源,提供了简洁、清晰...

    tp5 restful api框架

    标题中的“tp5 restful api框架”指的是基于ThinkPHP5框架构建的RESTful API开发方案。RESTful API设计风格是目前Web服务开发中常用的一种方式,它强调资源的表述状态转移,通过HTTP方法(如GET、POST、PUT、DELETE...

    PHP实例开发源码——JunePHP php框架.zip

    通过研究JunePHP的源码,开发者不仅能学习到PHP框架的基础知识,还能掌握MVC模式、路由、数据库操作、依赖注入等核心概念,进一步提升PHP编程能力。在实际项目中,理解框架的工作原理有助于优化代码,解决性能问题,...

    SlwRest-1.0(Super Lightweight Rest)超轻量RESTful框架

    **SlwRest-1.0:超级轻量级RESTful框架** 在当今的软件开发领域,RESTful架构已经成为构建Web服务的主流选择,因为它提供了高效、灵活且易于理解和实现的接口。然而,随着各种REST框架的出现,它们的体积和复杂性也...

    Go-一个框架用于在Go中构建RESTfulAPI

    Go语言,也被称为Golang,是由Google...通过阅读和理解这些源代码,开发者不仅可以学习如何使用Go-relax框架,还能深入理解Go语言构建RESTful API的最佳实践。这将有助于提升开发者在Go语言Web开发领域的技能和经验。

    物联网学习笔记——构建RESTFul平台1-附件资源

    物联网学习笔记——构建RESTFul平台1-附件资源

Global site tag (gtag.js) - Google Analytics