物联网系统的搭建(八)

 REST服务准备

1 Laravel

Laravel是一套简洁、优雅的PHP Web开发框架(PHP Web Framework)。它可以让你从面条一样杂乱的代码中解脱出来;它可以帮你构建一个完美的网络APP,而且每行代码都可以简洁、富于表达力。

  • RESTful 路由: 通过简单的闭包就能响应HTTP请求。帮你快速开始构建非凡的应用。
  • 强大的数据操纵能力: Laravel自带了强大的Eloquent ORM 和迁移工具。能够完美的与MySQL、Postgres、SQL Server 和 SQLite协同工作。
  • 优雅的模版引擎: PHP代码或轻量级的Blade模版引擎都可无缝融合。Blade模版可以继承,并且拥有极快的解析速度。相信你会喜欢它的。
  • 为明天做准备: 构建大型的企业级应用或者只是提供简单的JSON API;书写强大的控制器或轻巧的RESTful路由,Laravel适应所有级别的开发工作。
  • 可靠的基石: Laravel 的基石是数个Symfony组件,这些经过千锤百炼、可靠的组件为你的应用提供坚实的基础。
  • 基于Composer管理器: Composer 是一套帮你管理第三方扩展包的工具。能够让你迅速在 Packagist 中找到需要的扩展包。
  • 强大的社区支持: 无论你是一个PHP新手还是经验丰富的架构师,都能在社区中找到需要的知识。你可以在IRC中讨论Idea,或者在论坛中发布问题。
  • 测试、重构: Laravel 从开始就将测试作为重点功能。我们提供了灵活的IoC容器,集成了PHPUnit 测试工具。不用担心,这些都很容易上手。

1.1 为什么是 Laravel

  • 因为个人喜爱,你也可以用 Ruby On Rails来搭建这样一个功能,或者是Java。
  • PHP在我的服务器上运行得挺不错的,而且我又不需要重新去写配置那些配置。
    • Laravel 可以简单的开发我们所需要的功能,换句话说他是 PHP 世界的 Ruby On Rails。

这里不会再重述之前的问题,这里只是将需要的步骤一个个写下来,然后丢到这里好好说一下。至于RESTful是什么,前面已经介绍了,就不再重复了。那么下面,我们就用Laravel来搭建一个平台给物联网用的。

2 安装 Laravel

2.1 GNU/Linux安装Composer

GNU/Linux Ubuntu/OpenSUSE下可以执行

$ curl -sS https://getcomposer.org/installer | php
2.1.1 Windows安装Composer

请直接下载

Composer-Setup

2.1.2 Mac OS

1.安装Composer

brew install homebrew/php/composer

2.安装Laravel

composer global require "laravel/installer=~1.1"

3.创建Laravel工程

composer create-project laravel/laravel your-project-name --prefer-dist
2.1.3 Mac OS

1.下载laravel.phar

wget http://laravel.com/laravel.phar

2.重命名

mv laravel.phar laravel

3.移动到bin中

sudo mv laravel /usr/local/bin

4.创建项目

laravel new blog

3 MySQL

3.1 安装MySQL

出于某些原因,我建议用MariaDB替换MySQL,如果你"真正"需要mysql,将mariadb替换为mysql

ps: 在下文中我会继续用MySQL,而不是MariaDB,MairaDB是MySQL的一个分支,真正的开源分支。

Ubuntu/Debian/Mint

$ sudo apt-get install mariadb-server

Fedora/Centos

$ sudo yum install mariadb-server

openSUSE

$ sudo zypper install mariadb-server

Mac OS

$ brew install mariadb

3.2 配置MySQL

修改database.php

app/config/database.php

要修改的就是这个

'mysql' => array(
    'driver'    => 'mysql',
    'host'      => 'localhost',
    'database'  => 'iot',
    'username'  => 'root',
    'password'  => '940217',
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
),

如果你已经有phpmyadmin,似乎对你来说已经很简单了,如果没有的话,就直接用

$ mysql -uroot -p

来创建一个新的

CREATE DATABASE IF NOT EXISTS iot default charset utf8 COLLATE utf8_general_ci;

数据库的目的在于存储数据等等的闲话这里就不多说了,创建一个RESTful的目的在于产生下面的JSON格式数据,以便于我们在Android、Java、Python、jQuery等语言框架或者平台上可以调用,最主要的是可以直接用Ajax来产生更炫目的效果。

{
"id": 1,
"temperature": 14,
"sensors1": 12,
"sensors2": 12,
"led1": 0
}

 创建REST服务

1 数据库迁移

这个名字是源自于Ruby On Rails在那时候的印象,不直接使用MySQL的目的在于让我们可以专注于过程。

1.1 创建表

表的概念,类似于在Excel中的表,如果你真实不懂数据库。 让我们创建一个athomes的表,为什么是athomes,因为以前在写android程序的时候就叫的是athome,忽略掉这些次要的因素吧。

$ php artisan migrate:make create_athomes_table

打开 app/database/migrations/***create_athomes_table.php 这里的***是由日期和某些随机变量组成的,修改生成的PHP代码,如下:

use Illuminate\Database\Schema\Blueprint;  
use Illuminate\Database\Migrations\Migration;  

class CreateAthomesTable extends Migration {
    public function up()  
    {  
        Schema::create('athomes', function(Blueprint $table)  
        {  
            $table--->increments('id');  
            $table->float('temperature');  
            $table->float('sensors1');  
            $table->float('sensors2');  
            $table->boolean('led1');  
            $table->timestamps();  
        });  
    }  
    public function down()  
    {  
        Schema::drop('athomes');  
    }  
}

id值是自加的,也就是我们在localhost/athome/{id},当我们创建一个新的数据的时候,会自动加上去。最后一个timestamps批的是时间,会包含创建时间和修改时间。 剩下的temperature,sensors1,sensors2是小数,以及只有true和false的led1。

1.2 数据库迁移

我们只是写了我们需要的数据的格式而并没有丢到数据库里,

$ php artisan migrate

这个就是我们执行迁移的命令,如果你用phpmyadmin可以直接打开查看,没有的话,可以。

$ mysql -uroot -p
use iot;
select * from athomes;

就可以看到我们写的东西,那么接下来就是创建RESTful服务了

2 创建RESTful

用下面的代码实现我们称之为Athomes控制器的创建

$ php artisan controller:make AthomesController

就会在app/controllers下面生成下面的代码

class AthomesController extends \BaseController {  
    public function index() {}  
    public function create()  {} 
    public function store() {}  
    public function show($id) {}  
    public function edit($id) {}  
    public function update($id) {}  
    public function destroy($id) {} 
}

3 Laravel Resources

上面的代码过于沉重,请让我用 Ctrl+C 来带来点知识吧。

Verb

Path

Action

Route Name

GET

/resource

index

resource.index

GET

/resource/create

create

resource.create

POST

/resource

store

resource.store

GET

/resource/{resource}

show

resource.show

GET

/resource/{resource}/edit

edit

resource.edit

PUT/PATCH

/resource/{resource}

update

resource.update

DELETE

/resource/{resource}

destroy

resource.destroy

所以我们只需要专注于创建 create, edit, show, destory 等等。好吧,你可能没有耐心了,但是在修改这个之前我们需要先在 app/model 加个 class

class Athomes extends Eloquent {  
    protected $table = 'athomes';  
}

如果你想要的只是控制器Athomes的代码的话。。

class AthomesController extends \BaseController {
    public $restful=true;
    protected $athome;
    public function __construct(Athomes $athome)
    {
        $this--->athome = $athome ;
     }
    public function index()
    {
        $maxid=Athomes::all();
        return Response::json($maxid);
    }
    public function create()
    {
        $maxid=Athomes::max('id');
        return View::make('athome.create')->with('maxid',$maxid);
    }
    public function store()
    {
        $rules = array(
            'led1'=>'required',
            'sensors1' => 'required|numeric|Min:-50|Max:80',
            'sensors2' => 'required|numeric|Min:-50|Max:80',
            'temperature' => 'required|numeric|Min:-50|Max:80'
        );
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Redirect::to('athome/create')
                ->withErrors($validator)
                ->withInput(Input::except('password'));
        } else {
            $nerd = new Athomes;
            $nerd->sensors1       = Input::get('sensors1');
            $nerd->sensors2       = Input::get('sensors2');
            $nerd->temperature    = Input::get('temperature');
            $nerd->led1              = Input::get('led1');
            $nerd->save();
            Session::flash('message', 'Successfully created athome!');
            return Redirect::to('athome');
        }
    }
    public function show($id)
    {
        $myid=Athomes::find($id);
        $maxid=Athomes::where('id','=',$id)
                        ->select('id','temperature','sensors1','sensors2','led1')
                        ->get();
        return Response::json($maxid);
    }
    public function edit($id)
    {
        $athome = Athomes::find($id);
        return View::make('athome.edit')
            ->with('athome', $athome);
    }
    public function update($id)
    {
        $rules = array(
            'led1'=>'required|',
            'sensors1' => 'required|numeric|Min:-50|Max:80',
            'sensors2' => 'required|numeric|Min:-50|Max:80',
            'temperature' => 'required|numeric|Min:-50|Max:80'
        );
        $validator = Validator::make(Input::all(), $rules);
        if ($validator->fails()) {
            return Redirect::to('athome/' . $id . '/edit')
                ->withErrors($validator);
        } else {
            $nerd = Athomes::find($id);
            $nerd->sensors1       = Input::get('sensors1');
            $nerd->sensors2       = Input::get('sensors2');
            $nerd->temperature    = Input::get('temperature');
            $nerd->led1              = Input::get('led1');
            $nerd->save();
            Session::flash('message', 'Successfully created athome!');
            return Redirect::to('athome');
        }
    }
    public function destroy($id)
    {
        $athome = Athomes::find($id);
        $athome->delete();
        if(is_null($athome))
        {
             return Response::json('Todo not found', 404);
        }
        Session::flash('message', 'Successfully deleted the nerd!');
        return Redirect::to('athome');
    }
}

希望你能读懂,没有的话,继续。

下面这部分来自于之前的博客,这里就不多加论述了。 这个也就是我们要的模板,

3.1 修改Create()

public function create()
{
    $maxid=Athomes::max('id');
    return View::make('athome.create')->with('maxid',$maxid);
}

这里需要在app/views/创建一个athome里面创建一个create.blade.php,至于maxid,暂时还不需要,后面会用到show。如果只需要模板,可以简化为

public function create()
{
    return View::make('athome.create');
}

这里只是对其中代码的进行一下说明。

3.2 创建前台页面

3.2.1 开始之前

由于使用到了bootstrap以及bootstrap-select,记得添加css。

<link rel="stylesheet" type="text/css" href="<?= url('css/bootstrap.min.css') ?>" />
<link rel="stylesheet" type="text/css" href="<?= url('css/bootstrap-select.min.css') ?>" />

以及javascript

<script type="text/javascript" src="<?= url('js/jquery.min.js')?>"></script>
<script type="text/javascript" src="<?= url('js/bootstrap.min.js') ?>"></script>
<script type="text/javascript" src="<?= url('js/bootstrap-select.min.js') ?>"></script>
<script>
$('.selectpicker').selectpicker();
</script>
3.2.2 创建资源页面

这里用到的是之前提到的那个作者写下的,稍微修改了一下。

<div class="row-fluid">
  {{ HTML::ul($errors->all()) }}
  {{ Form::open(array('url' => 'athome')) }}
     <div class="form-group">
          {{ Form::label('led1', '开关1') }}
          {{ Form::select('led1',array('关','开'),$selected=NULL,array('class'=>'selectpicker')) }}
      </div>
      <div class="form-group">
          {{ Form::label('sensors1', 'sensors1') }}
          {{ Form::text('sensors1', Input::old('sensors1'), array('class' => 'form-control')) }}
      </div>
      <div class="form-group">
          {{ Form::label('sensors2', 'sensors2') }}
          {{ Form::text('sensors2', Input::old('sensors2'), array('class' => 'form-control')) }}
      </div>
      <div class="form-group">
          {{ Form::label('temperature', 'temperature') }}
          {{ Form::text('temperature', Input::old('temperature'), array('class' => 'form-control')) }}
      </div>
      {{ Form::submit('Create!', array('class' => 'btn btn-primary')) }}
  {{ Form::close() }}
  </div>

开关一开始打算用 checkbox,加上 bootstrap-switch 实现

ON  OFF

弱弱地觉得还是没掌握好的节奏,所以最后用 select 来实现。

还需要修改一下之前的 create(),添加一行

return Redirect::to('athome');

也就是添加完后,重定向到首页查看,最后例子给出的 create 如下

public function store()
{
    $rules = array(
        'led1'=>'required',
        'sensors1' => 'required|numeric|Min:-50|Max:80',
        'sensors2' => 'required|numeric|Min:-50|Max:80',
        'temperature' => 'required|numeric|Min:-50|Max:80'
    );
    $validator = Validator::make(Input::all(), $rules);
    if ($validator->fails()) {
        return Redirect::to('athome/create')
            ->withErrors($validator);
    } else {
        // store
        $nerd = new Athomes;
        $nerd->sensors1       = Input::get('sensors1');
        $nerd->sensors2       = Input::get('sensors2');
        $nerd->temperature    = Input::get('temperature');
        $nerd->led1            = Input::get('led1');
        $nerd->save();
        Session::flash('message', 'Successfully created athome!');
        return Redirect::to('athome');
    }
}

效果图:

创建页面效果图

3.4 更新资源页面

完整的 blade 模板文件

<!DOCTYPE html lang="zh-cn">
<html>
    <head>
        <meta http-equiv="Content-type" content="text/html; charset=utf-8">
        <meta name="keywords" content="">
        <meta name="viewport" content="width=device-width">
        <meta name="description" content="">
        <title>@yield('title')</title>
        <link rel="stylesheet" type="text/css" href="<?= url('css/bootstrap.min.css') ?>" />
        <link rel="stylesheet" type="text/css" href="<?= url('css/bootstrap-select.min.css') ?>" />
        <link rel="stylesheet" href="<?= url('css/justified-nav.css') ?>" type="text/css" media="screen" />
    </head>
<body>
<div class="container">
<div class="container">
  <div class="row-fluid">
<h1>Edit {{ $athome->id }}</h1>
<!-- if there are creation errors, they will show here -->
{{ HTML::ul($errors->all()) }}
{{ Form::model($athome, array('route' => array('athome.update', $athome->id), 'method' => 'PUT')) }}
        <div class="form-group">
            {{ Form::label('led1', '开关1') }}
            {{ Form::select('led1',array('关','开'),$selected=NULL,array('class'=>'selectpicker')) }}
        </div>
        <div class="form-group">
            {{ Form::label('sensors1', '传感器1') }}
            {{ Form::text('sensors1', Input::old('sensors1'), array('class' => 'form-control')) }}
        </div>
        <div class="form-group">
            {{ Form::label('sensors2', '传感器2') }}
            {{ Form::text('sensors2', Input::old('sensors2'), array('class' => 'form-control')) }}
        </div>
        <div class="form-group">
            {{ Form::label('temperature', '温度传感器') }}
            {{ Form::text('temperature', Input::old('temperature'), array('class' => 'form-control')) }}
        </div>
    {{ Form::submit('Edit the Nerd!', array('class' => 'btn btn-primary')) }}
{{ Form::close() }}
    </div>
</div>
<div class="footer">
        <p>© Company 2013</p>
      </div>
</div>
</div>
<script type="text/javascript" src="<?= url('js/jquery.min.js')?>"></script>
<script type="text/javascript" src="<?= url('js/bootstrap.min.js') ?>"></script>
<script type="text/javascript" src="<?= url('js/bootstrap-select.min.js') ?>"></script>
<script>
 $('.selectpicker').selectpicker();
 </script>
<script type="text/javascript" src="<?= url('js/log.js') ?>"></script>
</body>
</html>

效果图:

编辑页面效果图

最后效果见:http://b.phodal.com/


 RESTful Evertywhere

1 Javascript与ajax

AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。AJAX = 异步 JavaScript和XML(标准通用标记语言的子集)。

1.1 jQuery

Jquery是继prototype之后又一个优秀的Javascript框架。它是轻量级的js库 ,它兼容CSS3,还兼容各种浏览器(IE 6.0+, FF 1.5+, Safari 2.0+, Opera 9.0+),jQuery2.0及后续版本将不再支持IE6/7/8浏览器。jQuery使用户能更方便地处理HTML(标准通用标记语言下的一个应用)、events、实现动画效果,并且方便地为网站提供AJAX交互。jQuery还有一个比较大的优势是,它的文档说明很全,而且各种应用也说得很详细,同时还有许多成熟的插件可供选择。jQuery能够使用户的html页面保持代码和html内容分离,也就是说,不用再在html里面插入一堆js来调用命令了,只需定义id即可。

2 Java与json

Gson(又称Google Gson)是Google公司发布的一个开放源代码的Java库,主要用途为串行化Java对象为JSON字符串,或反串行化JSON字符串成Java对象。

2.1 Android

3 Python与json

使用pySerial可以使Python很好地在Windows/Linux/BSD上执行串口操作。

使用urllib2库时

#!/usr/bin/env python
import json
import urllib2

url="http://b.phodal.com/athome/1"

date=urllib2.urlopen(url)
result=json.load(date)
   print result

3.1 requests

Python 标准库中的 urllib2 模块提供了你所需要的大多数 HTTP 功能,但是它的 API 烂出翔来了。它是为另一个时代、另一个互联网所创建的。它需要巨量的工作,甚至包括各种方法覆盖,来完成最简单的任务。

GET请求

#!/usr/bin/env python
import requests

url = "http://b.phodal.com/athome/1"
r = requests.get(url)
print r.text

POST请求

#!/usr/bin/env python
import requests

url = "http://b.phodal.com/athome/1"
data = {"temperature": 19, "sensors1": 32, "sensors2": 7.5, "led1": 0, "method": "PUT"}
r = requests.put(url, data)
print r.text

 前端显示

1 库与车轮子

在多数的情况下我们都没有理由也没有必要去重新发明我们的车轮,在这时使用库会是一个比较好的做法。

2 库

2.1 jQuery Mobile

jQuery Mobile是jQuery 在手机上和平板设备上的版本。jQuery Mobile不仅会给主流移动平台带来jQuery核心库,而且会发布一个完整统一的jQuery移动UI框架。支持全球主流的移动平台。jQuery Mobile开发团队说:能开发这个项目,我们非常兴奋。移动Web太需要一个跨浏览器的框架,让开发人员开发出真正的移动Web网站。

3 网站前台显示

3.1 Highcharts

Highcharts有以下的特点

  • 兼容性:兼容当今所有的浏览器,包括 iPhone、IE 和火狐等等;
  • 对个人用户完全免费;
  • 纯JS,无BS;
  • 支持大部分的图表类型:直线图,曲线图、区域图、区域曲线图、柱状图、饼装图、散布图;
  • 跨语言:不管是 PHP、Asp.net 还是 Java 都可以使用,它只需要三个文件:一个是Highcharts 的核心文件 highcharts.js,还有 a canvas emulator for IE 和 Jquery类库或者 MooTools 类库;
  • 提示功能:鼠标移动到图表的某一点上有提示信息;
  • 放大功能:选中图表部分放大,近距离观察图表;
  • 易用性:无需要特殊的开发技能,只需要设置一下选项就可以制作适合自己的图表;
  • 时间轴:可以精确到毫秒;

在这里只需将需要处理的数据存储到数组中,便可以将其渲染成为图形,下面的温度走势图便是基于Highcharts的结果:

图像说明文字

var dataLength = [];

function drawTemp() {
    var zero = [];
    $.getJSON('/athome/', function(json) {
        var items = [];
        dataLength.push(json.length);
        $.each(json, function(key, val) {
            zero.push(val.temperature);
        });
        chart = new Highcharts.Chart({
            color: {
                linearGradient: {
                    x1: 0,
                    x2: 0,
                    y1: 0,
                    y1: 1
                },
                stops: [
                    [0, '#003399'],
                    [1, '#3366AA']
                ]
            },
            chart: {
                renderTo: 'Tchart',
                type: 'spline'
            },
            title: {
                text: '本月温度情况'
            },
            subtitle: {
                text: ''
            },
            xAxis: {
                categories: [],
                title: {
                    text: ''
                }
            },
            yAxis: {
                title: {
                    text: '温度 (°C)'
                }
            },
            tooltip: {
                backgroundColor: '#FCFFC5',
                borderColor: 'black',
                borderRadius: 10,
                borderWidth: 1,
                enabled: true,
                formatter: function() {
                    return '<b>' + this.series.name + '</b><br/>' + this.x + ': ' + this.y + '°C';
                }
            },
            legend: {
                layout: 'vertical',
                align: 'right',
                verticalAlign: 'top',
                x: -10,
                y: 100,
                borderWidth: 0
            },
            plotOptions: {
                line: {
                    dataLabels: {
                        enabled: true
                    },
                    enableMouseTracking: false
                }
            },
            series: [{
                name: '本月',
                data: zero
            }, {
                name: '对比',
                data: [26.0]
            }]
        });
    });
};

function showTemper() {
    var length = dataLength[0];
    $.ajax({
        url: '/athome/' + length,
        type: 'GET',
        dataType: 'json',
        async: true,
        timeout: 1000,
        error: function() {},
        success: function(sdata) {
            $('.temperStatus').empty();
            $('.temperStatus').append(sdata.temperature);
        }
    });
};

$(document).ready(function() {
    setInterval("drawTemp();", 5000);
    setInterval("showTemper();", 800);
    drawTemp();
    showTemper();
});

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值