【好奇心驱动力】ESP8266从零开始折腾记录

0.前言

最开始接触到ESP8266主要是在做完树莓派电子价签之后看到的,由ESP8266连接OLED屏幕可以显示图案,比树莓派连接电子价签显示要更灵活一些,从那之后开始正式接触ESP8266,后续又做了WIFI Killer,连接温湿度传感器,以及最近做好的通过小程序远程控制开关灯,期间编写脚本从Micropython到ArduinoIDE也算学习了不少。
在这些学习中主要感谢B站up主
会飞的阿卡林(UID:751219)
Hans叫泽涵(UID:15481541)
爱学习的素丸子(UID:269864982)

下面给几个之前做的链接,方便查找和参考:

0.【好奇心驱动力】e-paper电子价签从零开始折腾记录
1.【好奇心驱动力】ESP8266制作WiFikiller过程
2.【好奇心驱动力】ESP8266刷MicroPython及OLED显示
3.【好奇心驱动力】基于MicroPython的ESP8266连接OLED显示实时天气
4.【好奇心驱动力】ESP8266 PIN与GPIO引脚对应关系
5.【好奇心驱动力】ESP8266制作透明小电视

1.实验目的

利用ESP8266连接OLED屏幕显示时间、天气、室内温度
并通过小程序控制开关发光二极管。

2.实验方法

  • OLED屏幕显示当前时间
    利用的是B站UP主会飞的阿卡林、Hans叫泽涵(代码基于会飞的阿卡林)的源码,基本没有做修改,UP主的代码实现是通过连接阿里云NTP服务器进行获时、校准,再将返回的时间按格式进行显示。
    会飞的阿卡林源码:一直判断时间,只要时间变化就会显示。
    Hans叫泽涵源码:没有一直判断时间,结合了后面的图像变化,每个周期只更新一次时间。
    最终借鉴的是会飞的阿卡林的源码,感觉时间一直更新会看起来比较舒服,包括星期等字模,实际运行过程中有的时候回出现一次跳2秒的情况,因为判断时间变化也不是立刻能够更改并显示的,整体可以接受。效果如下图所示:
    【好奇心驱动力】ESP8266从零开始折腾记录_第1张图片
  • OLED屏幕显示当前天气
    想法的创新部分,利用的是B站UP主会飞的阿卡林、Hans叫泽涵(代码基于会飞的阿卡林)的源码,两位UP主显示时间之后显示的都是B站粉丝数,既然能够获取B站粉丝数,当然也可以通过访问天气网站的API接口来获取实时天气。之前利用树莓派连接墨水屏已经显示过天气,所以也是写类似的代码来解析返回的数据再进行显示,其余就是具体排版。
    天气数据使用的是OpenweatherAPI接口,图标也是Openweather官方提供的图标,显示地区、天气、风速、图标,效果如下图所示:
    【好奇心驱动力】ESP8266从零开始折腾记录_第2张图片
  • OLED显示当前室内温湿度
    想法的创新部分,之前给ESP8266刷MicroPython的时候连接过DHT11温湿度传感器,所以直接拿过来用就可以了,显示室内实时温湿度,效果如下图所示:
    【好奇心驱动力】ESP8266从零开始折腾记录_第3张图片
  • 小程序远程控制发光二极管开关
    利用的是B站UP主爱学习的素丸子的完整过程,物联网利用小程序远程控制LED灯开关,之前查找了很多资料只有这个UP主完整记录了操作过程,CSDN博主半颗心脏也提供了很多相关知识,虽然期间由于阿里云物联网平台有更新存在一定对照不上的情况,但还是最终实现了,是最艰难的过程。
    先贴一下B站UP主的原文:https://www.bilibili.com/read/cv4992901
    CSDN博主的首页:https://blog.csdn.net/xh870189248?spm=1001.2014.3001.5509
    效果如下图所示:

3.实验结果

至此最开始预计实现的功能全都实现了,贴下代码,第一次学习改写还比较乱,请大佬轻喷,需要修改的地方有WIFI用户名密码、openweatherAPI链接。

#include    //安装esp8266arduino开发环境
#include   //安装PubSubClient库
#include    //json  V6版本
#include 
#include "aliyun_mqtt.h"
//------------------
#include 
#include 
//#include 
//#include 
#include 
#include 
#include 
#include 
#include 

//U8G2_SSD1306_128X64_NONAME_F_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/4, /* dc=*/5, /* reset=*/3);
//如果是四线IIC的屏幕请替换成下面这行代码
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);

//---------------修改此处""内的信息---------------------------------------------
const char ssid[] = "XXXXXXXXXXX";                       //WiFi名
const char pass[] = "XXXXXXXXXXX";                   //WiFi密码
//-----------------------------------------------------------------------------

static const char ntpServerName[] = "ntp1.aliyun.com"; //NTP服务器,阿里云
const int timeZone = 8;                                //时区,北京时间为+8

const unsigned long HTTP_TIMEOUT = 10000;
WiFiClient client;
HTTPClient http;
WiFiUDP Udp;
unsigned int localPort = 8888; // 用于侦听UDP数据包的本地端口
#define DHT11PIN 14 //dht11连线接口
dht11 DHT11; //定义为DHT11
//函数定义
time_t getNtpTime();
void sendNTPpacket(IPAddress& address);
void oledClockDisplay();
void sendCommand(int command, int value);
void initdisplay();
//变量参数
bool getJson();
String response;
String weather_main;
String location;
String icon;
int wind_speed;
bool parseJson(String json);

boolean isNTPConnected = false;

const unsigned char xing[] U8X8_PROGMEM = {
  0x00, 0x00, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x08, 0x08, 0xF8, 0x0F, 0x80, 0x00, 0x88, 0x00,
  0xF8, 0x1F, 0x84, 0x00, 0x82, 0x00, 0xF8, 0x0F, 0x80, 0x00, 0x80, 0x00, 0xFE, 0x3F, 0x00, 0x00
};  /*星*/
const unsigned char liu[] U8X8_PROGMEM = { 
  0x40, 0x00, 0x80, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xFF, 0x7F, 0x00, 0x00, 0x00, 0x00,
  0x20, 0x02, 0x20, 0x04, 0x10, 0x08, 0x10, 0x10, 0x08, 0x10, 0x04, 0x20, 0x02, 0x20, 0x00, 0x00
};  /*六*/


//天气图标
const unsigned char A_01d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x03,0x00,0x00,0x80,0x03,0x00,0x00,0x82,0x83,0x00,0x00,0x07,0xc1,0x01,0x00,0x8e,0xe3,0x00,0x00,0xec,0x6f,0x00,0x00,0xf0,0x1e,0x00,0x00,0x38,0x38,0x00,0x00,0x18,0x30,0x00,0xc0,0x1d,0x30,0x03,0xc0,0x0f,0xb0,0x07,0xc0,0x1d,0xb0,0x07,0x00,0x18,0x30,0x00,0x00,0x38,0x38,0x00,0x00,0xf0,0x1f,0x00,0x00,0xec,0x6f,0x00,0x00,0x0e,0xe0,0x00,0x00,0x07,0xc3,0x01,0x00,0x80,0x83,0x00,0x00,0x80,0x03,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_01n[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xc0,0x00,0x00,0x00,0xf8,0x00,0x00,0x00,0xfe,0x00,0x00,0x00,0xcf,0x00,0x00,0x00,0xc7,0x00,0x00,0x80,0xc3,0x00,0x00,0xc0,0xc1,0x00,0x00,0xc0,0xc0,0x00,0x00,0xc0,0xc0,0x01,0x00,0xe0,0x80,0x03,0x00,0xe0,0x00,0x07,0x00,0xe0,0x00,0x1e,0x00,0xe0,0x00,0xfc,0x07,0xc0,0x00,0xf0,0x07,0xc0,0x00,0x80,0x03,0xc0,0x01,0x80,0x03,0x80,0x03,0x80,0x01,0x00,0x07,0xc0,0x01,0x00,0x0f,0xf0,0x00,0x00,0x7c,0x7e,0x00,0x00,0xf8,0x1f,0x00,0x00,0xc0,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_02d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x06,0x00,0x00,0x06,0x06,0x03,0x00,0x0c,0x80,0x03,0x00,0x98,0x9f,0x01,0x00,0xc0,0x3f,0x00,0x00,0x60,0x70,0x00,0x00,0x30,0x60,0x00,0x00,0x30,0xc0,0x00,0xc0,0x1b,0xc0,0x1e,0xc0,0x1b,0xc0,0x1e,0x00,0x10,0xc0,0x00,0x00,0x00,0xe0,0x00,0x00,0x78,0x60,0x00,0x80,0xff,0x38,0x00,0xc0,0x87,0x9d,0x01,0x60,0x02,0x83,0x03,0x60,0x00,0x03,0x03,0x70,0x00,0x07,0x02,0x18,0x00,0x0e,0x00,0x18,0x00,0x0c,0x00,0x18,0x00,0x0c,0x00,0xf0,0xff,0x0f,0x00,0xe0,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_02n[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x3e,0x00,0x00,0x00,0x1f,0x00,0x00,0x80,0x1b,0x00,0x00,0xc0,0x39,0x00,0x00,0xc0,0x31,0x00,0x00,0xc0,0x70,0x00,0x00,0xc0,0xe0,0x00,0x00,0xc0,0xe0,0x01,0x00,0xc0,0xc0,0x3f,0x00,0xc0,0x00,0x1f,0x00,0x00,0x00,0x1c,0x00,0xe0,0x03,0x1c,0x00,0xf0,0x07,0x0e,0x00,0x3f,0xce,0x07,0x80,0x1f,0xdc,0x03,0xc0,0x09,0x18,0x00,0xc0,0x00,0x18,0x00,0xe0,0x00,0x38,0x00,0xf0,0x00,0x78,0x00,0x38,0x00,0xe0,0x00,0x18,0x00,0xc0,0x00,0x18,0x00,0xc0,0x00,0x30,0x00,0xc0,0x00,0xf0,0xff,0xff,0x00,0xe0,0xff,0x7f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_03d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x20,0x00,0x00,0x00,0x21,0x0c,0x00,0x00,0x03,0x06,0x00,0x00,0xfa,0x02,0x00,0x00,0x8c,0x01,0x00,0x00,0x04,0x03,0x00,0x00,0x04,0x3f,0x00,0x00,0x00,0x1b,0x00,0x80,0x8f,0x01,0x00,0xe0,0x9f,0x01,0x00,0x7e,0x30,0x06,0x00,0x3f,0x60,0x0e,0x80,0x11,0x40,0x0c,0xc0,0x00,0xc0,0x00,0xc0,0x00,0x40,0x00,0xe0,0x00,0xc0,0x01,0x30,0x00,0xe0,0x03,0x18,0x00,0x00,0x06,0x18,0x00,0x00,0x06,0x18,0x00,0x00,0x04,0x18,0x00,0x00,0x06,0x30,0x00,0x00,0x06,0xe0,0xfe,0xbf,0x03,0xc0,0xff,0xff,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_03n[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0x01,0x00,0x00,0xf0,0x00,0x00,0x00,0xb8,0x00,0x00,0x00,0x98,0x01,0x00,0x00,0x98,0x03,0x00,0x00,0x08,0x0f,0x00,0x00,0x08,0x3e,0x00,0x00,0x04,0x18,0x00,0x80,0x3f,0x1c,0x00,0xc0,0xe1,0x0e,0x00,0x7c,0xc0,0x00,0x00,0x7f,0x80,0x01,0x80,0x23,0x00,0x01,0x80,0x01,0x00,0x03,0x80,0x01,0x00,0x03,0xe0,0x01,0x00,0x03,0x70,0x00,0x80,0x0f,0x30,0x00,0x00,0x1c,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x18,0x70,0x00,0x00,0x1c,0xe0,0xff,0xff,0x0f,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_04d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0c,0x00,0x00,0x80,0x3f,0x00,0x00,0xc0,0xe1,0x00,0x00,0xfe,0xc0,0x01,0x00,0x7f,0x80,0x01,0x80,0x23,0x00,0x01,0x80,0x01,0x00,0x03,0x80,0x00,0x00,0x03,0xc0,0x00,0x00,0x03,0xe0,0x00,0x80,0x0f,0x30,0x00,0x00,0x1c,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x30,0x00,0x00,0x18,0xe0,0xff,0xff,0x0f,0xc0,0xff,0xff,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_09d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0xc0,0x7f,0x00,0x00,0xe0,0xc0,0x00,0x00,0x7e,0x80,0x01,0x00,0x27,0x80,0x01,0x80,0x01,0x00,0x03,0x80,0x00,0x00,0x03,0xc0,0x00,0x00,0x03,0xe0,0x01,0x00,0x07,0x30,0x00,0x00,0x0f,0x18,0x00,0x00,0x18,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x38,0x00,0x00,0x38,0x70,0x00,0x00,0x1c,0xe0,0x6f,0xe9,0x0f,0x80,0xb7,0xed,0x07,0x00,0xf0,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xb6,0x01,0x00,0x00,0xb6,0x01,0x00,0x00,0xdb,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_10d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1f,0x00,0x00,0x80,0x7f,0x00,0x00,0xc0,0xe0,0x00,0x00,0x7e,0x80,0x01,0x00,0x3f,0x80,0x01,0x80,0x01,0x00,0x03,0x80,0x01,0x00,0x03,0x80,0x00,0x00,0x03,0xe0,0x01,0x00,0x07,0x70,0x00,0x80,0x1f,0x38,0x00,0x00,0x18,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x18,0x00,0x00,0x30,0x38,0x60,0x12,0x38,0x70,0x60,0x1b,0x18,0xe0,0x6f,0xfb,0x0f,0xc0,0xbf,0xed,0x07,0x00,0xb0,0x0d,0x00,0x00,0xd8,0x0f,0x00,0x00,0xd8,0x06,0x00,0x00,0xd8,0x06,0x00,0x00,0x6c,0x03,0x00,0x00,0x6c,0x03,0x00,0x00,0x30,0x00,0x00,0x00,0x30,0x00,0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_11d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3f,0x00,0x00,0x80,0x7f,0x00,0x00,0xe0,0xe0,0x00,0x00,0x7e,0x80,0x01,0x00,0x37,0x80,0x01,0x80,0x01,0x00,0x03,0x80,0x00,0x00,0x03,0x80,0x00,0x00,0x03,0xe0,0x01,0x00,0x07,0x70,0x00,0x80,0x1f,0x38,0x00,0x00,0x18,0x18,0x00,0x00,0x30,0x18,0x00,0x06,0x30,0x18,0x00,0x06,0x30,0x38,0x00,0x03,0x38,0x70,0x80,0x03,0x1c,0xe0,0x8f,0xe1,0x0f,0xc0,0xcf,0xee,0x07,0x00,0xe0,0x0f,0x00,0x80,0x6d,0x27,0x03,0x80,0x0d,0xb3,0x03,0xc0,0x86,0xb3,0x01,0xc0,0x86,0xd9,0x01,0x40,0xc2,0x98,0x00,0x00,0xc0,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_13d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x80,0x01,0x00,0x00,0x40,0x05,0x00,0x00,0xd6,0xd7,0x00,0x00,0xbe,0x53,0x00,0x00,0x3c,0x31,0x00,0x00,0xbe,0xf9,0x00,0x00,0x74,0x6d,0x00,0x00,0xe3,0x85,0x01,0x80,0xd6,0xd7,0x03,0xc0,0xff,0xff,0x07,0x00,0x86,0xc7,0x00,0x00,0x63,0x8f,0x01,0x00,0x34,0x1d,0x00,0x00,0x9e,0xf9,0x00,0x00,0x38,0x71,0x00,0x00,0xb6,0xf3,0x00,0x00,0xd2,0xd7,0x00,0x00,0xc0,0x05,0x00,0x00,0x80,0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_50d[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x80,0x7f,0x00,0x00,0xc0,0xef,0x00,0x04,0x40,0x80,0x03,0x07,0x00,0x10,0xfe,0x03,0x80,0x7f,0x78,0x00,0xc0,0xe1,0x01,0x04,0x40,0x80,0x87,0x07,0x00,0x0c,0xfe,0x03,0x80,0xff,0x30,0x00,0xc0,0xc1,0x01,0x06,0x40,0x00,0x87,0x07,0x00,0x00,0xfe,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
const unsigned char A_unknown[] U8X8_PROGMEM = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0e,0x00,0x00,0x80,0x7f,0x00,0x00,0xc0,0xf1,0x00,0x00,0xfe,0xc0,0x01,0x00,0x7f,0x80,0x01,0x80,0xa3,0x87,0x03,0x80,0xc1,0x0f,0x03,0x80,0xc0,0x0c,0x03,0xe0,0xc1,0x0c,0x07,0x70,0x00,0x86,0x0f,0x30,0x00,0x03,0x1c,0x18,0x00,0x03,0x38,0x18,0x00,0x03,0x30,0x18,0x00,0x03,0x30,0x18,0x00,0x03,0x30,0x30,0x00,0x03,0x18,0xf0,0xff,0xff,0x1f,0xc0,0xff,0xff,0x0f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};


const int slaveSelect = 5;
const int scanLimit = 7;
int times = 0;
//------------------
//需要安装crypto库
#define LED     D7
#define WIFI_SSID        "XXXXXXXX"//替换自己的WIFI
#define WIFI_PASSWD      "XXXXXXXX"//替换自己的WIFI

#define PRODUCT_KEY      "XXXXXXXX" //替换自己的PRODUCT_KEY
#define DEVICE_NAME      "ESP8266Side" //替换自己的DEVICE_NAME
#define DEVICE_SECRET    "XXXXXXXX"//替换自己的DEVICE_SECRET

#define DEV_VERSION       "S-TH-WIFI-v1.0-20190220"        //固件版本信息

#define ALINK_BODY_FORMAT         "{\"id\":\"123\",\"version\":\"1.0\",\"method\":\"%s\",\"params\":%s}"
#define ALINK_TOPIC_PROP_POST     "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post"
#define ALINK_TOPIC_PROP_POSTRSP  "/sys/" PRODUCT_KEY "/" DEVICE_NAME "/thing/event/property/post_reply"
#define ALINK_TOPIC_PROP_SET      "/" PRODUCT_KEY "/" DEVICE_NAME "/user/sub"
#define ALINK_METHOD_PROP_POST    "thing.event.property.post"
#define ALINK_TOPIC_DEV_INFO      "/ota/device/inform/" PRODUCT_KEY "/" DEVICE_NAME ""    
#define ALINK_VERSION_FROMA      "{\"id\": 123,\"params\": {\"version\": \"%s\"}}"
unsigned long lastMs = 0;
int pos = 90;

WiFiClient   espClient;
PubSubClient mqttClient(espClient);
Servo myServo;

void init_wifi(const char *ssid, const char *password)      //连接WiFi
{
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        Serial.println("WiFi does not connect, try again ...");
        delay(500);
    }

    Serial.println("Wifi is connected.");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
}

void mqtt_callback(char *topic, byte *payload, unsigned int length) //mqtt回调函数
{
    Serial.print("Message arrived [");
    Serial.print(topic);
    Serial.print("] ");
    payload[length] = '\0';
    Serial.print("****** ");
    Serial.println((char *)payload);
    Serial.print("****** ");
   // https://arduinojson.org/v5/assistant/  json数据解析网站

    
 
  Serial.println((char *)payload);
   
    if (strstr(topic, ALINK_TOPIC_PROP_SET))
    {
        StaticJsonDocument<100> jsonBuffer;
        deserializeJson(jsonBuffer,payload);
        JsonObject root = jsonBuffer.as<JsonObject>();
        auto error = deserializeJson(jsonBuffer,payload);
        //JsonObject &root = jsonBuffer.parseObject(payload);
        int params_LightSwitch = root["params"]["LightSwitch"];
        if(params_LightSwitch==1)
        {Serial.println("led off");
        digitalWrite(LED, HIGH); 
        }
        else
        {Serial.println("led on");
        if (!digitalRead(LED)){
          digitalWrite(LED, HIGH);
          for(pos=90;pos>55;pos--){
           myServo.write(pos);             // 使用pos变量数值设置伺服电机
           delay(15);} 
        }else{
          digitalWrite(LED, LOW);
          for(pos=55 ;pos<=90;pos++){
           myServo.write(pos);             // 使用pos变量数值设置伺服电机
           delay(15);
          }
        }
        }
        if (error)
        {
            Serial.println("parseObject() failed");
            return;
        }
    }
}
void mqtt_version_post()
{
    char param[512];
    char jsonBuf[1024];

    //sprintf(param, "{\"MotionAlarmState\":%d}", digitalRead(13));
    sprintf(param, "{\"id\": 123,\"params\": {\"version\": \"%s\"}}", DEV_VERSION);
   // sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
    Serial.println(param);
    mqttClient.publish(ALINK_TOPIC_DEV_INFO, param);
}
void mqtt_check_connect()
{
    while (!mqttClient.connected())//
    {
        while (connect_aliyun_mqtt(mqttClient, PRODUCT_KEY, DEVICE_NAME, DEVICE_SECRET))
        {
            Serial.println("MQTT connect succeed!");
            //client.subscribe(ALINK_TOPIC_PROP_POSTRSP);
            mqttClient.subscribe(ALINK_TOPIC_PROP_SET);
            
            Serial.println("subscribe done");
            mqtt_version_post();
        }
    }
    
}

void mqtt_interval_post()
{
    char param[512];
    char jsonBuf[1024];

    //sprintf(param, "{\"MotionAlarmState\":%d}", digitalRead(13));
    sprintf(param, "{\"LightSwitch\":%d,\"CurrentTemperature\":%d}", !digitalRead(LED),random(0,55));
    sprintf(jsonBuf, ALINK_BODY_FORMAT, ALINK_METHOD_PROP_POST, param);
    Serial.println(jsonBuf);
    mqttClient.publish(ALINK_TOPIC_PROP_POST, jsonBuf);
}


void setup()
{
    myServo.attach(D8);
    pinMode(LED, OUTPUT);
    /* initialize serial for debugging */
    Serial.begin(115200);

    Serial.println("Demo Start");

    init_wifi(WIFI_SSID, WIFI_PASSWD);

    mqttClient.setCallback(mqtt_callback);
    //-----
    while (!Serial)
      continue;
    Serial.println("NTP Clock Weather Display v1.0");
    initdisplay();
    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_unifont_t_chinese2);
    u8g2.setCursor(0, 14);
    u8g2.print("Waiting for WiFi");
    u8g2.setCursor(0, 30);
    u8g2.print("Connection...");
    u8g2.setCursor(0, 47);
    u8g2.print("By CC.INC");
    u8g2.setCursor(0, 64);
    u8g2.print("WeatherClock");
    u8g2.sendBuffer();
  
  
    Serial.print("Connecting WiFi...");
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, pass);
    while (WiFi.status() != WL_CONNECTED){
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    Serial.println("Starting UDP");
    Udp.begin(localPort);
    Serial.print("Local port: ");
    Serial.println(Udp.localPort());
    Serial.println("waiting for sync");
    setSyncProvider(getNtpTime);
    setSyncInterval(300); //每300秒同步一次时间
    isNTPConnected = true;
    //-----
}
//----
time_t prevDisplay = 0;   //当时钟已经显示

// the loop function runs over and over again forever
void loop()
{
   if (millis() - lastMs >= 50000)  //5S
    {
        lastMs = millis();
        mqtt_check_connect();
                 
       // mqtt_interval_post();
    }

    mqttClient.loop();
    if (times <10) {
    if (timeStatus() != timeNotSet)
    {
      if (now() != prevDisplay)
      { 
        //时间改变时更新显示
        prevDisplay = now();
        oledClockDisplay();
      }
    }
  }

  if (times == 10) {
    if (WiFi.status() == WL_CONNECTED){
        if (getJson()){
            if (parseJson(response)){
                  DHT11.read(DHT11PIN);
                  u8g2.clearBuffer();
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  //icon
                  if (icon == "A_01d"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_01d );
                    }
                  else if (icon == "A_01n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_01n ); 
                    }
                  else if (icon == "A_02d"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_02d );
                    }
                  else if (icon == "A_02n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_02n );
                    }
                  else if (icon == "A_03d"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_03d );
                    }
                  else if (icon == "A_03n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_03n );
                    }
                  else if (icon == "A_04d" or icon == "A_04n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_04d );
                    }
                  else if (icon == "A_09d" or icon == "A_09n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_09d );
                    }
                  else if (icon == "A_10d" or icon == "A_10n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_10d );
                    }
                  else if (icon == "A_11d" or icon == "A_11n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_11d );
                    }
                  else if (icon == "A_13d" or icon == "A_13n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_13d );
                    }
                  else if (icon == "A_50d" or icon == "A_50n"){
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_50d );
                    }
                  else {
                    u8g2.drawXBMP( 96 , 32 , 32 , 32 , A_unknown );
                    }
                  //Temperature
                  u8g2.setCursor(0, 45);
                  u8g2.print("InD_Tem:");
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(64, 45);
                  u8g2.println((int)DHT11.temperature);
                  u8g2.println("C");
                  //Humidity
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(0, 62);
                  u8g2.print("InD_Hum:");
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(64, 62);
                  u8g2.println((int)DHT11.humidity);
                  u8g2.println("%");
                  //wind
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(0, 28);
                  u8g2.println("Now_Wind:");
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(71, 28);
                  u8g2.println(wind_speed);
                  u8g2.println("m/s");
                  //location
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(0, 11);
                  u8g2.println(location);
                  //weather
                  u8g2.setFont(u8g2_font_unifont_t_chinese2);
                  u8g2.setCursor(64, 11);
                  u8g2.println(weather_main);
                  u8g2.sendBuffer();
            }
         }
         delay(1000);
    }
  }
  
  times += 1;
  if (times >= 15) {
    times = 0;
  }
  delay(1000);
}

bool getJson()
{
   bool r = false;  
   http.setTimeout(HTTP_TIMEOUT);
   http.begin("http://api.openweathermap.org/data/2.5/weather?q=beijing&appid=XXXXXXX"); 
   int httpCode = http.GET();
   if (httpCode > 0){
      if (httpCode == HTTP_CODE_OK){
          response = http.getString();
          Serial.println(response);
          r = true;
        }
    }else{
      Serial.printf("[HTTP] GET JSON failed, error: %s\n", http.errorToString(httpCode).c_str());
      r = false;
    }
    http.end();
    return r;
}

//JSON
bool parseJson(String json){
  const size_t capacity = 1024;
  DynamicJsonDocument doc(capacity);
  deserializeJson(doc,json);
  //weather
  const char *weather_main_fun = doc["weather"][0]["main"];
  //city
  const char *location_fun = doc["name"];
  //wind_speed
  JsonObject wind_c = doc["wind"];
  int wind = wind_c["speed"];
  //icon
  String icon_fun = doc["weather"][0]["icon"];
  //parameter
  weather_main = weather_main_fun;
  location = location_fun;
  wind_speed = wind;
  icon = "A_"+icon_fun;
  //Serial.println(icon);
  //true
  return true;
}

void initdisplay()
{
  u8g2.begin();
  u8g2.enableUTF8Print();
}

void oledClockDisplay()
{
  int years, months, days, hours, minutes, seconds, weekdays;
  years = year();
  months = month();
  days = day();
  hours = hour();
  minutes = minute();
  seconds = second();
  weekdays = weekday();
  Serial.printf("%d/%d/%d %d:%d:%d Weekday:%d\n", years, months, days, hours, minutes, seconds, weekdays);
  u8g2.clearBuffer();
  u8g2.setFont(u8g2_font_unifont_t_chinese2);
  u8g2.setCursor(0, 14);
  if (isNTPConnected)
    u8g2.print("当前时间 (UTC+8)");
  else
    u8g2.print("无网络!"); //如果上次对时失败,则会显示无网络
  String currentTime = "";
  if (hours < 10)
    currentTime += 0;
  currentTime += hours;
  currentTime += ":";
  if (minutes < 10)
    currentTime += 0;
  currentTime += minutes;
  currentTime += ":";
  if (seconds < 10)
    currentTime += 0;
  currentTime += seconds;
  String currentDay = "";
  currentDay += years;
  currentDay += "/";
  if (months < 10)
    currentDay += 0;
  currentDay += months;
  currentDay += "/";
  if (days < 10)
    currentDay += 0;
  currentDay += days;

  u8g2.setFont(u8g2_font_logisoso24_tr);
  u8g2.setCursor(0, 44);
  u8g2.print(currentTime);
  u8g2.setCursor(0, 61);
  u8g2.setFont(u8g2_font_unifont_t_chinese2);
  u8g2.print(currentDay);
  u8g2.drawXBM(80, 48, 16, 16, xing);
  u8g2.setCursor(95, 62);
  u8g2.print("期");
  if (weekdays == 1)
    u8g2.print("日");
  else if (weekdays == 2)
    u8g2.print("一");
  else if (weekdays == 3)
    u8g2.print("二");
  else if (weekdays == 4)
    u8g2.print("三");
  else if (weekdays == 5)
    u8g2.print("四");
  else if (weekdays == 6)
    u8g2.print("五");
  else if (weekdays == 7)
    u8g2.drawXBM(111, 49, 16, 16, liu);
  u8g2.sendBuffer();
}

/*-------- NTP 代码 ----------*/

const int NTP_PACKET_SIZE = 48;     // NTP时间在消息的前48个字节里
byte packetBuffer[NTP_PACKET_SIZE]; // 输入输出包的缓冲区


time_t getNtpTime()
{
  IPAddress ntpServerIP;          // NTP服务器的地址

  while (Udp.parsePacket() > 0);  // 丢弃以前接收的任何数据包
  Serial.println("Transmit NTP Request");
  // 从池中获取随机服务器
  WiFi.hostByName(ntpServerName, ntpServerIP);
  Serial.print(ntpServerName);
  Serial.print(": ");
  Serial.println(ntpServerIP);
  sendNTPpacket(ntpServerIP);
  uint32_t beginWait = millis();
  while (millis() - beginWait < 1500)
  {
    int size = Udp.parsePacket();
    if (size >= NTP_PACKET_SIZE)
    {
      Serial.println("Receive NTP Response");
      isNTPConnected = true;
      Udp.read(packetBuffer, NTP_PACKET_SIZE); // 将数据包读取到缓冲区
      unsigned long secsSince1900;
      // 将从位置40开始的四个字节转换为长整型,只取前32位整数部分
      secsSince1900 = (unsigned long)packetBuffer[40] << 24;
      secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
      secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
      secsSince1900 |= (unsigned long)packetBuffer[43];
      Serial.println(secsSince1900);
      Serial.println(secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR);
      return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
    }
  }
  Serial.println("No NTP Response :-("); //无NTP响应
  isNTPConnected = false;
  return 0; //如果未得到时间则返回0
}


// 向给定地址的时间服务器发送NTP请求
void sendNTPpacket(IPAddress& address)
{
  memset(packetBuffer, 0, NTP_PACKET_SIZE);
  packetBuffer[0] = 0b11100011; // LI, Version, Mode
  packetBuffer[1] = 0;          // Stratum, or type of clock
  packetBuffer[2] = 6;          // Polling Interval
  packetBuffer[3] = 0xEC;       // Peer Clock Precision
  // 8 bytes of zero for Root Delay & Root Dispersion
  packetBuffer[12] = 49;
  packetBuffer[13] = 0x4E;
  packetBuffer[14] = 49;
  packetBuffer[15] = 52;
  Udp.beginPacket(address, 123); //NTP需要使用的UDP端口号为123
  Udp.write(packetBuffer, NTP_PACKET_SIZE);
  Udp.endPacket();
}

你可能感兴趣的:(好奇心驱动力,单片机,ESP8266,物联网,arduino)