Quantcast
Channel: 英特尔开发人员专区文章
Viewing all articles
Browse latest Browse all 583

基于Edison的微信硬件平台

$
0
0

该方案的初衷是只用微信来控制物联网,免去开发其他的控制端应用。

此次更改主要加上了Edison,并不是简单地让微信来控制Edison,这太简单了.......
稍微加点难度,想到了在保证控制的及时情况下,减小服务器端的资源消耗。
简单地讲,就是每个Arduino或其他物联网节点,通过Edison这个相当于路由器来发送传感器数据和获取控制命令。

控制Arduino
首先服务器上有一个数据库,数据库里面有几个记录,每个开关都有一个对应的值。
在微信中,我们对一个公众平台发送类似于“开灯”,“打开热水器”之类的命令,以“开灯”为例公众平台的后台服务器会对这个命令进行判断,如果符合预设的命令,就会进入数据库,找到这个LED对应的记录,把这个记录对应的值改为“1”(值其实是随意的)。
这里的命令发送方式包括文字消息,语音消息。

与此同时,Arduino通过wifi从edison,不断向一个服务器上的页面发送请求,请求中会包含一些诸如请求的开关ID,密码等参数,服务器核实后,就会进入数据库,找到对应的开关的记录,把对应的值“1”通过edison反馈给Arduino,Arduino收到反馈后,就会进行判断,如果是“1”,就把对应引脚上的LED点亮。如果是”0“,就把它熄灭。
Arduino的这个过程是不断的进行的,但由于网络和性能问题,通常会有几秒钟的延迟。
实例:
首先是服务器和微信端,
服务器端选择新浪云,毕竟这是不买VPS的一种比较好的方案,如果有自己的服务器,那么看了代码就懂了,也就不用看服务器端的部署了:)。
http://sae.sina.com.cn/,注册并登录,应该有免费云豆吧。
在管理页面选择创建新应用。


  

数据可以这么填,有些空会影响后面的过程


  

进入该应用的管理页面,并选择左边的代码管理
  

编辑代码
  

编辑器
  

添加文件
  

粘贴下面的代码,注意修改代码,有些值后面会看到
<?php  if ($_GET['data'] && ($_GET['token'] == "doubleq")) {//可以改token,这相当于密码,在Arduino端改成相应的值即可
        $con = mysql_connect(SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); 
        $data = $_GET['data'];
        mysql_select_db("app_ulink42", $con);//要改成相应的数据库名
 
        $result = mysql_query("SELECT * FROM switch");
        while($arr = mysql_fetch_array($result)){//找到需要的数据的记录,并读出状态值
                if ($arr['ID'] == 1) {
                        $state = $arr['state'];
                }
        }
        $dati = date("h:i:sa");//获取时间
        $sql ="UPDATE sensor SET timestamp='$dati',data = '$data'
        WHERE ID = '1'";//更新相应的传感器的值
        if(!mysql_query($sql,$con)){
            die('Error: ' . mysql_error());//如果出错,显示错误
        }
        mysql_close($con);
        echo "{".$state."}";//返回状态值,加“{”是为了帮助Arduino确定数据的位置
}else{
        echo "Permission Denied";//请求中没有type或data或token或token错误时,显示Permission Denied
}
 
?>

同样地,把index.php改掉
<?php
 
//错误日志
function echo_server_log($log){
        file_put_contents("log.txt", $log, FILE_APPEND);
}
 
//定义TOKEN
define ( "TOKEN", "ulink" );
 
//验证微信公众平台签名
function checkSignature() {
        $signature = $_GET ['signature'];
        $nonce = $_GET ['nonce'];
        $timestamp = $_GET ['timestamp'];
        $tmpArr = array ($nonce, $timestamp, TOKEN );
        sort ( $tmpArr );
         
        $tmpStr = implode ( $tmpArr );
        $tmpStr = sha1 ( $tmpStr );
        if ($tmpStr == $signature) {
                return true;
        }else{
                return false;
        }
}
if(false == checkSignature()) {
        exit(0);
}
 
//接入时验证接口
$echostr = $_GET ['echostr'];
if($echostr) {
        echo $echostr;
        exit(0);
}
 
//获取POST数据
function getPostData() {
        $data = $GLOBALS['HTTP_RAW_POST_DATA'];
        return        $data;
}
$PostData = getPostData();
 
//验错
if(!$PostData){
        echo_server_log("wrong input! PostData is NULL");
        echo "wrong input!";
        exit(0);
}
 
//装入XML
$xmlObj = simplexml_load_string($PostData, 'SimpleXMLElement', LIBXML_NOCDATA);
 
//验错
if(!$xmlObj) {
        echo_server_log("wrong input! xmlObj is NULL\n");
        echo "wrong input!";
        exit(0);
}
 
//准备XML
$fromUserName = $xmlObj->FromUserName;
$toUserName = $xmlObj->ToUserName;
$msgType = $xmlObj->MsgType;
 
 
if($msgType == 'voice') {//判断是否为语音
        $content = $xmlObj->Recognition;
}elseif($msgType == 'text'){
        $content = $xmlObj->Content;
}else{
        $retMsg = '只支持文本和语音消息';
}
 
if (strstr($content, "温度")) {
        $con = mysql_connect(SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); 
        mysql_select_db("app_ulink42", $con);//修改数据库名
 
        $result = mysql_query("SELECT * FROM sensor");
        while($arr = mysql_fetch_array($result)){
          if ($arr['ID'] == 1) {
                  $tempr = $arr['data'];
          }
        }
        mysql_close($con);
 
    $retMsg = "报告大王:"."\n"."主人房间的室温为".$tempr."℃,感谢您对主人的关心";
}else if (strstr($content, "开灯")) {
        $con = mysql_connect(SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); 
 
 
        $dati = date("h:i:sa");
        mysql_select_db("app_ulink42", $con);//修改数据库名
 
        $sql ="UPDATE switch SET timestamp='$dati',state = '1'
        WHERE ID = '1'";//修改开关状态值
 
        if(!mysql_query($sql,$con)){
            die('Error: ' . mysql_error());
        }else{
                mysql_close($con);
                $retMsg = "好的主人";
        }
}else if (strstr($content, "关灯")) {
        $con = mysql_connect(SAE_MYSQL_HOST_M.':'.SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS); 
 
 
        $dati = date("h:i:sa");
        mysql_select_db("app_ulink42", $con);//修改数据库名
 
        $sql ="UPDATE switch SET timestamp='$dati',state = '0'
        WHERE ID = '1'";//修改开关状态值
 
        if(!mysql_query($sql,$con)){
            die('Error: ' . mysql_error());
        }else{
                mysql_close($con);
                $retMsg = "好的主人";
        }        
}else{
        $retMsg = "暂时不支持该命令";
}
 
//装备XML
$retTmp = "<xml>
                <ToUserName><![CDATA[%s]]></ToUserName>
                <FromUserName><![CDATA[%s]]></FromUserName>
                <CreateTime>%s</CreateTime>
                <MsgType><![CDATA[text]]></MsgType>
                <Content><![CDATA[%s]]></Content>
                <FuncFlag>0</FuncFlag>
                </xml>";
$resultStr = sprintf($retTmp, $fromUserName, $toUserName, time(), $retMsg);
 
//反馈到微信服务器
echo $resultStr;
?>

回到应用管理页面,选择左边的MySQL,单击初始化
  

管理MySQL
  

新建数据表
  

参数如下


  同样的方法,建立一个名字为sensor字段数为3的数据表
参数如下
  
分别插入一条记录
  
  

然后进入http://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index,申请测试号,
填写相应配置
  
这时候可以用手机端进行测试了,可以发送包含”温度“,”关灯“,”开灯“的文字消息,或者语音消息,都会有相应的反馈。

   
在Edison主要使用node.js,来接受终端的请求和发起对服务器的请求。
在随便一个位置添加以下代码
//httpserverrequestget.js
var http =require('http');
var http2 = require('http');
var url = require('url');
var querystring = require("querystring");
var path1 = '/downup.php?token=doubleq&data=';
var sensordata = '123';
var pathful;
var options;
var resdata;

http.createServer(function(req,res){
  res.writeHead(200,{'Content-Type':'text/html'});
  var objectUrl = url.parse(req.url);
        var objectQuery = querystring.parse(objectUrl.query);
  var gething = objectQuery['data'];
  pathful = path1+gething;
  options = {
      host: '1.ulink42.sinaapp.com',
      path: pathful,
      method: 'GET',
      headers: {
          'Accept': 'text/html'
      }
  };
  var req = http2.request(options, function(res2) {
      res2.setEncoding('utf8');
      res2.on('data', function(data) {
          console.log(data);
          resdata = data;
      });
  });
  req.end();
  res.end(resdata);
}).listen(8080);

我测试的物联网终端是DFRobot出的WIDO
用IDE烧写以下的代码
#include <Adafruit_CC3000.h>
#include <ccspi.h>
#include <SPI.h>
#include <string.h>
#include "utility/debug.h"

#define WiDo_IRQ   7
#define WiDo_VBAT  5
#define WiDo_CS    10

Adafruit_CC3000 WiDo = Adafruit_CC3000(WiDo_CS, WiDo_IRQ, WiDo_VBAT,
SPI_CLOCK_DIVIDER);

#define WLAN_SSID       "yourwifi"
#define WLAN_PASS       "yourpswd"
#define WLAN_SECURITY   WLAN_SEC_WPA2
int value = 0;
char tem[5];
char state;
char c;

#define TIMEOUT_MS      20000

void setup(){
  Serial.begin(9600);
  pinMode(2, OUTPUT);
  Serial.println(F("Hello, Wido!\n"));
  Serial.println(F("\nInitialising the CC3000 ..."));
  if (!WiDo.begin())
  {
    Serial.println(F("Unable to initialise the CC3000! Check your wiring?"));
    while(1);
  }

  if (!WiDo.connectToAP(WLAN_SSID,WLAN_PASS,WLAN_SECURITY)) {
    Serial.println(F("Failed!"));
    while(1);
  }

  Serial.println(F("Connected!"));
  Serial.println(F("Request DHCP"));
  while (!WiDo.checkDHCP())
  {
    delay(100);
  }
}


void loop(){
  static Adafruit_CC3000_Client client;

  if(client.connected()){

    if(state == '0'){
      digitalWrite(2, LOW);      
    }else if(state == '1'){
      digitalWrite(2, HIGH);
    }
   

    
    value = analogRead(0);
    value= int(value*0.0048828125*100);   //把读取到的val转换为温度数值,系数一:0.00488125=5/1024,0~5V对应模拟口读数1~1024,系数二:100=1000/10,1000是毫伏与伏的转换;10是每10毫伏对应一度温升。
    itoa(value,tem,10);
    Serial.println(tem);
    client.fastrprint("GET /?data=");
    client.fastrprint(tem);
    client.fastrprint(" HTTP/1.1\r\nHost: 192.168.11.132\r\nUser-Agent: arduino-ethernet\r\nConnection: close");
    Serial.println("geted");
    client.fastrprint(F("\r\n"));
    client.fastrprint(F("\r\n"));

    Serial.println();

    unsigned long lastRead = millis();
    while (client.connected() && (millis() - lastRead < TIMEOUT_MS)) {
      while(client.available()) {
        c = client.read();
        Serial.print(c);
        if (c == '{'){
            state = client.read();
            Serial.print(state);
        }
      }
    }
    client.close();
  }else{
    uint32_t ip = WiDo.IP2U32(192,168,11,132);
    client = WiDo.connectTCP(ip,8080);
    Serial.println("Connecting IoT Server...");
  }
  delay(5000);
}
其中发起请求的ip是Edison的地址,务必使他们在同一局域网内,可在Edison的命令行中输入ifconfig来进行查看。
在这个例子中,WIDO收集LM35的温度值,上传到Edison,Edison收到请求后,将数据上传至新浪云上的服务器,并获得控制LED的命令,返回给WIDO,WIDO再对LED进行控制。


Viewing all articles
Browse latest Browse all 583

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>