查看: 6515|回复: 36

[教程] 《博哥ESP8266系列5》- ESP8266 + EDP+OneNet平台

[复制链接]
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

    发表于 2017-9-16 20:51 | 显示全部楼层 |阅读模式
    本帖最后由 单片机菜鸟 于 2019-3-5 10:52 编辑

    https://blog.csdn.net/wubo_fly


    一、前言

                代码烧写分为两个部分:前几篇帖子主要讲从第三方接口获取数据以及怎么建立一个家庭局域网。接下来,楼主直接开始讲解物联网平台的使用以及如何把传感器数据提交到云平台。现在市面上物联网云平台非常多,经常听到的就有OneNet 机智云 YeeLink等等。
          本篇就直接 介绍 OneNet平台(中移动出品,大财主),具体介绍请看 开发文档
          在这里,楼主只挑一些重点以及我们本篇用到的讲解,其余的可以通过看开发文档来继续深入。
          1.物联网的原型图(以OneNet为例子):
           6f88171fc20240b67552f2340b3b6043.jpg
               那么问题来了,在OneNet中我们要怎么创建出上面的模型呢?
               1)首先我们需要在OneNet上建立我们自己的产品,每个产品都有一个唯一的标识 产品ID(API_Key)
              (楼主理解,所谓产品就是你这个系统的名字,楼主这本篇的例子是  智能温湿度管理系统
               2)在产品的基础上,我们需要去创建出设备,设备可以多个,每个设备也有自己唯一的标识 设备ID(DeviceID),比如楼主这里的设备就叫做 温度计
               (楼主理解,设备可理解为独立个体,可以作为独立功能,比如温度计 湿度计,楼主这里以传感器为单位,每个传感器作为一个设备)
           3)在设备的基础上,我们需要获取数据,那么我们就需要创建出数据流,数据流由一些列数据点组成。
                每个数据流也有自己唯一的标识 我们叫做 数据流ID(datastreamId)
               (数据点就是我们最终需要提交上去的数据)。
           4)OneNet 平台有了我们提交上去的数据,那么怎么在它上面生动活泼地展示数据呢?OneNet平台提供了一个叫做 应用的东西
               (其实就是把数据通过图表之类的显示出来)


           是不是很抽象呢?没关系,老规矩,有图有真相。
           03bf6891e2f646c5b4f89b685bf7ab48.jpg


           设备接入需要遵循一定的协议,有EDP MQTT HTTP,至于有什么区别?其实楼主也不知道哈哈哈,本篇我们是建立EDP协议产品。
           那么,开始本篇的重点,先看楼主在OneNet上创建的系统:
            
                 A}MZ7L6AA@1A{DE))D1$PGG.png
                 EH]CKQ8`OKBU`_6WDRG92]L.png
    二、撸代码
          
          配置好必要的云平台之后,我们要做的就是往温度计设备 每个10s提交一个数据点,POST请求。
          请把以下代码烧录进8266 模块:
          

    kittenblock中小学创客名师推荐的图形化编程软件

    /**
    * 日期:2017/09/15
    * 功能:Post数据到OneNet(智能温湿度管理系统) 
    * 作者:单片机菜鸟
    **/
    #include <ESP8266WiFi.h>
    #include <ArduinoJson.h>
    
    const char* ssid = "360wifilulu";// XXXXXX -- 使用时请修改为当前你的 wifi ssid
    const char* password = "6206908you11011010";// XXXXXX -- 使用时请修改为当前你的 wifi 密码
    const char* host = "api.heclouds.com";
    const char* APIKEY = "0ove=yI5zy01lFtBYH9J1RdpURU=";//API KEY
    const char* DeviceID = "13851462";//对应温度计的设备ID
    const char* Device = "/devices/";
    const char* addDataPoint = "/datapoints?type=3";
    //新增一个数据点 Url //api.heclouds.com/devices/device_id/datapoints
    
    const unsigned long BAUD_RATE = 115200;// serial connection speed
    const unsigned long HTTP_TIMEOUT = 5000;// max respone time from server
    const size_t MAX_CONTENT_SIZE = 500;// max size of the HTTP response
    
    WiFiClient client;
    char response[MAX_CONTENT_SIZE];
    char endOfHeaders[] = "\r\n\r\n";
    
    /**
    * @Desc 初始化操作
    */
    void setup() {
        WiFi.mode(WIFI_STA);//设置esp8266 工作模式
        Serial.begin(BAUD_RATE);
        delay(2000);//第一次进来先延时两秒;
        Serial.println();
        Serial.print("Connecting to ");//写几句提示,哈哈
        Serial.println(ssid);
        WiFi.begin(ssid, password);//连接wifi
        while (WiFi.status() != WL_CONNECTED) {
    //这个函数是wifi连接状态,返回wifi链接状态
          delay(500);
          Serial.print(".");
        }
        Serial.println("");
        Serial.println("WiFi connected");
        delay(500);
        Serial.println("IP address: ");
        Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
        client.setTimeout(HTTP_TIMEOUT);
        delay(2000);
    }
    
    /**
    * @Desc  主函数
    */
    void loop() {
       while (!client.connected()){
             if (!client.connect(host, 80)){
                 Serial.println("connection....");
                 delay(1000);
             }
       }
      StaticJsonBuffer<100> jsonBuffer;
      //创建根,也就是顶节点
      JsonObject& root = jsonBuffer.createObject();
      root["temp"] = 25;
      int len = root.measureLength();
    
      char buffer[100];
      root.printTo(buffer, sizeof(buffer));
      String data;
      for(int index = 0;index<len;index++){
         data += buffer[index]; 
      }
      if(postToDeviceDataPoint(DeviceID,data)){
        clrEsp8266ResponseBuffer();
        readReponseContent(response, sizeof(response));
      }
      delay(10000);//每15s调用一次
    }
    
    /**
    * @给设备新增一个数据点 
    */
    bool postToDeviceDataPoint(String deviceId,String data){
        String url = Device;
        url += DeviceID;
        url += addDataPoint;
    
        String header = "api-key: ";
        header += APIKEY;
        return sendPostRequest(host,url,header,data);
    }
    
    /**
    * @发送Get请求
    * @param host 
    * @param getUrl 服务地址 
    * @param header 请求头
    */
    bool sendGetRequest(const char* host,String getUrl,String header){
    // This will send the request to the server
        client.print(String("GET ") + getUrl + " HTTP/1.1\r\n" +
                     "Host: " + host + "\r\n" +
                      header + "\r\n" +
                     "Connection: Keep-Alive\r\n\r\n");
        Serial.println("Get request:");
        Serial.println(String("GET ") + getUrl + " HTTP/1.1\r\n" +
                       "Host: " + host + "\r\n" +
                       header + "\r\n" +
                       "Connection: Keep-Alive\r\n\r\n");
        delay(1000);
        return true;
    }
    
    /**
    * @发送Post请求
    */
    bool sendPostRequest(const char* host,String postUrl,String header,String data) {
    // We now create a URI for the request
        client.print(String("POST ") + postUrl + 
                              " HTTP/1.1\r\n" +
                              "Host: " + host + "\r\n" +
                              header + "\r\n" +
                             "Content-Type: application/json\r\n" +
                             "Content-Length: " + data.length() + "\r\n" +
                             "Connection: Keep-Alive\r\n\r\n"+
                             data+"\r\n");
        Serial.println("Post request:");
        Serial.println(String("POST ") + postUrl +
                              " HTTP/1.1\r\n" +
                              "Host: " + host + "\r\n" +
                              header + "\r\n" +
                             "Content-Type: application/json\r\n" +
                             "Content-Length: " + data.length() + "\r\n" +
                             "Connection: Keep-Alive\r\n\r\n"+
                             data+"\r\n");
        return true;
    }
    
    /**
    * @Desc 跳过 HTTP 头,使我们在响应正文的开头
    */
    bool skipResponseHeaders() {
    // HTTP headers end with an empty line
        bool ok = client.find(endOfHeaders);
        if(!ok){
           Serial.println("No response or invalid response!");
        }
        return ok;
    }
    
    /**
    * @Desc 从HTTP服务器响应中读取正文
    */
    void readReponseContent(char* content, size_t maxSize) {
       size_t length = client.peekBytes(content, maxSize);
       delay(100);
       Serial.println("Get the data from Internet!");
       content[length] = 0;
       Serial.println(content);
       Serial.println("Read data Over!");
       client.flush();//这句代码需要加上  不然会发现每隔一次client.find会失败
    }
    
    /**
     * @Desc 解析数据 
     * 数据格式如下:
     */
    bool parseData(char* content) {
    //    -- 根据我们需要解析的数据来计算JSON缓冲区最佳大小
    //   如果你使用StaticJsonBuffer时才需要
    //    const size_t BUFFER_SIZE = 1024;
    //   在堆栈上分配一个临时内存池
    //    StaticJsonBuffer<BUFFER_SIZE> jsonBuffer;
    //    -- 如果堆栈的内存池太大,使用 DynamicJsonBuffer jsonBuffer 代替
        DynamicJsonBuffer jsonBuffer;
        JsonObject& root = jsonBuffer.parseObject(content);
    
        if(!root.success()){
          Serial.println("JSON parsing failed!");
          return false;
        }
    //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
    //   当你读取字符串时它仍在内存中
        return true;
    }
    // 关闭与HTTP服务器连接
    void stopConnect() {
       Serial.println("Disconnect");
       client.stop();
    }
    void clrEsp8266ResponseBuffer(void){
      memset(response, 0, MAX_CONTENT_SIZE); //清空
    }

         烧录代码后,可以从串口看到调试信息:   

    2I{AJ[32Q){~IK3L100`3XG.png
         其他请求估计也跟这个格式差不多,楼主就不一一去测试。
        楼主估计其他云平台也类似(对比了一下其他平台,感觉机智云貌似活跃点,楼主计划后面接入一下。


        后面研究方向:
          1.如何配置8266 ssid和密码  不用代码写死。
          2.如果利用云平台,达到设备之间的数据直接传输,把wifi彩灯从局域网变广域网。

    博哥自建qq交流群:869920142



    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

     楼主| 发表于 2017-9-18 08:49 | 显示全部楼层
    楼主坐好冷板凳
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2018-11-27 20:16
  • 签到天数: 1 天

    [LV.1]初来乍到

    发表于 2018-4-11 01:20 | 显示全部楼层
    你好 为什么我编译你的代码问题
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-4-11 08:23 | 显示全部楼层
    oyxw 发表于 2018-4-11 01:20
    你好 为什么我编译你的代码问题

    问题是什么
    打赏作者鼓励一下!
  • TA的每日心情

    2018-4-23 20:55
  • 签到天数: 52 天

    [LV.5]常住居民I

    发表于 2018-4-11 11:13 | 显示全部楼层
    本帖最后由 rockze 于 2018-4-11 11:17 编辑

    WIFI帐号密码可以自己写一条串口指令修改啊!

    用这样的串口指令去改WIFI密码就好。
    如:  !WIFI#帐号#密码#
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-4-11 12:47 | 显示全部楼层
    rockze 发表于 2018-4-11 11:13
    WIFI帐号密码可以自己写一条串口指令修改啊!

    用这样的串口指令去改WIFI密码就好。

    没这么用过
    打赏作者鼓励一下!
  • TA的每日心情

    2018-4-23 20:55
  • 签到天数: 52 天

    [LV.5]常住居民I

    发表于 2018-4-11 18:03 | 显示全部楼层

    你查看一下ESP8266的指令。
    可以做到串口改WIFI帐号密码,AP模式的WIFI帐号密码,等等.....
    也可以在没连接WIFI的时候,自动打开AP模式,然后手机连接上ESP8266,通过手机软件发送帐号密码到ESP8266。
    当然还可以通过指令来改各个IO口的状态~
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-4-11 19:30 | 显示全部楼层
    rockze 发表于 2018-4-11 18:03
    你查看一下ESP8266的指令。
    可以做到串口改WIFI帐号密码,AP模式的WIFI帐号密码,等等.....
    也可以在没连 ...

    都没有怎么去研究AT模式  现在基本上都是搞直接编程8266
    打赏作者鼓励一下!
  • TA的每日心情

    2018-4-23 20:55
  • 签到天数: 52 天

    [LV.5]常住居民I

    发表于 2018-4-11 20:29 | 显示全部楼层
    单片机菜鸟 发表于 2018-4-11 19:30
    都没有怎么去研究AT模式  现在基本上都是搞直接编程8266

    我指的就是直接编程模式,AT模式做不了这些功能。
    编程模式下ESP8266有很多专用的指令我都找不到。
    你有ESP8266比较详细的编程用指令吗?
    打赏作者鼓励一下!
  • TA的每日心情
    开心
    2019-3-23 11:09
  • 签到天数: 634 天

    [LV.9]以坛为家II

     楼主| 发表于 2018-4-11 21:06 | 显示全部楼层
    rockze 发表于 2018-4-11 20:29
    我指的就是直接编程模式,AT模式做不了这些功能。
    编程模式下ESP8266有很多专用的指令我都找不到。
    你有E ...

    直接编程我就不用AT了
    打赏作者鼓励一下!
    您需要登录后才可以回帖 登录 | 立即注册  

    本版积分规则

    热门推荐

    BlinkerAT固件不能用
    BlinkerAT固件不能用
    如图,在配网的时候就卡住了,再发指令就没用了,固件和库都是今天刚下载的,以前的也不好
    为什么这个库已经装好了可是在调用的时候却没有显示
    为什么这个库已经装好了可
    为什么这个库已经装好了可是在调用的时候却没有显示求解决
    UART 传输(字符)不稳定,如何解决数据错位和乱码的情况
    UART 传输(字符)不稳定
    求助大家,我正在写一个 UART 传输多组数据的项目,想要将一端 Arduino 的多组数据通
    请问这是什么板子?
    请问这是什么板子?
    如图,两年前比赛学校发的,但网上找不到资料,现在翻出来,想问问有人知道它怎么用吗
    【原创】 drawbot平面关节scara机械臂写字机 画画机器人直播...
    【原创】 drawbot平面关节
    这个项目上个月就在做了,结构和代码反反复复改了多次,加上自己又太忙,一直没来得及
    Copyright   ©2015-2016  Arduino中文社区  Powered by©Discuz!   ( 蜀ICP备14017632号-3 )
    快速回复 返回顶部 返回列表