zoukankan      html  css  js  c++  java
  • 初探物联网

    如果你参加了上个月在北京的Autodesk 开发者日,你应该看到了我做的关于Arduino的物联网实例演示,如果你没看到,欢迎参加14号在上海的开发者日,到时候我会再演(xian)示(bai)一下。

    这是个基于这样一个场景的简单演示。我的一个建筑物上面安装了这样一个温度传感器,随时把当前环境温度上传到云端,在浏览器端可以显示这个建筑物的三维模型和温度变化曲线图。如果温度到达一定的高温,比如大于40度,那可能是起火了,就需要发出高温报警,在三维模型中定位出报警的温度传感器的位置,并发出火警警报。

    演示地址 : http://arduiview.herokuapp.com/ 

    继续之前你可能需要阅读一下我前面的两篇文章:

    迈出物联网的第一步,玩儿一下Arduino

    使用 Arduino 和 LM35 温度传感器监测温度

    下面简单介绍一下这个实例系统的实现。下图为系统的架构图, Arduino 和 Viewer都通过REST 的方式和云端的服务器进行通信。Arduino 定时把当前温度通过REST的方式上传,Viewer定时取得温度信息并绘制曲线图,如遇高温则报警。貌似相当简单,这种基于HTTP的REST API方式的一个缺点就是实时性不好,需要进行轮询。后面我做了改进,通过WebSocket和MQTT协议,可以实现更好的实时传输,这个我们后面再说。

    Screen Shot 2015-12-03 at 2.50.53 PM

    下图就是Arduino 和LM 35温度传感器的链接情况。Arduino 本身并没有联网功能,所以还需要一个额外的设备,我采用了CC3000 WiFi Shield模块,在淘宝上也可以买到。把Arduino 和CC3000两个套在一起,然后按照前面文章中提到的方式把温度传感器连接起来即可。

    arduino-lm35

    然后我们需要写些代码驱动CC3300 WiFi模块联网。我们可以使用Adafruite CC3000 Library 。 在Arduino IDE里面,“Project” –> “Include Libraries” –> “Manage Libraries”, 搜索“CC3000”,找到这个类库安装。然后你可以阅读一下自带的例子。这一点Arduino 做的非常好,每个类库都有完备的实例,拿过来改一下就可以了。

     Screen Shot 2015-12-03 at 1.25.34 PM

    下面我们需要创建云端的服务器,我用node.js来创建并且暴露了一些REST API。其中一个就是用来解释Arduino上传的温度数据的REST API。如下所示:

    PUT /sensors/somesensorId/values

    body:

    {

    value : 22

    }

    node.js中路由部分的代码实现为:

    router.route('/sensors/:sensorId/values')
      .get(sensorController.getSensorValues)
      .put(sensorController.appendSensorValues);

    下面是sensorController控制器的实现代码。这里没有列出的是,其实后端我还使用的mongoose和mongoDb以便把上传的温度数据保存起来,这样以后就可以做大数据分析了。不过这个例子只是为了演示,我也没保存全部数据,只是保存了最近50多个。

    exports.appendSensorValues = function(req,res){  //append
    
        //we just save 50 + 1 values items to save db spaces
        var MAX_VAULE_ITEM_COUNT = 50;
    
        var sensorId = req.params.sensorId;
    
        Sensor.findById(sensorId, function(err, sensor){
          if(err)
            res.json(err);
    
          var sensorValueItem = {};
          sensorValueItem.timestamp = new Date().getTime();
          sensorValueItem.value = req.body.value;
    
          //console.log(sensorValueItem);
          var len = sensor.values.length;
          sensor.values = sensor.values.slice(len - MAX_VAULE_ITEM_COUNT );
    
          sensor.values = sensor.values.concat(sensorValueItem);
    
          sensor.save(function(err){
            
            if(err)
              res.send(err);
    
            res.json(sensorValueItem);
          })
        });
    
    }

    这里的代码还是挂一漏万,如果大家感兴趣还是在github上看完整代码.https://github.com/duchangyu/project-arduivew/tree/v0.1,

    下面来实现Arduino的部分,获取温度并通过REST的方式上传。前面提到的CC3000提供的实例已经演示了怎么连接到WiFi并上网,这里略过,如果你感兴趣可以看我的完整代码。这里我们只说说Arduino怎么发送REST请求的部分。在Arduino里面,我没有找到好的REST 的client库,不过说起来也不复杂,就是按照HTTP的协议发送原生字符串即可。按照我们的REST接口的定义,上传的REST协议应该是这样的:

    PUT /api/sensors/somesensorid/value HTTP/1.1

    HOST: arduiview.heroku.com

    content-type : application/json

    Content-Length : 19

    {

    value : 22

    }

    下面就是构建这样的字符串,然后通过CC3000客户端发送出去即可,代码片段如下:

    void postTemperatureToCloudServer() {
    
      //connectToCloudServer
      Serial.println(F("trying to connect to cloud server....."));
      //client.close();
      client = cc3000.connectTCP(ip, 80);
    
      Serial.println(F("connected to cloud server - "));
      Serial.println(WEBSITE );
    
      Serial.println(F("begin uploading..."));
    
      float temp = 0.0;
      // get the current temperature from sensor
      int reading = analogRead(0);
      temp = reading * 0.0048828125 * 100;
      Serial.print(F("Current temp"));
      Serial.println(temp);
    
      int length;
      char sTemp[5] = "";
      //convert float to char*,
      dtostrf(temp, 2, 2, sTemp); //val, integer part width, precise, result char array
      //itoa(temp, sTemp,10);
      Serial.println(sTemp);
    
    
      char sLength[3];
    
    
      //prepare the http body
      //
      //{
      //  "value" : 55.23
      //}
      //
    
      char httpPackage[20] = "";
    
      strcat(httpPackage, "{"value": "");
      strcat(httpPackage, sTemp);
      strcat(httpPackage, "" }");
    
      // get the length of data package
      length = strlen(httpPackage);
      // convert int to char array for posting
      itoa(length, sLength, 10);
      Serial.print(F("body lenght="));
      Serial.println(sLength);
    
      //prepare the http header
      Serial.println(F("Sending headers..."));
    
      client.fastrprint(F("PUT /api/sensors/"));
      char *sensorId = SENSOR_ID;
      client.fastrprint(sensorId);
      //client.fastrprint(SENSOR_ID);
      client.fastrprint(F("/values"));
    
      client.fastrprintln(F(" HTTP/1.1"));
      Serial.print(F("."));
    
      client.fastrprint(F("Host: "));
      client.fastrprintln(WEBSITE);
      Serial.print(F("."));
    
      client.fastrprint(F("content-type: "));
      client.fastrprintln(F("application/json"));
      Serial.print(F("."));
    
      client.fastrprint(F("Content-Length: "));
      client.fastrprintln(sLength);
      client.fastrprintln(F(""));
      Serial.print(F("."));
    
      Serial.println(F("header done."));
    
      //send data
      Serial.println(F("Sending data"));
      client.fastrprintln(httpPackage);
    
    
      Serial.println(F("===upload completed."));
    
      // Get the http page feedback
    
      unsigned long rTimer = millis();
      Serial.println(F("Reading Cloud Response!!!
    "));
      while (millis() - rTimer < 2000) {
        while (client.connected() && client.available()) {
          char c = client.read();
          Serial.print(c);
        }
      }
      delay(1000);             // Wait for 1s to finish posting the data stream
      client.close();      // Close the service connection
    
     
      Serial.println(F("upload completed
    "));
    
    }
     
    感兴趣还是看一下完整代码,在这里:
    https://github.com/duchangyu/project-arduivew/blob/v0.1/arduino/arduiview-lm35-2/arduiview-lm35-2.ino 
  • 相关阅读:
    输入任意个数字求和的小程序
    两个小的java程序,用于练习java基本语法
    《大道至简》第一,二章读后感
    搜索
    Dijkstra模板
    图论
    SPFA模板
    HDU 5114 Collision(扩展欧几里得) xgtao
    BZOJ 1001 狼抓兔子 (最大流转最短路) xgtao
    Codeforces 697C Lorenzo Von Matterhorn(严格二叉树的LCA) xgtao
  • 原文地址:https://www.cnblogs.com/junqilian/p/5019706.html
Copyright © 2011-2022 走看看