215 lines
5.7 KiB
C++
215 lines
5.7 KiB
C++
#ifndef __UTILS__
|
||
#include <utils.h>
|
||
#endif
|
||
|
||
#include <Arduino.h>
|
||
|
||
#include <ESP8266WiFi.h>
|
||
#include <ESP8266HTTPClient.h>
|
||
#include <WiFiClientSecureBearSSL.h>
|
||
|
||
#include <ArduinoJson.h>
|
||
|
||
#include <TimeLib.h>
|
||
#include <WiFiUdp.h>
|
||
|
||
// Global Config
|
||
IPConfig APStatic = {
|
||
IPAddress(10, 1, 1, 1),
|
||
IPAddress(10, 0, 1, 1),
|
||
IPAddress(255, 255, 255, 0)
|
||
};
|
||
IPConfig STAStatic = {
|
||
IPAddress(192, 168, 43, 141),
|
||
IPAddress(192,168,0,1),
|
||
IPAddress(255, 255, 255, 0)
|
||
};
|
||
BoardInfo Board = {
|
||
"0.0.1",
|
||
WiFi.localIP()
|
||
};
|
||
|
||
// https://github.com/PaulStoffregen/Time/blob/master/examples/TimeNTP_ESP8266WiFi/TimeNTP_ESP8266WiFi.ino
|
||
static const int timeZone = 8;
|
||
static const int NTP_PACKET_SIZE = 48;
|
||
static byte packetBuffer[NTP_PACKET_SIZE];
|
||
static IPAddress ntpServerIP(203, 107, 6, 88);
|
||
// static const char ntpServerName[] = "ntp.aliyun.com";
|
||
|
||
static bool isNTPConnected = false;
|
||
static WiFiUDP ntpUDP;
|
||
static unsigned int localPort = 2390;
|
||
|
||
static 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;
|
||
ntpUDP.beginPacket(address, 123);
|
||
ntpUDP.write(packetBuffer, NTP_PACKET_SIZE);
|
||
ntpUDP.endPacket();
|
||
}
|
||
|
||
static time_t getNtpTime() {
|
||
byte tmp[1];
|
||
while( ntpUDP.parsePacket() > 0 ) ntpUDP.read(tmp, 1);
|
||
|
||
sendNTPpacket(ntpServerIP);
|
||
|
||
uint32_t beginWait = millis();
|
||
while( millis() - beginWait < 1500 )
|
||
{
|
||
int size = ntpUDP.parsePacket();
|
||
if( size >= NTP_PACKET_SIZE )
|
||
{
|
||
isNTPConnected = true;
|
||
ntpUDP.read(packetBuffer, NTP_PACKET_SIZE);
|
||
|
||
// 将从位置40开始的四个字节转换为长整型,只取前32位整数部分
|
||
unsigned long secsSince1900;
|
||
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
|
||
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
|
||
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
|
||
secsSince1900 |= (unsigned long)packetBuffer[43];
|
||
|
||
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
|
||
}
|
||
}
|
||
|
||
isNTPConnected = false;
|
||
return 0;
|
||
}
|
||
|
||
void initNtp() {
|
||
ntpUDP.begin(localPort);
|
||
setSyncProvider(getNtpTime);
|
||
setSyncInterval(300);
|
||
}
|
||
|
||
static String formatDigits(int digits)
|
||
{
|
||
if( digits < 10 )
|
||
return "0" + (String)digits;
|
||
return (String)digits;
|
||
}
|
||
|
||
String ntpTime() {
|
||
String timeString("");
|
||
timeString = (String)year() + '-'
|
||
+ formatDigits(month()) + '-'
|
||
+ formatDigits(day()) + ' '
|
||
+ formatDigits(hour()) + ':'
|
||
+ formatDigits(minute()) + ':'
|
||
+ formatDigits(second());
|
||
return timeString;
|
||
}
|
||
|
||
|
||
long view = 0;
|
||
long likes = 0;
|
||
long follower = 0;
|
||
long dayView = 0;
|
||
long weekView = 0;
|
||
long monthView = 0;
|
||
|
||
static String UID = "450115492";
|
||
static String followerUrl = "http://api.bilibili.com/x/relation/stat?vmid=" + UID;
|
||
static String viewAndLikesUrl = "http://api.bilibili.com/x/space/upstat?mid=" + UID;
|
||
static String webViewerUrl = "https://api.foolishfox.cn/data/board.json";
|
||
|
||
static const char UserAgent[] PROGMEM = "UserAgent";
|
||
static const char Cookie[] PROGMEM = "Cookie";
|
||
|
||
static WiFiClient client;
|
||
std::unique_ptr<BearSSL::WiFiClientSecure>clientSecure(new BearSSL::WiFiClientSecure);
|
||
StaticJsonDocument<256> jsonBuffer;
|
||
|
||
static void getFollower() {
|
||
HTTPClient http;
|
||
http.begin(client, followerUrl);
|
||
|
||
int resCode = http.GET();
|
||
if( resCode == 200 ) {
|
||
String resBuffer = http.getString();
|
||
DeserializationError error = deserializeJson(jsonBuffer, resBuffer);
|
||
|
||
if( error ) {
|
||
Serial.print(F("deserializeJson(Follower) failed: "));
|
||
Serial.println(error.f_str());
|
||
return;
|
||
}
|
||
|
||
follower = jsonBuffer["data"]["follower"];
|
||
} else {
|
||
Serial.printf("[HTTP] GET Follower failed, error: %d\n", resCode);
|
||
}
|
||
|
||
http.end();
|
||
}
|
||
|
||
static void getViewAndLikes() {
|
||
HTTPClient http;
|
||
http.begin(client, viewAndLikesUrl);
|
||
|
||
http.addHeader("Host", "api.bilibili.com");
|
||
http.addHeader("User-Agent", UserAgent);
|
||
http.addHeader("Cookie", Cookie);
|
||
|
||
int resCode = http.GET();
|
||
if( resCode == 200 ) {
|
||
String resBuffer = http.getString();
|
||
DeserializationError error = deserializeJson(jsonBuffer, resBuffer);
|
||
|
||
if( error ) {
|
||
Serial.print(F("deserializeJson(View & Likes) failed: "));
|
||
Serial.println(error.f_str());
|
||
return;
|
||
}
|
||
|
||
likes = jsonBuffer["data"]["likes"];
|
||
view = jsonBuffer["data"]["archive"]["view"];
|
||
} else {
|
||
Serial.printf("[HTTP] GET View & Likes failed, error: %d\n", resCode);
|
||
}
|
||
|
||
http.end();
|
||
}
|
||
|
||
static void getWebView() {
|
||
HTTPClient https;
|
||
clientSecure->setInsecure();
|
||
https.begin(*clientSecure, webViewerUrl);
|
||
|
||
int resCode = https.GET();
|
||
if( resCode == 200 ) {
|
||
String resBuffer = https.getString();
|
||
DeserializationError error = deserializeJson(jsonBuffer, resBuffer);
|
||
|
||
if( error ) {
|
||
Serial.print(F("deserializeJson(Web View) failed: "));
|
||
Serial.println(error.f_str());
|
||
return;
|
||
}
|
||
|
||
dayView = jsonBuffer["day"];
|
||
weekView = jsonBuffer["week"];
|
||
monthView = jsonBuffer["month"];
|
||
} else {
|
||
Serial.printf("[HTTP] GET Web View failed, error: %d\n", resCode);
|
||
}
|
||
|
||
https.end();
|
||
}
|
||
|
||
void getData() {
|
||
getFollower();
|
||
getViewAndLikes();
|
||
getWebView();
|
||
} |