ESP8266 MP3——获取时间

获取时间

概述

ESP8266内置芯片无法完成实时功能,或许可以通过串口把当前时间输入,然后用定时器得到对应的时间,但是定时器不会很准,所以用到一定时间就得校准,特别麻烦。而如果一直获取时间,带宽消耗太大,而且费电,所以我给出的方案是每隔一段时间获取一次进行校准,获取后启动定时器来实现实时的时间更新。

网络API接口

这里我推荐使用苏宁易购的免费API:http://quan.suning.com/getSysTime.do
这个API好用在它返回的是具体的北京时间,而不是时间戳不用自己写解析,但是因为免费,所以用的人很多,有时候会返回403,所以多返回错误多请求几次就好了(用代码逻辑实现)。

信息获取

获取时间和获取天气本质上是一样的,用http访问接口,然后通过ArduinoJSON读取出对应的数据即可。
部分代码段:

bool getTimeInfo()
{
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;

    Serial.print("[HTTP] begin...\n");
    if (http.begin(client, "http://quan.suning.com/getSysTime.do")) {  // HTTP
      Serial.print("[HTTP] GET...\n");
      // start connection and send HTTP header
      int httpCode = http.GET();

      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);

        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String res = http.getString();
          Serial.println(res);
          DynamicJsonDocument doc(256);
          deserializeJson(doc,res);
          String timeData = doc["sysTime2"].as<String>();
          Serial.println(timeData);
          setCurrentTime(timeData);
          http.end();
          return true;
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }
  else
  {
    Serial.println("failed to connect to wifi!");
  }
  http.end();
  return false;
}

这个是处理403的片段:

	bool gotTime = false;
    while(!gotTime)
    {
      gotTime = getTimeInfo();
    }

信息处理

自己写个结构体是最方便的了

struct TimeData
{
  int year;
  int month;
  int date;
  int hour;
  int minute;
  int second;
}currentTime;

void setCurrentTime(String timeData)
{
  String year = timeData.substring(0,4);
  String month = timeData.substring(5,7);
  String date = timeData.substring(8,10);
  String hour = timeData.substring(11,13);
  String minute = timeData.substring(14,16);
  String second = timeData.substring(17,19);
  currentTime.year = year.toInt();
  currentTime.month = month.toInt();
  currentTime.date = date.toInt();
  currentTime.hour = hour.toInt();
  currentTime.minute = minute.toInt();
  currentTime.second = second.toInt();
}

不知道我为什么要把数据定义成int形式,现在懒得改了,其实没必要怎么做,直接定义String形式,因为OLED要求的参数也是String
所以大体思路就是获取数据,设置到全局变量中,接下来打印在OLED屏幕即可

定时器

首先需要一个Ticker对象和回调函数

	#include <Ticker.h>
	Ticker myTicker;
	void ticker_callback();

在获取到第一个时间数据(在setup函数里面)后启动定时器,每秒调用一次callback函数(这里定时器的用法很显而易见,还没了解过的朋友可以上网查一查),在回调函数里面把currentTime.second加1,然后刷新屏幕即可:

//启动定时器:
myTicker.attach(1,ticker_callback);

void ticker_callback()
{
  currentTime.second++;
  Serial.println(currentTime.second);
  showOLED();
}

这里还好,但是如果你想这么做,那程序肯定崩!

更新时间和一个重要的问题

按上面那样说,在一段时间后自动重新获取时间,那么我们初定这段时间为一分钟吧,然后一分钟到了自动刷新时间,就有如下代码:

void ticker_callback()
{
  currentTime.second++;
  Serial.println(currentTime.second);
  if(currentTime.second >= 60)
  {
    myTicker.detach();
    bool gotTime = false;
    while(!gotTime)
    {
      gotTime = getTimeInfo();
    }
    if(gotTime)
    {
    	myTicker.attach(1,ticker_callback);
    }
  }
}

如果你真的这么写,那就肯定崩了,因为定时器回调函数不能太复杂,这是特别需要注意的点!
所以应该把更新操作和定时器回调函数分开,怎么做到呢,我想了一种办法:

bool needTo_UpdateTime;
void ticker_callback()
{
  Serial.println(currentTime.second);
  currentTime.second++;
  if(currentTime.second >= 60)
  {
    myTicker.detach();
    needTo_UpdateTime = true;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  if(needTo_UpdateTime)
  {
    bool gotTime = false;
    while(!gotTime)
    {
      gotTime = getTimeInfo();
    }
    if(gotTime)
    {
      myTicker.attach(1,ticker_callback);
    }
    needTo_UpdateTime = false;
  }
}

在loop中判断是我认为最可靠的方式了!
另外,OLED屏幕的显示也稍微有些复杂,建议加个needTo_UpdateOLED变量来确保不会出现大bug

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值