如何用ESP8266做一个天气预报_ZHANGGUOQI20120的博客-程序员宅基地

技术标签: python  c/c++  嵌入式  

1、硬件
用一个四博智联提供的nodemcu 。一个 OLED 屏,一个 USB 线, 4 根杜邦线,可以上网的路由器,电脑。

 

<ignore_js_op>

 

     3V3---VCC
     GND---GND
     GPIO4(D2)---SDA
     GPIO5(D1)---SCL

 

2、设置路由器
把路由器账号设置为把路由器账号设置为
账号:xh003
密码:zxd+19901120=
3、烧录程序
打开ESP_TOOLS 下载工具,选择 8266.

 

<ignore_js_op>
点击START. 等待烧录完成。

 

烧录完成后复位一下nodemcu 。等待 10s 左右。
测试结果如下:
<ignore_js_op>  <ignore_js_op>




Arduino代码如下:
#include <ESP8266WiFi.h>
#include <ArduinoJson.h>
#include <Wire.h>
#include "OLED.h"
static const char logo[] PROGMEM={
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0x7f,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0x03,0x00,0xf0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xfe,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x03,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x1f,0x1c,0xf0,0x1f,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x0f,0x00,0x80,0x7f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xff,0x01,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x07,0x00,0x00,0xfe,0x03,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xfc,0x07,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x01,0x00,0x00,0xf8,0x0f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x3f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x1f,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x0f,0x00,0x00,0x00,0xf0,0x3f,0x00,0xf0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xf0,0x1f,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x07,0x00,0x00,0x00,0xf0,0x0f,0x00,0xf8,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x03,0x00,0x00,0x00,0xf8,0x03,0x00,0xfc,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x01,0x00,0x00,0x00,0xfc,0x00,0x00,0x7e,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x01,0x00,0x00,0x00,0x7f,0x00,0x00,0x7f,0xf8,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x00,0x00,0x00,0x80,0x1f,0x00,0x80,0x7f,0xf8,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x00,0x00,0x00,0xe0,0x07,0x00,0xc0,0x3f,0xf0,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x00,0x00,0x00,0xf8,0x01,0x00,0xe0,0x3f,0xf0,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x00,0x00,0x7f,0x00,0x00,0xf8,0x3f,0xf0,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x00,0xe0,0x1f,0x00,0x00,0xfe,0x0f,0xf0,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x00,0xf8,0x03,0x00,0x80,0xff,0x0f,0xf8,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x00,0x7e,0x00,0x00,0xe0,0xff,0x01,0xf0,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x00,0x1f,0x00,0x00,0xf8,0xff,0x00,0xf8,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0xc0,0x0f,0x00,0x00,0xfe,0x7f,0x00,0xfc,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0xe0,0x03,0x00,0x80,0xff,0x1f,0x00,0xfe,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0xf8,0x01,0x00,0xe0,0xff,0x07,0x00,0xfe,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x7c,0x00,0x00,0xfc,0xff,0x00,0x00,0xfc,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x3e,0x00,0x00,0xff,0x07,0x00,0x00,0xfc,0xff,0xff,0xff,0x7f,
0xff,0xff,0x7f,0x00,0x0f,0x00,0xc0,0xff,0x07,0x00,0x00,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x80,0x07,0x00,0xf0,0xff,0xff,0x0f,0xc0,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xc0,0x03,0x00,0xf8,0xff,0xff,0x3f,0xf8,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xc0,0x01,0x00,0xfe,0xf8,0xc7,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xe1,0x01,0x00,0x7f,0xc0,0x03,0x87,0x00,0xfe,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xe1,0x00,0xc0,0x7f,0x80,0x01,0x86,0x00,0xfe,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x63,0x00,0xe0,0x7f,0x80,0x01,0x86,0x00,0xfe,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x63,0x00,0xe0,0x7f,0x8c,0x31,0x86,0xc3,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x67,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x6f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x7f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0x7f,0x00,0xc0,0x7f,0x8c,0x31,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x00,0x80,0x7f,0x80,0x01,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x01,0x00,0x7f,0x80,0x01,0x86,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x03,0x00,0x7c,0xc0,0x03,0x87,0x83,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x07,0x00,0xf8,0xff,0xff,0xf1,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x0f,0x00,0xe0,0xff,0x7f,0xf0,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x3f,0x00,0x00,0xfe,0x07,0xfc,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0x7f,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x03,0x00,0x00,0xe0,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x0f,0x00,0x00,0xfc,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0x7f,0x00,0x80,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x7f
};
//GPIO4(SDA) GPIO5(SCL)
OLED display(4, 5);

 

const char* ssid     = "xh003";         // XXXXXX -- 使用时请修改为当前你的 wifi ssid
const char* password = "zxd+19901120=";         // XXXXXX -- 使用时请修改为当前你的 wifi 密码
const char* host = "api.seniverse.com";
const char* APIKEY = "wcmquevztdy1jpca";        //API KEY
const char* city = "shenzhen";
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(100);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");
  delay(100);
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());//WiFi.localIP()返回8266获得的ip地址
  client.setTimeout(HTTP_TIMEOUT);

 

}

 

/**
* @Desc  主函数
*/

 

void loop() {
   //初始化oled
  display.begin();

 

  //测试显示信息
  display.print("Hello DOIT",2,3);
  display.print("www.doit.am",4,3);
  delay(2*1000);
  display.clear();

 

  while (!client.connected()){
     if (!client.connect(host, 80)){
         Serial.println("connection....");
         delay(100);
     }
  }
  if (sendRequest(host, city, APIKEY) && skipResponseHeaders()) {
    clrEsp8266ResponseBuffer();
    readReponseContent(response, sizeof(response));
    UserData userData;
    if (parseUserData(response, &userData)) {
      printUserData(&userData);
    }
  }
  delay(300);//每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(100);
  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( struct UserData* userData) {
  Serial.println("Print parsed data :");
  display.print("City: ",0,0);
  display.print(userData->city,0,6);
  display.print("Weat: ",2,0);
  display.print(userData->weather,2,6);
  display.print("Temp: ",4,0);
  display.print(userData->temp,4,6);
// display.print("Last Updata : ",7,2);
display.print(userData->udate,6,0);
// display.print("\r\n");
delay(4*1000);
}

 

// 关闭与HTTP服务器连接
void stopConnect() {
  Serial.println("Disconnect");
  client.stop();
}

 

void clrEsp8266ResponseBuffer(void){
    memset(response, 0, MAX_CONTENT_SIZE);      //清空
}
 
 
程序下载地址:http://bbs.doit.am/forum.php?mod=viewthread&tid=442&extra=

转载于:https://www.cnblogs.com/ESP8266/p/9186143.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/ZHANGGUOQI20120/article/details/102353379

智能推荐

博弈-巴什博弈-程序员宅基地

博弈论:是二人或多人在平等的对局中各自利用对方的策略变换自己的对抗策略,达到取胜目标的理论。巴什博弈(Bash Game):只有一堆n个物品,两个人轮流从这n个物品中取数,规定每次至少取一个,最多取m个,最后取光着获胜。显然,如果n=m+1,那么由于一次最多只能取m个,所以无论先取者拿走多少个,后取者都能够一次拿走剩余的物品,后取者获胜。因此我们发现了如何获胜的法则,每个回合时m+1个,如果n=(..._巴什博弈

html使用div显示会错位,DIV+CSS网页错位诊断和解决方法-程序员宅基地

你地DIV+CSS网页错位的概念是否了解,这里和大家分享一下常见DIV+CSS网页错位问题及解决方法,希望对你的学习有所帮助。DIV+CSS网页错位诊断随着WEB2.0标准化设计理念的普及,国内很多大型门户网站已经纷纷采用DIV+CSS制作方法,奋斗网络也成为了CSS网页布局技术学习的先锋站点,从实际应用情况来看,此种方法绝对好于表格制作页面的方法。如今大部分网站仍然采用表格嵌套内容的方式来制作网..._div 里面的内容与元素占位有位移

UVa 1595 - Symmetry_东风uva-程序员宅基地

题意平面上一些点, 找是否存在一条竖线 是这些点的对称轴思路水题 一开始还以为是对称轴 不好做, 后来一读题这对称轴一定是与x轴垂直的竖线, 就很好处理了 用set&lt; pair&lt; int,int&gt; &gt; s; 存下所有点 横坐标最大值和最小值除以二就是对称轴竖线所在的线 然后再对对称轴左边的点逐一判断有没有对称轴右边的对应点即可AC代码..._东风uva

置换密码c语言,替代密码和置换密码的C语言实现-程序员宅基地

《替代密码和置换密码的C语言实现》由会员分享,可在线阅读,更多相关《替代密码和置换密码的C语言实现(13页珍藏版)》请在人人文库网上搜索。1、实验一一、实验名称:替代密码和置换密码的实现二、实验目的:通过编程实现替代密码算法和置换密码算法,加深对古典密码体系的了解,为以后深入学习密码学奠定基础。三、实验内容:A:替代密码1、实验原理:使用替代法进行加密,将明文中的字符用其他字符替代后形成密文。最早..._置换密码c语言

最后一期:如何更新LSTM模型?(附代码)| 博士带你学LSTM_lstm参数更新-程序员宅基地

最后一期:如何更新LSTM模型?(附代码)| 博士带你学LSTMLSTM是一种时间递归神经网络,适合于处理和预测时间序列中间隔和延迟相对较长的重要事件。在自然语言处理、语言识别等一系列的应用上都取得了很好的效果。《Long Short Term Memory Networks with Python》是澳大利亚机器学习专家Jason Brownlee的著作,里面详细介绍了..._lstm参数更新

solr学习安装随笔_slorj客户端查询api-程序员宅基地

1.案例:实现solr电商的搜索功能2.解决方案:2.1方案一  使用数据库搜索,关系型数据库mysql、oracle实现搜索商品信息,标题中包含关键的商品。     select * from 商品表 where 商品标签 like ‘%搜索信息%’   海量数据中搜索速度非常慢,顺序扫描。   like是否能使用索引?   ’%%’:索引不能使用这种形式   关键词%:可以使用索引_slorj客户端查询api

随便推点

Fuzzing及Sulley简介-程序员宅基地

模糊测试(Fuzzing)1、泛化定义:Fuzzing是一种软件漏洞检测技术,通过提供非预期的、随机的或者错误的数据作为输入来检测软件漏洞,在软件出现崩溃时监视异常结果来找出其存在的潜在漏洞。2、类比理解可以将模糊测试类比为如何闯进一幢房子。为了破门进入某人的家,假设采用纯白盒的方法,那么在实施破门之前应该能够得到对所有关于这个家的充分信息。这些信息可能要包括房屋设计图、各种锁的制造商列表、房屋建筑

python 加密解密 rc4_python RC4加密操作示例【测试可用】-程序员宅基地

python如何实现rsa加密的示例代码分享import rsakey = rsa.newkeys(3000)#生成随机秘钥privateKey = key[1]#私钥publicKey = key[0]#公钥message ='sanxi Now is better than never.'print('Before encrypted:',message)message = message.e..._rc4加密例子

window.close and self.close do not close the window in Chrome-程序员宅基地

The issue is that when I invoke window.close or self.close it doesn't close the window. Now there seems to be a belief that in Chrome you can't close by script any window that is not script created.

修改qt QTableView里的modal数据并更新数据_qml view中修改model-程序员宅基地

1.当表格有某行被选择时,获取所选行的QModelIndex并调用setData函数int row = ui.tv_searchList->currentIndex().row();//QAbstractItemModel *model = ui.tv_searchList->model();//m_deviceTableModel是qtableview关联的modal类_qml view中修改model

[Qt] 循序容器(QVector、QLinkedList、QList...)-程序员宅基地

QVector 、 QLinkedList与QList是Qt所提供的几个常用容器类别。QVector将 ​​项目(item)储存在邻接的记忆体空间之中,提供基于索引(index-based)存取方式的容器类别。QLinkedList以链结(Linked)的方式储存项目,提供基于迭代器(iterator- based )存取方式的容器类别。QList提供基于索引的快速存取容器类别,内部使用指标阵列,

Drawing skins in container-程序员宅基地

Drawing skins in containerFrom Forum Nokia WikiThe CSkinnedContainer implementation illustrates how to draw skins in a CCoeControl derived container in the S60 platform. The iBgContext is th