用户
 找回密码
 立即注册

QQ登录

只需一步,快速开始

点击进入授权页面

只需一步,快速开始

  • QQ空间
  • 回复
  • 收藏
  • TA的每日心情
    开心
    2018-2-26 09:28
  • 签到天数: 357 天

    [LV.8]以坛为家I

    本帖最后由 单片机菜鸟 于 2017-9-13 23:54 编辑

    一、前言                           

             接着上一篇这一次我们在配置好的环境下撸代码。之前说了,8266既然作为wifi模块,那么我们就可以进行一些网络请求。在我刚开始学Android的时候,最喜欢找一些免费的第三方接口去做一些小东西,这里也一样,我们直接用第三方API 心知天气具体的细节请到官网去参考文档,我只介绍其中一个API。我们用第三方接口的时候,免不了要注册以及使用到API_KEY,不想注册的同学直接使用楼主的密钥(wcmquevztdy1jpca),仅供学习参考用。

    二、获取指定城市的实况天气
           请求地址: https://api.thinkpage.cn/v3/weather/now.json?key=wcmquevztdy1jpca&location=guangzhou&language=en&unit=c
           请求方式:Get
           1.首先,我们可以在浏览器直接打开以上网址,不出意外,应该有以下信息,也就是我们需要的信息。
          
    [C] 纯文本查看 复制代码
    {
        "results": [
            {
                "location": {
                    "id": "WS0E9D8WN298",
                    "name": "Guangzhou",
                    "country": "CN",
                    "path": "Guangzhou,Guangzhou,Guangdong,China",
                    "timezone": "Asia/Shanghai",
                    "timezone_offset": "+08:00"
                },
                "now": {
                    "text": "Sunny",
                    "code": "1",
                    "temperature": "26"
                },
                "last_update": "2017-09-13T23:05:00+08:00"
            }
        ]
    }

           2.直接撸上我们的代码:
    [C] 纯文本查看 复制代码
    /**
    * 日期:2017/09/13
    * 功能:在线获取天气数据情况 心知天气API 
    * 作者:单片机菜鸟
    **/
    #include <ESP8266WiFi.h>
    #include <ArduinoJson.h>
     
    const char* ssid     = "360wifilulu";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
    const char* password = "6206908you11011010";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码
    const char* host = "api.seniverse.com";
    const char* APIKEY = "wcmquevztdy1jpca";        //API KEY
    const char* city = "guangzhou";
    const char* language = "en";//zh-Hans 简体中文  会显示乱码
     
    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 = 1000;                   // max size of the HTTP response
     
    // 我们要从此网页中提取的数据的类型
    struct UserData {
      char city[16];//城市名称
      char weather[32];//天气介绍(多云...)
      char temp[16];//温度
      char udate[32];//更新时间
    };
     
    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(10);
      Serial.println();
      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);
    }
     
    /**
    * @Desc  主函数
    */
    void loop() {
      while (!client.connected()){
         if (!client.connect(host, 80)){
             Serial.println("connection....");
             delay(500);
         }
      }
      if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
        clrEsp8266ResponseBuffer();
        readReponseContent(response, sizeof(response));
        UserData userData;
        if (parseUserData(response, &userData)) {
          printUserData(&userData);
        }
      }
      delay(5000);//每5s调用一次
    }
     
    /**
    * @发送请求指令
    */
    bool sendRequest(const char* host, const char* cityid, const char* apiKey) {
      // We now create a URI for the request
      //心知天气
      String GetUrl = "/v3/weather/now.json?key=";
      GetUrl += apiKey;
      GetUrl += "&location=";
      GetUrl += city;
      GetUrl += "&language=";
      GetUrl += language;
      // This will send the request to the server
      client.print(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n\r\n");
      Serial.println("create a request:");
      Serial.println(String("GET ") + GetUrl + " HTTP/1.1\r\n" +
                   "Host: " + host + "\r\n" +
                   "Connection: close\r\n");
      delay(1000);
      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 解析数据 
     * 数据格式如下:
     * {
     *    "results": [
     *        {
     *            "location": {
     *                "id": "WX4FBXXFKE4F",
     *                "name": "北京",
     *                "country": "CN",
     *                "path": "北京,北京,中国",
     *                "timezone": "Asia/Shanghai",
     *                "timezone_offset": "+08:00"
     *            },
     *            "now": {
     *                "text": "多云",
     *                "code": "4",
     *                "temperature": "23"
     *            },
     *            "last_update": "2017-09-13T09:51:00+08:00"
     *        }
     *    ]
     *}
     */
    bool parseUserData(char* content, struct UserData* userData) {
    //    -- 根据我们需要解析的数据来计算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;
      }
       
      //复制我们感兴趣的字符串
      strcpy(userData->city, root["results"][0]["location"]["name"]);
      strcpy(userData->weather, root["results"][0]["now"]["text"]);
      strcpy(userData->temp, root["results"][0]["now"]["temperature"]);
      strcpy(userData->udate, root["results"][0]["last_update"]);
      //  -- 这不是强制复制,你可以使用指针,因为他们是指向“内容”缓冲区内,所以你需要确保
      //   当你读取字符串时它仍在内存中
      return true;
    }
      
    // 打印从JSON中提取的数据
    void printUserData(const struct UserData* userData) {
      Serial.println("Print parsed data :");
      Serial.print("City : ");
      Serial.print(userData->city);
      Serial.print(", \t");
      Serial.print("Weather : ");
      Serial.print(userData->weather);
      Serial.print(",\t");
      Serial.print("Temp : ");
      Serial.print(userData->temp);
      Serial.print(" C");
      Serial.print(",\t");
      Serial.print("Last Updata : ");
      Serial.print(userData->udate);
      Serial.println("\r\n");
    }
      
    // 关闭与HTTP服务器连接
    void stopConnect() {
      Serial.println("Disconnect");
      client.stop();
    }
     
    void clrEsp8266ResponseBuffer(void){
        memset(response, 0, MAX_CONTENT_SIZE);      //清空
    }


           代码很熟悉有木有?是不是跟直接烧录Arduino一样。
          这里我们用到了ArduinoJson库,不清楚的同学可以参考我这篇帖子 ArduinoJson库
          然后把上面的代码烧录进你的Esp8266(楼主的是01)。没有意外的话,Esp8266处于工作模式时会打印出信息:
          [L9DH4_NSG80@C)MZQ3M[2H.jpg

         那么有人问了,该怎么连线呢?
         硬件平台搭建:
        1、硬件:可以选择以下的任一种
            (1)ESP8266-01 ~13 + USB 转 TTL串口模块(如PL2303、CH340)
            (2)ESP8266开发板或NodeMCU开发板 + USB数据线
             硬件连接如下
                    ESP8266-01 ~13 + USB 转 TTL串口模块(如PL2303、CH340)
            (1)如果wifi模块是ESP8266-01的按以下接线:(按烧写模式接线)
                    运行模式接线方法:(用USB转TTL串口连接模块与PC)
                    esp8266-01         u转串
                    VCC-----------3.3
                    GND----------GND
                    CH_PD--------3.3
                    RX-------------TX
                    TX-------------Rx
                    其余引脚为空。
                   烧写模式接线方法:烧写模式时需要将gpio0接地,工作模式时gpio0悬空
                   (注意有时8266需要独立供电,不直接在ttl取电,很多出现问题都在供电上,别对自己的电源太自信)
                    191649f3zfhdk1xs8yi6c8.png

         楼主的连接图(参考跑龙套帖子-http://www.arduino.cn/forum.php? ... =1&extra=#pid148026):
          Q_{{H[UNRLA]XVPYM_6$(LS.png
         楼主这里用了一个Esp测试座,本质上还是上面的操作方式。附上一个测试座的讲解图:
          }5F0MV%RK68440C{6J9.png
        硬件连接好了,就可以下载了,配置参考以下图。
        _X7GA)FH1(80]T7FHMAQC$S.png
        点击上传,稍等一会下载完成。默认出现以下页面就是正常下载。
        [W`G~JTZ@`KPIXLR8KC6.png
        下载时可能会出现以下问题:
         1.下载出错,可能没有进入到烧录模式
              7}OGBE%HECB@8]36`}W6PYC.png
         2.卡着不动,需重启一下8266,烧写模式时GPIO0接地,烧写完毕重启模块,GPIO0置空
         3.正确的下载的情况是ide通知栏是一串小点在增加,最后显示下载成功

    三、总结

         研究过程总会遇到各种问题,最重要淡定。

         通过以上代码,我们就可以在线获取天气情况,既然能拿到天气信息,那么我们就可以在这基础上加入点显示功能,比如什么OLED 点阵屏等等。

    打赏作者鼓励一下!
    楼主做好前排
    打赏作者鼓励一下!
    专供8266系列
    打赏作者鼓励一下!
    大佬,就是有的网站给你API接口,我新手小白GET请求格式老是不对,求指教
    Evangelions 发表于 2017-9-14 11:12
    大佬,就是有的网站给你API接口,我新手小白GET请求格式老是不对,求指教

    首先  你得确定 请求是Get 还是 Post  然后就是你的网址对不对了  API应该都有格式要求的
    打赏作者鼓励一下!
    本帖最后由 Evangelions 于 2017-9-14 11:54 编辑
    单片机菜鸟 发表于 2017-9-14 11:21
    首先  你得确定 请求是Get 还是 Post  然后就是你的网址对不对了  API应该都有格式要求的 ...

    GET 请求,试了有两三天了,就是弄不好,就是把ESP8266接入图灵机器人
    还有在阿里云弄的天气查询API,每次都是能连接上,但是发送的请求的格式没有对过;

    但是像这种的时间查询啊,免费不用特定KEY的倒是能完成;

    Evangelions 发表于 2017-9-14 11:52
    GET 请求,试了有两三天了,就是弄不好,就是把ESP8266接入图灵机器人
    还有在阿里云弄的天气查询API,每次 ...

    有空我看看你说的这两个
    打赏作者鼓励一下!
    Evangelions 发表于 2017-9-14 11:52
    GET 请求,试了有两三天了,就是弄不好,就是把ESP8266接入图灵机器人
    还有在阿里云弄的天气查询API,每次 ...

    刚试了一下你说的阿里云天气查询  需要购买才能够使用额。。。。。
    打赏作者鼓励一下!
    单片机菜鸟 发表于 2017-9-14 14:26
    刚试了一下你说的阿里云天气查询  需要购买才能够使用额。。。。。

    咱们加个好友吧,我现在在写论文,就是这个有太多的问题了

    qq 979692038
    单片机菜鸟 发表于 2017-9-14 14:26
    刚试了一下你说的阿里云天气查询  需要购买才能够使用额。。。。。

    有一个是免费使用的,还有一个可以1分钱100次
    123下一页
    发新帖
    发表评论
    高级模式  
    您需要登录后才可以回帖 登录 | 立即注册  
    关闭

    推荐主题 上一条 /2 下一条