Skip to content

Commit 30d614c

Browse files
committed
adding double reset detector example
1 parent caf443b commit 30d614c

File tree

1 file changed

+212
-0
lines changed

1 file changed

+212
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*******************************************************************
2+
* Read YouTube Channel statistics from the YouTube API *
3+
* This sketch uses the WiFiManager Library for configuraiton *
4+
* Using DoubleResetDetector to launch config mode *
5+
* *
6+
* By Brian Lough *
7+
* https://www.youtube.com/channel/UCezJOfu7OtqGzd5xrP3q6WA *
8+
*******************************************************************/
9+
10+
#include <YoutubeApi.h>
11+
#include <ESP8266WiFi.h>
12+
#include <WiFiClientSecure.h>
13+
14+
15+
#include <DoubleResetDetector.h>
16+
// For entering Config mode by pressing reset twice
17+
// Available on the library manager (DoubleResetDetector)
18+
// https://github.com/datacute/DoubleResetDetector
19+
20+
#include <ArduinoJson.h>
21+
// Required for the YouTubeApi and used for the config file
22+
// Available on the library manager (ArduinoJson)
23+
// https://github.com/bblanchon/ArduinoJson
24+
25+
#include <WiFiManager.h>
26+
// For configuring the Wifi credentials without re-programing
27+
// Availalbe on library manager (WiFiManager)
28+
// https://github.com/tzapu/WiFiManager
29+
30+
// For storing configurations
31+
#include "FS.h"
32+
33+
// Additional libraries needed by WiFiManager
34+
#include <DNSServer.h> //Local DNS Server used for redirecting all rs to the configuration portal
35+
#include <ESP8266WebServer.h> //Local WebServer used to serve the configuration portal
36+
37+
char apiKey[45] = "";
38+
char channelId[30] = "UCezJOfu7OtqGzd5xrP3q6WA";
39+
40+
WiFiClientSecure client;
41+
YoutubeApi *api;
42+
43+
unsigned long api_mtbs = 60000; //mean time between api requests
44+
unsigned long api_lasttime; //last time api request has been done
45+
46+
long subs = 0;
47+
48+
// flag for saving data
49+
bool shouldSaveConfig = false;
50+
51+
// Number of seconds after reset during which a
52+
// subseqent reset will be considered a double reset.
53+
// This sketch uses drd.stop() rather than relying on the timeout
54+
#define DRD_TIMEOUT 10
55+
56+
// RTC Memory Address for the DoubleResetDetector to use
57+
#define DRD_ADDRESS 0
58+
59+
DoubleResetDetector drd(DRD_TIMEOUT, DRD_ADDRESS);
60+
61+
//callback notifying us of the need to save config
62+
void saveConfigCallback () {
63+
Serial.println("Should save config");
64+
shouldSaveConfig = true;
65+
}
66+
67+
void configModeCallback (WiFiManager *myWiFiManager) {
68+
Serial.println("Entered config mode");
69+
Serial.println(WiFi.softAPIP());
70+
71+
// You could indicate on your screen or by an LED you are in config mode here
72+
73+
// We don't want the next time the boar resets to be considered a double reset
74+
// so we remove the flag
75+
drd.stop();
76+
}
77+
78+
void setup() {
79+
80+
Serial.begin(115200);
81+
82+
if (!SPIFFS.begin()) {
83+
Serial.println("Failed to mount FS");
84+
return;
85+
}
86+
87+
pinMode(LED_BUILTIN, OUTPUT); // Initialize the LED_BUILTIN pin as an output
88+
digitalWrite(LED_BUILTIN, LOW); // Turn the LED on (Note that LOW is the voltage level
89+
loadConfig();
90+
91+
WiFiManager wifiManager;
92+
wifiManager.setSaveConfigCallback(saveConfigCallback);
93+
94+
// Adding an additional config on the WIFI manager webpage for the API Key and Channel ID
95+
WiFiManagerParameter customApiKey("apiKey", "API Key", apiKey, 50);
96+
WiFiManagerParameter customChannelId("channelId", "Channel ID", channelId, 35);
97+
wifiManager.addParameter(&customApiKey);
98+
wifiManager.addParameter(&customChannelId);
99+
100+
if (drd.detectDoubleReset()) {
101+
Serial.println("Double Reset Detected");
102+
wifiManager.startConfigPortal("YouTube-Counter", "supersecret");
103+
} else {
104+
Serial.println("No Double Reset Detected");
105+
wifiManager.autoConnect("YouTube-Counter", "supersecret");
106+
}
107+
108+
strcpy(apiKey, customApiKey.getValue());
109+
strcpy(channelId, customChannelId.getValue());
110+
111+
if (shouldSaveConfig) {
112+
saveConfig();
113+
}
114+
115+
digitalWrite(LED_BUILTIN, HIGH); // Turn the LED off by making the voltage HIGH
116+
// Force Config mode if there is no API key
117+
if(strcmp(apiKey, "") > 0) {
118+
Serial.println("Init YouTube API");
119+
api = new YoutubeApi(apiKey, client);
120+
} else {
121+
Serial.println("Forcing Config Mode");
122+
forceConfigMode();
123+
}
124+
Serial.println("");
125+
Serial.println("WiFi connected");
126+
Serial.println("IP address: ");
127+
IPAddress ip = WiFi.localIP();
128+
Serial.println(ip);
129+
130+
drd.stop();
131+
132+
}
133+
134+
bool loadConfig() {
135+
File configFile = SPIFFS.open("/config.json", "r");
136+
if (!configFile) {
137+
Serial.println("Failed to open config file");
138+
return false;
139+
}
140+
141+
size_t size = configFile.size();
142+
if (size > 1024) {
143+
Serial.println("Config file size is too large");
144+
return false;
145+
}
146+
147+
// Allocate a buffer to store contents of the file.
148+
std::unique_ptr<char[]> buf(new char[size]);
149+
150+
configFile.readBytes(buf.get(), size);
151+
152+
StaticJsonBuffer<200> jsonBuffer;
153+
JsonObject& json = jsonBuffer.parseObject(buf.get());
154+
155+
if (!json.success()) {
156+
Serial.println("Failed to parse config file");
157+
return false;
158+
}
159+
160+
strcpy(apiKey, json["apiKey"]);
161+
strcpy(channelId, json["channelId"]);
162+
return true;
163+
}
164+
165+
bool saveConfig() {
166+
StaticJsonBuffer<200> jsonBuffer;
167+
JsonObject& json = jsonBuffer.createObject();
168+
json["apiKey"] = apiKey;
169+
json["channelId"] = channelId;
170+
171+
File configFile = SPIFFS.open("/config.json", "w");
172+
if (!configFile) {
173+
Serial.println("Failed to open config file for writing");
174+
return false;
175+
}
176+
177+
json.printTo(configFile);
178+
return true;
179+
}
180+
181+
void forceConfigMode() {
182+
Serial.println("Reset");
183+
WiFi.disconnect();
184+
Serial.println("Dq");
185+
delay(500);
186+
ESP.restart();
187+
delay(5000);
188+
}
189+
190+
void loop() {
191+
192+
if (millis() - api_lasttime > api_mtbs) {
193+
if(api->getChannelStatistics(channelId))
194+
{
195+
Serial.println("---------Stats---------");
196+
Serial.print("Subscriber Count: ");
197+
Serial.println(api->channelStats.subscriberCount);
198+
Serial.print("View Count: ");
199+
Serial.println(api->channelStats.viewCount);
200+
Serial.print("Comment Count: ");
201+
Serial.println(api->channelStats.commentCount);
202+
Serial.print("Video Count: ");
203+
Serial.println(api->channelStats.videoCount);
204+
// Probably not needed :)
205+
//Serial.print("hiddenSubscriberCount: ");
206+
//Serial.println(api->channelStats.hiddenSubscriberCount);
207+
Serial.println("------------------------");
208+
209+
}
210+
api_lasttime = millis();
211+
}
212+
}

0 commit comments

Comments
 (0)